diff --git a/src/index.tsx b/src/index.tsx index db48a62..65efdad 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -22,6 +22,11 @@ export interface SegmentedLabeledOption { title?: string; } +type ItemRender = ( + node: React.ReactNode, + info: { item: SegmentedLabeledOption }, +) => React.ReactNode; + type SegmentedOptions = ( | T | SegmentedLabeledOption @@ -44,6 +49,7 @@ export interface SegmentedProps name?: string; classNames?: Partial>; styles?: Partial>; + itemRender?: ItemRender; } function getValidTitle(option: SegmentedLabeledOption) { @@ -80,6 +86,7 @@ const InternalSegmentedOption: React.FC<{ style?: React.CSSProperties; classNames?: Partial>; styles?: Partial>; + data: SegmentedLabeledOption; disabled?: boolean; checked: boolean; label: React.ReactNode; @@ -95,12 +102,14 @@ const InternalSegmentedOption: React.FC<{ onKeyDown: (e: React.KeyboardEvent) => void; onKeyUp: (e: React.KeyboardEvent) => void; onMouseDown: () => void; + itemRender?: ItemRender; }> = ({ prefixCls, className, style, styles, classNames: segmentedClassNames, + data, disabled, checked, label, @@ -113,6 +122,7 @@ const InternalSegmentedOption: React.FC<{ onKeyDown, onKeyUp, onMouseDown, + itemRender = (node: React.ReactNode) => node, }) => { const handleChange = (event: React.ChangeEvent) => { if (disabled) { @@ -120,8 +130,7 @@ const InternalSegmentedOption: React.FC<{ } onChange(event, value); }; - - return ( + const itemContent: React.ReactNode = ( ); + return itemRender(itemContent, { item: data }); }; const Segmented = React.forwardRef( @@ -174,6 +184,7 @@ const Segmented = React.forwardRef( styles, classNames: segmentedClassNames, motionName = 'thumb-motion', + itemRender, ...restProps } = props; @@ -258,6 +269,54 @@ const Segmented = React.forwardRef( break; } }; + + const renderOption = (segmentedOption: SegmentedLabeledOption) => { + const { + label, + value: optionValue, + disabled: optionDisabled, + title, + } = segmentedOption; + const optionData: SegmentedLabeledOption = { + label, + value: optionValue, + disabled: optionDisabled, + title, + }; + return ( + + ); + }; + return (
( setThumbShow(false); }} /> - {segmentedOptions.map((segmentedOption) => ( - - ))} + {segmentedOptions.map(renderOption)}
); diff --git a/tests/index.test.tsx b/tests/index.test.tsx index d1d0844..7fff1b4 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -799,4 +799,47 @@ describe('Segmented keyboard navigation', () => { expect(itemElement.style.color).toBe('yellow'); expect(labelElement.style.backgroundColor).toBe('black'); }); + describe('itemRender', () => { + it('When "itemRender" is not configured, render the original "label"', () => { + const { container } = render( + , + ); + const label = container.querySelector('.rc-segmented-item-label'); + expect(label).toHaveTextContent('iOS'); + }); + it('Configure "itemRender" to render the return value', () => { + const { container } = render( +
{node}
} + />, + ); + const labels = container.querySelectorAll('.test-title'); + expect(labels).toHaveLength(3); + }); + it('should pass complete params to itemRender', () => { + const mockItemRender = jest.fn((node, params) => node); + const testData = { + label: 'iOS', + value: 'iOS', + disabled: false, + title: 'iOS', + }; + render( + , + ); + expect(mockItemRender).toHaveBeenCalledTimes(3); + const callArgs = mockItemRender.mock.calls[0]; + const receivedParams = callArgs[1]; + expect(receivedParams).toEqual({ + item: { + ...testData, + }, + }); + expect(React.isValidElement(callArgs[0])).toBeTruthy(); + }); + }); });

AltStyle によって変換されたページ (->オリジナル) /