From 0718d8c4d19e1431846b2ca61e2ea4379be25c35 Mon Sep 17 00:00:00 2001 From: haishan <710328466@qq.com> Date: Thu, 30 May 2024 10:40:46 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9ts=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/request/src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/request/src/index.tsx b/packages/request/src/index.tsx index 627369f..9070965 100644 --- a/packages/request/src/index.tsx +++ b/packages/request/src/index.tsx @@ -69,7 +69,7 @@ export const reqConfig = (config: ReqConfigProps) => { // 一个二元组,第一个元素是 request 拦截器,第二个元素是错误处理 [ (response: { status: number; data: any; }) => { - const { code, data = {} } = response?.data || {} + const { code } = response?.data || {} if (code !== 200) { // 报错捕捉 From 54a680c0ffb4e36925d2bd04d3c100cb8b39b6a2 Mon Sep 17 00:00:00 2001 From: haishan <710328466@qq.com> Date: Thu, 30 May 2024 11:41:50 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat(tsconfig):=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tsconfig.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 774856c..8d76e68 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,7 @@ "sourceMap": true, "strictNullChecks": true, "module": "esnext", - "moduleResolution": "Bundler", + "moduleResolution": "NodeNext", "experimentalDecorators": true, "jsxFactory": "React.createElement", "jsxFragmentFactory": "React.Fragment", @@ -26,7 +26,6 @@ "target": "es6", "lib": ["dom", "es2017"], "stripInternal": true, - "resolvePackageJsonExports": true, "resolveJsonModule": true, "types": [ // "@zhst/meta" 全局使用的工具包,不建议写到 npm 包中去 From 46e6d0b4d02025f3ac7fc9791921c7b94daa40a9 Mon Sep 17 00:00:00 2001 From: haishan <710328466@qq.com> Date: Fri, 31 May 2024 16:22:09 +0800 Subject: [PATCH 3/3] =?UTF-8?q?feat(zhst/biz,zhst/meta):=20=E7=A9=BF?= =?UTF-8?q?=E6=A2=AD=E6=A1=86=E5=AE=8C=E6=88=90,=E6=96=B0=E5=A2=9Emeta?= =?UTF-8?q?=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../biz/es/BigImageModal/BigImageModal.js | 254 +- .../biz/src/boxSelectTree/boxSelectTree.tsx | 3 +- .../components/boxPanel/index.tsx | 34 +- packages/biz/src/boxSelectTree/demo/basic.tsx | 2 +- packages/biz/src/boxSelectTree/index.md | 2 +- packages/biz/src/tree/boxTree.tsx | 3 +- packages/biz/src/tree/index.md | 7 +- .../biz/src/treeTransfer/TreeTransfer.tsx | 211 +- packages/biz/src/treeTransfer/demo/basic.tsx | 8 + .../biz/src/treeTransfer/demo/noSearch.tsx | 57 + .../biz/src/treeTransfer/demo/withFilter.tsx | 66 + .../biz/src/treeTransfer/demo/withMap.tsx | 103 + packages/biz/src/treeTransfer/index.less | 66 +- packages/biz/src/treeTransfer/index.md | 33 +- packages/func/es/file/index.d.ts | 2 +- packages/func/es/string/index.js | 16 + packages/func/lib/file/index.d.ts | 2 +- packages/func/lib/string/index.js | 11 + packages/func/lib/time/index.js | 8 +- .../es/useCustomCompareEffect/index.d.ts | 2 +- packages/hooks/es/useJump/interface.d.ts | 2 +- packages/hooks/es/useRafLoop.d.ts | 2 +- packages/hooks/es/useSocket/index.d.ts | 1 + .../lib/useCustomCompareEffect/index.d.ts | 2 +- packages/hooks/lib/useJump/interface.d.ts | 2 +- packages/hooks/lib/useRafLoop.d.ts | 2 +- packages/hooks/lib/useSocket/index.d.ts | 1 + packages/icon/es/Iconfont.js | 8 +- packages/map/package.json | 7 +- packages/map/src/demo/basic.tsx | 30 +- packages/map/src/tools/index.less | 1 + packages/meta/es/index.js | 7 +- packages/meta/src/_util/ActionButton.tsx | 5 +- packages/meta/src/_util/PurePanel.tsx | 2 +- .../src/_util/__tests__/getScroll.test.ts | 10 +- .../meta/src/_util/__tests__/hooks.test.tsx | 100 +- .../src/_util/__tests__/reactNode.test.tsx | 7 +- .../__tests__/responsiveObserve.test.tsx | 1 + .../src/_util/__tests__/transButton.test.tsx | 3 +- .../meta/src/_util/__tests__/type.test.tsx | 105 + .../src/_util/__tests__/useSyncState.test.tsx | 3 +- .../meta/src/_util/__tests__/util.test.tsx | 3 +- .../meta/src/_util/__tests__/warning.test.tsx | 3 +- .../meta/src/_util/__tests__/wave.test.tsx | 6 +- packages/meta/src/_util/aria-data-attrs.ts | 5 + packages/meta/src/_util/colors.ts | 2 +- packages/meta/src/_util/getAllowClear.tsx | 20 + packages/meta/src/_util/hooks/useClosable.tsx | 193 +- .../_util/hooks/useProxyImperativeHandle.ts | 3 +- packages/meta/src/_util/index.zh-CN.md | 49 + packages/meta/src/_util/motion.ts | 2 +- packages/meta/src/_util/reactNode.ts | 21 +- packages/meta/src/_util/responsiveObserver.ts | 10 +- packages/meta/src/_util/scrollTo.ts | 1 + packages/meta/src/_util/statusUtils.ts | 3 +- packages/meta/src/_util/transButton.tsx | 9 +- packages/meta/src/_util/transKeys.ts | 8 +- packages/meta/src/_util/type.ts | 28 + packages/meta/src/_util/warning.ts | 5 + packages/meta/src/_util/wave/WaveEffect.tsx | 23 +- packages/meta/src/_util/wave/index.ts | 12 +- packages/meta/src/_util/wave/style.ts | 5 +- packages/meta/src/_util/wave/useWave.ts | 16 +- packages/meta/src/date-picker/style/index.ts | 2 +- .../__snapshots__/demo-extend.test.ts.snap | 7150 +++++ .../__snapshots__/demo.test.tsx.snap | 1213 + .../dropdown-button.test.tsx.snap | 80 + .../__snapshots__/index.test.tsx.snap | 91 + .../dropdown/__tests__/demo-extend.test.ts | 5 + .../meta/src/dropdown/__tests__/demo.test.tsx | 37 + .../__tests__/dropdown-button.test.tsx | 173 + .../meta/src/dropdown/__tests__/image.test.ts | 5 + .../src/dropdown/__tests__/index.test.tsx | 327 + .../meta/src/dropdown/demo/arrow-center.md | 7 + .../meta/src/dropdown/demo/arrow-center.tsx | 59 + packages/meta/src/dropdown/demo/arrow.md | 7 + packages/meta/src/dropdown/demo/arrow.tsx | 59 + packages/meta/src/dropdown/demo/basic.md | 7 + packages/meta/src/dropdown/demo/basic.tsx | 52 + .../meta/src/dropdown/demo/context-menu.md | 7 + .../meta/src/dropdown/demo/context-menu.tsx | 42 + .../meta/src/dropdown/demo/custom-dropdown.md | 7 + .../src/dropdown/demo/custom-dropdown.tsx | 73 + .../meta/src/dropdown/demo/dropdown-button.md | 7 + .../src/dropdown/demo/dropdown-button.tsx | 83 + packages/meta/src/dropdown/demo/event.md | 7 + packages/meta/src/dropdown/demo/event.tsx | 36 + packages/meta/src/dropdown/demo/icon-debug.md | 7 + .../meta/src/dropdown/demo/icon-debug.tsx | 13 + packages/meta/src/dropdown/demo/item.md | 7 + packages/meta/src/dropdown/demo/item.tsx | 44 + packages/meta/src/dropdown/demo/loading.md | 7 + packages/meta/src/dropdown/demo/loading.tsx | 60 + packages/meta/src/dropdown/demo/menu-full.md | 11 + packages/meta/src/dropdown/demo/menu-full.tsx | 68 + .../meta/src/dropdown/demo/overlay-open.md | 7 + .../meta/src/dropdown/demo/overlay-open.tsx | 55 + packages/meta/src/dropdown/demo/placement.md | 7 + packages/meta/src/dropdown/demo/placement.tsx | 59 + .../meta/src/dropdown/demo/render-panel.md | 7 + .../meta/src/dropdown/demo/render-panel.tsx | 44 + packages/meta/src/dropdown/demo/selectable.md | 7 + .../meta/src/dropdown/demo/selectable.tsx | 38 + .../meta/src/dropdown/demo/sub-menu-debug.md | 7 + .../meta/src/dropdown/demo/sub-menu-debug.tsx | 66 + packages/meta/src/dropdown/demo/sub-menu.md | 7 + packages/meta/src/dropdown/demo/sub-menu.tsx | 64 + packages/meta/src/dropdown/demo/trigger.md | 7 + packages/meta/src/dropdown/demo/trigger.tsx | 35 + .../meta/src/dropdown/dropdown-button.tsx | 142 + packages/meta/src/dropdown/dropdown.tsx | 344 + packages/meta/src/dropdown/index.ts | 12 + packages/meta/src/dropdown/index.zh-CN.md | 85 + packages/meta/src/dropdown/style/index.ts | 370 + packages/meta/src/dropdown/style/status.ts | 25 + packages/meta/src/form/ErrorList.tsx | 8 +- packages/meta/src/form/Form.tsx | 57 +- .../meta/src/form/FormItem/StatusProvider.tsx | 3 +- packages/meta/src/form/FormItem/index.tsx | 17 +- packages/meta/src/form/FormItemLabel.tsx | 5 +- .../__snapshots__/demo-extend.test.ts.snap | 24982 +++++++++------- .../__snapshots__/demo.test.tsx.snap | 2065 +- .../__snapshots__/index.test.tsx.snap | 42 +- .../meta/src/form/__tests__/demo.test.tsx | 1 + .../meta/src/form/__tests__/index.test.tsx | 174 +- .../src/form/__tests__/list-noStyle.test.tsx | 4 +- .../meta/src/form/__tests__/list.test.tsx | 1 + packages/meta/src/form/__tests__/ref.test.tsx | 1 + .../meta/src/form/__tests__/type.test.tsx | 1 + packages/meta/src/form/context.tsx | 7 +- .../meta/src/form/demo/advanced-search.tsx | 2 +- packages/meta/src/form/demo/basic.tsx | 17 +- packages/meta/src/form/demo/col-24-debug.tsx | 4 +- .../meta/src/form/demo/component-token.tsx | 5 +- .../src/form/demo/custom-feedback-icons.tsx | 2 +- .../src/form/demo/customized-form-controls.md | 10 +- .../form/demo/customized-form-controls.tsx | 6 +- packages/meta/src/form/demo/form-context.tsx | 22 +- .../{dependencies.md => form-dependencies.md} | 0 ...dependencies.tsx => form-dependencies.tsx} | 0 packages/meta/src/form/demo/form-in-modal.md | 6 - packages/meta/src/form/demo/form-in-modal.tsx | 126 +- .../meta/src/form/demo/form-item-path.tsx | 8 +- .../src/form/demo/getValueProps-normalize.md | 7 + .../src/form/demo/getValueProps-normalize.tsx | 44 + packages/meta/src/form/demo/register.tsx | 27 +- .../src/form/demo/time-related-controls.tsx | 2 +- packages/meta/src/form/demo/validate-only.tsx | 27 +- .../meta/src/form/demo/validate-other.tsx | 2 +- .../src/form/demo/validate-scroll-to-field.md | 7 + .../form/demo/validate-scroll-to-field.tsx | 55 + .../meta/src/form/demo/validate-static.tsx | 11 + packages/meta/src/form/demo/variant.md | 7 + packages/meta/src/form/demo/variant.tsx | 101 + .../src/form/demo/without-form-create.tsx | 7 +- packages/meta/src/form/hooks/useChildren.ts | 1 + packages/meta/src/form/hooks/useForm.ts | 22 +- .../meta/src/form/hooks/useFormInstance.ts | 1 + packages/meta/src/form/hooks/useFrameState.ts | 2 +- packages/meta/src/form/hooks/useItemRef.ts | 3 +- packages/meta/src/form/hooks/useVariants.ts | 30 + packages/meta/src/form/index.ts | 17 +- packages/meta/src/form/index.zh-CN.md | 26 +- packages/meta/src/form/style/fallbackCmp.ts | 6 +- packages/meta/src/form/style/index.ts | 14 +- .../meta/src/form/validateMessagesContext.tsx | 2 +- packages/meta/src/index.tsx | 22 +- .../__snapshots__/demo-extend.test.ts.snap | 1791 +- .../__snapshots__/demo.test.tsx.snap | 1783 +- .../__snapshots__/index.test.tsx.snap | 8 +- .../src/input-number/__tests__/addon.test.tsx | 5 +- .../__tests__/demo-extend.test.ts | 4 +- .../src/input-number/__tests__/demo.test.tsx | 5 +- .../src/input-number/__tests__/index.test.tsx | 13 +- .../input-number/__tests__/prefix.test.tsx | 1 + packages/meta/src/input-number/demo/addon.tsx | 2 +- packages/meta/src/input-number/demo/basic.tsx | 3 +- .../meta/src/input-number/demo/borderless.md | 7 - .../meta/src/input-number/demo/borderless.tsx | 6 - .../src/input-number/demo/change-on-wheel.md | 7 + .../src/input-number/demo/change-on-wheel.tsx | 13 + .../src/input-number/demo/debug-token.tsx | 14 + packages/meta/src/input-number/demo/digit.tsx | 3 +- .../src/input-number/demo/filled-debug.md | 7 + .../src/input-number/demo/filled-debug.tsx | 46 + .../meta/src/input-number/demo/formatter.tsx | 11 +- packages/meta/src/input-number/demo/size.tsx | 3 +- .../meta/src/input-number/demo/variant.md | 7 + .../meta/src/input-number/demo/variant.tsx | 12 + packages/meta/src/input-number/index.tsx | 43 +- packages/meta/src/input-number/index.zh-CN.md | 31 +- packages/meta/src/input-number/style/index.ts | 173 +- packages/meta/src/input-number/style/token.ts | 80 + packages/meta/src/input/Input.tsx | 81 +- packages/meta/src/input/OTP/OTPInput.tsx | 75 + packages/meta/src/input/OTP/index.tsx | 260 + packages/meta/src/input/Password.tsx | 40 +- packages/meta/src/input/Search.tsx | 4 +- packages/meta/src/input/TextArea.tsx | 77 +- .../src/input/__tests__/Password.test.tsx | 1 + .../meta/src/input/__tests__/Search.test.tsx | 3 +- .../__snapshots__/Password.test.tsx.snap | 10 +- .../__snapshots__/Search.test.tsx.snap | 48 +- .../__snapshots__/demo-extend.test.ts.snap | 6067 ++-- .../__snapshots__/demo.test.tsx.snap | 971 +- .../__snapshots__/index.test.tsx.snap | 36 +- .../__tests__/__snapshots__/otp.test.tsx.snap | 44 + .../__snapshots__/textarea.test.tsx.snap | 26 +- .../meta/src/input/__tests__/demo.test.tsx | 1 + .../meta/src/input/__tests__/focus.test.tsx | 3 +- .../meta/src/input/__tests__/index.test.tsx | 13 +- .../meta/src/input/__tests__/otp.test.tsx | 170 + .../src/input/__tests__/textarea.test.tsx | 8 + .../meta/src/input/__tests__/type.test.tsx | 1 + .../meta/src/input/demo/_semantic_input.tsx | 44 + .../src/input/demo/_semantic_textarea.tsx | 32 + packages/meta/src/input/demo/basic.tsx | 2 +- .../meta/src/input/demo/borderless-debug.tsx | 14 +- packages/meta/src/input/demo/borderless.md | 7 - packages/meta/src/input/demo/borderless.tsx | 6 - .../meta/src/input/demo/compact-style.tsx | 2 +- .../meta/src/input/demo/component-token.tsx | 14 +- packages/meta/src/input/demo/debug-addon.tsx | 2 +- packages/meta/src/input/demo/filled-debug.md | 7 + packages/meta/src/input/demo/filled-debug.tsx | 72 + packages/meta/src/input/demo/focus.tsx | 1 - packages/meta/src/input/demo/group.tsx | 2 +- packages/meta/src/input/demo/otp.md | 7 + packages/meta/src/input/demo/otp.tsx | 33 + packages/meta/src/input/demo/presuffix.tsx | 2 +- packages/meta/src/input/demo/search-input.tsx | 4 +- packages/meta/src/input/demo/variant.md | 7 + packages/meta/src/input/demo/variant.tsx | 12 + .../input/hooks/useRemovePasswordTimeout.ts | 1 + packages/meta/src/input/index.ts | 13 +- packages/meta/src/input/index.zh-CN.md | 78 +- packages/meta/src/input/style/index.ts | 375 +- packages/meta/src/input/style/otp.ts | 47 + packages/meta/src/input/style/token.ts | 155 + packages/meta/src/input/style/variants.ts | 341 + packages/meta/src/input/utils.ts | 11 +- packages/meta/src/layout/Sider.tsx | 221 + .../__snapshots__/demo-extend.test.ts.snap | 5181 ++++ .../__tests__/__snapshots__/demo.test.ts.snap | 2739 ++ .../__snapshots__/index.test.tsx.snap | 63 + .../src/layout/__tests__/demo-extend.test.ts | 3 + .../meta/src/layout/__tests__/demo.test.ts | 3 + .../__tests__/dynamic-breakpoint.test.tsx | 50 + .../meta/src/layout/__tests__/image.test.ts | 7 + .../meta/src/layout/__tests__/index.test.tsx | 348 + .../meta/src/layout/__tests__/token.test.tsx | 86 + .../src/layout/__tests__/warning.test.tsx | 32 + packages/meta/src/layout/context.ts | 15 + packages/meta/src/layout/demo/basic.md | 7 + packages/meta/src/layout/demo/basic.tsx | 86 + .../meta/src/layout/demo/component-token.md | 7 + .../meta/src/layout/demo/component-token.tsx | 87 + .../src/layout/demo/custom-trigger-debug.md | 3 + .../src/layout/demo/custom-trigger-debug.tsx | 114 + .../meta/src/layout/demo/custom-trigger.md | 7 + .../meta/src/layout/demo/custom-trigger.tsx | 75 + packages/meta/src/layout/demo/fixed-sider.md | 7 + packages/meta/src/layout/demo/fixed-sider.tsx | 76 + packages/meta/src/layout/demo/fixed.md | 7 + packages/meta/src/layout/demo/fixed.tsx | 61 + packages/meta/src/layout/demo/responsive.md | 11 + packages/meta/src/layout/demo/responsive.tsx | 57 + packages/meta/src/layout/demo/side.md | 15 + packages/meta/src/layout/demo/side.tsx | 80 + packages/meta/src/layout/demo/top-side-2.md | 7 + packages/meta/src/layout/demo/top-side-2.tsx | 83 + packages/meta/src/layout/demo/top-side.md | 7 + packages/meta/src/layout/demo/top-side.tsx | 78 + packages/meta/src/layout/demo/top.md | 13 + packages/meta/src/layout/demo/top.tsx | 52 + packages/meta/src/layout/hooks/useHasSider.ts | 22 + packages/meta/src/layout/index.ts | 26 + packages/meta/src/layout/index.zh-CN.md | 133 + packages/meta/src/layout/layout.tsx | 158 + packages/meta/src/layout/style/index.ts | 329 + packages/meta/src/layout/style/light.ts | 28 + packages/meta/src/menu/MenuContext.tsx | 23 + packages/meta/src/menu/MenuDivider.tsx | 29 + packages/meta/src/menu/MenuItem.tsx | 117 + packages/meta/src/menu/OverrideContext.tsx | 54 + packages/meta/src/menu/SubMenu.tsx | 91 + .../__snapshots__/demo-extend.test.ts.snap | 8412 ++++++ .../__snapshots__/demo.test.tsx.snap | 3116 ++ .../__snapshots__/index.test.tsx.snap | 482 + .../menu/__tests__/cached-context.test.tsx | 43 + .../src/menu/__tests__/demo-extend.test.ts | 3 + .../meta/src/menu/__tests__/demo.test.tsx | 36 + .../meta/src/menu/__tests__/image.test.ts | 5 + .../meta/src/menu/__tests__/index.test.tsx | 1173 + .../meta/src/menu/__tests__/type.test.tsx | 110 + .../meta/src/menu/demo/component-token.md | 7 + .../meta/src/menu/demo/component-token.tsx | 181 + .../meta/src/menu/demo/horizontal-dark.md | 7 + .../meta/src/menu/demo/horizontal-dark.tsx | 66 + packages/meta/src/menu/demo/horizontal.md | 7 + packages/meta/src/menu/demo/horizontal.tsx | 64 + .../meta/src/menu/demo/inline-collapsed.md | 11 + .../meta/src/menu/demo/inline-collapsed.tsx | 74 + packages/meta/src/menu/demo/inline.md | 7 + packages/meta/src/menu/demo/inline.tsx | 93 + packages/meta/src/menu/demo/menu-v4.md | 7 + packages/meta/src/menu/demo/menu-v4.tsx | 114 + packages/meta/src/menu/demo/sider-current.md | 7 + packages/meta/src/menu/demo/sider-current.tsx | 119 + packages/meta/src/menu/demo/style-debug.md | 7 + packages/meta/src/menu/demo/style-debug.tsx | 96 + packages/meta/src/menu/demo/submenu-theme.md | 7 + packages/meta/src/menu/demo/submenu-theme.tsx | 60 + packages/meta/src/menu/demo/switch-mode.md | 7 + packages/meta/src/menu/demo/switch-mode.tsx | 97 + packages/meta/src/menu/demo/theme.md | 7 + packages/meta/src/menu/demo/theme.tsx | 86 + packages/meta/src/menu/demo/vertical.md | 7 + packages/meta/src/menu/demo/vertical.tsx | 72 + packages/meta/src/menu/index.tsx | 71 + packages/meta/src/menu/index.zh-CN.md | 147 + packages/meta/src/menu/interface.ts | 37 + packages/meta/src/menu/menu.tsx | 208 + packages/meta/src/menu/style/horizontal.ts | 59 + packages/meta/src/menu/style/index.ts | 1067 + packages/meta/src/menu/style/rtl.ts | 35 + packages/meta/src/menu/style/theme.ts | 273 + packages/meta/src/menu/style/vertical.ts | 236 + packages/meta/src/tooltip/index.tsx | 3 +- packages/meta/src/tree/DirectoryTree.tsx | 213 + packages/meta/src/tree/Tree.tsx | 273 + .../__snapshots__/demo-extend.test.ts.snap | 4762 +++ .../__tests__/__snapshots__/demo.test.ts.snap | 4641 +++ .../__snapshots__/directory.test.tsx.snap | 2607 ++ .../__snapshots__/index.test.tsx.snap | 790 + .../src/tree/__tests__/demo-extend.test.ts | 3 + packages/meta/src/tree/__tests__/demo.test.ts | 3 + .../src/tree/__tests__/directory.test.tsx | 326 + .../src/tree/__tests__/dropIndicator.test.tsx | 61 + .../meta/src/tree/__tests__/image.test.ts | 5 + .../meta/src/tree/__tests__/index.test.tsx | 218 + .../meta/src/tree/__tests__/type.test.tsx | 100 + .../meta/src/tree/__tests__/util.test.tsx | 99 + .../meta/src/tree/demo/basic-controlled.md | 7 + .../meta/src/tree/demo/basic-controlled.tsx | 88 + packages/meta/src/tree/demo/basic.md | 7 + packages/meta/src/tree/demo/basic.tsx | 57 + packages/meta/src/tree/demo/big-data.md | 7 + packages/meta/src/tree/demo/big-data.tsx | 26 + packages/meta/src/tree/demo/block-node.tsx | 28 + .../meta/src/tree/demo/component-token.md | 7 + .../meta/src/tree/demo/component-token.tsx | 68 + .../meta/src/tree/demo/customized-icon.md | 7 + .../meta/src/tree/demo/customized-icon.tsx | 42 + packages/meta/src/tree/demo/directory.md | 7 + packages/meta/src/tree/demo/directory.tsx | 48 + packages/meta/src/tree/demo/drag-debug.md | 1 + packages/meta/src/tree/demo/drag-debug.tsx | 153 + packages/meta/src/tree/demo/draggable.md | 7 + packages/meta/src/tree/demo/draggable.tsx | 111 + packages/meta/src/tree/demo/dynamic.md | 7 + packages/meta/src/tree/demo/dynamic.tsx | 59 + packages/meta/src/tree/demo/line.md | 7 + packages/meta/src/tree/demo/line.tsx | 119 + packages/meta/src/tree/demo/multiple-line.md | 7 + packages/meta/src/tree/demo/multiple-line.tsx | 58 + packages/meta/src/tree/demo/search.md | 13 + packages/meta/src/tree/demo/search.tsx | 131 + packages/meta/src/tree/demo/switcher-icon.md | 7 + packages/meta/src/tree/demo/switcher-icon.tsx | 73 + packages/meta/src/tree/demo/virtual-scroll.md | 7 + .../meta/src/tree/demo/virtual-scroll.tsx | 36 + packages/meta/src/tree/index.ts | 38 + packages/meta/src/tree/index.zh-CN.md | 143 + packages/meta/src/tree/style/index.ts | 553 + packages/meta/src/tree/utils/dictUtil.ts | 110 + .../meta/src/tree/utils/dropIndicator.tsx | 33 + packages/meta/src/tree/utils/iconUtil.tsx | 82 + packages/request/es/index.js | 57 +- packages/request/lib/index.js | 57 +- packages/slave/lib/index.js | 4 +- tsconfig.json | 2 +- 382 files changed, 82702 insertions(+), 15183 deletions(-) create mode 100644 packages/biz/src/treeTransfer/demo/noSearch.tsx create mode 100644 packages/biz/src/treeTransfer/demo/withFilter.tsx create mode 100644 packages/biz/src/treeTransfer/demo/withMap.tsx create mode 100644 packages/meta/src/_util/__tests__/type.test.tsx create mode 100644 packages/meta/src/_util/aria-data-attrs.ts create mode 100644 packages/meta/src/_util/getAllowClear.tsx create mode 100644 packages/meta/src/_util/index.zh-CN.md create mode 100644 packages/meta/src/dropdown/__tests__/__snapshots__/demo-extend.test.ts.snap create mode 100644 packages/meta/src/dropdown/__tests__/__snapshots__/demo.test.tsx.snap create mode 100644 packages/meta/src/dropdown/__tests__/__snapshots__/dropdown-button.test.tsx.snap create mode 100644 packages/meta/src/dropdown/__tests__/__snapshots__/index.test.tsx.snap create mode 100644 packages/meta/src/dropdown/__tests__/demo-extend.test.ts create mode 100644 packages/meta/src/dropdown/__tests__/demo.test.tsx create mode 100644 packages/meta/src/dropdown/__tests__/dropdown-button.test.tsx create mode 100644 packages/meta/src/dropdown/__tests__/image.test.ts create mode 100644 packages/meta/src/dropdown/__tests__/index.test.tsx create mode 100644 packages/meta/src/dropdown/demo/arrow-center.md create mode 100644 packages/meta/src/dropdown/demo/arrow-center.tsx create mode 100644 packages/meta/src/dropdown/demo/arrow.md create mode 100644 packages/meta/src/dropdown/demo/arrow.tsx create mode 100644 packages/meta/src/dropdown/demo/basic.md create mode 100644 packages/meta/src/dropdown/demo/basic.tsx create mode 100644 packages/meta/src/dropdown/demo/context-menu.md create mode 100644 packages/meta/src/dropdown/demo/context-menu.tsx create mode 100644 packages/meta/src/dropdown/demo/custom-dropdown.md create mode 100644 packages/meta/src/dropdown/demo/custom-dropdown.tsx create mode 100644 packages/meta/src/dropdown/demo/dropdown-button.md create mode 100644 packages/meta/src/dropdown/demo/dropdown-button.tsx create mode 100644 packages/meta/src/dropdown/demo/event.md create mode 100644 packages/meta/src/dropdown/demo/event.tsx create mode 100644 packages/meta/src/dropdown/demo/icon-debug.md create mode 100644 packages/meta/src/dropdown/demo/icon-debug.tsx create mode 100644 packages/meta/src/dropdown/demo/item.md create mode 100644 packages/meta/src/dropdown/demo/item.tsx create mode 100644 packages/meta/src/dropdown/demo/loading.md create mode 100644 packages/meta/src/dropdown/demo/loading.tsx create mode 100644 packages/meta/src/dropdown/demo/menu-full.md create mode 100644 packages/meta/src/dropdown/demo/menu-full.tsx create mode 100644 packages/meta/src/dropdown/demo/overlay-open.md create mode 100644 packages/meta/src/dropdown/demo/overlay-open.tsx create mode 100644 packages/meta/src/dropdown/demo/placement.md create mode 100644 packages/meta/src/dropdown/demo/placement.tsx create mode 100644 packages/meta/src/dropdown/demo/render-panel.md create mode 100644 packages/meta/src/dropdown/demo/render-panel.tsx create mode 100644 packages/meta/src/dropdown/demo/selectable.md create mode 100644 packages/meta/src/dropdown/demo/selectable.tsx create mode 100644 packages/meta/src/dropdown/demo/sub-menu-debug.md create mode 100644 packages/meta/src/dropdown/demo/sub-menu-debug.tsx create mode 100644 packages/meta/src/dropdown/demo/sub-menu.md create mode 100644 packages/meta/src/dropdown/demo/sub-menu.tsx create mode 100644 packages/meta/src/dropdown/demo/trigger.md create mode 100644 packages/meta/src/dropdown/demo/trigger.tsx create mode 100644 packages/meta/src/dropdown/dropdown-button.tsx create mode 100644 packages/meta/src/dropdown/dropdown.tsx create mode 100644 packages/meta/src/dropdown/index.ts create mode 100644 packages/meta/src/dropdown/index.zh-CN.md create mode 100644 packages/meta/src/dropdown/style/index.ts create mode 100644 packages/meta/src/dropdown/style/status.ts rename packages/meta/src/form/demo/{dependencies.md => form-dependencies.md} (100%) rename packages/meta/src/form/demo/{dependencies.tsx => form-dependencies.tsx} (100%) create mode 100644 packages/meta/src/form/demo/getValueProps-normalize.md create mode 100644 packages/meta/src/form/demo/getValueProps-normalize.tsx create mode 100644 packages/meta/src/form/demo/validate-scroll-to-field.md create mode 100644 packages/meta/src/form/demo/validate-scroll-to-field.tsx create mode 100644 packages/meta/src/form/demo/variant.md create mode 100644 packages/meta/src/form/demo/variant.tsx create mode 100644 packages/meta/src/form/hooks/useVariants.ts delete mode 100644 packages/meta/src/input-number/demo/borderless.md delete mode 100644 packages/meta/src/input-number/demo/borderless.tsx create mode 100644 packages/meta/src/input-number/demo/change-on-wheel.md create mode 100644 packages/meta/src/input-number/demo/change-on-wheel.tsx create mode 100644 packages/meta/src/input-number/demo/filled-debug.md create mode 100644 packages/meta/src/input-number/demo/filled-debug.tsx create mode 100644 packages/meta/src/input-number/demo/variant.md create mode 100644 packages/meta/src/input-number/demo/variant.tsx create mode 100644 packages/meta/src/input-number/style/token.ts create mode 100644 packages/meta/src/input/OTP/OTPInput.tsx create mode 100644 packages/meta/src/input/OTP/index.tsx create mode 100644 packages/meta/src/input/__tests__/__snapshots__/otp.test.tsx.snap create mode 100644 packages/meta/src/input/__tests__/otp.test.tsx create mode 100644 packages/meta/src/input/demo/_semantic_input.tsx create mode 100644 packages/meta/src/input/demo/_semantic_textarea.tsx delete mode 100644 packages/meta/src/input/demo/borderless.md delete mode 100644 packages/meta/src/input/demo/borderless.tsx create mode 100644 packages/meta/src/input/demo/filled-debug.md create mode 100644 packages/meta/src/input/demo/filled-debug.tsx create mode 100644 packages/meta/src/input/demo/otp.md create mode 100644 packages/meta/src/input/demo/otp.tsx create mode 100644 packages/meta/src/input/demo/variant.md create mode 100644 packages/meta/src/input/demo/variant.tsx create mode 100644 packages/meta/src/input/style/otp.ts create mode 100644 packages/meta/src/input/style/token.ts create mode 100644 packages/meta/src/input/style/variants.ts create mode 100644 packages/meta/src/layout/Sider.tsx create mode 100644 packages/meta/src/layout/__tests__/__snapshots__/demo-extend.test.ts.snap create mode 100644 packages/meta/src/layout/__tests__/__snapshots__/demo.test.ts.snap create mode 100644 packages/meta/src/layout/__tests__/__snapshots__/index.test.tsx.snap create mode 100644 packages/meta/src/layout/__tests__/demo-extend.test.ts create mode 100644 packages/meta/src/layout/__tests__/demo.test.ts create mode 100644 packages/meta/src/layout/__tests__/dynamic-breakpoint.test.tsx create mode 100644 packages/meta/src/layout/__tests__/image.test.ts create mode 100644 packages/meta/src/layout/__tests__/index.test.tsx create mode 100644 packages/meta/src/layout/__tests__/token.test.tsx create mode 100644 packages/meta/src/layout/__tests__/warning.test.tsx create mode 100644 packages/meta/src/layout/context.ts create mode 100644 packages/meta/src/layout/demo/basic.md create mode 100644 packages/meta/src/layout/demo/basic.tsx create mode 100644 packages/meta/src/layout/demo/component-token.md create mode 100644 packages/meta/src/layout/demo/component-token.tsx create mode 100644 packages/meta/src/layout/demo/custom-trigger-debug.md create mode 100644 packages/meta/src/layout/demo/custom-trigger-debug.tsx create mode 100644 packages/meta/src/layout/demo/custom-trigger.md create mode 100644 packages/meta/src/layout/demo/custom-trigger.tsx create mode 100644 packages/meta/src/layout/demo/fixed-sider.md create mode 100644 packages/meta/src/layout/demo/fixed-sider.tsx create mode 100644 packages/meta/src/layout/demo/fixed.md create mode 100644 packages/meta/src/layout/demo/fixed.tsx create mode 100644 packages/meta/src/layout/demo/responsive.md create mode 100644 packages/meta/src/layout/demo/responsive.tsx create mode 100644 packages/meta/src/layout/demo/side.md create mode 100644 packages/meta/src/layout/demo/side.tsx create mode 100644 packages/meta/src/layout/demo/top-side-2.md create mode 100644 packages/meta/src/layout/demo/top-side-2.tsx create mode 100644 packages/meta/src/layout/demo/top-side.md create mode 100644 packages/meta/src/layout/demo/top-side.tsx create mode 100644 packages/meta/src/layout/demo/top.md create mode 100644 packages/meta/src/layout/demo/top.tsx create mode 100644 packages/meta/src/layout/hooks/useHasSider.ts create mode 100644 packages/meta/src/layout/index.ts create mode 100644 packages/meta/src/layout/index.zh-CN.md create mode 100644 packages/meta/src/layout/layout.tsx create mode 100644 packages/meta/src/layout/style/index.ts create mode 100644 packages/meta/src/layout/style/light.ts create mode 100644 packages/meta/src/menu/MenuContext.tsx create mode 100644 packages/meta/src/menu/MenuDivider.tsx create mode 100644 packages/meta/src/menu/MenuItem.tsx create mode 100644 packages/meta/src/menu/OverrideContext.tsx create mode 100644 packages/meta/src/menu/SubMenu.tsx create mode 100644 packages/meta/src/menu/__tests__/__snapshots__/demo-extend.test.ts.snap create mode 100644 packages/meta/src/menu/__tests__/__snapshots__/demo.test.tsx.snap create mode 100644 packages/meta/src/menu/__tests__/__snapshots__/index.test.tsx.snap create mode 100644 packages/meta/src/menu/__tests__/cached-context.test.tsx create mode 100644 packages/meta/src/menu/__tests__/demo-extend.test.ts create mode 100644 packages/meta/src/menu/__tests__/demo.test.tsx create mode 100644 packages/meta/src/menu/__tests__/image.test.ts create mode 100644 packages/meta/src/menu/__tests__/index.test.tsx create mode 100644 packages/meta/src/menu/__tests__/type.test.tsx create mode 100755 packages/meta/src/menu/demo/component-token.md create mode 100644 packages/meta/src/menu/demo/component-token.tsx create mode 100755 packages/meta/src/menu/demo/horizontal-dark.md create mode 100644 packages/meta/src/menu/demo/horizontal-dark.tsx create mode 100755 packages/meta/src/menu/demo/horizontal.md create mode 100644 packages/meta/src/menu/demo/horizontal.tsx create mode 100644 packages/meta/src/menu/demo/inline-collapsed.md create mode 100644 packages/meta/src/menu/demo/inline-collapsed.tsx create mode 100755 packages/meta/src/menu/demo/inline.md create mode 100644 packages/meta/src/menu/demo/inline.tsx create mode 100644 packages/meta/src/menu/demo/menu-v4.md create mode 100644 packages/meta/src/menu/demo/menu-v4.tsx create mode 100755 packages/meta/src/menu/demo/sider-current.md create mode 100644 packages/meta/src/menu/demo/sider-current.tsx create mode 100644 packages/meta/src/menu/demo/style-debug.md create mode 100644 packages/meta/src/menu/demo/style-debug.tsx create mode 100755 packages/meta/src/menu/demo/submenu-theme.md create mode 100644 packages/meta/src/menu/demo/submenu-theme.tsx create mode 100755 packages/meta/src/menu/demo/switch-mode.md create mode 100644 packages/meta/src/menu/demo/switch-mode.tsx create mode 100755 packages/meta/src/menu/demo/theme.md create mode 100644 packages/meta/src/menu/demo/theme.tsx create mode 100755 packages/meta/src/menu/demo/vertical.md create mode 100644 packages/meta/src/menu/demo/vertical.tsx create mode 100644 packages/meta/src/menu/index.tsx create mode 100644 packages/meta/src/menu/index.zh-CN.md create mode 100644 packages/meta/src/menu/interface.ts create mode 100644 packages/meta/src/menu/menu.tsx create mode 100644 packages/meta/src/menu/style/horizontal.ts create mode 100644 packages/meta/src/menu/style/index.ts create mode 100644 packages/meta/src/menu/style/rtl.ts create mode 100644 packages/meta/src/menu/style/theme.ts create mode 100644 packages/meta/src/menu/style/vertical.ts create mode 100644 packages/meta/src/tree/DirectoryTree.tsx create mode 100644 packages/meta/src/tree/Tree.tsx create mode 100644 packages/meta/src/tree/__tests__/__snapshots__/demo-extend.test.ts.snap create mode 100644 packages/meta/src/tree/__tests__/__snapshots__/demo.test.ts.snap create mode 100644 packages/meta/src/tree/__tests__/__snapshots__/directory.test.tsx.snap create mode 100644 packages/meta/src/tree/__tests__/__snapshots__/index.test.tsx.snap create mode 100644 packages/meta/src/tree/__tests__/demo-extend.test.ts create mode 100644 packages/meta/src/tree/__tests__/demo.test.ts create mode 100644 packages/meta/src/tree/__tests__/directory.test.tsx create mode 100644 packages/meta/src/tree/__tests__/dropIndicator.test.tsx create mode 100644 packages/meta/src/tree/__tests__/image.test.ts create mode 100644 packages/meta/src/tree/__tests__/index.test.tsx create mode 100644 packages/meta/src/tree/__tests__/type.test.tsx create mode 100644 packages/meta/src/tree/__tests__/util.test.tsx create mode 100644 packages/meta/src/tree/demo/basic-controlled.md create mode 100644 packages/meta/src/tree/demo/basic-controlled.tsx create mode 100644 packages/meta/src/tree/demo/basic.md create mode 100644 packages/meta/src/tree/demo/basic.tsx create mode 100644 packages/meta/src/tree/demo/big-data.md create mode 100644 packages/meta/src/tree/demo/big-data.tsx create mode 100644 packages/meta/src/tree/demo/block-node.tsx create mode 100644 packages/meta/src/tree/demo/component-token.md create mode 100644 packages/meta/src/tree/demo/component-token.tsx create mode 100644 packages/meta/src/tree/demo/customized-icon.md create mode 100644 packages/meta/src/tree/demo/customized-icon.tsx create mode 100644 packages/meta/src/tree/demo/directory.md create mode 100644 packages/meta/src/tree/demo/directory.tsx create mode 100644 packages/meta/src/tree/demo/drag-debug.md create mode 100644 packages/meta/src/tree/demo/drag-debug.tsx create mode 100644 packages/meta/src/tree/demo/draggable.md create mode 100644 packages/meta/src/tree/demo/draggable.tsx create mode 100644 packages/meta/src/tree/demo/dynamic.md create mode 100644 packages/meta/src/tree/demo/dynamic.tsx create mode 100644 packages/meta/src/tree/demo/line.md create mode 100644 packages/meta/src/tree/demo/line.tsx create mode 100644 packages/meta/src/tree/demo/multiple-line.md create mode 100644 packages/meta/src/tree/demo/multiple-line.tsx create mode 100644 packages/meta/src/tree/demo/search.md create mode 100644 packages/meta/src/tree/demo/search.tsx create mode 100644 packages/meta/src/tree/demo/switcher-icon.md create mode 100644 packages/meta/src/tree/demo/switcher-icon.tsx create mode 100644 packages/meta/src/tree/demo/virtual-scroll.md create mode 100644 packages/meta/src/tree/demo/virtual-scroll.tsx create mode 100644 packages/meta/src/tree/index.ts create mode 100644 packages/meta/src/tree/index.zh-CN.md create mode 100644 packages/meta/src/tree/style/index.ts create mode 100644 packages/meta/src/tree/utils/dictUtil.ts create mode 100644 packages/meta/src/tree/utils/dropIndicator.tsx create mode 100644 packages/meta/src/tree/utils/iconUtil.tsx diff --git a/packages/biz/es/BigImageModal/BigImageModal.js b/packages/biz/es/BigImageModal/BigImageModal.js index 1bdd0f8..6d99f22 100644 --- a/packages/biz/es/BigImageModal/BigImageModal.js +++ b/packages/biz/es/BigImageModal/BigImageModal.js @@ -4,7 +4,6 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } -function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } @@ -12,13 +11,16 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } // @ts-nocheck -import React, { forwardRef, useImperativeHandle, useRef, useState, useEffect } from 'react'; +import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react'; import { ConfigProvider, Descriptions, Modal, Tabs, CropperImage, AttachImage, VideoPlayer, BtnGroup, RelatedImage } from '@zhst/meta'; import classNames from 'classnames'; import { get, isEmpty, pick } from '@zhst/func'; import Navigation from "./components/navigation"; import CombineImage from "./components/CombineImage"; import "./index.less"; +import { jsx as _jsx } from "react/jsx-runtime"; +import { Fragment as _Fragment } from "react/jsx-runtime"; +import { jsxs as _jsxs } from "react/jsx-runtime"; var DescriptionsItem = Descriptions.Item; export var componentPrefix = 'zhst-image'; @@ -98,58 +100,62 @@ var BigImageModal = /*#__PURE__*/forwardRef(function (props, ref) { items: [{ label: '对比图模式', key: 'COMPATER', - children: /*#__PURE__*/React.createElement(CombineImage, _extends({ + children: /*#__PURE__*/_jsx(CombineImage, _objectSpread({ ref: combineImageRef, data: pick(dataSource, 'compaterImage', 'imgSummary', 'imageKey', 'score') }, compareImageProps)) }, { label: '场景图模式', key: 'NORMAL', - children: /*#__PURE__*/React.createElement("div", { + children: /*#__PURE__*/_jsx("div", { style: { display: 'flex', justifyContent: 'center', width: '100%' - } - }, /*#__PURE__*/React.createElement("div", { - style: { - width: '85%', - height: '500px' - } - }, /*#__PURE__*/React.createElement(CropperImage, _extends({ - type: "rect", - odList: get(dataSource, 'odRect', []) - }, cropperImageProps), !(cropperImageProps !== null && cropperImageProps !== void 0 && cropperImageProps.editAble) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(AttachImage, { - data: [{ - label: '测试', - url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' - }] - }), /*#__PURE__*/React.createElement("div", { - style: { - position: 'absolute', - right: '24px', - bottom: '24px', - fontSize: '18px', - color: 'red', - cursor: 'default' - } - }, "\u4EBA\u8138\u8D28\u91CF\u5206\uFF1A".concat(Number(cropperImageProps === null || cropperImageProps === void 0 ? void 0 : cropperImageProps.score).toFixed(2)))), (cropperImageProps === null || cropperImageProps === void 0 ? void 0 : cropperImageProps.showEditTools) && /*#__PURE__*/React.createElement(BtnGroup, _extends({ - circle: true, - style: { - position: 'absolute', - top: 0, - right: 0 }, - dataSource: cropBtnDataSource, - onClick: handleCropBtnClick, - selectKey: cropType - }, btnGroupProps))))) + children: /*#__PURE__*/_jsx("div", { + style: { + width: '85%', + height: '500px' + }, + children: /*#__PURE__*/_jsxs(CropperImage, _objectSpread(_objectSpread({ + type: "rect", + odList: get(dataSource, 'odRect', []) + }, cropperImageProps), {}, { + children: [!(cropperImageProps !== null && cropperImageProps !== void 0 && cropperImageProps.editAble) && /*#__PURE__*/_jsxs(_Fragment, { + children: [/*#__PURE__*/_jsx(AttachImage, { + data: [{ + label: '测试', + url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' + }] + }), /*#__PURE__*/_jsx("div", { + style: { + position: 'absolute', + right: '24px', + bottom: '24px', + fontSize: '18px', + color: 'red', + cursor: 'default' + }, + children: "\u4EBA\u8138\u8D28\u91CF\u5206\uFF1A".concat(Number(cropperImageProps === null || cropperImageProps === void 0 ? void 0 : cropperImageProps.score).toFixed(2)) + })] + }), (cropperImageProps === null || cropperImageProps === void 0 ? void 0 : cropperImageProps.showEditTools) && /*#__PURE__*/_jsx(BtnGroup, _objectSpread({ + circle: true, + style: { + position: 'absolute', + top: 0, + right: 0 + }, + dataSource: cropBtnDataSource, + onClick: handleCropBtnClick, + selectKey: cropType + }, btnGroupProps))] + })) + }) + }) }] }; - // TODO: 页面初始化 - useEffect(function () {}, [dataSource]); - // 暴露 ref 实例 useImperativeHandle(ref, function () { return { @@ -163,7 +169,7 @@ var BigImageModal = /*#__PURE__*/forwardRef(function (props, ref) { combineImageRef: combineImageRef }; }); - return /*#__PURE__*/React.createElement(Modal, _extends({ + return /*#__PURE__*/_jsxs(Modal, _objectSpread(_objectSpread({ destroyOnClose: true, width: width, open: open, @@ -172,85 +178,93 @@ var BigImageModal = /*#__PURE__*/forwardRef(function (props, ref) { className: componentPrefix, title: title, onCancel: onCancel - }, modalProps), /*#__PURE__*/React.createElement("div", { - style: { - marginTop: '16px' - } - }, /*#__PURE__*/React.createElement(ConfigProvider, { - theme: _objectSpread({ - token: { - colorTextSecondary: 'rgba(0,0,0,0.45)' - }, - components: { - Descriptions: { - titleMarginBottom: '20px', - viewBg: '#f6f6f6', - titleColor: 'rgba(0,0,0,0.45)', - colorTextLabel: 'rgba(0,0,0,0.45)', - contentColor: 'rgba(0,0,0,0.88)' - } - } - }, theme) - }, attributeList.map(function (descriptions) { - var _descriptions$childre; - return /*#__PURE__*/React.createElement(Descriptions, _extends({ - key: descriptions.title, - title: /*#__PURE__*/React.createElement("p", { - style: { - margin: '12px 0 0', - fontSize: initialStyle.fontSize - } - }, descriptions.title), - column: 8, + }, modalProps), {}, { + children: [/*#__PURE__*/_jsxs("div", { style: { - padding: '0 64px' - } - }, descriptionsProps), descriptions === null || descriptions === void 0 || (_descriptions$childre = descriptions.children) === null || _descriptions$childre === void 0 ? void 0 : _descriptions$childre.map(function (item) { - return /*#__PURE__*/React.createElement(DescriptionsItem, { - key: item.key, - label: item.label, - span: 1, - contentStyle: { - fontSize: initialStyle.fontSize - }, - labelStyle: { - fontSize: initialStyle.fontSize - } - }, item.children); - })); - })), /*#__PURE__*/React.createElement("div", { - className: classNames("".concat(componentPrefix, "-view-container")) - }, /*#__PURE__*/React.createElement(Tabs, _extends({ - activeKey: tab, - centered: true, - destroyInactiveTabPane: true, - onChange: function onChange(v) { - setTab(function (pre) { - onTabChange === null || onTabChange === void 0 || onTabChange(v, pre); - return v; - }); - }, - tabBarStyle: { - fontSize: '18px', - fontWeight: 'bold' - } - }, defaultTabsProps, tabsProps)), tab === 'VIDEO' && /*#__PURE__*/React.createElement(VideoPlayer, { - ref: videoPlayerRef, - url: dataSource === null || dataSource === void 0 ? void 0 : dataSource.flvUrl - }), /*#__PURE__*/React.createElement(Navigation, _extends({ - className: classNames("".concat(componentPrefix, "-view-container__nav"), (prevButtonProps === null || prevButtonProps === void 0 ? void 0 : prevButtonProps.disabled) && "".concat(componentPrefix, "-view-container__nav--disabled"), "".concat(componentPrefix, "-view-container__nav--left")), - prev: true, - show: showNavigation, - onClick: onPrevButtonClick - }, prevButtonProps)), /*#__PURE__*/React.createElement(Navigation, _extends({ - className: classNames("".concat(componentPrefix, "-view-container__nav"), (nextButtonProps === null || nextButtonProps === void 0 ? void 0 : nextButtonProps.disabled) && "".concat(componentPrefix, "-view-container__nav--disabled"), "".concat(componentPrefix, "-view-container__nav--right")), - next: true, - show: showNavigation, - onClick: onNextButtonClick - }, nextButtonProps)), isRelated && /*#__PURE__*/React.createElement("div", { - style: { - margin: '24px 0' - } - }, /*#__PURE__*/React.createElement(RelatedImage, relatedImageProps)))), children); + marginTop: '16px' + }, + children: [/*#__PURE__*/_jsx(ConfigProvider, { + theme: _objectSpread({ + token: { + colorTextSecondary: 'rgba(0,0,0,0.45)' + }, + components: { + Descriptions: { + titleMarginBottom: '20px', + viewBg: '#f6f6f6', + titleColor: 'rgba(0,0,0,0.45)', + colorTextLabel: 'rgba(0,0,0,0.45)', + contentColor: 'rgba(0,0,0,0.88)' + } + } + }, theme), + children: attributeList.map(function (descriptions) { + var _descriptions$childre; + return /*#__PURE__*/_jsx(Descriptions, _objectSpread(_objectSpread({ + title: /*#__PURE__*/_jsx("p", { + style: { + margin: '12px 0 0', + fontSize: initialStyle.fontSize + }, + children: descriptions.title + }), + column: 8, + style: { + padding: '0 64px' + } + }, descriptionsProps), {}, { + children: descriptions === null || descriptions === void 0 || (_descriptions$childre = descriptions.children) === null || _descriptions$childre === void 0 ? void 0 : _descriptions$childre.map(function (item) { + return /*#__PURE__*/_jsx(DescriptionsItem, { + label: item.label, + span: 1, + contentStyle: { + fontSize: initialStyle.fontSize + }, + labelStyle: { + fontSize: initialStyle.fontSize + }, + children: item.children + }, item.key); + }) + }), descriptions.title); + }) + }), /*#__PURE__*/_jsxs("div", { + className: classNames("".concat(componentPrefix, "-view-container")), + children: [/*#__PURE__*/_jsx(Tabs, _objectSpread(_objectSpread({ + activeKey: tab, + centered: true, + destroyInactiveTabPane: true, + onChange: function onChange(v) { + setTab(function (pre) { + onTabChange === null || onTabChange === void 0 || onTabChange(v, pre); + return v; + }); + }, + tabBarStyle: { + fontSize: '18px', + fontWeight: 'bold' + } + }, defaultTabsProps), tabsProps)), tab === 'VIDEO' && /*#__PURE__*/_jsx(VideoPlayer, { + ref: videoPlayerRef, + url: dataSource === null || dataSource === void 0 ? void 0 : dataSource.flvUrl + }), /*#__PURE__*/_jsx(Navigation, _objectSpread({ + className: classNames("".concat(componentPrefix, "-view-container__nav"), (prevButtonProps === null || prevButtonProps === void 0 ? void 0 : prevButtonProps.disabled) && "".concat(componentPrefix, "-view-container__nav--disabled"), "".concat(componentPrefix, "-view-container__nav--left")), + prev: true, + show: showNavigation, + onClick: onPrevButtonClick + }, prevButtonProps)), /*#__PURE__*/_jsx(Navigation, _objectSpread({ + className: classNames("".concat(componentPrefix, "-view-container__nav"), (nextButtonProps === null || nextButtonProps === void 0 ? void 0 : nextButtonProps.disabled) && "".concat(componentPrefix, "-view-container__nav--disabled"), "".concat(componentPrefix, "-view-container__nav--right")), + next: true, + show: showNavigation, + onClick: onNextButtonClick + }, nextButtonProps)), isRelated && /*#__PURE__*/_jsx("div", { + style: { + margin: '24px 0' + }, + children: /*#__PURE__*/_jsx(RelatedImage, _objectSpread({}, relatedImageProps)) + })] + })] + }), children] + })); }); export default BigImageModal; \ No newline at end of file diff --git a/packages/biz/src/boxSelectTree/boxSelectTree.tsx b/packages/biz/src/boxSelectTree/boxSelectTree.tsx index e460842..e965cad 100644 --- a/packages/biz/src/boxSelectTree/boxSelectTree.tsx +++ b/packages/biz/src/boxSelectTree/boxSelectTree.tsx @@ -1,6 +1,5 @@ import React, { FC, ReactNode, useContext } from 'react'; -import { Tabs, TabsProps } from 'antd' -import { ConfigProvider } from '@zhst/meta'; +import { ConfigProvider, Tabs, TabsProps } from '@zhst/meta'; import BoxPanel from './components/boxPanel'; import type { BoxPanelProps } from './components/boxPanel'; import './index.less' diff --git a/packages/biz/src/boxSelectTree/components/boxPanel/index.tsx b/packages/biz/src/boxSelectTree/components/boxPanel/index.tsx index 299b2b1..79fa16e 100644 --- a/packages/biz/src/boxSelectTree/components/boxPanel/index.tsx +++ b/packages/biz/src/boxSelectTree/components/boxPanel/index.tsx @@ -1,13 +1,22 @@ import React, { FC, useState, useContext, ReactNode } from 'react'; -import{ Button, Divider, Dropdown, Input, TreeDataNode } from 'antd' import { ModalFormProps } from '@ant-design/pro-components' -import { ButtonProps, ConfigProvider, Tooltip } from '@zhst/meta'; +import { Input, Dropdown } from 'antd' +import { + ButtonProps, + ConfigProvider, + Tooltip, + Button, + Divider, + DataNode as TreeDataNode, + Tree as BoxTree, + TreeProps as BoxTreeProps, + TreeProps, + InputProps, + DropDownProps +} from '@zhst/meta'; import { IconFont } from '@zhst/icon'; import { ClockCircleOutlined, CloseCircleOutlined, DiffOutlined, FolderAddOutlined, ImportOutlined, SwitcherOutlined } from '@ant-design/icons' -import type { TreeProps, InputProps, DropDownProps } from 'antd'; import classNames from 'classnames'; -import type { BoxTreeProps } from '../../../tree'; -import BoxTree from '../../../tree'; import './index.less' interface IOption { @@ -42,10 +51,6 @@ export interface BoxPanelProps { * @deprecated 将于下个版本 0.23.0 以后弃用 */ onBoxBatchDelete?: (data?: any) => void - /** - * @deprecated 将于下个版本 0.23.0 以后弃用 - */ - onBoxDelete?: (data?: any) => void /** * @deprecated 将于下个版本 0.23.0 以后弃用 */ @@ -98,7 +103,6 @@ const BoxPanel: FC = (props) => { onItemCheck, onItemSelect, onBoxBatchDelete, - onBoxDelete, onClockClick, onImport, onBatch, @@ -314,11 +318,11 @@ const BoxPanel: FC = (props) => { )} diff --git a/packages/biz/src/boxSelectTree/demo/basic.tsx b/packages/biz/src/boxSelectTree/demo/basic.tsx index fb3db19..65290c3 100644 --- a/packages/biz/src/boxSelectTree/demo/basic.tsx +++ b/packages/biz/src/boxSelectTree/demo/basic.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { BoxSelectTree } from '@zhst/biz'; import { treeData, boxDataSource } from './mock' -import { Select, TreeProps, Modal, Checkbox, Button } from 'antd'; +import { Select, TreeProps, Modal, Checkbox, Button } from '@zhst/meta'; const { Option } = Select diff --git a/packages/biz/src/boxSelectTree/index.md b/packages/biz/src/boxSelectTree/index.md index 2feff2c..303c436 100644 --- a/packages/biz/src/boxSelectTree/index.md +++ b/packages/biz/src/boxSelectTree/index.md @@ -3,7 +3,7 @@ category: Components title: BoxSelectTree 盒子树 toc: content demo: - cols: 3 + cols: 2 group: title: 进阶组件 --- diff --git a/packages/biz/src/tree/boxTree.tsx b/packages/biz/src/tree/boxTree.tsx index 3caf29d..3b3e8bc 100644 --- a/packages/biz/src/tree/boxTree.tsx +++ b/packages/biz/src/tree/boxTree.tsx @@ -1,5 +1,6 @@ +// !! 已经弃用,改为使用meta/tree import React, { FC, useState } from 'react'; -import { Tree, Badge, TreeDataNode, Space, TreeProps, theme, ConfigProvider } from 'antd'; +import { Tree, Badge, DataNode as TreeDataNode, Space, TreeProps, theme } from '@zhst/meta' import { CloseOutlined, EditOutlined, SettingOutlined } from '@ant-design/icons' import classNames from 'classnames'; import './index.less' diff --git a/packages/biz/src/tree/index.md b/packages/biz/src/tree/index.md index 164a658..ec3cfc1 100644 --- a/packages/biz/src/tree/index.md +++ b/packages/biz/src/tree/index.md @@ -1,6 +1,6 @@ --- category: Components -title: Tree 树 +title: Tree 树 [废弃] toc: content demo: cols: 2 @@ -10,6 +10,11 @@ group: --- +:::warning{title=0.25.1之后版本已废弃} +组件迁移到 @zhst/meta +::: + + ## 代码演示 基本用法 diff --git a/packages/biz/src/treeTransfer/TreeTransfer.tsx b/packages/biz/src/treeTransfer/TreeTransfer.tsx index ca5dedc..4ba3180 100644 --- a/packages/biz/src/treeTransfer/TreeTransfer.tsx +++ b/packages/biz/src/treeTransfer/TreeTransfer.tsx @@ -1,22 +1,45 @@ -import React, { useState } from 'react'; -import { Button, Card, ConfigProvider, theme, Flex, Input, InputProps, TransferProps, TreeDataNode, TreeProps, Tree } from 'antd'; +import React, { ReactNode } from 'react'; +import { Button, ConfigProvider, theme, Flex, InputProps, TabsProps, Tabs, ButtonProps, Tree, TreeProps, DataNode as TreeDataNode } from '@zhst/meta' +import { Input } from 'antd' +import { IconFont } from '@zhst/icon' import './index.less' -import { DeleteOutlined, DoubleRightOutlined, SearchOutlined } from '@ant-design/icons'; const componentName = 'zhst-biz-treeTransfer' export interface TreeTransferProps { + titles?: string[] | ReactNode[] dataSource: TreeDataNode[] treeProps?: TreeProps + showLeftSearch?: boolean searchInputProps?: InputProps targetItems: TreeDataNode[]; checkedKeys: string[]; + showFilter?: boolean; + showLeftPanelFooter?: boolean; + leftPanelFooterRender?: ReactNode | string; + showRightPanelFooter?: boolean; + rightPanelFooterRender?: (events: { onOk: TreeTransferProps['onOk'], onReset: TreeTransferProps['onReset'] }) => ReactNode | string; + leftPanelWidth?: string | number; + rightPanelWidth?: string | number; + leftPanelScrollY?: number; + rightPanelScrollY?: number; + tabsItems?: TabsProps['items'] + showLeftTabs?: boolean + activeTabKey?: string + treeBackgroundColor?: string + leftTabsProps?: Partial + customLeftPanelContent?: (data?: TreeDataNode[]) => ReactNode + filters?: (ButtonProps & { + label?: string; + icon?: ReactNode; + })[] + onLeftTabsChange?: TabsProps['onChange'] onTreeSelect?: TreeProps['onSelect'] onTreeCheck?: TreeProps['onCheck'] onItemDelete?: (key: string, info?: TreeDataNode) => void - onChange?: TransferProps['onChange']; onOk?: (data: any) => void; onReset?: () => void; + onSearch?: InputProps['onChange'] } const { useToken } = theme @@ -24,68 +47,133 @@ const { useToken } = theme const TreeTransfer: React.FC = ({ dataSource, treeProps, + titles = ['可选择的范围', '已选择的范围'], searchInputProps, + showLeftSearch = true, + leftPanelScrollY = 300, + treeBackgroundColor = '#FCFCFC', + leftPanelWidth = 500, + rightPanelScrollY = 422, + rightPanelWidth = 300, targetItems = [], checkedKeys = [], + showFilter = true, + showLeftPanelFooter, + showRightPanelFooter = true, + customLeftPanelContent, + leftPanelFooterRender, + rightPanelFooterRender, + showLeftTabs, + leftTabsProps, + activeTabKey, + tabsItems = [ + { + key: 'camera', + label:
摄像头
, + }, + { + key: 'plan', + label:
预案
, + }, + { + key: 'map', + label:
地图框选
, + }, + ], + filters = [], + onLeftTabsChange, onTreeCheck, onTreeSelect, onItemDelete, + onSearch, onOk, onReset }) => { const { token } = useToken() - const [keyWords, setKeyWords ] = useState('') - - function findNodesWithKeyword(_keyWords: string, _treeData: TreeDataNode[]) { - // @ts-ignore - function dfs(node: any) { - return node.filter((item: { title: string | string[]; }) => item.title.includes(_keyWords)) - } - - const data = dfs(_treeData) - return data || []; - } return ( - -
- +
+
可选择的范围
} > - } onChange={e => setKeyWords(e.target.value)} placeholder='请输入设备名称' {...searchInputProps} /> - - onTreeCheck?.(keys, info)} - onSelect={(keys, info) => onTreeSelect?.(keys, info)} - {...treeProps} +
{titles?.[0]}
+ {showLeftTabs && ( + -
- + )} + {showLeftSearch && ( +
+ } + placeholder='请输入设备名称' + onChange={onSearch} + {...searchInputProps} + /> + {showFilter && ( +
+ {filters?.map(item => ( + + ))} +
+ )} +
+ )} + {customLeftPanelContent?.(dataSource) || ( + + onTreeCheck?.(keys, info)} + onSelect={(keys: any, info: any) => onTreeSelect?.(keys, info)} + {...treeProps} + /> + + )} + {showLeftPanelFooter && ( +
+ {leftPanelFooterRender} +
+ )} +
- -
- + +
+
+
已选择的范围
} > +
{titles?.[1]}
{targetItems.map(item => (
= ({ > {item.title as any}
- { - // const { root, keys } = getAllRootKeyById(item.key as string, dataSource) + { onItemDelete?.(item.key as string, item) }} />
@@ -111,19 +198,25 @@ const TreeTransfer: React.FC = ({ ))}
- - - - - + {showRightPanelFooter && ( + + {rightPanelFooterRender?.({ onOk, onReset }) || ( + <> + + + + )} + + )} +
-
+ ); } diff --git a/packages/biz/src/treeTransfer/demo/basic.tsx b/packages/biz/src/treeTransfer/demo/basic.tsx index 35be3a6..4590e2f 100644 --- a/packages/biz/src/treeTransfer/demo/basic.tsx +++ b/packages/biz/src/treeTransfer/demo/basic.tsx @@ -42,10 +42,18 @@ const App: React.FC = () => { return ( + 自定义脚部dom + + )} onItemDelete={onItemDelete} onOk={onOk} onReset={onReset} diff --git a/packages/biz/src/treeTransfer/demo/noSearch.tsx b/packages/biz/src/treeTransfer/demo/noSearch.tsx new file mode 100644 index 0000000..da40546 --- /dev/null +++ b/packages/biz/src/treeTransfer/demo/noSearch.tsx @@ -0,0 +1,57 @@ +import React, { useState } from 'react'; +import { TreeTransfer } from '@zhst/biz'; +import { TreeDataNode } from 'antd'; +import { TreeProps } from 'antd/lib'; +import { boxDataSource } from './mock' + +const App: React.FC = () => { + const [targetItems, setTargetItems] = useState([]); + const [checkedKeys, setCheckedKeys] = useState([]); + + const onTreeCheck: TreeProps['onCheck'] = (keys: any, info) => { + let _targetItems: TreeDataNode[] = [] + setCheckedKeys(keys) + info.checkedNodes.forEach(o => { + o.isLeaf && _targetItems.push(o) + }) + setTargetItems(_targetItems) + } + + /** + * 删除 + * @param key + * @param param1 + */ + const onItemDelete = (key: any, { keys = [] }: any) => { + setCheckedKeys(pre => { + const newKeys = pre.filter(_key => _key !== key) + console.log('newKeys', newKeys, keys) + return newKeys + }) + setTargetItems(pre => pre.filter(o => o.key !== key)) + } + + const onOk = (data: any) => { + console.log('data', data) + } + + const onReset = () => { + setCheckedKeys([]) + setTargetItems([]) + } + + return ( + + ) +}; + +export default App; diff --git a/packages/biz/src/treeTransfer/demo/withFilter.tsx b/packages/biz/src/treeTransfer/demo/withFilter.tsx new file mode 100644 index 0000000..0958a89 --- /dev/null +++ b/packages/biz/src/treeTransfer/demo/withFilter.tsx @@ -0,0 +1,66 @@ +import React, { useState } from 'react'; +import { TreeTransfer } from '@zhst/biz'; +import { TreeDataNode } from 'antd'; +import { IconFont } from '@zhst/icon' +import { TreeProps } from 'antd/lib'; +import { boxDataSource } from './mock' + +const App: React.FC = () => { + const [targetItems, setTargetItems] = useState([]); + const [checkedKeys, setCheckedKeys] = useState([]); + + const onTreeCheck: TreeProps['onCheck'] = (keys: any, info) => { + let _targetItems: TreeDataNode[] = [] + setCheckedKeys(keys) + info.checkedNodes.forEach(o => { + o.isLeaf && _targetItems.push(o) + }) + setTargetItems(_targetItems) + } + + /** + * 删除 + * @param key + * @param param1 + */ + const onItemDelete = (key: any, { keys = [] }: any) => { + setCheckedKeys(pre => { + const newKeys = pre.filter(_key => _key !== key) + console.log('newKeys', newKeys, keys) + return newKeys + }) + setTargetItems(pre => pre.filter(o => o.key !== key)) + } + + const onOk = (data: any) => { + console.log('data', data) + } + + const onReset = () => { + setCheckedKeys([]) + setTargetItems([]) + } + + return ( + , + danger: true, + onClick: () => {} + } + ]} + onItemDelete={onItemDelete} + onOk={onOk} + onReset={onReset} + /> + ) +}; + +export default App; diff --git a/packages/biz/src/treeTransfer/demo/withMap.tsx b/packages/biz/src/treeTransfer/demo/withMap.tsx new file mode 100644 index 0000000..8e76286 --- /dev/null +++ b/packages/biz/src/treeTransfer/demo/withMap.tsx @@ -0,0 +1,103 @@ +import React, { useRef, useState } from 'react'; +import { TreeTransfer } from '@zhst/biz'; +import { TreeDataNode } from 'antd'; +import { TreeProps } from 'antd/lib'; +import { MapBox } from '@zhst/map' +import { boxDataSource } from './mock' + +const App: React.FC = () => { + const [targetItems, setTargetItems] = useState([]); + const [checkedKeys, setCheckedKeys] = useState([]); + const [activeTabKey, setActiveTabKey] = useState('camera'); + const mapRef = useRef(null); + const [canDraw, setCanDraw] = useState(false) + const [toolsBarOpen, setToolsBarOpen] = useState(false) + + // 地图初始化 + const handleMapLoad = (e: mapboxgl.MapboxEvent) => { + const map = e.target; + + if (!map) return + + map.flyTo({ + // center: [120,30], + // zoom: map?.getMaxZoom(), + }); + }; + + const onTreeCheck: TreeProps['onCheck'] = (keys: any, info) => { + let _targetItems: TreeDataNode[] = [] + setCheckedKeys(keys) + info.checkedNodes.forEach(o => { + o.isLeaf && _targetItems.push(o) + }) + setTargetItems(_targetItems) + } + + /** + * 删除 + * @param key + * @param param1 + */ + const onItemDelete = (key: any, { keys = [] }: any) => { + setCheckedKeys(pre => { + const newKeys = pre.filter(_key => _key !== key) + console.log('newKeys', newKeys, keys) + return newKeys + }) + setTargetItems(pre => pre.filter(o => o.key !== key)) + } + + const onOk = (data: any) => { + console.log('data', data) + } + + const onReset = () => { + setCheckedKeys([]) + setTargetItems([]) + } + + return ( + setActiveTabKey(val)} + customLeftPanelContent={(data) => { + if (activeTabKey !== 'map') return null + + return ( +
+ { + setCanDraw(pre => !pre) + setToolsBarOpen(pre => !pre) + }} + drawerProps={{ + onActionable: e => console.log('e', e) + }} + > +
+ ) + }} + onItemDelete={onItemDelete} + onOk={onOk} + onReset={onReset} + /> + ) +}; + +export default App; diff --git a/packages/biz/src/treeTransfer/index.less b/packages/biz/src/treeTransfer/index.less index 6943db8..c8721d5 100644 --- a/packages/biz/src/treeTransfer/index.less +++ b/packages/biz/src/treeTransfer/index.less @@ -1,28 +1,84 @@ .zhst-biz-treeTransfer { + display: flex; + align-items: center; &-left { &_card { - width: 500px; + display: flex; + flex-direction: column; + position: relative; min-height: 544px; background-color: #FCFCFC; + border: 2px solid #f7f7f7; + + &_title { + padding: 12px; + text-align: center; + border-bottom: 2px solid #f7f7f7; + } + + .ant-tabs { + .ant-tabs-nav { + margin-bottom: 0; + } + .ant-tabs-nav-list { + width: 100%; + } + .ant-tabs-tab { + margin: 0; + justify-content: center; + text-align: center; + flex: 1; + } + } + + &_search { + display: flex; + margin: 8px; + &_input { + margin-right: 8px; + } + } &-tree { - margin-top: 6px; + } + + &-footer { + position: absolute; + width: 100%; + bottom: 0; + left: 0; } } } + &-middle { + padding: 24px; + height: 100%; + color: #d9d9d9; + transform-origin: center center; + transform: rotate(90deg); + } + &-right { &_card { - width: 300px; + position: relative; min-height: 544px; background-color: #FCFCFC; + border: 2px solid #f7f7f7; + + &_title { + padding: 12px; + text-align: center; + border-bottom: 2px solid #f7f7f7; + } &__items { - padding: 8px 4px; width: 100%; height: calc(100% - 105px); + font-size: 14px; overflow-y: scroll; max-height: 422px; + box-sizing: border-box; &::-webkit-scrollbar { display: none; @@ -44,7 +100,7 @@ left: 50%; transform: translateX(-50%); box-sizing: border-box; - border-top: 1px solid #f0f0f0; + border-top: 2px solid #f0f0f0; } } } diff --git a/packages/biz/src/treeTransfer/index.md b/packages/biz/src/treeTransfer/index.md index 38f801f..7cf044f 100644 --- a/packages/biz/src/treeTransfer/index.md +++ b/packages/biz/src/treeTransfer/index.md @@ -12,10 +12,41 @@ group: ## 代码演示 基本用法 +没有搜索框 +加载filter按钮 +和地图组件搭配使用 和Modal组合使用 ## API | 参数 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | -| data | 数据源 | Array[] | [] | - | +| titles | 顶部标题 | string[]、ReactNode[] | [] | - | +| dataSource | 数据 | TreeDataNode[] | [] | - | +| treeProps | 左侧树的props | antd-tree | [] | - | +| showLeftSearch | 显示左侧搜索框 | boolean | true | - | +| searchInputProps | 左侧搜索透传 | InputProps | {} | - | +| targetItems | 选中数据 | TreeDataNode[] | [] | - | +| checkedKeys | 选中的key数组 | string[] | [] | - | +| showFilter | 是否显示搜索框边上的dom | boolean | false | - | +| leftPanelWidth | 左边面板高度 | string、number | - | - | +| leftPanelScrollY | 左边面板滚动高度 | number | - | - | +| showLeftPanelFooter | 是否显示左边面板的底部 | boolean | false | - | +| leftPanelFooterRender | 左边面板底部自定义 | | ReactNode、string | - | +| rightPanelWidth | 右边面板高度 | number、string | - | - | +| rightPanelScrollY | 右边面板滚动高度 | number | - | - | +| showRightPanelFooter | 是否显示右边面板的底部 | boolean | false | - | +| rightPanelFooterRender | 右边边面板底部自定义 | ReactNode、string | - | - | +| tabsItems | tab列表 | 参考antd-tabs组件的 tabsProps['items'] | - | - | +| showLeftTabs | 是否显示tabs组件 | boolean | false | - | +| activeTabKey | 当前选中tab | string | - | - | +| treeBackgroundColor | 左侧树颜色 | string | #FCFCFC | - | +| leftTabsProps | 左侧树tabs的props | tabsProps | - | - | +| customLeftPanelContent | 左侧树自定义内容 | (data?: TreeDataNode[]) => ReactNode | - | - | +| filters | 左侧过滤自定义 | ButtonProps & { label: string; icon?: string } | - | - | +| onLeftTabsChange | 左侧tab点击事件 | TabsProps['onChange'] | - | - | +| onTreeSelect | 左侧树点击事件 | TreeProps['onSelect'] | - | - | +| onTreeCheck | 左侧树勾选☑️事件 | TreeProps['onCheck'] | - | - | +| onOk | 提交事件 | (data: any) => void; | - | - | +| onReset | 重置事件 | () => void; | - | - | +| onSearch | 左侧树搜索事件 | InputProps['onChange'] | - | - | diff --git a/packages/func/es/file/index.d.ts b/packages/func/es/file/index.d.ts index 2f4e705..dabc536 100644 --- a/packages/func/es/file/index.d.ts +++ b/packages/func/es/file/index.d.ts @@ -1,4 +1,4 @@ -export type Rect = { +export declare type Rect = { x: number; y: number; w: number; diff --git a/packages/func/es/string/index.js b/packages/func/es/string/index.js index 6920e07..f8ed1cd 100644 --- a/packages/func/es/string/index.js +++ b/packages/func/es/string/index.js @@ -86,4 +86,20 @@ export var pxToRem = function pxToRem(value, rootFontSize) { }).map(function (val) { return parseFloat(val) / fontSize + 'rem'; }).join(' '); +}; + +/** + * 跳转到指定URL + * @param to 跳转的url + * @returns URL + */ +export var jumpTo = function jumpTo(to) { + var from = location.origin + location.pathname; + // 检查是否为url,并且跑出错误 + if (!isUrl(to)) { + throw Error("\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u94FE\u63A5\uFF0C\u4EE5http(s)://\u5F00\u5934\uFF01'"); + } + var _targetUrl = new URL(to); + _targetUrl.searchParams.set('from', from); + return _targetUrl; }; \ No newline at end of file diff --git a/packages/func/lib/file/index.d.ts b/packages/func/lib/file/index.d.ts index 2f4e705..dabc536 100644 --- a/packages/func/lib/file/index.d.ts +++ b/packages/func/lib/file/index.d.ts @@ -1,4 +1,4 @@ -export type Rect = { +export declare type Rect = { x: number; y: number; w: number; diff --git a/packages/func/lib/string/index.js b/packages/func/lib/string/index.js index b018287..6d0895c 100644 --- a/packages/func/lib/string/index.js +++ b/packages/func/lib/string/index.js @@ -23,6 +23,7 @@ __export(string_exports, { getStrLength: () => getStrLength, getValueByUrl: () => getValueByUrl, isUrl: () => isUrl, + jumpTo: () => jumpTo, pxToRem: () => pxToRem }); module.exports = __toCommonJS(string_exports); @@ -80,11 +81,21 @@ var pxToRem = (value, rootFontSize) => { const valueArr = value.split(" "); return valueArr.filter((o) => o).map((val) => parseFloat(val) / fontSize + "rem").join(" "); }; +var jumpTo = (to) => { + const from = location.origin + location.pathname; + if (!isUrl(to)) { + throw Error(`\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u94FE\u63A5\uFF0C\u4EE5http(s)://\u5F00\u5934\uFF01'`); + } + let _targetUrl = new URL(to); + _targetUrl.searchParams.set("from", from); + return _targetUrl; +}; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { cutStr, getStrLength, getValueByUrl, isUrl, + jumpTo, pxToRem }); diff --git a/packages/func/lib/time/index.js b/packages/func/lib/time/index.js index cf77388..ba4fcef 100644 --- a/packages/func/lib/time/index.js +++ b/packages/func/lib/time/index.js @@ -43,15 +43,15 @@ var formateDuration = (diff) => { var minutes = Math.floor(leave2 / (60 * 1e3)); var leave3 = leave2 % (60 * 1e3); var seconds = Math.round(leave3 / 1e3); - var returnStr = seconds + "秒"; + var returnStr = seconds + "\u79D2"; if (minutes > 0) { - returnStr = minutes + "分"; + returnStr = minutes + "\u5206"; } if (hours > 0) { - returnStr = hours + "小时"; + returnStr = hours + "\u5C0F\u65F6"; } if (days > 0) { - returnStr = days + "天"; + returnStr = days + "\u5929"; } return returnStr; }; diff --git a/packages/hooks/es/useCustomCompareEffect/index.d.ts b/packages/hooks/es/useCustomCompareEffect/index.d.ts index e1ddb43..ec9bb85 100644 --- a/packages/hooks/es/useCustomCompareEffect/index.d.ts +++ b/packages/hooks/es/useCustomCompareEffect/index.d.ts @@ -1,4 +1,4 @@ import { DependencyList, EffectCallback } from 'react'; -type DepsEqualFnType = (prevDeps: TDeps, nextDeps: TDeps) => boolean; +declare type DepsEqualFnType = (prevDeps: TDeps, nextDeps: TDeps) => boolean; declare const useCustomCompareEffect: (effect: EffectCallback, deps: TDeps, depsEqual: DepsEqualFnType) => void; export default useCustomCompareEffect; diff --git a/packages/hooks/es/useJump/interface.d.ts b/packages/hooks/es/useJump/interface.d.ts index f0a8dac..2f384b9 100644 --- a/packages/hooks/es/useJump/interface.d.ts +++ b/packages/hooks/es/useJump/interface.d.ts @@ -1 +1 @@ -export type JumpType = 'warningRecord' | 'targetSearch' | 'passerby' | 'targetDetail' | 'traceAnalysis' | 'offlineAnalysis'; +export declare type JumpType = 'warningRecord' | 'targetSearch' | 'passerby' | 'targetDetail' | 'traceAnalysis' | 'offlineAnalysis'; diff --git a/packages/hooks/es/useRafLoop.d.ts b/packages/hooks/es/useRafLoop.d.ts index 3b7c6c2..608583e 100644 --- a/packages/hooks/es/useRafLoop.d.ts +++ b/packages/hooks/es/useRafLoop.d.ts @@ -1,2 +1,2 @@ -export type RafLoopReturns = [() => void, () => void, () => boolean]; +export declare type RafLoopReturns = [() => void, () => void, () => boolean]; export default function useRafLoop(callback: FrameRequestCallback, initiallyActive?: boolean): RafLoopReturns; diff --git a/packages/hooks/es/useSocket/index.d.ts b/packages/hooks/es/useSocket/index.d.ts index e69de29..cb0ff5c 100644 --- a/packages/hooks/es/useSocket/index.d.ts +++ b/packages/hooks/es/useSocket/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/hooks/lib/useCustomCompareEffect/index.d.ts b/packages/hooks/lib/useCustomCompareEffect/index.d.ts index e1ddb43..ec9bb85 100644 --- a/packages/hooks/lib/useCustomCompareEffect/index.d.ts +++ b/packages/hooks/lib/useCustomCompareEffect/index.d.ts @@ -1,4 +1,4 @@ import { DependencyList, EffectCallback } from 'react'; -type DepsEqualFnType = (prevDeps: TDeps, nextDeps: TDeps) => boolean; +declare type DepsEqualFnType = (prevDeps: TDeps, nextDeps: TDeps) => boolean; declare const useCustomCompareEffect: (effect: EffectCallback, deps: TDeps, depsEqual: DepsEqualFnType) => void; export default useCustomCompareEffect; diff --git a/packages/hooks/lib/useJump/interface.d.ts b/packages/hooks/lib/useJump/interface.d.ts index f0a8dac..2f384b9 100644 --- a/packages/hooks/lib/useJump/interface.d.ts +++ b/packages/hooks/lib/useJump/interface.d.ts @@ -1 +1 @@ -export type JumpType = 'warningRecord' | 'targetSearch' | 'passerby' | 'targetDetail' | 'traceAnalysis' | 'offlineAnalysis'; +export declare type JumpType = 'warningRecord' | 'targetSearch' | 'passerby' | 'targetDetail' | 'traceAnalysis' | 'offlineAnalysis'; diff --git a/packages/hooks/lib/useRafLoop.d.ts b/packages/hooks/lib/useRafLoop.d.ts index 3b7c6c2..608583e 100644 --- a/packages/hooks/lib/useRafLoop.d.ts +++ b/packages/hooks/lib/useRafLoop.d.ts @@ -1,2 +1,2 @@ -export type RafLoopReturns = [() => void, () => void, () => boolean]; +export declare type RafLoopReturns = [() => void, () => void, () => boolean]; export default function useRafLoop(callback: FrameRequestCallback, initiallyActive?: boolean): RafLoopReturns; diff --git a/packages/hooks/lib/useSocket/index.d.ts b/packages/hooks/lib/useSocket/index.d.ts index e69de29..cb0ff5c 100644 --- a/packages/hooks/lib/useSocket/index.d.ts +++ b/packages/hooks/lib/useSocket/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/icon/es/Iconfont.js b/packages/icon/es/Iconfont.js index fd9fed8..574fa37 100644 --- a/packages/icon/es/Iconfont.js +++ b/packages/icon/es/Iconfont.js @@ -6,6 +6,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } import { createFromIconfontCN } from '@ant-design/icons'; import React from 'react'; +import { jsx as _jsx } from "react/jsx-runtime"; var Icon = createFromIconfontCN({ scriptUrl: require("./font/iconfont.js") }); @@ -24,7 +25,7 @@ var IconFont = function IconFont(props) { active = _ref$active === void 0 ? false : _ref$active, _ref$color = _ref.color, color = _ref$color === void 0 ? '' : _ref$color; - return /*#__PURE__*/React.createElement(Icon, { + return /*#__PURE__*/_jsx(Icon, { title: title, onClick: function onClick(e) { onIconClick && onIconClick(e); @@ -36,7 +37,8 @@ var IconFont = function IconFont(props) { }, active ? { color: '#09f' } : {}), - type: icon - }, children); + type: icon, + children: children + }); }; export default IconFont; \ No newline at end of file diff --git a/packages/map/package.json b/packages/map/package.json index 5f931f6..869c5a3 100644 --- a/packages/map/package.json +++ b/packages/map/package.json @@ -40,8 +40,8 @@ "@mapbox/mapbox-gl-draw": "^1.4.3", "@mapbox/mapbox-gl-draw-static-mode": "^1.0.1", "@turf/turf": "^6.5.0", - "@zhst/hooks": "workspace:^0.13.1", - "@zhst/icon": "workspace:^0.5.0", + "@zhst/hooks": "workspace:^", + "@zhst/icon": "workspace:^", "@zhst/meta": "workspace:^", "classnames": "^2.5.1", "mapbox-gl": "^2.15.0", @@ -51,7 +51,6 @@ "react-map-gl": "^7.1.7" }, "devDependencies": { - "@types/mapbox__mapbox-gl-draw": "^1.4.6", - "axios": "^1.7.2" + "@types/mapbox__mapbox-gl-draw": "^1.4.6" } } diff --git a/packages/map/src/demo/basic.tsx b/packages/map/src/demo/basic.tsx index 9628dd8..b2826d9 100644 --- a/packages/map/src/demo/basic.tsx +++ b/packages/map/src/demo/basic.tsx @@ -1,7 +1,6 @@ import React, { useRef, useEffect, useState } from 'react'; import { MapBox, Marker } from '@zhst/map'; -import axios from 'axios'; -import { FloatButton, Switch } from '@zhst/meta'; +import { Button, Input, Space } from '@zhst/meta'; import { MarkerProps } from '../components/marker'; import { getDistancesByStringLine, lineToPoly } from '../utils'; // import { sluterData } from './.data/mock.ts' @@ -18,6 +17,7 @@ const demo = () => { const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }) const [rangingList, setRangingList] = useState([]) const mapRef = useRef(null); + const [token, setToken] = useState('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTczMDA4NTIsImp0aSI6IjExNTkiLCJpYXQiOjE3MTcwNDE2NTIsInVzZXJJZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsImRhdGFSaWdodCI6MiwiY2FtZXJhUmlnaHQiOjEsImdwdVJpZ2h0IjoxLCJ1c2VybGVhZGVySWQiOjAsIm9yZ2FuaXphdGlvbklkIjoxLCJyb2xlSWQiOjF9.n9b_jcvzyehu2vmZF6ZrFM4Vz7h7Xr2GCf9p7muGTBE') // 初始化 const handleMapLoad = (e: mapboxgl.MapboxEvent) => { @@ -31,21 +31,23 @@ const demo = () => { }); }; - const getData = async () => { - let res = await axios({ + const getData = async ({ url = 'http://10.0.0.120:30003/singer.DeviceService/ListCamera', token }: { url?: String, token: string }) => { + let res = await fetch( + url, + { method: 'post', - url: 'http://10.0.0.120:30003/singer.DeviceService/ListCamera', headers: { - Authorization: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTcwNDAzNzEsImp0aSI6IjExMjgiLCJpYXQiOjE3MTY3ODExNzEsInVzZXJJZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsImRhdGFSaWdodCI6MiwiY2FtZXJhUmlnaHQiOjEsImdwdVJpZ2h0IjoxLCJ1c2VybGVhZGVySWQiOjAsIm9yZ2FuaXphdGlvbklkIjoxLCJyb2xlSWQiOjF9.XHbXIkXkfUuvqV6_qSV4d20xj-s7I0qOQZgL-zspMDc' + Authorization: token }, data: {"labelData":[],"filter":{"realtimeProcessingFilter":0,"cameraFilter":[{"opt":"ORNOT","cameraOpt":"CAMERAOPT_TYPE","value":"100"}]},"maxResults":50} }); + const data = await res.json() if (res.status === 200) { let markers = [] let sluters = { features: [] } - res.data.cameras?.forEach(camera => { + data.cameras?.forEach(camera => { markers.push({ key: camera.id, id: camera.id, @@ -74,15 +76,13 @@ const demo = () => { } } - useEffect(() => { - getData() - }, []) - return (
- - - + + 获取摄像头位置: + setToken(e.target.value)} value={token} /> + + { {rangingList?.map((item, index) => { return ( = (props) => { clickedRef.current = false; } else { returnValueOfOnOk = actionFn(); - if (!returnValueOfOnOk) { + if (!isThenable(returnValueOfOnOk)) { onInternalClose(); return; } diff --git a/packages/meta/src/_util/PurePanel.tsx b/packages/meta/src/_util/PurePanel.tsx index beb4731..f0b2f81 100644 --- a/packages/meta/src/_util/PurePanel.tsx +++ b/packages/meta/src/_util/PurePanel.tsx @@ -45,7 +45,7 @@ const genPurePanel = ( if (typeof ResizeObserver !== 'undefined') { const resizeObserver = new ResizeObserver((entries) => { - const element: HTMLDivElement = entries[0].target as any; + const element = entries[0].target as HTMLDivElement; setPopupHeight(element.offsetHeight + 8); setPopupWidth(element.offsetWidth); }); diff --git a/packages/meta/src/_util/__tests__/getScroll.test.ts b/packages/meta/src/_util/__tests__/getScroll.test.ts index 8cb737f..f7b7e11 100644 --- a/packages/meta/src/_util/__tests__/getScroll.test.ts +++ b/packages/meta/src/_util/__tests__/getScroll.test.ts @@ -1,12 +1,12 @@ import getScroll from '../getScroll'; describe('getScroll', () => { - it('getScroll target null', async () => { + it('getScroll target null', () => { expect(getScroll(null, true)).toBe(0); expect(getScroll(null, false)).toBe(0); }); - it('getScroll window', async () => { + it('getScroll window', () => { const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => { window.pageXOffset = x; window.pageYOffset = y; @@ -17,7 +17,7 @@ describe('getScroll', () => { scrollToSpy.mockRestore(); }); - it('getScroll document', async () => { + it('getScroll document', () => { const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => { document.documentElement.scrollLeft = x; document.documentElement.scrollTop = y; @@ -28,7 +28,7 @@ describe('getScroll', () => { scrollToSpy.mockRestore(); }); - it('getScroll div', async () => { + it('getScroll div', () => { const div = document.createElement('div'); const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => { div.scrollLeft = x; @@ -40,7 +40,7 @@ describe('getScroll', () => { scrollToSpy.mockRestore(); }); - it('getScroll documentElement', async () => { + it('getScroll documentElement', () => { const div: any = {}; const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => { div.scrollLeft = null; diff --git a/packages/meta/src/_util/__tests__/hooks.test.tsx b/packages/meta/src/_util/__tests__/hooks.test.tsx index fd708e8..f60d51f 100644 --- a/packages/meta/src/_util/__tests__/hooks.test.tsx +++ b/packages/meta/src/_util/__tests__/hooks.test.tsx @@ -1,13 +1,14 @@ +import React, { useEffect } from 'react'; import { CloseOutlined } from '@ant-design/icons'; import { render } from '@testing-library/react'; -import React, { useEffect } from 'react'; + import type { UseClosableParams } from '../hooks/useClosable'; import useClosable from '../hooks/useClosable'; type ParamsOfUseClosable = [ - UseClosableParams['closable'], - UseClosableParams['closeIcon'], - UseClosableParams['defaultClosable'], + closable: UseClosableParams['closable'], + closeIcon: UseClosableParams['closeIcon'], + defaultClosable: UseClosableParams['defaultClosable'], ]; describe('hooks test', () => { @@ -19,7 +20,7 @@ describe('hooks test', () => { }, { params: [undefined, undefined, true], - res: [true, 'anticon-close'], + res: [true, '.anticon-close'], }, { params: [undefined, undefined, false], @@ -33,11 +34,11 @@ describe('hooks test', () => { }, { params: [true, undefined, true], - res: [true, 'anticon-close'], + res: [true, '.anticon-close'], }, { params: [true, undefined, false], - res: [true, 'anticon-close'], + res: [true, '.anticon-close'], }, // test case like: @@ -51,19 +52,19 @@ describe('hooks test', () => { }, { params: [true, null, true], - res: [true, 'anticon-close'], + res: [true, '.anticon-close'], }, { params: [true, false, true], - res: [true, 'anticon-close'], + res: [true, '.anticon-close'], }, { params: [true, null, false], - res: [true, 'anticon-close'], + res: [true, '.anticon-close'], }, { params: [true, false, false], - res: [true, 'anticon-close'], + res: [true, '.anticon-close'], }, { params: [ @@ -73,14 +74,14 @@ describe('hooks test', () => {
, false, ], - res: [true, 'custom-close'], + res: [true, '.custom-close'], }, { params: [false,
close
, false], res: [false, ''], }, - // test case like: + // test case like: { params: [undefined, null, undefined], res: [false, ''], @@ -89,6 +90,10 @@ describe('hooks test', () => { params: [undefined, false, undefined], res: [false, ''], }, + { + params: [undefined, true, undefined], + res: [true, '.anticon-close'], + }, { params: [ undefined, @@ -97,7 +102,7 @@ describe('hooks test', () => { , undefined, ], - res: [true, 'custom-close'], + res: [true, '.custom-close'], }, { params: [ @@ -107,7 +112,7 @@ describe('hooks test', () => { , true, ], - res: [true, 'custom-close'], + res: [true, '.custom-close'], }, { params: [ @@ -117,7 +122,18 @@ describe('hooks test', () => { , false, ], - res: [true, 'custom-close'], + res: [true, '.custom-close'], + }, + { + params: [ + { + closeIcon: 'Close', + 'aria-label': 'Close Btn', + }, + undefined, + false, + ], + res: [true, '*[aria-label="Close Btn"]'], }, ]; @@ -127,11 +143,14 @@ describe('hooks test', () => { },defaultClosable=${params[2]}. the result should be ${res}`, () => { const App = () => { const [closable, closeIcon] = useClosable( - params[0], - params[1], - undefined, - undefined, - params[2], + { + closable: params[0], + closeIcon: params[1], + }, + null, + { + closable: params[2], + }, ); useEffect(() => { expect(closable).toBe(res[0]); @@ -142,7 +161,7 @@ describe('hooks test', () => { if (res[1] === '') { expect(container.querySelector('.anticon-close')).toBeFalsy(); } else { - expect(container.querySelector(`.${res[1]}`)).toBeTruthy(); + expect(container.querySelector(`${res[1]}`)).toBeTruthy(); } }); }); @@ -150,10 +169,13 @@ describe('hooks test', () => { it('useClosable with defaultCloseIcon', () => { const App = () => { const [closable, closeIcon] = useClosable( - true, - undefined, - undefined, - , + { + closable: true, + }, + null, + { + closeIcon: , + }, ); useEffect(() => { expect(closable).toBe(true); @@ -163,13 +185,37 @@ describe('hooks test', () => { const { container } = render(); expect(container.querySelector('.custom-close-icon')).toBeTruthy(); }); + it('useClosable without defaultCloseIcon', () => { + const App = () => { + const [closable, closeIcon] = useClosable( + { + closable: true, + }, + null, + ); + useEffect(() => { + expect(closable).toBe(true); + }, [closable]); + return
hooks test {closeIcon}
; + }; + const { container } = render(); + expect(container.querySelector('.anticon-close')).toBeTruthy(); + }); it('useClosable with customCloseIconRender', () => { const App = () => { const customCloseIconRender = (icon: React.ReactNode) => ( {icon} ); - const [closable, closeIcon] = useClosable(true, undefined, customCloseIconRender); + const [closable, closeIcon] = useClosable( + { + closable: true, + }, + null, + { + closeIconRender: customCloseIconRender, + }, + ); useEffect(() => { expect(closable).toBe(true); }, [closable]); diff --git a/packages/meta/src/_util/__tests__/reactNode.test.tsx b/packages/meta/src/_util/__tests__/reactNode.test.tsx index dc2cad7..b56c3e9 100644 --- a/packages/meta/src/_util/__tests__/reactNode.test.tsx +++ b/packages/meta/src/_util/__tests__/reactNode.test.tsx @@ -1,11 +1,8 @@ import React from 'react'; -import { isValidElement, cloneElement, isFragment, replaceElement } from '../reactNode'; + +import { cloneElement, isFragment, replaceElement } from '../reactNode'; describe('reactNode test', () => { - it('isValidElement', () => { - expect(isValidElement(null)).toBe(false); - expect(isValidElement(

test

)).toBe(true); - }); it('isFragment', () => { expect(isFragment(

test

)).toBe(false); expect(isFragment(<>test)).toBe(true); diff --git a/packages/meta/src/_util/__tests__/responsiveObserve.test.tsx b/packages/meta/src/_util/__tests__/responsiveObserve.test.tsx index d88c5ea..effc257 100644 --- a/packages/meta/src/_util/__tests__/responsiveObserve.test.tsx +++ b/packages/meta/src/_util/__tests__/responsiveObserve.test.tsx @@ -1,4 +1,5 @@ import React from 'react'; + import { render } from '../../../tests/utils'; import useResponsiveObserver from '../responsiveObserver'; diff --git a/packages/meta/src/_util/__tests__/transButton.test.tsx b/packages/meta/src/_util/__tests__/transButton.test.tsx index 6f1fef1..41806b8 100644 --- a/packages/meta/src/_util/__tests__/transButton.test.tsx +++ b/packages/meta/src/_util/__tests__/transButton.test.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import TransButton from '../transButton'; + import { render } from '../../../tests/utils'; +import TransButton from '../transButton'; describe('transButton component', () => { it('disabled should update style', () => { diff --git a/packages/meta/src/_util/__tests__/type.test.tsx b/packages/meta/src/_util/__tests__/type.test.tsx new file mode 100644 index 0000000..4b99b9c --- /dev/null +++ b/packages/meta/src/_util/__tests__/type.test.tsx @@ -0,0 +1,105 @@ +import * as React from 'react'; + +import type { GetProp, GetProps, GetRef } from '../type'; + +describe('type', () => { + class CC extends React.Component<{ bamboo?: number }> { + getBamboo() { + return this.props.bamboo; + } + + render() { + return this.props.bamboo; + } + } + + interface TestRef { + nativeElement: HTMLDivElement; + } + + const RefFC = React.forwardRef((props, ref) => { + const eleRef = React.useRef(null); + + React.useImperativeHandle(ref, () => ({ + nativeElement: eleRef.current!, + })); + + return
{props.bamboo}
; + }); + + describe('GetProps', () => { + it('FC', () => { + const FC = (props: { bamboo: number }) => props.bamboo; + type Props = GetProps; + const props: Props = { bamboo: 123 }; + + expect(props).toBeTruthy(); + }); + + it('CC', () => { + type Props = GetProps; + const props: Props = { bamboo: 123 }; + + expect(props).toBeTruthy(); + }); + + it('RefFc', () => { + type Props = GetProps; + const props: Props = { bamboo: 123 }; + + expect(props).toBeTruthy(); + }); + }); + + describe('GetRef', () => { + it('CC', () => { + type Ref = GetRef; + const ref = React.createRef(); + + expect().toBeTruthy(); + }); + + it('RefFC', () => { + type Ref = GetRef; + const ref = React.createRef(); + + expect().toBeTruthy(); + }); + + it('Support ForwardRefExoticComponent type', () => { + interface InnerProps { + test: number; + } + interface InnerRef { + bamboo: number; + } + type TestComponent = React.ForwardRefExoticComponent< + InnerProps & React.RefAttributes + >; + type ExtractedTestRef = GetRef; + + const a: ExtractedTestRef = { bamboo: 123 }; + expect(a).toBeTruthy(); + }); + }); + + describe('GetProp', () => { + it('optional', () => { + const Optional = (props: { list?: { bamboo: string }[] }) => props.list?.length; + type ListItemType = GetProp[number]; + + const item: ListItemType = { bamboo: '123' }; + expect(item).toBeTruthy(); + }); + + it('interface directly', () => { + interface Props { + bamboo: number; + } + + type BambooType = GetProp; + const bamboo: BambooType = 123; + expect(bamboo).toBeTruthy(); + }); + }); +}); diff --git a/packages/meta/src/_util/__tests__/useSyncState.test.tsx b/packages/meta/src/_util/__tests__/useSyncState.test.tsx index b0c0d96..3ba9241 100644 --- a/packages/meta/src/_util/__tests__/useSyncState.test.tsx +++ b/packages/meta/src/_util/__tests__/useSyncState.test.tsx @@ -1,6 +1,7 @@ import React from 'react'; + +import { fireEvent, render } from '../../../tests/utils'; import useSyncState from '../hooks/useSyncState'; -import { render, fireEvent } from '../../../tests/utils'; describe('Table', () => { it('useSyncState', () => { diff --git a/packages/meta/src/_util/__tests__/util.test.tsx b/packages/meta/src/_util/__tests__/util.test.tsx index 6b80428..8fef3c6 100644 --- a/packages/meta/src/_util/__tests__/util.test.tsx +++ b/packages/meta/src/_util/__tests__/util.test.tsx @@ -1,6 +1,7 @@ /* eslint-disable class-methods-use-this */ -import KeyCode from 'rc-util/lib/KeyCode'; import React from 'react'; +import KeyCode from 'rc-util/lib/KeyCode'; + import { fireEvent, render, waitFakeTimer } from '../../../tests/utils'; import { isStyleSupport } from '../styleChecker'; import throttleByAnimationFrame from '../throttleByAnimationFrame'; diff --git a/packages/meta/src/_util/__tests__/warning.test.tsx b/packages/meta/src/_util/__tests__/warning.test.tsx index 9c85ae4..2772592 100644 --- a/packages/meta/src/_util/__tests__/warning.test.tsx +++ b/packages/meta/src/_util/__tests__/warning.test.tsx @@ -1,5 +1,6 @@ -import { render } from '@testing-library/react'; import React from 'react'; +import { render } from '@testing-library/react'; + import { devUseWarning as useWarning } from '../warning'; describe('Test warning', () => { diff --git a/packages/meta/src/_util/__tests__/wave.test.tsx b/packages/meta/src/_util/__tests__/wave.test.tsx index 0f6bd7e..b21f4bf 100644 --- a/packages/meta/src/_util/__tests__/wave.test.tsx +++ b/packages/meta/src/_util/__tests__/wave.test.tsx @@ -1,10 +1,11 @@ import React from 'react'; import classNames from 'classnames'; + import mountTest from '../../../tests/shared/mountTest'; import { act, fireEvent, getByText, render, waitFakeTimer } from '../../../tests/utils'; +import Checkbox from '../../checkbox'; import Wave from '../wave'; import { TARGET_CLS } from '../wave/interface'; -import Checkbox from '../../checkbox'; (global as any).isVisible = true; @@ -79,6 +80,7 @@ describe('Wave component', () => { } it('work', async () => { + const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const { container, unmount } = render( @@ -94,6 +96,8 @@ describe('Wave component', () => { expect(document.querySelector('.ant-wave')).toBeFalsy(); + expect(errorSpy).not.toHaveBeenCalled(); + unmount(); }); diff --git a/packages/meta/src/_util/aria-data-attrs.ts b/packages/meta/src/_util/aria-data-attrs.ts new file mode 100644 index 0000000..e5e4c08 --- /dev/null +++ b/packages/meta/src/_util/aria-data-attrs.ts @@ -0,0 +1,5 @@ +import type * as React from 'react'; + +export type HTMLAriaDataAttributes = React.AriaAttributes & { + [key: `data-${string}`]: unknown; +} & Pick, 'role'>; diff --git a/packages/meta/src/_util/colors.ts b/packages/meta/src/_util/colors.ts index 5c21c66..5fe27ca 100644 --- a/packages/meta/src/_util/colors.ts +++ b/packages/meta/src/_util/colors.ts @@ -14,7 +14,7 @@ export const PresetStatusColorTypes = [ export type PresetColorType = PresetColorKey | InverseColor; -export type PresetStatusColorType = typeof PresetStatusColorTypes[number]; +export type PresetStatusColorType = (typeof PresetStatusColorTypes)[number]; /** * determine if the color keyword belongs to the `Ant Design` {@link PresetColors}. diff --git a/packages/meta/src/_util/getAllowClear.tsx b/packages/meta/src/_util/getAllowClear.tsx new file mode 100644 index 0000000..3bde548 --- /dev/null +++ b/packages/meta/src/_util/getAllowClear.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled'; +import type { BaseInputProps } from 'rc-input/lib/interface'; + +export type AllowClear = BaseInputProps['allowClear']; + +const getAllowClear = (allowClear: AllowClear): AllowClear => { + let mergedAllowClear: AllowClear; + if (typeof allowClear === 'object' && allowClear?.clearIcon) { + mergedAllowClear = allowClear; + } else if (allowClear) { + mergedAllowClear = { + clearIcon: , + }; + } + + return mergedAllowClear; +}; + +export default getAllowClear; diff --git a/packages/meta/src/_util/hooks/useClosable.tsx b/packages/meta/src/_util/hooks/useClosable.tsx index d6fc240..f917221 100644 --- a/packages/meta/src/_util/hooks/useClosable.tsx +++ b/packages/meta/src/_util/hooks/useClosable.tsx @@ -1,43 +1,176 @@ -import CloseOutlined from '@ant-design/icons/CloseOutlined'; import type { ReactNode } from 'react'; import React from 'react'; +import CloseOutlined from '@ant-design/icons/CloseOutlined'; +import pickAttrs from 'rc-util/lib/pickAttrs'; -function useInnerClosable( - closable?: boolean, - closeIcon?: boolean | ReactNode, - defaultClosable?: boolean, -): boolean { - if (typeof closable === 'boolean') { - return closable; +export type BaseClosableType = { closeIcon?: React.ReactNode } & React.AriaAttributes; +export type ClosableType = boolean | BaseClosableType; + +export type ContextClosable = + Partial>; + +export function pickClosable( + context?: ContextClosable, +): ContextClosable | undefined { + if (!context) { + return undefined; } - if (closeIcon === undefined) { - return !!defaultClosable; - } - return closeIcon !== false && closeIcon !== null; + return { + closable: context.closable, + closeIcon: context.closeIcon, + }; } export type UseClosableParams = { - closable?: boolean; - closeIcon?: boolean | ReactNode; + closable?: ClosableType; + closeIcon?: ReactNode; defaultClosable?: boolean; defaultCloseIcon?: ReactNode; customCloseIconRender?: (closeIcon: ReactNode) => ReactNode; + context?: ContextClosable; }; -export default function useClosable( - closable?: boolean, - closeIcon?: boolean | ReactNode, - customCloseIconRender?: (closeIcon: ReactNode) => ReactNode, - defaultCloseIcon: ReactNode = , - defaultClosable = false, -): [closable: boolean, closeIcon: React.ReactNode | null] { - const mergedClosable = useInnerClosable(closable, closeIcon, defaultClosable); - if (!mergedClosable) { - return [false, null]; - } - const mergedCloseIcon = - typeof closeIcon === 'boolean' || closeIcon === undefined || closeIcon === null - ? defaultCloseIcon - : closeIcon; - return [true, customCloseIconRender ? customCloseIconRender(mergedCloseIcon) : mergedCloseIcon]; +/** Convert `closable` and `closeIcon` to config object */ +function useClosableConfig(closableCollection?: ClosableCollection | null) { + const { closable, closeIcon } = closableCollection || {}; + + return React.useMemo(() => { + if ( + // If `closable`, whatever rest be should be true + !closable && + (closable === false || closeIcon === false || closeIcon === null) + ) { + return false; + } + + if (closable === undefined && closeIcon === undefined) { + return null; + } + + let closableConfig: BaseClosableType = { + closeIcon: typeof closeIcon !== 'boolean' && closeIcon !== null ? closeIcon : undefined, + }; + if (closable && typeof closable === 'object') { + closableConfig = { + ...closableConfig, + ...closable, + }; + } + + return closableConfig; + }, [closable, closeIcon]); +} + +/** + * Assign object without `undefined` field. Will skip if is `false`. + * This helps to handle both closableConfig or false + */ +function assignWithoutUndefined( + ...objList: (Partial | false | null | undefined)[] +): Partial { + const target: Partial = {}; + + objList.forEach((obj) => { + if (obj) { + (Object.keys(obj) as (keyof T)[]).forEach((key) => { + if (obj[key] !== undefined) { + target[key] = obj[key]; + } + }); + } + }); + + return target; +} + +/** Collection contains the all the props related with closable. e.g. `closable`, `closeIcon` */ +interface ClosableCollection { + closable?: ClosableType; + closeIcon?: ReactNode; +} + +/** Use same object to support `useMemo` optimization */ +const EmptyFallbackCloseCollection: ClosableCollection = {}; + +export default function useClosable( + propCloseCollection?: ClosableCollection, + contextCloseCollection?: ClosableCollection | null, + fallbackCloseCollection: ClosableCollection & { + /** + * Some components need to wrap CloseIcon twice, + * this method will be executed once after the final CloseIcon is calculated + */ + closeIconRender?: (closeIcon: ReactNode) => ReactNode; + } = EmptyFallbackCloseCollection, +): [closable: boolean, closeIcon: React.ReactNode | null] { + // Align the `props`, `context` `fallback` to config object first + const propCloseConfig = useClosableConfig(propCloseCollection); + const contextCloseConfig = useClosableConfig(contextCloseCollection); + const mergedFallbackCloseCollection = React.useMemo( + () => ({ + closeIcon: , + ...fallbackCloseCollection, + }), + [fallbackCloseCollection], + ); + + // Use fallback logic to fill the config + const mergedClosableConfig = React.useMemo(() => { + // ================ Props First ================ + // Skip if prop is disabled + if (propCloseConfig === false) { + return false; + } + + if (propCloseConfig) { + return assignWithoutUndefined( + mergedFallbackCloseCollection, + contextCloseConfig, + propCloseConfig, + ); + } + + // =============== Context Second ============== + // Skip if context is disabled + if (contextCloseConfig === false) { + return false; + } + + if (contextCloseConfig) { + return assignWithoutUndefined(mergedFallbackCloseCollection, contextCloseConfig); + } + + // ============= Fallback Default ============== + return !mergedFallbackCloseCollection.closable ? false : mergedFallbackCloseCollection; + }, [propCloseConfig, contextCloseConfig, mergedFallbackCloseCollection]); + + // Calculate the final closeIcon + return React.useMemo(() => { + if (mergedClosableConfig === false) { + return [false, null]; + } + + const { closeIconRender } = mergedFallbackCloseCollection; + const { closeIcon } = mergedClosableConfig; + + let mergedCloseIcon: ReactNode = closeIcon; + if (mergedCloseIcon !== null && mergedCloseIcon !== undefined) { + // Wrap the closeIcon if needed + if (closeIconRender) { + mergedCloseIcon = closeIconRender(closeIcon); + } + + // Wrap the closeIcon with aria props + const ariaProps = pickAttrs(mergedClosableConfig, true); + if (Object.keys(ariaProps).length) { + mergedCloseIcon = React.isValidElement(mergedCloseIcon) ? ( + React.cloneElement(mergedCloseIcon, ariaProps) + ) : ( + {mergedCloseIcon} + ); + } + } + + return [true, mergedCloseIcon]; + }, [mergedClosableConfig, mergedFallbackCloseCollection]); } diff --git a/packages/meta/src/_util/hooks/useProxyImperativeHandle.ts b/packages/meta/src/_util/hooks/useProxyImperativeHandle.ts index 849630c..18691e8 100644 --- a/packages/meta/src/_util/hooks/useProxyImperativeHandle.ts +++ b/packages/meta/src/_util/hooks/useProxyImperativeHandle.ts @@ -1,7 +1,8 @@ // Proxy the dom ref with `{ nativeElement, otherFn }` type // ref: https://github.com/ant-design/ant-design/discussions/45242 -import { useImperativeHandle, type Ref } from 'react'; +import { useImperativeHandle } from 'react'; +import type { Ref } from 'react'; function fillProxy( element: HTMLElement & { _antProxy?: Record }, diff --git a/packages/meta/src/_util/index.zh-CN.md b/packages/meta/src/_util/index.zh-CN.md new file mode 100644 index 0000000..0e7efe7 --- /dev/null +++ b/packages/meta/src/_util/index.zh-CN.md @@ -0,0 +1,49 @@ +--- +category: Components +title: Util 工具类 +subtitle: 工具类 +description: 辅助开发,提供一些常用的工具方法。 +showImport: false +demo: + cols: 2 +group: + title: 其他 + order: 99 +--- + +自 `5.13.0` 版本开始提供这些方法。 + +## GetRef + +获取组件的 `ref` 属性定义,这对于未直接暴露或者子组件的 `ref` 属性定义非常有用。 + +```ts +import { Select } from 'antd'; +import type { GetRef } from 'antd'; + +type SelectRefType = GetRef; // BaseSelectRef +``` + +## GetProps + +获取组件的 `props` 属性定义: + +```ts +import { Checkbox } from 'antd'; +import type { GetProps } from 'antd'; + +type CheckboxGroupType = GetProps; +``` + +## GetProp + +获取组件的单个 `props` 属性定义。它已经将 `NonNullable` 进行了封装,所以不用在考虑为空的情况: + +```ts +import { Select } from 'antd'; +import type { GetProp, SelectProps } from 'antd'; + +// 以下两种都可以生效 +type SelectOptionType1 = GetProp[number]; +type SelectOptionType2 = GetProp[number]; +``` diff --git a/packages/meta/src/_util/motion.ts b/packages/meta/src/_util/motion.ts index 7156f26..474ccc8 100644 --- a/packages/meta/src/_util/motion.ts +++ b/packages/meta/src/_util/motion.ts @@ -27,7 +27,7 @@ const initCollapseMotion = (rootCls: string = 'ant'): CSSMotionProps => ({ const SelectPlacements = ['bottomLeft', 'bottomRight', 'topLeft', 'topRight'] as const; -export type SelectCommonPlacement = typeof SelectPlacements[number]; +export type SelectCommonPlacement = (typeof SelectPlacements)[number]; const getTransitionName = (rootPrefixCls: string, motion: string, transitionName?: string) => { if (transitionName !== undefined) { diff --git a/packages/meta/src/_util/reactNode.ts b/packages/meta/src/_util/reactNode.ts index bb4e703..aafedf5 100644 --- a/packages/meta/src/_util/reactNode.ts +++ b/packages/meta/src/_util/reactNode.ts @@ -1,28 +1,27 @@ -import * as React from 'react'; +import React from 'react'; + import type { AnyObject } from './type'; -export const { isValidElement } = React; - export function isFragment(child: any): boolean { - return child && isValidElement(child) && child.type === React.Fragment; + return child && React.isValidElement(child) && child.type === React.Fragment; } type RenderProps = AnyObject | ((originProps: AnyObject) => AnyObject | void); -export function replaceElement( +export const replaceElement =

( element: React.ReactNode, replacement: React.ReactNode, props?: RenderProps, -): React.ReactNode { - if (!isValidElement(element)) { +) => { + if (!React.isValidElement

(element)) { return replacement; } - return React.cloneElement( + return React.cloneElement

( element, typeof props === 'function' ? props(element.props || {}) : props, ); -} +}; -export function cloneElement(element: React.ReactNode, props?: RenderProps): React.ReactElement { - return replaceElement(element, element, props) as React.ReactElement; +export function cloneElement

(element: React.ReactNode, props?: RenderProps) { + return replaceElement

(element, element, props) as React.ReactElement; } diff --git a/packages/meta/src/_util/responsiveObserver.ts b/packages/meta/src/_util/responsiveObserver.ts index dcf4d04..26a487f 100644 --- a/packages/meta/src/_util/responsiveObserver.ts +++ b/packages/meta/src/_util/responsiveObserver.ts @@ -95,18 +95,16 @@ export default function useResponsiveObserver() { if (!subscribers.size) this.unregister(); }, unregister() { - // @ts-ignore - Object.keys(responsiveMap).forEach((screen: Breakpoint) => { - const matchMediaQuery = responsiveMap[screen]; + Object.keys(responsiveMap).forEach((screen) => { + const matchMediaQuery = responsiveMap[screen as Breakpoint]; const handler = this.matchHandlers[matchMediaQuery]; handler?.mql.removeListener(handler?.listener); }); subscribers.clear(); }, register() { - // @ts-ignore - Object.keys(responsiveMap).forEach((screen: Breakpoint) => { - const matchMediaQuery = responsiveMap[screen]; + Object.keys(responsiveMap).forEach((screen) => { + const matchMediaQuery = responsiveMap[screen as Breakpoint]; const listener = ({ matches }: { matches: boolean }) => { this.dispatch({ ...screens, diff --git a/packages/meta/src/_util/scrollTo.ts b/packages/meta/src/_util/scrollTo.ts index fb6141c..e0fcda9 100644 --- a/packages/meta/src/_util/scrollTo.ts +++ b/packages/meta/src/_util/scrollTo.ts @@ -1,4 +1,5 @@ import raf from 'rc-util/lib/raf'; + import { easeInOutCubic } from './easings'; import getScroll, { isWindow } from './getScroll'; diff --git a/packages/meta/src/_util/statusUtils.ts b/packages/meta/src/_util/statusUtils.ts index 08358b6..43113b3 100644 --- a/packages/meta/src/_util/statusUtils.ts +++ b/packages/meta/src/_util/statusUtils.ts @@ -1,9 +1,10 @@ import classNames from 'classnames'; + import type { ValidateStatus } from '../form/FormItem'; const InputStatuses = ['warning', 'error', ''] as const; -export type InputStatus = typeof InputStatuses[number]; +export type InputStatus = (typeof InputStatuses)[number]; export function getStatusClassNames( prefixCls: string, diff --git a/packages/meta/src/_util/transButton.tsx b/packages/meta/src/_util/transButton.tsx index 73a9f99..a62dcd0 100644 --- a/packages/meta/src/_util/transButton.tsx +++ b/packages/meta/src/_util/transButton.tsx @@ -3,14 +3,15 @@ * * This helps accessibility reader to tread as a interactive button to operation. */ -import KeyCode from 'rc-util/lib/KeyCode'; import * as React from 'react'; +import KeyCode from 'rc-util/lib/KeyCode'; interface TransButtonProps extends React.HTMLAttributes { - onClick?: (e?: React.MouseEvent) => void; + onClick?: (e?: React.MouseEvent) => void; noStyle?: boolean; autoFocus?: boolean; disabled?: boolean; + tabIndex?: number; } const inlineStyle: React.CSSProperties = { @@ -37,7 +38,7 @@ const TransButton = React.forwardRef((props, r } }; - const { style, noStyle, disabled, ...restProps } = props; + const { style, noStyle, disabled, tabIndex = 0, ...restProps } = props; let mergedStyle: React.CSSProperties = {}; @@ -59,7 +60,7 @@ const TransButton = React.forwardRef((props, r return (

{ - const map = new Map(); +import type { TransferKey } from '../transfer/interface'; + +export const groupKeysMap = (keys: TransferKey[]) => { + const map = new Map(); keys.forEach((key, index) => { map.set(key, index); }); @@ -7,7 +9,7 @@ export const groupKeysMap = (keys: string[]) => { }; export const groupDisabledKeysMap = (dataSource: RecordType) => { - const map = new Map(); + const map = new Map(); dataSource.forEach(({ disabled, key }, index) => { if (disabled) { map.set(key, index); diff --git a/packages/meta/src/_util/type.ts b/packages/meta/src/_util/type.ts index 25115ca..074ebdc 100644 --- a/packages/meta/src/_util/type.ts +++ b/packages/meta/src/_util/type.ts @@ -1,6 +1,34 @@ +import type React from 'react'; + /** https://github.com/Microsoft/TypeScript/issues/29729 */ export type LiteralUnion = T | (string & {}); export type AnyObject = Record; export type CustomComponent

= React.ComponentType

| string; + +export type GetProps | object> = T extends React.ComponentType< + infer P +> + ? P + : T extends object + ? T + : never; + +export type GetProp< + T extends React.ComponentType | object, + PropName extends keyof GetProps, +> = NonNullable[PropName]>; + +type ReactRefComponent | string }> = ( + props: Props, +) => React.ReactNode; + +type ExtractRefAttributesRef = T extends React.RefAttributes ? P : never; + +export type GetRef | React.Component> = + T extends React.Component + ? T + : T extends React.ComponentType + ? ExtractRefAttributesRef

+ : never; diff --git a/packages/meta/src/_util/warning.ts b/packages/meta/src/_util/warning.ts index 0c3688f..0d226cc 100644 --- a/packages/meta/src/_util/warning.ts +++ b/packages/meta/src/_util/warning.ts @@ -41,6 +41,11 @@ type TypeWarning = BaseTypeWarning & { }; export interface WarningContextProps { + /** + * @descCN 设置警告等级,设置 `false` 时会将废弃相关信息聚合为单条信息。 + * @descEN Set the warning level. When set to `false`, discard related information will be aggregated into a single message. + * @since 5.10.0 + */ strict?: boolean; } diff --git a/packages/meta/src/_util/wave/WaveEffect.tsx b/packages/meta/src/_util/wave/WaveEffect.tsx index a58a732..ad44e4a 100644 --- a/packages/meta/src/_util/wave/WaveEffect.tsx +++ b/packages/meta/src/_util/wave/WaveEffect.tsx @@ -1,10 +1,13 @@ +import * as React from 'react'; import classNames from 'classnames'; import CSSMotion from 'rc-motion'; -import { render, unmount } from 'rc-util/lib/React/render'; import raf from 'rc-util/lib/raf'; -import * as React from 'react'; +import { render, unmount } from 'rc-util/lib/React/render'; +import { composeRef } from 'rc-util/lib/ref'; + +import { TARGET_CLS } from './interface'; +import type { ShowWaveEffect } from './interface'; import { getTargetWaveColor } from './util'; -import { type ShowWaveEffect, TARGET_CLS } from './interface'; function validateNum(value: number) { return Number.isNaN(value) ? 0 : value; @@ -18,7 +21,7 @@ export interface WaveEffectProps { const WaveEffect: React.FC = (props) => { const { className, target, component } = props; - const divRef = React.useRef(null); + const divRef = React.useRef(null); const [color, setWaveColor] = React.useState(null); const [borderRadius, setBorderRadius] = React.useState([]); @@ -123,16 +126,10 @@ const WaveEffect: React.FC = (props) => { return false; }} > - {({ className: motionClassName }) => ( + {({ className: motionClassName }, ref) => (

)} diff --git a/packages/meta/src/_util/wave/index.ts b/packages/meta/src/_util/wave/index.ts index 24bf37a..5b4f4a5 100644 --- a/packages/meta/src/_util/wave/index.ts +++ b/packages/meta/src/_util/wave/index.ts @@ -1,7 +1,8 @@ -import classNames from 'classnames'; -import { composeRef, supportRef } from 'rc-util/lib/ref'; -import isVisible from 'rc-util/lib/Dom/isVisible'; import React, { useContext, useRef } from 'react'; +import classNames from 'classnames'; +import isVisible from 'rc-util/lib/Dom/isVisible'; +import { composeRef, supportRef } from 'rc-util/lib/ref'; + import type { ConfigConsumerProps } from '../../config-provider'; import { ConfigContext } from '../../config-provider'; import { cloneElement } from '../reactNode'; @@ -11,7 +12,7 @@ import useWave from './useWave'; export interface WaveProps { disabled?: boolean; children?: React.ReactNode; - component?: string; + component?: 'Tag' | 'Button' | 'Checkbox' | 'Radio' | 'Switch'; } const Wave: React.FC = (props) => { @@ -47,7 +48,6 @@ const Wave: React.FC = (props) => { ) { return; } - showWave(e); }; @@ -60,7 +60,7 @@ const Wave: React.FC = (props) => { // ============================== Render ============================== if (!React.isValidElement(children)) { - return (children ?? null) as unknown as React.ReactElement; + return children ?? null; } const ref = supportRef(children) ? composeRef((children as any).ref, containerRef) : containerRef; diff --git a/packages/meta/src/_util/wave/style.ts b/packages/meta/src/_util/wave/style.ts index 140e697..6bc8ce9 100644 --- a/packages/meta/src/_util/wave/style.ts +++ b/packages/meta/src/_util/wave/style.ts @@ -29,11 +29,10 @@ const genWaveStyle: GenerateStyle = (token) => { boxShadow: `0 0 0 6px currentcolor`, opacity: 0, }, - '&.wave-quick': { transition: [ - `box-shadow 0.3s ${token.motionEaseInOut}`, - `opacity 0.35s ${token.motionEaseInOut}`, + `box-shadow ${token.motionDurationSlow} ${token.motionEaseInOut}`, + `opacity ${token.motionDurationSlow} ${token.motionEaseInOut}`, ].join(','), }, }, diff --git a/packages/meta/src/_util/wave/useWave.ts b/packages/meta/src/_util/wave/useWave.ts index 24bee62..5746967 100644 --- a/packages/meta/src/_util/wave/useWave.ts +++ b/packages/meta/src/_util/wave/useWave.ts @@ -1,16 +1,18 @@ import * as React from 'react'; import { useEvent } from 'rc-util'; import raf from 'rc-util/lib/raf'; -import showWaveEffect from './WaveEffect'; + import { ConfigContext } from '../../config-provider'; import useToken from '../../theme/useToken'; -import { TARGET_CLS, type ShowWave } from './interface'; +import { TARGET_CLS } from './interface'; +import type { ShowWave } from './interface'; +import showWaveEffect from './WaveEffect'; -export default function useWave( +const useWave = ( nodeRef: React.RefObject, className: string, - component?: string, -) { + component?: 'Tag' | 'Button' | 'Checkbox' | 'Radio' | 'Switch', +) => { const { wave } = React.useContext(ConfigContext); const [, token, hashId] = useToken(); @@ -41,4 +43,6 @@ export default function useWave( }; return showDebounceWave; -} +}; + +export default useWave; diff --git a/packages/meta/src/date-picker/style/index.ts b/packages/meta/src/date-picker/style/index.ts index 98d2098..abb3caf 100644 --- a/packages/meta/src/date-picker/style/index.ts +++ b/packages/meta/src/date-picker/style/index.ts @@ -6,10 +6,10 @@ import type { SharedComponentToken, SharedInputToken } from '../../input/style'; import { genActiveStyle, genBasicInputStyle, - genHoverStyle, initComponentToken, initInputToken, } from '../../input/style'; +import { genHoverStyle } from '../../input/style/variants' import { resetComponent, textEllipsis } from '../../style'; import { genCompactItemStyle } from '../../style/compact-item'; import { diff --git a/packages/meta/src/dropdown/__tests__/__snapshots__/demo-extend.test.ts.snap b/packages/meta/src/dropdown/__tests__/__snapshots__/demo-extend.test.ts.snap new file mode 100644 index 0000000..899a1f6 --- /dev/null +++ b/packages/meta/src/dropdown/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -0,0 +1,7150 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders components/dropdown/demo/arrow.tsx extend context correctly 1`] = ` +
+
+
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+
+
+
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+
+
+`; + +exports[`renders components/dropdown/demo/arrow.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/arrow-center.tsx extend context correctly 1`] = ` +
+
+
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+
+
+
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+
+
+`; + +exports[`renders components/dropdown/demo/arrow-center.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/basic.tsx extend context correctly 1`] = ` +Array [ + +
+
+ Hover me +
+
+ + + +
+
+
, +
+ + , +] +`; + +exports[`renders components/dropdown/demo/basic.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/context-menu.tsx extend context correctly 1`] = ` +Array [ +
+ Right Click on here +
, +
+ + , +] +`; + +exports[`renders components/dropdown/demo/context-menu.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/custom-dropdown.tsx extend context correctly 1`] = ` +Array [ + +
+
+ Hover me +
+
+ + + +
+
+
, +
+
+ + , +] +`; + +exports[`renders components/dropdown/demo/custom-dropdown.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/dropdown-button.tsx extend context correctly 1`] = ` +
+
+
+ + +
+ + +
+
+
+
+ + +
+ + +
+
+
+
+ + +
+ + +
+
+
+
+ +
+
+
+ +
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ + +
+ + +
+
+
+`; + +exports[`renders components/dropdown/demo/dropdown-button.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/event.tsx extend context correctly 1`] = ` +Array [ + +
+
+ Hover me, Click menu item +
+
+ + + +
+
+
, +
+ + , +] +`; + +exports[`renders components/dropdown/demo/event.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/icon-debug.tsx extend context correctly 1`] = ` +
+
+
+ + +
+
+
+
+`; + +exports[`renders components/dropdown/demo/icon-debug.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/item.tsx extend context correctly 1`] = ` +Array [ + +
+
+ Hover me +
+
+ + + +
+
+
, +
+ + , +] +`; + +exports[`renders components/dropdown/demo/item.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/loading.tsx extend context correctly 1`] = ` +
+
+
+ + +
+ + +
+
+
+
+ + +
+ + +
+
+
+
+ + +
+ + +
+
+
+
+ + +
+ + +
+
+
+`; + +exports[`renders components/dropdown/demo/loading.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/menu-full.tsx extend context correctly 1`] = ` +Array [ + +
+
+ Hover to check menu style +
+
+ + + +
+
+
, +
+ + , +] +`; + +exports[`renders components/dropdown/demo/menu-full.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/overlay-open.tsx extend context correctly 1`] = ` +Array [ + +
+
+ Hover me +
+
+ + + +
+
+
, +
+ + , +] +`; + +exports[`renders components/dropdown/demo/overlay-open.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/placement.tsx extend context correctly 1`] = ` +
+
+
+
+ +
+ + +
+
+ +
+ + +
+
+ +
+ + +
+
+
+
+
+
+ +
+ + +
+
+ +
+ + +
+
+ +
+ + +
+
+
+
+`; + +exports[`renders components/dropdown/demo/placement.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/render-panel.tsx extend context correctly 1`] = ` +
+ +
+ + +
+`; + +exports[`renders components/dropdown/demo/render-panel.tsx extend context correctly 2`] = ` +[ + "Warning: [antd: Dropdown] \`visible\` is deprecated. Please use \`open\` instead.", +] +`; + +exports[`renders components/dropdown/demo/selectable.tsx extend context correctly 1`] = ` +Array [ + +
+
+ Selectable +
+
+ + + +
+
+
, +
+ + , +] +`; + +exports[`renders components/dropdown/demo/selectable.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/sub-menu.tsx extend context correctly 1`] = ` +Array [ + +
+
+ Cascading menu +
+
+ + + +
+
+
, +
+ + , +] +`; + +exports[`renders components/dropdown/demo/sub-menu.tsx extend context correctly 2`] = `[]`; + +exports[`renders components/dropdown/demo/trigger.tsx extend context correctly 1`] = ` +Array [ + +
+
+ Click me +
+
+ + + +
+
+
, +
+ + , +] +`; + +exports[`renders components/dropdown/demo/trigger.tsx extend context correctly 2`] = `[]`; diff --git a/packages/meta/src/dropdown/__tests__/__snapshots__/demo.test.tsx.snap b/packages/meta/src/dropdown/__tests__/__snapshots__/demo.test.tsx.snap new file mode 100644 index 0000000..2224fcd --- /dev/null +++ b/packages/meta/src/dropdown/__tests__/__snapshots__/demo.test.tsx.snap @@ -0,0 +1,1213 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders components/dropdown/demo/arrow.tsx correctly 1`] = ` +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+`; + +exports[`renders components/dropdown/demo/arrow-center.tsx correctly 1`] = ` +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+`; + +exports[`renders components/dropdown/demo/basic.tsx correctly 1`] = ` + +
+
+ Hover me +
+
+ + + +
+
+
+`; + +exports[`renders components/dropdown/demo/context-menu.tsx correctly 1`] = ` +
+ Right Click on here +
+`; + +exports[`renders components/dropdown/demo/custom-dropdown.tsx correctly 1`] = ` + +
+
+ Hover me +
+
+ + + +
+
+
+`; + +exports[`renders components/dropdown/demo/dropdown-button.tsx correctly 1`] = ` +
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+`; + +exports[`renders components/dropdown/demo/event.tsx correctly 1`] = ` + +
+
+ Hover me, Click menu item +
+
+ + + +
+
+
+`; + +exports[`renders components/dropdown/demo/icon-debug.tsx correctly 1`] = ` +
+
+
+ + +
+
+
+`; + +exports[`renders components/dropdown/demo/item.tsx correctly 1`] = ` + +
+
+ Hover me +
+
+ + + +
+
+
+`; + +exports[`renders components/dropdown/demo/loading.tsx correctly 1`] = ` +
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+`; + +exports[`renders components/dropdown/demo/menu-full.tsx correctly 1`] = ` + +
+
+ Hover to check menu style +
+
+ + + +
+
+
+`; + +exports[`renders components/dropdown/demo/overlay-open.tsx correctly 1`] = ` + +
+
+ Hover me +
+
+ + + +
+
+
+`; + +exports[`renders components/dropdown/demo/placement.tsx correctly 1`] = ` +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+`; + +exports[`renders components/dropdown/demo/render-panel.tsx correctly 1`] = ` +
+ +
+`; + +exports[`renders components/dropdown/demo/selectable.tsx correctly 1`] = ` + +
+
+ Selectable +
+
+ + + +
+
+
+`; + +exports[`renders components/dropdown/demo/sub-menu.tsx correctly 1`] = ` + +
+
+ Cascading menu +
+
+ + + +
+
+
+`; + +exports[`renders components/dropdown/demo/trigger.tsx correctly 1`] = ` + +
+
+ Click me +
+
+ + + +
+
+
+`; diff --git a/packages/meta/src/dropdown/__tests__/__snapshots__/dropdown-button.test.tsx.snap b/packages/meta/src/dropdown/__tests__/__snapshots__/dropdown-button.test.tsx.snap new file mode 100644 index 0000000..a6fd8e0 --- /dev/null +++ b/packages/meta/src/dropdown/__tests__/__snapshots__/dropdown-button.test.tsx.snap @@ -0,0 +1,80 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DropdownButton rtl render component should be rendered correctly in RTL direction 1`] = ` +
+ +
+`; + +exports[`DropdownButton should support href like Button 1`] = ` + +`; diff --git a/packages/meta/src/dropdown/__tests__/__snapshots__/index.test.tsx.snap b/packages/meta/src/dropdown/__tests__/__snapshots__/index.test.tsx.snap new file mode 100644 index 0000000..f856e9b --- /dev/null +++ b/packages/meta/src/dropdown/__tests__/__snapshots__/index.test.tsx.snap @@ -0,0 +1,91 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Dropdown overlay is function and has custom transitionName 1`] = ` +Array [ + , +
+
+ menu +
+
, +] +`; + +exports[`Dropdown overlay is string 1`] = ` +Array [ + , +
+ + string + +
, +] +`; + +exports[`Dropdown rtl render component should be rendered correctly in RTL direction 1`] = ` + +`; + +exports[`Dropdown should render custom dropdown correctly 1`] = ` +Array [ + , +
+
+ + +
, +] +`; diff --git a/packages/meta/src/dropdown/__tests__/demo-extend.test.ts b/packages/meta/src/dropdown/__tests__/demo-extend.test.ts new file mode 100644 index 0000000..c25f0f1 --- /dev/null +++ b/packages/meta/src/dropdown/__tests__/demo-extend.test.ts @@ -0,0 +1,5 @@ +import { extendTest } from '../../../tests/shared/demoTest'; + +extendTest('dropdown', { + skip: ['sub-menu-debug.tsx'], +}); diff --git a/packages/meta/src/dropdown/__tests__/demo.test.tsx b/packages/meta/src/dropdown/__tests__/demo.test.tsx new file mode 100644 index 0000000..8cdbcc9 --- /dev/null +++ b/packages/meta/src/dropdown/__tests__/demo.test.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; + +import demoTest, { rootPropsTest } from '../../../tests/shared/demoTest'; + +demoTest('dropdown', { + testRootProps: false, + skip: ['sub-menu-debug.tsx'], +}); + +rootPropsTest( + 'dropdown', + (Dropdown, props) => ( + +
+ + ), + { + findRootElements: () => document.querySelector('.ant-dropdown')!, + }, +); diff --git a/packages/meta/src/dropdown/__tests__/dropdown-button.test.tsx b/packages/meta/src/dropdown/__tests__/dropdown-button.test.tsx new file mode 100644 index 0000000..ec616c8 --- /dev/null +++ b/packages/meta/src/dropdown/__tests__/dropdown-button.test.tsx @@ -0,0 +1,173 @@ +import React from 'react'; + +import mountTest from '../../../tests/shared/mountTest'; +import rtlTest from '../../../tests/shared/rtlTest'; +import { render, waitFakeTimer } from '../../../tests/utils'; +import type { DropdownProps } from '../dropdown'; +import DropdownButton from '../dropdown-button'; + +let dropdownProps: DropdownProps; + +jest.mock('../dropdown', () => { + const ActualDropdown = jest.requireActual('../dropdown'); + const ActualDropdownComponent = ActualDropdown.default; + const h: typeof React = jest.requireActual('react'); + + const MockedDropdown: React.FC & { + Button: typeof ActualDropdownComponent.Button; + } = (props) => { + const clone: Record = {}; + Object.keys(props).forEach((key) => { + clone[key] = props[key as keyof typeof props]; + }); + + dropdownProps = clone; + const { children, ...restProps } = props; + return h.createElement(ActualDropdownComponent, { ...restProps }, children); + }; + MockedDropdown.Button = ActualDropdownComponent.Button; + + return { + ...ActualDropdown, + __esModule: true, + default: MockedDropdown, + }; +}); + +describe('DropdownButton', () => { + mountTest(DropdownButton); + rtlTest(DropdownButton); + + it('pass appropriate props to Dropdown', () => { + const items = [ + { + label: 'foo', + key: '1', + }, + ]; + + const props: DropdownProps = { + align: { + offset: [10, 20], + }, + menu: { items }, + disabled: false, + trigger: ['hover'], + open: true, + onOpenChange: () => {}, + }; + + const { rerender } = render(); + + (Object.keys(props) as (keyof DropdownProps)[]).forEach((key) => { + expect(dropdownProps[key]).toBe(props[key]); + }); + + rerender(); + expect(dropdownProps.open).toBe(true); + }); + + it("don't pass open to Dropdown if it's not exits", () => { + const items = [ + { + label: 'foo', + key: '1', + }, + ]; + render(); + expect('open' in dropdownProps).toBe(false); + }); + + it('should support href like Button', () => { + const items = [ + { + label: 'foo', + key: '1', + }, + ]; + const { asFragment } = render(); + expect(asFragment().firstChild).toMatchSnapshot(); + }); + + it('have static property for type detecting', () => { + expect(DropdownButton.__ANT_BUTTON).toBe(true); + }); + + it('should pass mouseEnterDelay and mouseLeaveDelay to Dropdown', () => { + const items = [ + { + label: 'foo', + key: '1', + }, + ]; + render(); + expect(dropdownProps.mouseEnterDelay).toBe(1); + expect(dropdownProps.mouseLeaveDelay).toBe(2); + }); + + it('should support overlayClassName and overlayStyle', () => { + const items = [ + { + label: 'foo', + key: '1', + }, + ]; + const { container } = render( + , + ); + expect(container.querySelector('.ant-dropdown')?.classList).toContain('className'); + expect((container.querySelector('.ant-dropdown') as HTMLElement).style.color).toContain('red'); + }); + + it('should support loading', () => { + const items = [ + { + label: 'foo', + key: '1', + }, + ]; + const { container } = render(); + + expect(container.querySelector('.ant-dropdown-button .ant-btn-loading')?.classList).toContain( + 'ant-btn', + ); + }); + it('should console Error when `overlay` in props', () => { + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + render(test
} />); + expect(errSpy).toHaveBeenCalledWith( + 'Warning: [antd: Dropdown] `overlay` is deprecated. Please use `menu` instead.', + ); + errSpy.mockRestore(); + }); + it('should not console Error when `overlay` not in props', () => { + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + render(); + expect(errSpy).not.toHaveBeenCalled(); + errSpy.mockRestore(); + }); + + it('should support dropdownRender', () => { + const dropdownRender = jest.fn((menu) =>
Custom Menu {menu}
); + render(); + expect(dropdownRender).toHaveBeenCalled(); + }); + + it('should support focus menu when set autoFocus', async () => { + jest.useFakeTimers(); + const items = [ + { + label: 'foo', + key: '1', + }, + ]; + const { container } = render(); + await waitFakeTimer(); + expect(container.querySelector('.ant-dropdown-menu-item-active')).toBeTruthy(); + }); +}); diff --git a/packages/meta/src/dropdown/__tests__/image.test.ts b/packages/meta/src/dropdown/__tests__/image.test.ts new file mode 100644 index 0000000..ad2c9d5 --- /dev/null +++ b/packages/meta/src/dropdown/__tests__/image.test.ts @@ -0,0 +1,5 @@ +import { imageDemoTest } from '../../../tests/shared/imageTest'; + +describe('Dropdown image', () => { + imageDemoTest('dropdown', { skip: ['dropdown-button.tsx'] }); +}); diff --git a/packages/meta/src/dropdown/__tests__/index.test.tsx b/packages/meta/src/dropdown/__tests__/index.test.tsx new file mode 100644 index 0000000..a980f92 --- /dev/null +++ b/packages/meta/src/dropdown/__tests__/index.test.tsx @@ -0,0 +1,327 @@ +import React from 'react'; +import type { TriggerProps } from '@rc-component/trigger'; + +import type { DropDownProps } from '..'; +import Dropdown from '..'; +import { resetWarned } from '../../_util/warning'; +import mountTest from '../../../tests/shared/mountTest'; +import rtlTest from '../../../tests/shared/rtlTest'; +import { act, fireEvent, render, waitFakeTimer } from '../../../tests/utils'; + +let triggerProps: TriggerProps; + +jest.mock('@rc-component/trigger', () => { + let Trigger = jest.requireActual('@rc-component/trigger/lib/mock'); + Trigger = Trigger.default || Trigger; + const h: typeof React = jest.requireActual('react'); + + return { + default: h.forwardRef((props, ref) => { + triggerProps = props; + return h.createElement(Trigger, { ref, ...props }); + }), + __esModule: true, + }; +}); + +describe('Dropdown', () => { + const items = [ + { + label: 'foo', + key: '1', + }, + ]; + + mountTest(() => ( + + + + )); + + rtlTest(() => ( + + + + )); + + it('overlay is function and has custom transitionName', () => { + const { asFragment } = render( +
menu
} transitionName="move-up" open> + +
, + ); + expect(Array.from(asFragment().childNodes)).toMatchSnapshot(); + }); + + it('overlay is string', () => { + const { asFragment } = render( + + + , + ); + expect(Array.from(asFragment().childNodes)).toMatchSnapshot(); + }); + + it('should render custom dropdown correctly', () => { + const { asFragment } = render( + ( +
+ {menu} +
CUSTOM NODE
+
+ )} + > + +
, + ); + expect(Array.from(asFragment().childNodes)).toMatchSnapshot(); + }); + + it('support Menu expandIcon', async () => { + jest.useFakeTimers(); + const props: DropDownProps = { + menu: { + items: [ + { + label: 'foo', + key: '1', + }, + { + label: 'SubMenu', + key: 'submenu', + children: [ + { + label: 'foo', + key: '1', + }, + ], + }, + ], + expandIcon: , + }, + open: true, + getPopupContainer: (node) => node, + }; + + const { container } = render( + + + , + ); + await waitFakeTimer(); + expect(container.querySelectorAll('#customExpandIcon').length).toBe(1); + jest.useRealTimers(); + }); + + it('should warn if use topCenter or bottomCenter', () => { + const error = jest.spyOn(console, 'error').mockImplementation(() => {}); + render( +
+ + + + + + +
, + ); + expect(error).toHaveBeenCalledWith( + expect.stringContaining("[antd: Dropdown] You are using 'bottomCenter'"), + ); + expect(error).toHaveBeenCalledWith( + expect.stringContaining("[antd: Dropdown] You are using 'topCenter'"), + ); + error.mockRestore(); + }); + + // zombieJ: when replaced with react test lib, it may be mock fully content + it('dropdown should support auto adjust placement', () => { + render( + + + , + ); + + expect(triggerProps.builtinPlacements).toEqual( + expect.objectContaining({ + bottomLeft: expect.objectContaining({ + overflow: { + adjustX: true, + adjustY: true, + }, + }), + }), + ); + }); + + it('menu item with group', () => { + jest.useFakeTimers(); + const { container } = render( + +
+ , + ); + + // Open + fireEvent.click(container.querySelector('a')!); + act(() => { + jest.runAllTimers(); + }); + + // Close + fireEvent.click(container.querySelector('.ant-dropdown-menu-item')!); + + // Force Motion move on + for (let i = 0; i < 10; i += 1) { + act(() => { + jest.runAllTimers(); + }); + } + + // Motion End + fireEvent.animationEnd(container.querySelector('.ant-slide-up-leave-active')!); + + expect(container.querySelector('.ant-dropdown-hidden')).toBeTruthy(); + + jest.useRealTimers(); + }); + + it('legacy visible', () => { + resetWarned(); + const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + const onOpenChange = jest.fn(); + const onVisibleChange = jest.fn(); + + const { container, rerender } = render( + , + key: 'bamboo', + }, + ], + }} + > + + , + ); + + expect(document.querySelector('.bamboo')).toBeTruthy(); + expect(errorSpy).toHaveBeenCalledWith( + 'Warning: [antd: Dropdown] `visible` is deprecated. Please use `open` instead.', + ); + expect(errorSpy).toHaveBeenCalledWith( + 'Warning: [antd: Dropdown] `onVisibleChange` is deprecated. Please use `onOpenChange` instead.', + ); + + fireEvent.click(container.querySelector('.little')!); + expect(onOpenChange).toHaveBeenCalled(); + expect(onVisibleChange).toHaveBeenCalled(); + + rerender( + menu
}> + + , + ); + expect(errorSpy).toHaveBeenCalledWith( + 'Warning: [antd: Dropdown] `overlay` is deprecated. Please use `menu` instead.', + ); + + errorSpy.mockRestore(); + }); + + it('not block ref', () => { + const divRef = React.createRef(); + render( +
}> + + , + ); + + expect(divRef.current).toBeTruthy(); + }); + + it('should trigger open event when click on item', () => { + const onOpenChange = jest.fn(); + render( + , + key: 1, + }, + ], + }} + > + + , + ); + + fireEvent.click(document.body.querySelector('.bamboo')!); + expect(onOpenChange).toHaveBeenCalledWith(false, { source: 'menu' }); + }); + + it('is still open after selection in multiple mode', () => { + jest.useFakeTimers(); + const { container } = render( + + + , + ); + + // Open + fireEvent.click(container.querySelector('a')!); + act(() => { + jest.runAllTimers(); + }); + + // Selecting item + fireEvent.click(container.querySelector('.ant-dropdown-menu-item')!); + + // Force Motion move on + for (let i = 0; i < 10; i += 1) { + act(() => { + jest.runAllTimers(); + }); + } + expect(container.querySelector('.ant-dropdown-hidden')).toBeFalsy(); + jest.useRealTimers(); + }); +}); diff --git a/packages/meta/src/dropdown/demo/arrow-center.md b/packages/meta/src/dropdown/demo/arrow-center.md new file mode 100644 index 0000000..2f0e8c7 --- /dev/null +++ b/packages/meta/src/dropdown/demo/arrow-center.md @@ -0,0 +1,7 @@ +## zh-CN + +设置 `arrow` 为 `{ pointAtCenter: true }` 后,箭头将指向目标元素的中心。 + +## en-US + +By specifying `arrow` prop with `{ pointAtCenter: true }`, the arrow will point to the center of the target element. diff --git a/packages/meta/src/dropdown/demo/arrow-center.tsx b/packages/meta/src/dropdown/demo/arrow-center.tsx new file mode 100644 index 0000000..8242735 --- /dev/null +++ b/packages/meta/src/dropdown/demo/arrow-center.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import type { MenuProps } from 'antd'; +import { Button, Dropdown, Space } from 'antd'; + +const items: MenuProps['items'] = [ + { + key: '1', + label: ( + + 1st menu item + + ), + }, + { + key: '2', + label: ( + + 2nd menu item + + ), + }, + { + key: '3', + label: ( + + 3rd menu item + + ), + }, +]; + +const App: React.FC = () => ( + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/arrow.md b/packages/meta/src/dropdown/demo/arrow.md new file mode 100644 index 0000000..42fde13 --- /dev/null +++ b/packages/meta/src/dropdown/demo/arrow.md @@ -0,0 +1,7 @@ +## zh-CN + +可以展示一个箭头。 + +## en-US + +You could display an arrow. diff --git a/packages/meta/src/dropdown/demo/arrow.tsx b/packages/meta/src/dropdown/demo/arrow.tsx new file mode 100644 index 0000000..e806a56 --- /dev/null +++ b/packages/meta/src/dropdown/demo/arrow.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import type { MenuProps } from 'antd'; +import { Button, Dropdown, Space } from 'antd'; + +const items: MenuProps['items'] = [ + { + key: '1', + label: ( + + 1st menu item + + ), + }, + { + key: '2', + label: ( + + 2nd menu item + + ), + }, + { + key: '3', + label: ( + + 3rd menu item + + ), + }, +]; + +const App: React.FC = () => ( + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/basic.md b/packages/meta/src/dropdown/demo/basic.md new file mode 100644 index 0000000..988ed60 --- /dev/null +++ b/packages/meta/src/dropdown/demo/basic.md @@ -0,0 +1,7 @@ +## zh-CN + +最简单的下拉菜单。 + +## en-US + +The most basic dropdown menu. diff --git a/packages/meta/src/dropdown/demo/basic.tsx b/packages/meta/src/dropdown/demo/basic.tsx new file mode 100644 index 0000000..6a617fd --- /dev/null +++ b/packages/meta/src/dropdown/demo/basic.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { DownOutlined, SmileOutlined } from '@ant-design/icons'; +import type { MenuProps } from 'antd'; +import { Dropdown, Space } from 'antd'; + +const items: MenuProps['items'] = [ + { + key: '1', + label: ( + + 1st menu item + + ), + }, + { + key: '2', + label: ( + + 2nd menu item (disabled) + + ), + icon: , + disabled: true, + }, + { + key: '3', + label: ( + + 3rd menu item (disabled) + + ), + disabled: true, + }, + { + key: '4', + danger: true, + label: 'a danger item', + }, +]; + +const App: React.FC = () => ( + + e.preventDefault()}> + + Hover me + + + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/context-menu.md b/packages/meta/src/dropdown/demo/context-menu.md new file mode 100644 index 0000000..91cfa3a --- /dev/null +++ b/packages/meta/src/dropdown/demo/context-menu.md @@ -0,0 +1,7 @@ +## zh-CN + +默认是移入触发菜单,可以点击鼠标右键触发。弹出菜单位置会跟随右键点击位置变动。 + +## en-US + +The default trigger mode is `hover`, you can change it to `contextMenu`. The pop-up menu position will follow the right-click position. diff --git a/packages/meta/src/dropdown/demo/context-menu.tsx b/packages/meta/src/dropdown/demo/context-menu.tsx new file mode 100644 index 0000000..dbd531a --- /dev/null +++ b/packages/meta/src/dropdown/demo/context-menu.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import type { MenuProps } from 'antd'; +import { Dropdown, theme } from 'antd'; + +const items: MenuProps['items'] = [ + { + label: '1st menu item', + key: '1', + }, + { + label: '2nd menu item', + key: '2', + }, + { + label: '3rd menu item', + key: '3', + }, +]; + +const App: React.FC = () => { + const { + token: { colorBgLayout, colorTextTertiary }, + } = theme.useToken(); + + return ( + +
+ Right Click on here +
+
+ ); +}; + +export default App; diff --git a/packages/meta/src/dropdown/demo/custom-dropdown.md b/packages/meta/src/dropdown/demo/custom-dropdown.md new file mode 100644 index 0000000..568d670 --- /dev/null +++ b/packages/meta/src/dropdown/demo/custom-dropdown.md @@ -0,0 +1,7 @@ +## zh-CN + +使用 `dropdownRender` 对下拉菜单进行自由扩展。如果你并不需要 Menu 内容,请直接使用 Popover 组件。 + +## en-US + +Customize the dropdown menu via `dropdownRender`. If you don't need the Menu content, use the Popover component directly. diff --git a/packages/meta/src/dropdown/demo/custom-dropdown.tsx b/packages/meta/src/dropdown/demo/custom-dropdown.tsx new file mode 100644 index 0000000..bdb713c --- /dev/null +++ b/packages/meta/src/dropdown/demo/custom-dropdown.tsx @@ -0,0 +1,73 @@ +import React from 'react'; +import { DownOutlined } from '@ant-design/icons'; +import { Button, Divider, Dropdown, Space, theme } from 'antd'; +import type { MenuProps } from 'antd'; + +const { useToken } = theme; + +const items: MenuProps['items'] = [ + { + key: '1', + label: ( + + 1st menu item + + ), + }, + { + key: '2', + label: ( + + 2nd menu item (disabled) + + ), + disabled: true, + }, + { + key: '3', + label: ( + + 3rd menu item (disabled) + + ), + disabled: true, + }, +]; + +const App: React.FC = () => { + const { token } = useToken(); + + const contentStyle: React.CSSProperties = { + backgroundColor: token.colorBgElevated, + borderRadius: token.borderRadiusLG, + boxShadow: token.boxShadowSecondary, + }; + + const menuStyle: React.CSSProperties = { + boxShadow: 'none', + }; + + return ( + ( +
+ {React.cloneElement(menu as React.ReactElement, { style: menuStyle })} + + + + +
+ )} + > + e.preventDefault()}> + + Hover me + + + +
+ ); +}; + +export default App; diff --git a/packages/meta/src/dropdown/demo/dropdown-button.md b/packages/meta/src/dropdown/demo/dropdown-button.md new file mode 100644 index 0000000..be7eb88 --- /dev/null +++ b/packages/meta/src/dropdown/demo/dropdown-button.md @@ -0,0 +1,7 @@ +## zh-CN + +左边是按钮,右边是额外的相关功能菜单。可设置 `icon` 属性来修改右边的图标。 + +## en-US + +A button is on the left, and a related functional menu is on the right. You can set the icon property to modify the icon of right. diff --git a/packages/meta/src/dropdown/demo/dropdown-button.tsx b/packages/meta/src/dropdown/demo/dropdown-button.tsx new file mode 100644 index 0000000..d2897fe --- /dev/null +++ b/packages/meta/src/dropdown/demo/dropdown-button.tsx @@ -0,0 +1,83 @@ +import React from 'react'; +import { DownOutlined, UserOutlined } from '@ant-design/icons'; +import type { MenuProps } from 'antd'; +import { Button, Dropdown, message, Space, Tooltip } from 'antd'; + +const handleButtonClick = (e: React.MouseEvent) => { + message.info('Click on left button.'); + console.log('click left button', e); +}; + +const handleMenuClick: MenuProps['onClick'] = (e) => { + message.info('Click on menu item.'); + console.log('click', e); +}; + +const items: MenuProps['items'] = [ + { + label: '1st menu item', + key: '1', + icon: , + }, + { + label: '2nd menu item', + key: '2', + icon: , + }, + { + label: '3rd menu item', + key: '3', + icon: , + danger: true, + }, + { + label: '4rd menu item', + key: '4', + icon: , + danger: true, + disabled: true, + }, +]; + +const menuProps = { + items, + onClick: handleMenuClick, +}; + +const App: React.FC = () => ( + + + Dropdown + + }> + Dropdown + + + Dropdown + + [ + + {leftButton} + , + React.cloneElement(rightButton as React.ReactElement, { loading: true }), + ]} + > + With Tooltip + + + + + + Danger + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/event.md b/packages/meta/src/dropdown/demo/event.md new file mode 100644 index 0000000..9a95a92 --- /dev/null +++ b/packages/meta/src/dropdown/demo/event.md @@ -0,0 +1,7 @@ +## zh-CN + +点击菜单项后会触发事件,用户可以通过相应的菜单项 key 进行不同的操作。 + +## en-US + +An event will be triggered when you click menu items, in which you can make different operations according to item's key. diff --git a/packages/meta/src/dropdown/demo/event.tsx b/packages/meta/src/dropdown/demo/event.tsx new file mode 100644 index 0000000..0684aeb --- /dev/null +++ b/packages/meta/src/dropdown/demo/event.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { DownOutlined } from '@ant-design/icons'; +import type { MenuProps } from 'antd'; +import { Dropdown, message, Space } from 'antd'; + +const onClick: MenuProps['onClick'] = ({ key }) => { + message.info(`Click on item ${key}`); +}; + +const items: MenuProps['items'] = [ + { + label: '1st menu item', + key: '1', + }, + { + label: '2nd menu item', + key: '2', + }, + { + label: '3rd menu item', + key: '3', + }, +]; + +const App: React.FC = () => ( + + e.preventDefault()}> + + Hover me, Click menu item + + + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/icon-debug.md b/packages/meta/src/dropdown/demo/icon-debug.md new file mode 100644 index 0000000..30c7698 --- /dev/null +++ b/packages/meta/src/dropdown/demo/icon-debug.md @@ -0,0 +1,7 @@ +## zh-CN + +特殊处理 Down icon。 + +## en-US + +Specially handle Down icon. diff --git a/packages/meta/src/dropdown/demo/icon-debug.tsx b/packages/meta/src/dropdown/demo/icon-debug.tsx new file mode 100644 index 0000000..0903b09 --- /dev/null +++ b/packages/meta/src/dropdown/demo/icon-debug.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { DownOutlined } from '@ant-design/icons'; +import { Dropdown, Space } from 'antd'; + +const App: React.FC = () => ( + + } menu={{ items: [] }}> + Submit + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/item.md b/packages/meta/src/dropdown/demo/item.md new file mode 100644 index 0000000..fe04f28 --- /dev/null +++ b/packages/meta/src/dropdown/demo/item.md @@ -0,0 +1,7 @@ +## zh-CN + +分割线和不可用菜单项。 + +## en-US + +Divider and disabled menu item. diff --git a/packages/meta/src/dropdown/demo/item.tsx b/packages/meta/src/dropdown/demo/item.tsx new file mode 100644 index 0000000..08a41fd --- /dev/null +++ b/packages/meta/src/dropdown/demo/item.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { DownOutlined } from '@ant-design/icons'; +import type { MenuProps } from 'antd'; +import { Dropdown, Space } from 'antd'; + +const items: MenuProps['items'] = [ + { + label: ( + + 1st menu item + + ), + key: '0', + }, + { + label: ( + + 2nd menu item + + ), + key: '1', + }, + { + type: 'divider', + }, + { + label: '3rd menu item(disabled)', + key: '3', + disabled: true, + }, +]; + +const App: React.FC = () => ( + + e.preventDefault()}> + + Hover me + + + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/loading.md b/packages/meta/src/dropdown/demo/loading.md new file mode 100644 index 0000000..e3bf3b7 --- /dev/null +++ b/packages/meta/src/dropdown/demo/loading.md @@ -0,0 +1,7 @@ +## zh-CN + +添加 `loading` 属性即可让按钮处于加载状态,最后两个按钮演示点击后进入加载状态。 + +## en-US + +A loading indicator can be added to a button by setting the `loading` property on the `Dropdown.Button`. diff --git a/packages/meta/src/dropdown/demo/loading.tsx b/packages/meta/src/dropdown/demo/loading.tsx new file mode 100644 index 0000000..9d33019 --- /dev/null +++ b/packages/meta/src/dropdown/demo/loading.tsx @@ -0,0 +1,60 @@ +import React, { useState } from 'react'; +import { DownOutlined } from '@ant-design/icons'; +import type { MenuProps } from 'antd'; +import { Dropdown, Space } from 'antd'; + +const items: MenuProps['items'] = [ + { + label: 'Submit and continue', + key: '1', + }, +]; + +const App: React.FC = () => { + const [loadings, setLoadings] = useState([]); + + const enterLoading = (index: number) => { + setLoadings((state) => { + const newLoadings = [...state]; + newLoadings[index] = true; + return newLoadings; + }); + + setTimeout(() => { + setLoadings((state) => { + const newLoadings = [...state]; + newLoadings[index] = false; + return newLoadings; + }); + }, 6000); + }; + + return ( + + + Submit + + + Submit + + enterLoading(0)} + > + Submit + + } + loading={loadings[1]} + menu={{ items }} + onClick={() => enterLoading(1)} + > + Submit + + + ); +}; + +export default App; diff --git a/packages/meta/src/dropdown/demo/menu-full.md b/packages/meta/src/dropdown/demo/menu-full.md new file mode 100644 index 0000000..e75d313 --- /dev/null +++ b/packages/meta/src/dropdown/demo/menu-full.md @@ -0,0 +1,11 @@ +## zh-CN + +此演示需要注意去掉 Reset 样式后查看 Dropdown 内 Menu 的样式是否正常。 + +[#19150](https://github.com/ant-design/ant-design/pull/19150) + +## en-US + +This demo was created for debugging Menu styles inside Dropdown. + +[#19150](https://github.com/ant-design/ant-design/pull/19150) diff --git a/packages/meta/src/dropdown/demo/menu-full.tsx b/packages/meta/src/dropdown/demo/menu-full.tsx new file mode 100644 index 0000000..a9b611f --- /dev/null +++ b/packages/meta/src/dropdown/demo/menu-full.tsx @@ -0,0 +1,68 @@ +import React from 'react'; +import { AppstoreOutlined, DownOutlined, MailOutlined, SettingOutlined } from '@ant-design/icons'; +import type { MenuProps } from 'antd'; +import { Dropdown, Space } from 'antd'; + +type MenuItem = Required['items'][number]; + +function getItem( + label: React.ReactNode, + key: React.Key, + icon?: React.ReactNode, + children?: MenuItem[], + type?: 'group', +): MenuItem { + return { + key, + icon, + children, + label, + type, + } as MenuItem; +} + +const items: MenuItem[] = [ + getItem( + 'Item Group', + 'group', + null, + [getItem('Option 0', '01'), getItem('Option 0', '02')], + 'group', + ), + getItem('Navigation One', 'sub1', , [ + getItem('Item 1', 'g1', null, [getItem('Option 1', '1'), getItem('Option 2', '2')], 'group'), + getItem('Item 2', 'g2', null, [getItem('Option 3', '3'), getItem('Option 4', '4')], 'group'), + ]), + getItem('Navigation Two', 'sub2', , [ + getItem('Option 5', '5'), + getItem('Option 6', '6'), + getItem('Submenu', 'sub3', null, [getItem('Option 7', '7'), getItem('Option 8', '8')]), + ]), + getItem('Navigation Three', 'sub4', , [ + getItem('Option 9', '9'), + getItem('Option 10', '10'), + getItem('Option 11', '11'), + getItem('Option 12', '12'), + ]), + // Not crash + null as any, +]; + +const App: React.FC = () => ( + + e.preventDefault()}> + + Hover to check menu style + + + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/overlay-open.md b/packages/meta/src/dropdown/demo/overlay-open.md new file mode 100644 index 0000000..168d93d --- /dev/null +++ b/packages/meta/src/dropdown/demo/overlay-open.md @@ -0,0 +1,7 @@ +## zh-CN + +默认是点击关闭菜单,可以关闭此功能。 + +## en-US + +The default is to close the menu when you click on menu items, this feature can be turned off. diff --git a/packages/meta/src/dropdown/demo/overlay-open.tsx b/packages/meta/src/dropdown/demo/overlay-open.tsx new file mode 100644 index 0000000..6b63c06 --- /dev/null +++ b/packages/meta/src/dropdown/demo/overlay-open.tsx @@ -0,0 +1,55 @@ +import React, { useState } from 'react'; +import { DownOutlined } from '@ant-design/icons'; +import type { DropdownProps, MenuProps } from 'antd'; +import { Dropdown, Space } from 'antd'; + +const App: React.FC = () => { + const [open, setOpen] = useState(false); + + const handleMenuClick: MenuProps['onClick'] = (e) => { + if (e.key === '3') { + setOpen(false); + } + }; + + const handleOpenChange: DropdownProps['onOpenChange'] = (nextOpen, info) => { + if (info.source === 'trigger' || nextOpen) { + setOpen(nextOpen); + } + }; + + const items: MenuProps['items'] = [ + { + label: 'Clicking me will not close the menu.', + key: '1', + }, + { + label: 'Clicking me will not close the menu also.', + key: '2', + }, + { + label: 'Clicking me will close the menu.', + key: '3', + }, + ]; + + return ( + + e.preventDefault()}> + + Hover me + + + + + ); +}; + +export default App; diff --git a/packages/meta/src/dropdown/demo/placement.md b/packages/meta/src/dropdown/demo/placement.md new file mode 100644 index 0000000..911a6d4 --- /dev/null +++ b/packages/meta/src/dropdown/demo/placement.md @@ -0,0 +1,7 @@ +## zh-CN + +支持 6 个弹出位置。 + +## en-US + +Support 6 placements. diff --git a/packages/meta/src/dropdown/demo/placement.tsx b/packages/meta/src/dropdown/demo/placement.tsx new file mode 100644 index 0000000..b915977 --- /dev/null +++ b/packages/meta/src/dropdown/demo/placement.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import type { MenuProps } from 'antd'; +import { Button, Dropdown, Space } from 'antd'; + +const items: MenuProps['items'] = [ + { + key: '1', + label: ( + + 1st menu item + + ), + }, + { + key: '2', + label: ( + + 2nd menu item + + ), + }, + { + key: '3', + label: ( + + 3rd menu item + + ), + }, +]; + +const App: React.FC = () => ( + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/render-panel.md b/packages/meta/src/dropdown/demo/render-panel.md new file mode 100644 index 0000000..70bcbec --- /dev/null +++ b/packages/meta/src/dropdown/demo/render-panel.md @@ -0,0 +1,7 @@ +## zh-CN + +调试用组件,请勿直接使用。 + +## en-US + +Debug usage. Do not use in your production. diff --git a/packages/meta/src/dropdown/demo/render-panel.tsx b/packages/meta/src/dropdown/demo/render-panel.tsx new file mode 100644 index 0000000..6ef5ce5 --- /dev/null +++ b/packages/meta/src/dropdown/demo/render-panel.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { SmileOutlined } from '@ant-design/icons'; +import { Dropdown } from 'antd'; + +const { _InternalPanelDoNotUseOrYouWillBeFired: InternalDropdown } = Dropdown; + +const menu = [ + { + key: '1', + label: ( + + 1st menu item + + ), + }, + { + key: '2', + label: ( + + 2nd menu item (disabled) + + ), + icon: , + disabled: true, + }, + { + key: '3', + label: ( + + 3rd menu item (disabled) + + ), + disabled: true, + }, + { + key: '4', + danger: true, + label: 'a danger item', + }, +]; + +const App: React.FC = () => ; + +export default App; diff --git a/packages/meta/src/dropdown/demo/selectable.md b/packages/meta/src/dropdown/demo/selectable.md new file mode 100644 index 0000000..d4ef858 --- /dev/null +++ b/packages/meta/src/dropdown/demo/selectable.md @@ -0,0 +1,7 @@ +## zh-CN + +添加 `menu` 中的 `selectable` 属性可以开启选择能力。 + +## en-US + +Configure the `selectable` property in `menu` to enable selectable ability. diff --git a/packages/meta/src/dropdown/demo/selectable.tsx b/packages/meta/src/dropdown/demo/selectable.tsx new file mode 100644 index 0000000..3c1fa85 --- /dev/null +++ b/packages/meta/src/dropdown/demo/selectable.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { DownOutlined } from '@ant-design/icons'; +import type { MenuProps } from 'antd'; +import { Dropdown, Space, Typography } from 'antd'; + +const items: MenuProps['items'] = [ + { + key: '1', + label: 'Item 1', + }, + { + key: '2', + label: 'Item 2', + }, + { + key: '3', + label: 'Item 3', + }, +]; + +const App: React.FC = () => ( + + + + Selectable + + + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/sub-menu-debug.md b/packages/meta/src/dropdown/demo/sub-menu-debug.md new file mode 100644 index 0000000..eed7642 --- /dev/null +++ b/packages/meta/src/dropdown/demo/sub-menu-debug.md @@ -0,0 +1,7 @@ +## zh-CN + +传入的菜单里有多个层级。 + +## en-US + +The menu has multiple levels. diff --git a/packages/meta/src/dropdown/demo/sub-menu-debug.tsx b/packages/meta/src/dropdown/demo/sub-menu-debug.tsx new file mode 100644 index 0000000..ce695f1 --- /dev/null +++ b/packages/meta/src/dropdown/demo/sub-menu-debug.tsx @@ -0,0 +1,66 @@ +import React from 'react'; +import { DownOutlined } from '@ant-design/icons'; +import type { MenuProps } from 'antd'; +import { Dropdown, Space } from 'antd'; + +const items: MenuProps['items'] = [ + { + key: '1', + type: 'group', + label: 'Group title', + children: [ + { + key: '1-1', + label: '1st menu item', + }, + { + key: '1-2', + label: '2nd menu item', + }, + ], + }, + { + key: '2', + label: 'sub menu', + children: [ + { + key: '2-1', + label: '3rd menu item', + }, + { + key: '2-2', + label: '4th menu item', + }, + ], + }, + { + key: '3', + label: 'disabled sub menu', + disabled: true, + children: [ + { + key: '3-1', + label: '5d menu item', + }, + { + key: '3-2', + label: '6th menu item', + }, + ], + }, +]; + +const App: React.FC = () => ( + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/sub-menu.md b/packages/meta/src/dropdown/demo/sub-menu.md new file mode 100644 index 0000000..eed7642 --- /dev/null +++ b/packages/meta/src/dropdown/demo/sub-menu.md @@ -0,0 +1,7 @@ +## zh-CN + +传入的菜单里有多个层级。 + +## en-US + +The menu has multiple levels. diff --git a/packages/meta/src/dropdown/demo/sub-menu.tsx b/packages/meta/src/dropdown/demo/sub-menu.tsx new file mode 100644 index 0000000..7c7f382 --- /dev/null +++ b/packages/meta/src/dropdown/demo/sub-menu.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { DownOutlined } from '@ant-design/icons'; +import type { MenuProps } from 'antd'; +import { Dropdown, Space } from 'antd'; + +const items: MenuProps['items'] = [ + { + key: '1', + type: 'group', + label: 'Group title', + children: [ + { + key: '1-1', + label: '1st menu item', + }, + { + key: '1-2', + label: '2nd menu item', + }, + ], + }, + { + key: '2', + label: 'sub menu', + children: [ + { + key: '2-1', + label: '3rd menu item', + }, + { + key: '2-2', + label: '4th menu item', + }, + ], + }, + { + key: '3', + label: 'disabled sub menu', + disabled: true, + children: [ + { + key: '3-1', + label: '5d menu item', + }, + { + key: '3-2', + label: '6th menu item', + }, + ], + }, +]; + +const App: React.FC = () => ( + + e.preventDefault()}> + + Cascading menu + + + + +); + +export default App; diff --git a/packages/meta/src/dropdown/demo/trigger.md b/packages/meta/src/dropdown/demo/trigger.md new file mode 100644 index 0000000..e43eadd --- /dev/null +++ b/packages/meta/src/dropdown/demo/trigger.md @@ -0,0 +1,7 @@ +## zh-CN + +默认是移入触发菜单,可以点击触发。 + +## en-US + +The default trigger mode is `hover`, you can change it to `click`. diff --git a/packages/meta/src/dropdown/demo/trigger.tsx b/packages/meta/src/dropdown/demo/trigger.tsx new file mode 100644 index 0000000..ca85c6f --- /dev/null +++ b/packages/meta/src/dropdown/demo/trigger.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { DownOutlined } from '@ant-design/icons'; +import type { MenuProps } from 'antd'; +import { Dropdown, Space } from 'antd'; + +const items: MenuProps['items'] = [ + { + label: 1st menu item, + key: '0', + }, + { + label: 2nd menu item, + key: '1', + }, + { + type: 'divider', + }, + { + label: '3rd menu item', + key: '3', + }, +]; + +const App: React.FC = () => ( + + e.preventDefault()}> + + Click me + + + + +); + +export default App; diff --git a/packages/meta/src/dropdown/dropdown-button.tsx b/packages/meta/src/dropdown/dropdown-button.tsx new file mode 100644 index 0000000..95ea68f --- /dev/null +++ b/packages/meta/src/dropdown/dropdown-button.tsx @@ -0,0 +1,142 @@ +import * as React from 'react'; +import EllipsisOutlined from '@ant-design/icons/EllipsisOutlined'; +import classNames from 'classnames'; + +import Button from '../button'; +import type { ButtonHTMLType, ButtonProps } from '../button'; +import type { ButtonGroupProps } from '../button/button-group'; +import { ConfigContext } from '../config-provider'; +import Space from '../space'; +import { useCompactItemContext } from '../space/Compact'; +import Dropdown from './dropdown'; +import type { DropdownProps } from './dropdown'; + +export type DropdownButtonType = 'default' | 'primary' | 'dashed' | 'link' | 'text'; + +export interface DropdownButtonProps extends ButtonGroupProps, DropdownProps { + type?: DropdownButtonType; + htmlType?: ButtonHTMLType; + danger?: boolean; + disabled?: boolean; + loading?: ButtonProps['loading']; + onClick?: React.MouseEventHandler; + icon?: React.ReactNode; + href?: string; + children?: React.ReactNode; + title?: string; + buttonsRender?: (buttons: React.ReactNode[]) => React.ReactNode[]; +} + +type CompoundedComponent = React.FC & { + /** @internal */ + __ANT_BUTTON: boolean; +}; + +const DropdownButton: CompoundedComponent = (props) => { + const { + getPopupContainer: getContextPopupContainer, + getPrefixCls, + direction, + } = React.useContext(ConfigContext); + + const { + prefixCls: customizePrefixCls, + type = 'default', + danger, + disabled, + loading, + onClick, + htmlType, + children, + className, + menu, + arrow, + autoFocus, + overlay, + trigger, + align, + open, + onOpenChange, + placement, + getPopupContainer, + href, + icon = , + title, + buttonsRender = (buttons: React.ReactNode[]) => buttons, + mouseEnterDelay, + mouseLeaveDelay, + overlayClassName, + overlayStyle, + destroyPopupOnHide, + dropdownRender, + ...restProps + } = props; + + const prefixCls = getPrefixCls('dropdown', customizePrefixCls); + const buttonPrefixCls = `${prefixCls}-button`; + + const dropdownProps: DropdownProps = { + menu, + arrow, + autoFocus, + align, + disabled, + trigger: disabled ? [] : trigger, + onOpenChange, + getPopupContainer: getPopupContainer || getContextPopupContainer, + mouseEnterDelay, + mouseLeaveDelay, + overlayClassName, + overlayStyle, + destroyPopupOnHide, + dropdownRender, + }; + + const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction); + + const classes = classNames(buttonPrefixCls, compactItemClassnames, className); + + if ('overlay' in props) { + dropdownProps.overlay = overlay; + } + + if ('open' in props) { + dropdownProps.open = open; + } + + if ('placement' in props) { + dropdownProps.placement = placement; + } else { + dropdownProps.placement = direction === 'rtl' ? 'bottomLeft' : 'bottomRight'; + } + + const leftButton = ( + + ); + + const rightButton = -
+
+ + +
+ +
- - -
-
- - - - - - - - - - - - - - - + + + + + + + + + + + + + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - -
- Su - - Mo - - Tu - - We - - Th - - Fr - - Sa -
-
+
+ Su + + Mo + + Tu + + We + + Th + + Fr + + Sa +
- 30 - - -
+ 30 +
+
- 31 - - -
+ 31 +
+
- 1 - - -
+ 1 +
+
- 2 - - -
+ 2 +
+
- 3 - - -
+ 3 +
+
- 4 - - -
+ 4 +
+
- 5 - -
-
+ 5 +
+
- 6 - - -
+ 6 +
+
- 7 - - -
+ 7 +
+
- 8 - - -
+ 8 +
+
- 9 - - -
+ 9 +
+
- 10 - - -
+ 10 +
+
- 11 - - -
+ 11 +
+
- 12 - -
-
+ 12 +
+
- 13 - - -
+ 13 +
+
- 14 - - -
+ 14 +
+
- 15 - - -
+ 15 +
+
- 16 - - -
+ 16 +
+
- 17 - - -
+ 17 +
+
- 18 - - -
+ 18 +
+
- 19 - -
-
+ 19 +
+
- 20 - - -
+ 20 +
+
- 21 - - -
+ 21 +
+
- 22 - - -
+ 22 +
+
- 23 - - -
+ 23 +
+
- 24 - - -
+ 24 +
+
- 25 - - -
+ 25 +
+
- 26 - -
-
+ 26 +
+
- 27 - - -
+ 27 +
+
- 28 - - -
+ 28 +
+
- 29 - - -
+ 29 +
+
- 30 - - -
+ 30 +
+
- 1 - - -
+ 1 +
+
- 2 - - -
+ 2 +
+
- 3 - -
-
+ 3 +
+
- 4 - - -
+ 4 +
+
- 5 - - -
+ 5 +
+
- 6 - - -
+ 6 +
+
- 7 - - -
+ 7 +
+
- 8 - - -
+ 8 +
+
- 9 - - -
+ 9 +
+
- 10 - -
+
+ 10 +
+ + + + +
@@ -3770,16 +3648,17 @@ Array [ class="ant-form-item-control-input-content" >
@@ -3816,17 +3695,18 @@ Array [ class="ant-picker-input" >
+ + + + + 12 + + + +
+`; + +exports[`renders components/input/demo/filled-debug.tsx extend context correctly 2`] = `[]`; + exports[`renders components/input/demo/focus.tsx extend context correctly 1`] = `
@@ -6116,7 +6646,7 @@ exports[`renders components/input/demo/group.tsx extend context correctly 1`] = style="padding-left: 4px; padding-right: 4px;" > @@ -6128,13 +6658,13 @@ exports[`renders components/input/demo/group.tsx extend context correctly 1`] = class="ant-input-group ant-input-group-compact" >
-
+
- -
+
+ + +
+ +
- - -
-
- - - - - - - - - - - - - - - + + + + + + + + + + + + + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - -
- Su - - Mo - - Tu - - We - - Th - - Fr - - Sa -
-
+
+ Su + + Mo + + Tu + + We + + Th + + Fr + + Sa +
- 30 - - -
+ 30 +
+
- 31 - - -
+ 31 +
+
- 1 - - -
+ 1 +
+
- 2 - - -
+ 2 +
+
- 3 - - -
+ 3 +
+
- 4 - - -
+ 4 +
+
- 5 - -
-
+ 5 +
+
- 6 - - -
+ 6 +
+
- 7 - - -
+ 7 +
+
- 8 - - -
+ 8 +
+
- 9 - - -
+ 9 +
+
- 10 - - -
+ 10 +
+
- 11 - - -
+ 11 +
+
- 12 - -
-
+ 12 +
+
- 13 - - -
+ 13 +
+
- 14 - - -
+ 14 +
+
- 15 - - -
+ 15 +
+
- 16 - - -
+ 16 +
+
- 17 - - -
+ 17 +
+
- 18 - - -
+ 18 +
+
- 19 - -
-
+ 19 +
+
- 20 - - -
+ 20 +
+
- 21 - - -
+ 21 +
+
- 22 - - -
+ 22 +
+
- 23 - - -
+ 23 +
+
- 24 - - -
+ 24 +
+
- 25 - - -
+ 25 +
+
- 26 - -
-
+ 26 +
+
- 27 - - -
+ 27 +
+
- 28 - - -
+ 28 +
+
- 29 - - -
+ 29 +
+
- 30 - - -
+ 30 +
+
- 1 - - -
+ 1 +
+
- 2 - - -
+ 2 +
+
- 3 - -
-
+ 3 +
+
- 4 - - -
+ 4 +
+
- 5 - - -
+ 5 +
+
- 6 - - -
+ 6 +
+
- 7 - - -
+ 7 +
+
- 8 - - -
+ 8 +
+
- 9 - - -
+ 9 +
+
- 10 - -
+
+ 10 +
+ + + + +
@@ -7378,22 +7920,23 @@ exports[`renders components/input/demo/group.tsx extend context correctly 1`] = class="ant-input-group ant-input-group-compact" >
@@ -7430,16 +7973,17 @@ exports[`renders components/input/demo/group.tsx extend context correctly 1`] = class="ant-picker-input" >