From 2e7b6e1c395f7b041248de658e36ff3273a23e57 Mon Sep 17 00:00:00 2001 From: nils Date: Wed, 22 Jan 2025 12:26:42 +0100 Subject: [PATCH] remove remaining forwardRef --- .../src/autocomplete/autocomplete.tsx | 63 ++++++----- design-system/src/code/code.stories.tsx | 2 +- design-system/src/dialog/dialog.tsx | 2 +- .../src/floating/floating.stories.tsx | 6 +- design-system/src/index.ts | 2 - design-system/src/menu/menu.tsx | 2 + design-system/src/react.d.ts | 8 -- design-system/src/select/select.tsx | 106 +++++++++--------- design-system/src/slider/slider.stories.tsx | 1 - design-system/src/slider/slider.tsx | 42 +++---- design-system/src/theme.stories.tsx | 12 +- src/components/controlled.tsx | 11 +- src/components/full-screen.tsx | 15 +-- src/components/link.tsx | 43 +++---- src/components/list.tsx | 26 ++--- src/components/status-badges.tsx | 11 +- src/components/string-array-input.tsx | 22 ++-- src/components/terminal/terminal.tsx | 17 +-- src/layouts/main/estimated-costs-popup.tsx | 33 +++--- src/layouts/main/layout.tsx | 11 +- .../command-palette/command-palette.tsx | 10 +- src/modules/trial/trial-summary-popup.tsx | 71 ++++++------ src/react.d.ts | 8 -- 23 files changed, 238 insertions(+), 286 deletions(-) delete mode 100644 design-system/src/react.d.ts delete mode 100644 src/react.d.ts diff --git a/design-system/src/autocomplete/autocomplete.tsx b/design-system/src/autocomplete/autocomplete.tsx index c9d10781..42d2e7de 100644 --- a/design-system/src/autocomplete/autocomplete.tsx +++ b/design-system/src/autocomplete/autocomplete.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import { useCombobox } from 'downshift'; import IconChevronDown from 'lucide-static/icons/chevron-down.svg?react'; -import { forwardRef, useMemo } from 'react'; +import { useMemo } from 'react'; import { Dropdown } from '../dropdown/dropdown'; import { useDropdown } from '../dropdown/use-dropdown'; @@ -10,6 +10,7 @@ import { InputBox } from '../input/input'; import { useId } from '../utils/use-id'; type AutocompleteProps = { + ref?: React.Ref; open?: boolean; size?: 1 | 2 | 3; label?: React.ReactNode; @@ -36,35 +37,33 @@ type AutocompleteProps = { renderNoItems?: () => React.ReactNode; }; -export const Autocomplete = forwardRef(function Autocomplete( - { - open, - size, - label, - helpTooltip, - helperText, - placeholder, - error, - invalid = Boolean(error), - required, - disabled, - className, - id: idProp, - name, - items, - selectedItem, - onSelectedItemChange, - inputValue, - onInputValueChange, - resetOnBlur = true, - onBlur, - getKey, - itemToString, - renderItem, - renderNoItems, - }: AutocompleteProps, - ref: React.ForwardedRef, -) { +export function Autocomplete({ + ref, + open, + size, + label, + helpTooltip, + helperText, + placeholder, + error, + invalid = Boolean(error), + required, + disabled, + className, + id: idProp, + name, + items, + selectedItem, + onSelectedItemChange, + inputValue, + onInputValueChange, + resetOnBlur = true, + onBlur, + getKey, + itemToString, + renderItem, + renderNoItems, +}: AutocompleteProps) { const id = useId(idProp); const helperTextId = `${id}-helper-text`; @@ -154,6 +153,8 @@ export const Autocomplete = forwardRef(function Autocomplete( className="peer" aria-invalid={invalid} aria-errormessage={helperTextId} + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore {...getInputProps({ ref, id, onBlur, required })} /> @@ -169,4 +170,4 @@ export const Autocomplete = forwardRef(function Autocomplete( /> ); -}); +} diff --git a/design-system/src/code/code.stories.tsx b/design-system/src/code/code.stories.tsx index 2a5aed08..457fbb6a 100644 --- a/design-system/src/code/code.stories.tsx +++ b/design-system/src/code/code.stories.tsx @@ -16,7 +16,7 @@ export default meta; export const Default: StoryObj = { render: (args) => , args: { - lang: 'typescript', + lang: 'javascript', value: "import type { Meta } from '@storybook/react';\n\nexport default {\n title: 'MyStory',\n} satisfies Meta;", }, diff --git a/design-system/src/dialog/dialog.tsx b/design-system/src/dialog/dialog.tsx index 2dc39737..7e17e245 100644 --- a/design-system/src/dialog/dialog.tsx +++ b/design-system/src/dialog/dialog.tsx @@ -140,7 +140,7 @@ export function Dialog({ ); } -const MotionFloatingOverlay = motion(FloatingOverlay); +const MotionFloatingOverlay = motion.create(FloatingOverlay); type Dialog2Props = { open: boolean; diff --git a/design-system/src/floating/floating.stories.tsx b/design-system/src/floating/floating.stories.tsx index 5036d102..92b3dd54 100644 --- a/design-system/src/floating/floating.stories.tsx +++ b/design-system/src/floating/floating.stories.tsx @@ -18,9 +18,9 @@ const meta = { setOpen: action('setOpen'), offset: 8, placement: 'bottom', - renderReference: (ref, props) =>
, - renderFloating: (ref, props) => ( -
+ renderReference: (props) =>
, + renderFloating: (props) => ( +
Floating
), diff --git a/design-system/src/index.ts b/design-system/src/index.ts index 3cc12a4f..5a0ebe5d 100644 --- a/design-system/src/index.ts +++ b/design-system/src/index.ts @@ -1,5 +1,3 @@ -import './react.d'; - export * from './accordion/accordion'; export * from './alert/alert'; export * from './autocomplete/autocomplete'; diff --git a/design-system/src/menu/menu.tsx b/design-system/src/menu/menu.tsx index 1d6049a6..24bdf5f3 100644 --- a/design-system/src/menu/menu.tsx +++ b/design-system/src/menu/menu.tsx @@ -5,6 +5,8 @@ import { Extend } from '../utils/types'; export function Menu({ className, ...props }: React.ComponentProps<'div'>) { return ( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore
( - render: (props: P, ref: React.Ref) => React.ReactElement | null, - ): (props: P & React.RefAttributes) => React.ReactElement | null; -} diff --git a/design-system/src/select/select.tsx b/design-system/src/select/select.tsx index f27d837a..17e05e57 100644 --- a/design-system/src/select/select.tsx +++ b/design-system/src/select/select.tsx @@ -1,14 +1,16 @@ import clsx from 'clsx'; import { useSelect, UseSelectProps, UseSelectState, UseSelectStateChangeOptions } from 'downshift'; import IconChevronDown from 'lucide-static/icons/chevron-down.svg?react'; -import { forwardRef, useCallback, useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { Dropdown, DropdownGroup } from '../dropdown/dropdown'; import { useDropdown } from '../dropdown/use-dropdown'; import { Field, FieldHelperText, FieldLabel } from '../field/field'; +import { Extend } from '../utils/types'; import { useId } from '../utils/use-id'; type SelectProps = { + ref?: React.Ref; open?: boolean; size?: 1 | 2 | 3; label?: React.ReactNode; @@ -36,36 +38,34 @@ type SelectProps = { stateReducer?: UseSelectProps['stateReducer']; }; -export const Select = forwardRef(function Select( - { - open, - size = 2, - label, - helpTooltip, - helperText, - error, - invalid = Boolean(error), - disabled, - readOnly, - placeholder, - className, - id: idProp, - items, - groups, - selectedItem: selectedItemProp, - onSelectedItemChange, - onItemClick, - onBlur, - getKey, - itemToString, - renderItem, - renderNoItems, - renderSelectedItem, - canSelectItem, - stateReducer, - }: SelectProps, - forwardedRef: React.ForwardedRef, -) { +export function Select({ + ref: forwardedRef, + open, + size = 2, + label, + helpTooltip, + helperText, + error, + invalid = Boolean(error), + disabled, + readOnly, + placeholder, + className, + id: idProp, + items, + groups, + selectedItem: selectedItemProp, + onSelectedItemChange, + onItemClick, + onBlur, + getKey, + itemToString, + renderItem, + renderNoItems, + renderSelectedItem, + canSelectItem, + stateReducer, +}: SelectProps) { const id = useId(idProp); const helperTextId = `${id}-helper-text`; @@ -105,7 +105,7 @@ export const Select = forwardRef(function Select( if (typeof forwardedRef === 'function') { forwardedRef(ref); - } else if (forwardedRef) { + } else if (forwardedRef != null) { forwardedRef.current = ref; } }, @@ -173,33 +173,29 @@ export const Select = forwardRef(function Select( /> ); -}); +} -type MultiSelectProps = Omit< +type MultiSelectProps = Extend< SelectProps, - 'selectedItem' | 'onSelectedItemChange' | 'renderItem' | 'renderSelectedItem' -> & { - selectedItems?: Item[]; - onItemsSelected?: (item: Item) => void; - onItemsUnselected?: (item: Item) => void; - renderItem: (item: Item, selected: boolean, index?: number) => React.ReactNode; - renderSelectedItems: (items: Item[]) => React.ReactNode; -}; - -export const MultiSelect = forwardRef(function MultiSelect( { - selectedItems = [], - onItemsSelected, - onItemsUnselected, - renderItem, - renderSelectedItems, - ...props - }: MultiSelectProps, - ref: React.ForwardedRef, -) { + selectedItems?: Item[]; + onItemsSelected?: (item: Item) => void; + onItemsUnselected?: (item: Item) => void; + renderItem: (item: Item, selected: boolean, index?: number) => React.ReactNode; + renderSelectedItems: (items: Item[]) => React.ReactNode; + } +>; + +export function MultiSelect({ + selectedItems = [], + onItemsSelected, + onItemsUnselected, + renderItem, + renderSelectedItems, + ...props +}: MultiSelectProps) { return ( setValueStr(event.target.value)} onBlur={() => onChange?.(parseArray(valueStr))} /> ); -}); +} function parseArray(input: string): string[] { if (input === '') { diff --git a/src/components/terminal/terminal.tsx b/src/components/terminal/terminal.tsx index d08f508e..a612f1f4 100644 --- a/src/components/terminal/terminal.tsx +++ b/src/components/terminal/terminal.tsx @@ -1,24 +1,25 @@ import { FitAddon } from '@xterm/addon-fit'; import { ITerminalOptions, Terminal as XTerm } from '@xterm/xterm'; -import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react'; +import { useEffect, useImperativeHandle, useMemo, useState } from 'react'; import { useWatchElementSize } from '@koyeb/design-system'; import { useThemeModeOrPreferred } from 'src/hooks/theme'; import '@xterm/xterm/css/xterm.css'; -type TerminalProps = { - onSizeChange: (size: { cols: number; rows: number }) => void; - onData: (data: string) => void; -}; - export type TerminalRef = { focus(): void; clear(): void; write(chunk: string): void; }; -export default forwardRef(function Terminal({ onSizeChange, onData }, ref) { +type TerminalProps = { + ref?: React.Ref; + onSizeChange: (size: { cols: number; rows: number }) => void; + onData: (data: string) => void; +}; + +export default function Terminal({ ref, onSizeChange, onData }: TerminalProps) { const xterm = useMemo(() => new XTerm(), []); const fitAddon = useMemo(() => new FitAddon(), []); const [container, setContainer] = useState(null); @@ -54,7 +55,7 @@ export default forwardRef(function Terminal({ onSize
); -}); +} function useTerminalTheme(xterm: XTerm) { const themeMode = useThemeModeOrPreferred(); diff --git a/src/layouts/main/estimated-costs-popup.tsx b/src/layouts/main/estimated-costs-popup.tsx index ab0f24e7..76b7e6f4 100644 --- a/src/layouts/main/estimated-costs-popup.tsx +++ b/src/layouts/main/estimated-costs-popup.tsx @@ -1,11 +1,10 @@ import clsx from 'clsx'; -import { forwardRef } from 'react'; import { Fragment } from 'react/jsx-runtime'; import { FormattedNumber } from 'react-intl'; import { useNextInvoiceQuery } from 'src/api/hooks/billing'; import { useOrganization } from 'src/api/hooks/session'; -import { InvoiceLine, InvoiceUsageLine, InvoicePlanLine, Invoice } from 'src/api/model'; +import { Invoice, InvoiceLine, InvoicePlanLine, InvoiceUsageLine } from 'src/api/model'; import { routes } from 'src/application/routes'; import { LinkButton } from 'src/components/link'; import { Loading } from 'src/components/loading'; @@ -14,25 +13,23 @@ import { createTranslate, TranslateEnum } from 'src/intl/translate'; const T = createTranslate('layouts.main.organizationPlan.estimatedCost'); -export const EstimatedCostsPopup = forwardRef>( - function EstimatedCostsPopup({ className, ...props }, ref) { - const organization = useOrganization(); - const nextInvoiceQuery = useNextInvoiceQuery(); +export function EstimatedCostsPopup({ className, ...props }: React.ComponentProps<'div'>) { + const organization = useOrganization(); + const nextInvoiceQuery = useNextInvoiceQuery(); - return ( -
-
- }} /> -
+ return ( +
+
+ }} /> +
-
+
- {nextInvoiceQuery.isLoading && } - {nextInvoiceQuery.isSuccess && } -
- ); - }, -); + {nextInvoiceQuery.isLoading && } + {nextInvoiceQuery.isSuccess && } +
+ ); +} function CostsDetails({ costs }: { costs: ReturnType }) { return ( diff --git a/src/layouts/main/layout.tsx b/src/layouts/main/layout.tsx index 00782640..aa5353be 100644 --- a/src/layouts/main/layout.tsx +++ b/src/layouts/main/layout.tsx @@ -9,7 +9,7 @@ import { useTransitionStyles, } from '@floating-ui/react'; import clsx from 'clsx'; -import { forwardRef, useState } from 'react'; +import { useState } from 'react'; import { Button, useBreakpoint } from '@koyeb/design-system'; import { IconMenu } from 'src/components/icons'; @@ -180,19 +180,14 @@ function MobileMenu({ state, setState, children }: MobileMenuProps) { ); } -const Aside = forwardRef>(function Aside( - { className, ...props }, - ref, -) { +export function Aside({ className, ...props }: React.ComponentProps<'aside'>) { return (