From 5851494d555970c81cf1c3712687fd6c2eb79ecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=B1=AA?= <1844749591@qq.com> Date: Wed, 26 Feb 2025 10:57:53 +0800 Subject: [PATCH 01/11] refactor: update prop names and remove deprecated props --- examples/visible.tsx | 6 ++-- package.json | 2 +- src/Cascader.tsx | 59 ++++++++++++++--------------------- src/OptionList/Column.tsx | 4 +-- src/OptionList/List.tsx | 4 +-- src/Panel.tsx | 4 +-- src/context.ts | 4 +-- src/utils/warningPropsUtil.ts | 14 +-------- tests/index.spec.tsx | 18 +++-------- tests/private.spec.tsx | 2 +- 10 files changed, 43 insertions(+), 74 deletions(-) diff --git a/examples/visible.tsx b/examples/visible.tsx index 775433c8..2080e4de 100644 --- a/examples/visible.tsx +++ b/examples/visible.tsx @@ -59,7 +59,7 @@ const addressOptions = [ const Demo = () => { const [value, setValue] = useState([]); - const [popupVisible, setPopupVisible] = useState(false); + const [open, setOpen] = useState(false); const getLabel = () => { return arrayTreeFilter(addressOptions, (o, level) => o.value === value[level]) @@ -69,10 +69,10 @@ const Demo = () => { return ( setPopupVisible(open)} + onPopupVisibleChange={open => setOpen(open)} onChange={value => setValue(value)} > diff --git a/package.json b/package.json index dfd09b2a..9ecb80d7 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@types/classnames": "^2.2.6", "@types/enzyme": "^3.1.15", "@types/jest": "^29.4.0", - "@types/react": "^17.0.38", + "@types/react": "^18.0.38", "@types/react-dom": "^18.0.11", "@types/warning": "^3.0.0", "@umijs/fabric": "^4.0.0", diff --git a/src/Cascader.tsx b/src/Cascader.tsx index 0f8d5b0a..660dc3f8 100644 --- a/src/Cascader.tsx +++ b/src/Cascader.tsx @@ -24,7 +24,7 @@ import { toRawValues, } from './utils/commonUtil'; import { formatStrategyValues, toPathOptions } from './utils/treeUtil'; -import warningProps, { warningNullOptions } from './utils/warningPropsUtil'; +import { warningNullOptions } from './utils/warningPropsUtil'; export interface BaseOptionType { disabled?: boolean; @@ -67,9 +67,9 @@ interface BaseCascaderProps< OptionType extends DefaultOptionType = DefaultOptionType, ValueField extends keyof OptionType = keyof OptionType, > extends Omit< - BaseSelectPropsWithoutPrivate, - 'tokenSeparators' | 'labelInValue' | 'mode' | 'showSearch' - > { + BaseSelectPropsWithoutPrivate, + 'tokenSeparators' | 'labelInValue' | 'mode' | 'showSearch' +> { // MISC id?: string; prefixCls?: string; @@ -95,18 +95,14 @@ interface BaseCascaderProps< // Options options?: OptionType[]; /** @private Internal usage. Do not use in your production. */ - dropdownPrefixCls?: string; + popupPrefixCls?: string; loadData?: (selectOptions: OptionType[]) => void; - // Open - /** @deprecated Use `open` instead */ - popupVisible?: boolean; - popupClassName?: string; + /** @deprecated Use `popupMenuColumnStyle` instead */ dropdownMenuColumnStyle?: React.CSSProperties; + popupMenuColumnStyle?: React.CSSProperties; - /** @deprecated Use `placement` instead */ - popupPlacement?: Placement; placement?: Placement; builtinPlacements?: BuildInPlacements; @@ -131,8 +127,8 @@ export type ValueType< ValueField extends keyof OptionType = keyof OptionType, > = keyof OptionType extends ValueField ? unknown extends OptionType['value'] - ? OptionType[ValueField] - : OptionType['value'] + ? OptionType[ValueField] + : OptionType['value'] : OptionType[ValueField]; export type GetValueType< @@ -201,18 +197,16 @@ const Cascader = React.forwardRef((props, re // Options options, - dropdownPrefixCls, + popupPrefixCls, loadData, - // Open - popupVisible, open, popupClassName, dropdownMenuColumnStyle, + popupMenuColumnStyle, popupStyle: customPopupStyle, - popupPlacement, placement, onPopupVisibleChange, @@ -272,7 +266,7 @@ const Cascader = React.forwardRef((props, re mergedSearchValue, mergedOptions, mergedFieldNames, - dropdownPrefixCls || prefixCls, + popupPrefixCls || prefixCls, searchConfig, changeOnSelect || multiple, ); @@ -365,19 +359,14 @@ const Cascader = React.forwardRef((props, re onInternalSelect(valueCells); }; - // ============================ Open ============================ - const mergedOpen = open !== undefined ? open : popupVisible; - - - const mergedPlacement = placement || popupPlacement; - const onInternalPopupVisibleChange = (nextVisible: boolean) => { onPopupVisibleChange?.(nextVisible); }; + const mergedPopupMenuColumnStyle = popupMenuColumnStyle || dropdownMenuColumnStyle; + // ========================== Warning =========================== if (process.env.NODE_ENV !== 'production') { - warningProps(props); warningNullOptions(mergedOptions, mergedFieldNames); } @@ -392,12 +381,12 @@ const Cascader = React.forwardRef((props, re onSelect: onInternalSelect, checkable, searchOptions, - dropdownPrefixCls, + popupPrefixCls, loadData, expandTrigger, expandIcon, loadingIcon, - dropdownMenuColumnStyle, + popupMenuColumnStyle: mergedPopupMenuColumnStyle, optionRender, }), [ @@ -409,12 +398,12 @@ const Cascader = React.forwardRef((props, re onInternalSelect, checkable, searchOptions, - dropdownPrefixCls, + popupPrefixCls, loadData, expandTrigger, expandIcon, loadingIcon, - dropdownMenuColumnStyle, + mergedPopupMenuColumnStyle, optionRender, ], ); @@ -427,12 +416,12 @@ const Cascader = React.forwardRef((props, re const popupStyle: React.CSSProperties = // Search to match width (mergedSearchValue && searchConfig.matchInputWidth) || - // Empty keep the width - emptyOptions + // Empty keep the width + emptyOptions ? {} : { - minWidth: 'auto', - }; + minWidth: 'auto', + }; return ( @@ -460,9 +449,9 @@ const Cascader = React.forwardRef((props, re OptionList={OptionList} emptyOptions={emptyOptions} // Open - open={mergedOpen} + open={open} popupClassName={popupClassName} - placement={mergedPlacement} + placement={placement} onPopupVisibleChange={onInternalPopupVisibleChange} // Children getRawInputElement={() => children as React.ReactElement} diff --git a/src/OptionList/Column.tsx b/src/OptionList/Column.tsx index c46cc457..7797b358 100644 --- a/src/OptionList/Column.tsx +++ b/src/OptionList/Column.tsx @@ -50,7 +50,7 @@ export default function Column(( changeOnSelect, onSelect, searchOptions, - dropdownPrefixCls, + popupPrefixCls, loadData, expandTrigger, } = React.useContext(CascaderContext); - const mergedPrefixCls = dropdownPrefixCls || prefixCls; + const mergedPrefixCls = popupPrefixCls || prefixCls; // ========================= loadData ========================= const [loadingKeys, setLoadingKeys] = React.useState([]); diff --git a/src/Panel.tsx b/src/Panel.tsx index 3154e881..0e9dc491 100644 --- a/src/Panel.tsx +++ b/src/Panel.tsx @@ -153,12 +153,12 @@ export default function Panel< onSelect: onInternalSelect, checkable, searchOptions: [], - dropdownPrefixCls: undefined, + popupPrefixCls: undefined, loadData, expandTrigger, expandIcon, loadingIcon, - dropdownMenuColumnStyle: undefined, + popupMenuColumnStyle: undefined, }), [ mergedOptions, diff --git a/src/context.ts b/src/context.ts index 85e3b6a3..ffa5585e 100644 --- a/src/context.ts +++ b/src/context.ts @@ -15,12 +15,12 @@ export interface CascaderContextProps { onSelect: (valuePath: SingleValueType) => void; checkable?: boolean | React.ReactNode; searchOptions: DefaultOptionType[]; - dropdownPrefixCls?: string; + popupPrefixCls?: string; loadData?: (selectOptions: DefaultOptionType[]) => void; expandTrigger?: 'hover' | 'click'; expandIcon?: React.ReactNode; loadingIcon?: React.ReactNode; - dropdownMenuColumnStyle?: React.CSSProperties; + popupMenuColumnStyle?: React.CSSProperties; optionRender?: CascaderProps['optionRender']; } diff --git a/src/utils/warningPropsUtil.ts b/src/utils/warningPropsUtil.ts index 07b90327..e8f3b4ac 100644 --- a/src/utils/warningPropsUtil.ts +++ b/src/utils/warningPropsUtil.ts @@ -1,15 +1,5 @@ import warning from '@rc-component/util/lib/warning'; -import type { DefaultOptionType, FieldNames, InternalCascaderProps } from '../Cascader'; - -function warningProps(props: InternalCascaderProps) { - const { popupVisible, popupPlacement } = props; - - warning(popupVisible === undefined, '`popupVisible` is deprecated. Please use `open` instead.'); - warning( - popupPlacement === undefined, - '`popupPlacement` is deprecated. Please use `placement` instead.', - ); -} +import type { DefaultOptionType, FieldNames } from '../Cascader'; // value in Cascader options should not be null export function warningNullOptions(options: DefaultOptionType[], fieldNames: FieldNames) { @@ -35,5 +25,3 @@ export function warningNullOptions(options: DefaultOptionType[], fieldNames: Fie recursiveOptions(options); } } - -export default warningProps; diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index fc8d43d5..d1779a55 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -514,28 +514,20 @@ describe('Cascader.Basic', () => { expect(wrapper.isOpen()).toBeTruthy(); }); - it('warning popupVisible & onPopupVisibleChange & popupClassName', () => { + it('warning onPopupVisibleChange & popupClassName', () => { resetWarned(); const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const onPopupVisibleChange = jest.fn(); const wrapper = mount( , ); - expect(errorSpy).toHaveBeenCalledWith( - 'Warning: `popupVisible` is deprecated. Please use `open` instead.', - ); - expect(errorSpy).toHaveBeenCalledWith( - 'Warning: `popupPlacement` is deprecated. Please use `placement` instead.', - ); - expect(wrapper.exists('.legacy-cls')).toBeTruthy(); - expect(wrapper.find('Trigger').prop('popupPlacement')).toEqual('topRight'); errorSpy.mockRestore(); }); @@ -604,7 +596,7 @@ describe('Cascader.Basic', () => { }, ]; const wrapper = mount( - + , ); @@ -616,7 +608,7 @@ describe('Cascader.Basic', () => { const wrapper = mount( (
{menus} diff --git a/tests/private.spec.tsx b/tests/private.spec.tsx index ab9ff361..08518fb8 100644 --- a/tests/private.spec.tsx +++ b/tests/private.spec.tsx @@ -21,7 +21,7 @@ describe('Cascader.Private', () => { ]} open prefixCls="bamboo" - dropdownPrefixCls="little" + popupPrefixCls="little" />, ); From 4807756d00193a0808e462d87de65982be29c5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=B1=AA?= <1844749591@qq.com> Date: Tue, 4 Mar 2025 11:05:58 +0800 Subject: [PATCH 02/11] chore: adjust logic --- package.json | 5 +++-- src/Cascader.tsx | 2 +- src/hooks/useOptions.ts | 2 +- src/utils/treeUtil.ts | 2 +- tsconfig.json | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 9ecb80d7..5c2d9b9e 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "build": "dumi build", "compile": "father build", "coverage": "father test --coverage", + "tsc": "bunx tsc --noEmit", "deploy": "UMI_ENV=gh npm run build && gh-pages -d dist", "lint": "eslint src/ examples/ --ext .tsx,.ts,.jsx,.jsx", "now-build": "npm run build", @@ -55,8 +56,8 @@ "@types/classnames": "^2.2.6", "@types/enzyme": "^3.1.15", "@types/jest": "^29.4.0", - "@types/react": "^18.0.38", - "@types/react-dom": "^18.0.11", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", "@types/warning": "^3.0.0", "@umijs/fabric": "^4.0.0", "array-tree-filter": "^3.0.2", diff --git a/src/Cascader.tsx b/src/Cascader.tsx index 660dc3f8..94cf521b 100644 --- a/src/Cascader.tsx +++ b/src/Cascader.tsx @@ -153,7 +153,7 @@ export interface CascaderProps< ) => void; } -export type SingleValueType = (string | number)[]; +export type SingleValueType = React.Key[]; export type InternalValueType = SingleValueType | SingleValueType[]; export interface InternalFieldNames extends Required { diff --git a/src/hooks/useOptions.ts b/src/hooks/useOptions.ts index ea4c93f9..01e2ca69 100644 --- a/src/hooks/useOptions.ts +++ b/src/hooks/useOptions.ts @@ -22,7 +22,7 @@ export default function useOptions( const keyPathEntities = getPathKeyEntities(); return pathKeys.map(pathKey => { - const { nodes } = keyPathEntities[pathKey]; + const { nodes } = keyPathEntities[pathKey as string]; return nodes.map(node => (node as Record)[mergedFieldNames.value]); }); diff --git a/src/utils/treeUtil.ts b/src/utils/treeUtil.ts index b514a7d8..e89e5a13 100644 --- a/src/utils/treeUtil.ts +++ b/src/utils/treeUtil.ts @@ -16,7 +16,7 @@ export function formatStrategyValues( const keyPathEntities = getKeyPathEntities(); return pathKeys.filter(key => { - const entity = keyPathEntities[key]; + const entity = keyPathEntities[key as string]; const parent = entity ? entity.parent : null; const children = entity ? entity.children : null; diff --git a/tsconfig.json b/tsconfig.json index f0d983d0..299bbc7e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,7 @@ "paths": { "@/*": ["src/*"], "@@/*": ["src/.umi/*"], - "rc-cascader": ["src/index.ts"] + "@rc-component/cascader": ["src/index.ts"] } } } From f76b4ecfca0514f449a56fc20a99c4cce4ec63bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=B1=AA?= <1844749591@qq.com> Date: Tue, 4 Mar 2025 11:14:48 +0800 Subject: [PATCH 03/11] chore: remove useless code --- src/Cascader.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Cascader.tsx b/src/Cascader.tsx index ad0e32d3..6101ebf7 100644 --- a/src/Cascader.tsx +++ b/src/Cascader.tsx @@ -368,11 +368,6 @@ const Cascader = React.forwardRef((props, re onInternalSelect(valueCells); }; - // ============================ Open ============================ - const mergedOpen = open !== undefined ? open : popupVisible; - - const mergedPlacement = placement || popupPlacement; - const onInternalPopupVisibleChange = (nextVisible: boolean) => { onPopupVisibleChange?.(nextVisible); }; From f5693696bc4fb1f91eb94116430dc44f8c059ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=B1=AA?= <1844749591@qq.com> Date: Tue, 4 Mar 2025 12:47:11 +0800 Subject: [PATCH 04/11] refactor: rename to popup --- docs/demo/dropdown-render.md | 8 -------- docs/demo/popup-render.md | 8 ++++++++ examples/{dropdown-render.tsx => popup-render.tsx} | 2 +- tests/__snapshots__/index.spec.tsx.snap | 8 ++++---- tests/index.spec.tsx | 14 +++++++------- tests/private.spec.tsx | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) delete mode 100644 docs/demo/dropdown-render.md create mode 100644 docs/demo/popup-render.md rename examples/{dropdown-render.tsx => popup-render.tsx} (95%) diff --git a/docs/demo/dropdown-render.md b/docs/demo/dropdown-render.md deleted file mode 100644 index ee9f20f0..00000000 --- a/docs/demo/dropdown-render.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: dropdown-render -nav: - title: Demo - path: /demo ---- - - diff --git a/docs/demo/popup-render.md b/docs/demo/popup-render.md new file mode 100644 index 00000000..692731bd --- /dev/null +++ b/docs/demo/popup-render.md @@ -0,0 +1,8 @@ +--- +title: popup-render +nav: + title: Demo + path: /demo +--- + + diff --git a/examples/dropdown-render.tsx b/examples/popup-render.tsx similarity index 95% rename from examples/dropdown-render.tsx rename to examples/popup-render.tsx index 63f181bc..71abd581 100644 --- a/examples/dropdown-render.tsx +++ b/examples/popup-render.tsx @@ -74,7 +74,7 @@ const Demo = () => {
{menus}
- Hey, DropdownRender, Long DropdownRender, Long DropdownRender + Hey, popupRender, Long popupRender, Long popupRender
)} > diff --git a/tests/__snapshots__/index.spec.tsx.snap b/tests/__snapshots__/index.spec.tsx.snap index 6feee02a..17ebb6e1 100644 --- a/tests/__snapshots__/index.spec.tsx.snap +++ b/tests/__snapshots__/index.spec.tsx.snap @@ -60,14 +60,14 @@ exports[`Cascader.Basic should not show title when title is falsy 1`] = ` `; -exports[`Cascader.Basic should render custom dropdown correctly 1`] = ` +exports[`Cascader.Basic should render custom popup correctly 1`] = `

- Hello, DropdownRender + Hello, popupRender
diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index 689a6246..b2f0a01f 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -604,16 +604,16 @@ describe('Cascader.Basic', () => { expect(menus.render()).toMatchSnapshot(); }); - it('should render custom dropdown correctly', () => { + it('should render custom popup correctly', () => { const wrapper = mount( ( -
+
{menus}
- Hello, DropdownRender + Hello, popupRender
)} > @@ -621,10 +621,10 @@ describe('Cascader.Basic', () => { , ); - const customDropdown = wrapper.find('.custom-dropdown'); - expect(customDropdown.length).toBe(1); - const customDropdownContent = wrapper.find('.custom-dropdown-content'); - expect(customDropdownContent.length).toBe(1); + const customPopup = wrapper.find('.custom-popup'); + expect(customPopup.length).toBe(1); + const customPopupContent = wrapper.find('.custom-popup-content'); + expect(customPopupContent.length).toBe(1); const menus = wrapper.find('.rc-cascader-dropdown'); expect(menus.render()).toMatchSnapshot(); }); diff --git a/tests/private.spec.tsx b/tests/private.spec.tsx index 08518fb8..7fd79c17 100644 --- a/tests/private.spec.tsx +++ b/tests/private.spec.tsx @@ -3,7 +3,7 @@ import React from 'react'; import Cascader from '../src'; describe('Cascader.Private', () => { - it('dropdownPrefixCls', () => { + it('popupPrefixCls', () => { const { container } = render( Date: Wed, 5 Mar 2025 19:11:10 +0800 Subject: [PATCH 05/11] chore: change import path --- package.json | 4 ++-- src/hooks/useEntities.ts | 4 ++-- src/hooks/useSelect.ts | 2 +- src/hooks/useValues.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 104560c3..234d85ad 100644 --- a/package.json +++ b/package.json @@ -44,9 +44,9 @@ }, "dependencies": { "@rc-component/select": "~1.0.0", + "@rc-component/tree": "~1.0.0", "@rc-component/util": "^1.2.1", - "classnames": "^2.3.1", - "rc-tree": "~5.13.1" + "classnames": "^2.3.1" }, "devDependencies": { "@rc-component/father-plugin": "^2.0.2", diff --git a/src/hooks/useEntities.ts b/src/hooks/useEntities.ts index 47a83207..9724516c 100644 --- a/src/hooks/useEntities.ts +++ b/src/hooks/useEntities.ts @@ -1,7 +1,7 @@ import * as React from 'react'; -import { convertDataToEntities } from 'rc-tree/lib/utils/treeUtil'; +import { convertDataToEntities } from '@rc-component/tree/lib/utils/treeUtil'; import type { DefaultOptionType, InternalFieldNames } from '../Cascader'; -import type { DataEntity, DataNode } from 'rc-tree/lib/interface'; +import type { DataEntity, DataNode } from '@rc-component/tree/lib/interface'; import { VALUE_SPLIT } from '../utils/commonUtil'; export interface OptionsInfo { diff --git a/src/hooks/useSelect.ts b/src/hooks/useSelect.ts index 9c6b6540..2fef3dcc 100644 --- a/src/hooks/useSelect.ts +++ b/src/hooks/useSelect.ts @@ -1,4 +1,4 @@ -import { conductCheck } from 'rc-tree/lib/utils/conductUtil'; +import { conductCheck } from '@rc-component/tree/lib/utils/conductUtil'; import type { InternalValueType, ShowCheckedStrategy, SingleValueType } from '../Cascader'; import { toPathKey, toPathKeys } from '../utils/commonUtil'; import { formatStrategyValues } from '../utils/treeUtil'; diff --git a/src/hooks/useValues.ts b/src/hooks/useValues.ts index c2abfd0f..ddae685b 100644 --- a/src/hooks/useValues.ts +++ b/src/hooks/useValues.ts @@ -1,5 +1,5 @@ -import type { DataEntity } from 'rc-tree/lib/interface'; -import { conductCheck } from 'rc-tree/lib/utils/conductUtil'; +import type { DataEntity } from '@rc-component/tree/lib/interface'; +import { conductCheck } from '@rc-component/tree/lib/utils/conductUtil'; import * as React from 'react'; import type { SingleValueType } from '../Cascader'; import { toPathKeys } from '../utils/commonUtil'; From ced37ee1aeaaed2c61127d8c40ed4a6a090e9885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=B1=AA?= <1844749591@qq.com> Date: Wed, 5 Mar 2025 21:05:58 +0800 Subject: [PATCH 06/11] chore: remove useless test case --- tests/index.spec.tsx | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index b2f0a01f..bc124832 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -1,5 +1,4 @@ import { spyElementPrototypes } from '@rc-component/util/lib/test/domHook'; -import { resetWarned } from '@rc-component/util/lib/warning'; import React, { useEffect, useState } from 'react'; import type { CascaderRef, BaseOptionType, CascaderProps } from '../src'; import Cascader from '../src'; @@ -514,24 +513,6 @@ describe('Cascader.Basic', () => { expect(wrapper.isOpen()).toBeTruthy(); }); - it('warning onPopupVisibleChange & popupClassName', () => { - resetWarned(); - const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - const onPopupVisibleChange = jest.fn(); - const wrapper = mount( - , - ); - - expect(wrapper.exists('.legacy-cls')).toBeTruthy(); - - errorSpy.mockRestore(); - }); - it('should support custom expand icon(text icon)', () => { const wrapper = mount( Date: Wed, 5 Mar 2025 21:10:15 +0800 Subject: [PATCH 07/11] chore: remove compatible logic --- src/Cascader.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Cascader.tsx b/src/Cascader.tsx index 6101ebf7..d4d73d6f 100644 --- a/src/Cascader.tsx +++ b/src/Cascader.tsx @@ -103,8 +103,6 @@ interface BaseCascaderProps< loadData?: (selectOptions: OptionType[]) => void; popupClassName?: string; - /** @deprecated Use `popupMenuColumnStyle` instead */ - dropdownMenuColumnStyle?: React.CSSProperties; popupMenuColumnStyle?: React.CSSProperties; placement?: Placement; @@ -212,7 +210,6 @@ const Cascader = React.forwardRef((props, re open, popupClassName, - dropdownMenuColumnStyle, popupMenuColumnStyle, popupStyle: customPopupStyle, @@ -372,7 +369,6 @@ const Cascader = React.forwardRef((props, re onPopupVisibleChange?.(nextVisible); }; - const mergedPopupMenuColumnStyle = popupMenuColumnStyle || dropdownMenuColumnStyle; // ========================== Warning =========================== if (process.env.NODE_ENV !== 'production') { @@ -395,7 +391,7 @@ const Cascader = React.forwardRef((props, re expandTrigger, expandIcon, loadingIcon, - popupMenuColumnStyle: mergedPopupMenuColumnStyle, + popupMenuColumnStyle, optionRender, }), [ @@ -412,7 +408,7 @@ const Cascader = React.forwardRef((props, re expandTrigger, expandIcon, loadingIcon, - mergedPopupMenuColumnStyle, + popupMenuColumnStyle, optionRender, ], ); From 39a61a8ab2246eede5346ed1d7f5cf0baf36d8c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=B1=AA?= <1844749591@qq.com> Date: Wed, 5 Mar 2025 21:15:09 +0800 Subject: [PATCH 08/11] revert --- src/hooks/useOptions.ts | 2 +- src/utils/treeUtil.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/useOptions.ts b/src/hooks/useOptions.ts index 01e2ca69..ea4c93f9 100644 --- a/src/hooks/useOptions.ts +++ b/src/hooks/useOptions.ts @@ -22,7 +22,7 @@ export default function useOptions( const keyPathEntities = getPathKeyEntities(); return pathKeys.map(pathKey => { - const { nodes } = keyPathEntities[pathKey as string]; + const { nodes } = keyPathEntities[pathKey]; return nodes.map(node => (node as Record)[mergedFieldNames.value]); }); diff --git a/src/utils/treeUtil.ts b/src/utils/treeUtil.ts index e89e5a13..b514a7d8 100644 --- a/src/utils/treeUtil.ts +++ b/src/utils/treeUtil.ts @@ -16,7 +16,7 @@ export function formatStrategyValues( const keyPathEntities = getKeyPathEntities(); return pathKeys.filter(key => { - const entity = keyPathEntities[key as string]; + const entity = keyPathEntities[key]; const parent = entity ? entity.parent : null; const children = entity ? entity.children : null; From c911ae5d2f98d961fd1ed4fe959cfc6251127ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=B1=AA?= <1844749591@qq.com> Date: Wed, 5 Mar 2025 21:18:10 +0800 Subject: [PATCH 09/11] revert --- src/Cascader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cascader.tsx b/src/Cascader.tsx index d4d73d6f..84bbad18 100644 --- a/src/Cascader.tsx +++ b/src/Cascader.tsx @@ -160,7 +160,7 @@ export interface CascaderProps< ) => void; } -export type SingleValueType = React.Key[]; +export type SingleValueType = (string | number)[]; export type InternalValueType = SingleValueType | SingleValueType[]; export interface InternalFieldNames extends Required { From 96b19eef762f96f6aabbfed2faf4b625510759b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=B1=AA?= <1844749591@qq.com> Date: Wed, 5 Mar 2025 22:59:49 +0800 Subject: [PATCH 10/11] refactor: update key logic --- src/Cascader.tsx | 3 +++ src/OptionList/List.tsx | 8 ++++---- src/OptionList/useActive.ts | 5 +++-- src/OptionList/useKeyboard.ts | 10 +++++----- src/hooks/useOptions.ts | 6 +++--- src/hooks/useSelect.ts | 6 +++--- src/hooks/useValues.ts | 4 ++-- src/utils/treeUtil.ts | 3 ++- 8 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/Cascader.tsx b/src/Cascader.tsx index 84bbad18..8fdd65ce 100644 --- a/src/Cascader.tsx +++ b/src/Cascader.tsx @@ -161,6 +161,9 @@ export interface CascaderProps< } export type SingleValueType = (string | number)[]; + +export type LegacyKey = string | number; + export type InternalValueType = SingleValueType | SingleValueType[]; export interface InternalFieldNames extends Required { diff --git a/src/OptionList/List.tsx b/src/OptionList/List.tsx index d4763bfb..720ef56a 100644 --- a/src/OptionList/List.tsx +++ b/src/OptionList/List.tsx @@ -3,7 +3,7 @@ import classNames from 'classnames'; import type { useBaseProps } from '@rc-component/select'; import type { RefOptionListProps } from '@rc-component/select/lib/OptionList'; import * as React from 'react'; -import type { DefaultOptionType, SingleValueType } from '../Cascader'; +import type { DefaultOptionType, LegacyKey, SingleValueType } from '../Cascader'; import CascaderContext from '../context'; import { getFullPathKeys, @@ -62,9 +62,9 @@ const RawOptionList = React.forwardRef(( const mergedPrefixCls = popupPrefixCls || prefixCls; // ========================= loadData ========================= - const [loadingKeys, setLoadingKeys] = React.useState([]); + const [loadingKeys, setLoadingKeys] = React.useState([]); - const internalLoadData = (valueCells: React.Key[]) => { + const internalLoadData = (valueCells: LegacyKey[]) => { // Do not load when search if (!loadData || searchValue) { return; @@ -108,7 +108,7 @@ const RawOptionList = React.forwardRef(( const [activeValueCells, setActiveValueCells] = useActive(multiple, open); // =========================== Path =========================== - const onPathOpen = (nextValueCells: React.Key[]) => { + const onPathOpen = (nextValueCells: LegacyKey[]) => { setActiveValueCells(nextValueCells); // Trigger loadData diff --git a/src/OptionList/useActive.ts b/src/OptionList/useActive.ts index ca0519ec..12482716 100644 --- a/src/OptionList/useActive.ts +++ b/src/OptionList/useActive.ts @@ -1,5 +1,6 @@ import * as React from 'react'; import CascaderContext from '../context'; +import { LegacyKey } from '@/Cascader'; /** * Control the active open options path. @@ -7,14 +8,14 @@ import CascaderContext from '../context'; const useActive = ( multiple?: boolean, open?: boolean, -): [React.Key[], (activeValueCells: React.Key[]) => void] => { +): [LegacyKey[], (activeValueCells: LegacyKey[]) => void] => { const { values } = React.useContext(CascaderContext); const firstValueCells = values[0]; // Record current dropdown active options // This also control the open status - const [activeValueCells, setActiveValueCells] = React.useState([]); + const [activeValueCells, setActiveValueCells] = React.useState([]); React.useEffect( () => { diff --git a/src/OptionList/useKeyboard.ts b/src/OptionList/useKeyboard.ts index cf4ccfa5..239f357e 100644 --- a/src/OptionList/useKeyboard.ts +++ b/src/OptionList/useKeyboard.ts @@ -1,7 +1,7 @@ import type { RefOptionListProps } from '@rc-component/select/lib/OptionList'; import KeyCode from '@rc-component/util/lib/KeyCode'; import * as React from 'react'; -import type { DefaultOptionType, InternalFieldNames, SingleValueType } from '../Cascader'; +import type { DefaultOptionType, InternalFieldNames, LegacyKey, SingleValueType } from '../Cascader'; import { SEARCH_MARK } from '../hooks/useSearchOptions'; import { getFullPathKeys, toPathKey } from '../utils/commonUtil'; @@ -9,8 +9,8 @@ export default ( ref: React.Ref, options: DefaultOptionType[], fieldNames: InternalFieldNames, - activeValueCells: React.Key[], - setActiveValueCells: (activeValueCells: React.Key[]) => void, + activeValueCells: LegacyKey[], + setActiveValueCells: (activeValueCells: LegacyKey[]) => void, onKeyBoardSelect: (valueCells: SingleValueType, option: DefaultOptionType) => void, contextProps: { direction?: 'ltr' | 'rtl'; @@ -28,7 +28,7 @@ export default ( let currentOptions = options; const mergedActiveIndexes: number[] = []; - const mergedActiveValueCells: React.Key[] = []; + const mergedActiveValueCells: LegacyKey[] = []; const len = activeValueCells.length; @@ -64,7 +64,7 @@ export default ( }, [activeValueCells, fieldNames, options]); // Update active value cells and scroll to target element - const internalSetActiveValueCells = (next: React.Key[]) => { + const internalSetActiveValueCells = (next: LegacyKey[]) => { setActiveValueCells(next); }; diff --git a/src/hooks/useOptions.ts b/src/hooks/useOptions.ts index ea4c93f9..e52d58c1 100644 --- a/src/hooks/useOptions.ts +++ b/src/hooks/useOptions.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import type { DefaultOptionType } from '..'; -import type { InternalFieldNames, SingleValueType } from '../Cascader'; +import type { InternalFieldNames, SingleValueType, LegacyKey } from '../Cascader'; import useEntities, { type GetEntities } from './useEntities'; export default function useOptions( @@ -9,7 +9,7 @@ export default function useOptions( ): [ mergedOptions: DefaultOptionType[], getPathKeyEntities: GetEntities, - getValueByKeyPath: (pathKeys: React.Key[]) => SingleValueType[], + getValueByKeyPath: (pathKeys: LegacyKey[]) => SingleValueType[], ] { const mergedOptions = React.useMemo(() => options || [], [options]); @@ -18,7 +18,7 @@ export default function useOptions( /** Convert path key back to value format */ const getValueByKeyPath = React.useCallback( - (pathKeys: React.Key[]): SingleValueType[] => { + (pathKeys: LegacyKey[]): SingleValueType[] => { const keyPathEntities = getPathKeyEntities(); return pathKeys.map(pathKey => { diff --git a/src/hooks/useSelect.ts b/src/hooks/useSelect.ts index 2fef3dcc..f1f00c1a 100644 --- a/src/hooks/useSelect.ts +++ b/src/hooks/useSelect.ts @@ -1,5 +1,5 @@ import { conductCheck } from '@rc-component/tree/lib/utils/conductUtil'; -import type { InternalValueType, ShowCheckedStrategy, SingleValueType } from '../Cascader'; +import type { InternalValueType, LegacyKey, ShowCheckedStrategy, SingleValueType } from '../Cascader'; import { toPathKey, toPathKeys } from '../utils/commonUtil'; import { formatStrategyValues } from '../utils/treeUtil'; import type { GetEntities } from './useEntities'; @@ -11,7 +11,7 @@ export default function useSelect( halfCheckedValues: SingleValueType[], missingCheckedValues: SingleValueType[], getPathKeyEntities: GetEntities, - getValueByKeyPath: (pathKeys: React.Key[]) => SingleValueType[], + getValueByKeyPath: (pathKeys: LegacyKey[]) => SingleValueType[], showCheckedStrategy?: ShowCheckedStrategy, ) { return (valuePath: SingleValueType) => { @@ -46,7 +46,7 @@ export default function useSelect( const pathKeyEntities = getPathKeyEntities(); // Conduction by selected or not - let checkedKeys: React.Key[]; + let checkedKeys: LegacyKey[]; if (existInChecked) { ({ checkedKeys } = conductCheck( nextRawCheckedKeys, diff --git a/src/hooks/useValues.ts b/src/hooks/useValues.ts index ddae685b..d8241738 100644 --- a/src/hooks/useValues.ts +++ b/src/hooks/useValues.ts @@ -1,7 +1,7 @@ import type { DataEntity } from '@rc-component/tree/lib/interface'; import { conductCheck } from '@rc-component/tree/lib/utils/conductUtil'; import * as React from 'react'; -import type { SingleValueType } from '../Cascader'; +import type { LegacyKey, SingleValueType } from '../Cascader'; import { toPathKeys } from '../utils/commonUtil'; import type { GetMissValues } from './useMissingValues'; @@ -9,7 +9,7 @@ export default function useValues( multiple: boolean, rawValues: SingleValueType[], getPathKeyEntities: () => Record, - getValueByKeyPath: (pathKeys: React.Key[]) => SingleValueType[], + getValueByKeyPath: (pathKeys: LegacyKey[]) => SingleValueType[], getMissingValues: GetMissValues, ): [ checkedValues: SingleValueType[], diff --git a/src/utils/treeUtil.ts b/src/utils/treeUtil.ts index b514a7d8..7b46cd33 100644 --- a/src/utils/treeUtil.ts +++ b/src/utils/treeUtil.ts @@ -3,12 +3,13 @@ import type { DefaultOptionType, InternalFieldNames, ShowCheckedStrategy, + LegacyKey, } from '../Cascader'; import type { GetEntities } from '../hooks/useEntities'; import { SHOW_CHILD } from './commonUtil'; export function formatStrategyValues( - pathKeys: React.Key[], + pathKeys: LegacyKey[], getKeyPathEntities: GetEntities, showCheckedStrategy?: ShowCheckedStrategy, ) { From f442210323c0ab3ca24083034ecacb21a067f733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=B1=AA?= <1844749591@qq.com> Date: Thu, 6 Mar 2025 11:13:18 +0800 Subject: [PATCH 11/11] fix: type error --- src/hooks/useSelect.ts | 13 ++++++++++--- src/hooks/useValues.ts | 5 ++++- src/utils/treeUtil.ts | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/hooks/useSelect.ts b/src/hooks/useSelect.ts index f1f00c1a..35bda7d1 100644 --- a/src/hooks/useSelect.ts +++ b/src/hooks/useSelect.ts @@ -1,5 +1,10 @@ import { conductCheck } from '@rc-component/tree/lib/utils/conductUtil'; -import type { InternalValueType, LegacyKey, ShowCheckedStrategy, SingleValueType } from '../Cascader'; +import type { + InternalValueType, + LegacyKey, + ShowCheckedStrategy, + SingleValueType, +} from '../Cascader'; import { toPathKey, toPathKeys } from '../utils/commonUtil'; import { formatStrategyValues } from '../utils/treeUtil'; import type { GetEntities } from './useEntities'; @@ -52,9 +57,11 @@ export default function useSelect( nextRawCheckedKeys, { checked: false, halfCheckedKeys: halfCheckedPathKeys }, pathKeyEntities, - )); + ) as { checkedKeys: LegacyKey[] }); } else { - ({ checkedKeys } = conductCheck(nextRawCheckedKeys, true, pathKeyEntities)); + ({ checkedKeys } = conductCheck(nextRawCheckedKeys, true, pathKeyEntities) as { + checkedKeys: LegacyKey[]; + }); } // Roll up to parent level keys diff --git a/src/hooks/useValues.ts b/src/hooks/useValues.ts index d8241738..68526d49 100644 --- a/src/hooks/useValues.ts +++ b/src/hooks/useValues.ts @@ -27,7 +27,10 @@ export default function useValues( const keyPathValues = toPathKeys(existValues); const keyPathEntities = getPathKeyEntities(); - const { checkedKeys, halfCheckedKeys } = conductCheck(keyPathValues, true, keyPathEntities); + const { checkedKeys, halfCheckedKeys } = conductCheck(keyPathValues, true, keyPathEntities) as { + checkedKeys: LegacyKey[]; + halfCheckedKeys: LegacyKey[]; + }; // Convert key back to value cells return [getValueByKeyPath(checkedKeys), getValueByKeyPath(halfCheckedKeys), missingValues]; diff --git a/src/utils/treeUtil.ts b/src/utils/treeUtil.ts index 7b46cd33..f2810a53 100644 --- a/src/utils/treeUtil.ts +++ b/src/utils/treeUtil.ts @@ -26,8 +26,8 @@ export function formatStrategyValues( } return showCheckedStrategy === SHOW_CHILD - ? !(children && children.some(child => child.key && valueSet.has(child.key))) - : !(parent && !parent.node.disabled && valueSet.has(parent.key)); + ? !(children && children.some(child => child.key && valueSet.has(child.key as LegacyKey))) + : !(parent && !parent.node.disabled && valueSet.has(parent.key as LegacyKey)); }); }