From 666b1411efdf0dd9216cfdf89bad527234150487 Mon Sep 17 00:00:00 2001 From: wangdicoder Date: Sun, 19 Apr 2026 09:11:58 +1000 Subject: [PATCH 1/3] fix(react): restore intrinsic HTML props under React 19 types `React.PropsWithRef` relied on the global `JSX` namespace, which @types/react@19 no longer augments. Under React 19 the type collapsed to `any`, silently dropping `onClick`, `type`, `disabled`, `aria-*`, `children`, etc. from every affected component. Replaced with `React.ComponentProps<'x'>` / `React.ComponentPropsWithoutRef<'x'>` across ~60 type files. Works on React 18 and 19. Fixes #120. --- .changeset/react-19-types-compat.md | 5 +++++ packages/react/src/alert/types.ts | 2 +- packages/react/src/anchor/types.ts | 2 +- packages/react/src/aspect-ratio/types.ts | 2 +- packages/react/src/avatar/types.ts | 4 ++-- packages/react/src/badge/types.ts | 2 +- packages/react/src/breadcrumb/types.ts | 4 ++-- packages/react/src/button/types.ts | 4 ++-- packages/react/src/calendar/types.ts | 2 +- packages/react/src/card/types.ts | 4 ++-- packages/react/src/cascader/types.ts | 2 +- packages/react/src/checkbox/types.ts | 4 ++-- packages/react/src/color-picker/types.ts | 2 +- packages/react/src/copy-to-clipboard/types.ts | 2 +- packages/react/src/descriptions/types.ts | 2 +- packages/react/src/divider/types.ts | 2 +- packages/react/src/empty/types.ts | 2 +- packages/react/src/flex/types.ts | 2 +- packages/react/src/flip/types.ts | 4 ++-- packages/react/src/form/types.ts | 2 +- packages/react/src/grid/types.ts | 8 ++++---- packages/react/src/image/types.ts | 2 +- packages/react/src/input/types.ts | 6 +++--- packages/react/src/keyboard/types.ts | 2 +- packages/react/src/layout/types.ts | 4 ++-- packages/react/src/link/types.ts | 2 +- packages/react/src/list/types.ts | 6 +++--- packages/react/src/loader/types.ts | 2 +- packages/react/src/loading-bar/types.ts | 2 +- packages/react/src/marquee/types.ts | 2 +- packages/react/src/menu/types.ts | 8 ++++---- packages/react/src/native-select/types.ts | 6 +++--- packages/react/src/notification/types.ts | 2 +- packages/react/src/pagination/types.ts | 2 +- packages/react/src/popup/types.ts | 2 +- packages/react/src/progress/types.ts | 4 ++-- packages/react/src/radio/types.ts | 4 ++-- packages/react/src/rate/types.ts | 2 +- packages/react/src/result/types.ts | 2 +- packages/react/src/scroll-indicator/types.ts | 2 +- packages/react/src/scroll-number/types.ts | 2 +- packages/react/src/segmented/types.ts | 2 +- packages/react/src/select/types.ts | 6 +++--- packages/react/src/skeleton/types.ts | 2 +- packages/react/src/slider/types.ts | 2 +- packages/react/src/space/types.ts | 2 +- packages/react/src/speed-dial/types.ts | 4 ++-- packages/react/src/split/resizer.tsx | 2 +- packages/react/src/split/types.ts | 4 ++-- packages/react/src/statistic/types.ts | 2 +- packages/react/src/steps/types.ts | 4 ++-- packages/react/src/sticky/types.ts | 2 +- packages/react/src/strength-indicator/types.ts | 2 +- packages/react/src/switch/types.ts | 2 +- packages/react/src/table/types.ts | 2 +- packages/react/src/tag/types.ts | 2 +- packages/react/src/text-loop/types.ts | 2 +- packages/react/src/timeline/types.ts | 4 ++-- packages/react/src/transfer/transfer-panel.tsx | 2 +- packages/react/src/transfer/types.ts | 2 +- packages/react/src/tree/types.ts | 2 +- packages/react/src/typography/types.ts | 8 ++++---- packages/react/src/waterfall/types.ts | 2 +- 63 files changed, 97 insertions(+), 92 deletions(-) create mode 100644 .changeset/react-19-types-compat.md diff --git a/.changeset/react-19-types-compat.md b/.changeset/react-19-types-compat.md new file mode 100644 index 000000000..f23ebeca3 --- /dev/null +++ b/.changeset/react-19-types-compat.md @@ -0,0 +1,5 @@ +--- +'@tiny-design/react': patch +--- + +Fix TypeScript compatibility with React 19. Component prop interfaces used the pattern `React.PropsWithRef`, which relied on a globally-augmented `JSX` namespace that `@types/react@19` no longer provides. The resolved prop types collapsed to `any`, silently dropping every intrinsic HTML attribute (`onClick`, `type`, `disabled`, `aria-*`, `children`, etc.) for consumers on React 19. Replaced the pattern with `React.ComponentProps<'x'>` / `React.ComponentPropsWithoutRef<'x'>` across ~60 component type files. Works on React 18 and 19. diff --git a/packages/react/src/alert/types.ts b/packages/react/src/alert/types.ts index fe3445f68..11a21d034 100644 --- a/packages/react/src/alert/types.ts +++ b/packages/react/src/alert/types.ts @@ -5,7 +5,7 @@ export type AlertType = 'success' | 'info' | 'warning' | 'error'; export interface AlertProps extends BaseProps, - Omit, 'title'> { + Omit, 'title'> { /** alert title */ title?: string | ReactNode; diff --git a/packages/react/src/anchor/types.ts b/packages/react/src/anchor/types.ts index 41b6216dc..7799deab4 100644 --- a/packages/react/src/anchor/types.ts +++ b/packages/react/src/anchor/types.ts @@ -12,7 +12,7 @@ export interface AnchorProps extends BaseProps { children?: React.ReactNode; } -export interface AnchorLinkProps extends BaseProps, React.PropsWithRef { +export interface AnchorLinkProps extends BaseProps, React.ComponentProps<'a'> { href: string; title: string; children?: React.ReactElement[]; diff --git a/packages/react/src/aspect-ratio/types.ts b/packages/react/src/aspect-ratio/types.ts index 5f769bed2..c952daf36 100644 --- a/packages/react/src/aspect-ratio/types.ts +++ b/packages/react/src/aspect-ratio/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface AspectRatioProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { /** the width of the content */ width?: number | string; diff --git a/packages/react/src/avatar/types.ts b/packages/react/src/avatar/types.ts index 29962204f..e1161d99d 100644 --- a/packages/react/src/avatar/types.ts +++ b/packages/react/src/avatar/types.ts @@ -6,7 +6,7 @@ export type AvatarPresence = 'online' | 'busy' | 'away' | 'offline'; export interface AvatarProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'span'> { /** use an icon */ icon?: React.ReactNode; @@ -28,7 +28,7 @@ export interface AvatarProps export interface AvatarGroupProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'span'> { /** the distance between two avatars */ gap: number | string; } diff --git a/packages/react/src/badge/types.ts b/packages/react/src/badge/types.ts index f18b8d95b..744be720b 100644 --- a/packages/react/src/badge/types.ts +++ b/packages/react/src/badge/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface BadgeProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'span'> { /** the number to show in badge */ count?: React.ReactNode; diff --git a/packages/react/src/breadcrumb/types.ts b/packages/react/src/breadcrumb/types.ts index 5e657efb7..9776eed67 100644 --- a/packages/react/src/breadcrumb/types.ts +++ b/packages/react/src/breadcrumb/types.ts @@ -3,14 +3,14 @@ import { BaseProps } from '../_utils/props'; export interface BreadcrumbProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'nav'> { separator?: React.ReactNode; children: ReactElement | ReactElement[]; } export interface BreadcrumbItemProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'li'> { separator?: React.ReactNode; children?: React.ReactNode; } diff --git a/packages/react/src/button/types.ts b/packages/react/src/button/types.ts index 3c8f562bd..e9a87fd2d 100644 --- a/packages/react/src/button/types.ts +++ b/packages/react/src/button/types.ts @@ -12,7 +12,7 @@ export type ButtonIconPosition = 'start' | 'end'; export type ButtonGroupInheritMode = 'fill' | 'override' | 'none'; export interface ButtonProps - extends BaseProps, React.PropsWithRef { + extends BaseProps, React.ComponentProps<'button'> { variant?: ButtonVariant; color?: ButtonColor; loading?: boolean; @@ -27,7 +27,7 @@ export interface ButtonProps } export interface ButtonGroupProps - extends BaseProps, React.PropsWithRef { + extends BaseProps, React.ComponentProps<'div'> { variant?: ButtonVariant; color?: ButtonColor; size?: SizeType; diff --git a/packages/react/src/calendar/types.ts b/packages/react/src/calendar/types.ts index 2573729e0..c35c0a130 100644 --- a/packages/react/src/calendar/types.ts +++ b/packages/react/src/calendar/types.ts @@ -7,7 +7,7 @@ export type SelectionMode = 'single' | 'range' | 'multiple'; export interface CalendarProps extends BaseProps, - Omit, 'onChange' | 'onSelect' | 'defaultValue'> { + Omit, 'onChange' | 'onSelect' | 'defaultValue'> { /** Selected date (controlled, single mode) */ defaultValue?: Date; /** Controlled selected date */ diff --git a/packages/react/src/card/types.ts b/packages/react/src/card/types.ts index 9dd335a9f..82e7ddaa0 100644 --- a/packages/react/src/card/types.ts +++ b/packages/react/src/card/types.ts @@ -3,14 +3,14 @@ import { BaseProps } from '../_utils/props'; export type CardVariant = 'outlined' | 'elevated' | 'filled'; -export interface CardContentProps extends React.PropsWithoutRef { +export interface CardContentProps extends React.ComponentPropsWithoutRef<'div'> { prefixCls?: string; children: ReactNode; } export interface CardProps extends BaseProps, - Omit, 'title'> { + Omit, 'title'> { title?: ReactNode; extra?: ReactNode; /** Card surface style */ diff --git a/packages/react/src/cascader/types.ts b/packages/react/src/cascader/types.ts index a5a6dd0ef..a25be7ed4 100644 --- a/packages/react/src/cascader/types.ts +++ b/packages/react/src/cascader/types.ts @@ -13,7 +13,7 @@ export type CascaderValue = (string | number)[]; export interface CascaderProps extends BaseProps, - Omit, 'onChange' | 'defaultValue'> { + Omit, 'onChange' | 'defaultValue'> { options: CascaderOption[]; value?: CascaderValue; defaultValue?: CascaderValue; diff --git a/packages/react/src/checkbox/types.ts b/packages/react/src/checkbox/types.ts index 7df56e080..776a1bc8e 100644 --- a/packages/react/src/checkbox/types.ts +++ b/packages/react/src/checkbox/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface CheckboxGroupProps extends BaseProps, - Omit, 'onChange'> { + Omit, 'onChange'> { defaultValue?: string[]; value?: string[]; onChange?: (checkedValues: string[]) => void; @@ -13,7 +13,7 @@ export interface CheckboxGroupProps export interface CheckboxProps extends BaseProps, - Omit, 'onChange'> { + Omit, 'onChange'> { /** Only required when use checkbox group */ value?: string; defaultChecked?: boolean; diff --git a/packages/react/src/color-picker/types.ts b/packages/react/src/color-picker/types.ts index 538c74ce6..c2f8351fe 100644 --- a/packages/react/src/color-picker/types.ts +++ b/packages/react/src/color-picker/types.ts @@ -17,7 +17,7 @@ export interface ColorChangeMeta { export interface ColorPickerProps extends BaseProps, - Omit, 'onChange' | 'defaultValue'> { + Omit, 'onChange' | 'defaultValue'> { value?: string; defaultValue?: string; onChange?: (color: string, meta: ColorChangeMeta) => void; diff --git a/packages/react/src/copy-to-clipboard/types.ts b/packages/react/src/copy-to-clipboard/types.ts index ed7a378a1..250ceabb4 100644 --- a/packages/react/src/copy-to-clipboard/types.ts +++ b/packages/react/src/copy-to-clipboard/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface CopyToClipboardProps extends BaseProps, - Omit, 'onCopy'> { + Omit, 'onCopy'> { text: string; onCopy?: (copied: boolean, text: string) => void; children?: React.ReactNode; diff --git a/packages/react/src/descriptions/types.ts b/packages/react/src/descriptions/types.ts index 0e4b603c4..746f1529d 100644 --- a/packages/react/src/descriptions/types.ts +++ b/packages/react/src/descriptions/types.ts @@ -17,7 +17,7 @@ export interface DescriptionsItemType extends BaseProps { export interface DescriptionsProps extends BaseProps, - Omit, 'title'> { + Omit, 'title'> { title?: React.ReactNode; extra?: React.ReactNode; footer?: React.ReactNode; diff --git a/packages/react/src/divider/types.ts b/packages/react/src/divider/types.ts index da583f804..0e60189bb 100644 --- a/packages/react/src/divider/types.ts +++ b/packages/react/src/divider/types.ts @@ -7,7 +7,7 @@ export type DividerVariant = 'solid' | 'dashed' | 'dotted'; export interface DividerProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { orientation?: DividerOrientation; variant?: DividerVariant; titlePlacement?: DividerTitlePlacement; diff --git a/packages/react/src/empty/types.ts b/packages/react/src/empty/types.ts index 3f24952e8..770ec4f3d 100644 --- a/packages/react/src/empty/types.ts +++ b/packages/react/src/empty/types.ts @@ -1,7 +1,7 @@ import React, { CSSProperties, ReactNode } from 'react'; import { BaseProps } from '../_utils/props'; -export interface EmptyProps extends BaseProps, React.PropsWithoutRef { +export interface EmptyProps extends BaseProps, React.ComponentPropsWithoutRef<'div'> { image?: string | ReactNode; imageStyle?: CSSProperties; description?: boolean | string | React.ReactNode; diff --git a/packages/react/src/flex/types.ts b/packages/react/src/flex/types.ts index 592673521..e65778258 100644 --- a/packages/react/src/flex/types.ts +++ b/packages/react/src/flex/types.ts @@ -1,7 +1,7 @@ import React from 'react'; import { BaseProps, SizeType } from '../_utils/props'; -export interface FlexProps extends BaseProps, React.PropsWithRef { +export interface FlexProps extends BaseProps, React.ComponentProps<'div'> { vertical?: boolean; wrap?: React.CSSProperties['flexWrap']; justify?: React.CSSProperties['justifyContent']; diff --git a/packages/react/src/flip/types.ts b/packages/react/src/flip/types.ts index b3688c057..0599a168c 100644 --- a/packages/react/src/flip/types.ts +++ b/packages/react/src/flip/types.ts @@ -1,7 +1,7 @@ import React from 'react'; import { BaseProps, DirectionType } from '../_utils/props'; -export interface FlipProps extends BaseProps, React.PropsWithoutRef { +export interface FlipProps extends BaseProps, React.ComponentPropsWithoutRef<'div'> { /** a certain parent width and height to prevent the hover empty issue */ width: string | number; height: string | number; @@ -16,6 +16,6 @@ export interface FlipProps extends BaseProps, React.PropsWithoutRef, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { children?: React.ReactNode; } diff --git a/packages/react/src/form/types.ts b/packages/react/src/form/types.ts index f3a9c5c38..0d0011ae6 100644 --- a/packages/react/src/form/types.ts +++ b/packages/react/src/form/types.ts @@ -66,7 +66,7 @@ export interface FormOptionsProps { export interface FormProps extends BaseProps, Partial, - React.PropsWithRef { + React.ComponentProps<'form'> { form?: FormInstance; initialValues?: FormValues; onFinish?: (values: FormValues) => void; diff --git a/packages/react/src/grid/types.ts b/packages/react/src/grid/types.ts index 20edcc940..07d5baa71 100644 --- a/packages/react/src/grid/types.ts +++ b/packages/react/src/grid/types.ts @@ -11,7 +11,7 @@ export type RowJustify = | 'space-between' | 'space-evenly'; -export interface RowProps extends BaseProps, React.PropsWithRef { +export interface RowProps extends BaseProps, React.ComponentProps<'div'> { gutter?: number | [number, number]; gutterSide?: boolean; align?: RowAlign; @@ -29,7 +29,7 @@ export type GridTrackValue = number | React.CSSProperties['gridTemplateColumns'] export type GridItemSize = number | 'auto' | 'grow' | 'full'; export type GridItemOffset = number | 'auto'; -export interface GridProps extends BaseProps, React.PropsWithRef { +export interface GridProps extends BaseProps, React.ComponentProps<'div'> { columns?: ResponsiveValue; rows?: ResponsiveValue; spacing?: ResponsiveValue; @@ -51,7 +51,7 @@ export interface GridProps extends BaseProps, React.PropsWithRef { +export interface GridItemProps extends BaseProps, React.ComponentProps<'div'> { size?: ResponsiveValue; offset?: ResponsiveValue; column?: ResponsiveValue; @@ -64,7 +64,7 @@ export interface GridItemProps extends BaseProps, React.PropsWithRef { +export interface ColProps extends BaseProps, React.ComponentProps<'div'> { span?: number; offset?: number; order?: number; diff --git a/packages/react/src/image/types.ts b/packages/react/src/image/types.ts index e51e28a7c..0a49f01e7 100644 --- a/packages/react/src/image/types.ts +++ b/packages/react/src/image/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface ImageProps extends BaseProps, - Omit, 'placeholder'> { + Omit, 'placeholder'> { src?: string; placeholder?: React.ReactNode; alt?: string; diff --git a/packages/react/src/input/types.ts b/packages/react/src/input/types.ts index 4dfc34d1e..29cc6c198 100644 --- a/packages/react/src/input/types.ts +++ b/packages/react/src/input/types.ts @@ -3,7 +3,7 @@ import { BaseProps, SizeType } from '../_utils/props'; export interface InputProps extends BaseProps, - Omit, 'size' | 'prefix'> { + Omit, 'size' | 'prefix'> { clearable?: boolean; prefix?: ReactNode; suffix?: ReactNode; @@ -19,7 +19,7 @@ export interface InputProps export interface InputGroupProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { size?: SizeType; disabled?: boolean; children: React.ReactNode; @@ -27,7 +27,7 @@ export interface InputGroupProps export interface InputGroupAddonProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { noBorder?: boolean; disabled?: boolean; size?: SizeType; diff --git a/packages/react/src/keyboard/types.ts b/packages/react/src/keyboard/types.ts index d8e8476d5..78c852291 100644 --- a/packages/react/src/keyboard/types.ts +++ b/packages/react/src/keyboard/types.ts @@ -1,6 +1,6 @@ import React from 'react'; import { BaseProps } from '../_utils/props'; -export interface KeyboardProps extends BaseProps, React.PropsWithRef { +export interface KeyboardProps extends BaseProps, React.ComponentProps<'kbd'> { children?: React.ReactNode; } diff --git a/packages/react/src/layout/types.ts b/packages/react/src/layout/types.ts index 88a945c47..7eabeb431 100644 --- a/packages/react/src/layout/types.ts +++ b/packages/react/src/layout/types.ts @@ -1,11 +1,11 @@ import React from 'react'; import { BaseProps } from '../_utils/props'; -export interface LayoutProps extends BaseProps, React.PropsWithRef {} +export interface LayoutProps extends BaseProps, React.ComponentProps<'div'> {} export type SidebarTheme = 'light' | 'dark'; -export interface SidebarProps extends BaseProps, React.PropsWithRef { +export interface SidebarProps extends BaseProps, React.ComponentProps<'div'> { collapsible?: boolean; collapsed?: boolean; defaultCollapsed?: boolean; diff --git a/packages/react/src/link/types.ts b/packages/react/src/link/types.ts index 5c24054a3..8563e6fa8 100644 --- a/packages/react/src/link/types.ts +++ b/packages/react/src/link/types.ts @@ -1,7 +1,7 @@ import React from 'react'; import { BaseProps } from '../_utils/props'; -export interface LinkProps extends BaseProps, React.PropsWithRef { +export interface LinkProps extends BaseProps, React.ComponentProps<'a'> { external?: boolean; disabled?: boolean; underline?: boolean; diff --git a/packages/react/src/list/types.ts b/packages/react/src/list/types.ts index 66e9a3737..30da41595 100644 --- a/packages/react/src/list/types.ts +++ b/packages/react/src/list/types.ts @@ -4,7 +4,7 @@ import { PaginationProps } from '../pagination/types'; export interface ListProps extends BaseProps, - Omit, 'children'> { + Omit, 'children'> { dataSource?: T[]; renderItem?: (item: T, index: number) => React.ReactNode; header?: React.ReactNode; @@ -36,7 +36,7 @@ export interface ListPaginationProps extends Pick { + React.ComponentPropsWithoutRef<'li'> { extra?: React.ReactNode; actions?: React.ReactNode[]; children?: React.ReactNode; @@ -44,7 +44,7 @@ export interface ListItemProps export interface ListItemMetaProps extends BaseProps, - Omit, 'title'> { + Omit, 'title'> { avatar?: React.ReactNode; title?: React.ReactNode; description?: React.ReactNode; diff --git a/packages/react/src/loader/types.ts b/packages/react/src/loader/types.ts index 7c3c4b463..92839d18e 100644 --- a/packages/react/src/loader/types.ts +++ b/packages/react/src/loader/types.ts @@ -3,7 +3,7 @@ import { BaseProps, SizeType } from '../_utils/props'; export interface LoaderProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { /** customise the spinning indicator */ indicator?: ReactNode; diff --git a/packages/react/src/loading-bar/types.ts b/packages/react/src/loading-bar/types.ts index 89face8d2..6bb950005 100644 --- a/packages/react/src/loading-bar/types.ts +++ b/packages/react/src/loading-bar/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface LoadingBarProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { didMount?: () => void; children?: React.ReactNode; } diff --git a/packages/react/src/marquee/types.ts b/packages/react/src/marquee/types.ts index fec42121d..ada77dbb2 100644 --- a/packages/react/src/marquee/types.ts +++ b/packages/react/src/marquee/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface MarqueeProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { /** Scroll direction */ direction?: 'left' | 'right'; diff --git a/packages/react/src/menu/types.ts b/packages/react/src/menu/types.ts index 140c4900e..3c7d814bc 100644 --- a/packages/react/src/menu/types.ts +++ b/packages/react/src/menu/types.ts @@ -15,7 +15,7 @@ export interface MenuSelectInfo { export interface MenuProps extends BaseProps, - Omit, 'onSelect'> { + Omit, 'onSelect'> { defaultIndex?: string; selectedKeys?: string[]; defaultSelectedKeys?: string[]; @@ -55,7 +55,7 @@ export interface MenuProps export interface MenuItemProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'li'> { index?: string; disabled?: boolean; danger?: boolean; @@ -66,14 +66,14 @@ export interface MenuItemProps export interface MenuItemGroupProps extends BaseProps, - Omit, 'title'> { + Omit, 'title'> { index?: string; title?: ReactNode; } export interface SubMenuProps extends BaseProps, - Omit, 'title'> { + Omit, 'title'> { title: ReactNode; index?: string; disabled?: boolean; diff --git a/packages/react/src/native-select/types.ts b/packages/react/src/native-select/types.ts index 0656ee0f3..d91f22890 100644 --- a/packages/react/src/native-select/types.ts +++ b/packages/react/src/native-select/types.ts @@ -1,13 +1,13 @@ import React from 'react'; import { BaseProps, SizeType } from '../_utils/props'; -export type NativeSelectGroupProps = React.PropsWithRef; +export type NativeSelectGroupProps = React.ComponentProps<'optgroup'>; -export type NativeSelectOptionProps = React.PropsWithRef; +export type NativeSelectOptionProps = React.ComponentProps<'option'>; export interface NativeSelectProps extends BaseProps, - Omit, 'size'> { + Omit, 'size'> { size?: SizeType; children: | React.ReactElement diff --git a/packages/react/src/notification/types.ts b/packages/react/src/notification/types.ts index 0412b7bcc..3bbe99b70 100644 --- a/packages/react/src/notification/types.ts +++ b/packages/react/src/notification/types.ts @@ -5,7 +5,7 @@ export type NotificationType = 'success' | 'error' | 'warning' | 'info' | undefi export interface NotificationProps extends BaseProps, - Omit, 'title'> { + Omit, 'title'> { type: NotificationType; title?: ReactNode; description?: ReactNode; diff --git a/packages/react/src/pagination/types.ts b/packages/react/src/pagination/types.ts index e211ff148..ec3c6929b 100644 --- a/packages/react/src/pagination/types.ts +++ b/packages/react/src/pagination/types.ts @@ -6,7 +6,7 @@ export type PaginationSize = 'sm' | 'md'; export interface PaginationProps extends BaseProps, - Omit, 'onChange'> { + Omit, 'onChange'> { current?: number; total?: number; defaultCurrent?: number; diff --git a/packages/react/src/popup/types.ts b/packages/react/src/popup/types.ts index 60d9414a3..7672386ff 100644 --- a/packages/react/src/popup/types.ts +++ b/packages/react/src/popup/types.ts @@ -17,7 +17,7 @@ export type Placement = | 'right' | 'right-end'; -export interface PopupProps extends BaseProps, Omit, 'children' | 'content'> { +export interface PopupProps extends BaseProps, Omit, 'children' | 'content'> { disabled?: boolean; content?: React.ReactNode; placement?: Placement; diff --git a/packages/react/src/progress/types.ts b/packages/react/src/progress/types.ts index a6dfa91ef..3b4cfe3a3 100644 --- a/packages/react/src/progress/types.ts +++ b/packages/react/src/progress/types.ts @@ -7,7 +7,7 @@ export const strokePresetColors = ['primary', 'blue', 'green', 'yellow', 'red']; export type BarBackgroundType = 'impulse' | 'striped'; -export interface BarProps extends BaseProps, React.PropsWithoutRef { +export interface BarProps extends BaseProps, React.ComponentPropsWithoutRef<'div'> { percent?: number; /** Customise label style for both outer and inner label */ format?: (percent: number) => React.ReactNode; @@ -24,7 +24,7 @@ export interface BarProps extends BaseProps, React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { percent?: number; /** Customise label style for both outer and inner label */ format?: (percent: number) => React.ReactNode; diff --git a/packages/react/src/radio/types.ts b/packages/react/src/radio/types.ts index 0b29f676b..556fc7059 100644 --- a/packages/react/src/radio/types.ts +++ b/packages/react/src/radio/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface RadioProps extends BaseProps, - Omit, 'onChange'> { + Omit, 'onChange'> { radioRef?: RefObject; value?: string | number; name?: string; @@ -15,7 +15,7 @@ export interface RadioProps export interface RadioGroupProps extends BaseProps, - Omit, 'onChange'> { + Omit, 'onChange'> { name?: string; defaultValue?: number | string; value?: number | string; diff --git a/packages/react/src/rate/types.ts b/packages/react/src/rate/types.ts index 5c944eac9..efab46fd9 100644 --- a/packages/react/src/rate/types.ts +++ b/packages/react/src/rate/types.ts @@ -3,7 +3,7 @@ import { ReactNode } from 'react'; import { BaseProps } from '../_utils/props'; export interface RateProps extends BaseProps, - Omit, 'onChange'> { + Omit, 'onChange'> { color?: string; clearable?: boolean; half?: boolean; diff --git a/packages/react/src/result/types.ts b/packages/react/src/result/types.ts index 9f80b0154..5d2bf5fe4 100644 --- a/packages/react/src/result/types.ts +++ b/packages/react/src/result/types.ts @@ -5,7 +5,7 @@ export type ResultStatus = 'success' | 'error' | 'info' | 'warning' | 'loading'; export interface ResultProps extends BaseProps, - Omit, 'title'> { + Omit, 'title'> { title?: ReactNode; subtitle?: ReactNode; status?: ResultStatus; diff --git a/packages/react/src/scroll-indicator/types.ts b/packages/react/src/scroll-indicator/types.ts index 0e8d5dc22..cd3465b81 100644 --- a/packages/react/src/scroll-indicator/types.ts +++ b/packages/react/src/scroll-indicator/types.ts @@ -4,7 +4,7 @@ import { Target } from '../_utils/dom'; export interface ScrollIndicatorProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { fixed?: boolean; target?: () => Target; } diff --git a/packages/react/src/scroll-number/types.ts b/packages/react/src/scroll-number/types.ts index 78b8cce39..d1bcf9293 100644 --- a/packages/react/src/scroll-number/types.ts +++ b/packages/react/src/scroll-number/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface ScrollNumberProps extends BaseProps, - Omit, 'title' | 'prefix'> { + Omit, 'title' | 'prefix'> { /** The numeric value to display */ value?: number | string; /** Title displayed above the value */ diff --git a/packages/react/src/segmented/types.ts b/packages/react/src/segmented/types.ts index 766b5436e..78d0903c9 100644 --- a/packages/react/src/segmented/types.ts +++ b/packages/react/src/segmented/types.ts @@ -15,7 +15,7 @@ export type SegmentedValue = string | number; export interface SegmentedProps extends BaseProps, Omit< - React.PropsWithoutRef, + React.ComponentPropsWithoutRef<'div'>, 'children' | 'defaultValue' | 'onChange' > { options: SegmentedOption[]; diff --git a/packages/react/src/select/types.ts b/packages/react/src/select/types.ts index b6740c1c3..c1d5243cf 100644 --- a/packages/react/src/select/types.ts +++ b/packages/react/src/select/types.ts @@ -3,14 +3,14 @@ import { BaseProps, SizeType } from '../_utils/props'; export interface SelectOptGroupProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'li'> { label?: string; children?: React.ReactNode; } export interface SelectOptionsProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'li'> { value: string; label?: React.ReactNode; disabled?: boolean; @@ -28,7 +28,7 @@ export type SelectValue = string | string[]; export interface SelectProps extends BaseProps, Omit< - React.PropsWithoutRef, + React.ComponentPropsWithoutRef<'div'>, 'onSelect' | 'onChange' | 'defaultValue' > { value?: SelectValue; diff --git a/packages/react/src/skeleton/types.ts b/packages/react/src/skeleton/types.ts index 2d722cbc2..92e2526e4 100644 --- a/packages/react/src/skeleton/types.ts +++ b/packages/react/src/skeleton/types.ts @@ -1,7 +1,7 @@ import React from 'react'; import { BaseProps } from '../_utils/props'; -export interface SkeletonProps extends BaseProps, React.PropsWithRef { +export interface SkeletonProps extends BaseProps, React.ComponentProps<'div'> { active?: boolean; rounded?: boolean; children?: React.ReactNode; diff --git a/packages/react/src/slider/types.ts b/packages/react/src/slider/types.ts index 005254e16..e805f7ec9 100644 --- a/packages/react/src/slider/types.ts +++ b/packages/react/src/slider/types.ts @@ -14,7 +14,7 @@ export type SliderMarks = { export interface SliderProps extends BaseProps, - Omit, 'onChange' | 'defaultValue'> { + Omit, 'onChange' | 'defaultValue'> { value?: SliderValue; defaultValue?: SliderValue; min?: number; diff --git a/packages/react/src/space/types.ts b/packages/react/src/space/types.ts index 72a86fd2d..59629b6c8 100644 --- a/packages/react/src/space/types.ts +++ b/packages/react/src/space/types.ts @@ -4,7 +4,7 @@ import { BaseProps, DirectionType, SizeType } from '../_utils/props'; export type SpaceAlign = 'start' | 'end' | 'center' | 'baseline'; export type SpaceSize = SizeType | number; -export interface SpaceProps extends BaseProps, React.PropsWithRef { +export interface SpaceProps extends BaseProps, React.ComponentProps<'div'> { align?: SpaceAlign; direction?: DirectionType; size?: SpaceSize; diff --git a/packages/react/src/speed-dial/types.ts b/packages/react/src/speed-dial/types.ts index 54f5c5ca4..ec17b0a83 100644 --- a/packages/react/src/speed-dial/types.ts +++ b/packages/react/src/speed-dial/types.ts @@ -6,7 +6,7 @@ export type SpeedDialTrigger = 'hover' | 'click'; export interface SpeedDialProps extends BaseProps, - Omit, 'children'> { + Omit, 'children'> { icon?: React.ReactNode; openIcon?: React.ReactNode; direction?: SpeedDialDirection; @@ -20,7 +20,7 @@ export interface SpeedDialProps export interface SpeedDialActionProps extends BaseProps, - Omit, 'children'> { + Omit, 'children'> { icon: React.ReactNode; tooltip?: string; tooltipPlacement?: 'left' | 'right' | 'top' | 'bottom'; diff --git a/packages/react/src/split/resizer.tsx b/packages/react/src/split/resizer.tsx index 48ea1e438..eef47a943 100644 --- a/packages/react/src/split/resizer.tsx +++ b/packages/react/src/split/resizer.tsx @@ -7,7 +7,7 @@ import { SplitSeparatorRenderProps } from './types'; export interface ResizerProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { visualSize?: number; hitAreaSize: number; orientation: DirectionType; diff --git a/packages/react/src/split/types.ts b/packages/react/src/split/types.ts index 5c09bfb8d..5cc56ea07 100644 --- a/packages/react/src/split/types.ts +++ b/packages/react/src/split/types.ts @@ -18,7 +18,7 @@ export type SplitSeparatorRenderProps = { export interface SplitPaneProps extends BaseProps, - Omit, 'children'> { + Omit, 'children'> { /** Minimum pane size */ min?: SplitSize; @@ -30,7 +30,7 @@ export interface SplitPaneProps export interface SplitProps extends BaseProps, - Omit, 'children'> { + Omit, 'children'> { /** Pane arrangement: horizontal => left/right, vertical => top/bottom */ orientation?: SplitOrientation; diff --git a/packages/react/src/statistic/types.ts b/packages/react/src/statistic/types.ts index 782a0b8d5..612f0829f 100644 --- a/packages/react/src/statistic/types.ts +++ b/packages/react/src/statistic/types.ts @@ -49,7 +49,7 @@ export interface StatisticStatus { export interface StatisticProps extends BaseProps, - Omit, 'title' | 'prefix'> { + Omit, 'title' | 'prefix'> { title?: React.ReactNode; description?: React.ReactNode; tooltip?: React.ReactNode; diff --git a/packages/react/src/steps/types.ts b/packages/react/src/steps/types.ts index 3da660f89..009007d3d 100644 --- a/packages/react/src/steps/types.ts +++ b/packages/react/src/steps/types.ts @@ -5,7 +5,7 @@ export type StepsStatus = 'wait' | 'process' | 'finish' | 'error'; export interface StepsProps extends BaseProps, - Omit, 'onChange'> { + Omit, 'onChange'> { current?: number; defaultCurrent?: number; direction?: DirectionType; @@ -16,7 +16,7 @@ export interface StepsProps export interface StepsItemProps extends BaseProps, - Omit, 'title'> { + Omit, 'title'> { stepIndex?: number; icon?: ReactNode; title?: ReactNode; diff --git a/packages/react/src/sticky/types.ts b/packages/react/src/sticky/types.ts index feabb7b25..f210abfd8 100644 --- a/packages/react/src/sticky/types.ts +++ b/packages/react/src/sticky/types.ts @@ -4,7 +4,7 @@ import { Target } from '../_utils/dom'; export interface StickyProps extends BaseProps, - Omit, 'onChange'> { + Omit, 'onChange'> { offsetTop?: number; offsetBottom?: number; container?: () => Target; diff --git a/packages/react/src/strength-indicator/types.ts b/packages/react/src/strength-indicator/types.ts index 0d3ec3089..811975ebe 100644 --- a/packages/react/src/strength-indicator/types.ts +++ b/packages/react/src/strength-indicator/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface StrengthIndicatorProps extends BaseProps, - React.PropsWithRef { + React.ComponentProps<'div'> { /** the number of indicator, default is 3 */ blocks?: number; diff --git a/packages/react/src/switch/types.ts b/packages/react/src/switch/types.ts index 1bc72ed12..d55e2d772 100644 --- a/packages/react/src/switch/types.ts +++ b/packages/react/src/switch/types.ts @@ -3,7 +3,7 @@ import { BaseProps, SizeType } from '../_utils/props'; export interface SwitchProps extends BaseProps, - Omit, 'onChange' | 'onClick'> { + Omit, 'onChange' | 'onClick'> { defaultChecked?: boolean; checked?: boolean; disabled?: boolean; diff --git a/packages/react/src/table/types.ts b/packages/react/src/table/types.ts index 3ebc209e5..264b1f8e6 100644 --- a/packages/react/src/table/types.ts +++ b/packages/react/src/table/types.ts @@ -33,7 +33,7 @@ export interface TablePaginationConfig extends Pick extends BaseProps, - Omit, 'onChange'> { + Omit, 'onChange'> { columns: ColumnType[]; dataSource?: T[]; rowKey?: string | ((record: T) => React.Key); diff --git a/packages/react/src/tag/types.ts b/packages/react/src/tag/types.ts index 0d23ab002..afbc0b364 100644 --- a/packages/react/src/tag/types.ts +++ b/packages/react/src/tag/types.ts @@ -29,7 +29,7 @@ export const PresetColors = [ ...StatusColors, ]; -export interface TagProps extends BaseProps, React.PropsWithoutRef { +export interface TagProps extends BaseProps, React.ComponentPropsWithoutRef<'div'> { color?: string | StatusColor; variant?: TagVariant; closable?: boolean; diff --git a/packages/react/src/text-loop/types.ts b/packages/react/src/text-loop/types.ts index dc2c6457c..3299fd805 100644 --- a/packages/react/src/text-loop/types.ts +++ b/packages/react/src/text-loop/types.ts @@ -3,7 +3,7 @@ import { BaseProps } from '../_utils/props'; export interface TextLoopProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'div'> { /** Time each item stays visible, in ms (default: 3000) */ interval?: number; /** Pause cycling on hover (default: true) */ diff --git a/packages/react/src/timeline/types.ts b/packages/react/src/timeline/types.ts index 38b176280..3d310b4e5 100644 --- a/packages/react/src/timeline/types.ts +++ b/packages/react/src/timeline/types.ts @@ -5,14 +5,14 @@ export type TimelinePosition = 'left' | 'center'; export interface TimelineProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'ul'> { position?: TimelinePosition; children: React.ReactNode; } export interface TimelineItemProps extends BaseProps, - React.PropsWithoutRef { + React.ComponentPropsWithoutRef<'li'> { dot?: React.ReactNode; dotStyle?: CSSProperties; children?: React.ReactNode; diff --git a/packages/react/src/transfer/transfer-panel.tsx b/packages/react/src/transfer/transfer-panel.tsx index 4a92252c7..49d446294 100644 --- a/packages/react/src/transfer/transfer-panel.tsx +++ b/packages/react/src/transfer/transfer-panel.tsx @@ -11,7 +11,7 @@ import Input from '../input/input'; export interface TransferPanelProps extends BaseProps, - Omit, 'title' | 'onChange'> { + Omit, 'title' | 'onChange'> { dataSource: TransferItem[]; checkedKeys: string[]; onChange: (checkedKeys: string[]) => void; diff --git a/packages/react/src/transfer/types.ts b/packages/react/src/transfer/types.ts index 949594b62..7c4f3f345 100644 --- a/packages/react/src/transfer/types.ts +++ b/packages/react/src/transfer/types.ts @@ -9,7 +9,7 @@ export type TransferItem = { export interface TransferProps extends BaseProps, - Omit, 'onChange'> { + Omit, 'onChange'> { dataSource?: TransferItem[]; value?: string[]; defaultValue?: string[]; diff --git a/packages/react/src/tree/types.ts b/packages/react/src/tree/types.ts index f22384022..e06d8192e 100644 --- a/packages/react/src/tree/types.ts +++ b/packages/react/src/tree/types.ts @@ -12,7 +12,7 @@ export type TreeData = { export interface TreeProps extends BaseProps, - Omit, 'onSelect'> { + Omit, 'onSelect'> { data?: TreeData[]; indent?: number; checkable?: boolean; diff --git a/packages/react/src/typography/types.ts b/packages/react/src/typography/types.ts index 0797e80bf..6d102a7c4 100644 --- a/packages/react/src/typography/types.ts +++ b/packages/react/src/typography/types.ts @@ -30,11 +30,11 @@ export interface TypographyCopyableConfig { export interface TypographyProps extends BaseProps, - React.PropsWithRef { + React.ComponentProps<'div'> { children?: React.ReactNode; } -export interface ParagraphProps extends BaseProps, React.PropsWithRef { +export interface ParagraphProps extends BaseProps, React.ComponentProps<'p'> { as?: TypographyParagraphTag; ellipsis?: boolean | TypographyEllipsisConfig; children?: React.ReactNode; @@ -42,12 +42,12 @@ export interface ParagraphProps extends BaseProps, React.PropsWithRef> { + React.HTMLAttributes { level?: 1 | 2 | 3 | 4 | 5 | 6; children?: React.ReactNode; } -export interface TextProps extends BaseProps, React.PropsWithRef { +export interface TextProps extends BaseProps, React.ComponentProps<'span'> { as?: TypographyTextTag; type?: TextType; copyable?: boolean | TypographyCopyableConfig; diff --git a/packages/react/src/waterfall/types.ts b/packages/react/src/waterfall/types.ts index bf23b34e2..d8972c25f 100644 --- a/packages/react/src/waterfall/types.ts +++ b/packages/react/src/waterfall/types.ts @@ -15,7 +15,7 @@ export interface WaterfallItem { export interface WaterfallProps extends BaseProps, - Omit, 'children'> { + Omit, 'children'> { /** Number of columns, or responsive breakpoint config. Default: 3 */ columns?: number | Partial>; /** Spacing between items: number or [horizontal, vertical] */ From d4fcf7fb313991e83dfec80dac004f405e825482 Mon Sep 17 00:00:00 2001 From: wangdicoder Date: Sun, 19 Apr 2026 09:22:45 +1000 Subject: [PATCH 2/3] refactor(react): normalize forwardRef props to ComponentPropsWithoutRef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The codebase mixed `ComponentProps` (with ref) and `ComponentPropsWithoutRef` across prop interfaces, all consumed by `React.forwardRef`. Normalize to `ComponentPropsWithoutRef` throughout — the idiomatic pattern React docs recommend for forwardRef, since forwardRef re-adds ref via `RefAttributes` to the external component type. Side benefit: for the handful of non-forwardRef components (Link, Form, FormItem, Descriptions), this removes `ref` from the prop type so consumers can no longer pass a non-functional `ref` prop. Zero external API change for forwardRef components — ` + + ); + + expect(ref.current).toBeInstanceOf(HTMLFormElement); + }); }); diff --git a/packages/react/src/form/form.tsx b/packages/react/src/form/form.tsx index 64cd266f6..a57bf44f9 100644 --- a/packages/react/src/form/form.tsx +++ b/packages/react/src/form/form.tsx @@ -7,7 +7,7 @@ import { getPrefixCls } from '../_utils/general'; import { FormProps } from './types'; import FormInstance from './form-instance'; -const Form = (props: FormProps): JSX.Element => { +const Form = React.forwardRef((props, ref): JSX.Element => { const { initialValues = {}, labelCol = { span: 8, offset: 0 }, @@ -49,13 +49,13 @@ const Form = (props: FormProps): JSX.Element => { return ( -
+ {children}
); -}; +}); Form.displayName = 'Form'; diff --git a/packages/react/src/link/__tests__/link.test.tsx b/packages/react/src/link/__tests__/link.test.tsx index 1fadea1b0..ead4855c1 100644 --- a/packages/react/src/link/__tests__/link.test.tsx +++ b/packages/react/src/link/__tests__/link.test.tsx @@ -24,4 +24,18 @@ describe('', () => { const { container } = render(Link); expect(container.firstChild).toHaveClass('ty-link_disabled'); }); + + it('should forward ref to anchor element', () => { + const ref = React.createRef(); + render(Link); + + expect(ref.current).toBeInstanceOf(HTMLAnchorElement); + }); + + it('should forward ref to disabled fallback element', () => { + const ref = React.createRef(); + render(Link); + + expect(ref.current).toBeInstanceOf(HTMLSpanElement); + }); }); diff --git a/packages/react/src/link/link.tsx b/packages/react/src/link/link.tsx index f1abb9045..7116eb073 100755 --- a/packages/react/src/link/link.tsx +++ b/packages/react/src/link/link.tsx @@ -4,43 +4,47 @@ import { ConfigContext } from '../config-provider/config-context'; import { getPrefixCls } from '../_utils/general'; import { LinkProps } from './types'; -const Link = React.memo((props: LinkProps): React.ReactElement => { - const { - disabled = false, - external = true, - underline = true, - className, - style, - children, - target, - prefixCls: customisedCls, - ...otherProps - } = props; - const configContext = useContext(ConfigContext); - const prefixCls = getPrefixCls('link', configContext.prefixCls, customisedCls); - const cls = classNames(prefixCls, className, { - [`${prefixCls}_disabled`]: disabled, - [`${prefixCls}_no-underline`]: !underline, - }); +const Link = React.memo( + React.forwardRef((props, ref): React.ReactElement => { + const { + disabled = false, + external = true, + underline = true, + className, + style, + children, + target, + prefixCls: customisedCls, + ...otherProps + } = props; + const configContext = useContext(ConfigContext); + const prefixCls = getPrefixCls('link', configContext.prefixCls, customisedCls); + const cls = classNames(prefixCls, className, { + [`${prefixCls}_disabled`]: disabled, + [`${prefixCls}_no-underline`]: !underline, + }); + + if (disabled) { + return ( + } className={cls} style={style} role="link" aria-disabled="true"> + {children} + + ); + } - if (disabled) { return ( - + } + target={target ? target : external ? '_blank' : '_self'} + className={cls} + style={style} + role="link"> {children} - + ); - } - return ( - - {children} - - ); -}); + }) +); Link.displayName = 'Link'; diff --git a/packages/react/src/radio/radio-group.tsx b/packages/react/src/radio/radio-group.tsx index 7b2a42895..65f4a7d71 100755 --- a/packages/react/src/radio/radio-group.tsx +++ b/packages/react/src/radio/radio-group.tsx @@ -5,52 +5,50 @@ import { getPrefixCls } from '../_utils/general'; import { RadioGroupContext } from './radio-group-context'; import { RadioGroupProps } from './types'; -const RadioGroup = React.forwardRef( - (props: RadioGroupProps, ref): JSX.Element => { - const { - defaultValue = '', - disabled = false, - name, - onChange, - className, - children, - prefixCls: customisedCls, - ...otherProps - } = props; - const configContext = useContext(ConfigContext); - const prefixCls = getPrefixCls('radio-group', configContext.prefixCls, customisedCls); - const cls = classNames(prefixCls, className); - const [value, setValue] = useState( - 'value' in props ? (props.value as number | string) : defaultValue - ); +const RadioGroup = (props: RadioGroupProps): JSX.Element => { + const { + defaultValue = '', + disabled = false, + name, + onChange, + className, + children, + prefixCls: customisedCls, + ...otherProps + } = props; + const configContext = useContext(ConfigContext); + const prefixCls = getPrefixCls('radio-group', configContext.prefixCls, customisedCls); + const cls = classNames(prefixCls, className); + const [value, setValue] = useState( + 'value' in props ? (props.value as number | string) : defaultValue + ); - const radioOnChange = (e: React.ChangeEvent): void => { - if (!disabled) { - const val = e.currentTarget.value; - !('value' in props) && setValue(val); - onChange && onChange(val); - } - }; + const radioOnChange = (e: React.ChangeEvent): void => { + if (!disabled) { + const val = e.currentTarget.value; + !('value' in props) && setValue(val); + onChange && onChange(val); + } + }; - useEffect(() => { - 'value' in props && setValue(props.value as number | string); - }, [props]); + useEffect(() => { + 'value' in props && setValue(props.value as number | string); + }, [props]); - return ( - -
- {children} -
-
- ); - } -); + return ( + +
+ {children} +
+
+ ); +}; RadioGroup.displayName = 'RadioGroup';