diff --git a/docs/examples/multiple.tsx b/docs/examples/multiple.tsx index 0510eed20..a76ffba07 100644 --- a/docs/examples/multiple.tsx +++ b/docs/examples/multiple.tsx @@ -23,6 +23,16 @@ const sharedLocale = { style: { width: 300 }, }; +const maxTagPlaceholder = (value) => { + return ( + + ); +}; + export default () => { const singleRef = React.useRef(null); @@ -30,10 +40,20 @@ export default () => {
- + +
); }; diff --git a/src/PickerInput/Selector/SingleSelector/MultipleDates.tsx b/src/PickerInput/Selector/SingleSelector/MultipleDates.tsx index 670e7ba47..2ae4d50f6 100644 --- a/src/PickerInput/Selector/SingleSelector/MultipleDates.tsx +++ b/src/PickerInput/Selector/SingleSelector/MultipleDates.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import type { PickerProps } from '../../SinglePicker'; export interface MultipleDatesProps - extends Pick { + extends Pick { prefixCls: string; value: DateType[]; onRemove: (value: DateType) => void; @@ -25,6 +25,7 @@ export default function MultipleDates( formatDate, disabled, maxTagCount, + maxTagPlaceholder, placeholder, } = props; @@ -68,8 +69,10 @@ export default function MultipleDates( // ========================= Rest ========================= function renderRest(omittedValues: DateType[]) { - const content = `+ ${omittedValues.length} ...`; - + const content = + typeof maxTagPlaceholder === 'function' + ? maxTagPlaceholder(omittedValues) + : maxTagPlaceholder; return renderSelector(content); } diff --git a/src/PickerInput/Selector/SingleSelector/index.tsx b/src/PickerInput/Selector/SingleSelector/index.tsx index f8b56a832..767da8e34 100644 --- a/src/PickerInput/Selector/SingleSelector/index.tsx +++ b/src/PickerInput/Selector/SingleSelector/index.tsx @@ -12,7 +12,7 @@ import MultipleDates from './MultipleDates'; export interface SingleSelectorProps extends SelectorProps, - Pick { + Pick { id?: string; value?: DateType[]; @@ -75,6 +75,7 @@ function SingleSelector( onInputChange, multiple, maxTagCount, + maxTagPlaceholder = (omittedValues: DateType[]) => `+ ${omittedValues.length} ...`, // Valid format, @@ -170,6 +171,7 @@ function SingleSelector( onRemove={onMultipleRemove} formatDate={getText} maxTagCount={maxTagCount} + maxTagPlaceholder={maxTagPlaceholder} disabled={disabled} removeIcon={removeIcon} placeholder={placeholder} diff --git a/src/PickerInput/SinglePicker.tsx b/src/PickerInput/SinglePicker.tsx index c773fbd09..23fee4b67 100644 --- a/src/PickerInput/SinglePicker.tsx +++ b/src/PickerInput/SinglePicker.tsx @@ -46,6 +46,7 @@ export interface BasePickerProps removeIcon?: React.ReactNode; /** Only work when `multiple` is in used */ maxTagCount?: number | 'responsive'; + maxTagPlaceholder?: React.ReactNode | ((omittedValues: DateType[]) => React.ReactNode); // Value value?: DateType | DateType[] | null; diff --git a/tests/multiple.spec.tsx b/tests/multiple.spec.tsx index 67fa69df4..54c0c397c 100644 --- a/tests/multiple.spec.tsx +++ b/tests/multiple.spec.tsx @@ -155,6 +155,115 @@ describe('Picker.Multiple', () => { ).toBeFalsy(); }); }); + describe('maxTagPlaceholder', () => { + it('should not show maxTagPlaceholder when items count is within maxTagCount', () => { + const maxTagPlaceholder = (omittedValues: any[]) => ( + +{omittedValues.length} more + ); + + const { container } = render( + , + ); + + // Should show all items, no placeholder + expect(container.querySelectorAll('.rc-picker-selection-item')).toHaveLength(2); + expect(container.querySelector('.custom-max-tag-placeholder')).toBeFalsy(); + }); + + it('should show maxTagPlaceholder when items count exceeds maxTagCount', () => { + const maxTagPlaceholder = (omittedValues: any[]) => ( + +{omittedValues.length} items + ); + + const { container } = render( + , + ); + + // Should show maxTagCount items + placeholder + expect(container.querySelectorAll('.rc-picker-selection-item')).toHaveLength(3); + expect(container.querySelector('.custom-max-tag-placeholder').textContent).toBe('+2 items'); + }); + + it('should work with custom maxTagPlaceholder component', () => { + const CustomPlaceholder = ({ omittedValues }: { omittedValues: any[] }) => ( +
+ {omittedValues.length} + hidden dates +
+ ); + + const { container } = render( + } + defaultValue={[getDay('2000-01-01'), getDay('2000-01-02'), getDay('2000-01-03')]} + />, + ); + + expect(container.querySelector('.custom-placeholder-wrapper')).toBeTruthy(); + expect(container.querySelector('.omitted-count').textContent).toBe('2'); + expect(container.querySelector('.omitted-text').textContent).toBe('hidden dates'); + }); + + it('should handle maxTagCount edge cases1', () => { + const maxTagPlaceholder = (omittedValues: any[]) => ( + +{omittedValues.length} + ); + + // Test maxTagCount = 0 + const { container } = render( + , + ); + expect(container.querySelectorAll('.rc-picker-selection-item')).toHaveLength(1); + expect(container.querySelector('.edge-case-placeholder')).toBeTruthy(); + expect(container.querySelector('.edge-case-placeholder').textContent).toBe('+1'); + }); + + it('should pass correct omittedValues to maxTagPlaceholder', () => { + const maxTagPlaceholder = jest.fn((omittedValues) => ( + +{omittedValues.length} + )); + + const values = [ + getDay('2000-01-01'), + getDay('2000-01-02'), + getDay('2000-01-03'), + getDay('2000-01-04'), + ]; + + render( + , + ); + + expect(maxTagPlaceholder).toHaveBeenCalledWith([values[2], values[3]]); + }); + }); it('click year panel should not select', () => { const onChange = jest.fn();