diff --git a/packages/fuselage-forms/fuselage-forms.api.md b/packages/fuselage-forms/fuselage-forms.api.md index 880c4cb633..1f41a9a89f 100644 --- a/packages/fuselage-forms/fuselage-forms.api.md +++ b/packages/fuselage-forms/fuselage-forms.api.md @@ -13,6 +13,7 @@ import { ComponentPropsWithoutRef } from 'react'; import { Context } from 'react'; import { Dispatch } from 'react'; import { ElementType } from 'react'; +import { EmailInputProps } from '@rocket.chat/fuselage'; import { Field as Field_2 } from '@rocket.chat/fuselage'; import { FieldDescription as FieldDescription_2 } from '@rocket.chat/fuselage'; import { FieldError as FieldError_2 } from '@rocket.chat/fuselage'; @@ -22,7 +23,6 @@ import { FieldLabel as FieldLabel_2 } from '@rocket.chat/fuselage'; import { FieldLabelInfo } from '@rocket.chat/fuselage'; import { FieldLink } from '@rocket.chat/fuselage'; import { FieldRow } from '@rocket.chat/fuselage'; -import { ForwardRefExoticComponent } from 'react'; import { IconProps } from '@rocket.chat/fuselage'; import { InputBoxProps } from '@rocket.chat/fuselage'; import { JSX } from 'react'; @@ -34,25 +34,31 @@ import { PasswordInputProps } from '@rocket.chat/fuselage'; import { ReactNode } from 'react'; import { RefAttributes } from 'react'; import type { RefCallback } from 'react'; +import { SearchInputProps } from '@rocket.chat/fuselage'; import { SelectOption } from '@rocket.chat/fuselage'; import { SetStateAction } from 'react'; import { Slider as Slider_2 } from '@rocket.chat/fuselage'; +import { TelephoneInputProps } from '@rocket.chat/fuselage'; +import { TextAreaInputProps } from '@rocket.chat/fuselage'; import { UrlInputProps } from '@rocket.chat/fuselage'; // @public (undocumented) export const AutoComplete: typeof AutoComplete_2; // @public (undocumented) -export const CheckBox: ForwardRefExoticComponent & RefAttributes, "ref"> & RefAttributes>; +export const CheckBox: { + (props: Omit & RefAttributes & { + indeterminate?: boolean; + labelChildren?: ReactNode; + } & AllHTMLAttributes): JSX.Element; + displayName: string; +}; // @public (undocumented) -export const EmailInput: ForwardRefExoticComponent & { -addon?: ReactNode; -error?: string; -} & RefAttributes, "ref"> & RefAttributes>; +export const EmailInput: { + (props: EmailInputProps & RefAttributes): JSX.Element; + displayName: string; +}; // @public (undocumented) export function Field(input: FieldProps): JSX.Element; @@ -143,63 +149,78 @@ export type LabelForProps = ComponentProps; export type LabelTypes = 'hint' | 'description' | 'error' | 'placeholder'; // @public (undocumented) -export const MultiSelect: ForwardRefExoticComponent & { -value?: SelectOption[0][]; -error?: string; -options: SelectOption[]; -onChange: (params: SelectOption[0][]) => void; -getLabel?: (params: SelectOption) => SelectOption[1]; -getValue?: (params: SelectOption) => SelectOption[0]; -customEmpty?: string; -anchor?: ElementType | ((params: MultiSelectAnchorParams) => ReactNode); -renderOptions?: ElementType; -renderItem?: ElementType; -renderSelected?: ElementType< { -value: SelectOption[0]; -label: SelectOption[1]; -onMouseDown: MouseEventHandler; -children: ReactNode; -}>; -addonIcon?: IconProps["name"]; -setFilter?: (filter: string) => void; -} & RefAttributes, "ref"> & RefAttributes>; - -// @public (undocumented) -export const MultiSelectFiltered: ForwardRefExoticComponent & { -value?: SelectOption[0][]; -error?: string; -options: SelectOption[]; -onChange: (params: SelectOption[0][]) => void; -getLabel?: (params: SelectOption) => SelectOption[1]; -getValue?: (params: SelectOption) => SelectOption[0]; -customEmpty?: string; -anchor?: ElementType | ((params: MultiSelectAnchorParams) => ReactNode); -renderOptions?: ElementType; -renderItem?: ElementType; -renderSelected?: ElementType< { -value: SelectOption[0]; -label: SelectOption[1]; -onMouseDown: MouseEventHandler; -children: ReactNode; -}>; -addonIcon?: IconProps["name"]; -setFilter?: (filter: string) => void; -} & { -filter?: string; -setFilter?: Dispatch>; -addonIcon?: IconProps["name"]; -} & RefAttributes, "ref"> & RefAttributes>; - -// @public (undocumented) -export const NumberInput: ForwardRefExoticComponent, "ref"> & RefAttributes>; - -// @public (undocumented) -export const PasswordInput: ForwardRefExoticComponent, "ref"> & RefAttributes>; - -// @public (undocumented) -export const RadioButton: ForwardRefExoticComponent & { -labelChildren?: ReactNode; -} & RefAttributes, "ref"> & RefAttributes>; +export const MultiSelect: { + (props: Omit & RefAttributes & { + value?: SelectOption[0][]; + error?: string; + options: SelectOption[]; + onChange: (params: SelectOption[0][]) => void; + getLabel?: (params: SelectOption) => SelectOption[1]; + getValue?: (params: SelectOption) => SelectOption[0]; + customEmpty?: string; + anchor?: ElementType | ((params: MultiSelectAnchorParams) => ReactNode); + renderOptions?: ElementType; + renderItem?: ElementType; + renderSelected?: ElementType< { + value: SelectOption[0]; + label: SelectOption[1]; + onMouseDown: MouseEventHandler; + children: ReactNode; + }>; + addonIcon?: IconProps["name"]; + setFilter?: (filter: string) => void; + }): JSX.Element; + displayName: string; +}; + +// @public (undocumented) +export const MultiSelectFiltered: { + (props: Omit & RefAttributes & { + value?: SelectOption[0][]; + error?: string; + options: SelectOption[]; + onChange: (params: SelectOption[0][]) => void; + getLabel?: (params: SelectOption) => SelectOption[1]; + getValue?: (params: SelectOption) => SelectOption[0]; + customEmpty?: string; + anchor?: ElementType | ((params: MultiSelectAnchorParams) => ReactNode); + renderOptions?: ElementType; + renderItem?: ElementType; + renderSelected?: ElementType< { + value: SelectOption[0]; + label: SelectOption[1]; + onMouseDown: MouseEventHandler; + children: ReactNode; + }>; + addonIcon?: IconProps["name"]; + setFilter?: (filter: string) => void; + } & { + filter?: string; + setFilter?: Dispatch>; + addonIcon?: IconProps["name"]; + }): JSX.Element; + displayName: string; +}; + +// @public (undocumented) +export const NumberInput: { + (props: NumberInputProps & RefAttributes): JSX.Element; + displayName: string; +}; + +// @public (undocumented) +export const PasswordInput: { + (props: PasswordInputProps & RefAttributes): JSX.Element; + displayName: string; +}; + +// @public (undocumented) +export const RadioButton: { + (props: Omit & RefAttributes & AllHTMLAttributes & { + labelChildren?: ReactNode; + }): JSX.Element; + displayName: string; +}; // @public (undocumented) export const ReferencedLabel: (input: ReferencedLabelProps) => JSX.Element; @@ -208,50 +229,61 @@ export const ReferencedLabel: (input: ReferencedLabelProps) => JSX.Element; export type ReferencedLabelProps = ComponentProps; // @public (undocumented) -export const SearchInput: ForwardRefExoticComponent & { -addon?: ReactNode; -error?: string; -} & RefAttributes, "ref"> & RefAttributes>; +export const SearchInput: { + (props: SearchInputProps & RefAttributes): JSX.Element; + displayName: string; +}; // @public (undocumented) -export const Select: ForwardRefExoticComponent, "children" | "value" | "onChange"> & { -error?: string; -placeholder?: string; -value?: Key | null | undefined; -onChange?: ((key: Key) => any) | undefined; -options: SelectOption[]; -small?: boolean; -} & Omit, "value" | "onChange"> & RefAttributes, "ref"> & RefAttributes>; +export const Select: { + (props: Omit, "children" | "value" | "onChange"> & RefAttributes & { + error?: string; + placeholder?: string; + value?: Key | null | undefined; + onChange?: ((key: Key) => any) | undefined; + options: SelectOption[]; + small?: boolean; + } & Omit, "value" | "onChange">): JSX.Element; + displayName: string; +}; // @public (undocumented) export const Slider: typeof Slider_2; // @public (undocumented) -export const TelephoneInput: ForwardRefExoticComponent & { -addon?: ReactNode; -input?: ReactNode; -error?: string; -} & RefAttributes, "ref"> & RefAttributes>; +export const TelephoneInput: { + (props: TelephoneInputProps & RefAttributes): JSX.Element; + displayName: string; +}; // @public (undocumented) -export const TextAreaInput: ForwardRefExoticComponent & { -addon?: ReactNode; -error?: string; -} & RefAttributes, "ref"> & RefAttributes>; +export const TextAreaInput: { + (props: TextAreaInputProps & RefAttributes): JSX.Element; + displayName: string; +}; // @public (undocumented) -export const TextInput: ForwardRefExoticComponent & { -addon?: ReactNode; -error?: string; -} & RefAttributes, "ref"> & RefAttributes>; +export const TextInput: { + (props: Omit & RefAttributes & { + addon?: ReactNode; + error?: string; + }): JSX.Element; + displayName: string; +}; // @public (undocumented) -export const ToggleSwitch: ForwardRefExoticComponent & { -labelChildren?: ReactNode; -} & RefAttributes, "ref"> & RefAttributes>; +export const ToggleSwitch: { + (props: Omit & RefAttributes & AllHTMLAttributes & { + labelChildren?: ReactNode; + }): JSX.Element; + displayName: string; +}; // @public (undocumented) -export const UrlInput: ForwardRefExoticComponent, "ref"> & RefAttributes>; +export const UrlInput: { + (props: UrlInputProps & RefAttributes): JSX.Element; + displayName: string; +}; // @public (undocumented) export const useFieldDescriptorId: (type: LabelTypes) => string; diff --git a/packages/fuselage-forms/src/Inputs/withLabelHelpers.tsx b/packages/fuselage-forms/src/Inputs/withLabelHelpers.tsx index e0392ed786..dd5e179be3 100644 --- a/packages/fuselage-forms/src/Inputs/withLabelHelpers.tsx +++ b/packages/fuselage-forms/src/Inputs/withLabelHelpers.tsx @@ -2,7 +2,6 @@ /* eslint-disable react/no-multi-comp */ import { useMergedRefs } from '@rocket.chat/fuselage-hooks'; import type { ReactNode, ComponentType, Ref, RefAttributes } from 'react'; -import { forwardRef } from 'react'; import { VisuallyHidden } from 'react-aria'; import { @@ -17,16 +16,10 @@ type WithLabelId = { id?: string }; function withLabelId( Component: ComponentType>, ) { - const WrappedComponent = forwardRef(function (props, ref) { + function WrappedComponent(props: TProps & RefAttributes) { const labelProps = useFieldReferencedByInput(); - return ( - - ); - }); + return ; + } WrappedComponent.displayName = `withLabelId(${Component.displayName ?? Component.name ?? 'InputComponent'})`; @@ -38,16 +31,10 @@ type WithLabelledBy = { 'aria-labelledby'?: string }; function withAriaLabelledBy( Component: ComponentType>, ) { - const WrappedComponent = forwardRef(function (props, ref) { + function WrappedComponent(props: TProps & RefAttributes) { const labelProps = useFieldReferencedByLabel(); - return ( - - ); - }); + return ; + } WrappedComponent.displayName = `withAriaLabelledBy(${Component.displayName ?? Component.name ?? 'InputComponent'})`; @@ -59,16 +46,10 @@ type WithLabelledByAndId = { 'aria-labelledby'?: string; 'id'?: string }; function withAriaLabelledByAndId( Component: ComponentType>, ) { - const WrappedComponent = forwardRef(function (props, ref) { + function WrappedComponent(props: TProps & RefAttributes) { const labelProps = useFieldReferencedByLabelWithId(); - return ( - - ); - }); + return ; + } WrappedComponent.displayName = `withAriaLabelledByAndId(${Component.displayName ?? Component.name ?? 'InputComponent'})`; @@ -80,18 +61,18 @@ type WithChildrenLabel = { labelChildren: ReactNode }; function withVisuallyHiddenLabel( Component: ComponentType>, ) { - const WrappedComponent = forwardRef(function (props, ref) { + function WrappedComponent(props: TProps & RefAttributes) { const [label, labelProps, labelRef] = useFieldWrappedByInputLabel(); - const mergedRef = useMergedRefs(ref, labelRef as Ref); + const mergedRef = useMergedRefs(props.ref, labelRef as Ref); return ( {label}} /> ); - }); + } WrappedComponent.displayName = `withVisuallyHiddenLabel(${Component.displayName ?? Component.name ?? 'InputComponent'})`; diff --git a/packages/fuselage/fuselage.api.md b/packages/fuselage/fuselage.api.md index 17803451c8..11158ceef8 100644 --- a/packages/fuselage/fuselage.api.md +++ b/packages/fuselage/fuselage.api.md @@ -19,9 +19,8 @@ import type { DetailedHTMLProps } from 'react'; import type { Dispatch } from 'react'; import { ElementType } from 'react'; import type { FocusEventHandler } from 'react'; -import { ForwardRefExoticComponent } from 'react'; import type { HTMLAttributeAnchorTarget } from 'react'; -import { HTMLAttributes } from 'react'; +import type { HTMLAttributes } from 'react'; import type { ImgHTMLAttributes } from 'react'; import type { ItemProps } from '@react-types/shared'; import { JSX } from 'react'; @@ -29,22 +28,20 @@ import { JSXElementConstructor } from 'react'; import { Key } from 'react'; import type { KeyboardEvent as KeyboardEvent_2 } from 'react'; import type { KeyboardEventHandler } from 'react'; -import { Keys } from '@rocket.chat/icons'; +import type { Keys } from '@rocket.chat/icons'; import type { LinkHTMLAttributes } from 'react'; import { MemoExoticComponent } from 'react'; import { MemoizedFunction } from '@rocket.chat/memo'; import type { MenuTriggerProps } from 'react-stately'; import { MouseEvent as MouseEvent_2 } from 'react'; -import { MouseEventHandler } from 'react'; -import { NamedExoticComponent } from 'react'; +import type { MouseEventHandler } from 'react'; import type { OverlayTriggerState } from 'react-stately'; import type { PropsWithChildren } from 'react'; -import type { PropsWithoutRef } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { ReactPortal } from 'react'; import type { Ref } from 'react'; -import { RefAttributes } from 'react'; +import type { RefAttributes } from 'react'; import type { RefObject } from 'react'; import type { SectionProps } from '@react-types/shared'; import type { SetStateAction } from 'react'; @@ -79,25 +76,7 @@ export type AccordionProps = { } & Partial; // @public (undocumented) -export const ActionButton: ForwardRefExoticComponent, "className" | "size" | "is"> & ActionButtonSize & { -icon: IconProps["name"]; -} & RefAttributes>; +export function ActionButton(input: ActionButtonProps): JSX.Element; // @public (undocumented) export type ActionButtonProps = ButtonProps & ActionButtonSize & { @@ -127,10 +106,32 @@ export type AnimatedVisibilityProps = { }; // @public (undocumented) -export const AudioPlayer: ForwardRefExoticComponent>; +export const AudioPlayer: (input: AudioPlayerProps) => JSX.Element; // @public (undocumented) -export type AudioPlayerProps = { +export const AudioPlayerControls: (input: AudioPlayerControlsProps) => JSX.Element; + +// @public (undocumented) +export type AudioPlayerControlsProps = { + isPlaying: boolean; + currentTime: number; + durationTime: number; + playbackSpeed: number; + onTogglePlay: () => void; + onSeek: (time: number) => void; + onChangePlaybackSpeed: () => void; + download?: boolean; + downloadHref?: string; + onDownload?: (event: MouseEvent_2) => void; + playLabel?: string; + pauseLabel?: string; + audioPlaybackRangeLabel?: string; + changePlaybackSpeedLabel?: string; + downloadAudioFileLabel?: string; +}; + +// @public (undocumented) +export type AudioPlayerProps = RefAttributes & { src: string; type?: string; maxPlaybackSpeed?: number; @@ -146,9 +147,7 @@ export type AudioPlayerProps = { }; // @public (undocumented) -export const AutoComplete: Pick, keyof ForwardRefExoticComponent> & { - (props: AutoCompleteProps & RefAttributes): ReactNode; -}; +export function AutoComplete(input: AutoCompleteProps): JSX.Element; // @public (undocumented) export type AutoCompleteOption = { @@ -172,6 +171,7 @@ export type AutoCompleteProps = Omit; renderEmpty?: ComponentType<{ customEmpty?: string; @@ -251,11 +251,13 @@ export const borderRadius: MemoizedFunction; +// Warning: (ae-forgotten-export) The symbol "Box_2" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const Box: NamedExoticComponent>; +export const Box: MemoExoticComponent; // @public (undocumented) -export interface BoxProps extends Partial, Omit, 'ref' | 'is' | 'className' | 'size' | 'elevation' | keyof StylingProps>, Omit, keyof AllHTMLAttributes | 'elevation' | keyof StylingProps> { +export interface BoxProps extends Partial, Omit, 'ref' | 'is' | 'className' | 'size' | 'elevation' | keyof StylingProps>, Omit, keyof AllHTMLAttributes | 'elevation' | keyof StylingProps>, RefAttributes { // (undocumented) animated?: boolean; // (undocumented) @@ -286,36 +288,13 @@ export type BubbleProps = { } & Omit, 'onClick'>; // @public (undocumented) -export const Button: ForwardRefExoticComponent, "className" | "size" | "is"> & RefAttributes>; - -// @public (undocumented) -export const ButtonGroup: ForwardRefExoticComponent< { -align?: "start" | "center" | "end"; -stretch?: boolean; -wrap?: boolean; -vertical?: boolean; -small?: boolean; -large?: boolean; -} & HTMLAttributes & RefAttributes>; - -// @public (undocumented) -export type ButtonGroupProps = { +export function Button(input: ButtonProps): JSX.Element; + +// @public (undocumented) +export function ButtonGroup(input: ButtonGroupProps): JSX.Element; + +// @public (undocumented) +export type ButtonGroupProps = RefAttributes & { align?: 'start' | 'center' | 'end'; stretch?: boolean; wrap?: boolean; @@ -325,7 +304,7 @@ export type ButtonGroupProps = { } & HTMLAttributes; // @public (undocumented) -export type ButtonProps = BoxProps & { +export type ButtonProps = Omit & { primary?: boolean; secondary?: boolean; danger?: boolean; @@ -341,7 +320,7 @@ export type ButtonProps = BoxProps & { square?: boolean; external?: boolean; icon?: IconProps['name']; -} & Omit, 'is' | 'className' | 'size'>; +} & Omit, 'is' | 'className' | 'size'> & RefAttributes; // @public (undocumented) export const Callout: (input: CalloutProps) => JSX.Element; @@ -439,13 +418,10 @@ export type CardTitleProps = { } & Omit, 'is'>; // @public (undocumented) -export const CheckBox: ForwardRefExoticComponent & RefAttributes>; +export function CheckBox(input: CheckBoxProps): JSX.Element; // @public (undocumented) -export type CheckBoxProps = BoxProps & { +export type CheckBoxProps = Omit & RefAttributes & { indeterminate?: boolean; labelChildren?: ReactNode; } & AllHTMLAttributes; @@ -505,8 +481,10 @@ export type CodeSnippetProps = BoxProps & { // @public (undocumented) export const color: MemoizedFunction; +// Warning: (ae-forgotten-export) The symbol "Contextualbar_2" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const Contextualbar: NamedExoticComponent>; +export const Contextualbar: MemoExoticComponent; // @public (undocumented) export const ContextualbarAction: MemoExoticComponent<(input: ContextualbarActionProps) => JSX.Element>; @@ -528,31 +506,33 @@ export const ContextualbarButton: MemoExoticComponent<(props: ContextualbarButto // @public (undocumented) export type ContextualbarButtonProps = ButtonProps; +// Warning: (ae-forgotten-export) The symbol "ContextualbarContent_2" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const ContextualbarContent: NamedExoticComponent>; +export const ContextualbarContent: MemoExoticComponent; // @public (undocumented) -export type ContextualbarContentProps = BoxProps; +export type ContextualbarContentProps = Omit & RefAttributes; +// Warning: (ae-forgotten-export) The symbol "ContextualbarEmptyContent_2" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const ContextualbarEmptyContent: NamedExoticComponent>; +export const ContextualbarEmptyContent: MemoExoticComponent; // @public (undocumented) -export type ContextualbarEmptyContentProps = BoxProps & { +export type ContextualbarEmptyContentProps = Omit & RefAttributes & { icon?: StatesIconProps['name']; title?: string; subtitle?: string; }; +// Warning: (ae-forgotten-export) The symbol "ContextualbarFooter_2" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const ContextualbarFooter: NamedExoticComponent>; +export const ContextualbarFooter: MemoExoticComponent; // @public (undocumented) -export type ContextualbarFooterProps = BoxProps; +export type ContextualbarFooterProps = Omit & RefAttributes; // @public (undocumented) export const ContextualbarHeader: MemoExoticComponent<(input: ContextualbarHeaderProps) => JSX.Element>; @@ -567,13 +547,15 @@ export const ContextualbarIcon: MemoExoticComponent<(props: ContextualbarIconPro export type ContextualbarIconProps = IconProps; // @public (undocumented) -export type ContextualbarProps = BoxProps; +export type ContextualbarProps = Omit & RefAttributes; +// Warning: (ae-forgotten-export) The symbol "ContextualbarSection_2" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const ContextualbarSection: NamedExoticComponent>; +export const ContextualbarSection: MemoExoticComponent; // @public (undocumented) -export type ContextualbarSectionProps = BoxProps; +export type ContextualbarSectionProps = Omit & RefAttributes; // @public (undocumented) export const ContextualbarSkeleton: MemoExoticComponent<(props: ContextualbarSkeletonProps) => JSX.Element>; @@ -587,8 +569,10 @@ export const ContextualbarTitle: MemoExoticComponent<(props: ContextualbarTitleP // @public (undocumented) export type ContextualbarTitleProps = BoxProps; +// Warning: (ae-forgotten-export) The symbol "Contextualbar_3" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const ContextualbarV2: NamedExoticComponent>; +export const ContextualbarV2: MemoExoticComponent; // @public (undocumented) export const ContextualbarV2Action: MemoExoticComponent<(input: ContextualbarV2ActionProps) => JSX.Element>; @@ -610,18 +594,18 @@ export const ContextualbarV2Button: MemoExoticComponent<(props: ContextualbarV2B // @public (undocumented) export type ContextualbarV2ButtonProps = ButtonProps; +// Warning: (ae-forgotten-export) The symbol "ContextualbarContent_3" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const ContextualbarV2Content: NamedExoticComponent>; +export const ContextualbarV2Content: MemoExoticComponent; // @public (undocumented) -export type ContextualbarV2ContentProps = BoxProps; +export type ContextualbarV2ContentProps = Omit & RefAttributes; +// Warning: (ae-forgotten-export) The symbol "ContextualbarEmptyContent_3" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const ContextualbarV2EmptyContent: NamedExoticComponent>; +export const ContextualbarV2EmptyContent: MemoExoticComponent; // @public (undocumented) export type ContextualbarV2EmptyContentProps = ContextualbarV2ContentProps & { @@ -630,11 +614,13 @@ export type ContextualbarV2EmptyContentProps = ContextualbarV2ContentProps & { subtitle?: string; }; +// Warning: (ae-forgotten-export) The symbol "ContextualbarFooter_3" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const ContextualbarV2Footer: NamedExoticComponent>; +export const ContextualbarV2Footer: MemoExoticComponent; // @public (undocumented) -export type ContextualbarV2FooterProps = BoxProps; +export type ContextualbarV2FooterProps = Omit & RefAttributes; // @public (undocumented) export const ContextualbarV2Header: MemoExoticComponent<(input: ContextualbarV2HeaderProps) => JSX.Element>; @@ -649,13 +635,15 @@ export const ContextualbarV2Icon: MemoExoticComponent<(props: ContextualbarV2Ico export type ContextualbarV2IconProps = IconProps; // @public (undocumented) -export type ContextualbarV2Props = BoxProps; +export type ContextualbarV2Props = Omit & RefAttributes; +// Warning: (ae-forgotten-export) The symbol "ContextualbarSection_3" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const ContextualbarV2Section: NamedExoticComponent>; +export const ContextualbarV2Section: MemoExoticComponent; // @public (undocumented) -export type ContextualbarV2SectionProps = BoxProps; +export type ContextualbarV2SectionProps = Omit & RefAttributes; // @public (undocumented) export const ContextualbarV2Skeleton: MemoExoticComponent<(props: ContextualbarV2SkeletonProps) => JSX.Element>; @@ -680,26 +668,20 @@ export type DividerProps = BoxProps & { }; // @public (undocumented) -export const Dropdown: ForwardRefExoticComponent & RefAttributes>; +export function Dropdown(input: DropdownProps): JSX.Element; // @public (undocumented) -export type DropdownProps = { +export type DropdownProps = RefAttributes & { reference: RefObject; placement?: UsePositionOptions['placement']; children: ReactNode; }; // @public (undocumented) -export const EmailInput: ForwardRefExoticComponent & { -addon?: ReactNode; -error?: string; -} & RefAttributes>; +export function EmailInput(props: EmailInputProps): JSX.Element; // @public (undocumented) -export type EmailInputProps = Omit & { - addon?: ReactNode; - error?: string; -}; +export type EmailInputProps = Omit, 'type'>; // @public (undocumented) export type Falsy = false | 0 | '' | null | undefined; @@ -732,11 +714,7 @@ export const FieldHint: (props: FieldHintProps) => JSX.Element; export type FieldHintProps = BoxProps; // @public (undocumented) -export const FieldLabel: ForwardRefExoticComponent & { -disabled?: boolean; -required?: boolean; -is?: (ElementType & string) | undefined; -} & RefAttributes>; +export function FieldLabel(props: FieldLabelProps): JSX.Element; // @public (undocumented) export const FieldLabelInfo: (props: FieldLabelInfoProps) => JSX.Element; @@ -853,22 +831,10 @@ export type GridProps = BoxProps & { }; // @public (undocumented) -export const Icon: ForwardRefExoticComponent & { -name: Keys; -size?: BoxProps["width"]; -} & RefAttributes>; +export function Icon(input: IconProps): JSX.Element; // @public (undocumented) -export const IconButton: ForwardRefExoticComponent< { -icon: Keys | ReactElement; -primary?: boolean; -secondary?: boolean; -info?: boolean; -danger?: boolean; -warning?: boolean; -success?: boolean; -pressed?: boolean; -} & IconButtonSize & BoxProps & RefAttributes>; +export function IconButton(input: IconButtonProps): JSX.Element; // @public (undocumented) export type IconButtonProps = { @@ -892,30 +858,19 @@ export type IconButtonSize = { }; // @public (undocumented) -export type IconProps = Omit & { +export type IconProps = Omit & RefAttributes & { name: Keys; size?: BoxProps['width']; }; // @public (undocumented) -export const Input: ForwardRefExoticComponent>; +export function Input(props: InputProps): JSX.Element; // @public (undocumented) -export const InputBox: ForwardRefExoticComponent>; +export function InputBox(input: InputBoxProps): JSX.Element; // @public (undocumented) -export type InputBoxProps = BoxProps & { +export type InputBoxProps = Omit & RefAttributes & { addon?: ReactNode; startAddon?: ReactNode; endAddon?: ReactNode; @@ -935,17 +890,13 @@ export const InputBoxSkeleton: (props: InputBoxSkeletonProps) => JSX.Element; export type InputBoxSkeletonProps = BoxProps; // @public (undocumented) -export type InputProps = BoxProps; +export type InputProps = Omit & RefAttributes; // @public (undocumented) export type ItemsPerPage = 25 | 50 | 100; // @public (undocumented) -export const Label: ForwardRefExoticComponent & { -disabled?: boolean; -required?: boolean; -is?: (ElementType & string) | undefined; -} & RefAttributes>; +export function Label(input: LabelProps): JSX.Element; // @public (undocumented) export type LabelInfoProps = { @@ -954,10 +905,9 @@ export type LabelInfoProps = { } & Omit; // @public (undocumented) -export type LabelProps = Omit & { +export type LabelProps = Omit & RefAttributes & { disabled?: boolean; required?: boolean; - is?: (ElementType & string) | undefined; }; // @public (undocumented) @@ -1035,25 +985,15 @@ export namespace MenuSection { export type MenuSectionProps = SectionProps; // @public (undocumented) -export const Message: ForwardRefExoticComponent & { -clickable?: boolean; -sequential?: boolean; -className?: string; -isSelected?: boolean; -isEditing?: boolean; -isPending?: boolean; -highlight?: boolean; -} & RefAttributes>; +export function Message(input: MessageProps): JSX.Element; // @public (undocumented) -export const MessageBlock: ForwardRefExoticComponent< { -fixedWidth?: boolean; -} & BoxProps & RefAttributes>; +export function MessageBlock(input: MessageBlockProps): JSX.Element; // @public (undocumented) -export type MessageBlockProps = { +export type MessageBlockProps = Omit & RefAttributes & { fixedWidth?: boolean; -} & BoxProps; +}; // @public (undocumented) export const MessageBody: (input: MessageBodyProps) => JSX.Element; @@ -1259,16 +1199,16 @@ export type MessageMetricsReplyProps = ButtonProps; export const MessageName: (props: MessageNameProps) => JSX.Element; // @public (undocumented) -export const MessageNameContainer: ForwardRefExoticComponent>; +export function MessageNameContainer(props: MessageNameContainerProps): JSX.Element; // @public (undocumented) -export type MessageNameContainerProps = HTMLAttributes; +export type MessageNameContainerProps = HTMLAttributes & RefAttributes; // @public (undocumented) export type MessageNameProps = HTMLAttributes; // @public (undocumented) -export type MessageProps = AllHTMLAttributes & { +export type MessageProps = AllHTMLAttributes & RefAttributes & { clickable?: boolean; sequential?: boolean; className?: string; @@ -1279,12 +1219,7 @@ export type MessageProps = AllHTMLAttributes & { }; // @public (undocumented) -export const MessageReaction: ForwardRefExoticComponent< { -name?: string; -counter?: number; -mine?: boolean; -children?: ReactNode; -} & HTMLAttributes & RefAttributes>; +export function MessageReaction(input: MessageReactionProps): JSX.Element; // @public (undocumented) export const MessageReactionAction: (input: MessageReactionActionProps) => JSX.Element; @@ -1308,7 +1243,7 @@ export const MessageReactionEmoji: (input: MessageReactionEmojiProps) => JSX.Ele export type MessageReactionEmojiProps = MessageEmojiBaseProps; // @public (undocumented) -export type MessageReactionProps = { +export type MessageReactionProps = RefAttributes & { name?: string; counter?: number; mine?: boolean; @@ -1316,10 +1251,10 @@ export type MessageReactionProps = { } & HTMLAttributes; // @public (undocumented) -export const MessageReactions: ForwardRefExoticComponent>; +export function MessageReactions(props: MessageReactionsProps): JSX.Element; // @public (undocumented) -export type MessageReactionsProps = HTMLAttributes; +export type MessageReactionsProps = HTMLAttributes & RefAttributes; // @public (undocumented) export const MessageRole: (props: MessageRoleProps) => JSX.Element; @@ -1334,7 +1269,7 @@ export const MessageRoles: (props: MessageRolesProps) => JSX.Element; export type MessageRolesProps = HTMLAttributes; // @public (undocumented) -export const MessageStatusIndicator: ForwardRefExoticComponent>; +export function MessageStatusIndicator(props: MessageStatusIndicatorProps): JSX.Element; // @public (undocumented) export const MessageStatusIndicatorItem: (input: MessageStatusIndicatorItemProps) => JSX.Element; @@ -1346,7 +1281,7 @@ export type MessageStatusIndicatorItemProps = { } & Omit, 'is'>; // @public (undocumented) -export type MessageStatusIndicatorProps = AllHTMLAttributes; +export type MessageStatusIndicatorProps = AllHTMLAttributes & RefAttributes; // @public (undocumented) export const MessageStatusIndicatorText: (input: MessageStatusIndicatorTextProps) => JSX.Element; @@ -1420,40 +1355,22 @@ export const MessageTimestamp: (props: MessageTimestampProps) => JSX.Element; export type MessageTimestampProps = HTMLAttributes; // @public (undocumented) -export const MessageToolbar: ForwardRefExoticComponent< { -align?: "start" | "center" | "end"; -stretch?: boolean; -wrap?: boolean; -vertical?: boolean; -small?: boolean; -large?: boolean; -} & HTMLAttributes & RefAttributes>; +export function MessageToolbar(props: MessageToolbarProps): JSX.Element; // @public (undocumented) -export const MessageToolbarItem: ForwardRefExoticComponent< { -icon: Keys | ReactElement; -primary?: boolean; -secondary?: boolean; -info?: boolean; -danger?: boolean; -warning?: boolean; -success?: boolean; -pressed?: boolean; -} & IconButtonSize & BoxProps & RefAttributes>; +export function MessageToolbarItem(props: MessageToolbarItemProps): JSX.Element; // @public (undocumented) -export type MessageToolbarItemProps = IconButtonProps; +export type MessageToolbarItemProps = Omit & RefAttributes; // @public (undocumented) export type MessageToolbarProps = ButtonGroupProps; // @public (undocumented) -export const MessageToolbarWrapper: ForwardRefExoticComponent & { -visible?: boolean; -} & RefAttributes>; +export function MessageToolbarWrapper(input: MessageToolbarWrapperProps): JSX.Element; // @public (undocumented) -export type MessageToolbarWrapperProps = HTMLAttributes & { +export type MessageToolbarWrapperProps = HTMLAttributes & RefAttributes & { visible?: boolean; }; @@ -1464,10 +1381,7 @@ export const MessageUsername: (props: MessageUsernameProps) => JSX.Element; export type MessageUsernameProps = HTMLAttributes; // @public (undocumented) -export const Modal: ForwardRefExoticComponent< { -wrapperFunction?: (props: Pick) => ReactNode; -wrapper?: ElementType>; -} & BoxProps & RefAttributes>; +export const Modal: (input: ModalProps) => JSX.Element; // @public (undocumented) export const ModalBackdrop: (props: ModalBackdropProps) => JSX.Element; @@ -1536,10 +1450,10 @@ export type ModalIconProps = BoxProps & { }; // @public (undocumented) -export type ModalProps = { +export type ModalProps = Omit & RefAttributes & { wrapperFunction?: (props: Pick) => ReactNode; wrapper?: ElementType>; -} & BoxProps; +}; // @public (undocumented) export const ModalTagline: (input: ModalTaglineProps) => JSX.Element; @@ -1560,26 +1474,7 @@ export const ModalTitle: (input: ModalTitleProps) => JSX.Element; export type ModalTitleProps = BoxProps; // @public (undocumented) -export const MultiSelect: ForwardRefExoticComponent & { -value?: SelectOption[0][]; -error?: string; -options: SelectOption[]; -onChange: (params: SelectOption[0][]) => void; -getLabel?: (params: SelectOption) => SelectOption[1]; -getValue?: (params: SelectOption) => SelectOption[0]; -customEmpty?: string; -anchor?: ElementType | ((params: MultiSelectAnchorParams) => ReactNode); -renderOptions?: ElementType; -renderItem?: ElementType; -renderSelected?: ElementType<{ -value: SelectOption[0]; -label: SelectOption[1]; -onMouseDown: MouseEventHandler; -children: ReactNode; -}>; -addonIcon?: IconProps["name"]; -setFilter?: (filter: string) => void; -} & RefAttributes>; +export function MultiSelect(input: MultiSelectProps): JSX.Element; // @public (undocumented) export type MultiSelectAnchorParams = { @@ -1596,30 +1491,7 @@ export type MultiSelectAnchorParams = { } & AriaAttributes; // @public (undocumented) -export const MultiSelectFiltered: ForwardRefExoticComponent & { -value?: SelectOption[0][]; -error?: string; -options: SelectOption[]; -onChange: (params: SelectOption[0][]) => void; -getLabel?: (params: SelectOption) => SelectOption[1]; -getValue?: (params: SelectOption) => SelectOption[0]; -customEmpty?: string; -anchor?: ElementType | ((params: MultiSelectAnchorParams) => ReactNode); -renderOptions?: ElementType; -renderItem?: ElementType; -renderSelected?: ElementType< { -value: SelectOption[0]; -label: SelectOption[1]; -onMouseDown: MouseEventHandler; -children: ReactNode; -}>; -addonIcon?: IconProps["name"]; -setFilter?: (filter: string) => void; -} & { -filter?: string; -setFilter?: Dispatch>; -addonIcon?: IconProps["name"]; -} & RefAttributes>; +export function MultiSelectFiltered(input: MultiSelectFilteredProps): JSX.Element; // @public (undocumented) export type MultiSelectFilteredProps = MultiSelectProps & { @@ -1629,7 +1501,7 @@ export type MultiSelectFilteredProps = MultiSelectProps & { }; // @public (undocumented) -export type MultiSelectProps = Omit & { +export type MultiSelectProps = Omit & RefAttributes & { value?: SelectOption[0][]; error?: string; options: SelectOption[]; @@ -1660,23 +1532,16 @@ export const NavBarDivider: (props: NavBarDividerProps) => JSX.Element; export type NavBarDividerProps = DividerProps; // @public (undocumented) -export const NavBarGroup: ForwardRefExoticComponent< { -align?: "start" | "center" | "end"; -stretch?: boolean; -wrap?: boolean; -vertical?: boolean; -small?: boolean; -large?: boolean; -} & HTMLAttributes & RefAttributes>; +export function NavBarGroup(props: NavBarGroupProps): JSX.Element; // @public (undocumented) export type NavBarGroupProps = ButtonGroupProps; // @public (undocumented) -export const NavBarItem: ForwardRefExoticComponent & Partial & RefAttributes>; +export function NavBarItem(input: NavbarItemProps): JSX.Element; // @public (undocumented) -export type NavbarItemProps = HTMLAttributes & Partial; +export type NavbarItemProps = HTMLAttributes & Partial> & RefAttributes; // @public (undocumented) export type NavBarProps = HTMLAttributes; @@ -1688,13 +1553,15 @@ export const NavBarSection: (input: NavbarSectionProps) => JSX.Element; export type NavbarSectionProps = HTMLAttributes; // @public (undocumented) -export const NumberInput: ForwardRefExoticComponent>; +export function NumberInput(props: NumberInputProps): JSX.Element; // @public (undocumented) -export type NumberInputProps = Omit; +export type NumberInputProps = Omit, 'type'>; +// Warning: (ae-forgotten-export) The symbol "Option_3" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -const Option_2: NamedExoticComponent & RefAttributes>; +const Option_2: MemoExoticComponent; export { Option_2 as Option } // @public (undocumented) @@ -1722,10 +1589,10 @@ export { OptionColumnProps as MenuItemColumnProps } export { OptionColumnProps } // @public (undocumented) -export const OptionContainer: ForwardRefExoticComponent>; +export function OptionContainer(props: OptionContainerProps): JSX.Element; // @public (undocumented) -export type OptionContainerProps = BoxProps; +export type OptionContainerProps = Omit & RefAttributes; // @public (undocumented) const OptionContent: (props: OptionContentProps) => JSX.Element; @@ -1800,15 +1667,14 @@ export const OptionMenu: (props: OptionMenuProps) => JSX.Element; export type OptionMenuProps = HTMLAttributes; // @public (undocumented) -export type OptionProps = { +export type OptionProps = RefAttributes & { is?: BoxProps['is']; id?: string; children?: ReactNode; - label?: ReactNode; + label?: TLabel; focus?: boolean; selected?: boolean; className?: BoxProps['className']; - ref?: Ref; icon?: IconProps['name']; gap?: boolean; avatar?: ReactNode; @@ -1818,12 +1684,10 @@ export type OptionProps = { variant?: 'danger' | 'success' | 'warning' | 'primary'; onClick?: (event: MouseEvent_2) => void; description?: ReactNode; -} & Omit, 'is' | 'id' | 'children' | 'label' | 'selected' | 'className' | 'ref' | 'icon' | 'gap' | 'avatar' | 'title' | 'disabled' | 'value' | 'variant' | 'onClick' | 'description'>; +} & Omit, 'is' | 'id' | 'children' | 'label' | 'selected' | 'className' | 'ref' | 'icon' | 'gap' | 'avatar' | 'title' | 'disabled' | 'value' | 'variant' | 'onClick' | 'description'> & RefAttributes; // @public (undocumented) -export const Options: ForwardRefExoticComponent & RefAttributes> & { - (props: PropsWithoutRef> & RefAttributes): ReactNode; -}; +export function Options(input: OptionsProps): JSX.Element; // @public (undocumented) const OptionSkeleton: () => JSX.Element; @@ -1831,7 +1695,7 @@ export { OptionSkeleton as MenuItemSkeleton } export { OptionSkeleton } // @public (undocumented) -export type OptionsProps = Omit & { +export type OptionsProps = Omit & RefAttributes & { multiple?: boolean; options: OptionType[]; cursor: number; @@ -1841,6 +1705,8 @@ export type OptionsProps = Omit; renderEmpty?: ComponentType<{ customEmpty?: string; @@ -1867,7 +1733,21 @@ value: TValue, label: TLabel, selected?: boolean, disabled?: boolean, -type?: 'heading' | 'divider' | 'option', +type?: 'option', +url?: string +] | [ +value: TValue, +label: ReactNode, +selected: unknown, +disabled: unknown, +type: 'heading', +url?: string +] | [ +value: TValue, +label: unknown, +selected: unknown, +disabled: unknown, +type: 'divider', url?: string ]; @@ -1943,7 +1823,7 @@ export type PaginatedOptionType = { export const PaginatedSelectFiltered: (input: PaginatedSelectFilteredProps) => JSX.Element; // @public (undocumented) -export type PaginatedSelectFilteredProps = Omit & { +export type PaginatedSelectFilteredProps = Omit & RefAttributes & { setFilter: (value: string | undefined | number) => void; }; @@ -2102,10 +1982,10 @@ export interface PartialNode { } // @public (undocumented) -export const PasswordInput: ForwardRefExoticComponent>; +export function PasswordInput(props: PasswordInputProps): JSX.Element; // @public (undocumented) -export type PasswordInputProps = Omit; +export type PasswordInputProps = Omit, 'type'>; // @public (undocumented) export function Popover(input: PopoverProps): JSX.Element; @@ -2140,16 +2020,10 @@ export type PositionProps = { } & Omit; // @public (undocumented) -export const ProgressBar: ForwardRefExoticComponent< { -percentage: number; -variant?: "info" | "success" | "warning" | "danger"; -error?: string; -animated?: boolean; -light?: boolean; -} & Omit, "is"> & RefAttributes>; +export function ProgressBar(input: ProgressBarProps): JSX.Element; // @public (undocumented) -export type ProgressBarProps = { +export type ProgressBarProps = RefAttributes & { percentage: number; variant?: 'info' | 'success' | 'warning' | 'danger'; error?: string; @@ -2158,12 +2032,10 @@ export type ProgressBarProps = { } & Omit, 'is'>; // @public (undocumented) -export const RadioButton: ForwardRefExoticComponent & { -labelChildren?: ReactNode; -} & RefAttributes>; +export function RadioButton(input: RadioButtonProps): JSX.Element; // @public (undocumented) -export type RadioButtonProps = BoxProps & AllHTMLAttributes & { +export type RadioButtonProps = Omit & RefAttributes & AllHTMLAttributes & { labelChildren?: ReactNode; }; @@ -2181,46 +2053,18 @@ export type ScrollableProps = PropsWithChildren<{ }>; // @public (undocumented) -export const SearchInput: ForwardRefExoticComponent & { -addon?: ReactNode; -error?: string; -} & RefAttributes>; +export function SearchInput(props: SearchInputProps): JSX.Element; // @public (undocumented) -export type SearchInputProps = Omit & { - addon?: ReactNode; - error?: string; -}; +export type SearchInputProps = Omit, 'type'>; + +// Warning: (ae-forgotten-export) The symbol "SelectProps_2" needs to be exported by the entry point index.d.ts +// +// @public (undocumented) +export function Select(input: SelectProps_2): JSX.Element; // @public (undocumented) -export const Select: ForwardRefExoticComponent, "value" | "children" | "onChange"> & { -error?: string; -placeholder?: string; -value?: Key | null | undefined; -onChange?: ((key: Key) => any) | undefined; -options: SelectOption[]; -small?: boolean; -} & Omit, "value" | "onChange"> & RefAttributes>; - -// @public (undocumented) -export const SelectFiltered: ForwardRefExoticComponent & { -anchor?: ElementType; -error?: string; -options: SelectOption[]; -onChange: (value: SelectOption[0]) => void; -getLabel?: (params: SelectOption) => SelectOption[1]; -getValue?: (params: SelectOption) => SelectOption[0]; -filter?: string; -renderOptions?: ElementType; -renderItem?: ElementType; -renderSelected?: ElementType; -customEmpty?: string; -addonIcon?: IconProps["name"]; -} & { -filter?: string; -setFilter?: Dispatch>; -addonIcon?: IconProps["name"]; -} & RefAttributes>; +export function SelectFiltered(input: SelectFilteredProps): JSX.Element; // @public (undocumented) export type SelectFilteredProps = SelectProps & { @@ -2230,45 +2074,19 @@ export type SelectFilteredProps = SelectProps & { }; // @public (undocumented) -export const SelectInput: ForwardRefExoticComponent & { -error?: string; -options?: SelectInputOptions; -htmlSize?: number; -addon?: ReactNode; -} & RefAttributes>; +export function SelectInput(input: SelectInputProps): JSX.Element; // @public (undocumented) -export const SelectInputOption: ForwardRefExoticComponent>; +export function SelectInputOption(props: SelectInputOptionProps): JSX.Element; // @public (undocumented) -export type SelectInputOptionProps = BoxProps; +export type SelectInputOptionProps = Omit & RefAttributes; // @public (undocumented) -export type SelectInputOptions = readonly (readonly [string, string])[]; +export type SelectInputProps = Omit, 'type'>; // @public (undocumented) -export type SelectInputProps = Omit & { - error?: string; - options?: SelectInputOptions; - htmlSize?: number; - addon?: ReactNode; -}; - -// @public (undocumented) -export const SelectLegacy: ForwardRefExoticComponent & { -anchor?: ElementType; -error?: string; -options: SelectOption[]; -onChange: (value: SelectOption[0]) => void; -getLabel?: (params: SelectOption) => SelectOption[1]; -getValue?: (params: SelectOption) => SelectOption[0]; -filter?: string; -renderOptions?: ElementType; -renderItem?: ElementType; -renderSelected?: ElementType; -customEmpty?: string; -addonIcon?: IconProps["name"]; -} & RefAttributes>; +export const SelectLegacy: (input: SelectProps) => JSX.Element; // @public (undocumented) export type SelectOption = readonly [ @@ -2278,7 +2096,7 @@ selected?: boolean ]; // @public (undocumented) -export type SelectProps = Omit & { +export type SelectProps = Omit & RefAttributes & { anchor?: ElementType; error?: string; options: SelectOption[]; @@ -2302,24 +2120,8 @@ export const Sidebar: ((props: SidebarProps) => JSX.Element) & { Avatar: { size: "x24"; }; - Actions: ForwardRefExoticComponent< { - align?: "start" | "center" | "end"; - stretch?: boolean; - wrap?: boolean; - vertical?: boolean; - small?: boolean; - large?: boolean; - } & HTMLAttributes & RefAttributes>; - Action: ForwardRefExoticComponent< { - icon: Keys | ReactElement; - primary?: boolean; - secondary?: boolean; - info?: boolean; - danger?: boolean; - warning?: boolean; - success?: boolean; - pressed?: boolean; - } & IconButtonSize & BoxProps & RefAttributes>; + Actions: TopBarActions; + Action: TopBarAction; Divider: () => JSX.Element; Title: (props: TopBarTitleProps) => JSX.Element; }; @@ -2333,14 +2135,7 @@ export const Sidebar: ((props: SidebarProps) => JSX.Element) & { Wrapper: (input: SidebarItemWrapperProps) => JSX.Element; Icon: (input: SidebarItemIconProps) => JSX.Element; Avatar: (input: SidebarItemAvatarProps) => JSX.Element; - Actions: ForwardRefExoticComponent< { - align?: "start" | "center" | "end"; - stretch?: boolean; - wrap?: boolean; - vertical?: boolean; - small?: boolean; - large?: boolean; - } & HTMLAttributes & RefAttributes>; + Actions: SidebarActions; Action: (props: SidebarItemActionProps) => JSX.Element; Badge: (input: SidebarItemBadgeProps) => JSX.Element; }; @@ -2352,7 +2147,7 @@ export const Sidebar: ((props: SidebarProps) => JSX.Element) & { }; // @public (undocumented) -export type SidebarActionProps = IconButtonProps; +export type SidebarActionProps = Omit & RefAttributes; // @public (undocumented) export const SidebarBanner: (input: SidebarBannerProps) => JSX.Element; @@ -2402,14 +2197,7 @@ export const SidebarItem: ((input: SidebarItemProps) => JSX.Element) & { Wrapper: (input: SidebarItemWrapperProps) => JSX.Element; Icon: (input: SidebarItemIconProps) => JSX.Element; Avatar: (input: SidebarItemAvatarProps) => JSX.Element; - Actions: ForwardRefExoticComponent< { - align?: "start" | "center" | "end"; - stretch?: boolean; - wrap?: boolean; - vertical?: boolean; - small?: boolean; - large?: boolean; - } & HTMLAttributes & RefAttributes>; + Actions: typeof SidebarActions; Action: (props: SidebarItemActionProps) => JSX.Element; Badge: (input: SidebarItemBadgeProps) => JSX.Element; }; @@ -2421,14 +2209,7 @@ export const SidebarItemAction: (props: SidebarItemActionProps) => JSX.Element; export type SidebarItemActionProps = SidebarActionProps; // @public (undocumented) -export const SidebarItemActions: ForwardRefExoticComponent< { -align?: "start" | "center" | "end"; -stretch?: boolean; -wrap?: boolean; -vertical?: boolean; -small?: boolean; -large?: boolean; -} & HTMLAttributes & RefAttributes>; +export const SidebarItemActions: typeof SidebarActions; // @public (undocumented) export const SidebarItemAvatar: (input: SidebarItemAvatarProps) => JSX.Element; @@ -2558,32 +2339,14 @@ export const SidebarTopBar: ((input: TopBarProps) => JSX.Element) & { Avatar: { size: "x24"; }; - Actions: ForwardRefExoticComponent< { - align?: "start" | "center" | "end"; - stretch?: boolean; - wrap?: boolean; - vertical?: boolean; - small?: boolean; - large?: boolean; - } & HTMLAttributes & RefAttributes>; - Action: ForwardRefExoticComponent< { - icon: Keys | ReactElement; - primary?: boolean; - secondary?: boolean; - info?: boolean; - danger?: boolean; - warning?: boolean; - success?: boolean; - pressed?: boolean; - } & IconButtonSize & BoxProps & RefAttributes>; + Actions: typeof TopBarActions; + Action: typeof TopBarAction; Divider: () => JSX.Element; Title: (props: TopBarTitleProps) => JSX.Element; }; // @public (undocumented) -export const SidebarV2: ForwardRefExoticComponent< { -collapsed?: boolean; -} & HTMLAttributes & RefAttributes>; +export function SidebarV2(input: SidebarV2Props): JSX.Element; // @public (undocumented) export const SidebarV2Accordion: (input: SidebarV2AccordionProps) => JSX.Element; @@ -2607,29 +2370,13 @@ export type SidebarV2AccordionItemProps = { export type SidebarV2AccordionProps = HTMLAttributes; // @public (undocumented) -export const SidebarV2Action: ForwardRefExoticComponent< { -icon: Keys | ReactElement; -primary?: boolean; -secondary?: boolean; -info?: boolean; -danger?: boolean; -warning?: boolean; -success?: boolean; -pressed?: boolean; -} & IconButtonSize & BoxProps & RefAttributes>; +export function SidebarV2Action(props: SidebarV2ActionProps): JSX.Element; // @public (undocumented) -export type SidebarV2ActionProps = IconButtonProps; +export type SidebarV2ActionProps = Omit & RefAttributes; // @public (undocumented) -export const SidebarV2Actions: ForwardRefExoticComponent< { -align?: "start" | "center" | "end"; -stretch?: boolean; -wrap?: boolean; -vertical?: boolean; -small?: boolean; -large?: boolean; -} & HTMLAttributes & RefAttributes>; +export function SidebarV2Actions(props: SidebarV2ActionsProps): JSX.Element; // @public (undocumented) export type SidebarV2ActionsProps = ButtonGroupProps; @@ -2655,15 +2402,10 @@ export type SidebarV2BannerVariant = 'default' | 'info' | 'success' | 'warning' // @public (undocumented) export const SidebarV2ButtonGroup: (input: ButtonGroupProps) => JSX.Element; +// Warning: (ae-forgotten-export) The symbol "SidebarCollapseGroupProps" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const SidebarV2CollapseGroup: ForwardRefExoticComponent< { -expanded?: boolean; -defaultExpanded?: boolean; -tabIndex?: number; -title: string; -badge?: ReactNode; -actions?: ReactNode; -} & HTMLAttributes & RefAttributes>; +export function SidebarV2CollapseGroup(input: SidebarCollapseGroupProps): JSX.Element; // @public (undocumented) export const SidebarV2Divider: () => JSX.Element; @@ -2755,10 +2497,10 @@ export type SidebarV2LinkProps = { menu?: ReactNode; } & LinkHTMLAttributes; +// Warning: (ae-forgotten-export) The symbol "SidebarListItemProps" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const SidebarV2ListItem: ForwardRefExoticComponent< { -selected?: boolean; -} & HTMLAttributes & RefAttributes>; +export function SidebarV2ListItem(input: SidebarListItemProps): JSX.Element; // @public (undocumented) export const SidebarV2Media: (input: HTMLAttributes) => JSX.Element; @@ -2772,9 +2514,9 @@ export const SidebarV2MediaController: (input: { export const SidebarV2MediaTitle: (input: HTMLAttributes) => JSX.Element; // @public (undocumented) -export type SidebarV2Props = { +export type SidebarV2Props = HTMLAttributes & RefAttributes & { collapsed?: boolean; -} & HTMLAttributes; +}; // @public (undocumented) export const SidebarV2Section: (props: HTMLAttributes) => JSX.Element; @@ -2798,16 +2540,16 @@ export const SidepanelHeaderTitle: (input: SidepanelHeaderTitleProps) => JSX.Ele export type SidepanelHeaderTitleProps = HTMLAttributes; // @public (undocumented) -export const SidepanelList: ForwardRefExoticComponent>; +export function SidepanelList(input: SidepanelListProps): JSX.Element; // @public (undocumented) -export const SidepanelListItem: ForwardRefExoticComponent>; +export function SidepanelListItem(input: SidepanelListItemProps): JSX.Element; // @public (undocumented) -export type SidepanelListItemProps = HTMLAttributes; +export type SidepanelListItemProps = HTMLAttributes & RefAttributes; // @public (undocumented) -export type SidepanelListProps = HTMLAttributes; +export type SidepanelListProps = HTMLAttributes & RefAttributes; // @public (undocumented) export type SidepanelProps = HTMLAttributes; @@ -2836,10 +2578,10 @@ export type SkeletonProps = Omit & { } & AllHTMLAttributes; // @public (undocumented) -export const Slider: ForwardRefExoticComponent<(SliderProps | SliderProps<[min: number, max: number]>) & RefAttributes>; +export function Slider(input: T extends number ? SliderProps : SliderProps<[min: number, max: number]>): JSX.Element; // @public (undocumented) -export type SliderProps = AriaAttributes & { +export type SliderProps = AriaAttributes & RefAttributes & { formatOptions?: Intl.NumberFormatOptions; id?: string; label?: string; @@ -3165,20 +2907,14 @@ export function Tabs(input: TabsProps): JSX.Element; // @public (undocumented) export namespace Tabs { var // (undocumented) - Item: ForwardRefExoticComponent>; + Item: typeof TabsItem; } // @public (undocumented) -export const TabsItem: ForwardRefExoticComponent>; +export function TabsItem(input: TabsItemProps): JSX.Element; // @public (undocumented) -export type TabsItemProps = BoxProps & { +export type TabsItemProps = Omit & RefAttributes & { selected?: boolean; disabled?: boolean; }; @@ -3201,39 +2937,22 @@ export type TagProps = { } & Omit; // @public (undocumented) -export const TelephoneInput: ForwardRefExoticComponent & { -addon?: ReactNode; -input?: ReactNode; -error?: string; -} & RefAttributes>; +export function TelephoneInput(props: TelephoneInputProps): JSX.Element; // @public (undocumented) -export type TelephoneInputProps = Omit & { - addon?: ReactNode; - input?: ReactNode; - error?: string; -}; +export type TelephoneInputProps = Omit, 'type'>; // @public (undocumented) -export const TextAreaInput: ForwardRefExoticComponent & { -addon?: ReactNode; -error?: string; -} & RefAttributes>; +export function TextAreaInput(props: TextAreaInputProps): JSX.Element; // @public (undocumented) -export type TextAreaInputProps = Omit & { - addon?: ReactNode; - error?: string; -}; +export type TextAreaInputProps = Omit, 'type'>; // @public (undocumented) -export const TextInput: ForwardRefExoticComponent & { -addon?: ReactNode; -error?: string; -} & RefAttributes>; +export function TextInput(props: TextInputProps): JSX.Element; // @public (undocumented) -export type TextInputProps = Omit & { +export type TextInputProps = Omit & RefAttributes & { addon?: ReactNode; error?: string; }; @@ -3300,24 +3019,20 @@ export type ThreadMessageRowProps = HTMLAttributes; export const ThreadMessageUnfollow: () => JSX.Element; // @public (undocumented) -export const Throbber: ForwardRefExoticComponent & { -circleCount?: number; -disabled?: boolean; -inheritColor?: boolean; -} & RefAttributes>; +export function Throbber(input: ThrobberProps): JSX.Element; // @public (undocumented) -export type ThrobberProps = Omit & { +export type ThrobberProps = Omit & RefAttributes & { circleCount?: number; disabled?: boolean; inheritColor?: boolean; }; // @public (undocumented) -export const Tile: ForwardRefExoticComponent>; +export function Tile(input: TileProps): JSX.Element; // @public (undocumented) -export type TileProps = BoxProps; +export type TileProps = Omit & RefAttributes; // @public (undocumented) export function ToastBar(input: ToastBarProps): JSX.Element; @@ -3335,23 +3050,18 @@ export type ToastBarProps = { } & Omit, 'is'>; // @public (undocumented) -export const ToggleSwitch: ForwardRefExoticComponent & { -labelChildren?: ReactNode; -} & RefAttributes>; +export function ToggleSwitch(input: ToggleSwitchProps): JSX.Element; // @public (undocumented) -export type ToggleSwitchProps = BoxProps & AllHTMLAttributes & { +export type ToggleSwitchProps = Omit & RefAttributes & AllHTMLAttributes & { labelChildren?: ReactNode; }; // @public (undocumented) -export const Tooltip: ForwardRefExoticComponent>; +export function Tooltip(input: TooltipProps): JSX.Element; // @public (undocumented) -export type TooltipProps = BoxProps & { +export type TooltipProps = Omit & RefAttributes & { variation?: 'dark' | 'light'; placement?: 'top-start' | 'top-middle' | 'top-end' | 'bottom-start' | 'bottom-middle' | 'bottom-end' | 'top' | 'left' | 'bottom' | 'right' | null; }; @@ -3359,27 +3069,15 @@ export type TooltipProps = BoxProps & { // @public (undocumented) export const TopBar: (input: TopBarProps) => JSX.Element; +// Warning: (ae-forgotten-export) The symbol "TopBarActionProps" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const TopBarAction: ForwardRefExoticComponent< { -icon: Keys | ReactElement; -primary?: boolean; -secondary?: boolean; -info?: boolean; -danger?: boolean; -warning?: boolean; -success?: boolean; -pressed?: boolean; -} & IconButtonSize & BoxProps & RefAttributes>; +export function TopBarAction(props: TopBarActionProps): JSX.Element; +// Warning: (ae-forgotten-export) The symbol "TopBarActionsProps" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const TopBarActions: ForwardRefExoticComponent< { -align?: "start" | "center" | "end"; -stretch?: boolean; -wrap?: boolean; -vertical?: boolean; -small?: boolean; -large?: boolean; -} & HTMLAttributes & RefAttributes>; +export function TopBarActions(props: TopBarActionsProps): JSX.Element; // @public (undocumented) export const TopBarAvatar: { @@ -3436,10 +3134,10 @@ export type TopBarWrapperProps = { }; // @public (undocumented) -export const UrlInput: ForwardRefExoticComponent>; +export function UrlInput(props: UrlInputProps): JSX.Element; // @public (undocumented) -export type UrlInputProps = Omit; +export type UrlInputProps = Omit, 'type'>; // @public (undocumented) export const useArrayLikeClassNameProp: void // @public (undocumented) export type VisibilityType = 'hidden' | 'visible' | 'hiding' | 'unhiding' | undefined; +// Warnings were encountered during analysis: +// +// src/components/Sidebar/Sidebar.tsx:12:23 - (ae-forgotten-export) The symbol "SidebarActions" needs to be exported by the entry point index.d.ts + // (No @packageDocumentation comment for this package) ``` diff --git a/packages/fuselage/src/components/AudioPlayer/AudioPlayer.tsx b/packages/fuselage/src/components/AudioPlayer/AudioPlayer.tsx index 043a8be046..94295ddb24 100644 --- a/packages/fuselage/src/components/AudioPlayer/AudioPlayer.tsx +++ b/packages/fuselage/src/components/AudioPlayer/AudioPlayer.tsx @@ -1,6 +1,6 @@ import { useMergedRefs, useResizeObserver } from '@rocket.chat/fuselage-hooks'; -import type { TrackHTMLAttributes } from 'react'; -import { useState, useRef, forwardRef } from 'react'; +import type { RefAttributes, TrackHTMLAttributes } from 'react'; +import { useState, useRef } from 'react'; import { Box } from '../..'; import { useOwnerDocument } from '../../contexts'; @@ -59,7 +59,7 @@ const getDurationForInfinityDurationAudioFile = ( /** * A Fuselage’s custom AudioPlayer. */ -export type AudioPlayerProps = { +export type AudioPlayerProps = RefAttributes & { src: string; type?: string; maxPlaybackSpeed?: number; @@ -74,139 +74,135 @@ export type AudioPlayerProps = { trackProps?: TrackHTMLAttributes; }; -const AudioPlayer = forwardRef( - ( - { - src, - type = 'audio/mpeg', - maxPlaybackSpeed = 2, - minPlaybackSpeed = 0.5, - playbackSpeedStep = 0.25, - download = false, - playLabel = 'Play', - pauseLabel = 'Pause', - audioPlaybackRangeLabel = 'Audio Playback Range', - changePlaybackSpeedLabel = 'Change Playback Speed', - downloadAudioFileLabel = 'Download Audio File', - trackProps, - }, - ref, - ) => { - const audioRef = useRef(null); - const refs = useMergedRefs(ref, audioRef); - const [isPlaying, setIsPlaying] = useState(false); - const [currentTime, setCurrentTime] = useState(0); - const [durationTime, setDurationTime] = useState(0); - const [playbackSpeed, setPlaybackSpeed] = useState(1); - const { ref: containerRef } = useResizeObserver(); - - const handlePlay = () => { - const isPlaying = audioRef.current?.paused; - - if (isPlaying) { - audioRef.current?.play(); - } else { - audioRef.current?.pause(); - } - }; - - const handlePlaybackSpeed = (mod: 1 | -1) => { - if (audioRef.current) { - audioRef.current.playbackRate += playbackSpeedStep * mod; - } - }; - - const handlePlaybackSpeedSingleControl = () => { - if (!audioRef.current) return; - - const reachedMaxPlaybackSpeed = - maxPlaybackSpeed === audioRef?.current?.playbackRate; - - if (reachedMaxPlaybackSpeed) { - audioRef.current.playbackRate = minPlaybackSpeed; - return; - } - handlePlaybackSpeed(1); - }; - - const { document: ownerDocument } = useOwnerDocument(); - - return ( - { + const audioRef = useRef(null); + const refs = useMergedRefs(ref, audioRef); + const [isPlaying, setIsPlaying] = useState(false); + const [currentTime, setCurrentTime] = useState(0); + const [durationTime, setDurationTime] = useState(0); + const [playbackSpeed, setPlaybackSpeed] = useState(1); + const { ref: containerRef } = useResizeObserver(); + + const handlePlay = () => { + const isPlaying = audioRef.current?.paused; + + if (isPlaying) { + audioRef.current?.play(); + } else { + audioRef.current?.pause(); + } + }; + + const handlePlaybackSpeed = (mod: 1 | -1) => { + if (audioRef.current) { + audioRef.current.playbackRate += playbackSpeedStep * mod; + } + }; + + const handlePlaybackSpeedSingleControl = () => { + if (!audioRef.current) return; + + const reachedMaxPlaybackSpeed = + maxPlaybackSpeed === audioRef?.current?.playbackRate; + + if (reachedMaxPlaybackSpeed) { + audioRef.current.playbackRate = minPlaybackSpeed; + return; + } + handlePlaybackSpeed(1); + }; + + const { document: ownerDocument } = useOwnerDocument(); + + return ( + + { + if (audioRef.current) { + audioRef.current.currentTime = time; + } + }} + onChangePlaybackSpeed={handlePlaybackSpeedSingleControl} + download={download} + downloadHref={src} + onDownload={(e) => { + const { host } = new URL(src); + if (host !== ownerDocument.defaultView?.location.host) { + e.preventDefault(); + forceDownload(ownerDocument, src); + } + }} + playLabel={playLabel} + pauseLabel={pauseLabel} + audioPlaybackRangeLabel={audioPlaybackRangeLabel} + changePlaybackSpeedLabel={changePlaybackSpeedLabel} + downloadAudioFileLabel={downloadAudioFileLabel} + /> + - ); - }, -); + + + + + ); +}; export default AudioPlayer; diff --git a/packages/fuselage/src/components/AutoComplete/AutoComplete.tsx b/packages/fuselage/src/components/AutoComplete/AutoComplete.tsx index ba30715631..466d85f990 100644 --- a/packages/fuselage/src/components/AutoComplete/AutoComplete.tsx +++ b/packages/fuselage/src/components/AutoComplete/AutoComplete.tsx @@ -8,13 +8,12 @@ import type { ChangeEvent, ComponentType, FocusEvent, - ForwardRefExoticComponent, MouseEvent, + MouseEventHandler, ReactNode, - Ref, RefAttributes, } from 'react'; -import { useEffect, useRef, useMemo, useState, forwardRef } from 'react'; +import { useEffect, useRef, useMemo, useState } from 'react'; import { AnimatedVisibility } from '../AnimatedVisibility'; import { Box } from '../Box'; @@ -30,6 +29,30 @@ export type AutoCompleteOption = { label: TLabel; }; +const getSelected = ( + value: string | string[] | undefined, + options: AutoCompleteOption[], +) => { + if (!value) { + return []; + } + return typeof value === 'string' + ? options.filter((option) => option.value === value) + : options?.filter((option) => value.includes(option.value)); +}; + +const isSelectedValid = + (value: string | string[] | undefined) => + (selected: AutoCompleteOption) => { + if (!value) { + return false; + } + + return typeof value === 'string' + ? selected.value === value + : value.includes(selected.value); + }; + export type AutoCompleteProps = Omit< AllHTMLAttributes, 'value' | 'onChange' | 'is' @@ -48,6 +71,7 @@ export type AutoCompleteProps = Omit< value: string; selected?: boolean; focus?: boolean; + onMouseDown: MouseEventHandler; }>; renderEmpty?: ComponentType<{ customEmpty?: string; @@ -59,52 +83,26 @@ export type AutoCompleteProps = Omit< value?: string | string[]; } & RefAttributes; -const getSelected = ( - value: string | string[] | undefined, - options: AutoCompleteOption[], -) => { - if (!value) { - return []; - } - return typeof value === 'string' - ? options.filter((option) => option.value === value) - : options?.filter((option) => value.includes(option.value)); -}; - -const isSelectedValid = - (value: string | string[] | undefined) => - (selected: AutoCompleteOption) => { - if (!value) { - return false; - } - - return typeof value === 'string' - ? selected.value === value - : value.includes(selected.value); - }; - /** * An input for selection of options. */ -const AutoComplete = forwardRef(function AutoComplete( - { - value, - filter, - setFilter, - options = [], - renderItem, - renderSelected: RenderSelected, - onChange, - renderEmpty, - placeholder, - error, - disabled, - multiple, - onBlur: onBlurAction = () => {}, - ...props - }: AutoCompleteProps, - ref: Ref, -) { +function AutoComplete({ + ref, + value, + filter, + setFilter, + options = [], + renderItem, + renderSelected: RenderSelected, + onChange, + renderEmpty, + placeholder, + error, + disabled, + multiple, + onBlur: onBlurAction = () => {}, + ...props +}: AutoCompleteProps) { const innerRef = useRef(null); const mergedRefs = useMergedRefs(ref, innerRef); const { ref: containerRef, borderBoxSize } = useResizeObserver(); @@ -268,13 +266,6 @@ const AutoComplete = forwardRef(function AutoComplete( ); -}) as Pick< - ForwardRefExoticComponent, - keyof ForwardRefExoticComponent -> & { - ( - props: AutoCompleteProps & RefAttributes, - ): ReactNode; -}; +} export default AutoComplete; diff --git a/packages/fuselage/src/components/Box/Box.tsx b/packages/fuselage/src/components/Box/Box.tsx index 2c42d267a9..4a162b0100 100644 --- a/packages/fuselage/src/components/Box/Box.tsx +++ b/packages/fuselage/src/components/Box/Box.tsx @@ -5,7 +5,7 @@ import type { RefAttributes, SVGAttributes, } from 'react'; -import { createElement, forwardRef, memo } from 'react'; +import { createElement, memo } from 'react'; import { useArrayLikeClassNameProp } from '../../hooks/useArrayLikeClassNameProp'; import { useBoxOnlyProps } from '../../hooks/useBoxOnlyProps'; @@ -24,7 +24,8 @@ export interface BoxProps Omit< SVGAttributes, keyof AllHTMLAttributes | 'elevation' | keyof StylingProps - > { + >, + RefAttributes { /** * The `is` prop is used to render the Box as a different HTML tag. It can also be used to render a different fuselage component. */ @@ -36,17 +37,8 @@ export interface BoxProps focusable?: boolean; } -export const Box = forwardRef(function Box( - { is = 'div', children, ...props }, - ref, -) { - const propsWithRef: BoxProps & RefAttributes = props; - - if (ref) { - propsWithRef.ref = ref; - } - - let propsWithStringClassName = useArrayLikeClassNameProp(propsWithRef); +function Box({ is = 'div', ...props }: BoxProps) { + let propsWithStringClassName = useArrayLikeClassNameProp(props); const transformFn = useBoxTransform(); if (transformFn) { @@ -56,13 +48,13 @@ export const Box = forwardRef(function Box( const propsWithoutStylingProps = useStylingProps(propsWithStringClassName); const propsWithoutBoxOnlyProps = useBoxOnlyProps(propsWithoutStylingProps); - const element = createElement(is, propsWithoutBoxOnlyProps, children); + const element = createElement(is, propsWithoutBoxOnlyProps); if (transformFn) { return ; } return element; -}); +} export default memo(Box); diff --git a/packages/fuselage/src/components/Button/ActionButton.tsx b/packages/fuselage/src/components/Button/ActionButton.tsx index be95ae9877..8d8fb9aaff 100644 --- a/packages/fuselage/src/components/Button/ActionButton.tsx +++ b/packages/fuselage/src/components/Button/ActionButton.tsx @@ -1,5 +1,3 @@ -import { forwardRef } from 'react'; - import { Icon, type IconProps } from '../Icon'; import { Button } from '.'; @@ -26,13 +24,13 @@ const getSize = ({ tiny, mini, small }: ActionButtonSize) => { return 'x20'; }; -const ActionButton = forwardRef( - ({ icon, children, ...props }, ref) => ( - - ), -); + ); +} export default ActionButton; diff --git a/packages/fuselage/src/components/Button/Button.tsx b/packages/fuselage/src/components/Button/Button.tsx index 37853eb4ee..9f56c6b48b 100644 --- a/packages/fuselage/src/components/Button/Button.tsx +++ b/packages/fuselage/src/components/Button/Button.tsx @@ -1,10 +1,10 @@ -import type { AllHTMLAttributes } from 'react'; -import { forwardRef, useMemo } from 'react'; +import type { AllHTMLAttributes, RefAttributes } from 'react'; +import { useMemo } from 'react'; import { Box, type BoxProps } from '../Box'; import { Icon, type IconProps } from '../Icon'; -export type ButtonProps = BoxProps & { +export type ButtonProps = Omit & { primary?: boolean; secondary?: boolean; danger?: boolean; @@ -23,95 +23,92 @@ export type ButtonProps = BoxProps & { } & Omit< AllHTMLAttributes, 'is' | 'className' | 'size' - >; + > & + RefAttributes; /** * Indicates an actionable user action. */ -const Button = forwardRef( - function Button( - { - primary, - secondary, - danger, - warning, - success, - external, - icon, - is = 'button', - rel: _rel, - tiny, - mini, - small, - medium, - large, - square, - loading, - disabled, - children, - ...props - }, - ref, - ) { - const extraProps = - (is === 'a' && { - rel: external ? 'noopener noreferrer' : undefined, - target: external ? '_blank' : undefined, - }) || - (is === 'button' && { - type: 'button', - }) || - {}; +function Button({ + ref, + primary, + secondary, + danger, + warning, + success, + external, + icon, + is = 'button', + rel: _rel, + tiny, + mini, + small, + medium, + large, + square, + loading, + disabled, + children, + ...props +}: ButtonProps) { + const extraProps = + (is === 'a' && { + rel: external ? 'noopener noreferrer' : undefined, + target: external ? '_blank' : undefined, + }) || + (is === 'button' && { + type: 'button', + }) || + {}; - const kindAndVariantProps = useMemo(() => { - const variant = - (primary && 'primary') || - (secondary && success && 'secondary-success') || - (secondary && warning && 'secondary-warning') || - (secondary && danger && 'secondary-danger') || - (success && 'success') || - (warning && 'warning') || - (danger && 'danger') || - (secondary && 'secondary'); + const kindAndVariantProps = useMemo(() => { + const variant = + (primary && 'primary') || + (secondary && success && 'secondary-success') || + (secondary && warning && 'secondary-warning') || + (secondary && danger && 'secondary-danger') || + (success && 'success') || + (warning && 'warning') || + (danger && 'danger') || + (secondary && 'secondary'); - if (variant) { - return { - [`rcx-button--${[variant].filter(Boolean).join('-')}`]: true, - }; - } + if (variant) { + return { + [`rcx-button--${[variant].filter(Boolean).join('-')}`]: true, + }; + } - return {}; - }, [primary, secondary, danger, warning, success]); + return {}; + }, [primary, secondary, danger, warning, success]); - return ( - - - {icon && !loading && } - {loading && } - {children} - - - ); - }, -); + return ( + + + {icon && !loading && } + {loading && } + {children} + + + ); +} export default Button; diff --git a/packages/fuselage/src/components/Button/IconButton.tsx b/packages/fuselage/src/components/Button/IconButton.tsx index dc2bb0aa27..fcd03f9239 100644 --- a/packages/fuselage/src/components/Button/IconButton.tsx +++ b/packages/fuselage/src/components/Button/IconButton.tsx @@ -1,6 +1,6 @@ import type { Keys as IconName } from '@rocket.chat/icons'; import type { ReactElement } from 'react'; -import { isValidElement, useMemo, forwardRef } from 'react'; +import { isValidElement, useMemo } from 'react'; import { Box, type BoxProps } from '../Box'; import { Icon } from '../Icon'; @@ -42,97 +42,91 @@ const getPressedClass = (variant: string) => { return variantClass; }; -const IconButton = forwardRef( - ( - { - icon, - primary, - info, - secondary, - danger, - warning, - success, - mini, - large, - tiny, - small, - medium, - pressed, - children, - ...props - }, - ref, - ) => { - const variant = useMemo( - () => - (secondary && danger && 'secondary-danger') || - (secondary && warning && 'secondary-warning') || - (secondary && success && 'secondary-success') || - (secondary && info && 'secondary-info') || - (info && 'info') || - (success && 'success') || - (warning && 'warning') || - (danger && 'danger') || - (primary && 'secondary-info') || - (secondary && 'secondary') || - '', - [danger, info, primary, secondary, success, warning], - ); +function IconButton({ + icon, + primary, + info, + secondary, + danger, + warning, + success, + mini, + large, + tiny, + small, + medium, + pressed, + children, + ...props +}: IconButtonProps) { + const variant = useMemo( + () => + (secondary && danger && 'secondary-danger') || + (secondary && warning && 'secondary-warning') || + (secondary && success && 'secondary-success') || + (secondary && info && 'secondary-info') || + (info && 'info') || + (success && 'success') || + (warning && 'warning') || + (danger && 'danger') || + (primary && 'secondary-info') || + (secondary && 'secondary') || + '', + [danger, info, primary, secondary, success, warning], + ); - const kindAndVariantProps = useMemo(() => { - const variantProp = {} as any; - if (variant) { - variantProp[`${getVariantClass(variant)}`] = true; - } - if (pressed) { - variantProp[`${getPressedClass(variant)}`] = true; - } - return variantProp; - }, [variant, pressed]); + const kindAndVariantProps = useMemo(() => { + const variantProp = {} as any; + if (variant) { + variantProp[`${getVariantClass(variant)}`] = true; + } + if (pressed) { + variantProp[`${getPressedClass(variant)}`] = true; + } + return variantProp; + }, [variant, pressed]); - const size = useMemo( - () => - (mini && 'mini') || - (tiny && 'tiny') || - (small && 'small') || - (medium && 'medium') || - (large && 'large') || - 'large', - [medium, mini, small, tiny, large], - ); + const size = useMemo( + () => + (mini && 'mini') || + (tiny && 'tiny') || + (small && 'small') || + (medium && 'medium') || + (large && 'large') || + 'large', + [medium, mini, small, tiny, large], + ); - const getSizeClass = () => ({ [`rcx-button--${size}-square`]: true }); + const getSizeClass = () => ({ [`rcx-button--${size}-square`]: true }); - const getIconSize = () => - (large && 'x28') || - (medium && 'x24') || - (small && 'x20') || - (tiny && 'x16') || - (mini && 'x12') || - 'x28'; + const getIconSize = () => + (large && 'x28') || + (medium && 'x24') || + (small && 'x20') || + (tiny && 'x16') || + (mini && 'x12') || + 'x28'; - return ( - - {isValidElement(icon) ? ( - icon - ) : ( - - )} - {children} - - ); - }, -); + return ( + + {isValidElement(icon) ? ( + icon + ) : ( + + )} + {children} + + ); +} export default IconButton; diff --git a/packages/fuselage/src/components/ButtonGroup/ButtonGroup.tsx b/packages/fuselage/src/components/ButtonGroup/ButtonGroup.tsx index 30ae4bddf3..16a4a3b3b3 100644 --- a/packages/fuselage/src/components/ButtonGroup/ButtonGroup.tsx +++ b/packages/fuselage/src/components/ButtonGroup/ButtonGroup.tsx @@ -1,7 +1,6 @@ -import type { HTMLAttributes } from 'react'; -import { forwardRef } from 'react'; +import type { HTMLAttributes, RefAttributes } from 'react'; -export type ButtonGroupProps = { +export type ButtonGroupProps = RefAttributes & { align?: 'start' | 'center' | 'end'; stretch?: boolean; wrap?: boolean; @@ -13,43 +12,37 @@ export type ButtonGroupProps = { /** * A container for grouping buttons that semantically share a common action context. */ -const ButtonGroup = forwardRef( - function ButtonGroup( - { - align = 'start', - children, - stretch, - vertical, - wrap, - small, - large, - className, - ...props - }, - ref, - ) { - return ( -
- {children} -
- ); - }, -); +function ButtonGroup({ + align = 'start', + children, + stretch, + vertical, + wrap, + small, + large, + className, + ...props +}: ButtonGroupProps) { + return ( +
+ {children} +
+ ); +} export default ButtonGroup; diff --git a/packages/fuselage/src/components/CheckBox/CheckBox.tsx b/packages/fuselage/src/components/CheckBox/CheckBox.tsx index 3e15520ace..dc0f424368 100644 --- a/packages/fuselage/src/components/CheckBox/CheckBox.tsx +++ b/packages/fuselage/src/components/CheckBox/CheckBox.tsx @@ -1,18 +1,28 @@ import { useMergedRefs } from '@rocket.chat/fuselage-hooks'; -import type { AllHTMLAttributes, ChangeEvent, ReactNode } from 'react'; -import { forwardRef, useLayoutEffect, useRef, useCallback } from 'react'; +import type { + AllHTMLAttributes, + ChangeEvent, + ReactNode, + RefAttributes, +} from 'react'; +import { useLayoutEffect, useRef, useCallback } from 'react'; import { Box, type BoxProps } from '../Box'; -export type CheckBoxProps = BoxProps & { - indeterminate?: boolean; - labelChildren?: ReactNode; -} & AllHTMLAttributes; +export type CheckBoxProps = Omit & + RefAttributes & { + indeterminate?: boolean; + labelChildren?: ReactNode; + } & AllHTMLAttributes; -const CheckBox = forwardRef(function CheckBox( - { indeterminate, onChange, className, labelChildren, ...props }, +function CheckBox({ ref, -) { + indeterminate, + onChange, + className, + labelChildren, + ...props +}: CheckBoxProps) { const innerRef = useRef(null); const mergedRef = useMergedRefs(ref, innerRef); @@ -46,6 +56,6 @@ const CheckBox = forwardRef(function CheckBox( ); -}); +} export default CheckBox; diff --git a/packages/fuselage/src/components/Contextualbar/Contextualbar.stories.tsx b/packages/fuselage/src/components/Contextualbar/Contextualbar.stories.tsx index d037442090..c6f9ac1469 100644 --- a/packages/fuselage/src/components/Contextualbar/Contextualbar.stories.tsx +++ b/packages/fuselage/src/components/Contextualbar/Contextualbar.stories.tsx @@ -74,7 +74,7 @@ export const Default: StoryFn = () => ( } + endAddon={} /> diff --git a/packages/fuselage/src/components/Contextualbar/Contextualbar.tsx b/packages/fuselage/src/components/Contextualbar/Contextualbar.tsx index 350010d3a1..9a3f4169e7 100644 --- a/packages/fuselage/src/components/Contextualbar/Contextualbar.tsx +++ b/packages/fuselage/src/components/Contextualbar/Contextualbar.tsx @@ -1,42 +1,41 @@ -import { forwardRef, memo } from 'react'; +import type { RefAttributes } from 'react'; +import { memo } from 'react'; import { Box } from '..'; import type { BoxProps } from '../Box'; -export type ContextualbarProps = BoxProps; +export type ContextualbarProps = Omit & + RefAttributes; /** * The `Contextualbar` has the purpose to persist and input information about the scope of the related page. */ -const Contextualbar = forwardRef( - function Contextualbar( - { children, width, position, bg = 'room', ...props }, - ref, - ) { - return ( - - {children} - - ); - }, -); +function Contextualbar({ + width, + position, + bg = 'room', + ...props +}: ContextualbarProps) { + return ( + + ); +} export default memo(Contextualbar); diff --git a/packages/fuselage/src/components/Contextualbar/ContextualbarContent.tsx b/packages/fuselage/src/components/Contextualbar/ContextualbarContent.tsx index 994389ce5f..4d033c86a2 100644 --- a/packages/fuselage/src/components/Contextualbar/ContextualbarContent.tsx +++ b/packages/fuselage/src/components/Contextualbar/ContextualbarContent.tsx @@ -1,24 +1,23 @@ -import { forwardRef, memo } from 'react'; +import type { RefAttributes } from 'react'; +import { memo } from 'react'; import { Box, type BoxProps } from '../Box'; -export type ContextualbarContentProps = BoxProps; +export type ContextualbarContentProps = Omit & + RefAttributes; -const ContextualbarContent = forwardRef( - function ContextualbarContent(props, ref) { - return ( - - ); - }, -); +function ContextualbarContent(props: ContextualbarContentProps) { + return ( + + ); +} export default memo(ContextualbarContent); diff --git a/packages/fuselage/src/components/Contextualbar/ContextualbarEmptyContent.tsx b/packages/fuselage/src/components/Contextualbar/ContextualbarEmptyContent.tsx index 5dfbf53600..d99d69498b 100644 --- a/packages/fuselage/src/components/Contextualbar/ContextualbarEmptyContent.tsx +++ b/packages/fuselage/src/components/Contextualbar/ContextualbarEmptyContent.tsx @@ -1,4 +1,5 @@ -import { forwardRef, memo } from 'react'; +import type { RefAttributes } from 'react'; +import { memo } from 'react'; import type { StatesIconProps } from '..'; import { StatesIcon, States, StatesTitle, StatesSubtitle } from '..'; @@ -6,21 +7,21 @@ import type { BoxProps } from '../Box'; import ContextualbarContent from './ContextualbarContent'; -export type ContextualbarEmptyContentProps = BoxProps & { - icon?: StatesIconProps['name']; - title?: string; - subtitle?: string; -}; +export type ContextualbarEmptyContentProps = Omit & + RefAttributes & { + icon?: StatesIconProps['name']; + title?: string; + subtitle?: string; + }; -const ContextualbarEmptyContent = forwardRef< - HTMLElement, - ContextualbarEmptyContentProps ->(function ContextualbarEmptyContent( - { icon = 'magnifier', title = 'Nothing Found', subtitle, ...props }, - ref, -) { +function ContextualbarEmptyContent({ + icon = 'magnifier', + title = 'Nothing Found', + subtitle, + ...props +}: ContextualbarEmptyContentProps) { return ( - + {title} @@ -28,6 +29,6 @@ const ContextualbarEmptyContent = forwardRef< ); -}); +} export default memo(ContextualbarEmptyContent); diff --git a/packages/fuselage/src/components/Contextualbar/ContextualbarFooter.tsx b/packages/fuselage/src/components/Contextualbar/ContextualbarFooter.tsx index 4669b43551..ff805b309b 100644 --- a/packages/fuselage/src/components/Contextualbar/ContextualbarFooter.tsx +++ b/packages/fuselage/src/components/Contextualbar/ContextualbarFooter.tsx @@ -1,18 +1,14 @@ -import { forwardRef, memo } from 'react'; +import type { RefAttributes } from 'react'; +import { memo } from 'react'; import { Box } from '..'; import type { BoxProps } from '../Box'; -export type ContextualbarFooterProps = BoxProps; +export type ContextualbarFooterProps = Omit & + RefAttributes; -const ContextualbarFooter = forwardRef( - function ContextualbarFooter({ children, ...props }, ref) { - return ( - - {children} - - ); - }, -); +function ContextualbarFooter(props: ContextualbarFooterProps) { + return ; +} export default memo(ContextualbarFooter); diff --git a/packages/fuselage/src/components/Contextualbar/ContextualbarSection.tsx b/packages/fuselage/src/components/Contextualbar/ContextualbarSection.tsx index 4513fe03b9..3208c3ff25 100644 --- a/packages/fuselage/src/components/Contextualbar/ContextualbarSection.tsx +++ b/packages/fuselage/src/components/Contextualbar/ContextualbarSection.tsx @@ -1,26 +1,25 @@ -import { forwardRef, memo } from 'react'; +import type { RefAttributes } from 'react'; +import { memo } from 'react'; import { Box, type BoxProps } from '../Box'; -export type ContextualbarSectionProps = BoxProps; +export type ContextualbarSectionProps = Omit & + RefAttributes; -const ContextualbarSection = forwardRef( - function ContextualbarSection(props, ref) { - return ( - - ); - }, -); +function ContextualbarSection(props: ContextualbarSectionProps) { + return ( + + ); +} export default memo(ContextualbarSection); diff --git a/packages/fuselage/src/components/ContextualbarV2/Contextualbar.stories.tsx b/packages/fuselage/src/components/ContextualbarV2/Contextualbar.stories.tsx index 492c27f4f0..a65119a025 100644 --- a/packages/fuselage/src/components/ContextualbarV2/Contextualbar.stories.tsx +++ b/packages/fuselage/src/components/ContextualbarV2/Contextualbar.stories.tsx @@ -76,7 +76,7 @@ export const Default: StoryFn = () => ( } + endAddon={} /> @@ -152,7 +152,7 @@ export const WithLongTitle: StoryFn = () => ( } + endAddon={} /> diff --git a/packages/fuselage/src/components/ContextualbarV2/Contextualbar.tsx b/packages/fuselage/src/components/ContextualbarV2/Contextualbar.tsx index 99cfd62ca6..2ab3305026 100644 --- a/packages/fuselage/src/components/ContextualbarV2/Contextualbar.tsx +++ b/packages/fuselage/src/components/ContextualbarV2/Contextualbar.tsx @@ -1,41 +1,40 @@ -import { forwardRef, memo } from 'react'; +import type { RefAttributes } from 'react'; +import { memo } from 'react'; import { Box, type BoxProps } from '../Box'; -export type ContextualbarProps = BoxProps; +export type ContextualbarProps = Omit & + RefAttributes; /** * The `Contextualbar` has the purpose to persist and input information about the scope of the related page. */ -const Contextualbar = forwardRef( - function Contextualbar( - { children, width, position, bg = 'room', ...props }, - ref, - ) { - return ( - - {children} - - ); - }, -); +function Contextualbar({ + width, + position, + bg = 'room', + ...props +}: ContextualbarProps) { + return ( + + ); +} export default memo(Contextualbar); diff --git a/packages/fuselage/src/components/ContextualbarV2/ContextualbarContent.tsx b/packages/fuselage/src/components/ContextualbarV2/ContextualbarContent.tsx index 994389ce5f..4d033c86a2 100644 --- a/packages/fuselage/src/components/ContextualbarV2/ContextualbarContent.tsx +++ b/packages/fuselage/src/components/ContextualbarV2/ContextualbarContent.tsx @@ -1,24 +1,23 @@ -import { forwardRef, memo } from 'react'; +import type { RefAttributes } from 'react'; +import { memo } from 'react'; import { Box, type BoxProps } from '../Box'; -export type ContextualbarContentProps = BoxProps; +export type ContextualbarContentProps = Omit & + RefAttributes; -const ContextualbarContent = forwardRef( - function ContextualbarContent(props, ref) { - return ( - - ); - }, -); +function ContextualbarContent(props: ContextualbarContentProps) { + return ( + + ); +} export default memo(ContextualbarContent); diff --git a/packages/fuselage/src/components/ContextualbarV2/ContextualbarEmptyContent.tsx b/packages/fuselage/src/components/ContextualbarV2/ContextualbarEmptyContent.tsx index d0b4124c9d..88d274af67 100644 --- a/packages/fuselage/src/components/ContextualbarV2/ContextualbarEmptyContent.tsx +++ b/packages/fuselage/src/components/ContextualbarV2/ContextualbarEmptyContent.tsx @@ -1,4 +1,4 @@ -import { forwardRef, memo } from 'react'; +import { memo } from 'react'; import { StatesIcon, @@ -17,15 +17,14 @@ export type ContextualbarEmptyContentProps = ContextualbarContentProps & { subtitle?: string; }; -const ContextualbarEmptyContent = forwardRef< - HTMLElement, - ContextualbarEmptyContentProps ->(function ContextualbarEmptyContent( - { icon = 'magnifier', title = 'Nothing Found', subtitle, ...props }, - ref, -) { +function ContextualbarEmptyContent({ + icon = 'magnifier', + title = 'Nothing Found', + subtitle, + ...props +}: ContextualbarEmptyContentProps) { return ( - + {title} @@ -33,6 +32,6 @@ const ContextualbarEmptyContent = forwardRef< ); -}); +} export default memo(ContextualbarEmptyContent); diff --git a/packages/fuselage/src/components/ContextualbarV2/ContextualbarFooter.tsx b/packages/fuselage/src/components/ContextualbarV2/ContextualbarFooter.tsx index 01c2d958eb..3976458d4a 100644 --- a/packages/fuselage/src/components/ContextualbarV2/ContextualbarFooter.tsx +++ b/packages/fuselage/src/components/ContextualbarV2/ContextualbarFooter.tsx @@ -1,17 +1,13 @@ -import { forwardRef, memo } from 'react'; +import type { RefAttributes } from 'react'; +import { memo } from 'react'; import { Box, type BoxProps } from '../Box'; -export type ContextualbarFooterProps = BoxProps; +export type ContextualbarFooterProps = Omit & + RefAttributes; -const ContextualbarFooter = forwardRef( - function ContextualbarFooter({ children, ...props }, ref) { - return ( - - {children} - - ); - }, -); +function ContextualbarFooter(props: ContextualbarFooterProps) { + return ; +} export default memo(ContextualbarFooter); diff --git a/packages/fuselage/src/components/ContextualbarV2/ContextualbarSection.tsx b/packages/fuselage/src/components/ContextualbarV2/ContextualbarSection.tsx index b4aa3c9273..cca19f80eb 100644 --- a/packages/fuselage/src/components/ContextualbarV2/ContextualbarSection.tsx +++ b/packages/fuselage/src/components/ContextualbarV2/ContextualbarSection.tsx @@ -1,25 +1,24 @@ -import { forwardRef, memo } from 'react'; +import type { RefAttributes } from 'react'; +import { memo } from 'react'; import { Box, type BoxProps } from '../Box'; -export type ContextualbarSectionProps = BoxProps; +export type ContextualbarSectionProps = Omit & + RefAttributes; -const ContextualbarSection = forwardRef( - function ContextualbarSection(props, ref) { - return ( - - ); - }, -); +function ContextualbarSection(props: ContextualbarSectionProps) { + return ( + + ); +} export default memo(ContextualbarSection); diff --git a/packages/fuselage/src/components/Dropdown/Dropdown.tsx b/packages/fuselage/src/components/Dropdown/Dropdown.tsx index 7634ff5488..3186e0d599 100644 --- a/packages/fuselage/src/components/Dropdown/Dropdown.tsx +++ b/packages/fuselage/src/components/Dropdown/Dropdown.tsx @@ -1,32 +1,35 @@ import type { UsePositionOptions } from '@rocket.chat/fuselage-hooks'; import { useMediaQuery } from '@rocket.chat/fuselage-hooks'; -import type { ReactNode, RefObject } from 'react'; -import { forwardRef } from 'react'; +import type { ReactNode, RefAttributes, RefObject } from 'react'; import { DropdownDesktopWrapper } from './DropdownDesktopWrapper'; import { DropdownMobile } from './DropdownMobile'; -export type DropdownProps = { - reference: RefObject; - placement?: UsePositionOptions['placement']; - children: ReactNode; -}; +export type DropdownProps = + RefAttributes & { + reference: RefObject; + placement?: UsePositionOptions['placement']; + children: ReactNode; + }; -const Dropdown = forwardRef>( - function Dropdown({ children, reference, placement = 'bottom-start' }, ref) { - const notSmall = useMediaQuery('(min-width: 500px)'); +function Dropdown({ + ref, + children, + reference, + placement = 'bottom-start', +}: DropdownProps) { + const notSmall = useMediaQuery('(min-width: 500px)'); - return notSmall ? ( - - ) : ( - - ); - }, -); + return notSmall ? ( + + ) : ( + + ); +} export default Dropdown; diff --git a/packages/fuselage/src/components/Dropdown/DropdownDesktop.tsx b/packages/fuselage/src/components/Dropdown/DropdownDesktop.tsx index 6c5bc0a12d..8807fe3347 100644 --- a/packages/fuselage/src/components/Dropdown/DropdownDesktop.tsx +++ b/packages/fuselage/src/components/Dropdown/DropdownDesktop.tsx @@ -1,9 +1,8 @@ -import type { CSSProperties, ReactNode } from 'react'; -import { forwardRef } from 'react'; +import type { CSSProperties, ReactNode, RefAttributes } from 'react'; import { Box, Tile } from '..'; -export type DropdownDesktopProps = { +export type DropdownDesktopProps = RefAttributes & { children: ReactNode; maxWidth?: string; maxHeight?: string; @@ -11,25 +10,26 @@ export type DropdownDesktopProps = { style?: CSSProperties; }; -export const DropdownDesktop = forwardRef( - function DropdownDesktop({ children, style, ...props }, ref) { - return ( - - - {style?.visibility === 'hidden' ? null : children} - - - ); - }, -); +export function DropdownDesktop({ + children, + style, + ...props +}: DropdownDesktopProps) { + return ( + + + {style?.visibility === 'hidden' ? null : children} + + + ); +} diff --git a/packages/fuselage/src/components/Dropdown/DropdownDesktopWrapper.tsx b/packages/fuselage/src/components/Dropdown/DropdownDesktopWrapper.tsx index f3e2ff5c4e..dcfb7b5cf2 100644 --- a/packages/fuselage/src/components/Dropdown/DropdownDesktopWrapper.tsx +++ b/packages/fuselage/src/components/Dropdown/DropdownDesktopWrapper.tsx @@ -1,23 +1,22 @@ import type { UsePositionOptions } from '@rocket.chat/fuselage-hooks'; import { usePosition } from '@rocket.chat/fuselage-hooks'; -import type { ReactNode, RefObject } from 'react'; -import { forwardRef } from 'react'; +import type { ReactNode, RefAttributes, RefObject } from 'react'; import { DropdownDesktop } from './DropdownDesktop'; -export type DropdownDesktopWrapperProps = { - reference: RefObject; - placement?: UsePositionOptions['placement']; - children: ReactNode; -}; +export type DropdownDesktopWrapperProps = + RefAttributes & { + reference: RefObject; + placement?: UsePositionOptions['placement']; + children: ReactNode; + }; -export const DropdownDesktopWrapper = forwardRef< - HTMLElement, - DropdownDesktopWrapperProps ->(function DropdownDesktopWrapper( - { children, reference, placement = 'bottom-start', ...props }, +export function DropdownDesktopWrapper({ ref, -) { + reference, + placement = 'bottom-start', + ...props +}: DropdownDesktopWrapperProps) { const { style } = usePosition( reference, ref as RefObject, @@ -26,7 +25,5 @@ export const DropdownDesktopWrapper = forwardRef< }, ); - return ( - - ); -}); + return ; +} diff --git a/packages/fuselage/src/components/Dropdown/DropdownMobile.tsx b/packages/fuselage/src/components/Dropdown/DropdownMobile.tsx index bebcce5ccf..d8322efa57 100644 --- a/packages/fuselage/src/components/Dropdown/DropdownMobile.tsx +++ b/packages/fuselage/src/components/Dropdown/DropdownMobile.tsx @@ -1,35 +1,31 @@ -import type { ReactNode } from 'react'; -import { forwardRef } from 'react'; +import type { ReactNode, RefAttributes } from 'react'; import { Box, Tile } from '..'; -export type DropdownMobileProps = { +export type DropdownMobileProps = RefAttributes & { children: ReactNode; }; -export const DropdownMobile = forwardRef( - function DropdownMobile({ children, ...props }, ref) { - return ( - - - {children} - - - ); - }, -); +export function DropdownMobile({ children, ...props }: DropdownMobileProps) { + return ( + + + {children} + + + ); +} diff --git a/packages/fuselage/src/components/EmailInput/EmailInput.stories.tsx b/packages/fuselage/src/components/EmailInput/EmailInput.stories.tsx index 1bbfdf5f6b..0692cfcc48 100644 --- a/packages/fuselage/src/components/EmailInput/EmailInput.stories.tsx +++ b/packages/fuselage/src/components/EmailInput/EmailInput.stories.tsx @@ -17,7 +17,7 @@ const Template: StoryFn = (args) => ( export const Default: StoryFn = Template.bind({}); export const WithIconAddon: StoryFn = () => ( - } /> + } /> ); export const Invalid: StoryFn = Template.bind({}); @@ -50,7 +50,7 @@ export const States: StoryFn = () => ( 'with placeholder': { placeholder: 'Placeholder' }, 'with value': { value: 'support@rocket.chat' }, 'with icon': { - addon: , + endAddon: , value: 'support@rocket.chat', }, }} @@ -74,7 +74,7 @@ export const States: StoryFn = () => ( 'with placeholder': { placeholder: 'Placeholder' }, 'with value': { value: 'support@rocket.chat' }, 'with icon': { - addon: , + endAddon: , value: 'support@rocket.chat', }, }} diff --git a/packages/fuselage/src/components/EmailInput/EmailInput.tsx b/packages/fuselage/src/components/EmailInput/EmailInput.tsx index 11d2d58886..80f5ce6412 100644 --- a/packages/fuselage/src/components/EmailInput/EmailInput.tsx +++ b/packages/fuselage/src/components/EmailInput/EmailInput.tsx @@ -1,50 +1,12 @@ -import type { ReactNode } from 'react'; -import { forwardRef } from 'react'; - import { InputBox, type InputBoxProps } from '../InputBox'; -export type EmailInputProps = Omit & { - addon?: ReactNode; - error?: string; -}; - -// Import from InputBox once it's converted to tsx -type InputType = - | 'button' - | 'checkbox' - | 'color' - | 'date' - | 'datetime' - | 'datetime-local' - | 'email' - | 'file' - | 'hidden' - | 'image' - | 'month' - | 'number' - | 'password' - | 'radio' - | 'range' - | 'reset' - | 'search' - | 'submit' - | 'tel' - | 'text' - | 'time' - | 'url' - | 'week' - | 'textarea' - | 'select'; - -const type: InputType = 'email'; +export type EmailInputProps = Omit, 'type'>; /** * An input for email addresses. */ -const EmailInput = forwardRef( - function EmailInput(props, ref) { - return ; - }, -); +function EmailInput(props: EmailInputProps) { + return ; +} export default EmailInput; diff --git a/packages/fuselage/src/components/Field/FieldLabel.tsx b/packages/fuselage/src/components/Field/FieldLabel.tsx index fd8caee091..e510b8890e 100644 --- a/packages/fuselage/src/components/Field/FieldLabel.tsx +++ b/packages/fuselage/src/components/Field/FieldLabel.tsx @@ -1,5 +1,3 @@ -import { forwardRef } from 'react'; - import WithErrorWrapper from '../../helpers/WithErrorWrapper'; import type { LabelProps } from '../Label'; import { Label } from '../Label'; @@ -8,23 +6,21 @@ import { FieldContext } from './Field'; export type FieldLabelProps = LabelProps; -const FieldLabel = forwardRef( - function FieldLabel(props, ref) { - const component = diff --git a/packages/fuselage/src/components/Icon/Icon.tsx b/packages/fuselage/src/components/Icon/Icon.tsx index 4c02c9e2f2..00b8b1b67b 100644 --- a/packages/fuselage/src/components/Icon/Icon.tsx +++ b/packages/fuselage/src/components/Icon/Icon.tsx @@ -1,18 +1,16 @@ import type { Keys as IconName } from '@rocket.chat/icons'; import nameToCharacterMapping from '@rocket.chat/icons'; -import { forwardRef } from 'react'; +import type { RefAttributes } from 'react'; import { Box, type BoxProps } from '../Box'; -export type IconProps = Omit & { - name: IconName; - size?: BoxProps['width']; -}; +export type IconProps = Omit & + RefAttributes & { + name: IconName; + size?: BoxProps['width']; + }; -const Icon = forwardRef(function Icon( - { name, size, ...props }, - ref, -) { +function Icon({ name, size, ...props }: IconProps) { return ( (function Icon( children={nameToCharacterMapping[name]} aria-hidden='true' fontSize={size} - ref={ref} {...props} /> ); -}); +} export default Icon; diff --git a/packages/fuselage/src/components/InputBox/Input.tsx b/packages/fuselage/src/components/InputBox/Input.tsx index ae3911082c..f1e482eb70 100644 --- a/packages/fuselage/src/components/InputBox/Input.tsx +++ b/packages/fuselage/src/components/InputBox/Input.tsx @@ -1,13 +1,15 @@ -import { forwardRef } from 'react'; +import type { RefAttributes } from 'react'; import { Box, type BoxProps } from '../Box'; -export type InputProps = BoxProps; +export type InputProps< + T extends HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, +> = Omit & RefAttributes; -const Input = forwardRef( - function Input(props, ref) { - return ; - }, -); +function Input< + T extends HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, +>(props: InputProps) { + return ; +} export default Input; diff --git a/packages/fuselage/src/components/InputBox/InputBox.stories.tsx b/packages/fuselage/src/components/InputBox/InputBox.stories.tsx index e76fa5e97e..ea63b45a27 100644 --- a/packages/fuselage/src/components/InputBox/InputBox.stories.tsx +++ b/packages/fuselage/src/components/InputBox/InputBox.stories.tsx @@ -41,7 +41,7 @@ Time.args = { export const WithAddon: StoryFn = Template.bind({}); WithAddon.args = { - addon: , + endAddon: , }; export const WithStartAddon: StoryFn = Template.bind({}); @@ -83,7 +83,7 @@ export const SmallVariants: StoryFn = () => ( type='text' small placeholder='Search' - addon={} + endAddon={} aria-label='Search' /> diff --git a/packages/fuselage/src/components/InputBox/InputBox.tsx b/packages/fuselage/src/components/InputBox/InputBox.tsx index d26c6e3733..3a2c3c3349 100644 --- a/packages/fuselage/src/components/InputBox/InputBox.tsx +++ b/packages/fuselage/src/components/InputBox/InputBox.tsx @@ -1,6 +1,6 @@ import { useMergedRefs } from '@rocket.chat/fuselage-hooks'; -import type { ChangeEvent, ReactNode } from 'react'; -import { forwardRef, useCallback, useLayoutEffect, useRef } from 'react'; +import type { ChangeEvent, ReactNode, RefAttributes } from 'react'; +import { useCallback, useLayoutEffect, useRef } from 'react'; import type { BoxProps } from '../Box'; import { Icon } from '../Icon'; @@ -9,44 +9,47 @@ import Input from './Input'; import InputBoxAddon from './InputBoxAddon'; import InputBoxWrapper from './InputBoxWrapper'; -export type InputBoxProps = BoxProps & { - /** @deprecated Prefer using `startAddon` and `endAddon` instead. */ - addon?: ReactNode; - startAddon?: ReactNode; - endAddon?: ReactNode; - input?: ReactNode; - multiple?: boolean; - error?: string; - placeholder?: string; - placeholderVisible?: boolean; - small?: boolean; - type: - | 'button' - | 'checkbox' - | 'color' - | 'date' - | 'datetime' - | 'datetime-local' - | 'email' - | 'file' - | 'hidden' - | 'image' - | 'month' - | 'number' - | 'password' - | 'radio' - | 'range' - | 'reset' - | 'search' - | 'submit' - | 'tel' - | 'text' - | 'time' - | 'url' - | 'week' - | 'textarea' - | 'select'; -}; +export type InputBoxProps< + T extends HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement = any, +> = Omit & + RefAttributes & { + /** @deprecated Prefer using `startAddon` and `endAddon` instead. */ + addon?: ReactNode; + startAddon?: ReactNode; + endAddon?: ReactNode; + input?: ReactNode; + multiple?: boolean; + error?: string; + placeholder?: string; + placeholderVisible?: boolean; + small?: boolean; + type: + | 'button' + | 'checkbox' + | 'color' + | 'date' + | 'datetime' + | 'datetime-local' + | 'email' + | 'file' + | 'hidden' + | 'image' + | 'month' + | 'number' + | 'password' + | 'radio' + | 'range' + | 'reset' + | 'search' + | 'submit' + | 'tel' + | 'text' + | 'time' + | 'url' + | 'week' + | 'textarea' + | 'select'; + }; /** * A decorated input control with support for addons. @@ -55,27 +58,25 @@ export type InputBoxProps = BoxProps & { * components over this one because it works as a construction block for them. */ // eslint-disable-next-line complexity -const InputBox = forwardRef(function InputBox( - { - className, - addon, - startAddon, - endAddon, - error, - hidden, - invisible, - multiple, - placeholderVisible, - type = 'text', - small, - onChange, - ...props - }, +function InputBox< + T extends HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, +>({ ref, -) { - const innerRef = useRef< - HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement - >(null); + className, + addon, + startAddon, + endAddon, + error, + hidden, + invisible, + multiple, + placeholderVisible, + type = 'text', + small, + onChange, + ...props +}: InputBoxProps) { + const innerRef = useRef(null); const mergedRef = useMergedRefs(ref, innerRef); let defaultAddon = endAddon ?? addon; @@ -183,6 +184,6 @@ const InputBox = forwardRef(function InputBox( {defaultAddon && } ); -}); +} export default InputBox; diff --git a/packages/fuselage/src/components/InputBox/InputBoxAddon.tsx b/packages/fuselage/src/components/InputBox/InputBoxAddon.tsx index 38815fc51b..11f0bb4abf 100644 --- a/packages/fuselage/src/components/InputBox/InputBoxAddon.tsx +++ b/packages/fuselage/src/components/InputBox/InputBoxAddon.tsx @@ -1,13 +1,15 @@ -import { forwardRef } from 'react'; +import type { RefAttributes } from 'react'; import { Box, type BoxProps } from '../Box'; -export type InputBoxAddonProps = BoxProps; +export type InputBoxAddonProps = Omit & + RefAttributes; -const InputBoxAddon = forwardRef( - function InputBoxAddon(props, ref) { - return ; - }, -); +/** + * An addon for the input box. + */ +function InputBoxAddon(props: InputBoxAddonProps) { + return ; +} export default InputBoxAddon; diff --git a/packages/fuselage/src/components/Label/Label.tsx b/packages/fuselage/src/components/Label/Label.tsx index 21ab4ee306..fb5cc5fa5c 100644 --- a/packages/fuselage/src/components/Label/Label.tsx +++ b/packages/fuselage/src/components/Label/Label.tsx @@ -1,35 +1,26 @@ -import type { ElementType } from 'react'; -import { createContext, forwardRef, useContext } from 'react'; +import type { RefAttributes } from 'react'; +import { createContext, useContext } from 'react'; import { Box, type BoxProps } from '../Box'; const LabelContext = createContext(false); -export type LabelProps = Omit & { - disabled?: boolean; - required?: boolean; - is?: (ElementType & string) | undefined; -}; +export type LabelProps = Omit & + RefAttributes & { + disabled?: boolean; + required?: boolean; + }; /** * A caption for an input component. */ -const Label = forwardRef(function Label( - { disabled, is, required, children, ...props }, - ref, -) { +function Label({ disabled, is, required, children, ...props }: LabelProps) { const isInsideLabel = useContext(LabelContext); const component = is || (isInsideLabel && 'span') || 'label'; return ( - + {children} {required && ( ); -}); +} export default Label; diff --git a/packages/fuselage/src/components/Menu/Menu.stories.tsx b/packages/fuselage/src/components/Menu/Menu.stories.tsx index 7b0ce59a15..004eeb6f62 100644 --- a/packages/fuselage/src/components/Menu/Menu.stories.tsx +++ b/packages/fuselage/src/components/Menu/Menu.stories.tsx @@ -1,6 +1,6 @@ import type { StoryFn, Meta } from '@storybook/react-webpack5'; import type { ReactNode } from 'react'; -import { forwardRef, useState } from 'react'; +import { useState } from 'react'; import { Box } from '../Box'; import type { IconButtonProps } from '../Button'; @@ -426,9 +426,9 @@ export const Sizes = () => ( ); -const CustomButton = forwardRef((props, ref) => ( - -)); +const CustomButton = (props: IconButtonProps) => ( + +); export const WithCustomButton = () => ( diff --git a/packages/fuselage/src/components/Menu/MenuOption.tsx b/packages/fuselage/src/components/Menu/MenuOption.tsx index d0cacccdf7..efceb85b09 100644 --- a/packages/fuselage/src/components/Menu/MenuOption.tsx +++ b/packages/fuselage/src/components/Menu/MenuOption.tsx @@ -1,17 +1,21 @@ -import type { Ref, ReactNode, MouseEvent, AllHTMLAttributes } from 'react'; -import { forwardRef, memo } from 'react'; +import type { + ReactNode, + MouseEvent, + AllHTMLAttributes, + RefAttributes, +} from 'react'; +import { memo } from 'react'; import { prevent } from '../../helpers/prevent'; import type { BoxProps } from '../Box'; -export type MenuOptionProps = { +export type MenuOptionProps = RefAttributes & { is?: BoxProps['is']; id?: string; children?: ReactNode; focus?: boolean; selected?: boolean; className?: BoxProps['className']; - ref?: Ref; title?: string; disabled?: boolean; value?: string; @@ -20,28 +24,24 @@ export type MenuOptionProps = { description?: ReactNode; } & Omit, 'label'>; -const MenuOption = forwardRef(function MenuOption( - { - is: Tag = 'li', - id, - children, - focus, - selected, - className, - title, - disabled, - variant, - onClick, - ...props - }: MenuOptionProps, - ref, -) { +function MenuOption({ + is: Tag = 'li', + id, + children, + focus, + selected, + className, + title, + disabled, + variant, + onClick, + ...props +}: MenuOptionProps) { return ( (function MenuOption( {children} ); -}); +} export default memo(MenuOption); diff --git a/packages/fuselage/src/components/Message/Message.tsx b/packages/fuselage/src/components/Message/Message.tsx index bcd5686351..21d7078a70 100644 --- a/packages/fuselage/src/components/Message/Message.tsx +++ b/packages/fuselage/src/components/Message/Message.tsx @@ -1,34 +1,30 @@ -import type { AllHTMLAttributes } from 'react'; -import { forwardRef } from 'react'; +import type { AllHTMLAttributes, RefAttributes } from 'react'; import { prependClassName } from '../../helpers/prependClassName'; -export type MessageProps = AllHTMLAttributes & { - clickable?: boolean; - sequential?: boolean; - className?: string; - isSelected?: boolean; - isEditing?: boolean; - isPending?: boolean; - highlight?: boolean; -}; +export type MessageProps = AllHTMLAttributes & + RefAttributes & { + clickable?: boolean; + sequential?: boolean; + className?: string; + isSelected?: boolean; + isEditing?: boolean; + isPending?: boolean; + highlight?: boolean; + }; -const Message = forwardRef(function Message( - { - className, - clickable, - sequential, - isSelected, - isEditing, - isPending, - highlight, - ...props - }, - ref, -) { +function Message({ + className, + clickable, + sequential, + isSelected, + isEditing, + isPending, + highlight, + ...props +}: MessageProps) { return (
(function Message( {...props} /> ); -}); +} export default Message; diff --git a/packages/fuselage/src/components/Message/MessageBlock.tsx b/packages/fuselage/src/components/Message/MessageBlock.tsx index efae635176..0b8e8b4f19 100644 --- a/packages/fuselage/src/components/Message/MessageBlock.tsx +++ b/packages/fuselage/src/components/Message/MessageBlock.tsx @@ -1,20 +1,24 @@ -import { forwardRef } from 'react'; +import type { RefAttributes } from 'react'; import { Box, type BoxProps } from '../Box'; -export type MessageBlockProps = { - fixedWidth?: boolean; -} & BoxProps; +export type MessageBlockProps = Omit & + RefAttributes & { + fixedWidth?: boolean; + }; -const MessageBlock = forwardRef( - ({ className: _className, fixedWidth, ...props }, ref) => ( +function MessageBlock({ + className: _className, + fixedWidth, + ...props +}: MessageBlockProps) { + return ( - ), -); + ); +} export default MessageBlock; diff --git a/packages/fuselage/src/components/Message/MessageNameContainer.tsx b/packages/fuselage/src/components/Message/MessageNameContainer.tsx index 6ea5cbb5a0..8411e43d80 100644 --- a/packages/fuselage/src/components/Message/MessageNameContainer.tsx +++ b/packages/fuselage/src/components/Message/MessageNameContainer.tsx @@ -1,19 +1,15 @@ -import type { HTMLAttributes } from 'react'; -import { forwardRef } from 'react'; +import type { HTMLAttributes, RefAttributes } from 'react'; -export type MessageNameContainerProps = HTMLAttributes; +export type MessageNameContainerProps = HTMLAttributes & + RefAttributes; -const MessageNameContainer = forwardRef< - HTMLSpanElement, - MessageNameContainerProps ->(function MessageNameContainer(props, ref) { +function MessageNameContainer(props: MessageNameContainerProps) { return ( ); -}); +} export default MessageNameContainer; diff --git a/packages/fuselage/src/components/Message/MessageReactions/MessageReaction.tsx b/packages/fuselage/src/components/Message/MessageReactions/MessageReaction.tsx index 63c0285ceb..1a00ba9146 100644 --- a/packages/fuselage/src/components/Message/MessageReactions/MessageReaction.tsx +++ b/packages/fuselage/src/components/Message/MessageReactions/MessageReaction.tsx @@ -1,44 +1,44 @@ -import type { HTMLAttributes, ReactNode } from 'react'; -import { forwardRef } from 'react'; +import type { HTMLAttributes, ReactNode, RefAttributes } from 'react'; import MessageReactionCounter from './MessageReactionCounter'; import MessageReactionEmoji from './MessageReactionEmoji'; -export type MessageReactionProps = { +export type MessageReactionProps = RefAttributes & { name?: string; counter?: number; mine?: boolean; children?: ReactNode; } & HTMLAttributes; -const MessageReaction = forwardRef( - function Reaction( - { name, counter, mine, children, className, ...props }, - ref, - ) { - return ( -
- {children || ( - <> - {name && } - {counter && } - - )} -
- ); - }, -); +function MessageReaction({ + name, + counter, + mine, + children, + className, + ...props +}: MessageReactionProps) { + return ( +
+ {children || ( + <> + {name && } + {counter && } + + )} +
+ ); +} export default MessageReaction; diff --git a/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.tsx b/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.tsx index df0fbd5d9d..db725beb3e 100644 --- a/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.tsx +++ b/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.tsx @@ -1,22 +1,16 @@ -import type { HTMLAttributes } from 'react'; -import { forwardRef } from 'react'; +import type { HTMLAttributes, RefAttributes } from 'react'; import MessageBlock from '../MessageBlock'; -export type MessageReactionsProps = HTMLAttributes; +export type MessageReactionsProps = HTMLAttributes & + RefAttributes; -const MessageReactions = forwardRef( - function MessageReactions(props, ref) { - return ( - -
- - ); - }, -); +function MessageReactions(props: MessageReactionsProps) { + return ( + +
+ + ); +} export default MessageReactions; diff --git a/packages/fuselage/src/components/Message/MessageStatusIndicator/MessageStatusIndicator.tsx b/packages/fuselage/src/components/Message/MessageStatusIndicator/MessageStatusIndicator.tsx index 3bd758325d..decdcad716 100644 --- a/packages/fuselage/src/components/Message/MessageStatusIndicator/MessageStatusIndicator.tsx +++ b/packages/fuselage/src/components/Message/MessageStatusIndicator/MessageStatusIndicator.tsx @@ -1,15 +1,12 @@ -import type { AllHTMLAttributes } from 'react'; -import { forwardRef } from 'react'; +import type { AllHTMLAttributes, RefAttributes } from 'react'; import './MessageStatusIndicator.styles.scss'; -export type MessageStatusIndicatorProps = AllHTMLAttributes; +export type MessageStatusIndicatorProps = AllHTMLAttributes & + RefAttributes; -const MessageStatusIndicator = forwardRef< - HTMLDivElement, - MessageStatusIndicatorProps ->(function MessageStatusIndicator(props, ref) { - return
; -}); +function MessageStatusIndicator(props: MessageStatusIndicatorProps) { + return
; +} export default MessageStatusIndicator; diff --git a/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.tsx b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.tsx index cf930a535d..92b99c5d60 100644 --- a/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.tsx +++ b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.tsx @@ -1,17 +1,13 @@ -import { forwardRef } from 'react'; - import { ButtonGroup, type ButtonGroupProps } from '../../ButtonGroup'; export type MessageToolbarProps = ButtonGroupProps; -const MessageToolbar = forwardRef( - function MessageToolbar(props, ref) { - return ( -
- -
- ); - }, -); +function MessageToolbar(props: MessageToolbarProps) { + return ( +
+ +
+ ); +} export default MessageToolbar; diff --git a/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarItem.tsx b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarItem.tsx index a3c9bc2198..e0797754eb 100644 --- a/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarItem.tsx +++ b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarItem.tsx @@ -1,15 +1,13 @@ -import { forwardRef } from 'react'; +import type { RefAttributes } from 'react'; import { IconButton } from '../../Button'; import type { IconButtonProps } from '../../Button/IconButton'; -export type MessageToolbarItemProps = IconButtonProps; +export type MessageToolbarItemProps = Omit & + RefAttributes; -const MessageToolbarItem = forwardRef< - HTMLButtonElement, - MessageToolbarItemProps ->(function MessageToolbarItem(props, ref) { - return ; -}); +function MessageToolbarItem(props: MessageToolbarItemProps) { + return ; +} export default MessageToolbarItem; diff --git a/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarWrapper.tsx b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarWrapper.tsx index ec7a5c1ab5..3a2d6b5d10 100644 --- a/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarWrapper.tsx +++ b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarWrapper.tsx @@ -1,17 +1,17 @@ -import type { HTMLAttributes } from 'react'; -import { forwardRef } from 'react'; +import type { HTMLAttributes, RefAttributes } from 'react'; -export type MessageToolbarWrapperProps = HTMLAttributes & { - visible?: boolean; -}; +export type MessageToolbarWrapperProps = HTMLAttributes & + RefAttributes & { + visible?: boolean; + }; -const MessageToolbarWrapper = forwardRef< - HTMLDivElement, - MessageToolbarWrapperProps ->(function MessageToolbarWrapper({ className, visible, ...props }, ref) { +function MessageToolbarWrapper({ + className, + visible, + ...props +}: MessageToolbarWrapperProps) { return (
); -}); +} export default MessageToolbarWrapper; diff --git a/packages/fuselage/src/components/Modal/Modal.tsx b/packages/fuselage/src/components/Modal/Modal.tsx index 97137fa9e1..3bb25114f4 100644 --- a/packages/fuselage/src/components/Modal/Modal.tsx +++ b/packages/fuselage/src/components/Modal/Modal.tsx @@ -1,31 +1,37 @@ -import type { ElementType, ReactNode } from 'react'; -import { createElement, forwardRef } from 'react'; +import type { ElementType, ReactNode, RefAttributes } from 'react'; +import { createElement } from 'react'; import { Box, type BoxProps } from '../Box'; -export type ModalProps = { - wrapperFunction?: ( - props: Pick, - ) => ReactNode; - wrapper?: ElementType>; -} & BoxProps; +export type ModalProps = Omit & + RefAttributes & { + wrapperFunction?: ( + props: Pick, + ) => ReactNode; + wrapper?: ElementType< + Pick + >; + }; -const Modal = forwardRef( - ({ children, wrapper = Box, wrapperFunction, ...props }, ref) => { - const wrapperProps = { - children, - className: 'rcx-modal__inner', - elevation: '2', - } as const; +const Modal = ({ + children, + wrapper = Box, + wrapperFunction, + ...props +}: ModalProps) => { + const wrapperProps = { + children, + className: 'rcx-modal__inner', + elevation: '2', + } as const; - return ( - - {wrapperFunction - ? wrapperFunction(wrapperProps) - : createElement(wrapper, wrapperProps)} - - ); - }, -); + return ( + + {wrapperFunction + ? wrapperFunction(wrapperProps) + : createElement(wrapper, wrapperProps)} + + ); +}; export default Modal; diff --git a/packages/fuselage/src/components/MultiSelect/MultiSelect.tsx b/packages/fuselage/src/components/MultiSelect/MultiSelect.tsx index aa429d01ca..375fc52d60 100644 --- a/packages/fuselage/src/components/MultiSelect/MultiSelect.tsx +++ b/packages/fuselage/src/components/MultiSelect/MultiSelect.tsx @@ -4,11 +4,15 @@ import { useResizeObserver, useOutsideClick, } from '@rocket.chat/fuselage-hooks'; -import type { ElementType, MouseEventHandler, ReactNode } from 'react'; -import { useState, useRef, useEffect, forwardRef } from 'react'; +import type { + ElementType, + MouseEventHandler, + ReactNode, + RefAttributes, +} from 'react'; +import { useState, useRef, useEffect } from 'react'; import type { IconProps, SelectOption } from '..'; -import { isForwardRefType } from '../../helpers/isForwardRefType'; import { prevent } from '../../helpers/prevent'; import { AnimatedVisibility } from '../AnimatedVisibility'; import { Box, type BoxProps } from '../Box'; @@ -24,257 +28,240 @@ import MultiSelectAnchor from './MultiSelectAnchor'; import type { MultiSelectAnchorParams } from './MultiSelectAnchorParams'; import { SelectedOptions } from './SelectedOptions'; -export type MultiSelectProps = Omit & { - value?: SelectOption[0][]; - error?: string; - options: SelectOption[]; - onChange: (params: SelectOption[0][]) => void; - getLabel?: (params: SelectOption) => SelectOption[1]; - getValue?: (params: SelectOption) => SelectOption[0]; - customEmpty?: string; - anchor?: - | ElementType - | ((params: MultiSelectAnchorParams) => ReactNode); - renderOptions?: ElementType; - renderItem?: ElementType; - renderSelected?: ElementType<{ - value: SelectOption[0]; - label: SelectOption[1]; - onMouseDown: MouseEventHandler; - children: ReactNode; - }>; - addonIcon?: IconProps['name']; - setFilter?: (filter: string) => void; -}; +export type MultiSelectProps = Omit & + RefAttributes & { + value?: SelectOption[0][]; + error?: string; + options: SelectOption[]; + onChange: (params: SelectOption[0][]) => void; + getLabel?: (params: SelectOption) => SelectOption[1]; + getValue?: (params: SelectOption) => SelectOption[0]; + customEmpty?: string; + anchor?: + | ElementType + | ((params: MultiSelectAnchorParams) => ReactNode); + renderOptions?: ElementType; + renderItem?: ElementType; + renderSelected?: ElementType<{ + value: SelectOption[0]; + label: SelectOption[1]; + onMouseDown: MouseEventHandler; + children: ReactNode; + }>; + addonIcon?: IconProps['name']; + setFilter?: (filter: string) => void; + }; /** * An input for selection of options. */ -const MultiSelect = forwardRef( - ( - { - value, - filter, - setFilter, - options = [], - error, - disabled, - anchor: Anchor = MultiSelectAnchor, - onChange = () => {}, - getLabel = ([, label] = ['', '']) => label, - getValue = ([value]) => value, - placeholder, - renderOptions: _Options = Options, - renderItem, - customEmpty, - renderSelected: RenderSelected, - addonIcon, - ...props - }, - ref, - ) => { - const [internalValue, setInternalValue] = useState( - value || [], - ); +function MultiSelect({ + ref, + value, + filter, + setFilter, + options = [], + error, + disabled, + anchor: Anchor = MultiSelectAnchor, + onChange = () => {}, + getLabel = ([, label] = ['', '']) => label, + getValue = ([value]) => value, + placeholder, + renderOptions: _Options = Options, + renderItem, + customEmpty, + renderSelected: RenderSelected, + addonIcon, + ...props +}: MultiSelectProps) { + const [internalValue, setInternalValue] = useState( + value || [], + ); - useEffect((): void => setInternalValue(value || []), [value]); + useEffect((): void => setInternalValue(value || []), [value]); - const [currentOptionValue, setCurrentOption] = useState(); + const [currentOptionValue, setCurrentOption] = useState(); - const index = options.findIndex( - (option) => getValue(option) === currentOptionValue, - ); + const index = options.findIndex( + (option) => getValue(option) === currentOptionValue, + ); - const removeFocusClass = () => - innerRef.current?.classList.remove('focus-visible'); + const removeFocusClass = () => + innerRef.current?.classList.remove('focus-visible'); - const internalChanged = ([value]: SelectOption) => { - if (internalValue.includes(value)) { - setCurrentOption(undefined); - const newValue = internalValue.filter((item) => item !== value); - setInternalValue(newValue); - return onChange(newValue); - } - setFilter?.(''); - setCurrentOption(value); - const newValue = [...internalValue, value]; + const internalChanged = ([value]: SelectOption) => { + if (internalValue.includes(value)) { + setCurrentOption(undefined); + const newValue = internalValue.filter((item) => item !== value); setInternalValue(newValue); return onChange(newValue); - }; + } + setFilter?.(''); + setCurrentOption(value); + const newValue = [...internalValue, value]; + setInternalValue(newValue); + return onChange(newValue); + }; - const mapOptions = ([value, label]: SelectOption): SelectOption => { - if (internalValue.includes(value)) { - return [value, label, true]; - } - return [value, label]; - }; + const mapOptions = ([value, label]: SelectOption): SelectOption => { + if (internalValue.includes(value)) { + return [value, label, true]; + } + return [value, label]; + }; - const applyFilter = ([, option]: SelectOption) => - !filter || option.toLowerCase().includes(filter.toLowerCase()); + const applyFilter = ([, option]: SelectOption) => + !filter || option.toLowerCase().includes(filter.toLowerCase()); - const filteredOptions: SelectOption[] = options - .filter(applyFilter) - .map(mapOptions); + const filteredOptions: SelectOption[] = options + .filter(applyFilter) + .map(mapOptions); - const [cursor, handleKeyDown, handleKeyUp, reset, [visible, hide, show]] = - useCursor(index, filteredOptions, internalChanged); + const [cursor, handleKeyDown, handleKeyUp, reset, [visible, hide, show]] = + useCursor(index, filteredOptions, internalChanged); - useEffect(reset, [filter]); + useEffect(reset, [filter]); - const innerRef = useRef(null); - const anchorRef = useMergedRefs(ref, innerRef); + const innerRef = useRef(null); + const anchorRef = useMergedRefs(ref, innerRef); - const { ref: containerRef, borderBoxSize } = useResizeObserver(); - useOutsideClick([containerRef], removeFocusClass); + const { ref: containerRef, borderBoxSize } = useResizeObserver(); + useOutsideClick([containerRef], removeFocusClass); - const renderAnchor = (params: MultiSelectAnchorParams) => { - if (isForwardRefType(Anchor)) { - return ; - } + const handleClick = useStableCallback(() => { + if (visible === AnimatedVisibility.VISIBLE) { + return hide(); + } + innerRef.current?.focus(); + return show(); + }); - if (typeof Anchor === 'function') { - return (Anchor as (params: MultiSelectAnchorParams) => ReactNode)( - params, - ); - } + const listboxId = props.id ? `${props.id}-listbox` : undefined; - return null; - }; + const { + id, + name, + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledBy, + 'aria-describedby': ariaDescribedBy, + 'aria-invalid': ariaInvalid, + 'aria-required': ariaRequired, + ...containerProps + } = props; - const handleClick = useStableCallback(() => { - if (visible === AnimatedVisibility.VISIBLE) { - return hide(); - } - innerRef.current?.focus(); - return show(); - }); - - const listboxId = props.id ? `${props.id}-listbox` : undefined; - - const { - id, - name, - 'aria-label': ariaLabel, - 'aria-labelledby': ariaLabelledBy, - 'aria-describedby': ariaDescribedBy, - 'aria-invalid': ariaInvalid, - 'aria-required': ariaRequired, - ...containerProps - } = props; - - return ( - - - - - - - - {renderAnchor({ - 'ref': anchorRef, - 'children': - internalValue.length === 0 ? placeholder : null, - 'disabled': disabled ?? false, - 'onClick': show, - 'onBlur': hide, - 'onKeyDown': handleKeyDown, - 'onKeyUp': handleKeyUp, - 'role': 'combobox', - 'aria-expanded': visible === AnimatedVisibility.VISIBLE, - 'aria-haspopup': 'listbox', - 'aria-controls': listboxId, - id, - name, - 'aria-label': ariaLabel, - 'aria-labelledby': ariaLabelledBy, - 'aria-describedby': ariaDescribedBy, - 'aria-invalid': ariaInvalid, - 'aria-required': ariaRequired, - })} - {internalValue.map((value: SelectOption[0]) => { - const currentOption = options.find( - ([val]) => val === value, - ) as SelectOption; - return RenderSelected ? ( - { - prevent(e); - internalChanged(currentOption); - removeFocusClass(); - }} - children={getLabel(currentOption)} - /> - ) : ( - { - prevent(e); - internalChanged(currentOption); - removeFocusClass(); - }} - children={getLabel(currentOption)} - /> - ); - })} - - + return ( + + + + + + + + + {internalValue.length === 0 ? placeholder : null} + + {internalValue.map((value: SelectOption[0]) => { + const currentOption = options.find( + ([val]) => val === value, + ) as SelectOption; + return RenderSelected ? ( + { + prevent(e); + internalChanged(currentOption); + removeFocusClass(); + }} + children={getLabel(currentOption)} + /> + ) : ( + { + prevent(e); + internalChanged(currentOption); + removeFocusClass(); + }} + children={getLabel(currentOption)} + /> + ); + })} + - - - - - - - } - /> - - - - - <_Options - width={borderBoxSize.inlineSize} - onMouseDown={prevent} - multiple - filter={filter} - renderItem={renderItem || CheckOption} - id={listboxId} - options={filteredOptions} - onSelect={internalChanged} - cursor={cursor} - customEmpty={customEmpty} - /> - - - - ); - }, -); + + + + + + + + } + /> + + + + + <_Options + width={borderBoxSize.inlineSize} + onMouseDown={prevent} + multiple + filter={filter} + renderItem={renderItem || CheckOption} + id={listboxId} + options={filteredOptions} + onSelect={internalChanged} + cursor={cursor} + customEmpty={customEmpty} + /> + + + + ); +} export default MultiSelect; diff --git a/packages/fuselage/src/components/MultiSelect/MultiSelectAnchor.tsx b/packages/fuselage/src/components/MultiSelect/MultiSelectAnchor.tsx index ddaab3a2af..1456789226 100644 --- a/packages/fuselage/src/components/MultiSelect/MultiSelectAnchor.tsx +++ b/packages/fuselage/src/components/MultiSelect/MultiSelectAnchor.tsx @@ -4,12 +4,12 @@ import type { KeyboardEventHandler, MouseEventHandler, ReactNode, + RefAttributes, } from 'react'; -import { forwardRef } from 'react'; import SelectFocus from '../Select/SelectFocus'; -type MultiSelectAnchorProps = { +type MultiSelectAnchorProps = RefAttributes & { children: ReactNode; disabled: boolean; onClick: MouseEventHandler; @@ -21,14 +21,8 @@ type MultiSelectAnchorProps = { name?: string; } & AriaAttributes; -const MultiSelectAnchor = forwardRef( - function MultiSelectAnchor({ children, ...props }, ref) { - return ( - - {children} - - ); - }, -); +function MultiSelectAnchor(props: MultiSelectAnchorProps) { + return ; +} export default MultiSelectAnchor; diff --git a/packages/fuselage/src/components/MultiSelect/MultiSelectFiltered.tsx b/packages/fuselage/src/components/MultiSelect/MultiSelectFiltered.tsx index 0784ba141c..7936ee3abf 100644 --- a/packages/fuselage/src/components/MultiSelect/MultiSelectFiltered.tsx +++ b/packages/fuselage/src/components/MultiSelect/MultiSelectFiltered.tsx @@ -1,5 +1,5 @@ import type { Dispatch, SetStateAction } from 'react'; -import { useState, forwardRef } from 'react'; +import { useState } from 'react'; import type { IconProps } from '../Icon'; @@ -14,40 +14,31 @@ export type MultiSelectFilteredProps = MultiSelectProps & { addonIcon?: IconProps['name']; }; -const MultiSelectFiltered = forwardRef< - HTMLInputElement, - MultiSelectFilteredProps ->( - ( - { - options, - placeholder, - filter: propFilter, - setFilter: propSetFilter, - ...props - }, - ref, - ) => { - const [filter, setFilter] = useState(''); +function MultiSelectFiltered({ + options, + placeholder, + filter: propFilter, + setFilter: propSetFilter, + ...props +}: MultiSelectFilteredProps) { + const [filter, setFilter] = useState(''); - return ( - ( - - )} - /> - ); - }, -); + return ( + ( + + )} + /> + ); +} export default MultiSelectFiltered; diff --git a/packages/fuselage/src/components/MultiSelect/MultiSelectFilteredAnchor.tsx b/packages/fuselage/src/components/MultiSelect/MultiSelectFilteredAnchor.tsx index d404d1b9fd..e86923938e 100644 --- a/packages/fuselage/src/components/MultiSelect/MultiSelectFilteredAnchor.tsx +++ b/packages/fuselage/src/components/MultiSelect/MultiSelectFilteredAnchor.tsx @@ -5,13 +5,13 @@ import type { KeyboardEventHandler, MouseEventHandler, ReactNode, + RefAttributes, } from 'react'; -import { forwardRef } from 'react'; import { FlexItem } from '../Flex'; import { Input } from '../InputBox'; -type MultiSelectFilteredAnchorProps = { +type MultiSelectFilteredAnchorProps = RefAttributes & { children: ReactNode; disabled: boolean; filter: string; @@ -26,17 +26,16 @@ type MultiSelectFilteredAnchorProps = { name?: string; } & AriaAttributes; -const MultiSelectFilteredAnchor = forwardRef< - HTMLInputElement, - MultiSelectFilteredAnchorProps ->(function MultiSelectFilteredAnchor( - { children: _children, filter, onChangeFilter, placeholder, ...props }, - ref, -) { +function MultiSelectFilteredAnchor({ + children: _children, + filter, + onChangeFilter, + placeholder, + ...props +}: MultiSelectFilteredAnchorProps) { return ( ) => @@ -49,6 +48,6 @@ const MultiSelectFilteredAnchor = forwardRef< /> ); -}); +} export default MultiSelectFilteredAnchor; diff --git a/packages/fuselage/src/components/NavBar/NavBarGroup.tsx b/packages/fuselage/src/components/NavBar/NavBarGroup.tsx index e9bb9f0e5f..2d91ce600d 100644 --- a/packages/fuselage/src/components/NavBar/NavBarGroup.tsx +++ b/packages/fuselage/src/components/NavBar/NavBarGroup.tsx @@ -1,14 +1,10 @@ -import { forwardRef } from 'react'; - import type { ButtonGroupProps } from '../ButtonGroup'; import { ButtonGroup } from '../ButtonGroup'; export type NavBarGroupProps = ButtonGroupProps; -const NavBarGroup = forwardRef( - (props, ref) => ( - - ), -); +function NavBarGroup(props: NavBarGroupProps) { + return ; +} export default NavBarGroup; diff --git a/packages/fuselage/src/components/NavBar/NavBarItem.tsx b/packages/fuselage/src/components/NavBar/NavBarItem.tsx index 508d3dea59..49da8e19cc 100644 --- a/packages/fuselage/src/components/NavBar/NavBarItem.tsx +++ b/packages/fuselage/src/components/NavBar/NavBarItem.tsx @@ -1,5 +1,4 @@ -import type { HTMLAttributes } from 'react'; -import { forwardRef } from 'react'; +import type { HTMLAttributes, RefAttributes } from 'react'; import { appendClassName } from '../../helpers/appendClassName'; import { patchChildren } from '../../helpers/patchChildren'; @@ -7,28 +6,25 @@ import { IconButton } from '../Button'; import type { IconButtonProps } from '../Button/IconButton'; export type NavbarItemProps = HTMLAttributes & - Partial; + Partial> & + RefAttributes; -const NavBarItem = forwardRef(function NavBarItem( - { children, icon, ...props }, - ref, -) { +function NavBarItem({ children, icon, ...props }: NavbarItemProps) { return ( <> {icon ? ( - + ) : ( patchChildren( children, (childProps: { className: string | string[] }) => ({ className: appendClassName(childProps.className, 'rcx-navbar-item'), - ref, ...props, }), ) )} ); -}); +} export default NavBarItem; diff --git a/packages/fuselage/src/components/NavBar/NavBarSection.tsx b/packages/fuselage/src/components/NavBar/NavBarSection.tsx index 785633261b..6ba7da1aa8 100644 --- a/packages/fuselage/src/components/NavBar/NavBarSection.tsx +++ b/packages/fuselage/src/components/NavBar/NavBarSection.tsx @@ -16,7 +16,7 @@ const isNavBarGroup = ( ): child is ReactElement => { if (!isValidElement(child)) return false; const component = child.type as ComponentWithDisplayName; - return component.displayName === NavBarGroup.displayName; + return component.name === NavBarGroup.name; }; const NavBarSection = ({ children, ...props }: NavbarSectionProps) => { diff --git a/packages/fuselage/src/components/NumberInput/NumberInput.stories.tsx b/packages/fuselage/src/components/NumberInput/NumberInput.stories.tsx index 7b8a5dbfd9..84ae53735c 100644 --- a/packages/fuselage/src/components/NumberInput/NumberInput.stories.tsx +++ b/packages/fuselage/src/components/NumberInput/NumberInput.stories.tsx @@ -18,7 +18,7 @@ export const Default: StoryFn = Template.bind({}); export const WithIconAddon: StoryFn = Template.bind({}); WithIconAddon.args = { - addon: , + endAddon: , }; export const Invalid: StoryFn = Template.bind({}); @@ -44,7 +44,7 @@ export const States: StoryFn = () => ( 'with placeholder': { placeholder: 'Placeholder' }, 'with value': { value: 1024 }, 'with icon': { - addon: , + endAddon: , value: 1024, }, }} @@ -68,7 +68,7 @@ export const States: StoryFn = () => ( 'with placeholder': { placeholder: 'Placeholder' }, 'with value': { value: 1024 }, 'with icon': { - addon: , + endAddon: , value: 1024, }, }} diff --git a/packages/fuselage/src/components/NumberInput/NumberInput.tsx b/packages/fuselage/src/components/NumberInput/NumberInput.tsx index 8e4a628427..ec89499760 100644 --- a/packages/fuselage/src/components/NumberInput/NumberInput.tsx +++ b/packages/fuselage/src/components/NumberInput/NumberInput.tsx @@ -1,16 +1,12 @@ -import { forwardRef } from 'react'; - import { InputBox, type InputBoxProps } from '../InputBox'; -export type NumberInputProps = Omit; +export type NumberInputProps = Omit, 'type'>; /** * An input for numbers. */ -const NumberInput = forwardRef( - function NumberInput(props, ref) { - return ; - }, -); +function NumberInput(props: NumberInputProps) { + return ; +} export default NumberInput; diff --git a/packages/fuselage/src/components/Option/Option.tsx b/packages/fuselage/src/components/Option/Option.tsx index c73e58d41a..85fd0ab653 100644 --- a/packages/fuselage/src/components/Option/Option.tsx +++ b/packages/fuselage/src/components/Option/Option.tsx @@ -1,5 +1,10 @@ -import type { Ref, ReactNode, MouseEvent, AllHTMLAttributes } from 'react'; -import { forwardRef, memo } from 'react'; +import type { + ReactNode, + MouseEvent, + AllHTMLAttributes, + RefAttributes, +} from 'react'; +import { memo } from 'react'; import { prevent } from '../../helpers/prevent'; import type { BoxProps } from '../Box'; @@ -10,15 +15,14 @@ import OptionColumn from './OptionColumn'; import OptionContent from './OptionContent'; import OptionIcon from './OptionIcon'; -export type OptionProps = { +export type OptionProps = RefAttributes & { is?: BoxProps['is']; id?: string; children?: ReactNode; - label?: ReactNode; + label?: TLabel; focus?: boolean; selected?: boolean; className?: BoxProps['className']; - ref?: Ref; icon?: IconProps['name']; gap?: boolean; avatar?: ReactNode; @@ -29,55 +33,52 @@ export type OptionProps = { onClick?: (event: MouseEvent) => void; description?: ReactNode; } & Omit< - AllHTMLAttributes, - | 'is' - | 'id' - | 'children' - | 'label' - | 'selected' - | 'className' - | 'ref' - | 'icon' - | 'gap' - | 'avatar' - | 'title' - | 'disabled' - | 'value' - | 'variant' - | 'onClick' - | 'description' ->; + AllHTMLAttributes, + | 'is' + | 'id' + | 'children' + | 'label' + | 'selected' + | 'className' + | 'ref' + | 'icon' + | 'gap' + | 'avatar' + | 'title' + | 'disabled' + | 'value' + | 'variant' + | 'onClick' + | 'description' + > & + RefAttributes; /** * The generic `Option` item of options. Can be freely used or inside the `Options` as well. */ -const Option = forwardRef(function Option( - { - is: Tag = 'li', - id, - children, - label, - focus, - selected, - className, - icon, - gap, - avatar, - title, - disabled, - variant, - onClick, - description, - ...props - }: OptionProps, - ref, -) { +function Option({ + is: Tag = 'li', + id, + children, + label, + focus, + selected, + className, + icon, + gap, + avatar, + title, + disabled, + variant, + onClick, + description, + ...props +}: OptionProps) { return ( (function Option( {avatar && {avatar}} {icon && } {gap && } - {label && {label}} + {label && {label as ReactNode}} {label !== children && children}
); -}); +} export default memo(Option); diff --git a/packages/fuselage/src/components/Options/OptionContainer.tsx b/packages/fuselage/src/components/Options/OptionContainer.tsx index 321580d6e5..5ad01fdcf4 100644 --- a/packages/fuselage/src/components/Options/OptionContainer.tsx +++ b/packages/fuselage/src/components/Options/OptionContainer.tsx @@ -1,31 +1,22 @@ -import { forwardRef } from 'react'; +import type { RefAttributes } from 'react'; import { Box, type BoxProps } from '../Box'; import { Scrollable } from '../Scrollable'; import { Tile } from '../Tile'; -export type OptionContainerProps = BoxProps; +export type OptionContainerProps = Omit & + RefAttributes; -const OptionContainer = forwardRef( - function OptionContainer({ children, ...props }, ref) { - return ( - - - - - {children} - - - - - ); - }, -); +function OptionContainer(props: OptionContainerProps) { + return ( + + + + + + + + ); +} export default OptionContainer; diff --git a/packages/fuselage/src/components/Options/OptionType.tsx b/packages/fuselage/src/components/Options/OptionType.tsx index b1265bf042..a5706160df 100644 --- a/packages/fuselage/src/components/Options/OptionType.tsx +++ b/packages/fuselage/src/components/Options/OptionType.tsx @@ -1,10 +1,27 @@ import type { ReactNode } from 'react'; -export type OptionType = [ - value: TValue, - label: TLabel, - selected?: boolean, - disabled?: boolean, - type?: 'heading' | 'divider' | 'option', - url?: string, -]; +export type OptionType = + | [ + value: TValue, + label: TLabel, + selected?: boolean, + disabled?: boolean, + type?: 'option', + url?: string, + ] + | [ + value: TValue, + label: ReactNode, + selected: unknown, + disabled: unknown, + type: 'heading', + url?: string, + ] + | [ + value: TValue, + label: unknown, + selected: unknown, + disabled: unknown, + type: 'divider', + url?: string, + ]; diff --git a/packages/fuselage/src/components/Options/Options.tsx b/packages/fuselage/src/components/Options/Options.tsx index 0f9f493454..c3bd3afaec 100644 --- a/packages/fuselage/src/components/Options/Options.tsx +++ b/packages/fuselage/src/components/Options/Options.tsx @@ -1,11 +1,10 @@ import type { ComponentType, - ForwardRefExoticComponent, - PropsWithoutRef, + MouseEventHandler, ReactNode, RefAttributes, } from 'react'; -import { forwardRef, useLayoutEffect, useMemo, useRef } from 'react'; +import { useLayoutEffect, useMemo, useRef } from 'react'; import { prevent } from '../../helpers/prevent'; import { Box, type BoxProps } from '../Box'; @@ -16,45 +15,48 @@ import { Tile } from '../Tile'; import type { OptionType } from './OptionType'; import OptionsEmpty from './OptionsEmpty'; -export type OptionsProps = Omit< - BoxProps, - 'onSelect' -> & { - multiple?: boolean; - options: OptionType[]; - cursor: number; - renderItem?: ComponentType<{ - role?: string; - label: TLabel; - value: TValue; - selected?: boolean; - focus?: boolean; - }>; - renderEmpty?: ComponentType<{ +export type OptionsProps< + TValue extends string | number = string | number, + TLabel = ReactNode, +> = Omit & + RefAttributes & { + multiple?: boolean; + options: OptionType[]; + cursor: number; + renderItem?: ComponentType<{ + role?: string; + label: TLabel; + value: TValue; + selected?: boolean; + focus?: boolean; + disabled?: boolean; + onMouseDown: MouseEventHandler; + }>; + renderEmpty?: ComponentType<{ + customEmpty?: string; + }>; + onSelect: (option: OptionType) => void; customEmpty?: string; - }>; - onSelect: (option: OptionType) => void; - customEmpty?: string; -}; + }; /** * An input for selection of options. */ -const Options = forwardRef(function Options( - { - maxHeight = 'x144', - multiple, - renderEmpty: EmptyComponent = OptionsEmpty, - options, - cursor, - renderItem: OptionComponent = Option, - onSelect, - customEmpty, - id, - ...props - }, - ref, -) { +function Options< + TValue extends string | number = string | number, + TLabel = ReactNode, +>({ + maxHeight = 'x144', + multiple, + renderEmpty: EmptyComponent = OptionsEmpty, + options, + cursor, + renderItem: OptionComponent = Option, + onSelect, + customEmpty, + id, + ...props +}: OptionsProps) { const liRef = useRef(null); useLayoutEffect(() => { @@ -77,7 +79,7 @@ const Options = forwardRef(function Options( const optionsMemoized = useMemo( () => - options?.map(([value, label, selected, disabled, type, url], i) => { + options.map(([value, label, selected, disabled, type, url], i) => { switch (type) { case 'heading': return {label}; @@ -89,27 +91,25 @@ const Options = forwardRef(function Options( role='option' label={label} onMouseDown={(e) => { - if (disabled) { - return; - } + if (disabled) return; + prevent(e); onSelect([value, label, selected, disabled, type, url]); - return false; }} key={value} value={value} - selected={selected || (multiple !== true && undefined)} // TODO: undefined? + selected={selected} disabled={disabled} - focus={cursor === i || undefined} // TODO: undefined? + focus={cursor === i} /> ); } }), - [options, multiple, cursor, onSelect, OptionComponent], + [options, cursor, onSelect, OptionComponent], ); return ( - + (function Options( ); -}) as ForwardRefExoticComponent< - PropsWithoutRef & RefAttributes -> & { - ( - props: PropsWithoutRef> & - RefAttributes, - ): ReactNode; -}; +} export default Options; diff --git a/packages/fuselage/src/components/OptionsPaginated/OptionsPaginated.tsx b/packages/fuselage/src/components/OptionsPaginated/OptionsPaginated.tsx index 546d43c3db..f140bac16e 100644 --- a/packages/fuselage/src/components/OptionsPaginated/OptionsPaginated.tsx +++ b/packages/fuselage/src/components/OptionsPaginated/OptionsPaginated.tsx @@ -2,8 +2,14 @@ import { useStableCallback, useDebouncedState, } from '@rocket.chat/fuselage-hooks'; -import type { ComponentType, ElementType, MouseEvent, ReactNode } from 'react'; -import { forwardRef, memo } from 'react'; +import type { + ComponentType, + ElementType, + MouseEvent, + ReactNode, + RefAttributes, +} from 'react'; +import { memo } from 'react'; import { Virtuoso } from 'react-virtuoso'; import { prevent } from '../../helpers/prevent'; @@ -14,25 +20,26 @@ import type { OptionProps } from '../Option'; import { Option } from '../Option'; import { Tile } from '../Tile'; -export type OptionsPaginatedProps = Omit & { - multiple?: boolean; - options: { value: string | number; label: string; selected?: boolean }[]; - cursor: number; - withTitle?: boolean; - renderItem?: ComponentType<{ - role?: string; - label?: ReactNode; - title?: string; - selected?: boolean; - index?: number; - focus?: boolean; - value?: string | number; - onMouseDown?: (e: MouseEvent) => void; - }>; - renderEmpty?: ElementType; - onSelect: (option: [unknown, string]) => void; - endReached?: (start?: number | undefined, end?: number | undefined) => void; -}; +export type OptionsPaginatedProps = Omit & + RefAttributes & { + multiple?: boolean; + options: { value: string | number; label: string; selected?: boolean }[]; + cursor: number; + withTitle?: boolean; + renderItem?: ComponentType<{ + role?: string; + label?: ReactNode; + title?: string; + selected?: boolean; + index?: number; + focus?: boolean; + value?: string | number; + onMouseDown?: (e: MouseEvent) => void; + }>; + renderEmpty?: ElementType; + onSelect: (option: [unknown, string]) => void; + endReached?: (start?: number | undefined, end?: number | undefined) => void; + }; export const Empty = memo(() =>