From 2ee3d43534cb99ac152be831ddb6c370264fd1bc Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Sat, 12 Mar 2022 09:56:32 +0800 Subject: [PATCH] Feat css var (#5327) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style: affix & util * feat(alert): add customIcon slot * feat(anchor): ts type * style: auto-complete * feat: avatar add crossOrigin & maxPopoverTrigger * style(backTop): v-show instead v-if * style: badge * style: breadcrumb * feat: button add global size * feat: update i18n * feat: picker add disabledTime * test: update snap * doc: update img url * style: fix Card tabs of left position * doc: update cascader doc * feat: collapse * style: comment * style: configprovider * feat: date-picker add soem icon slot * style: update descriptions style * feat: add divider orientationMargin * doc: update drawer * feat: dropdown add destroyPopupOnHide & loading * style: update empty * feat: form add labelWrap * style: update grid * test: update grid snap * fix: image ts error * fix: mentions cannot select, close #5233 * doc: update pagination change info, close #5293 * fix: table dynamic expand error, close #5295 * style: remove not use * release 3.0.0-beta.11 * doc: update typo * feat: input add showCount * feat: inputNumber add prefix slot * style: update layout * style: update list * feat: add locale i18 * style: update locale ts * style: update mentions * feat: menu divider add dashed * perf: menu * perf: menu animate * feat: modal method add wrapClassName * style: update pageheader * feat: update pagination ts * feat: confirm add showCancel & promise * doc: update popover * style: update progress * style: radio * style: update rate、result、row * feat: select add fieldNames * feat: add skeleton button & input * feat: spin tip support slot * style: slider & space * stype: update steps ts type * style: update switch * feat: table add tree filter * test: update input sanp * feat: table add filterMode... * fix: tree autoExpandParent bug * test: update input snap * doc: tabs add destroyInactiveTabPane * style: update tag * style: update timeline & time-picker * fix: Tooltip arrowPointAtCenter 1px shift bug * feat: typography add enterEnterIcon triggerType * doc: update tree-select * fix: deps and TypeScript types * style: udpate transfer * style: update style * doc: add colorScheme * chore: add css var builg * doc: sort api * style: lint code * doc: add css var * test: update snap * chore: add pre script * chore: update lint * perf: collapse animate * perf: collapse tree * perf: typography shaking when edit * doc: update auto-complete demo * fix: table tree not have animate * feat: deprecated dropdown center placement * feat: deprecated dropdown center placement * test: update snap --- .antd-tools.config.js | 195 +++ .eslintignore | 1 + .gitignore | 3 + antd-tools/apiCollection.js | 68 + antd-tools/cli/run.js | 1 - antd-tools/getNpm.js | 17 + antd-tools/gulpfile.js | 116 +- antd-tools/replaceLib.js | 13 + antd-tools/runCmd.js | 8 + antd-tools/sortApiTable.js | 165 +++ antd-tools/transformLess.js | 19 +- antd-tools/utils/CleanUpStatsPlugin.js | 8 +- antd-tools/utils/get-npm-args.js | 5 + antd-tools/utils/getRunCmdEnv.js | 5 +- antd-tools/utils/projectHelper.js | 27 + antd-tools/utils/styleUtil.js | 11 + components/{modal => _util}/ActionButton.tsx | 10 +- components/_util/EventInterface.ts | 5 + .../__tests__/unreachableException.test.js | 8 + .../collapseMotion.tsx} | 10 +- components/_util/hooks/useConfigInject.ts | 1 + components/_util/hooks/useDestroyed.ts | 12 + components/_util/hooks/usePrefixCls.ts | 9 - components/_util/openAnimation.js | 67 - components/_util/styleChecker.ts | 23 +- components/_util/transition.tsx | 12 +- components/_util/unreachableException.ts | 7 + components/_util/wave.tsx | 6 +- components/affix/index.en-US.md | 14 +- components/affix/index.tsx | 5 +- components/affix/index.zh-CN.md | 16 +- components/affix/utils.ts | 17 +- .../__tests__/__snapshots__/demo.test.js.snap | 152 +-- components/alert/index.en-US.md | 1 + components/alert/index.tsx | 82 +- components/alert/index.zh-CN.md | 1 + components/alert/style/index.less | 70 +- components/alert/style/rtl.less | 40 + components/anchor/Anchor.tsx | 44 +- components/anchor/index.en-US.md | 10 +- components/anchor/index.zh-CN.md | 10 +- components/anchor/style/index.less | 3 + .../anchor/style/{index.ts => index.tsx} | 0 .../__tests__/__snapshots__/demo.test.js.snap | 6 +- .../auto-complete/demo/certain-category.vue | 58 +- .../auto-complete/demo/uncertain-category.vue | 66 +- components/auto-complete/index.en-US.md | 34 +- components/auto-complete/index.tsx | 26 +- components/auto-complete/index.zh-CN.md | 28 +- .../style/{index.ts => index.tsx} | 1 - components/avatar/Avatar.tsx | 12 +- components/avatar/Group.tsx | 27 +- .../__tests__/__snapshots__/demo.test.js.snap | 8 +- components/avatar/demo/group.vue | 6 +- components/avatar/demo/type.vue | 2 +- components/avatar/index.en-US.md | 18 +- components/avatar/index.zh-CN.md | 16 +- .../__tests__/__snapshots__/demo.test.js.snap | 12 +- components/back-top/index.tsx | 23 +- .../back-top/style/{index.ts => index.tsx} | 0 components/badge/Badge.tsx | 2 +- .../__tests__/__snapshots__/demo.test.js.snap | 175 ++- components/badge/demo/basic.vue | 8 +- components/badge/demo/change.vue | 17 +- components/badge/demo/colors.vue | 20 +- components/badge/demo/dot.vue | 27 +- components/badge/demo/index.vue | 2 +- components/badge/demo/link.vue | 4 +- components/badge/demo/overflow.vue | 10 +- components/badge/demo/ribbon.vue | 33 +- components/badge/demo/title.vue | 22 +- components/badge/index.zh-CN.md | 2 +- components/badge/style/index.less | 30 +- .../badge/style/{index.ts => index.tsx} | 0 components/badge/style/rtl.less | 49 +- components/breadcrumb/Breadcrumb.tsx | 4 +- components/breadcrumb/BreadcrumbItem.tsx | 2 +- components/breadcrumb/index.en-US.md | 2 +- components/breadcrumb/index.zh-CN.md | 2 +- components/breadcrumb/style/index.less | 2 + .../breadcrumb/style/{index.ts => index.tsx} | 1 + .../__tests__/__snapshots__/demo.test.js.snap | 37 +- components/button/button-group.tsx | 7 +- components/button/button.tsx | 33 +- components/button/buttonTypes.ts | 2 +- components/button/demo/ghost.vue | 2 +- components/button/demo/icon.vue | 46 + components/button/demo/loading.vue | 31 +- components/button/demo/size.vue | 2 +- components/button/index.en-US.md | 2 +- components/button/index.zh-CN.md | 4 +- components/button/style/index.less | 100 +- components/button/style/mixin.less | 169 ++- components/button/style/rtl.less | 21 +- .../__tests__/__snapshots__/demo.test.js.snap | 8 +- components/calendar/index.en-US.md | 8 +- components/calendar/index.zh-CN.md | 6 +- components/calendar/locale/bn_BD.tsx | 3 + components/calendar/locale/ka_GE.tsx | 3 + components/calendar/locale/km_KH.tsx | 3 + components/calendar/locale/ml_IN.tsx | 3 + components/calendar/locale/ur_PK.tsx | 3 + .../__tests__/__snapshots__/demo.test.js.snap | 2 +- components/card/demo/meta.vue | 2 +- components/card/index.en-US.md | 16 +- components/card/index.zh-CN.md | 16 +- components/card/style/index.less | 4 +- components/carousel/index.en-US.md | 2 +- components/cascader/index.en-US.md | 28 +- components/cascader/index.zh-CN.md | 26 +- components/checkbox/index.zh-CN.md | 4 +- components/collapse/Collapse.tsx | 26 +- .../__tests__/__snapshots__/demo.test.js.snap | 66 +- .../__snapshots__/index.test.js.snap | 4 +- components/collapse/index.en-US.md | 8 +- components/collapse/index.zh-CN.md | 8 +- components/collapse/style/index.less | 13 +- components/collapse/style/rtl.less | 10 +- components/color-picker/index.en-US.md | 24 +- components/color-picker/index.zh-CN.md | 24 +- .../__tests__/__snapshots__/demo.test.js.snap | 20 +- .../__snapshots__/index.test.js.snap | 6 +- components/comment/demo/basic.vue | 5 +- components/comment/demo/editor.vue | 7 +- components/comment/demo/list.vue | 4 +- components/comment/demo/nested.vue | 26 +- components/comment/style/index.less | 4 + .../comment/style/{index.ts => index.tsx} | 0 components/comment/style/rtl.less | 1 + components/components.ts | 10 +- components/config-provider/context.ts | 131 ++ components/config-provider/cssVariables.tsx | 97 ++ components/config-provider/index.en-US.md | 11 +- components/config-provider/index.tsx | 137 +- components/config-provider/index.zh-CN.md | 9 +- components/config-provider/renderEmpty.tsx | 9 +- .../__tests__/__snapshots__/demo.test.js.snap | 9 +- components/date-picker/demo/format.vue | 9 + .../generatePicker/generateRangePicker.tsx | 22 +- .../generatePicker/generateSinglePicker.tsx | 16 +- components/date-picker/index.en-US.md | 10 +- components/date-picker/index.zh-CN.md | 14 +- components/date-picker/locale/bn_BD.tsx | 27 + components/date-picker/locale/example.json | 2 +- components/date-picker/locale/ka_GE.tsx | 23 + components/date-picker/locale/km_KH.tsx | 27 + components/date-picker/locale/ml_IN.tsx | 27 + components/date-picker/locale/pt_PT.tsx | 2 +- components/date-picker/locale/sl_SI.tsx | 2 +- components/date-picker/locale/ur_PK.tsx | 27 + components/date-picker/locale/zh_CN.tsx | 2 +- components/date-picker/style/index.less | 5 + components/date-picker/style/panel.less | 24 +- components/date-picker/style/rtl.less | 10 +- components/descriptions/index.en-US.md | 26 +- components/descriptions/index.tsx | 1 + components/descriptions/index.zh-CN.md | 26 +- components/descriptions/style/index.less | 7 +- .../style/{index.ts => index.tsx} | 0 components/descriptions/style/rtl.less | 2 +- .../__tests__/__snapshots__/demo.test.js.snap | 4 + components/divider/demo/with-text.vue | 14 + components/divider/index.en-US.md | 3 +- components/divider/index.tsx | 34 +- components/divider/index.zh-CN.md | 13 +- components/divider/style/index.less | 31 +- .../divider/style/{index.ts => index.tsx} | 0 components/divider/style/rtl.less | 2 + .../__tests__/__snapshots__/demo.test.js.snap | 4 +- components/drawer/demo/basic.vue | 2 +- components/drawer/demo/form-in-drawer.vue | 10 +- components/drawer/demo/render-in-current.vue | 4 +- components/drawer/index.en-US.md | 2 +- components/drawer/index.tsx | 16 +- components/drawer/index.zh-CN.md | 4 +- components/drawer/style/drawer.less | 30 +- .../__tests__/__snapshots__/demo.test.js.snap | 49 +- .../dropdown-button.test.js.snap | 4 +- components/dropdown/demo/index.vue | 3 + components/dropdown/demo/loading.vue | 86 ++ components/dropdown/demo/placement.vue | 4 +- components/dropdown/dropdown-button.tsx | 10 +- components/dropdown/dropdown.tsx | 23 +- components/dropdown/index.en-US.md | 28 +- components/dropdown/index.zh-CN.md | 38 +- components/dropdown/props.ts | 28 +- components/dropdown/style/index.less | 36 +- components/dropdown/style/rtl.less | 7 +- components/dropdown/style/status.less | 4 +- .../__tests__/__snapshots__/demo.test.js.snap | 4 +- components/empty/empty.tsx | 5 +- components/empty/index.en-US.md | 2 +- components/empty/index.tsx | 12 +- components/empty/index.zh-CN.md | 2 +- components/empty/simple.tsx | 5 +- components/empty/style/index.less | 20 +- .../empty/style/{index.ts => index.tsx} | 0 components/form/ErrorList.tsx | 76 +- components/form/Form.tsx | 5 +- components/form/FormItem.tsx | 6 +- components/form/FormItemInput.tsx | 10 +- components/form/FormItemLabel.tsx | 4 + .../__tests__/__snapshots__/demo.test.js.snap | 236 ++-- components/form/context.ts | 1 + components/form/index.en-US.md | 51 +- components/form/index.zh-CN.md | 51 +- components/form/style/components.less | 11 +- components/form/style/horizontal.less | 10 +- components/form/style/index.less | 100 +- components/form/style/{index.ts => index.tsx} | 0 components/form/style/inline.less | 5 +- components/form/style/mixin.less | 6 +- components/form/style/rtl.less | 8 + components/form/style/status.less | 56 +- components/form/style/vertical.less | 7 +- components/grid/Col.tsx | 51 +- components/grid/Row.tsx | 22 +- .../__tests__/__snapshots__/demo.test.js.snap | 16 +- components/grid/demo/flex.vue | 10 +- components/grid/demo/gutter.vue | 2 +- components/grid/index.en-US.md | 2 +- components/grid/index.zh-CN.md | 2 +- components/grid/style/{index.ts => index.tsx} | 0 components/icon/index.en-US.md | 18 +- components/icon/index.zh-CN.md | 18 +- components/image/PreviewGroup.tsx | 10 +- .../__tests__/__snapshots__/demo.test.js.snap | 30 +- ...lledPreview.vue => controlled-preview.vue} | 0 components/image/demo/index.vue | 7 +- .../image/demo/preview-group-visible.vue | 49 + .../{previewGroup.vue => preview-group.vue} | 0 components/image/style/index.less | 46 +- .../image/style/{index.ts => index.tsx} | 0 .../__tests__/__snapshots__/demo.test.js.snap | 74 +- components/input-number/demo/formatter.vue | 4 +- components/input-number/demo/index.vue | 3 + components/input-number/demo/prefix.vue | 49 + components/input-number/demo/size.vue | 9 +- components/input-number/index.en-US.md | 34 +- components/input-number/index.tsx | 37 +- components/input-number/index.zh-CN.md | 18 +- components/input-number/style/affix.less | 64 + components/input-number/style/index.less | 1 + components/input/ClearableLabeledInput.tsx | 10 +- components/input/Input.tsx | 60 +- components/input/ResizableTextArea.tsx | 6 + components/input/TextArea.tsx | 5 +- .../__tests__/__snapshots__/demo.test.js.snap | 49 +- .../__snapshots__/index.test.js.snap | 2 +- components/input/demo/addon.vue | 62 +- components/input/demo/group.vue | 24 +- components/input/demo/search-input.vue | 10 +- components/input/demo/show-count.vue | 15 +- components/input/index.en-US.md | 29 +- components/input/index.zh-CN.md | 19 +- components/input/inputProps.ts | 7 +- components/input/style/affix.less | 8 + components/input/util.ts | 38 + .../__tests__/__snapshots__/demo.test.js.snap | 4 +- components/layout/demo/fixed-sider.vue | 2 +- components/layout/index.en-US.md | 8 +- components/layout/index.zh-CN.md | 8 +- components/layout/style/index.less | 2 + .../layout/style/{index.ts => index.tsx} | 0 .../__tests__/__snapshots__/demo.test.js.snap | 14 +- components/list/demo/basic.vue | 2 +- components/list/demo/loadmore.vue | 89 +- components/list/demo/vertical.vue | 2 +- components/list/index.en-US.md | 30 +- components/list/index.tsx | 70 +- components/list/index.zh-CN.md | 36 +- components/list/style/customize.less | 3 +- components/list/style/index.less | 9 + components/list/style/{index.ts => index.tsx} | 0 components/list/style/responsive.less | 3 + components/locale-provider/LocaleReceiver.tsx | 8 +- .../__snapshots__/index.test.js.snap | 408 ++++-- components/locale-provider/bn_BD.ts | 3 + components/locale-provider/ka_GE.ts | 3 + components/locale-provider/km_HK.ts | 3 + components/locale-provider/ml_IN.ts | 3 + components/locale-provider/ur_PK.ts | 3 + components/locale/bn_BD.tsx | 134 ++ components/locale/ca_ES.tsx | 1 + components/locale/cs_CZ.tsx | 6 +- components/locale/da_DK.tsx | 12 +- components/locale/de_DE.tsx | 3 + components/locale/default.tsx | 2 + components/locale/en_GB.tsx | 1 + components/locale/es_ES.tsx | 3 + components/locale/et_EE.tsx | 94 +- components/locale/fi_FI.tsx | 3 + components/locale/ka_GE.tsx | 134 ++ components/locale/kk_KZ.tsx | 2 +- components/locale/km_KH.tsx | 108 ++ components/locale/ko_KR.tsx | 2 +- components/locale/ml_IN.tsx | 134 ++ components/locale/ms_MY.tsx | 2 +- components/locale/pl_PL.tsx | 89 +- components/locale/ru_RU.tsx | 3 +- components/locale/tr_TR.tsx | 3 + components/locale/ur_PK.tsx | 134 ++ components/locale/zh_CN.tsx | 2 + components/locale/zh_HK.tsx | 6 + components/locale/zh_TW.tsx | 7 + .../__tests__/__snapshots__/demo.test.js.snap | 6 +- components/mentions/index.en-US.md | 6 +- components/mentions/index.tsx | 4 +- components/mentions/index.zh-CN.md | 4 +- components/mentions/style/index.less | 2 + .../mentions/style/{index.ts => index.tsx} | 0 .../__tests__/__snapshots__/demo.test.js.snap | 12 +- components/menu/index.en-US.md | 26 +- components/menu/index.zh-CN.md | 26 +- components/menu/src/Divider.tsx | 20 +- components/menu/src/InlineSubMenuList.tsx | 11 +- components/menu/src/Menu.tsx | 17 +- components/menu/src/PopupTrigger.tsx | 8 +- components/menu/src/SubMenu.tsx | 100 +- components/menu/src/hooks/useMenuContext.ts | 6 +- components/menu/style/dark.less | 7 + components/menu/style/index.less | 46 +- components/menu/style/rtl.less | 1 + components/menu/style/status.less | 4 +- components/message/index.en-US.md | 6 +- components/message/index.tsx | 5 +- components/message/index.zh-CN.md | 14 +- components/modal/ConfirmDialog.tsx | 8 +- components/modal/Modal.tsx | 3 +- .../__tests__/__snapshots__/demo.test.js.snap | 52 +- components/modal/demo/async.vue | 7 +- components/modal/demo/confirm.vue | 24 +- components/modal/demo/info.vue | 4 +- components/modal/index.en-US.md | 17 +- components/modal/index.tsx | 2 +- components/modal/index.zh-CN.md | 19 +- components/notification/index.en-US.md | 10 +- components/notification/index.zh-CN.md | 16 +- .../__tests__/__snapshots__/demo.test.js.snap | 1 + components/page-header/demo/responsive.vue | 2 +- components/page-header/index.en-US.md | 10 +- components/page-header/index.tsx | 6 +- components/page-header/index.zh-CN.md | 10 +- components/page-header/style/index.less | 4 +- .../page-header/style/{index.ts => index.tsx} | 0 components/page-header/style/rtl.less | 1 + components/pagination/Pagination.tsx | 84 +- components/pagination/index.en-US.md | 4 +- components/pagination/index.zh-CN.md | 4 +- components/pagination/style/index.less | 12 +- .../__tests__/__snapshots__/demo.test.js.snap | 6 + components/popconfirm/demo/index.vue | 3 + components/popconfirm/demo/promise.vue | 47 + components/popconfirm/index.en-US.md | 15 +- components/popconfirm/index.tsx | 49 +- components/popconfirm/index.zh-CN.md | 13 +- .../__tests__/__snapshots__/demo.test.js.snap | 20 +- .../popover/demo/arrow-point-at-center.vue | 4 +- components/popover/style/customize.less | 3 - components/popover/style/index.less | 5 + components/progress/Circle.tsx | 13 +- components/progress/index.en-US.md | 2 +- components/progress/index.zh-CN.md | 2 +- components/progress/style/index.less | 5 + components/radio/Radio.tsx | 3 +- components/radio/style/index.less | 27 +- .../radio/style/{index.ts => index.tsx} | 0 components/rate/index.en-US.md | 2 +- components/rate/index.zh-CN.md | 2 +- components/rate/style/index.less | 9 +- components/rate/style/{index.ts => index.tsx} | 0 components/result/index.en-US.md | 14 +- components/result/index.zh-CN.md | 14 +- components/result/style/index.less | 3 +- .../result/style/{index.ts => index.tsx} | 0 components/result/style/rtl.less | 2 +- components/row/style/{index.ts => index.tsx} | 0 .../__tests__/__snapshots__/demo.test.js.snap | 11 + components/select/demo/field-names.vue | 81 ++ components/select/demo/index.vue | 3 + components/select/index.en-US.md | 27 +- components/select/index.tsx | 8 +- components/select/index.zh-CN.md | 25 +- components/skeleton/Avatar.tsx | 25 +- components/skeleton/Button.tsx | 22 +- components/skeleton/Element.tsx | 15 +- components/skeleton/Image.tsx | 3 +- components/skeleton/Input.tsx | 5 +- components/skeleton/Paragraph.tsx | 10 +- components/skeleton/Skeleton.tsx | 10 +- components/skeleton/Title.tsx | 8 +- .../__tests__/__snapshots__/demo.test.js.snap | 111 +- components/skeleton/demo/element.vue | 75 ++ components/skeleton/demo/index.vue | 3 + components/skeleton/demo/list.vue | 2 +- components/skeleton/index.en-US.md | 20 +- components/skeleton/index.tsx | 10 +- components/skeleton/index.zh-CN.md | 20 +- components/skeleton/style/index.less | 12 + .../skeleton/style/{index.ts => index.tsx} | 0 components/skeleton/style/rtl.less | 1 + .../__tests__/__snapshots__/demo.test.js.snap | 8 +- components/slider/index.en-US.md | 14 +- components/slider/index.zh-CN.md | 12 +- components/slider/style/index.less | 6 + components/space/demo/vertical.vue | 2 +- components/space/style/index.less | 4 + .../space/style/{index.ts => index.tsx} | 0 components/spin/Spin.tsx | 9 +- .../__tests__/__snapshots__/demo.test.js.snap | 14 +- components/spin/index.en-US.md | 16 +- components/spin/index.zh-CN.md | 16 +- components/spin/style/index.less | 3 + components/spin/style/{index.ts => index.tsx} | 0 components/statistic/index.en-US.md | 2 +- components/steps/index.en-US.md | 12 +- components/steps/index.tsx | 45 +- components/steps/index.zh-CN.md | 12 +- components/steps/style/index.less | 9 + components/steps/style/label-placement.less | 6 + components/steps/style/nav.less | 4 + components/steps/style/progress-dot.less | 11 +- components/steps/style/rtl.less | 2 + components/steps/style/small.less | 1 + components/style/compact.less | 4 + components/style/core/base.less | 7 - components/style/core/global.less | 13 +- components/style/core/motion.less | 3 +- components/style/core/motion/fade.less | 2 + components/style/core/motion/move.less | 8 + components/style/core/motion/slide.less | 8 + components/style/core/motion/zoom.less | 17 +- components/style/dark.less | 2 + components/style/default.less | 4 + components/style/mixins/clearfix.less | 8 +- components/style/mixins/compatibility.less | 11 +- components/style/mixins/customize.less | 3 + components/style/mixins/iconfont.less | 15 - components/style/mixins/index.less | 6 +- components/style/mixins/modal-mask.less | 4 +- components/style/mixins/motion.less | 2 - components/style/mixins/operation-unit.less | 2 - components/style/mixins/reset.less | 2 - components/style/themes/compact.less | 12 +- components/style/themes/dark.less | 1 + components/style/themes/default.less | 128 +- components/style/themes/index.less | 8 +- components/style/themes/variable.less | 1116 +++++++++++++++++ components/style/v2-compatible-reset.less | 51 - components/style/v2-compatible-reset.tsx | 1 - components/style/variable.less | 4 + .../__tests__/__snapshots__/demo.test.js.snap | 36 +- .../__snapshots__/index.test.js.snap | 4 +- components/switch/index.en-US.md | 4 +- components/switch/index.tsx | 9 +- components/switch/index.zh-CN.md | 8 +- components/switch/style/index.less | 248 ++-- .../switch/style/{index.ts => index.tsx} | 0 components/switch/style/rtl.less | 52 + components/table/Table.tsx | 9 +- .../Table.pagination.test.js.snap | 2 +- .../__tests__/__snapshots__/demo.test.js.snap | 307 ++++- components/table/demo/colspan-rowspan.vue | 39 +- components/table/demo/edit-row.vue | 2 +- components/table/demo/filter-in-tree.vue | 138 ++ components/table/demo/index.vue | 4 +- components/table/demo/order-column.vue | 80 ++ components/table/demo/sticky.vue | 11 +- components/table/hooks/useColumns.tsx | 3 + .../table/hooks/useFilter/FilterDropdown.tsx | 286 ++++- .../table/hooks/useFilter/FilterSearch.tsx | 38 + components/table/hooks/useFilter/index.tsx | 6 +- components/table/hooks/usePagination.ts | 4 +- components/table/hooks/useSelection.tsx | 176 ++- components/table/index.en-US.md | 63 +- components/table/index.tsx | 11 +- components/table/index.zh-CN.md | 64 +- components/table/interface.tsx | 8 +- components/table/style/bordered.less | 14 +- components/table/style/index.less | 88 +- components/table/style/index.tsx | 2 + components/table/style/resize.less | 28 - components/table/style/rtl.less | 14 +- components/table/style/size.less | 4 +- .../__tests__/__snapshots__/demo.test.js.snap | 2 +- components/tabs/demo/custom-add-trigger.vue | 10 +- components/tabs/index.en-US.md | 11 +- components/tabs/index.zh-CN.md | 31 +- components/tag/style/index.less | 26 +- components/tag/style/{index.ts => index.tsx} | 0 components/time-picker/demo/addon.vue | 4 +- components/time-picker/locale/bn_BD.tsx | 8 + components/time-picker/locale/ka_GE.tsx | 8 + components/time-picker/locale/km_KH.tsx | 8 + components/time-picker/locale/ml_IN.tsx | 8 + components/time-picker/locale/ur_PK.tsx | 8 + components/timeline/index.en-US.md | 4 +- components/timeline/index.zh-CN.md | 4 +- components/timeline/style/index.less | 1 - components/tooltip/index.en-US.md | 6 +- components/tooltip/index.zh-CN.md | 4 +- components/tooltip/placements.ts | 5 +- .../tooltip/style/{index.ts => index.tsx} | 0 .../__tests__/__snapshots__/demo.test.js.snap | 48 +- .../__snapshots__/search.test.js.snap | 10 +- components/transfer/__tests__/search.test.js | 2 +- components/transfer/index.en-US.md | 22 +- components/transfer/index.tsx | 6 +- components/transfer/index.zh-CN.md | 22 +- components/transfer/list.tsx | 25 +- components/transfer/search.tsx | 41 +- components/transfer/style/customize.less | 9 +- components/transfer/style/index.less | 24 +- .../transfer/style/{index.ts => index.tsx} | 0 components/transfer/style/rtl.less | 2 + .../__tests__/__snapshots__/demo.test.js.snap | 8 +- components/tree-select/demo/async.vue | 6 +- components/tree-select/index.en-US.md | 80 +- components/tree-select/index.tsx | 12 +- components/tree-select/index.zh-CN.md | 80 +- components/tree/DirectoryTree.tsx | 6 +- .../__tests__/__snapshots__/demo.test.js.snap | 8 +- components/tree/index.en-US.md | 10 +- components/tree/index.zh-CN.md | 48 +- components/typography/Base.tsx | 17 +- components/typography/Editable.tsx | 22 +- components/typography/Typography.tsx | 14 +- .../__tests__/__snapshots__/demo.test.js.snap | 38 +- components/typography/__tests__/index.test.js | 18 +- components/typography/demo/interactive.vue | 61 +- components/typography/index.en-US.md | 17 +- components/typography/index.zh-CN.md | 17 +- components/typography/style/index.less | 12 +- .../typography/style/{index.ts => index.tsx} | 0 components/typography/util.tsx | 74 +- components/upload/UploadList/index.tsx | 4 +- components/upload/index.en-US.md | 65 +- components/upload/index.zh-CN.md | 65 +- components/vc-image/src/Image.tsx | 24 +- components/vc-image/src/Preview.tsx | 126 +- components/vc-picker/Picker.tsx | 74 +- components/vc-picker/PickerPanel.tsx | 14 +- components/vc-picker/RangePicker.tsx | 39 +- components/vc-picker/index.tsx | 1 + components/vc-picker/locale/bn_BD.ts | 33 + components/vc-picker/locale/es_MX.ts | 33 + components/vc-picker/locale/ka_GE.ts | 33 + components/vc-picker/locale/ur_PK.ts | 33 + .../vc-picker/panels/DatetimePanel/index.tsx | 3 +- .../vc-picker/panels/TimePanel/TimeBody.tsx | 37 +- .../vc-picker/panels/TimePanel/index.tsx | 12 +- components/vc-picker/utils/warnUtil.ts | 17 + components/vc-table/Body/BodyRow.tsx | 19 +- components/vc-table/Body/ExpandedRow.tsx | 37 +- components/vc-table/Body/MeasureCell.tsx | 2 +- components/vc-table/Body/index.tsx | 30 +- components/vc-table/Cell/index.tsx | 103 +- components/vc-table/ColGroup.tsx | 3 +- components/vc-table/Footer/Cell.tsx | 10 +- components/vc-table/Table.tsx | 36 +- components/vc-table/constant.ts | 1 + components/vc-table/context/BodyContext.tsx | 4 - .../vc-table/context/ExpandedRowContext.tsx | 18 + components/vc-table/context/HoverContext.tsx | 21 + components/vc-table/context/StickyContext.tsx | 13 + components/vc-table/hooks/useColumns.tsx | 50 +- .../vc-table/hooks/useFlattenRecords.ts | 14 +- components/vc-table/index.ts | 13 +- components/vc-table/interface.ts | 18 +- components/vc-table/stickyScrollBar.tsx | 3 + components/vc-table/utils/legacyUtil.ts | 50 +- components/vc-tree/MotionTreeNode.tsx | 23 +- components/vc-tree/Tree.tsx | 60 +- components/vc-trigger/Popup/PopupInner.tsx | 39 +- components/vc-util/Dom/dynamicCSS.ts | 99 ++ components/version/index.ts | 6 +- package.json | 32 +- scripts/css-variable-sync.js | 222 ++++ scripts/generate-version.js | 10 + site/debugger/index.tsx | 2 +- site/src/App.vue | 2 + site/src/layouts/index.vue | 2 +- site/src/router/index.js | 11 + .../vueDocs/customize-theme-variable.en-US.md | 80 ++ .../vueDocs/customize-theme-variable.zh-CN.md | 80 ++ site/src/vueDocs/customize-theme.en-US.md | 4 + site/src/vueDocs/customize-theme.zh-CN.md | 4 + site/src/vueDocs/i18n.en-US.md | 103 +- site/src/vueDocs/i18n.zh-CN.md | 103 +- site/themeConfig.ts | 1 + site/vite.config.ts | 1 + tests/__snapshots__/index.test.js.snap | 1 + webpack.build.conf.js | 122 +- webpack.config.js | 149 --- 594 files changed, 11092 insertions(+), 4173 deletions(-) create mode 100644 .antd-tools.config.js create mode 100644 antd-tools/apiCollection.js create mode 100644 antd-tools/getNpm.js create mode 100644 antd-tools/sortApiTable.js create mode 100644 antd-tools/utils/styleUtil.js rename components/{modal => _util}/ActionButton.tsx (92%) create mode 100644 components/_util/__tests__/unreachableException.test.js rename components/{upload/UploadList/listAnimation.ts => _util/collapseMotion.tsx} (81%) create mode 100644 components/_util/hooks/useDestroyed.ts delete mode 100644 components/_util/hooks/usePrefixCls.ts delete mode 100644 components/_util/openAnimation.js create mode 100644 components/_util/unreachableException.ts create mode 100644 components/alert/style/rtl.less rename components/anchor/style/{index.ts => index.tsx} (100%) rename components/auto-complete/style/{index.ts => index.tsx} (79%) rename components/back-top/style/{index.ts => index.tsx} (100%) rename components/badge/style/{index.ts => index.tsx} (100%) rename components/breadcrumb/style/{index.ts => index.tsx} (83%) create mode 100644 components/calendar/locale/bn_BD.tsx create mode 100644 components/calendar/locale/ka_GE.tsx create mode 100644 components/calendar/locale/km_KH.tsx create mode 100644 components/calendar/locale/ml_IN.tsx create mode 100644 components/calendar/locale/ur_PK.tsx rename components/comment/style/{index.ts => index.tsx} (100%) create mode 100644 components/config-provider/context.ts create mode 100644 components/config-provider/cssVariables.tsx create mode 100644 components/date-picker/locale/bn_BD.tsx create mode 100644 components/date-picker/locale/ka_GE.tsx create mode 100644 components/date-picker/locale/km_KH.tsx create mode 100644 components/date-picker/locale/ml_IN.tsx create mode 100644 components/date-picker/locale/ur_PK.tsx rename components/descriptions/style/{index.ts => index.tsx} (100%) rename components/divider/style/{index.ts => index.tsx} (100%) create mode 100644 components/dropdown/demo/loading.vue rename components/empty/style/{index.ts => index.tsx} (100%) rename components/form/style/{index.ts => index.tsx} (100%) rename components/grid/style/{index.ts => index.tsx} (100%) rename components/image/demo/{controlledPreview.vue => controlled-preview.vue} (100%) create mode 100644 components/image/demo/preview-group-visible.vue rename components/image/demo/{previewGroup.vue => preview-group.vue} (100%) rename components/image/style/{index.ts => index.tsx} (100%) create mode 100644 components/input-number/demo/prefix.vue create mode 100644 components/input-number/style/affix.less create mode 100644 components/input/util.ts rename components/layout/style/{index.ts => index.tsx} (100%) rename components/list/style/{index.ts => index.tsx} (100%) create mode 100644 components/locale-provider/bn_BD.ts create mode 100644 components/locale-provider/ka_GE.ts create mode 100644 components/locale-provider/km_HK.ts create mode 100644 components/locale-provider/ml_IN.ts create mode 100644 components/locale-provider/ur_PK.ts create mode 100644 components/locale/bn_BD.tsx create mode 100644 components/locale/ka_GE.tsx create mode 100644 components/locale/km_KH.tsx create mode 100644 components/locale/ml_IN.tsx create mode 100644 components/locale/ur_PK.tsx rename components/mentions/style/{index.ts => index.tsx} (100%) rename components/page-header/style/{index.ts => index.tsx} (100%) create mode 100644 components/popconfirm/demo/promise.vue delete mode 100644 components/popover/style/customize.less rename components/radio/style/{index.ts => index.tsx} (100%) rename components/rate/style/{index.ts => index.tsx} (100%) rename components/result/style/{index.ts => index.tsx} (100%) rename components/row/style/{index.ts => index.tsx} (100%) create mode 100644 components/select/demo/field-names.vue create mode 100644 components/skeleton/demo/element.vue rename components/skeleton/style/{index.ts => index.tsx} (100%) rename components/space/style/{index.ts => index.tsx} (100%) rename components/spin/style/{index.ts => index.tsx} (100%) create mode 100644 components/style/compact.less create mode 100644 components/style/default.less create mode 100644 components/style/themes/variable.less delete mode 100644 components/style/v2-compatible-reset.less delete mode 100644 components/style/v2-compatible-reset.tsx create mode 100644 components/style/variable.less rename components/switch/style/{index.ts => index.tsx} (100%) create mode 100644 components/switch/style/rtl.less create mode 100644 components/table/demo/filter-in-tree.vue create mode 100644 components/table/demo/order-column.vue create mode 100644 components/table/hooks/useFilter/FilterSearch.tsx delete mode 100644 components/table/style/resize.less rename components/tag/style/{index.ts => index.tsx} (100%) create mode 100644 components/time-picker/locale/bn_BD.tsx create mode 100644 components/time-picker/locale/ka_GE.tsx create mode 100644 components/time-picker/locale/km_KH.tsx create mode 100644 components/time-picker/locale/ml_IN.tsx create mode 100644 components/time-picker/locale/ur_PK.tsx rename components/tooltip/style/{index.ts => index.tsx} (100%) rename components/transfer/style/{index.ts => index.tsx} (100%) rename components/typography/style/{index.ts => index.tsx} (100%) create mode 100644 components/vc-picker/locale/bn_BD.ts create mode 100644 components/vc-picker/locale/es_MX.ts create mode 100644 components/vc-picker/locale/ka_GE.ts create mode 100644 components/vc-picker/locale/ur_PK.ts create mode 100644 components/vc-picker/utils/warnUtil.ts create mode 100644 components/vc-table/constant.ts create mode 100644 components/vc-table/context/ExpandedRowContext.tsx create mode 100644 components/vc-table/context/HoverContext.tsx create mode 100644 components/vc-table/context/StickyContext.tsx create mode 100644 components/vc-util/Dom/dynamicCSS.ts create mode 100644 scripts/css-variable-sync.js create mode 100644 scripts/generate-version.js create mode 100644 site/src/vueDocs/customize-theme-variable.en-US.md create mode 100644 site/src/vueDocs/customize-theme-variable.zh-CN.md delete mode 100644 webpack.config.js diff --git a/.antd-tools.config.js b/.antd-tools.config.js new file mode 100644 index 000000000..7a5bec367 --- /dev/null +++ b/.antd-tools.config.js @@ -0,0 +1,195 @@ +const fs = require('fs'); +const path = require('path'); +const defaultVars = require('./scripts/default-vars'); +const darkVars = require('./scripts/dark-vars'); +const compactVars = require('./scripts/compact-vars'); + +function generateThemeFileContent(theme) { + return `const { ${theme}ThemeSingle } = require('./theme');\nconst defaultTheme = require('./default-theme');\n +module.exports = { + ...defaultTheme, + ...${theme}ThemeSingle +}`; +} + +// We need compile additional content for antd user +function finalizeCompile() { + if (fs.existsSync(path.join(__dirname, './lib'))) { + // Build a entry less file to dist/antd.less + const componentsPath = path.join(process.cwd(), 'components'); + let componentsLessContent = ''; + // Build components in one file: lib/style/components.less + fs.readdir(componentsPath, (err, files) => { + files.forEach(file => { + if (fs.existsSync(path.join(componentsPath, file, 'style', 'index.less'))) { + componentsLessContent += `@import "../${path.posix.join( + file, + 'style', + 'index-pure.less', + )}";\n`; + } + }); + fs.writeFileSync( + path.join(process.cwd(), 'lib', 'style', 'components.less'), + componentsLessContent, + ); + }); + } +} + +function buildThemeFile(theme, vars) { + // Build less entry file: dist/antd.${theme}.less + if (theme !== 'default') { + fs.writeFileSync( + path.join(process.cwd(), 'dist', `antd.${theme}.less`), + `@import "../lib/style/${theme}.less";\n@import "../lib/style/components.less";`, + ); + // eslint-disable-next-line no-console + console.log(`Built a entry less file to dist/antd.${theme}.less`); + } else { + fs.writeFileSync( + path.join(process.cwd(), 'dist', `default-theme.js`), + `module.exports = ${JSON.stringify(vars, null, 2)};\n`, + ); + return; + } + + // Build ${theme}.js: dist/${theme}-theme.js, for less-loader + + fs.writeFileSync( + path.join(process.cwd(), 'dist', `theme.js`), + `const ${theme}ThemeSingle = ${JSON.stringify(vars, null, 2)};\n`, + { + flag: 'a', + }, + ); + + fs.writeFileSync( + path.join(process.cwd(), 'dist', `${theme}-theme.js`), + generateThemeFileContent(theme), + ); + + // eslint-disable-next-line no-console + console.log(`Built a ${theme} theme js file to dist/${theme}-theme.js`); +} + +function finalizeDist() { + if (fs.existsSync(path.join(__dirname, './dist'))) { + // Build less entry file: dist/antd.less + fs.writeFileSync( + path.join(process.cwd(), 'dist', 'antd.less'), + '@import "../lib/style/default.less";\n@import "../lib/style/components.less";', + ); + // eslint-disable-next-line no-console + fs.writeFileSync( + path.join(process.cwd(), 'dist', 'theme.js'), + `const defaultTheme = require('./default-theme.js');\n`, + ); + // eslint-disable-next-line no-console + console.log('Built a entry less file to dist/antd.less'); + buildThemeFile('default', defaultVars); + buildThemeFile('dark', darkVars); + buildThemeFile('compact', compactVars); + buildThemeFile('variable', {}); + fs.writeFileSync( + path.join(process.cwd(), 'dist', `theme.js`), + ` +function getThemeVariables(options = {}) { + let themeVar = { + 'hack': \`true;@import "\${require.resolve('antd/lib/style/color/colorPalette.less')}";\`, + ...defaultTheme + }; + if(options.dark) { + themeVar = { + ...themeVar, + ...darkThemeSingle + } + } + if(options.compact){ + themeVar = { + ...themeVar, + ...compactThemeSingle + } + } + return themeVar; +} + +module.exports = { + darkThemeSingle, + compactThemeSingle, + getThemeVariables +}`, + { + flag: 'a', + }, + ); + } +} + +function isComponentStyleEntry(file) { + return file.path.match(/style(\/|\\)index\.tsx/); +} + +function needTransformStyle(content) { + return content.includes('../../style/index.less') || content.includes('./index.less'); +} + +module.exports = { + compile: { + includeLessFile: [/(\/|\\)components(\/|\\)style(\/|\\)default.less$/], + transformTSFile(file) { + if (isComponentStyleEntry(file)) { + let content = file.contents.toString(); + + if (needTransformStyle(content)) { + const cloneFile = file.clone(); + + // Origin + content = content.replace('../../style/index.less', '../../style/default.less'); + cloneFile.contents = Buffer.from(content); + + return cloneFile; + } + } + }, + transformFile(file) { + if (isComponentStyleEntry(file)) { + const indexLessFilePath = file.path.replace('index.tsx', 'index.less'); + + if (fs.existsSync(indexLessFilePath)) { + // We put origin `index.less` file to `index-pure.less` + const pureFile = file.clone(); + pureFile.contents = Buffer.from(fs.readFileSync(indexLessFilePath, 'utf8')); + pureFile.path = pureFile.path.replace('index.tsx', 'index-pure.less'); + + // Rewrite `index.less` file with `root-entry-name` + const indexLessFile = file.clone(); + indexLessFile.contents = Buffer.from( + [ + // Inject variable + '@root-entry-name: default;', + // Point to origin file + "@import './index-pure.less';", + ].join('\n\n'), + ); + indexLessFile.path = indexLessFile.path.replace('index.tsx', 'index.less'); + + return [indexLessFile, pureFile]; + } + } + + return []; + }, + lessConfig: { + modifyVars: { + 'root-entry-name': 'default', + }, + }, + finalize: finalizeCompile, + }, + dist: { + finalize: finalizeDist, + }, + generateThemeFileContent, + bail: true, +}; diff --git a/.eslintignore b/.eslintignore index 5484d7a9c..1b06d2da6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -7,3 +7,4 @@ es/ lib/ _site/ dist/ +components/version/version.tsx diff --git a/.gitignore b/.gitignore index 528ba0b75..c57a39388 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,6 @@ vetur/ report.html site/src/router/demoRoutes.js + +components/version/version.tsx +~component-api.json diff --git a/antd-tools/apiCollection.js b/antd-tools/apiCollection.js new file mode 100644 index 000000000..99843601c --- /dev/null +++ b/antd-tools/apiCollection.js @@ -0,0 +1,68 @@ +// Read all the api from current documents + +const glob = require('glob'); +const fs = require('fs'); + +const COMPONENT_NAME = /components\/([^/]*)/; +const PROP_NAME = /^\s*\|\s*([^\s|]*)/; + +const components = {}; + +function mappingPropLine(component, line) { + const propMatch = line.match(PROP_NAME); + if (!propMatch) return; + + const propName = propMatch[1]; + if (!/^[a-z]/.test(propName)) return; + + components[component] = Array.from(new Set([...(components[component] || []), propName])); +} + +function apiReport(entities) { + const apis = {}; + Object.keys(entities).forEach(component => { + const apiList = entities[component]; + apiList.forEach(api => { + if (typeof apis[api] === 'function') { + apis[api] = []; + } + apis[api] = [...(apis[api] || []), component]; + }); + }); + + return apis; +} + +function printReport(apis) { + const apiList = Object.keys(apis).map(api => ({ + name: api, + componentList: apis[api], + })); + apiList.sort((a, b) => b.componentList.length - a.componentList.length); + // eslint-disable-next-line no-console + console.log('| name | components | comments |'); + // eslint-disable-next-line no-console + console.log('| ---- | ---------- | -------- |'); + apiList.forEach(({ name, componentList }) => { + // eslint-disable-next-line no-console + console.log('|', name, '|', componentList.join(', '), '| |'); + }); +} + +module.exports = () => { + glob('components/*/*.md', (error, files) => { + files.forEach(filePath => { + // Read md file to parse content + const content = fs.readFileSync(filePath, 'utf8'); + const component = filePath.match(COMPONENT_NAME)[1]; + + // Parse lines to get API + const lines = content.split(/[\r\n]+/); + lines.forEach(line => { + mappingPropLine(component, line); + }); + }); + + printReport(apiReport(components)); + }); +}; diff --git a/antd-tools/cli/run.js b/antd-tools/cli/run.js index b60b54bb0..e1466aa6c 100644 --- a/antd-tools/cli/run.js +++ b/antd-tools/cli/run.js @@ -4,7 +4,6 @@ 'use strict'; require('colorful').colorful(); -require('colorful').isatty = true; const gulp = require('gulp'); const program = require('commander'); diff --git a/antd-tools/getNpm.js b/antd-tools/getNpm.js new file mode 100644 index 000000000..52eee5011 --- /dev/null +++ b/antd-tools/getNpm.js @@ -0,0 +1,17 @@ +'use strict'; + +const runCmd = require('./runCmd'); + +module.exports = function (done) { + if (process.env.NPM_CLI) { + done(process.env.NPM_CLI); + return; + } + runCmd('which', ['tnpm'], code => { + let npm = 'npm'; + if (!code) { + npm = 'tnpm'; + } + done(npm); + }); +}; diff --git a/antd-tools/gulpfile.js b/antd-tools/gulpfile.js index 6a3243cec..9090cfab8 100644 --- a/antd-tools/gulpfile.js +++ b/antd-tools/gulpfile.js @@ -1,5 +1,5 @@ /* eslint-disable no-console */ -const { getProjectPath } = require('./utils/projectHelper'); +const { getProjectPath, getConfig } = require('./utils/projectHelper'); const runCmd = require('./runCmd'); const getBabelCommonConfig = require('./getBabelCommonConfig'); const merge2 = require('merge2'); @@ -26,6 +26,7 @@ const stripCode = require('gulp-strip-code'); const compareVersions = require('compare-versions'); const getTSCommonConfig = require('./getTSCommonConfig'); const replaceLib = require('./replaceLib'); +const sortApiTable = require('./sortApiTable'); const packageJson = require(getProjectPath('package.json')); const tsDefaultReporter = ts.reporter.defaultReporter(); @@ -49,11 +50,17 @@ function dist(done) { } const info = stats.toJson(); + const { dist: { finalize } = {}, bail } = getConfig(); if (stats.hasErrors()) { - console.error(info.errors); + (info.errors || []).forEach(error => { + console.error(error); + }); + // https://github.com/ant-design/ant-design/pull/31662 + if (bail) { + process.exit(1); + } } - if (stats.hasWarnings()) { console.warn(info.warnings); } @@ -68,6 +75,11 @@ function dist(done) { version: false, }); console.log(buildInfo); + // Additional process of dist finalize + if (finalize) { + console.log('[Dist] Finalization...'); + finalize(); + } done(0); }); } @@ -103,7 +115,7 @@ function babelify(js, modules) { if (modules === false) { babelConfig.plugins.push(replaceLib); } - let stream = js.pipe(babel(babelConfig)).pipe( + const stream = js.pipe(babel(babelConfig)).pipe( through2.obj(function z(file, encoding, next) { this.push(file.clone()); if (file.path.match(/\/style\/index\.(js|jsx|ts|tsx)$/)) { @@ -128,33 +140,40 @@ function babelify(js, modules) { next(); }), ); - if (modules === false) { - stream = stream.pipe( - stripCode({ - start_comment: '@remove-on-es-build-begin', - end_comment: '@remove-on-es-build-end', - }), - ); - } return stream.pipe(gulp.dest(modules === false ? esDir : libDir)); } function compile(modules) { + const { compile: { transformTSFile, transformFile, includeLessFile = [] } = {} } = getConfig(); rimraf.sync(modules !== false ? libDir : esDir); + + // =============================== LESS =============================== const less = gulp .src(['components/**/*.less']) .pipe( through2.obj(function (file, encoding, next) { - this.push(file.clone()); + // Replace content + const cloneFile = file.clone(); + const content = file.contents.toString().replace(/^\uFEFF/, ''); + + cloneFile.contents = Buffer.from(content); + + // Clone for css here since `this.push` will modify file.path + const cloneCssFile = cloneFile.clone(); + + this.push(cloneFile); + + // Transform less file if ( - file.path.match(/\/style\/index\.less$/) || - file.path.match(/\/style\/v2-compatible-reset\.less$/) + file.path.match(/(\/|\\)style(\/|\\)index\.less$/) || + file.path.match(/(\/|\\)style(\/|\\)v2-compatible-reset\.less$/) || + includeLessFile.some(regex => file.path.match(regex)) ) { - transformLess(file.path) + transformLess(cloneCssFile.contents.toString(), cloneCssFile.path) .then(css => { - file.contents = Buffer.from(css); - file.path = file.path.replace(/\.less$/, '.css'); - this.push(file); + cloneCssFile.contents = Buffer.from(css); + cloneCssFile.path = cloneCssFile.path.replace(/\.less$/, '.css'); + this.push(cloneCssFile); next(); }) .catch(e => { @@ -170,6 +189,25 @@ function compile(modules) { .src(['components/**/*.@(png|svg)']) .pipe(gulp.dest(modules === false ? esDir : libDir)); let error = 0; + + // =============================== FILE =============================== + let transformFileStream; + + if (transformFile) { + transformFileStream = gulp + .src(['components/**/*.tsx']) + .pipe( + through2.obj(function (file, encoding, next) { + let nextFile = transformFile(file) || file; + nextFile = Array.isArray(nextFile) ? nextFile : [nextFile]; + nextFile.forEach(f => this.push(f)); + next(); + }), + ) + .pipe(gulp.dest(modules === false ? esDir : libDir)); + } + + // ================================ TS ================================ const source = [ 'components/**/*.js', 'components/**/*.jsx', @@ -179,7 +217,29 @@ function compile(modules) { '!components/*/__tests__/*', ]; - const tsResult = gulp.src(source).pipe( + // Strip content if needed + let sourceStream = gulp.src(source); + if (modules === false) { + sourceStream = sourceStream.pipe( + stripCode({ + start_comment: '@remove-on-es-build-begin', + end_comment: '@remove-on-es-build-end', + }), + ); + } + + if (transformTSFile) { + sourceStream = sourceStream.pipe( + through2.obj(function (file, encoding, next) { + let nextFile = transformTSFile(file) || file; + nextFile = Array.isArray(nextFile) ? nextFile : [nextFile]; + nextFile.forEach(f => this.push(f)); + next(); + }), + ); + } + + const tsResult = sourceStream.pipe( ts(tsConfig, { error(e) { tsDefaultReporter.error(e); @@ -199,7 +259,7 @@ function compile(modules) { tsResult.on('end', check); const tsFilesStream = babelify(tsResult.js, modules); const tsd = tsResult.dts.pipe(gulp.dest(modules === false ? esDir : libDir)); - return merge2([less, tsFilesStream, tsd, assets]); + return merge2([less, tsFilesStream, tsd, assets, transformFileStream].filter(s => s)); } function tag() { @@ -420,7 +480,11 @@ gulp.task( const npmArgs = getNpmArgs(); if (npmArgs) { for (let arg = npmArgs.shift(); arg; arg = npmArgs.shift()) { - if (/^pu(b(l(i(sh?)?)?)?)?$/.test(arg) && npmArgs.indexOf('--with-antd-tools') < 0) { + if ( + /^pu(b(l(i(sh?)?)?)?)?$/.test(arg) && + npmArgs.indexOf('--with-antd-tools') < 0 && + !process.env.npm_config_with_antd_tools + ) { reportError(); done(1); return; @@ -430,3 +494,11 @@ gulp.task( done(); }), ); + +gulp.task( + 'sort-api-table', + gulp.series(done => { + sortApiTable(); + done(); + }), +); diff --git a/antd-tools/replaceLib.js b/antd-tools/replaceLib.js index 08d84b4ea..e9da6e86c 100644 --- a/antd-tools/replaceLib.js +++ b/antd-tools/replaceLib.js @@ -12,6 +12,19 @@ function replacePath(path) { path.node.source.value = esModule; } } + + // @ant-design/icons-vue/xxx => @ant-design/icons-vue/es/icons/xxx + const antdIconMatcher = /@ant-design\/icons-vue\/([^/]*)$/; + if (path.node.source && antdIconMatcher.test(path.node.source.value)) { + const esModule = path.node.source.value.replace( + antdIconMatcher, + (_, iconName) => `@ant-design/icons-vue/es/icons/${iconName}`, + ); + const esPath = dirname(getProjectPath('node_modules', esModule)); + if (fs.existsSync(esPath)) { + path.node.source.value = esModule; + } + } } function replaceLib() { diff --git a/antd-tools/runCmd.js b/antd-tools/runCmd.js index f5a822a97..b25ca5711 100644 --- a/antd-tools/runCmd.js +++ b/antd-tools/runCmd.js @@ -1,9 +1,17 @@ 'use strict'; +const isWindows = require('is-windows'); const getRunCmdEnv = require('./utils/getRunCmdEnv'); function runCmd(cmd, _args, fn) { const args = _args || []; + + if (isWindows()) { + args.unshift(cmd); + args.unshift('/c'); + cmd = process.env.ComSpec; + } + const runner = require('child_process').spawn(cmd, args, { // keep color stdio: 'inherit', diff --git a/antd-tools/sortApiTable.js b/antd-tools/sortApiTable.js new file mode 100644 index 000000000..56a2bd21b --- /dev/null +++ b/antd-tools/sortApiTable.js @@ -0,0 +1,165 @@ +const program = require('commander'); +const majo = require('majo'); +const fs = require('fs'); +const path = require('path'); +const chalk = require('chalk'); + +const unified = require('unified'); +const parse = require('remark-parse'); +const stringify = require('remark-stringify'); + +const yamlConfig = require('remark-yaml-config'); +const frontmatter = require('remark-frontmatter'); + +let fileAPIs = {}; +const remarkWithYaml = unified() + .use(parse) + .use(stringify, { + paddedTable: false, + listItemIndent: 1, + stringLength: () => 3, + }) + .use(frontmatter) + .use(yamlConfig); + +const stream = majo.majo(); + +function getCellValue(node) { + return node.children[0].children[0].value; +} + +// from small to large +const sizeBreakPoints = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl']; + +const whiteMethodList = ['afterChange', 'beforeChange']; + +const groups = { + isDynamic: val => /^on[A-Z]/.test(val) || whiteMethodList.indexOf(val) > -1, + isSize: val => sizeBreakPoints.indexOf(val) > -1, +}; + +function asciiSort(prev, next) { + if (prev > next) { + return 1; + } + + if (prev < next) { + return -1; + } + + return 0; +} + +// follow the alphabet order +function alphabetSort(nodes) { + // use toLowerCase to keep `case insensitive` + return nodes.sort((...comparison) => + asciiSort(...comparison.map(val => getCellValue(val).toLowerCase())), + ); +} + +function sizeSort(nodes) { + return nodes.sort((...comparison) => + asciiSort(...comparison.map(val => sizeBreakPoints.indexOf(getCellValue(val).toLowerCase()))), + ); +} + +function sort(ast, filename) { + const nameMatch = filename.match(/^components\/([^/]*)\//); + const componentName = nameMatch[1]; + fileAPIs[componentName] = fileAPIs[componentName] || { + static: new Set(), + size: new Set(), + dynamic: new Set(), + }; + + ast.children.forEach(child => { + const staticProps = []; + // prefix with `on` + const dynamicProps = []; + // one of ['xs', 'sm', 'md', 'lg', 'xl'] + const sizeProps = []; + + // find table markdown type + if (child.type === 'table') { + // slice will create new array, so sort can affect the original array. + // slice(1) cut down the thead + child.children.slice(1).forEach(node => { + const value = getCellValue(node); + if (groups.isDynamic(value)) { + dynamicProps.push(node); + fileAPIs[componentName].dynamic.add(value); + } else if (groups.isSize(value)) { + sizeProps.push(node); + fileAPIs[componentName].size.add(value); + } else { + staticProps.push(node); + fileAPIs[componentName].static.add(value); + } + }); + + // eslint-disable-next-line + child.children = [ + child.children[0], + ...alphabetSort(staticProps), + ...sizeSort(sizeProps), + ...alphabetSort(dynamicProps), + ]; + } + }); + + return ast; +} + +function sortAPI(md, filename) { + return remarkWithYaml.stringify(sort(remarkWithYaml.parse(md), filename)); +} + +function sortMiddleware(ctx) { + Object.keys(ctx.files).forEach(filename => { + const content = ctx.fileContents(filename); + ctx.writeContents(filename, sortAPI(content, filename)); + }); +} + +module.exports = () => { + fileAPIs = {}; + + program + .version('0.1.0') + .option( + '-f, --file [file]', + 'Specify which file to be transformed', + // default value + 'components/**/index.+(zh-CN|en-US).md', + ) + .option('-o, --output [output]', 'Specify component api output path', '~component-api.json') + .parse(process.argv); + // Get the markdown file all need to be transformed + + /* eslint-disable no-console */ + stream + .source(program.file) + .use(sortMiddleware) + .dest('.') + .then(() => { + if (program.output) { + const data = {}; + Object.keys(fileAPIs).forEach(componentName => { + data[componentName] = { + static: [...fileAPIs[componentName].static], + size: [...fileAPIs[componentName].size], + dynamic: [...fileAPIs[componentName].dynamic], + }; + }); + + const reportPath = path.resolve(program.output); + fs.writeFileSync(reportPath, JSON.stringify(data, null, 2), 'utf8'); + console.log(chalk.cyan(`API list file: ${reportPath}`)); + } + }) + .then(() => { + console.log(chalk.green(`sort ant-design-vue api successfully!`)); + }); + /* eslint-enable no-console */ +}; diff --git a/antd-tools/transformLess.js b/antd-tools/transformLess.js index 370ffc17b..0e949b243 100644 --- a/antd-tools/transformLess.js +++ b/antd-tools/transformLess.js @@ -1,16 +1,14 @@ const less = require('less'); -const { readFileSync } = require('fs'); const path = require('path'); const postcss = require('postcss'); -const NpmImportPlugin = require('less-plugin-npm-import'); const autoprefixer = require('autoprefixer'); +const NpmImportPlugin = require('less-plugin-npm-import'); +const { getConfig } = require('./utils/projectHelper'); -function transformLess(lessFile, config = {}) { +function transformLess(lessContent, lessFilePath, config = {}) { const { cwd = process.cwd() } = config; - const resolvedLessFile = path.resolve(cwd, lessFile); - - let data = readFileSync(resolvedLessFile, 'utf-8'); - data = data.replace(/^\uFEFF/, ''); + const { compile: { lessConfig } = {} } = getConfig(); + const resolvedLessFile = path.resolve(cwd, lessFilePath); // Do less compile const lessOpts = { @@ -18,13 +16,12 @@ function transformLess(lessFile, config = {}) { filename: resolvedLessFile, plugins: [new NpmImportPlugin({ prefix: '~' })], javascriptEnabled: true, + ...lessConfig, }; return less - .render(data, lessOpts) + .render(lessContent, lessOpts) .then(result => postcss([autoprefixer]).process(result.css, { from: undefined })) - .then(r => { - return r.css; - }); + .then(r => r.css); } module.exports = transformLess; diff --git a/antd-tools/utils/CleanUpStatsPlugin.js b/antd-tools/utils/CleanUpStatsPlugin.js index 5029bba39..300168c4f 100644 --- a/antd-tools/utils/CleanUpStatsPlugin.js +++ b/antd-tools/utils/CleanUpStatsPlugin.js @@ -24,13 +24,13 @@ class CleanUpStatsPlugin { apply(compiler) { compiler.hooks.done.tap('CleanUpStatsPlugin', stats => { - const { children } = stats.compilation; + const { children, warnings } = stats.compilation; if (Array.isArray(children)) { stats.compilation.children = children.filter(child => this.shouldPickStatChild(child)); } - // if (Array.isArray(warnings)) { - // stats.compilation.warnings = warnings.filter(message => this.shouldPickWarning(message)); - // } + if (Array.isArray(warnings)) { + stats.compilation.warnings = warnings.filter(message => this.shouldPickWarning(message)); + } }); } } diff --git a/antd-tools/utils/get-npm-args.js b/antd-tools/utils/get-npm-args.js index 9de9013c1..2e11613cc 100644 --- a/antd-tools/utils/get-npm-args.js +++ b/antd-tools/utils/get-npm-args.js @@ -2,6 +2,11 @@ // NOTE: the following code was partially adopted from https://github.com/iarna/in-publish module.exports = function getNpmArgs() { + // https://github.com/iarna/in-publish/pull/14 + if (process.env.npm_command) { + return [process.env.npm_command]; + } + let npmArgv = null; try { diff --git a/antd-tools/utils/getRunCmdEnv.js b/antd-tools/utils/getRunCmdEnv.js index c7b474bb3..12e326050 100644 --- a/antd-tools/utils/getRunCmdEnv.js +++ b/antd-tools/utils/getRunCmdEnv.js @@ -1,6 +1,7 @@ 'use strict'; const path = require('path'); +const isWindows = require('is-windows'); module.exports = function getRunCmdEnv() { const env = {}; @@ -14,7 +15,9 @@ module.exports = function getRunCmdEnv() { .filter(v => v.slice(0, 1).pop().toLowerCase() === 'path') .forEach(v => { const key = v.slice(0, 1).pop(); - env[key] = env[key] ? `${nodeModulesBinDir}:${env[key]}` : nodeModulesBinDir; + env[key] = env[key] + ? `${nodeModulesBinDir}${isWindows() ? ';' : ':'}${env[key]}` + : nodeModulesBinDir; }); return env; }; diff --git a/antd-tools/utils/projectHelper.js b/antd-tools/utils/projectHelper.js index 79cdb57cc..9ade6c777 100644 --- a/antd-tools/utils/projectHelper.js +++ b/antd-tools/utils/projectHelper.js @@ -13,6 +13,7 @@ function resolve(moduleName) { // We need hack the require to ensure use package module first // For example, `typescript` is required by `gulp-typescript` but provided by `antd` +// we do not need for ant-design-vue let injected = false; function injectRequire() { if (injected) return; @@ -45,9 +46,35 @@ function getConfig() { return {}; } +/** + * 是否存在可用的browserslist config + * https://github.com/browserslist/browserslist#queries + * @returns + */ +function isThereHaveBrowserslistConfig() { + try { + const packageJson = require(getProjectPath('package.json')); + if (packageJson.browserslist) { + return true; + } + } catch (e) { + // + } + if (fs.existsSync(getProjectPath('.browserslistrc'))) { + return true; + } + if (fs.existsSync(getProjectPath('browserslist'))) { + return true; + } + // parent项目的配置支持,需要再补充 + // ROWSERSLIST ROWSERSLIST_ENV 变量的形式,需要再补充。 + return false; +} + module.exports = { getProjectPath, resolve, injectRequire, getConfig, + isThereHaveBrowserslistConfig, }; diff --git a/antd-tools/utils/styleUtil.js b/antd-tools/utils/styleUtil.js new file mode 100644 index 000000000..7b05ee315 --- /dev/null +++ b/antd-tools/utils/styleUtil.js @@ -0,0 +1,11 @@ +// We convert less import in es/lib to css file path +function cssInjection(content) { + return content + .replace(/\/style\/?'/g, "/style/css'") + .replace(/\/style\/?"/g, '/style/css"') + .replace(/\.less/g, '.css'); +} + +module.exports = { + cssInjection, +}; diff --git a/components/modal/ActionButton.tsx b/components/_util/ActionButton.tsx similarity index 92% rename from components/modal/ActionButton.tsx rename to components/_util/ActionButton.tsx index cc3766368..fe1eb83de 100644 --- a/components/modal/ActionButton.tsx +++ b/components/_util/ActionButton.tsx @@ -4,6 +4,7 @@ import Button from '../button'; import type { ButtonProps } from '../button'; import type { LegacyButtonType } from '../button/buttonTypes'; import { convertLegacyProps } from '../button/buttonTypes'; +import useDestroyed from './hooks/useDestroyed'; const actionButtonProps = { type: { @@ -32,6 +33,7 @@ export default defineComponent({ const buttonRef = ref(); const loading = ref(false); let timeoutId: any; + const isDestroyed = useDestroyed(); onMounted(() => { if (props.autofocus) { timeoutId = setTimeout(() => buttonRef.value.$el?.focus()); @@ -49,7 +51,9 @@ export default defineComponent({ loading.value = true; returnValueOfOnOk!.then( (...args: any[]) => { - loading.value = false; + if (!isDestroyed.value) { + loading.value = false; + } close(...args); clickedRef.value = false; }, @@ -58,7 +62,9 @@ export default defineComponent({ // eslint-disable-next-line no-console console.error(e); // See: https://github.com/ant-design/ant-design/issues/6183 - loading.value = false; + if (!isDestroyed.value) { + loading.value = false; + } clickedRef.value = false; }, ); diff --git a/components/_util/EventInterface.ts b/components/_util/EventInterface.ts index b9d0bd019..7d6f193c9 100644 --- a/components/_util/EventInterface.ts +++ b/components/_util/EventInterface.ts @@ -6,5 +6,10 @@ export type ChangeEvent = Event & { value?: string | undefined; }; }; +export type CheckboxChangeEvent = Event & { + target: { + checked?: boolean; + }; +}; export type EventHandler = (...args: any[]) => void; diff --git a/components/_util/__tests__/unreachableException.test.js b/components/_util/__tests__/unreachableException.test.js new file mode 100644 index 000000000..4019e4fed --- /dev/null +++ b/components/_util/__tests__/unreachableException.test.js @@ -0,0 +1,8 @@ +import UnreachableException from '../unreachableException'; + +describe('UnreachableException', () => { + it('error thrown matches snapshot', () => { + const exception = new UnreachableException('some value'); + expect(exception.error.message).toMatchInlineSnapshot(`"unreachable case: \\"some value\\""`); + }); +}); diff --git a/components/upload/UploadList/listAnimation.ts b/components/_util/collapseMotion.tsx similarity index 81% rename from components/upload/UploadList/listAnimation.ts rename to components/_util/collapseMotion.tsx index bcc4f6d00..6af29a463 100644 --- a/components/upload/UploadList/listAnimation.ts +++ b/components/_util/collapseMotion.tsx @@ -1,11 +1,11 @@ -import { addClass, removeClass } from '../../vc-util/Dom/class'; import { nextTick } from 'vue'; -import type { CSSMotionProps } from '../../_util/transition'; +import { addClass, removeClass } from '../vc-util/Dom/class'; +import type { CSSMotionProps } from './transition'; -const listAnimation = (name = 'ant-motion-collapse'): CSSMotionProps => { +const collapseMotion = (name = 'ant-motion-collapse', appear = true): CSSMotionProps => { return { name, - appear: true, + appear, css: true, onBeforeEnter: (node: HTMLDivElement) => { node.style.height = '0px'; @@ -47,4 +47,4 @@ const listAnimation = (name = 'ant-motion-collapse'): CSSMotionProps => { }, }; }; -export default listAnimation; +export default collapseMotion; diff --git a/components/_util/hooks/useConfigInject.ts b/components/_util/hooks/useConfigInject.ts index 56e9d4cfb..079ac95b3 100644 --- a/components/_util/hooks/useConfigInject.ts +++ b/components/_util/hooks/useConfigInject.ts @@ -19,6 +19,7 @@ export default ( pageHeader: ComputedRef<{ ghost: boolean }>; form?: ComputedRef<{ requiredMark?: RequiredMark; + colon?: boolean; }>; autoInsertSpaceInButton: ComputedRef; renderEmpty?: ComputedRef<(componentName?: string) => VueNode>; diff --git a/components/_util/hooks/useDestroyed.ts b/components/_util/hooks/useDestroyed.ts new file mode 100644 index 000000000..d5cd6b0f4 --- /dev/null +++ b/components/_util/hooks/useDestroyed.ts @@ -0,0 +1,12 @@ +import { onBeforeUnmount, ref } from 'vue'; + +const useDestroyed = () => { + const mounted = ref(true); + onBeforeUnmount(() => { + mounted.value = false; + }); + + return mounted; +}; + +export default useDestroyed; diff --git a/components/_util/hooks/usePrefixCls.ts b/components/_util/hooks/usePrefixCls.ts deleted file mode 100644 index 96c62d4b6..000000000 --- a/components/_util/hooks/usePrefixCls.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { ComputedRef } from 'vue'; -import { computed, inject } from 'vue'; -import { defaultConfigProvider } from '../../config-provider'; - -export default (name: string, props: Record): ComputedRef => { - const configProvider = inject('configProvider', defaultConfigProvider); - const prefixCls = computed(() => configProvider.getPrefixCls(name, props.prefixCls)); - return prefixCls; -}; diff --git a/components/_util/openAnimation.js b/components/_util/openAnimation.js deleted file mode 100644 index d01df6d74..000000000 --- a/components/_util/openAnimation.js +++ /dev/null @@ -1,67 +0,0 @@ -import cssAnimation from './css-animation'; -import { nextTick } from 'vue'; -import { requestAnimationTimeout, cancelAnimationTimeout } from './requestAnimationTimeout'; - -function animate(node, show, done) { - let height; - let requestAnimationFrameId; - let appearRequestAnimationFrameId; - return cssAnimation(node, 'ant-motion-collapse-legacy', { - start() { - if (appearRequestAnimationFrameId) { - cancelAnimationTimeout(appearRequestAnimationFrameId); - } - if (!show) { - node.style.height = `${node.offsetHeight}px`; - node.style.opacity = '1'; - } else { - height = node.offsetHeight; - // not get offsetHeight when appear - // set it into raf get correct offsetHeight - if (height === 0) { - appearRequestAnimationFrameId = requestAnimationTimeout(() => { - height = node.offsetHeight; - node.style.height = '0px'; - node.style.opacity = '0'; - }); - } else { - node.style.height = '0px'; - node.style.opacity = '0'; - } - } - }, - active() { - if (requestAnimationFrameId) { - cancelAnimationTimeout(requestAnimationFrameId); - } - requestAnimationFrameId = requestAnimationTimeout(() => { - node.style.height = `${show ? height : 0}px`; - node.style.opacity = show ? '1' : '0'; - }); - }, - end() { - if (appearRequestAnimationFrameId) { - cancelAnimationTimeout(appearRequestAnimationFrameId); - } - if (requestAnimationFrameId) { - cancelAnimationTimeout(requestAnimationFrameId); - } - node.style.height = ''; - node.style.opacity = ''; - done && done(); - }, - }); -} - -const animation = { - onEnter(node, done) { - nextTick(() => { - animate(node, true, done); - }); - }, - onLeave(node, done) { - return animate(node, false, done); - }, -}; - -export default animation; diff --git a/components/_util/styleChecker.ts b/components/_util/styleChecker.ts index ae845c67e..59244441a 100644 --- a/components/_util/styleChecker.ts +++ b/components/_util/styleChecker.ts @@ -2,8 +2,8 @@ import canUseDom from './canUseDom'; export const canUseDocElement = () => canUseDom() && window.document.documentElement; -export const isStyleSupport = (styleName: string | Array): boolean => { - if (canUseDocElement()) { +const isStyleNameSupport = (styleName: string | string[]): boolean => { + if (canUseDom() && window.document.documentElement) { const styleNameList = Array.isArray(styleName) ? styleName : [styleName]; const { documentElement } = window.document; @@ -12,6 +12,25 @@ export const isStyleSupport = (styleName: string | Array): boolean => { return false; }; +const isStyleValueSupport = (styleName: string, value: any) => { + if (!isStyleNameSupport(styleName)) { + return false; + } + + const ele = document.createElement('div'); + const origin = ele.style[styleName]; + ele.style[styleName] = value; + return ele.style[styleName] !== origin; +}; + +export function isStyleSupport(styleName: string | string[], styleValue?: any) { + if (!Array.isArray(styleName) && styleValue !== undefined) { + return isStyleValueSupport(styleName, styleValue); + } + + return isStyleNameSupport(styleName); +} + let flexGapSupported: boolean | undefined; export const detectFlexGapSupported = () => { if (!canUseDocElement()) { diff --git a/components/_util/transition.tsx b/components/_util/transition.tsx index cf8177af2..0d9ab7c9f 100644 --- a/components/_util/transition.tsx +++ b/components/_util/transition.tsx @@ -129,13 +129,17 @@ export interface CSSMotionProps extends Partial> { css?: boolean; } -const collapseMotion = (style: Ref, className: Ref): CSSMotionProps => { +const collapseMotion = ( + name = 'ant-motion-collapse', + style: Ref, + className: Ref, +): CSSMotionProps => { return { - name: 'ant-motion-collapse', + name, appear: true, css: true, onBeforeEnter: node => { - className.value = 'ant-motion-collapse'; + className.value = name; style.value = getCollapsedHeight(node); }, onEnter: node => { @@ -148,7 +152,7 @@ const collapseMotion = (style: Ref, className: Ref): CSSM style.value = {}; }, onBeforeLeave: node => { - className.value = 'ant-motion-collapse'; + className.value = name; style.value = getCurrentHeight(node); }, onLeave: node => { diff --git a/components/_util/unreachableException.ts b/components/_util/unreachableException.ts new file mode 100644 index 000000000..9218b14dc --- /dev/null +++ b/components/_util/unreachableException.ts @@ -0,0 +1,7 @@ +export default class UnreachableException { + error: Error; + + constructor(value: any) { + this.error = new Error(`unreachable case: ${JSON.stringify(value)}`); + } +} diff --git a/components/_util/wave.tsx b/components/_util/wave.tsx index 4fd70e193..a733fcbc5 100644 --- a/components/_util/wave.tsx +++ b/components/_util/wave.tsx @@ -24,6 +24,7 @@ export default defineComponent({ name: 'Wave', props: { insertExtraNode: Boolean, + disabled: Boolean, }, setup(props, { slots, expose }) { const instance = getCurrentInstance(); @@ -60,10 +61,11 @@ export default defineComponent({ return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node'; }; const onClick = (node: HTMLElement, waveColor: string) => { - if (!node || isHidden(node) || node.className.indexOf('-leave') >= 0) { + const { insertExtraNode, disabled } = props; + if (disabled || !node || isHidden(node) || node.className.indexOf('-leave') >= 0) { return; } - const { insertExtraNode } = props; + extraNode = document.createElement('div'); extraNode.className = 'ant-click-animating-node'; const attributeName = getAttributeName(); diff --git a/components/affix/index.en-US.md b/components/affix/index.en-US.md index 75d27a721..910c536c5 100644 --- a/components/affix/index.en-US.md +++ b/components/affix/index.en-US.md @@ -23,9 +23,9 @@ Please note that Affix should not cover other content on the page, especially wh ### events -| Events Name | Description | Arguments | Version | -| ----------- | ---------------------------------------- | ----------------- | ------- | -| change | Callback for when Affix state is changed | Function(affixed) | +| Events Name | Description | Arguments | Version | +| ----------- | ---------------------------------------- | --------------------------- | ------- | +| change | Callback for when Affix state is changed | (affixed?: boolean) => void | | **Note:** Children of `Affix` must not have the property `position: absolute`, but you can set `position: absolute` on `Affix` itself: @@ -35,8 +35,12 @@ Please note that Affix should not cover other content on the page, especially wh ## FAQ -### Affix bind container with `target`, sometime move out of container. +### When binding container with `target` in Affix, elements sometimes move out of the container. -We don't listen window scroll for performance consideration. +We only listen to container scroll events for performance consideration. You can add custom listeners if you still want to, like react demo Related issues:[#3938](https://github.com/ant-design/ant-design/issues/3938) [#5642](https://github.com/ant-design/ant-design/issues/5642) [#16120](https://github.com/ant-design/ant-design/issues/16120) + +### When Affix is ​​used in a horizontal scroll container, the position of the element `left` is incorrect. + +Affix is ​​generally only applicable to areas with one-way scrolling, and only supports usage in vertical scrolling containers. If you want to use it in a horizontal container, you can consider implementing with the native `position: sticky` property. diff --git a/components/affix/index.tsx b/components/affix/index.tsx index e403f96e6..aa451f51f 100644 --- a/components/affix/index.tsx +++ b/components/affix/index.tsx @@ -179,10 +179,7 @@ const Affix = defineComponent({ watch( () => props.target, val => { - let newTarget = null; - if (val) { - newTarget = val() || null; - } + const newTarget = val?.() || null; if (state.prevTarget !== newTarget) { removeObserveTarget(currentInstance); if (newTarget) { diff --git a/components/affix/index.zh-CN.md b/components/affix/index.zh-CN.md index 7128d19a0..daddfa00b 100644 --- a/components/affix/index.zh-CN.md +++ b/components/affix/index.zh-CN.md @@ -19,14 +19,14 @@ cover: https://gw.alipayobjects.com/zos/alicdn/tX6-md4H6/Affix.svg | 成员 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | | offsetBottom | 距离窗口底部达到指定偏移量后触发 | number | | | -| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | | | +| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | 0 | | | target | 设置 `Affix` 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | () => HTMLElement | () => window | | ### 事件 -| 事件名称 | 说明 | 回调参数 | 版本 | -| -------- | ---------------------------- | ----------------- | ---- | --- | -| change | 固定状态改变时触发的回调函数 | Function(affixed) | 无 | | +| 事件名称 | 说明 | 回调参数 | 版本 | | +| -------- | ---------------------------- | --------------------------- | ---- | --- | +| change | 固定状态改变时触发的回调函数 | (affixed?: boolean) => void | - | | **注意:**`Affix` 内的元素不要使用绝对定位,如需要绝对定位的效果,可以直接设置 `Affix` 为绝对定位: @@ -38,6 +38,12 @@ cover: https://gw.alipayobjects.com/zos/alicdn/tX6-md4H6/Affix.svg ### Affix 使用 `target` 绑定容器时,元素会跑到容器外。 -从性能角度考虑,我们只监听容器滚动事件。 +从性能角度考虑,我们只监听容器滚动事件。如果希望任意滚动,你可以在窗体添加滚动监听, 参考 react 版本示例 相关 issue:[#3938](https://github.com/ant-design/ant-design/issues/3938) [#5642](https://github.com/ant-design/ant-design/issues/5642) [#16120](https://github.com/ant-design/ant-design/issues/16120) + +### Affix 在水平滚动容器中使用时, 元素 `left` 位置不正确。 + +Affix 一般只适用于单向滚动的区域,只支持在垂直滚动容器中使用。如果希望在水平容器中使用,你可以考虑使用 原生 `position: sticky` 实现。 + +相关 issue: [#29108](https://github.com/ant-design/ant-design/issues/29108) diff --git a/components/affix/utils.ts b/components/affix/utils.ts index 20543df10..4ce8c11bb 100644 --- a/components/affix/utils.ts +++ b/components/affix/utils.ts @@ -3,19 +3,14 @@ import type { ComponentPublicInstance } from 'vue'; import supportsPassive from '../_util/supportsPassive'; export type BindElement = HTMLElement | Window | null | undefined; -export type Rect = ClientRect | DOMRect; -export function getTargetRect(target: BindElement): ClientRect { +export function getTargetRect(target: BindElement): DOMRect { return target !== window ? (target as HTMLElement).getBoundingClientRect() - : ({ top: 0, bottom: window.innerHeight } as ClientRect); + : ({ top: 0, bottom: window.innerHeight } as DOMRect); } -export function getFixedTop( - placeholderReact: Rect, - targetRect: Rect, - offsetTop: number | undefined, -) { +export function getFixedTop(placeholderReact: DOMRect, targetRect: DOMRect, offsetTop: number) { if (offsetTop !== undefined && targetRect.top > placeholderReact.top - offsetTop) { return `${offsetTop + targetRect.top}px`; } @@ -23,9 +18,9 @@ export function getFixedTop( } export function getFixedBottom( - placeholderReact: Rect, - targetRect: Rect, - offsetBottom: number | undefined, + placeholderReact: DOMRect, + targetRect: DOMRect, + offsetBottom: number, ) { if (offsetBottom !== undefined && targetRect.bottom < placeholderReact.bottom + offsetBottom) { const targetBottomOffset = window.innerHeight - targetRect.bottom; diff --git a/components/alert/__tests__/__snapshots__/demo.test.js.snap b/components/alert/__tests__/__snapshots__/demo.test.js.snap index 7c10e97ce..87c3dee8c 100644 --- a/components/alert/__tests__/__snapshots__/demo.test.js.snap +++ b/components/alert/__tests__/__snapshots__/demo.test.js.snap @@ -1,68 +1,56 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders ./components/alert/demo/banner.vue correctly 1`] = ` -
+
-
+
-
+
-
+ `; exports[`renders ./components/alert/demo/basic.vue correctly 1`] = ` -
+ `; exports[`renders ./components/alert/demo/closable.vue correctly 1`] = ` -
+ -
+