diff --git a/src/list-picker/interface.ts b/src/list-picker/interface.ts index b9f897114d..51da8eeb24 100644 --- a/src/list-picker/interface.ts +++ b/src/list-picker/interface.ts @@ -5,7 +5,10 @@ import { Placement, TriggerAction } from '../popover/interface'; import { ListProps } from '../list'; export interface ListPickerProps - extends Pick { + extends Pick< + ListProps, + 'model' | 'empty' | 'needEmpty' | 'max' | 'valueSeparator' | 'onMultipleOverflow' | 'onMultipleChange' + > { size?: 'small' | 'normal'; /** * 触发方式 diff --git a/src/list-picker/listPicker.tsx b/src/list-picker/listPicker.tsx index be84750008..d81543d636 100644 --- a/src/list-picker/listPicker.tsx +++ b/src/list-picker/listPicker.tsx @@ -16,8 +16,6 @@ import { callbackOnOverflow } from '../list/util'; const DEFAULT_DATA_TESTID = 'list-picker'; - - export const ListPicker: React.FC = (props) => { const localeTextObject: typeof defaultLocaleTextObject = useLocale('ListPicker') || defaultLocaleTextObject; const { @@ -32,6 +30,7 @@ export const ListPicker: React.FC = (props) => { onVisibleChange, onChange, onMultipleOverflow, + onMultipleChange, customTrigger: propsRenderTrigger, prefixCls = 'list-picker', getContainer, @@ -68,18 +67,18 @@ export const ListPicker: React.FC = (props) => { const [visible, setVisible] = useControlledState(controlledVisible, false); const [value, setValue] = useState(defaultValue); // use multiple and needConfirm, listPicker use prevValue instead of value - const [prevValue, setPrevValue] = useState( - model === 'multiple' && needConfirm ? defaultValue || [] : undefined - ); - const { options, setOptions, getOptionByValue, getLabelByValue, getOptionTreeByValue, getOptionsByValue } = useCacheOptions(); + const [prevValue, setPrevValue] = useState(model === 'multiple' && needConfirm ? defaultValue || [] : undefined); + + const { options, setOptions, getOptionByValue, getLabelByValue, getOptionTreeByValue, getOptionsByValue } = + useCacheOptions(); const triggerRef = useRef(undefined); // ========== control ========== useEffect(() => { setValue(controlledValue); }, [controlledValue, setValue]); - // when controlledValue, use multiple and needConfirm - // update prevValue, + // when controlledValue, use multiple and needConfirm + // update prevValue, // prevValue and value are in sync useEffect(() => { if (model === 'multiple' && needConfirm && Array.isArray(controlledValue) && !isEqual(controlledValue, prevValue)) { @@ -91,19 +90,22 @@ export const ListPicker: React.FC = (props) => { // use confirm,when without onconfirm click, return prevValue if (needConfirm && !visible && !isEqual(controlledValue, value)) { setValue(prevValue); + if (model === 'multiple') { + onMultipleChange?.(prevValue as any[]); + } } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [visible]); + }, [visible, needConfirm, controlledValue, value, model]); // recent - const setRecentValue = (val?:string |string[])=>{ + const setRecentValue = (val?: string | string[]) => { const localKey = isNil(propsRecentId) ? ITEM_KEY : `${ITEM_KEY}_${propsRecentId}`; - const localStorageValue = localStorage?.getItem(localKey); - const recentKey: string[] = (JSON.parse(isNil(localStorageValue) ? '[]' : localStorageValue) || []).filter( - (v: string) => v !== val - ); - localStorage?.setItem(localKey, JSON.stringify([val, ...recentKey].slice(0, 50))); - } + const localStorageValue = localStorage?.getItem(localKey); + const recentKey: string[] = (JSON.parse(isNil(localStorageValue) ? '[]' : localStorageValue) || []).filter( + (v: string) => v !== val + ); + localStorage?.setItem(localKey, JSON.stringify([val, ...recentKey].slice(0, 50))); + }; // methods const handVisibleChange = (vis: boolean) => { @@ -113,7 +115,7 @@ export const ListPicker: React.FC = (props) => { const handleConfim = () => { handVisibleChange(false); - + // 非受控模式,将value更新至PrevValue if (model === 'multiple' && needConfirm && typeof controlledValue === 'undefined') { setPrevValue(value); @@ -124,13 +126,13 @@ export const ListPicker: React.FC = (props) => { const handleChange = (val?: string | string[], opts?: OptionProps | OptionProps[]) => { if (model !== 'multiple') { setRecentValue(val); - if(typeof controlledValue === 'undefined'){ + if (typeof controlledValue === 'undefined') { setValue(val); } onChange?.(val, opts); handVisibleChange(false); } else { - callbackOnOverflow({ max, model, onMultipleOverflow, value: val }); + callbackOnOverflow({ max, model, onMultipleOverflow, onMultipleChange, value: val }); setValue(val); } }; @@ -183,7 +185,7 @@ export const ListPicker: React.FC = (props) => { ); }; - + // render const renderOverlay = () => (
void; + /** + * 当多选有值修改时,触发此功能 + */ + onMultipleChange?: (value?: Key[]) => void; /** * 仅支持options 形式。自定义 item render 自定义render时会劫持onClick方法提供给List来使用 */ diff --git a/src/list/util.ts b/src/list/util.ts index 4d55c98bb0..2db37881f2 100644 --- a/src/list/util.ts +++ b/src/list/util.ts @@ -158,16 +158,14 @@ export const collectOptions = (childs?: React.ReactNode | OptionProps): OptionPr /** * 多选模式下,如果用户选择超出了定义的最大可选值,将会触发 onMultipleOverflow 回调函数 */ -export const callbackOnOverflow = (params: Pick): void => { - const { max, model, value, onMultipleOverflow } = params; - // prettier-ignore - if ( - model === 'multiple' && - Array.isArray(value) && - max !== undefined && - value.length >= max && - onMultipleOverflow - ) { - onMultipleOverflow(value); +export const callbackOnOverflow = ( + params: Pick +): void => { + const { max, model, value, onMultipleOverflow, onMultipleChange } = params; + if (model === 'multiple' && Array.isArray(value)) { + onMultipleChange?.(value); + if (Array.isArray(value) && max !== undefined && value.length >= max) { + onMultipleOverflow?.(value); + } } };