diff --git a/.github/workflows/issue-check-inactive.yml b/.github/workflows/issue-check-inactive.yml index 6ca5f9f3e8..df05004109 100644 --- a/.github/workflows/issue-check-inactive.yml +++ b/.github/workflows/issue-check-inactive.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: check-inactive - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'check-inactive' inactive-label: 'Inactive' diff --git a/.github/workflows/issue-close-require.yml b/.github/workflows/issue-close-require.yml index 24c1292000..3107470326 100644 --- a/.github/workflows/issue-close-require.yml +++ b/.github/workflows/issue-close-require.yml @@ -9,14 +9,14 @@ jobs: runs-on: ubuntu-latest steps: - name: need reproduce - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'close-issues' labels: '🤔 Need Reproduce' inactive-day: 3 - name: needs more info - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'close-issues' labels: 'needs-more-info' diff --git a/.github/workflows/issue-labeled.yml b/.github/workflows/issue-labeled.yml index 226b92d249..889557feca 100644 --- a/.github/workflows/issue-labeled.yml +++ b/.github/workflows/issue-labeled.yml @@ -12,7 +12,7 @@ jobs: steps: - name: help wanted if: github.event.label.name == 'help wanted' - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'create-comment' token: ${{ secrets.GITHUB_TOKEN }} @@ -26,7 +26,7 @@ jobs: - name: 🤔 Need Reproduce if: github.event.label.name == '🤔 Need Reproduce' - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'create-comment' token: ${{ secrets.GITHUB_TOKEN }} @@ -40,7 +40,7 @@ jobs: - name: Usage if: github.event.label.name == 'Usage' || github.event.label.name == 'Question' - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'create-comment,close-issue' token: ${{ secrets.GITHUB_TOKEN }} @@ -52,7 +52,7 @@ jobs: - name: 3.x if: github.event.label.name == '3.x' - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'create-comment,close-issue' token: ${{ secrets.GITHUB_TOKEN }} @@ -64,7 +64,7 @@ jobs: - name: invalid if: github.event.label.name == 'Invalid' - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'create-comment,close-issue' token: ${{ secrets.GITHUB_TOKEN }} @@ -76,7 +76,7 @@ jobs: - name: rtl if: github.event.label.name == 'rtl' - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'add-assignees' assignees: 'xrkffgg' diff --git a/.github/workflows/issue-open-check.yml b/.github/workflows/issue-open-check.yml index 1eb22f59fb..e87ed10f1b 100644 --- a/.github/workflows/issue-open-check.yml +++ b/.github/workflows/issue-open-check.yml @@ -16,7 +16,7 @@ jobs: - name: check invalid if: (contains(github.event.issue.body, 'ant-design-issue-helper') == false) && (steps.checkUser.outputs.result == 'false') - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'create-comment,add-labels,close-issue' issue-number: ${{ github.event.issue.number }} @@ -27,7 +27,7 @@ jobs: 你好 @${{ github.event.issue.user.login }},为了能够进行高效沟通,我们对 issue 有一定的格式要求,你的 issue 因为不符合要求而被自动关闭。你可以通过 [issue 助手](http://new-issue.ant.design) 来创建 issue 以方便我们定位错误。谢谢配合! - name: check website - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 id: checkid with: actions: 'check-issue' @@ -37,7 +37,7 @@ jobs: - name: deal website if: steps.checkid.outputs.check-result == 'true' - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'create-comment,close-issue' issue-number: ${{ github.event.issue.number }} @@ -63,15 +63,15 @@ jobs: - name: check ie if: contains(github.event.issue.body, 'ant-design-issue-helper') == true && contains(github.event.issue.title, 'IE9') == true || contains(github.event.issue.title, 'IE 9') == true || contains(github.event.issue.title, 'IE10') == true || contains(github.event.issue.title, 'IE 10') == true || contains(github.event.issue.title, 'IE11') == true || contains(github.event.issue.title, 'IE 11') == true || contains(github.event.issue.title, 'Internet Explorer') == true || contains(github.event.issue.body, 'IE9') == true || contains(github.event.issue.body, 'IE 9') == true || contains(github.event.issue.body, 'IE10') == true || contains(github.event.issue.body, 'IE 10') == true || contains(github.event.issue.body, 'IE11') == true || contains(github.event.issue.body, 'IE 11') == true || contains(github.event.issue.body, 'Internet Explorer') == true - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'add-labels' issue-number: ${{ github.event.issue.number }} labels: 'IE | Firefox | Safari,Internet Explorer' - - name: check ie - if: contains(github.event.issue.body, 'ant-design-issue-helper') == true && contains(github.event.issue.title, 'IE9') == true || contains(github.event.issue.title, 'IE 9') == true || contains(github.event.issue.title, 'IE10') == true || contains(github.event.issue.title, 'IE 10') == true || contains(github.event.issue.title, 'IE11') == true || contains(github.event.issue.title, 'IE 11') == true || contains(github.event.issue.title, 'Internet Explorer') == true || contains(github.event.issue.body, 'IE9') == true || contains(github.event.issue.body, 'IE 9') == true || contains(github.event.issue.body, 'IE10') == true || contains(github.event.issue.body, 'IE 10') == true - uses: actions-cool/issues-helper@v2 + - name: check ie11- + if: contains(github.event.issue.body, 'ant-design-issue-helper') == true && contains(github.event.issue.title, 'IE9') == true || contains(github.event.issue.title, 'IE 9') == true || contains(github.event.issue.title, 'IE10') == true || contains(github.event.issue.title, 'IE 10') == true || contains(github.event.issue.body, 'IE9') == true || contains(github.event.issue.body, 'IE 9') == true || contains(github.event.issue.body, 'IE10') == true || contains(github.event.issue.body, 'IE 10') == true + uses: actions-cool/issues-helper@v3 with: actions: 'create-comment, close-issue' issue-number: ${{ github.event.issue.number }} diff --git a/.github/workflows/issue-remove-inactive.yml b/.github/workflows/issue-remove-inactive.yml index f6634e88c8..90556c416d 100644 --- a/.github/workflows/issue-remove-inactive.yml +++ b/.github/workflows/issue-remove-inactive.yml @@ -12,7 +12,7 @@ jobs: steps: - name: remove inactive if: github.event.issue.state == 'open' && github.actor == github.event.issue.user.login - uses: actions-cool/issues-helper@v2 + uses: actions-cool/issues-helper@v3 with: actions: 'remove-labels' issue-number: ${{ github.event.issue.number }} diff --git a/.github/workflows/pr-check-ci.yml b/.github/workflows/pr-check-ci.yml index a8d492dd5f..d9599590a5 100644 --- a/.github/workflows/pr-check-ci.yml +++ b/.github/workflows/pr-check-ci.yml @@ -13,7 +13,7 @@ jobs: with: filter-label: 'BranchAutoMerge' filter-creator-authority: 'write' - filter-head-ref: 'master, feature, master-merge-feature, feature-merge-master' + filter-head-ref: 'master, feature, next, master-merge-feature, feature-merge-master, next-merge-master' filter-support-fork: false skip-run-names: 'deploy preview, pr-check-ci, build preview failed, suggest-related-links' conflict-review-body: '😅 This branch has conflicts that must be resolved!' diff --git a/.github/workflows/pr-check-merge.yml b/.github/workflows/pr-check-merge.yml index 1d35c970dd..c2ff3d4e10 100644 --- a/.github/workflows/pr-check-merge.yml +++ b/.github/workflows/pr-check-merge.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest if: (github.event.pull_request.head.ref == 'feature' || github.event.pull_request.head.ref == 'master') && github.event.pull_request.head.user.login == 'ant-design' steps: - - uses: actions-cool/issues-helper@v2 + - uses: actions-cool/issues-helper@v3 with: actions: 'create-comment' issue-number: ${{ github.event.number }} diff --git a/.github/workflows/release-helper.yml b/.github/workflows/release-helper.yml index 66d96a6e6b..05ee24a927 100644 --- a/.github/workflows/release-helper.yml +++ b/.github/workflows/release-helper.yml @@ -16,25 +16,12 @@ jobs: runs-on: ubuntu-latest steps: - name: make release - uses: actions-cool/release-helper@v1 + uses: actions-cool/release-helper@v2 with: triger: 'tag' changelogs: 'CHANGELOG.en-US.md, CHANGELOG.zh-CN.md' branch: 'master' - dingding-token: ${{ secrets.DINGDING_BOT_TOKEN }} - dingding-msg: 'CHANGELOG.zh-CN.md' - msg-poster: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zx7LTI_ECSAAAAAAAAAAAABkARQnAQ' - msg-footer: '💬 前往 [**Ant Design Releases**]({{url}}) 查看更新日志' - prettier: true - prerelease-filter: '-, a, b, A, B' - - - name: make release - Bigfish - uses: actions-cool/release-helper@v1 - with: - triger: 'tag' - changelogs: 'CHANGELOG.en-US.md, CHANGELOG.zh-CN.md' - branch: 'master' - dingding-token: ${{ secrets.DINGDING_BOT_BIGFISH_TOKEN }} + dingding-token: ${{ secrets.DINGDING_BOT_TOKEN }} ${{ secrets.DINGDING_BOT_BIGFISH_TOKEN }} dingding-msg: 'CHANGELOG.zh-CN.md' msg-poster: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zx7LTI_ECSAAAAAAAAAAAABkARQnAQ' msg-footer: '💬 前往 [**Ant Design Releases**]({{url}}) 查看更新日志' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3b2abedf11..ff2cbddba1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -492,7 +492,7 @@ jobs: run: npx lessc --js ./dist/antd.variable.less - name: lessc component - run: npx lessc --js ./es/button/style/index.less + run: npx lessc --js ./es/input/style/index.less - name: lessc mixins run: npx lessc --js ./es/style/mixins/index.less diff --git a/.github/workflows/verify-files-modify.yml b/.github/workflows/verify-files-modify.yml index e536da38fa..d76777352f 100644 --- a/.github/workflows/verify-files-modify.yml +++ b/.github/workflows/verify-files-modify.yml @@ -14,10 +14,11 @@ jobs: forbid-paths: '.github/, scripts/' forbid-files: 'CHANGELOG.zh-CN.md, CHANGELOG.en-US.md, LICENSE' skip-verify-authority: 'write' - assignees: 'afc163, zombieJ, xrkffgg' + assignees: 'afc163, zombieJ, xrkffgg, MadCcc' comment: | Hi @${{ github.event.pull_request.user.login }}. Thanks for your contribution. The path `.github/` or `scripts/` and `CHANGELOG` `package.json` is only maintained by team members. This current PR will be closed and team members will help on this. close: true + set-failed: false - name: verify-less uses: actions-cool/verify-files-modify@v1 diff --git a/.gitignore b/.gitignore index 54b212c74d..5be4d3cb0b 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,5 @@ __image_snapshots__/ /jest-stare /imageSnapshots /imageDiffSnapshots + +.devcontainer* diff --git a/.stylelintrc.json b/.stylelintrc.json index 5a03e7f8aa..b5af6dd10a 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -8,6 +8,25 @@ "plugins": ["stylelint-declaration-block-no-ignored-properties"], "rules": { "function-name-case": ["lower", { "ignoreFunctions": ["/colorPalette/"] }], + "function-no-unknown": [ + true, + { + "ignoreFunctions": [ + "fade", + "tint", + "darken", + "ceil", + "fadein", + "floor", + "unit", + "shade", + "lighten", + "percentage", + "-", + "~`colorPalette" + ] + } + ], "no-descending-specificity": null, "no-invalid-position-at-import-rule": null, "declaration-empty-line-before": null, diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 509d75c6d7..3e2711b40b 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -15,6 +15,125 @@ timeline: true --- +## 4.19.2 + +`2022-03-13` + +- 🐞 Fix Dropdown not auto adjust placement when position on the edge of window. [#34390](https://github.com/ant-design/ant-design/pull/34390) +- 💄 Change PageHeader elements margin from `12px` to `8px` inside `extra`. [#34428](https://github.com/ant-design/ant-design/pull/34428) +- 🛠 Export css variable function in `antd/es/config-provider` folder to enable ssr requirement. [#34436](https://github.com/ant-design/ant-design/pull/34436) +- 🛠 Refactor Menu with React hooks. [#34433](https://github.com/ant-design/ant-design/pull/34433) +- Input + - 💄 Fix Input font-size when `size` is large. [#34381](https://github.com/ant-design/ant-design/pull/34381) + - 💄 Fix Input.Group wrong border when status is error. [#34412](https://github.com/ant-design/ant-design/pull/34412) +- Form + - 🐞 Fix Form.Item removed in `form.validateFields` throw `Can't perform a React state update on an unmounted component` warning. [#34405](https://github.com/ant-design/ant-design/pull/34405) + - 🐞 Fix to Form that `initialValues` would change if `preserve` is false. [#34411](https://github.com/ant-design/ant-design/pull/34411) +- Tooltip + - 💄 Fix Tooltip width in Safari. [#34415](https://github.com/ant-design/ant-design/pull/34415) [@jiandandkl](https://github.com/jiandandkl) + - 💄 Fix arrow size of Tooltip/Popover/Popconfirm. [#34407](https://github.com/ant-design/ant-design/pull/34407) +- 💄 Remove Collapse bottom border in simple style. [#34366](https://github.com/ant-design/ant-design/pull/34366) [@PanStar](https://github.com/PanStar) +- TypeScript + - 🤖 Fix Input `data-*` type definition. [#34410](https://github.com/ant-design/ant-design/pull/34410) [@GitKou](https://github.com/GitKou) + - 🤖 Fix Transfer `footer` type definition. [#34337](https://github.com/ant-design/ant-design/pull/34337) [@zomixi](https://github.com/zomixi) + +## 4.19.1 + +`2022-03-08` + +- 🐞 Fix less compile error related to custom status. [#34350](https://github.com/ant-design/ant-design/pull/34350) + - 🐞 Fix error `ReferenceError: colorPalette is not defined` when customize theme. + - 🐞 Fix error `Error: Invalid class or id selector syntax` when import `antd/dist/antd.css`. +- 🐞 Fix Input.Passowrd icon color in site. [#34354](https://github.com/ant-design/ant-design/pull/34354) +- 🐞 Fix ConfigProvider `csp` sometime not effect on Icon. [#34356](https://github.com/ant-design/ant-design/pull/34356) + +## 4.19.0 + +`2022-03-08` + +- 💄 Optimize arrow style for some components. [#33710](https://github.com/ant-design/ant-design/pull/33710) + + + +- Input + - 🛠 Refactor Input with rc-input. [#34206](https://github.com/ant-design/ant-design/pull/34206) + - Attention: The type and value of `ref` is modified because of refactoring from class component to function component. You can still get DOM node from `input`, and other methods such as `focus` and `blur` mentioned in document are also supported. + - 🆕 Support `clearIcon` prop for customizing clear icon. [#34325](https://github.com/ant-design/ant-design/pull/34325) +- Table + - 🆕 `filterSearch` now support passing function to customize search. [#34085](https://github.com/ant-design/ant-design/pull/34085) [@heiyu4585](https://github.com/heiyu4585) + - 🆕 `column.filterDropdown({ clearFilters })` support `clearFilters({ confirm: false, closeDropdown: false })`. [#34120](https://github.com/ant-design/ant-design/pull/34120) [@heiyu4585](https://github.com/heiyu4585) + - ⌨️ Table adds `aria-sort` attribute for screen readers. [#33603](https://github.com/ant-design/ant-design/pull/33603) [@dgreene1](https://github.com/dgreene1) + - 🐞 Fix Table filters select-all Checkbox not changed when select item. [#34295](https://github.com/ant-design/ant-design/pull/34295) +- 🆕 Data entry components add `status` prop to support custom status. + + - Transfer [#34098](https://github.com/ant-design/ant-design/pull/34098) + - AutoComplete [#34096](https://github.com/ant-design/ant-design/pull/34096) + - TreeSelect [#34093](https://github.com/ant-design/ant-design/pull/34093) + - Cascader [#34086](https://github.com/ant-design/ant-design/pull/34086) + - Select [#34084](https://github.com/ant-design/ant-design/pull/34084) + - DatePicker and TimePicker [#34073](https://github.com/ant-design/ant-design/pull/34073) + - Mentions [#34071](https://github.com/ant-design/ant-design/pull/34071) + - InputNumber [#34042](https://github.com/ant-design/ant-design/pull/34042) + - Input [#33995](https://github.com/ant-design/ant-design/pull/33995) + + + +- 🆕 InputNumber supports `controls={{ upIcon, downIcon }}` to customize icon up and down. [#33914](https://github.com/ant-design/ant-design/pull/33914) [@heiyu4585](https://github.com/heiyu4585) +- 🆕 Notification `placement` support `top` / `bottom` [#33871](https://github.com/ant-design/ant-design/pull/33871) [@heiyu4585](https://github.com/heiyu4585) +- 🆕 Select, Cascades, DatePicker now support `placement` property. [#33641](https://github.com/ant-design/ant-design/pull/33541) [@ONLY-yours](https://github.com/ONLY-yours) +- 🆕 Dropdown support `arrow={{ pointAtCenter: true }}` to make arrow point at center. And `top` `bottom` placement are also supported. [#33658](https://github.com/ant-design/ant-design/pull/33658) +- 🆕 Skeleton.Input Adds `block` prop. [#33672](https://github.com/ant-design/ant-design/pull/33672) [@woochanleee](https://github.com/woochanleee) +- 🆕 Move TimePicker `disabledHours`, `disabledMinutes`, `disabledSeconds` into `disabledTime` to align with DatePicker. [#33503](https://github.com/ant-design/ant-design/pull/33503) +- 💄 Modify the color of some borders and the background color of the progress bar to be transparent to suit the colored background. [#33506](https://github.com/ant-design/ant-design/pull/33506) +- 💄 Space support custom children `key`. [#33607](https://github.com/ant-design/ant-design/pull/33607) [@qin20](https://github.com/qin20) +- 🐞 Fix `Typography.Title` didn't keep font size when become editable. [#34169](https://github.com/ant-design/ant-design/pull/34169) [@heiyu4585](https://github.com/heiyu4585) +- 🐞 Fix Form.Item throw warning `React does not recognize the requiredMark prop on a DOM element`. [#34323](https://github.com/ant-design/ant-design/pull/34323) + +## 4.18.9 + +`2022-02-28` + +- 🆕 New theme less variable for Radio, Divider, Modal, Dropdown, Drawer. [#34194](https://github.com/ant-design/ant-design/pull/34194) [#34187](https://github.com/ant-design/ant-design/pull/34187) [#34191](https://github.com/ant-design/ant-design/pull/34191) [#34189](https://github.com/ant-design/ant-design/pull/34189) [#34188](https://github.com/ant-design/ant-design/pull/34188) [@qdzhaoxiaodao](https://github.com/qdzhaoxiaodao) +- 💄 Fix Dropdown item wrap style when text is too long. [#34177](https://github.com/ant-design/ant-design/pull/34177) +- TypeScript + - 🐞 Fix Upload `onChange` parameter generic passing. [#34161](https://github.com/ant-design/ant-design/pull/34161) [@wangcch](https://github.com/wangcch) + +## 4.18.8 + +`2022-02-21` + +- 🐞 Fix `getContainer` config not working bug when called multi-times via `message.config`. [#34123](https://github.com/ant-design/ant-design/pull/34123) [@TrickyPi](https://github.com/TrickyPi) +- 🐞 Fix invalid context value cache in Menu component. [#34121](https://github.com/ant-design/ant-design/pull/34121) [@mrwd2009](https://github.com/mrwd2009) +- 🐞 Fix ConfigProvider config theme on server side crash, and warning for useless in SSR instead. [#34118](https://github.com/ant-design/ant-design/pull/34118) +- Table + - ⚡️ Fix Table render twice on first mount. [#34106](https://github.com/ant-design/ant-design/pull/34106) + - ⚡️ Optimized Table rendering performance, now will skip useless rendering when deprecated `column.render: () => { children, props }` method is not used. [#34075](https://github.com/ant-design/ant-design/pull/34075) +- 🐞 Fix incorrect copy text of Typography after children is updated when enable `copyable`. [#34034](https://github.com/ant-design/ant-design/pull/34034) [@opopeieie](https://github.com/opopeieie) +- ⚡️ Optimize Avatar, List, Pagination, Steps to avoid additional render on mount if unnecessary. [34122](https://github.com/ant-design/ant-design/pull/34122) +- 💄 Fix Form broken style when Select item is too long in horizontal layout. [#34117](https://github.com/ant-design/ant-design/pull/34117) +- 🇸🇰 Improve texts for Table, Form and Modal in `sk_SK`. [#34061](https://github.com/ant-design/ant-design/pull/34061) [@xseman](https://github.com/xseman) +- TypeScript + - 🤖 Export `SiderProps` type from Layout component. [#34137](https://github.com/ant-design/ant-design/pull/34137) [@Picsong](https://github.com/Picsong) + +## 4.18.7 + +`2022-02-14` + +- Typography + - 🛠 Fix Typography `useLayoutEffect` warning in SSR. [#33818](https://github.com/ant-design/ant-design/pull/33818) [@SoYoung210](https://github.com/SoYoung210) + - 🐞 Fix Typography with `ellipsis` makes screen show the scroll bar in some case. [#34007](https://github.com/ant-design/ant-design/pull/34007) + - 🐞 Typography copy click event is now `stopPropagation` by default. [#33998](https://github.com/ant-design/ant-design/pull/33998) [@linxianxi](https://github.com/linxianxi) + - 🐞 Fix Typography edit & copy button not trigger by enter key. [#33976](https://github.com/ant-design/ant-design/pull/33976) [@mrwd2009](https://github.com/mrwd2009) +- 🐞 Fix Form `undefined` text of min/max validators in pl_PL locale. [#34024](https://github.com/ant-design/ant-design/pull/34024) [@MichalPodeszwa](https://github.com/MichalPodeszwa) +- 🐞 Fix Input.TextArea cut text logic when `maxLength` configured. [#33910](https://github.com/ant-design/ant-design/pull/33910) [@chenyizhongx](https://github.com/chenyizhongx) +- 💄 Button with `type=default` will provide `.ant-btn-default` className. [#34013](https://github.com/ant-design/ant-design/pull/34013) +- 💄 Improve Menu `:focus-visible` style. [#34008](https://github.com/ant-design/ant-design/pull/34008) +- 💄 Fix Pagination and Rate style problem in Safari. [#34002](https://github.com/ant-design/ant-design/pull/34002) +- 💄 Fix Row and Col component styles when using prefixCls. [#33969](https://github.com/ant-design/ant-design/pull/33969) [@mic-web](https://github.com/mic-web) +- 🐞 Fix Timeline icons with custom color not working. [#33951](https://github.com/ant-design/ant-design/pull/33951) [@MadCcc](https://github.com/MadCcc) +- TypeScript + - 🤖 Optimize Cascader `onChange` definition with `multiple` prop. [#33947](https://github.com/ant-design/ant-design/pull/33947) [@babycannotsay](https://github.com/babycannotsay) + ## 4.18.6 `2022-02-07` diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index e5a3781fcc..b46c47fa42 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -13,7 +13,127 @@ timeline: true - 次版本号:每月发布一个带有新特性的向下兼容的版本。 - 主版本号:含有破坏性更新和新特性,不在发布周期内。 ---- +-- + +## 4.19.2 + +`2022-03-13` + +- 🐞 修复 Dropdown 在边界情况下不会自动调整展示位置的问题。[#34390](https://github.com/ant-design/ant-design/pull/34390) +- 💄 缩小 PageHeader `extra` 内元素间距为 `8px`。[#34428](https://github.com/ant-design/ant-design/pull/34428) +- 🛠 导出 antd/es/config-provider 目录下的 css variable 函数以支持 ssr 的需求。[#34436](https://github.com/ant-design/ant-design/pull/34436) +- 🛠 使用 React hooks 重构 Menu。[#34433](https://github.com/ant-design/ant-design/pull/34433) +- Input + - 💄 修复大尺寸 Input 的字号问题。[#34381](https://github.com/ant-design/ant-design/pull/34381) + - 💄 修复 Input.Group 多余的错误边框样式。[#34412](https://github.com/ant-design/ant-design/pull/34412) +- Form + - 🐞 修复 Form.Item 在 `form.validateFields` 中移除时抛出 `Can't perform a React state update on an unmounted component` 警告的问题。[#34405](https://github.com/ant-design/ant-design/pull/34405) + - 🐞 修复 Form 组件当 `preserve` 为 `false` 时 `initialValues` 会被更改的问题。[#34411](https://github.com/ant-design/ant-design/pull/34411) +- Tooltip + - 💄 修复 Tooltip 在 Safari 下的内容宽度问题。[#34415](https://github.com/ant-design/ant-design/pull/34415) [@jiandandkl](https://github.com/jiandandkl) + - 💄 修复 Tooltip/Popover/Popconfirm 等组件箭头大小问题。[#34407](https://github.com/ant-design/ant-design/pull/34407) +- 💄 优化 Collapse 简洁模式的底边框。[#34366](https://github.com/ant-design/ant-design/pull/34366) [@PanStar](https://github.com/PanStar) +- TypeScript + - 🤖 修复 Input 不支持 `data-*` TS 定义的问题。[#34410](https://github.com/ant-design/ant-design/pull/34410) [@GitKou](https://github.com/GitKou) + - 🤖 修复 Transfer 的 `footer` 类型定义。[#34337](https://github.com/ant-design/ant-design/pull/34337) [@zomixi](https://github.com/zomixi) + +## 4.19.1 + +`2022-03-08` + +- 🐞 修复自定义状态相关的 less 编译错误。[#34350](htps://github.com/ant-dign/ant-design/pull/34350) + - 🐞 修复使用定制主题时 less 编译提示 `ReferenceError: colorPalette is not defined` 错误。 + - 🐞 修复引入 `antd/dist/antd.css` 时提示 `Error: Invalid class or id selector syntax` 错误。 +- 🐞 修复 Input.Passowrd 图标颜色错误。[#34354](https://github.com/ant-design/ant-design/pull/34354) +- 🐞 修复 ConfigProvider `csp` 有时在 Icon 上不会生效的问题。[#34356](https://github.com/ant-design/ant-design/pull/34356) + +## 4.19.0 + +`2022-03-08` + +- 💄 优化部分组件箭头样式。[#33710](https://github.com/ant-design/ant-design/pull/33710) + + + +- Input + - 🛠 引入 rc-input 重构 Input 组件为 function component。[#34206](https://github.com/ant-design/ant-design/pull/34206) + - 注意:由于从 class component 变为 function component,Input 组件的 `ref` 类型及内容已经更新,可以通过 `import { InputRef } from 'antd'` 引入。其中的 `input` 属性作为获取 DOM 的途径被保留,同时支持 `focus` 和 `blur` 等文档中支持的方法。 + - 🆕 新增 `clearIcon` 属性,支持自定义清除按钮。[#34325](https://github.com/ant-design/ant-design/pull/34325) +- Table + - 🆕 `column.filterSearch` 属性现在支持返回一个函数用于自定义搜索条件。[#34085](https://github.com/ant-design/ant-design/pull/34085) [@heiyu4585](https://github.com/heiyu4585) + - 🆕 `column.filterDropdown({ clearFilters })` 支持参数 `clearFilters({ confirm: false, closeDropdown: false })` 控制筛选。[#34120](https://github.com/ant-design/ant-design/pull/34120) [@heiyu4585](https://github.com/heiyu4585) + - ⌨️ 增加 `aria-sort` 属性以优化屏幕阅读器的使用体验。[#33603](https://github.com/ant-design/ant-design/pull/33603) [@dgreene1](https://github.com/dgreene1) + - 🐞 修复 Table 列筛选器中选择全部 Checkbox 状态问题。[#34295](https://github.com/ant-design/ant-design/pull/34295) +- 🆕 表单组件新增 `status` 属性以支持自定义状态。 + + - Transfer [#34098](https://github.com/ant-design/ant-design/pull/34098) + - AutoComplete [#34096](https://github.com/ant-design/ant-design/pull/34096) + - TreeSelect [#34093](https://github.com/ant-design/ant-design/pull/34093) + - Cascader [#34086](https://github.com/ant-design/ant-design/pull/34086) + - Select [#34084](https://github.com/ant-design/ant-design/pull/34084) + - DatePicker 和 TimePicker [#34073](https://github.com/ant-design/ant-design/pull/34073) + - Mentions [#34071](https://github.com/ant-design/ant-design/pull/34071) + - InputNumber [#34042](https://github.com/ant-design/ant-design/pull/34042) + - Input [#33995](https://github.com/ant-design/ant-design/pull/33995) + + + +- 🆕 InputNumber 组件支持 `controls={{ upIcon, downIcon }}` 用于自定义上下图标。[#33914](https://github.com/ant-design/ant-design/pull/33914) [@heiyu4585](https://github.com/heiyu4585) +- 🆕 Notification 组件弹窗位置新增支持 `top` / `bottom`。[#33871](https://github.com/ant-design/ant-design/pull/33871) [@heiyu4585](https://github.com/heiyu4585) +- 🆕 Select、Cascader、DatePicker 等组件新增 `placement` 用于自定义弹层方向。[#33641](https://github.com/ant-design/ant-design/pull/33541) [@ONLY-yours](https://github.com/ONLY-yours) +- 🆕 Dropdown 组件支持 `arrow={{ pointAtCenter: true }}` 用于指向元素正中间,并且新增 `top` `bottom` 两种 `placement` 位置。[#33658](https://github.com/ant-design/ant-design/pull/33658) +- 🆕 Skeleton.Input 添加 `block` 属性。[#33672](https://github.com/ant-design/ant-design/pull/33672) [@woochanleee](https://github.com/woochanleee) +- 🆕 合并 TimePicker `disabledHours`、`disabledMinutes`、`disabledSeconds` 至 `disabledTime` 以保持与 DatePicker 接口一致性。[#33503](https://github.com/ant-design/ant-design/pull/33503) +- 💄 修改部分边框颜色和进度条的背景色为透明色以适应有色背景。[#33506](https://github.com/ant-design/ant-design/pull/33506) +- 💄 Space 支持自定义 children 的 `key`。[#33607](https://github.com/ant-design/ant-design/pull/33607) [@qin20](https://github.com/qin20) +- 🐞 修复 Typography.Title 进入编辑模式时大小不一致的问题。[#34169](https://github.com/ant-design/ant-design/pull/34169) [@heiyu4585](https://github.com/heiyu4585) +- 🐞 修复 Form.Item 抛出 `React does not recognize the requiredMark prop on a DOM element` 的问题。[#34323](https://github.com/ant-design/ant-design/pull/34323) + +## 4.18.9 + +`2022-02-28` + +- 🆕 新增 Radio、Divider、Modal、Dropdown、Drawer 主题变量。[#34194](https://github.com/ant-design/ant-design/pull/34194) [#34187](https://github.com/ant-design/ant-design/pull/34187) [#34191](https://github.com/ant-design/ant-design/pull/34191) [#34189](https://github.com/ant-design/ant-design/pull/34189) [#34188](https://github.com/ant-design/ant-design/pull/34188) [@qdzhaoxiaodao](https://github.com/qdzhaoxiaodao) +- 🐞 修复 Form 组件当 `preserve` 为 `false` 时 `initialValues` 会被更改的问题。[#34153](https://github.com/ant-design/ant-design/pull/34153) +- 💄 修复 Dropdown 菜单项文本太长没有换行的问题。[#34177](https://github.com/ant-design/ant-design/pull/3417) +- TypeScript + - 🐞 修复 Upload `onChange` 参数泛型传递。[#34161](https://github.com/ant-design/ant-design/pull/34161) [@wangcch](https://github.com/wangcch) + +## 4.18.8 + +`2022-02-21` + +- 🐞 修复 `message.config` 多次配置 `getContainer` 时无法生效的问题。[#34123](https://github.com/ant-design/ant-design/pull/34123) [@TrickyPi](https://github.com/TrickyPi) +- 🐞 修复 Menu 组件中无效的缓存逻辑。[#34121](https://github.com/ant-design/ant-design/pull/34121) [@mrwd2009](https://github.com/mrwd2009) +- 🐞 修复 ConfigProvider 在服务端配置主题会崩溃的问题,同时现在会提示动态主题于 SSR 上无效。[#34118](https://github.com/ant-design/ant-design/pull/34118) +- Table + - ⚡️ 修复 Table 在首次加载时会渲染两次的问题。[#34106](https://github.com/ant-design/ant-design/pull/34106) + - ⚡️ 优化 Table 渲染性能,现在不使用废弃 `column.render: () => { children, props }` 方法时默认会跳过无用渲染。[#34075](https://github.com/ant-design/ant-design/pull/34075) +- 🐞 修复 Typography 启用 `copyable` 时 `children` 内容变化后复制内容没变的问题。[#34034](https://github.com/ant-design/ant-design/pull/34034) [@opopeieie](https://github.com/opopeieie) +- ⚡️ 优化 Avatar、List、Pagination、Steps 以防止初始化时非必要的额外渲染。[34122](https://github.com/ant-design/ant-design/pull/34122) +- 💄 修复 Form 下 Select 内容太长导致布局换行的问题。[#34117](https://github.com/ant-design/ant-design/pull/34117) +- 🇸🇰 完善 `sk-SK` 中 Table、Form、Modal 的文案。[#34061](https://github.com/ant-design/ant-design/pull/34061) [@xseman](https://github.com/xseman) +- TypeScript + - 🤖 导出 Layout 组件的 `SiderProps` 类型。[#34137](https://github.com/ant-design/ant-design/pull/34137) [@Picsong](https://github.com/Picsong) + +## 4.18.7 + +`2022-02-14` + +- Typography + - 🛠 修复 Typography 在 SSR 渲染时警告 `useLayoutEffect` 的问题。[#33818](https://github.com/ant-design/ant-design/pull/33818) [@SoYoung210](https://github.com/SoYoung210) + - 🐞 修复 Typography 配置 `ellipsis` 后在某些情况下会出现滚动条的问题。[#34007](https://github.com/ant-design/ant-design/pull/34007) + - 🐞 Typography 复制按钮点击事件不在冒泡。[#33998](https://github.com/ant-design/ant-design/pull/33998) [@linxianxi](https://github.com/linxianxi) + - 🐞 修复 Typography 中编辑和拷贝按钮无法响应 Enter 按键的问题。[#33976](https://github.com/ant-design/ant-design/pull/33976) [@mrwd2009](https://github.com/mrwd2009) +- 🐞 修复 Form 波兰语中表单校验部分文案未定义的问题。[#34024](https://github.com/ant-design/ant-design/pull/34024) [@MichalPodeszwa](https://github.com/MichalPodeszwa) +- 🐞 修复 Input.TextArea 设置 `maxLength` 时光标位置会影响超出部分截取的问题。[#33910](https://github.com/ant-design/ant-design/pull/33910) [@chenyizhongx](https://github.com/chenyizhongx) +- 💄 Button 对于 `type=default` 也会提供 `.ant-btn-default` 的样式类名。[#34013](https://github.com/ant-design/ant-design/pull/34013) +- 💄 优化 Menu `:focus-visible` 的样式。[#34008](https://github.com/ant-design/ant-design/pull/34008) +- 💄 修复 Pagination 和 Rate 在 Safari 下部分样式丢失的问题,比如分页按钮禁用样式失效。[#34002](https://github.com/ant-design/ant-design/pull/34002) +- 💄 修复 Row 与 Col 在配置 `prefixCls` 的样式问题。[#33969](https://github.com/ant-design/ant-design/pull/33969) [@mic-web](https://github.com/mic-web) +- 🐞 修复 Timeline 的自定义图标颜色无效的问题。[#33951](https://github.com/ant-design/ant-design/pull/33951) [@MadCcc](https://github.com/MadCcc) +- TypeScript + - 🤖 优化 Cascader `multiple` 属性对应的 `onChange` 类型推断。[#33947](https://github.com/ant-design/ant-design/pull/33947) [@babycannotsay](https://github.com/babycannotsay) ## 4.18.6 @@ -48,7 +168,7 @@ timeline: true - Typography - ⚡️ 优化 Typography 在配置 `tooltip` 时优先使用原生省略样式以提升性能。[#33669](https://github.com/ant-design/ant-design/pull/33669) - - 🐞 重构 Typography `ellipsis` 逻辑以修复 `children` 如果消费上游 Context 会报错的问题。 [#33725](https://github.com/ant-design/ant-design/pull/33725) + - 🐞 重构 Typography `ellipsis` 逻辑以修复 `children` 如果消费上游 Context 会报错的问题。[#33725](https://github.com/ant-design/ant-design/pull/33725) - Icon - 🐞 修复 `` 和 `` 不对齐的问题。[#33709](https://github.com/ant-design/ant-design/pull/33709) - 🐞 修复 `` 抖动的问题。[#33726](https://github.com/ant-design/ant-design/pull/33726) [@JX-Zhuang](https://github.com/JX-Zhuang) @@ -274,7 +394,7 @@ timeline: true - 🐞 修复 Button `ghost` 鼠标悬停样式。[#32289](https://github.com/ant-design/ant-design/pull/32289) - 🐞 修复 Button 配置 `loading` 时,无法触发 Tooltip 的问题。[#32158](https://github.com/ant-design/ant-design/pull/32158) - Pagination - - 🆕 Pagination 支持定制 `selectComponentClass`。 [#32132](https://github.com/ant-design/ant-design/pull/32132) [@JounQin](https://github.com/JounQin) + - 🆕 Pagination 支持定制 `selectComponentClass`。[#32132](https://github.com/ant-design/ant-design/pull/32132) [@JounQin](https://github.com/JounQin) - 💄 Pagination `simple` 属性下中翻页 input 增加 box-shadow。[#32528](https://github.com/ant-design/ant-design/pull/32528) [@chen-jingjie](https://github.com/chen-jingjie) - Upload - 🐞 修复 Upload `listStyle="picture"` 下加载中样式错位的问题。[#32664](https://github.com/ant-design/ant-design/pull/32664) @@ -327,7 +447,7 @@ timeline: true - 🤖 修复 Switch `id` 属性定义。[#32237](https://github.com/ant-design/ant-design/pull/32237) [@M-ZubairAhmed](https://github.com/M-ZubairAhmed) - 🤖 修复 Button 的 `type` 的 TS 类型定义。[#32004](https://github.com/ant-design/ant-design/pull/32004) [@jaredleechn](https://github.com/jaredleechn) - 🤖 完备 Pagination 的 `locale` TS 类型定义。[[#32128](https://github.com/ant-design/ant-design/pull/32128) [@JounQin](https://github.com/JounQin) - - 🤖 完善并导出 DropdownButton 的 `DropdownButtonType` TS 类型定义。 [[#31957](https://github.com/ant-design/ant-design/pull/31957) [@Dreamerryao](https://github.com/Dreamerryao) + - 🤖 完善并导出 DropdownButton 的 `DropdownButtonType` TS 类型定义。[[#31957](https://github.com/ant-design/ant-design/pull/31957) [@Dreamerryao](https://github.com/Dreamerryao) - 🤖 调整 List 组件 `rowKey` 类型为 React.key。[#32033](https://github.com/ant-design/ant-design/pull/32033) [@lironhl](https://github.com/lironhl) - 🐞 修复 DatePicker `ref` 类型。[#31993](https://github.com/ant-design/ant-design/pull/31993) [@acfasj](https://github.com/acfasj) - 🤖 更新 Drawer 中 `levelMove` 类型定义。[#30714](https://github.com/ant-design/ant-design/pull/30714) [@g0shed](https://github.com/g0shed) @@ -376,7 +496,7 @@ timeline: true - 🐞 修复 Progress 环形进度条 `success.strokeColor` 不生效的问题。[#31589](https://github.com/ant-design/ant-design/pull/31589) - 🐞 修复 Select 组件没有忽略 `getRawInputElement` 属性导致的类型报错问题。[#31566](https://github.com/ant-design/ant-design/pull/31566) [@aoilti](https://github.com/aoilti) - 🐞 修复 Pagination 的 `totalBoundaryShowSizeChanger` 属性类型错误。[#31549](https://github.com/ant-design/ant-design/pull/31549) [@Monty-Ma](https://github.com/Monty-Ma) -- 🐞 修复 Skeleton.Avatar `className` 重复应用的问题。 [#31536](https://github.com/ant-design/ant-design/pull/31536) [@Greatshock](https://github.com/Greatshock) +- 🐞 修复 Skeleton.Avatar `className` 重复应用的问题。[#31536](https://github.com/ant-design/ant-design/pull/31536) [@Greatshock](https://github.com/Greatshock) - 🌐 国际化 - 🇹🇷 为 Image 组件中 `预览` 文案增加土耳其语翻译。[#31593](https://github.com/ant-design/ant-design/pull/31593) [@mburakkalkan](https://github.com/mburakkalkan) - 🇰🇷 修复韩语中的错别字。[#31575](https://github.com/ant-design/ant-design/pull/31575) [@chatoo2412](https://github.com/chatoo2412) @@ -697,7 +817,7 @@ timeline: true - 🐞 修复 Modal 页脚里使用 href 按钮导致的间距丢失问题。[#29681](https://github.com/ant-design/ant-design/pull/29681) [@n0ruSh](https://github.com/n0ruSh) - 💄 修复 Input 组件配置附件元素时禁用样式异常的问题。[#29670](https://github.com/ant-design/ant-design/pull/29670) - 💄 优化 Form.Item 提示信息的鼠标显示样式。[#29650](https://github.com/ant-design/ant-design/pull/29650) -- 🇨🇿 修复 cs_CZ 语言环境中的错字。 [#29675](https://github.com/ant-design/ant-design/pull/29675) [@jvaclavik](https://github.com/jvaclavik) +- 🇨🇿 修复 cs_CZ 语言环境中的错字。[#29675](https://github.com/ant-design/ant-design/pull/29675) [@jvaclavik](https://github.com/jvaclavik) - 🇨🇦 添加 fr_CA 语言。[#29748](https://github.com/ant-design/ant-design/pull/29748) [@liufenghua808](https://github.com/liufenghua808) ## 4.13.1 @@ -797,7 +917,7 @@ timeline: true - TypeScript - 🤖 更新 Table TypeScript 定义 `dataSource` 至 `readonly`。[#29084](https://github.com/ant-design/ant-design/pull/29084) - Less - - 💄 增加 less 变量 `@progress-info-text-color`。 [#28981](https://github.com/ant-design/ant-design/pull/28981) [@yuxuan](https://github.com/yuxuan) + - 💄 增加 less 变量 `@progress-info-text-color`。[#28981](https://github.com/ant-design/ant-design/pull/28981) [@yuxuan](https://github.com/yuxuan) ## 4.11.3 @@ -936,7 +1056,7 @@ timeline: true - 🆕 多选模式下 `maxTagCount` 支持 `responsive`。[#28520](https://github.com/ant-design/ant-design/pull/28520) - 🆕 Slider 新增 range.draggableTrack 以支持范围刻度整体可拖拽。[#28592](https://github.com/ant-design/ant-design/pull/28592) - 🆕 `message` 新增 `onClick` 回调,会在消息被点击时触发。[#28148](https://github.com/ant-design/ant-design/pull/28148) [@ZeroTo0ne](https://github.com/ant-design/ant-design/pull/28148) -- 🆕 Descriptions 上可以统一设置 `labelStyle` 和 `contentStyle`。 [#28613](https://github.com/ant-design/ant-design/pull/28613) +- 🆕 Descriptions 上可以统一设置 `labelStyle` 和 `contentStyle`。[#28613](https://github.com/ant-design/ant-design/pull/28613) - 🆕 Form 的 `scrollToFirstError` 属性支持设置滚动的位置参数。[#28272](https://github.com/ant-design/ant-design/pull/28272) [@vouis](https://github.com/vouis) - 🆕 Steps 新增 reponsive 属性用于关闭响应式样式。[#28459](https://github.com/ant-design/ant-design/pull/28459) - 🌐 国际化 @@ -1327,7 +1447,7 @@ timeline: true - 🐞 修复 Form 使用 `help` 时出现的同构问题。[#26542](https://github.com/ant-design/ant-design/pull/26542) - 🐞 修复 Avatar 在 `display: none` 时不会正确缩放 fallback 文字的问题。[#26522](https://github.com/ant-design/ant-design/pull/26522) [@zhangyu1818](https://github.com/zhangyu1818) - TypeScript - - 🤖 Col 增加 `ColSize` 增加 `flex` 的定义。 [#26578](https://github.com/ant-design/ant-design/pull/26578) [@blaiz](https://github.com/blaiz) + - 🤖 Col 增加 `ColSize` 增加 `flex` 的定义。[#26578](https://github.com/ant-design/ant-design/pull/26578) [@blaiz](https://github.com/blaiz) - 🤖 修复 Tooltip/Popover `children` 定义不接受 ReactNode 的问题。[#26534](https://github.com/ant-design/ant-design/pull/26534) ## 4.6.2 diff --git a/components/_util/ActionButton.tsx b/components/_util/ActionButton.tsx index 50540b3c55..45f209602c 100644 --- a/components/_util/ActionButton.tsx +++ b/components/_util/ActionButton.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; +import useState from 'rc-util/lib/hooks/useState'; import Button from '../button'; import { LegacyButtonType, ButtonProps, convertLegacyProps } from '../button/button'; -import useDestroyed from './hooks/useDestroyed'; export interface ActionButtonProps { type?: LegacyButtonType; @@ -21,8 +21,7 @@ function isThenable(thing?: PromiseLike): boolean { const ActionButton: React.FC = props => { const clickedRef = React.useRef(false); const ref = React.useRef(); - const isDestroyed = useDestroyed(); - const [loading, setLoading] = React.useState(false); + const [loading, setLoading] = useState(false); React.useEffect(() => { let timeoutId: any; @@ -45,9 +44,7 @@ const ActionButton: React.FC = props => { setLoading(true); returnValueOfOnOk!.then( (...args: any[]) => { - if (!isDestroyed()) { - setLoading(false); - } + setLoading(false, true); close(...args); clickedRef.current = false; }, @@ -56,9 +53,7 @@ const ActionButton: React.FC = props => { // eslint-disable-next-line no-console console.error(e); // See: https://github.com/ant-design/ant-design/issues/6183 - if (!isDestroyed()) { - setLoading(false); - } + setLoading(false, true); clickedRef.current = false; }, ); diff --git a/components/_util/__tests__/capitalize.test.ts b/components/_util/__tests__/capitalize.test.ts new file mode 100644 index 0000000000..6369d5470f --- /dev/null +++ b/components/_util/__tests__/capitalize.test.ts @@ -0,0 +1,17 @@ +import capitalize from '../capitalize'; + +describe('capitalize', () => { + it('should capitalize the first character of a string', () => { + expect(capitalize('antd')).toBe('Antd'); + expect(capitalize('Antd')).toBe('Antd'); + expect(capitalize(' antd')).toBe(' antd'); + expect(capitalize('')).toBe(''); + }); + + it('should return the original value when is not a string', () => { + expect(capitalize(1 as any)).toBe(1); + expect(capitalize(true as any)).toBe(true); + expect(capitalize(undefined as any)).toBe(undefined); + expect(capitalize(null as any)).toBe(null); + }); +}); diff --git a/components/_util/__tests__/useDestroyed.test.js b/components/_util/__tests__/useDestroyed.test.js deleted file mode 100644 index d98979e49f..0000000000 --- a/components/_util/__tests__/useDestroyed.test.js +++ /dev/null @@ -1,20 +0,0 @@ -import { mount } from 'enzyme'; -import React from 'react'; -import useDestroyed from '../hooks/useDestroyed'; - -describe('useMounted', () => { - it('should work properly', () => { - let isDestroyed = null; - - const AutoUnmounted = () => { - isDestroyed = useDestroyed(); - - return
Mounted
; - }; - - const wrapper = mount(); - expect(isDestroyed()).toBeFalsy(); - wrapper.unmount(); - expect(isDestroyed()).toBeTruthy(); - }); -}); diff --git a/components/_util/capitalize.ts b/components/_util/capitalize.ts new file mode 100644 index 0000000000..b00c691b74 --- /dev/null +++ b/components/_util/capitalize.ts @@ -0,0 +1,8 @@ +export default function capitalize(str: T): Capitalize { + if (typeof str !== 'string') { + return str; + } + + const ret = str.charAt(0).toUpperCase() + str.slice(1); + return ret as Capitalize; +} diff --git a/components/_util/getDataOrAriaProps.ts b/components/_util/getDataOrAriaProps.ts index ee4e271ec6..1984714db6 100644 --- a/components/_util/getDataOrAriaProps.ts +++ b/components/_util/getDataOrAriaProps.ts @@ -1,8 +1,8 @@ export default function getDataOrAriaProps(props: any) { return Object.keys(props).reduce((prev: any, key: string) => { if ( - (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-' || key === 'role') && - key.substr(0, 7) !== 'data-__' + (key.startsWith('data-') || key.startsWith('aria-') || key === 'role') && + !key.startsWith('data-__') ) { prev[key] = props[key]; } diff --git a/components/_util/hooks/useDestroyed.ts b/components/_util/hooks/useDestroyed.ts deleted file mode 100644 index 4b361a78ae..0000000000 --- a/components/_util/hooks/useDestroyed.ts +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react'; - -export default function useDestroyed() { - const mountedRef = React.useRef(true); - - React.useEffect( - () => () => { - mountedRef.current = false; - }, - [], - ); - - return () => !mountedRef.current; -} diff --git a/components/_util/motion.tsx b/components/_util/motion.tsx index 1c69a9f05a..3f304ba6c6 100644 --- a/components/_util/motion.tsx +++ b/components/_util/motion.tsx @@ -1,5 +1,6 @@ import { CSSMotionProps, MotionEventHandler, MotionEndEventHandler } from 'rc-motion'; import { MotionEvent } from 'rc-motion/lib/interface'; +import { tuple } from './type'; // ================== Collapse Motion ================== const getCollapsedHeight: MotionEventHandler = () => ({ height: 0, opacity: 0 }); @@ -25,11 +26,22 @@ const collapseMotion: CSSMotionProps = { motionDeadline: 500, }; +const SelectPlacements = tuple('bottomLeft', 'bottomRight', 'topLeft', 'topRight'); +export type SelectCommonPlacement = typeof SelectPlacements[number]; + +const getTransitionDirection = (placement: SelectCommonPlacement | undefined) => { + if (placement !== undefined && (placement === 'topLeft' || placement === 'topRight')) { + return `slide-down`; + } + return `slide-up`; +}; + const getTransitionName = (rootPrefixCls: string, motion: string, transitionName?: string) => { if (transitionName !== undefined) { return transitionName; } return `${rootPrefixCls}-${motion}`; }; -export { getTransitionName }; + +export { getTransitionName, getTransitionDirection }; export default collapseMotion; diff --git a/components/tooltip/placements.tsx b/components/_util/placements.tsx similarity index 97% rename from components/tooltip/placements.tsx rename to components/_util/placements.tsx index 3fc9152268..eb4dead8a8 100644 --- a/components/tooltip/placements.tsx +++ b/components/_util/placements.tsx @@ -42,6 +42,7 @@ export default function getPlacements(config: PlacementsConfig) { horizontalArrowShift = 16, verticalArrowShift = 8, autoAdjustOverflow, + arrowPointAtCenter, } = config; const placementMap: BuildInPlacements = { left: { @@ -94,7 +95,7 @@ export default function getPlacements(config: PlacementsConfig) { }, }; Object.keys(placementMap).forEach(key => { - placementMap[key] = config.arrowPointAtCenter + placementMap[key] = arrowPointAtCenter ? { ...placementMap[key], overflow: getOverflowOptions(autoAdjustOverflow), diff --git a/components/_util/statusUtils.tsx b/components/_util/statusUtils.tsx new file mode 100644 index 0000000000..25153ba93f --- /dev/null +++ b/components/_util/statusUtils.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import CheckCircleFilled from '@ant-design/icons/CheckCircleFilled'; +import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled'; +import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled'; +import LoadingOutlined from '@ant-design/icons/LoadingOutlined'; +import classNames from 'classnames'; +import { ValidateStatus } from '../form/FormItem'; +import { tuple } from './type'; + +const InputStatuses = tuple('warning', 'error', ''); +export type InputStatus = typeof InputStatuses[number]; + +const iconMap = { + success: CheckCircleFilled, + warning: ExclamationCircleFilled, + error: CloseCircleFilled, + validating: LoadingOutlined, +}; + +export const getFeedbackIcon = (prefixCls: string, status?: ValidateStatus) => { + const IconNode = status && iconMap[status]; + return IconNode ? ( + + + + ) : null; +}; + +export function getStatusClassNames( + prefixCls: string, + status?: ValidateStatus, + hasFeedback?: boolean, +) { + return classNames({ + [`${prefixCls}-status-success`]: status === 'success', + [`${prefixCls}-status-warning`]: status === 'warning', + [`${prefixCls}-status-error`]: status === 'error', + [`${prefixCls}-status-validating`]: status === 'validating', + [`${prefixCls}-has-feedback`]: hasFeedback, + }); +} + +export const getMergedStatus = (contextStatus?: ValidateStatus, customStatus?: InputStatus) => + customStatus || contextStatus; diff --git a/components/_util/theme/default.tsx b/components/_util/theme/default.tsx new file mode 100644 index 0000000000..7c2faabe92 --- /dev/null +++ b/components/_util/theme/default.tsx @@ -0,0 +1,86 @@ +import { TinyColor } from '@ctrl/tinycolor'; + +import type { DesignToken, PresetColorType } from '.'; + +const presetColors: PresetColorType = { + blue: '#1890FF', + purple: '#722ED1', + cyan: '#13C2C2', + green: '#52C41A', + magenta: '#EB2F96', + pink: '#eb2f96', + red: '#F5222D', + orange: '#FA8C16', + yellow: '#FADB14', + volcano: '#FA541C', + geekblue: '#2F54EB', + gold: '#FAAD14', + lime: '#A0D911', +}; + +const defaultDesignToken: DesignToken = { + primaryColor: '#1890ff', + successColor: '#52c41a', + warningColor: '#faad14', + errorColor: '#ff4d4f', + infoColor: '#1890ff', + + // https://github.com/ant-design/ant-design/issues/20210 + lineHeight: 1.5715, + + borderWidth: 1, + borderStyle: 'solid', + borderRadius: 2, + borderColor: new TinyColor({ h: 0, s: 0, v: 85 }).toHexString(), + borderColorSplit: new TinyColor({ h: 0, s: 0, v: 94 }).toHexString(), + + easeInOut: `cubic-bezier(0.645, 0.045, 0.355, 1)`, + easeInOutCirc: `cubic-bezier(0.78, 0.14, 0.15, 0.86)`, + easeOutBack: `cubic-bezier(0.12, 0.4, 0.29, 1.46)`, + easeInQuint: `cubic-bezier(0.755, 0.05, 0.855, 0.06)`, + easeOutQuint: `cubic-bezier(0.23, 1, 0.32, 1)`, + + outlineWidth: 2, + outlineBlurSize: 0, + + fontSize: 14, + fontFamily: `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, + 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', + 'Noto Color Emoji'`, + textColor: new TinyColor('#000').setAlpha(0.85).toRgbString(), + textColorSecondary: new TinyColor('#000').setAlpha(0.45).toRgbString(), + textColorDisabled: new TinyColor('#000').setAlpha(0.25).toRgbString(), + textColorInverse: '#fff', + placeholderColor: new TinyColor({ h: 0, s: 0, v: 75 }).setAlpha(0.5).toRgbString(), + + disabledColor: new TinyColor('#000').setAlpha(0.25).toRgbString(), + + headingColor: new TinyColor('#000').setAlpha(0.85).toRgbString(), + + iconColorHover: new TinyColor('#000').setAlpha(0.75).toRgbString(), + + itemHoverBackground: '#f5f5f5', + + controlHeight: 32, + + padding: 16, + margin: 16, + + // Default grey background color + background: new TinyColor({ h: 0, s: 0, v: 96 }).toHexString(), + + // background of header and selected item + backgroundLight: new TinyColor({ h: 0, s: 0, v: 98 }).toHexString(), + + componentBackground: '#fff', + componentBackgroundDisabled: new TinyColor({ h: 0, s: 0, v: 96 }).toHexString(), + + duration: 0.3, + + zIndexDropdown: 1050, + + // preset color palettes + ...presetColors, +}; + +export default defaultDesignToken; diff --git a/components/_util/theme/index.tsx b/components/_util/theme/index.tsx new file mode 100644 index 0000000000..32fe21bd6f --- /dev/null +++ b/components/_util/theme/index.tsx @@ -0,0 +1,364 @@ +import React from 'react'; +import { generate } from '@ant-design/colors'; +import { TinyColor } from '@ctrl/tinycolor'; +import { + CSSInterpolation, + CSSObject, + Theme, + useCacheToken, + useStyleRegister, +} from '@ant-design/cssinjs'; +import defaultDesignToken from './default'; +import version from '../../version'; +import { resetComponent, resetIcon, clearFix } from './util'; +import { + initSlideMotion, + slideUpIn, + slideUpOut, + slideDownIn, + slideDownOut, + slideLeftIn, + slideLeftOut, + slideRightIn, + slideRightOut, +} from './util/slide'; + +export { + resetComponent, + resetIcon, + clearFix, + initSlideMotion, + slideUpIn, + slideUpOut, + slideDownIn, + slideDownOut, + slideLeftIn, + slideLeftOut, + slideRightIn, + slideRightOut, +}; + +export interface PresetColorType { + blue: string; + purple: string; + cyan: string; + green: string; + magenta: string; + pink: string; + red: string; + orange: string; + yellow: string; + volcano: string; + geekblue: string; + lime: string; + gold: string; +} + +export const PresetColorKeys: ReadonlyArray = [ + 'blue', + 'purple', + 'cyan', + 'green', + 'magenta', + 'pink', + 'red', + 'orange', + 'yellow', + 'volcano', + 'geekblue', + 'lime', + 'gold', +]; + +export interface DesignToken extends PresetColorType { + primaryColor: string; + successColor: string; + warningColor: string; + errorColor: string; + infoColor: string; + + lineHeight: number; + borderWidth: number; + borderStyle: string; + borderRadius: number; + borderColor: string; + borderColorSplit: string; + + easeInOut: string; + easeInOutCirc: string; + easeOutBack: string; + easeInQuint: string; + easeOutQuint: string; + + outlineWidth: number; + outlineBlurSize: number; + + fontSize: number; + fontFamily: string; + textColor: string; + textColorSecondary: string; + textColorDisabled: string; + textColorInverse: string; + placeholderColor: string; + + disabledColor: string; + + iconColorHover: string; + + headingColor: string; + + itemHoverBackground: string; + + controlHeight: number; + + padding: number; + margin: number; + + background: string; + backgroundLight: string; + + componentBackground: string; + componentBackgroundDisabled: string; + + duration: number; + + zIndexDropdown: number; + + boxShadow?: string; +} + +type ColorPaletteKeyIndexes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + +type ColorPalettes = { + [key in `${keyof PresetColorType}-${ColorPaletteKeyIndexes[number]}`]: string; +}; + +/** This is temporary token definition since final token definition is not ready yet. */ +export interface DerivativeToken extends ColorPalettes, Omit { + primaryHoverColor: string; + primaryActiveColor: string; + primaryOutlineColor: string; + errorHoverColor: string; + errorActiveColor: string; + errorOutlineColor: string; + warningHoverColor: string; + warningOutlineColor: string; + itemActiveBackground: string; + + highlightColor: string; + + linkColor: string; + linkHoverColor: string; + linkActiveColor: string; + linkDecoration: CSSObject['textDecoration']; + linkHoverDecoration: CSSObject['textDecoration']; + linkFocusDecoration: CSSObject['textDecoration']; + + fontSizeSM: number; + fontSizeLG: number; + /** @private Only Used for control inside component like Multiple Select inner selection item */ + controlHeightXS: number; + controlHeightSM: number; + controlHeightLG: number; + controlPaddingHorizontal: number; + controlPaddingHorizontalSM: number; + paddingSM: number; + paddingXS: number; + paddingXXS: number; + paddingLG: number; + marginXS: number; + marginLG: number; + marginXXS: number; + + duration: string; + durationMid: string; + durationFast: string; + + heading1Size: number; + heading2Size: number; + heading3Size: number; + heading4Size: number; + heading5Size: number; + + primaryColors: string[]; + errorColors: string[]; + warningColors: string[]; + + // TMP + tmpPrimaryColorWeak: string; + tmpPrimaryHoverColorWeak: string; + // Checked background for Checkable Tag + tmpPrimaryColor6: string; + // Active background for Checkable Tag + tmpPrimaryColor7: string; + + tmpSuccessColorDeprecatedBg: string; + tmpWarningColorDeprecatedBg: string; + tmpErrorColorDeprecatedBg: string; + tmpInfoColorDeprecatedBg: string; + + tmpSuccessColorDeprecatedBorder: string; + tmpWarningColorDeprecatedBorder: string; + tmpErrorColorDeprecatedBorder: string; + tmpInfoColorDeprecatedBorder: string; +} + +export { useStyleRegister }; + +// =============================== Derivative =============================== +function derivative(designToken: DesignToken): DerivativeToken { + const { primaryColor, errorColor, warningColor, infoColor, successColor } = designToken; + + const primaryColors = generate(primaryColor); + const errorColors = generate(errorColor); + const warningColors = generate(warningColor); + const infoColors = generate(infoColor); + const successColors = generate(successColor); + + const paddingSM = (designToken.padding / 4) * 3; + const paddingXS = designToken.padding * 0.5; + + const colorPalettes = PresetColorKeys.map((colorKey: keyof PresetColorType) => { + const colors = generate(designToken[colorKey]); + + const ret = new Array(10).fill(1).reduce((prev, _, i) => { + prev[`${colorKey}-${i + 1}`] = colors[i]; + return prev; + }, {}) as ColorPalettes; + return ret; + }).reduce((prev, cur) => { + prev = { + ...prev, + ...cur, + }; + return prev; + }, {} as ColorPalettes); + + return { + // FIXME: Need design token + boxShadow: ` + 0 3px 6px -4px rgba(0, 0, 0, 0.12), + 0 6px 16px 0 rgba(0, 0, 0, 0.08), + 0 9px 28px 8px rgba(0, 0, 0, 0.05)`, + + ...designToken, + + primaryHoverColor: primaryColors[4], + primaryActiveColor: primaryColors[6], + primaryOutlineColor: new TinyColor(primaryColor).setAlpha(0.2).toRgbString(), + + errorHoverColor: errorColors[4], + errorActiveColor: errorColors[6], + errorOutlineColor: new TinyColor(errorColor).setAlpha(0.2).toRgbString(), + + warningHoverColor: warningColors[4], + warningOutlineColor: new TinyColor(warningColor).setAlpha(0.2).toRgbString(), + + highlightColor: errorColors[4], // FIXME: Should not align with error color + + itemActiveBackground: primaryColors[0], + + linkColor: primaryColor, + linkHoverColor: primaryColors[4], + linkActiveColor: primaryColors[6], + linkDecoration: 'none', + linkHoverDecoration: 'none', + linkFocusDecoration: 'none', + + fontSizeSM: designToken.fontSize - 2, + fontSizeLG: designToken.fontSize + 2, + controlHeightXS: designToken.controlHeight / 2, + controlHeightSM: designToken.controlHeight * 0.75, + controlHeightLG: designToken.controlHeight * 1.25, + controlPaddingHorizontal: paddingSM, + controlPaddingHorizontalSM: paddingXS, + paddingSM, + paddingXS, + paddingXXS: designToken.padding * 0.25, + paddingLG: designToken.padding * 1.5, + marginXS: designToken.margin * 0.5, + marginLG: designToken.margin * 1.5, + marginXXS: designToken.margin * 0.25, + + duration: `${designToken.duration}s`, + durationMid: `${(designToken.duration / 3) * 2}s`, + durationFast: `${designToken.duration / 3}s`, + + ...colorPalettes, + + heading1Size: Math.ceil(designToken.fontSize * 2.71), + heading2Size: Math.ceil(designToken.fontSize * 2.14), + heading3Size: Math.ceil(designToken.fontSize * 1.71), + heading4Size: Math.ceil(designToken.fontSize * 1.42), + heading5Size: Math.ceil(designToken.fontSize * 1.14), + + primaryColors, + errorColors, + warningColors, + + // TMP + tmpPrimaryColorWeak: primaryColors[2], + tmpPrimaryHoverColorWeak: primaryColors[0], + tmpPrimaryColor6: primaryColors[5], + tmpPrimaryColor7: primaryColors[6], + + tmpSuccessColorDeprecatedBg: successColors[0], + tmpWarningColorDeprecatedBg: warningColors[0], + tmpErrorColorDeprecatedBg: errorColors[0], + tmpInfoColorDeprecatedBg: infoColors[0], + + tmpSuccessColorDeprecatedBorder: successColors[2], + tmpWarningColorDeprecatedBorder: warningColors[2], + tmpErrorColorDeprecatedBorder: errorColors[2], + tmpInfoColorDeprecatedBorder: infoColors[2], + }; +} + +// ================================ Context ================================= +export const ThemeContext = React.createContext( + new Theme(derivative), +); + +export const DesignTokenContext = React.createContext<{ + token: Partial; + hashed?: string | boolean; +}>({ + token: defaultDesignToken, +}); + +// ================================== Hook ================================== +export function useToken(): [Theme, DerivativeToken, string] { + const { token: rootDesignToken, hashed } = React.useContext(DesignTokenContext); + const theme = React.useContext(ThemeContext); + + const salt = `${version}-${hashed || ''}`; + + const [token, hashId] = useCacheToken( + theme, + [defaultDesignToken, rootDesignToken], + { + salt, + }, + ); + return [theme, token, hashed ? hashId : '']; +} + +export type UseComponentStyleResult = [(node: React.ReactNode) => React.ReactElement, string]; + +export type GenerateStyle = ( + token: ComponentToken, + hashId?: string, +) => ReturnType; + +// ================================== Util ================================== +export function withPrefix( + style: CSSObject, + prefixCls: string, + additionalClsList: string[] = [], +): CSSObject { + const fullClsList = [prefixCls, ...additionalClsList].filter(cls => cls).map(cls => `.${cls}`); + + return { + [fullClsList.join('')]: style, + }; +} diff --git a/components/_util/theme/util/index.tsx b/components/_util/theme/util/index.tsx new file mode 100644 index 0000000000..d04909f344 --- /dev/null +++ b/components/_util/theme/util/index.tsx @@ -0,0 +1,56 @@ +/* eslint-disable import/prefer-default-export */ +import { CSSObject } from '@ant-design/cssinjs'; +import type { DerivativeToken } from '..'; + +export const resetComponent = (token: DerivativeToken): CSSObject => ({ + boxSizing: 'border-box', + margin: 0, + padding: 0, + color: token.textColor, + fontSize: token.fontSize, + // font-variant: @font-variant-base; + lineHeight: token.lineHeight, + listStyle: 'none', + // font-feature-settings: @font-feature-settings-base; +}); + +export const resetIcon = (): CSSObject => ({ + display: 'inline-block', + color: 'inherit', + fontStyle: 'normal', + lineHeight: 0, + textAlign: 'center', + textTransform: 'none', + // for SVG icon, see https://blog.prototypr.io/align-svg-icons-to-text-and-say-goodbye-to-font-icons-d44b3d7b26b4 + verticalAlign: '-0.125em', + textRendering: 'optimizeLegibility', + '-webkit-font-smoothing': 'antialiased', + '-moz-osx-font-smoothing': 'grayscale', + + '> *': { + lineHeight: 1, + }, + + svg: { + display: 'inline-block', + }, + + '& &-icon': { + display: 'block', + }, +}); + +export const clearFix = (): CSSObject => ({ + // https://github.com/ant-design/ant-design/issues/21301#issuecomment-583955229 + '&::before': { + display: 'table', + content: '""', + }, + + '&::after': { + // https://github.com/ant-design/ant-design/issues/21864 + display: 'table', + clear: 'both', + content: '""', + }, +}); diff --git a/components/_util/theme/util/motion.tsx b/components/_util/theme/util/motion.tsx new file mode 100644 index 0000000000..f6b2698161 --- /dev/null +++ b/components/_util/theme/util/motion.tsx @@ -0,0 +1,52 @@ +/* eslint-disable import/prefer-default-export */ +import { CSSObject, Keyframes } from '@ant-design/cssinjs'; + +const initMotionCommon = (duration: string): CSSObject => ({ + animationDuration: duration, + animationFillMode: 'both', +}); + +// FIXME: origin less code seems same as initMotionCommon. Maybe we can safe remove +const initMotionCommonLeave = (duration: string): CSSObject => ({ + animationDuration: duration, + animationFillMode: 'both', +}); + +export const initMotion = ( + hashId: string, + motionName: string, + inKeyframes: Keyframes, + outKeyframes: Keyframes, + duration: string, +): CSSObject => { + const motionCls = `.${motionName}`; + + return { + [` + ${motionCls}-enter, + ${motionCls}-appear + `]: { + ...initMotionCommon(duration), + animationPlayState: 'paused', + }, + + [`${motionCls}-leave`]: { + ...initMotionCommonLeave(duration), + animationPlayState: 'paused', + }, + + [` + ${motionCls}-enter${motionCls}-enter-active, + ${motionCls}-appear${motionCls}-appear-active + `]: { + animationName: inKeyframes.getName(hashId), + animationPlayState: 'running', + }, + + [`${motionCls}-leave${motionCls}-leave-active`]: { + animationName: outKeyframes.getName(hashId), + animationPlayState: 'running', + pointerEvents: 'none', + }, + }; +}; diff --git a/components/_util/theme/util/operationUnit.tsx b/components/_util/theme/util/operationUnit.tsx new file mode 100644 index 0000000000..558baa68a8 --- /dev/null +++ b/components/_util/theme/util/operationUnit.tsx @@ -0,0 +1,19 @@ +import type { CSSObject } from '@ant-design/cssinjs'; +import { DerivativeToken } from '..'; + +// eslint-disable-next-line import/prefer-default-export +export const operationUnit = (token: DerivativeToken): CSSObject => ({ + color: token.linkColor, + textDecoration: 'none', + outline: 'none', + cursor: 'pointer', + transition: `color ${token.duration}`, + + '&:focus, &:hover': { + color: token.linkHoverColor, + }, + + '&:active': { + color: token.linkActiveColor, + }, +}); diff --git a/components/_util/theme/util/slide.tsx b/components/_util/theme/util/slide.tsx new file mode 100644 index 0000000000..229bbce4f9 --- /dev/null +++ b/components/_util/theme/util/slide.tsx @@ -0,0 +1,145 @@ +import { CSSInterpolation, Keyframes } from '@ant-design/cssinjs'; +import type { DerivativeToken } from '..'; +import { initMotion } from './motion'; + +export const initSlideMotion = ( + hashId: string, + rootPrefixCls: string, + motionName: string, + inKeyframes: Keyframes, + outKeyframes: Keyframes, + token: DerivativeToken, +): CSSInterpolation => { + const rootMotionName = `${rootPrefixCls}-${motionName}`; + const motionCls = `.${rootMotionName}`; + + return [ + initMotion(hashId, rootMotionName, inKeyframes, outKeyframes, token.durationMid), + + { + [` + ${motionCls}-enter, + ${motionCls}-appear + `]: { + opacity: 0, + animationTimingFunction: token.easeOutQuint, + }, + + [`${motionCls}-leave`]: { + animationTimingFunction: token.easeInQuint, + }, + }, + ]; +}; + +export const slideUpIn = new Keyframes('antSlideUpIn', { + '0%': { + transform: 'scaleY(0.8)', + transformOrigin: '0% 0%', + opacity: 0, + }, + + '100%': { + transform: 'scaleY(1)', + transformOrigin: '0% 0%', + opacity: 1, + }, +}); + +export const slideUpOut = new Keyframes('antSlideUpOut', { + '0%': { + transform: 'scaleY(1)', + transformOrigin: '0% 0%', + opacity: 1, + }, + + '100%': { + transform: 'scaleY(0.8)', + transformOrigin: '0% 0%', + opacity: 0, + }, +}); + +export const slideDownIn = new Keyframes('antSlideDownIn', { + '0%': { + transform: 'scaleY(0.8)', + transformOrigin: '100% 100%', + opacity: 0, + }, + + '100%': { + transform: 'scaleY(1)', + transformOrigin: '100% 100%', + opacity: 1, + }, +}); + +export const slideDownOut = new Keyframes('antSlideDownOut', { + '0%': { + transform: 'scaleY(1)', + transformOrigin: '100% 100%', + opacity: 1, + }, + + '100%': { + transform: 'scaleY(0.8)', + transformOrigin: '100% 100%', + opacity: 0, + }, +}); + +export const slideLeftIn = new Keyframes('antSlideLeftIn', { + '0%': { + transform: 'scaleX(0.8)', + transformOrigin: '0% 0%', + opacity: 0, + }, + + '100%': { + transform: 'scaleX(1)', + transformOrigin: '0% 0%', + opacity: 1, + }, +}); + +export const slideLeftOut = new Keyframes('antSlideLeftOut', { + '0%': { + transform: 'scaleX(1)', + transformOrigin: '0% 0%', + opacity: 1, + }, + + '100%': { + transform: 'scaleX(0.8)', + transformOrigin: '0% 0%', + opacity: 0, + }, +}); + +export const slideRightIn = new Keyframes('antSlideRightIn', { + '0%': { + transform: 'scaleX(0.8)', + transformOrigin: '100% 0%', + opacity: 0, + }, + + '100%': { + transform: 'scaleX(1)', + transformOrigin: '100% 0%', + opacity: 1, + }, +}); + +export const slideRightOut = new Keyframes('antSlideRightOut', { + '0%': { + transform: 'scaleX(1)', + transformOrigin: '100% 0%', + opacity: 1, + }, + + '100%': { + transform: 'scaleX(0.8)', + transformOrigin: '100% 0%', + opacity: 0, + }, +}); diff --git a/components/affix/__tests__/Affix.test.tsx b/components/affix/__tests__/Affix.test.tsx index e67833cbbb..5c47a383f4 100644 --- a/components/affix/__tests__/Affix.test.tsx +++ b/components/affix/__tests__/Affix.test.tsx @@ -17,7 +17,7 @@ class AffixMounter extends React.Component<{ }> { private container: HTMLDivElement; - public affix: Affix; + public affix: React.Component; componentDidMount() { this.container.addEventListener = jest @@ -58,7 +58,7 @@ describe('Affix Render', () => { const domMock = jest.spyOn(HTMLElement.prototype, 'getBoundingClientRect'); let affixMounterWrapper: ReactWrapper; - let affixWrapper: ReactWrapper; + let affixWrapper: ReactWrapper>; const classRect: Record = { container: { @@ -157,9 +157,9 @@ describe('Affix Render', () => { const getTarget = () => container; affixWrapper = mount({null}); affixWrapper.setProps({ target: () => null }); - expect(affixWrapper.instance().state.status).toBe(0); - expect(affixWrapper.instance().state.affixStyle).toBe(undefined); - expect(affixWrapper.instance().state.placeholderStyle).toBe(undefined); + expect(affixWrapper.find('Affix').last().state().status).toBe(0); + expect(affixWrapper.find('Affix').last().state().affixStyle).toBe(undefined); + expect(affixWrapper.find('Affix').last().state().placeholderStyle).toBe(undefined); }); it('instance change', async () => { diff --git a/components/affix/index.tsx b/components/affix/index.tsx index c39d282b2f..1be9f0f545 100644 --- a/components/affix/index.tsx +++ b/components/affix/index.tsx @@ -33,6 +33,10 @@ export interface AffixProps { children: React.ReactNode; } +export interface InternalAffixProps extends AffixProps { + affixPrefixCls: string; +} + enum AffixStatus { None, Prepare, @@ -47,7 +51,7 @@ export interface AffixState { prevTarget: Window | HTMLElement | null; } -class Affix extends React.Component { +class Affix extends React.Component { static contextType = ConfigContext; state: AffixState = { @@ -126,7 +130,7 @@ class Affix extends React.Component { getOffsetTop = () => { const { offsetBottom, offsetTop } = this.props; - return (offsetBottom === undefined && offsetTop === undefined) ? 0 : offsetTop; + return offsetBottom === undefined && offsetTop === undefined ? 0 : offsetTop; }; getOffsetBottom = () => this.props.offsetBottom; @@ -250,14 +254,20 @@ class Affix extends React.Component { // =================== Render =================== render() { - const { getPrefixCls } = this.context; const { affixStyle, placeholderStyle } = this.state; - const { prefixCls, children } = this.props; + const { affixPrefixCls, children } = this.props; const className = classNames({ - [getPrefixCls('affix', prefixCls)]: !!affixStyle, + [affixPrefixCls]: !!affixStyle, }); - let props = omit(this.props, ['prefixCls', 'offsetTop', 'offsetBottom', 'target', 'onChange']); + let props = omit(this.props, [ + 'prefixCls', + 'offsetTop', + 'offsetBottom', + 'target', + 'onChange', + 'affixPrefixCls', + ]); // Omit this since `onTestUpdatePosition` only works on test. if (process.env.NODE_ENV === 'test') { props = omit(props as typeof props & { onTestUpdatePosition: any }, ['onTestUpdatePosition']); @@ -286,4 +296,23 @@ class Affix extends React.Component { } } -export default Affix; +const AffixFC = React.forwardRef((props, ref) => { + const { prefixCls: customizePrefixCls } = props; + const { getPrefixCls } = React.useContext(ConfigContext); + + const affixPrefixCls = getPrefixCls('affix', customizePrefixCls); + + const AffixProps: InternalAffixProps = { + ...props, + + affixPrefixCls, + }; + + return ; +}); + +if (process.env.NODE_ENV !== 'production') { + AffixFC.displayName = 'Affix'; +} + +export default AffixFC; diff --git a/components/affix/utils.ts b/components/affix/utils.ts index dcbe2a2907..df79482da4 100644 --- a/components/affix/utils.ts +++ b/components/affix/utils.ts @@ -1,5 +1,4 @@ import addEventListener from 'rc-util/lib/Dom/addEventListener'; -import Affix from '.'; export type BindElement = HTMLElement | Window | null | undefined; @@ -41,7 +40,7 @@ const TRIGGER_EVENTS = [ interface ObserverEntity { target: HTMLElement | Window; - affixList: Affix[]; + affixList: any[]; eventHandlers: { [eventName: string]: any }; } @@ -52,7 +51,7 @@ export function getObserverEntities() { return observerEntities; } -export function addObserveTarget(target: HTMLElement | Window | null, affix: Affix): void { +export function addObserveTarget(target: HTMLElement | Window | null, affix: T): void { if (!target) return; let entity: ObserverEntity | undefined = observerEntities.find(item => item.target === target); @@ -78,7 +77,7 @@ export function addObserveTarget(target: HTMLElement | Window | null, affix: Aff } } -export function removeObserveTarget(affix: Affix): void { +export function removeObserveTarget(affix: T): void { const observerEntity = observerEntities.find(oriObserverEntity => { const hasAffix = oriObserverEntity.affixList.some(item => item === affix); if (hasAffix) { diff --git a/components/alert/index.en-US.md b/components/alert/index.en-US.md index d0f9bdcee0..8b8992206b 100644 --- a/components/alert/index.en-US.md +++ b/components/alert/index.en-US.md @@ -21,7 +21,7 @@ Alert component for feedback. | banner | Whether to show as banner | boolean | false | | | closable | Whether Alert can be closed | boolean | - | | | closeText | Close text to show | ReactNode | - | | -| closeIcon | Custom close icon | ReactNode | | 4.17.0 | +| closeIcon | Custom close icon | ReactNode | `` | 4.17.0 | | description | Additional content of Alert | ReactNode | - | | | icon | Custom icon, effective when `showIcon` is true | ReactNode | - | | | message | Content of Alert | ReactNode | - | | diff --git a/components/alert/index.tsx b/components/alert/index.tsx index 4ad113f95e..416c0e9c6f 100644 --- a/components/alert/index.tsx +++ b/components/alert/index.tsx @@ -16,6 +16,9 @@ import getDataOrAriaProps from '../_util/getDataOrAriaProps'; import ErrorBoundary from './ErrorBoundary'; import { replaceElement } from '../_util/reactNode'; +// CSSINJS +import useStyle from './style'; + export interface AlertProps { /** Type of Alert styles, options:`success`, `info`, `warning`, `error` */ type?: 'success' | 'info' | 'warning' | 'error'; @@ -87,8 +90,9 @@ const Alert: AlertInterface = ({ const [closed, setClosed] = React.useState(false); const ref = React.useRef(); - const { getPrefixCls, direction } = React.useContext(ConfigContext); + const { getPrefixCls, direction, iconPrefixCls } = React.useContext(ConfigContext); const prefixCls = getPrefixCls('alert', customizePrefixCls); + const [wrapSSR, hashId] = useStyle(prefixCls, iconPrefixCls); const handleClose = (e: React.MouseEvent) => { setClosed(true); @@ -147,11 +151,12 @@ const Alert: AlertInterface = ({ [`${prefixCls}-rtl`]: direction === 'rtl', }, className, + hashId, ); const dataOrAriaProps = getDataOrAriaProps(props); - return ( + return wrapSSR( )} - + , ); }; diff --git a/components/alert/index.zh-CN.md b/components/alert/index.zh-CN.md index 3f99bfbc33..8946f08330 100644 --- a/components/alert/index.zh-CN.md +++ b/components/alert/index.zh-CN.md @@ -22,7 +22,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/8emPa3fjl/Alert.svg | banner | 是否用作顶部公告 | boolean | false | | | closable | 默认不显示关闭按钮 | boolean | - | | | closeText | 自定义关闭按钮 | ReactNode | - | | -| closeIcon | 自定义关闭 Icon | ReactNode | | 4.17.0 | +| closeIcon | 自定义关闭 Icon | ReactNode | `` | 4.17.0 | | description | 警告提示的辅助性文字介绍 | ReactNode | - | | | icon | 自定义图标,`showIcon` 为 true 时有效 | ReactNode | - | | | message | 警告提示内容 | ReactNode | - | | diff --git a/components/alert/style/index.less b/components/alert/style/index.less index 7223850443..f0ac0f3cc3 100644 --- a/components/alert/style/index.less +++ b/components/alert/style/index.less @@ -1,155 +1,155 @@ -@import '../../style/themes/index'; -@import '../../style/mixins/index'; +// @import '../../style/themes/index'; +// @import '../../style/mixins/index'; -@alert-prefix-cls: ~'@{ant-prefix}-alert'; +// @alert-prefix-cls: ~'@{ant-prefix}-alert'; -.@{alert-prefix-cls} { - .reset-component(); +// .@{alert-prefix-cls} { +// .reset-component(); - position: relative; - display: flex; - align-items: center; - padding: 8px 15px; - word-wrap: break-word; - border-radius: @border-radius-base; +// position: relative; +// display: flex; +// align-items: center; +// padding: 8px 15px; +// word-wrap: break-word; +// border-radius: @border-radius-base; - &-content { - flex: 1; - min-width: 0; - } +// &-content { +// flex: 1; +// min-width: 0; +// } - &-icon { - margin-right: @margin-xs; - } +// &-icon { +// margin-right: @margin-xs; +// } - &-description { - display: none; - font-size: @font-size-base; - line-height: @font-size-base + 8px; - } +// &-description { +// display: none; +// font-size: @font-size-base; +// line-height: @font-size-base + 8px; +// } - &-success { - background-color: @alert-success-bg-color; - border: @border-width-base @border-style-base @alert-success-border-color; - .@{alert-prefix-cls}-icon { - color: @alert-success-icon-color; - } - } +// &-success { +// background-color: @alert-success-bg-color; +// border: @border-width-base @border-style-base @alert-success-border-color; +// .@{alert-prefix-cls}-icon { +// color: @alert-success-icon-color; +// } +// } - &-info { - background-color: @alert-info-bg-color; - border: @border-width-base @border-style-base @alert-info-border-color; - .@{alert-prefix-cls}-icon { - color: @alert-info-icon-color; - } - } +// &-info { +// background-color: @alert-info-bg-color; +// border: @border-width-base @border-style-base @alert-info-border-color; +// .@{alert-prefix-cls}-icon { +// color: @alert-info-icon-color; +// } +// } - &-warning { - background-color: @alert-warning-bg-color; - border: @border-width-base @border-style-base @alert-warning-border-color; - .@{alert-prefix-cls}-icon { - color: @alert-warning-icon-color; - } - } +// &-warning { +// background-color: @alert-warning-bg-color; +// border: @border-width-base @border-style-base @alert-warning-border-color; +// .@{alert-prefix-cls}-icon { +// color: @alert-warning-icon-color; +// } +// } - &-error { - background-color: @alert-error-bg-color; - border: @border-width-base @border-style-base @alert-error-border-color; +// &-error { +// background-color: @alert-error-bg-color; +// border: @border-width-base @border-style-base @alert-error-border-color; - .@{alert-prefix-cls}-icon { - color: @alert-error-icon-color; - } +// .@{alert-prefix-cls}-icon { +// color: @alert-error-icon-color; +// } - .@{alert-prefix-cls}-description > pre { - margin: 0; - padding: 0; - } - } +// .@{alert-prefix-cls}-description > pre { +// margin: 0; +// padding: 0; +// } +// } - &-action { - margin-left: @margin-xs; - } +// &-action { +// margin-left: @margin-xs; +// } - &-close-icon { - margin-left: @margin-xs; - padding: 0; - overflow: hidden; - font-size: @font-size-sm; - line-height: @font-size-sm; - background-color: transparent; - border: none; - outline: none; - cursor: pointer; +// &-close-icon { +// margin-left: @margin-xs; +// padding: 0; +// overflow: hidden; +// font-size: @font-size-sm; +// line-height: @font-size-sm; +// background-color: transparent; +// border: none; +// outline: none; +// cursor: pointer; - .@{iconfont-css-prefix}-close { - color: @alert-close-color; - transition: color 0.3s; +// .@{iconfont-css-prefix}-close { +// color: @alert-close-color; +// transition: color 0.3s; - &:hover { - color: @alert-close-hover-color; - } - } - } +// &:hover { +// color: @alert-close-hover-color; +// } +// } +// } - &-close-text { - color: @alert-close-color; - transition: color 0.3s; +// &-close-text { +// color: @alert-close-color; +// transition: color 0.3s; - &:hover { - color: @alert-close-hover-color; - } - } +// &:hover { +// color: @alert-close-hover-color; +// } +// } - &-with-description { - align-items: flex-start; - padding: @alert-with-description-padding; - } +// &-with-description { +// align-items: flex-start; +// padding: @alert-with-description-padding; +// } - &-with-description&-no-icon { - padding: @alert-with-description-no-icon-padding-vertical 15px; - } +// &-with-description&-no-icon { +// padding: @alert-with-description-no-icon-padding-vertical 15px; +// } - &-with-description &-icon { - margin-right: @alert-with-description-padding-vertical; - font-size: @alert-with-description-icon-size; - } +// &-with-description &-icon { +// margin-right: @alert-with-description-padding-vertical; +// font-size: @alert-with-description-icon-size; +// } - &-with-description &-message { - display: block; - margin-bottom: 4px; - color: @alert-message-color; - font-size: @font-size-lg; - } +// &-with-description &-message { +// display: block; +// margin-bottom: 4px; +// color: @alert-message-color; +// font-size: @font-size-lg; +// } - &-message { - color: @alert-message-color; - } +// &-message { +// color: @alert-message-color; +// } - &-with-description &-description { - display: block; - } +// &-with-description &-description { +// display: block; +// } - &&-motion-leave { - overflow: hidden; - opacity: 1; - transition: max-height 0.3s @ease-in-out-circ, opacity 0.3s @ease-in-out-circ, - padding-top 0.3s @ease-in-out-circ, padding-bottom 0.3s @ease-in-out-circ, - margin-bottom 0.3s @ease-in-out-circ; - } +// &&-motion-leave { +// overflow: hidden; +// opacity: 1; +// transition: max-height 0.3s @ease-in-out-circ, opacity 0.3s @ease-in-out-circ, +// padding-top 0.3s @ease-in-out-circ, padding-bottom 0.3s @ease-in-out-circ, +// margin-bottom 0.3s @ease-in-out-circ; +// } - &&-motion-leave-active { - max-height: 0; - margin-bottom: 0 !important; - padding-top: 0; - padding-bottom: 0; - opacity: 0; - } +// &&-motion-leave-active { +// max-height: 0; +// margin-bottom: 0 !important; +// padding-top: 0; +// padding-bottom: 0; +// opacity: 0; +// } - &-banner { - margin-bottom: 0; - border: 0; - border-radius: 0; - } -} +// &-banner { +// margin-bottom: 0; +// border: 0; +// border-radius: 0; +// } +// } -@import './rtl'; +// @import './rtl'; diff --git a/components/alert/style/index.tsx b/components/alert/style/index.tsx index 3a3ab0de59..a4021c9b81 100644 --- a/components/alert/style/index.tsx +++ b/components/alert/style/index.tsx @@ -1,2 +1,342 @@ -import '../../style/index.less'; -import './index.less'; +// import '../../style/index.less'; +// import './index.less'; + +// deps-lint-skip-all +import { generate } from '@ant-design/colors'; +import { CSSInterpolation, CSSObject } from '@ant-design/cssinjs'; + +import { + DerivativeToken, + useStyleRegister, + useToken, + resetComponent, + UseComponentStyleResult, + GenerateStyle, +} from '../../_util/theme'; + +// FIXME: missing token +type AlertToken = DerivativeToken & { + alertCls: string; + iconPrefixCls: string; + + alertMessageColor: string; + alertCloseColor: string; + alertCloseHoverColor: string; + + alertInfoBgColor: string; + alertInfoIconColor: string; + alertInfoBorderColor: string; + + alertSuccessBgColor: string; + alertSuccessIconColor: string; + alertSuccessBorderColor: string; + + alertWarningBgColor: string; + alertWarningIconColor: string; + alertWarningBorderColor: string; + + alertErrorBgColor: string; + alertErrorIconColor: string; + alertErrorBorderColor: string; + + alertWithDescriptionIconSize: number; + alertWithDescriptionPaddingVertical: number; + alertWithDescriptionNoIconPaddingVertical: number; +}; + +const genAlertTypeStyle = ( + bgColor: string, + borderColor: string, + iconColor: string, + token: AlertToken, + alertCls: string, +): CSSObject => ({ + backgroundColor: bgColor, + border: `${token.borderWidth}px ${token.borderStyle} ${borderColor}`, + [`${alertCls}-icon`]: { + color: iconColor, + }, +}); + +export const genBaseStyle: GenerateStyle = (token: AlertToken): CSSObject => { + const { + alertCls, + duration, + marginXS, + fontSize, + fontSizeLG, + borderRadius, + easeInOutCirc, + alertMessageColor, + alertWithDescriptionIconSize, + alertWithDescriptionPaddingVertical, + alertWithDescriptionNoIconPaddingVertical, + } = token; + + return { + [alertCls]: { + ...resetComponent(token), + position: 'relative', + display: 'flex', + alignItems: 'center', + padding: '8px 15px', + wordWrap: 'break-word', + borderRadius, + + '&&-rtl': { + direction: 'rtl', + }, + + [`${alertCls}-content`]: { + flex: 1, + minWidth: 0, + }, + + [`${alertCls}-icon`]: { + marginInlineEnd: marginXS, + }, + + [`&-description`]: { + display: 'none', + fontSize, + lineHeight: `${fontSize + 8}px`, + }, + + '&-message': { + color: alertMessageColor, + }, + + '&&-motion-leave': { + overflow: 'hidden', + opacity: 1, + transition: `max-height ${duration} ${easeInOutCirc}, opacity ${duration} ${easeInOutCirc}, + padding-top ${duration} ${easeInOutCirc}, padding-bottom ${duration} ${easeInOutCirc}, + margin-bottom ${duration} ${easeInOutCirc}`, + }, + + '&&-motion-leave-active': { + maxHeight: 0, + marginBottom: '0 !important', + paddingTop: 0, + paddingBottom: 0, + opacity: 0, + }, + }, + + [`${alertCls}-with-description`]: { + alignItems: 'flex-start', + paddingInlineStart: alertWithDescriptionIconSize, + paddingInlineEnd: alertWithDescriptionPaddingVertical, + paddingBlock: alertWithDescriptionPaddingVertical, + + [`&${alertCls}-no-icon`]: { + padding: `${alertWithDescriptionNoIconPaddingVertical}px 15px`, + }, + + [`${alertCls}-icon`]: { + marginInlineEnd: alertWithDescriptionPaddingVertical, + fontSize: alertWithDescriptionIconSize, + }, + + [`${alertCls}-message`]: { + display: 'block', + marginBottom: '4px', + color: alertMessageColor, + fontSize: fontSizeLG, + }, + + [`${alertCls}-description`]: { + display: 'block', + }, + }, + + [`${alertCls}-banner`]: { + marginBottom: 0, + border: '0 !important', + borderRadius: 0, + }, + }; +}; + +export const genTypeStyle: GenerateStyle = (token: AlertToken): CSSObject => { + const { + alertCls, + alertInfoBgColor, + alertInfoIconColor, + alertInfoBorderColor, + + alertSuccessBgColor, + alertSuccessIconColor, + alertSuccessBorderColor, + + alertWarningBgColor, + alertWarningIconColor, + alertWarningBorderColor, + + alertErrorBgColor, + alertErrorIconColor, + alertErrorBorderColor, + } = token; + + return { + [alertCls]: { + '&-success': genAlertTypeStyle( + alertSuccessBgColor, + alertSuccessBorderColor, + alertSuccessIconColor, + token, + alertCls, + ), + '&-info': genAlertTypeStyle( + alertInfoBgColor, + alertInfoBorderColor, + alertInfoIconColor, + token, + alertCls, + ), + '&-warning': genAlertTypeStyle( + alertWarningBgColor, + alertWarningBorderColor, + alertWarningIconColor, + token, + alertCls, + ), + '&-error': { + ...genAlertTypeStyle( + alertErrorBgColor, + alertErrorBorderColor, + alertErrorIconColor, + token, + alertCls, + ), + [`${alertCls}-description > pre`]: { + margin: 0, + padding: 0, + }, + }, + }, + }; +}; + +export const genActionStyle: GenerateStyle = (token: AlertToken): CSSObject => { + const { + alertCls, + iconPrefixCls, + duration, + marginXS, + fontSizeSM, + alertCloseColor, + alertCloseHoverColor, + } = token; + + return { + [alertCls]: { + [`&-action`]: { + marginInlineStart: marginXS, + }, + + [`${alertCls}-close-icon`]: { + marginInlineStart: marginXS, + padding: 0, + overflow: 'hidden', + fontSize: fontSizeSM, + lineHeight: `${fontSizeSM}px`, + backgroundColor: 'transparent', + border: 'none', + outline: 'none', + cursor: 'pointer', + + [`.${iconPrefixCls}-close`]: { + color: alertCloseColor, + transition: `color ${duration}`, + '&:hover': { + color: alertCloseHoverColor, + }, + }, + }, + + '&-close-text': { + color: alertCloseColor, + transition: `color ${duration}`, + '&:hover': { + color: alertCloseHoverColor, + }, + }, + }, + }; +}; + +export const genAlertStyle: GenerateStyle = (token: AlertToken): CSSInterpolation => [ + genBaseStyle(token), + genTypeStyle(token), + genActionStyle(token), +]; + +export default function useStyle( + prefixCls: string, + iconPrefixCls: string, +): UseComponentStyleResult { + const [theme, token, hashId] = useToken(); + + const alertCls = `.${prefixCls}`; + + const alertMessageColor = token.headingColor; + const alertCloseColor = token.textColorSecondary; + const alertCloseHoverColor = token.iconColorHover; + // FIXME + const alertWithDescriptionIconSize = 24; + const alertWithDescriptionPaddingVertical = token.padding - 1; + const alertWithDescriptionNoIconPaddingVertical = token.padding - 1; + + // FIXME + const infoColors = generate(token.infoColor); + const alertInfoBgColor = infoColors[0]; + const alertInfoIconColor = token.infoColor; + const alertInfoBorderColor = infoColors[2]; + + const successColors = generate(token.successColor); + const alertSuccessBgColor = successColors[0]; + const alertSuccessIconColor = token.successColor; + const alertSuccessBorderColor = successColors[2]; + + const warningColors = generate(token.warningColor); + const alertWarningBgColor = warningColors[0]; + const alertWarningIconColor = token.warningColor; + const alertWarningBorderColor = warningColors[2]; + + const errorColors = generate(token.errorColor); + const alertErrorBgColor = errorColors[0]; + const alertErrorIconColor = token.errorColor; + const alertErrorBorderColor = errorColors[2]; + + const alertToken: AlertToken = { + ...token, + alertCls, + iconPrefixCls, + alertInfoBgColor, + alertInfoIconColor, + alertInfoBorderColor, + alertSuccessBgColor, + alertSuccessIconColor, + alertSuccessBorderColor, + alertWarningBgColor, + alertWarningIconColor, + alertWarningBorderColor, + alertErrorBgColor, + alertErrorIconColor, + alertErrorBorderColor, + alertMessageColor, + alertCloseColor, + alertCloseHoverColor, + alertWithDescriptionIconSize, + alertWithDescriptionPaddingVertical, + alertWithDescriptionNoIconPaddingVertical, + }; + + return [ + useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => [ + genAlertStyle(alertToken), + ]), + hashId, + ]; +} diff --git a/components/auto-complete/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/auto-complete/__tests__/__snapshots__/demo-extend.test.ts.snap index 6bedc29b73..08fcb1420c 100644 --- a/components/auto-complete/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/auto-complete/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -107,7 +107,7 @@ exports[`renders ./components/auto-complete/demo/certain-category.md extend cont class="ant-select-selection-search" > `; +exports[`renders ./components/auto-complete/demo/status.md extend context correctly 1`] = ` +
+
+ +
+ +
+`; + exports[`renders ./components/auto-complete/demo/uncertain-category.md extend context correctly 1`] = `