From 5a414c4f027de25bb99ceb8c262b01d5b7d9d477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E6=9E=AB?= <645381995@qq.com> Date: Fri, 8 Dec 2023 11:53:00 +0800 Subject: [PATCH 01/10] feat: support generics --- docs/demo/basic.tsx | 12 +- docs/demo/controlled.tsx | 14 +-- docs/demo/refs.tsx | 12 +- package.json | 2 +- src/index.tsx | 247 ++++++++++++++++++++------------------- tsconfig.json | 2 +- 6 files changed, 146 insertions(+), 143 deletions(-) diff --git a/docs/demo/basic.tsx b/docs/demo/basic.tsx index 649a853..49b5caf 100644 --- a/docs/demo/basic.tsx +++ b/docs/demo/basic.tsx @@ -1,8 +1,9 @@ -import '../../assets/style.less'; -import React from 'react'; import Segmented from 'rc-segmented'; +import React from 'react'; -export default function App() { +import '../../assets/style.less'; + +const Demo = () => { return (
@@ -27,8 +28,11 @@ export default function App() { { label: 'Android', value: 'Android', disabled: true }, 'Web', ]} + onChange={(value) => console.log(value, typeof value)} />
); -} +}; + +export default Demo; diff --git a/docs/demo/controlled.tsx b/docs/demo/controlled.tsx index 2546819..d032844 100644 --- a/docs/demo/controlled.tsx +++ b/docs/demo/controlled.tsx @@ -1,15 +1,9 @@ -import '../../assets/style.less'; -import React from 'react'; import Segmented from 'rc-segmented'; -import type { SegmentedValue } from 'rc-segmented'; +import React from 'react'; +import '../../assets/style.less'; -export default class Demo extends React.Component< - unknown, - { value: SegmentedValue } -> { - state = { - value: 'Web3', - }; +export default class Demo extends React.Component { + state = { value: 'Web3' }; render() { return ( diff --git a/docs/demo/refs.tsx b/docs/demo/refs.tsx index 5a7e345..080f7b6 100644 --- a/docs/demo/refs.tsx +++ b/docs/demo/refs.tsx @@ -1,11 +1,11 @@ -import '../../assets/style.less'; -import React from 'react'; import Segmented from 'rc-segmented'; +import React from 'react'; +import '../../assets/style.less'; class ClassComponentWithStringRef extends React.Component { componentDidMount() { // eslint-disable-next-line react/no-string-refs - console.log(this.refs.segmentedRef, 'ref'); + console.log(this.refs.segmentedRef, 'ClassComponentWithStringRef'); } render() { @@ -22,7 +22,7 @@ class ClassComponent2 extends React.Component { segmentedRef: HTMLDivElement | null = null; componentDidMount() { - console.log(this.segmentedRef, 'ref'); + console.log(this.segmentedRef, 'ClassComponent2'); } render() { @@ -42,7 +42,7 @@ class ClassComponentWithCreateRef extends React.Component< segmentedRef = React.createRef(); componentDidMount() { - console.log(this.segmentedRef.current, 'ref'); + console.log(this.segmentedRef.current, 'ClassComponentWithCreateRef'); } render() { @@ -55,7 +55,7 @@ class ClassComponentWithCreateRef extends React.Component< function FunctionalComponent() { const segmentedRef = React.useRef(null); React.useEffect(() => { - console.log(segmentedRef.current, 'ref'); + console.log(segmentedRef.current, 'FunctionalComponent'); }, []); return ; } diff --git a/package.json b/package.json index 057fdb5..780a36e 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "pretty-quick": "pretty-quick", "test": "jest", "coverage": "jest --coverage", - "prepare": "husky install" + "prepare": "husky install && dumi setup" }, "dependencies": { "@babel/runtime": "^7.11.1", diff --git a/src/index.tsx b/src/index.tsx index efb923c..21cac88 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,34 +1,33 @@ -import * as React from 'react'; import classNames from 'classnames'; import useMergedState from 'rc-util/lib/hooks/useMergedState'; -import { composeRef } from 'rc-util/lib/ref'; import omit from 'rc-util/lib/omit'; +import { composeRef } from 'rc-util/lib/ref'; +import * as React from 'react'; import MotionThumb from './MotionThumb'; -export type SegmentedValue = string | number; - -export type SegmentedRawOption = SegmentedValue; - -export interface SegmentedLabeledOption { +export interface SegmentedLabeledOption { className?: string; disabled?: boolean; label: React.ReactNode; - value: SegmentedRawOption; + value: T; /** * html `title` property for label */ title?: string; } -type SegmentedOptions = (SegmentedRawOption | SegmentedLabeledOption)[]; - -export interface SegmentedProps - extends Omit, 'onChange'> { - options: SegmentedOptions; - defaultValue?: SegmentedValue; - value?: SegmentedValue; - onChange?: (value: SegmentedValue) => void; +type SegmentedOptions = (T | SegmentedLabeledOption)[]; + +export interface SegmentedProps + extends Omit< + React.HTMLProps, + 'value' | 'defaultValue' | 'onChange' + > { + options: SegmentedOptions; + defaultValue?: T; + value?: T; + onChange?: (value: T) => void; disabled?: boolean; prefixCls?: string; direction?: 'ltr' | 'rtl'; @@ -72,11 +71,8 @@ const InternalSegmentedOption: React.FC<{ checked: boolean; label: React.ReactNode; title?: string; - value: SegmentedRawOption; - onChange: ( - e: React.ChangeEvent, - value: SegmentedRawOption, - ) => void; + value: React.Key; + onChange: (e: React.ChangeEvent, value: React.Key) => void; }> = ({ prefixCls, className, @@ -115,110 +111,119 @@ const InternalSegmentedOption: React.FC<{ ); }; -const Segmented = React.forwardRef( - (props, ref) => { - const { - prefixCls = 'rc-segmented', - direction, - options = [], - disabled, - defaultValue, - value, - onChange, - className = '', - motionName = 'thumb-motion', - ...restProps - } = props; - - const containerRef = React.useRef(null); - const mergedRef = React.useMemo( - () => composeRef(containerRef, ref), - [containerRef, ref], - ); - - const segmentedOptions = React.useMemo(() => { - return normalizeOptions(options); - }, [options]); - - // Note: We should not auto switch value when value not exist in options - // which may break single source of truth. - const [rawValue, setRawValue] = useMergedState(segmentedOptions[0]?.value, { - value, - defaultValue, - }); - - // ======================= Change ======================== - const [thumbShow, setThumbShow] = React.useState(false); - - const handleChange = ( - event: React.ChangeEvent, - val: SegmentedRawOption, - ) => { - if (disabled) { - return; - } - - setRawValue(val); - - onChange?.(val); - }; +const InternalSegmented: React.ForwardRefRenderFunction< + HTMLDivElement, + SegmentedProps +> = (props, ref) => { + const { + prefixCls = 'rc-segmented', + direction, + options = [], + disabled, + defaultValue, + value, + onChange, + className = '', + motionName = 'thumb-motion', + ...restProps + } = props; + + const containerRef = React.useRef(null); + const mergedRef = React.useMemo( + () => composeRef(containerRef, ref), + [containerRef, ref], + ); - const divProps = omit(restProps, ['children']); - - return ( -
-
- { + return normalizeOptions(options); + }, [options]); + + // Note: We should not auto switch value when value not exist in options + // which may break single source of truth. + const [rawValue, setRawValue] = useMergedState(segmentedOptions[0]?.value, { + value, + defaultValue, + }); + + // ======================= Change ======================== + const [thumbShow, setThumbShow] = React.useState(false); + + const handleChange = ( + event: React.ChangeEvent, + val: React.Key, + ) => { + if (disabled) { + return; + } + + setRawValue(val); + + onChange?.(val); + }; + + const divProps = omit(restProps, ['children']); + + return ( +
+
+ + segmentedOptions.findIndex((n) => n.value === val) + } + onMotionStart={() => { + setThumbShow(true); + }} + onMotionEnd={() => { + setThumbShow(false); + }} + /> + {segmentedOptions.map((segmentedOption) => ( + - segmentedOptions.findIndex((n) => n.value === val) - } - onMotionStart={() => { - setThumbShow(true); - }} - onMotionEnd={() => { - setThumbShow(false); - }} + className={classNames( + segmentedOption.className, + `${prefixCls}-item`, + { + [`${prefixCls}-item-selected`]: + segmentedOption.value === rawValue && !thumbShow, + }, + )} + checked={segmentedOption.value === rawValue} + onChange={handleChange} + disabled={!!disabled || !!segmentedOption.disabled} /> - {segmentedOptions.map((segmentedOption) => ( - - ))} -
+ ))}
- ); - }, -); +
+ ); +}; -Segmented.displayName = 'Segmented'; +const Segmented = React.forwardRef( + InternalSegmented, +) as (( + props: SegmentedProps & { ref?: React.Ref }, +) => React.ReactElement) & { displayName?: string }; + +if (process.env.NODE_ENV !== 'production') { + Segmented.displayName = 'Segmented'; +} export default Segmented; diff --git a/tsconfig.json b/tsconfig.json index 850f783..4681e24 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,5 +19,5 @@ "rc-segmented": ["src/index.tsx"] } }, - "include": [".dumi/**/*", ".dumirc.ts", "src", "tests", "docs/examples"], + "include": [".dumirc.ts", "**/*"] } From ee3983424916d3f255bf030c7c5f6ed10b650ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E6=9E=AB?= <645381995@qq.com> Date: Fri, 8 Dec 2023 12:11:00 +0800 Subject: [PATCH 02/10] feat: support generics --- src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index 21cac88..e492106 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -17,7 +17,7 @@ export interface SegmentedLabeledOption { title?: string; } -type SegmentedOptions = (T | SegmentedLabeledOption)[]; +type SegmentedOptions = (T | SegmentedLabeledOption)[]; export interface SegmentedProps extends Omit< From 457691eca1b4658d55808e10905c83f7863f62b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E6=9E=AB?= <645381995@qq.com> Date: Fri, 8 Dec 2023 15:01:34 +0800 Subject: [PATCH 03/10] feat: t to value --- src/index.tsx | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index e492106..7b60da6 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -6,28 +6,31 @@ import * as React from 'react'; import MotionThumb from './MotionThumb'; -export interface SegmentedLabeledOption { +export interface SegmentedLabeledOption { className?: string; disabled?: boolean; label: React.ReactNode; - value: T; + value: Value; /** * html `title` property for label */ title?: string; } -type SegmentedOptions = (T | SegmentedLabeledOption)[]; +type SegmentedOptions = ( + | Value + | SegmentedLabeledOption +)[]; -export interface SegmentedProps +export interface SegmentedProps extends Omit< React.HTMLProps, 'value' | 'defaultValue' | 'onChange' > { - options: SegmentedOptions; - defaultValue?: T; - value?: T; - onChange?: (value: T) => void; + options: SegmentedOptions; + defaultValue?: Value; + value?: Value; + onChange?: (value: Value) => void; disabled?: boolean; prefixCls?: string; direction?: 'ltr' | 'rtl'; @@ -218,8 +221,8 @@ const InternalSegmented: React.ForwardRefRenderFunction< const Segmented = React.forwardRef( InternalSegmented, -) as (( - props: SegmentedProps & { ref?: React.Ref }, +) as (( + props: SegmentedProps & { ref?: React.Ref }, ) => React.ReactElement) & { displayName?: string }; if (process.env.NODE_ENV !== 'production') { From 4f3aafe87b7019f481d22ea9fb0d45719b5e1e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E6=9E=AB?= <645381995@qq.com> Date: Mon, 11 Dec 2023 10:21:16 +0800 Subject: [PATCH 04/10] =?UTF-8?q?feat:=20=E5=88=A0=E9=99=A4=20setup=20?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 780a36e..057fdb5 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "pretty-quick": "pretty-quick", "test": "jest", "coverage": "jest --coverage", - "prepare": "husky install && dumi setup" + "prepare": "husky install" }, "dependencies": { "@babel/runtime": "^7.11.1", From 4073184a918aa7a82e26e269fbe3cc10c933db60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E6=9E=AB?= <645381995@qq.com> Date: Mon, 11 Dec 2023 14:00:44 +0800 Subject: [PATCH 05/10] fix: ts --- package.json | 2 +- src/MotionThumb.tsx | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 057fdb5..ac5dd93 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "react": "^18.0.0", "react-dom": "^18.0.0", "ts-node": "^10.9.1", - "typescript": "^4.9.4" + "typescript": "^5.3.3" }, "peerDependencies": { "react": ">=16.0.0", diff --git a/src/MotionThumb.tsx b/src/MotionThumb.tsx index a2e26cc..1f17d24 100644 --- a/src/MotionThumb.tsx +++ b/src/MotionThumb.tsx @@ -3,7 +3,6 @@ import CSSMotion from 'rc-motion'; import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect'; import { composeRef } from 'rc-util/lib/ref'; import * as React from 'react'; -import type { SegmentedValue } from '.'; type ThumbReact = { left: number; @@ -11,10 +10,10 @@ type ThumbReact = { width: number; } | null; -export interface MotionThumbInterface { +export interface MotionThumbInterface { containerRef: React.RefObject; - value: SegmentedValue; - getValueIndex: (value: SegmentedValue) => number; + value: Value; + getValueIndex: (value: Value) => number; prefixCls: string; motionName: string; onMotionStart: VoidFunction; @@ -55,7 +54,7 @@ export default function MotionThumb(props: MotionThumbInterface) { const [prevValue, setPrevValue] = React.useState(value); // =========================== Effect =========================== - const findValueElement = (val: SegmentedValue) => { + const findValueElement = (val: any) => { const index = getValueIndex(val); const ele = containerRef.current?.querySelectorAll( From 59f30a1a453fe7156bc9346efe60673ccbc38c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E6=9E=AB?= <645381995@qq.com> Date: Wed, 20 Dec 2023 14:08:48 +0800 Subject: [PATCH 06/10] feat: React.Key to any --- src/MotionThumb.tsx | 2 +- src/index.tsx | 15 ++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/MotionThumb.tsx b/src/MotionThumb.tsx index 1f17d24..faea6f9 100644 --- a/src/MotionThumb.tsx +++ b/src/MotionThumb.tsx @@ -10,7 +10,7 @@ type ThumbReact = { width: number; } | null; -export interface MotionThumbInterface { +export interface MotionThumbInterface { containerRef: React.RefObject; value: Value; getValueIndex: (value: Value) => number; diff --git a/src/index.tsx b/src/index.tsx index 7b60da6..6d82894 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -6,7 +6,7 @@ import * as React from 'react'; import MotionThumb from './MotionThumb'; -export interface SegmentedLabeledOption { +export interface SegmentedLabeledOption { className?: string; disabled?: boolean; label: React.ReactNode; @@ -17,12 +17,9 @@ export interface SegmentedLabeledOption { title?: string; } -type SegmentedOptions = ( - | Value - | SegmentedLabeledOption -)[]; +type SegmentedOptions = (Value | SegmentedLabeledOption)[]; -export interface SegmentedProps +export interface SegmentedProps extends Omit< React.HTMLProps, 'value' | 'defaultValue' | 'onChange' @@ -74,8 +71,8 @@ const InternalSegmentedOption: React.FC<{ checked: boolean; label: React.ReactNode; title?: string; - value: React.Key; - onChange: (e: React.ChangeEvent, value: React.Key) => void; + value: any; + onChange: (e: React.ChangeEvent, value: any) => void; }> = ({ prefixCls, className, @@ -153,7 +150,7 @@ const InternalSegmented: React.ForwardRefRenderFunction< const handleChange = ( event: React.ChangeEvent, - val: React.Key, + val: any, ) => { if (disabled) { return; From d7be3e8cc4e7f13c599594693695c5efb9ac68d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E6=9E=AB?= <645381995@qq.com> Date: Wed, 27 Dec 2023 22:26:17 +0800 Subject: [PATCH 07/10] =?UTF-8?q?feat:=20=E7=A7=BB=E9=99=A4=E6=B0=B8?= =?UTF-8?q?=E8=BF=9C=E4=B8=8D=E4=BC=9A=E6=89=A7=E8=A1=8C=E7=9A=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 6d82894..364f1a9 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -152,10 +152,6 @@ const InternalSegmented: React.ForwardRefRenderFunction< event: React.ChangeEvent, val: any, ) => { - if (disabled) { - return; - } - setRawValue(val); onChange?.(val); From c82019326abeaef288cd7b96ad276f9248cf87a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E6=9E=AB?= <645381995@qq.com> Date: Tue, 2 Jan 2024 11:07:00 +0800 Subject: [PATCH 08/10] feat: options --- src/index.tsx | 2 +- tests/index.test.tsx | 51 ++++++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 364f1a9..8eb00fc 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -24,7 +24,7 @@ export interface SegmentedProps React.HTMLProps, 'value' | 'defaultValue' | 'onChange' > { - options: SegmentedOptions; + options?: SegmentedOptions; defaultValue?: Value; value?: Value; onChange?: (value: Value) => void; diff --git a/tests/index.test.tsx b/tests/index.test.tsx index 59fb1b1..f2abd12 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -45,6 +45,11 @@ describe('rc-segmented', () => { expect(asFragment().firstChild).toMatchSnapshot(); }); + it('render empty options segmented', () => { + const { asFragment } = render(); + expect(asFragment().firstChild).toMatchSnapshot(); + }); + it('render segmented ok', () => { const { container, asFragment } = render( { }); it('render segmented with controlled mode', () => { - const offsetParentSpy = jest - .spyOn(HTMLElement.prototype, 'offsetParent', 'get') - .mockImplementation(() => { - return container; - }); - const Demo = () => { const options = ['iOS', 'Android', 'Web3']; @@ -257,6 +256,12 @@ describe('rc-segmented', () => { }; const { container } = render(); + const offsetParentSpy = jest + .spyOn(HTMLElement.prototype, 'offsetParent', 'get') + .mockImplementation(() => { + return container; + }); + fireEvent.click(container.querySelectorAll('.rc-segmented-item-input')[0]); expect(container.querySelector('.value')?.textContent).toBe('iOS'); @@ -297,11 +302,6 @@ describe('rc-segmented', () => { describe('render segmented with CSSMotion', () => { it('basic', () => { - const offsetParentSpy = jest - .spyOn(HTMLElement.prototype, 'offsetParent', 'get') - .mockImplementation(() => { - return container; - }); const handleValueChange = jest.fn(); const { container, asFragment } = render( { onChange={(value) => handleValueChange(value)} />, ); + + const offsetParentSpy = jest + .spyOn(HTMLElement.prototype, 'offsetParent', 'get') + .mockImplementation(() => { + return container; + }); + expect(asFragment().firstChild).toMatchSnapshot(); expectMatchChecked(container, [true, false, false]); @@ -385,11 +392,6 @@ describe('rc-segmented', () => { }); it('quick switch', () => { - const offsetParentSpy = jest - .spyOn(HTMLElement.prototype, 'offsetParent', 'get') - .mockImplementation(() => { - return container; - }); const { container } = render( { />, ); + const offsetParentSpy = jest + .spyOn(HTMLElement.prototype, 'offsetParent', 'get') + .mockImplementation(() => { + return container; + }); + // >>> Click: Web3 fireEvent.click( container.querySelectorAll('.rc-segmented-item-input')[2], @@ -525,11 +533,6 @@ describe('rc-segmented', () => { }); it('click can work as expected with rtl', () => { - const offsetParentSpy = jest - .spyOn(HTMLElement.prototype, 'offsetParent', 'get') - .mockImplementation(() => { - return container; - }); const handleValueChange = jest.fn(); const { container } = render( { />, ); + const offsetParentSpy = jest + .spyOn(HTMLElement.prototype, 'offsetParent', 'get') + .mockImplementation(() => { + return container; + }); + fireEvent.click(container.querySelectorAll('.rc-segmented-item-input')[1]); expectMatchChecked(container, [false, true, false]); expect(handleValueChange).toBeCalledWith('Android'); From 37b4bb3bcff5cddde5440092c39b0831bea45545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E6=9E=AB?= <645381995@qq.com> Date: Tue, 2 Jan 2024 11:09:15 +0800 Subject: [PATCH 09/10] feat: coverage --- tests/__snapshots__/index.test.tsx.snap | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/__snapshots__/index.test.tsx.snap b/tests/__snapshots__/index.test.tsx.snap index fb6277d..327991d 100644 --- a/tests/__snapshots__/index.test.tsx.snap +++ b/tests/__snapshots__/index.test.tsx.snap @@ -1,5 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`rc-segmented render empty options segmented 1`] = ` +
+
+
+`; + exports[`rc-segmented render empty segmented 1`] = `
Date: Tue, 2 Jan 2024 11:38:10 +0800 Subject: [PATCH 10/10] feat: string number boolean --- src/MotionThumb.tsx | 3 ++- src/index.tsx | 15 ++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/MotionThumb.tsx b/src/MotionThumb.tsx index faea6f9..32584f5 100644 --- a/src/MotionThumb.tsx +++ b/src/MotionThumb.tsx @@ -3,6 +3,7 @@ import CSSMotion from 'rc-motion'; import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect'; import { composeRef } from 'rc-util/lib/ref'; import * as React from 'react'; +import type { SegmentedValue } from '.'; type ThumbReact = { left: number; @@ -10,7 +11,7 @@ type ThumbReact = { width: number; } | null; -export interface MotionThumbInterface { +export interface MotionThumbInterface { containerRef: React.RefObject; value: Value; getValueIndex: (value: Value) => number; diff --git a/src/index.tsx b/src/index.tsx index 8eb00fc..76e3e75 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -6,7 +6,9 @@ import * as React from 'react'; import MotionThumb from './MotionThumb'; -export interface SegmentedLabeledOption { +export type SegmentedValue = string | number | boolean; + +export interface SegmentedLabeledOption { className?: string; disabled?: boolean; label: React.ReactNode; @@ -17,9 +19,12 @@ export interface SegmentedLabeledOption { title?: string; } -type SegmentedOptions = (Value | SegmentedLabeledOption)[]; +type SegmentedOptions = ( + | Value + | SegmentedLabeledOption +)[]; -export interface SegmentedProps +export interface SegmentedProps extends Omit< React.HTMLProps, 'value' | 'defaultValue' | 'onChange' @@ -192,7 +197,7 @@ const InternalSegmented: React.ForwardRefRenderFunction< {segmentedOptions.map((segmentedOption) => ( ( InternalSegmented, -) as (( +) as (( props: SegmentedProps & { ref?: React.Ref }, ) => React.ReactElement) & { displayName?: string };