From ee61daea6347cd44fdb669e7f5fd285b725a5693 Mon Sep 17 00:00:00 2001 From: Alexander Harding Date: Sun, 17 Nov 2024 14:48:38 -0600 Subject: [PATCH 1/3] Support React 19 ref as prop This is a stab at supporting forwardRef and ref-as-prop (react 19). By defaulting to CustomItemComponentProps ref type to div, this *shouldn't* have breaking changes for most users. Note: I also abstracted the types to encourage users to spread onto the custom element. This may be helpful for changes passing other attributes in the future? --- src/react/VList.spec.tsx | 6 ++---- src/react/Virtualizer.tsx | 4 ++-- src/react/WindowVirtualizer.spec.tsx | 6 ++---- src/react/WindowVirtualizer.tsx | 4 ++-- src/react/types.ts | 22 +++++----------------- 5 files changed, 13 insertions(+), 29 deletions(-) diff --git a/src/react/VList.spec.tsx b/src/react/VList.spec.tsx index e3b02a611..c77f17ecf 100644 --- a/src/react/VList.spec.tsx +++ b/src/react/VList.spec.tsx @@ -35,11 +35,9 @@ it("should pass attributes to element", () => { it("should pass index to items", () => { const Item = forwardRef( - ({ children, index, style }, ref) => { + ({ index, ...rest }, ref) => { return ( -
- {children} -
+
); } ); diff --git a/src/react/Virtualizer.tsx b/src/react/Virtualizer.tsx index f89511a84..2dbcb884a 100644 --- a/src/react/Virtualizer.tsx +++ b/src/react/Virtualizer.tsx @@ -141,12 +141,12 @@ export interface VirtualizerProps { * Component or element type for container element. * @defaultValue "div" */ - as?: keyof JSX.IntrinsicElements | CustomContainerComponent; + as?: keyof JSX.IntrinsicElements | CustomContainerComponent; /** * Component or element type for item element. This component will get {@link CustomItemComponentProps} as props. * @defaultValue "div" */ - item?: keyof JSX.IntrinsicElements | CustomItemComponent; + item?: keyof JSX.IntrinsicElements | CustomItemComponent; /** * Reference to the scrollable element. The default will get the direct parent element of virtualizer. */ diff --git a/src/react/WindowVirtualizer.spec.tsx b/src/react/WindowVirtualizer.spec.tsx index f1be4c2de..48705f44b 100644 --- a/src/react/WindowVirtualizer.spec.tsx +++ b/src/react/WindowVirtualizer.spec.tsx @@ -14,11 +14,9 @@ afterEach(cleanup); it("should pass index to items", () => { const Item = forwardRef( - ({ children, index, style }, ref) => { + ({ index, ...rest }, ref) => { return ( -
- {children} -
+
); } ); diff --git a/src/react/WindowVirtualizer.tsx b/src/react/WindowVirtualizer.tsx index 79d5b987c..9e90824e2 100644 --- a/src/react/WindowVirtualizer.tsx +++ b/src/react/WindowVirtualizer.tsx @@ -92,12 +92,12 @@ export interface WindowVirtualizerProps { * Component or element type for container element. * @defaultValue "div" */ - as?: keyof JSX.IntrinsicElements | CustomContainerComponent; + as?: keyof JSX.IntrinsicElements | CustomContainerComponent; /** * Component or element type for item element. This component will get {@link CustomItemComponentProps} as props. * @defaultValue "div" */ - item?: keyof JSX.IntrinsicElements | CustomItemComponent; + item?: keyof JSX.IntrinsicElements | CustomItemComponent; /** * Callback invoked whenever scroll offset changes. * @param offset Current scrollTop, or scrollLeft if horizontal: true. diff --git a/src/react/types.ts b/src/react/types.ts index ba0f7f764..31b672da2 100644 --- a/src/react/types.ts +++ b/src/react/types.ts @@ -1,30 +1,18 @@ -import { CSSProperties, ReactNode } from "react"; - export type ViewportComponentAttributes = Pick< React.HTMLAttributes, "className" | "style" | "id" | "role" | "tabIndex" | "onKeyDown" | "onWheel" > & React.AriaAttributes; -export interface CustomContainerComponentProps { - style: CSSProperties; - children: ReactNode; -} +export type CustomContainerComponentProps = React.ComponentPropsWithRef -export type CustomContainerComponent = React.ForwardRefExoticComponent< - React.PropsWithoutRef & - React.RefAttributes ->; +export type CustomContainerComponent = React.FunctionComponent>; /** * Props of customized item component for {@link Virtualizer} or {@link WindowVirtualizer}. */ -export interface CustomItemComponentProps { - style: CSSProperties; +export type CustomItemComponentProps = React.ComponentPropsWithRef & React.PropsWithChildren<{ index: number; - children: ReactNode; -} +}>; -export type CustomItemComponent = React.ForwardRefExoticComponent< - React.PropsWithoutRef & React.RefAttributes ->; +export type CustomItemComponent = React.FunctionComponent>; From b4f6fcdcb70f5b710cb4981d31921a3049c67e3b Mon Sep 17 00:00:00 2001 From: Alexander Harding Date: Sun, 17 Nov 2024 14:55:50 -0600 Subject: [PATCH 2/3] simplify --- src/react/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/react/types.ts b/src/react/types.ts index 31b672da2..f15ce8313 100644 --- a/src/react/types.ts +++ b/src/react/types.ts @@ -11,8 +11,8 @@ export type CustomContainerComponent = Reac /** * Props of customized item component for {@link Virtualizer} or {@link WindowVirtualizer}. */ -export type CustomItemComponentProps = React.ComponentPropsWithRef & React.PropsWithChildren<{ +export type CustomItemComponentProps = React.ComponentPropsWithRef & { index: number; -}>; +}; export type CustomItemComponent = React.FunctionComponent>; From d903f3907b16fc8e8f6a226ead9f61630366b697 Mon Sep 17 00:00:00 2001 From: inokawa <48897392+inokawa@users.noreply.github.com> Date: Fri, 6 Dec 2024 21:11:29 +0900 Subject: [PATCH 3/3] Reconsider types --- src/react/Virtualizer.tsx | 4 ++-- src/react/WindowVirtualizer.tsx | 4 ++-- src/react/types.ts | 26 +++++++++++++++++++++----- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/react/Virtualizer.tsx b/src/react/Virtualizer.tsx index ac76a0d36..e203b8ef1 100644 --- a/src/react/Virtualizer.tsx +++ b/src/react/Virtualizer.tsx @@ -144,12 +144,12 @@ export interface VirtualizerProps { * Component or element type for container element. * @defaultValue "div" */ - as?: keyof JSX.IntrinsicElements | CustomContainerComponent; + as?: keyof JSX.IntrinsicElements | CustomContainerComponent; /** * Component or element type for item element. This component will get {@link CustomItemComponentProps} as props. * @defaultValue "div" */ - item?: keyof JSX.IntrinsicElements | CustomItemComponent; + item?: keyof JSX.IntrinsicElements | CustomItemComponent; /** * Reference to the scrollable element. The default will get the direct parent element of virtualizer. */ diff --git a/src/react/WindowVirtualizer.tsx b/src/react/WindowVirtualizer.tsx index d3a0c0c57..e8222b690 100644 --- a/src/react/WindowVirtualizer.tsx +++ b/src/react/WindowVirtualizer.tsx @@ -99,12 +99,12 @@ export interface WindowVirtualizerProps { * Component or element type for container element. * @defaultValue "div" */ - as?: keyof JSX.IntrinsicElements | CustomContainerComponent; + as?: keyof JSX.IntrinsicElements | CustomContainerComponent; /** * Component or element type for item element. This component will get {@link CustomItemComponentProps} as props. * @defaultValue "div" */ - item?: keyof JSX.IntrinsicElements | CustomItemComponent; + item?: keyof JSX.IntrinsicElements | CustomItemComponent; /** * Callback invoked whenever scroll offset changes. * @param offset Current scrollTop, or scrollLeft if horizontal: true. diff --git a/src/react/types.ts b/src/react/types.ts index f15ce8313..a505044ed 100644 --- a/src/react/types.ts +++ b/src/react/types.ts @@ -1,18 +1,34 @@ +import { ComponentType, CSSProperties, LegacyRef, ReactNode } from "react"; + export type ViewportComponentAttributes = Pick< React.HTMLAttributes, "className" | "style" | "id" | "role" | "tabIndex" | "onKeyDown" | "onWheel" > & React.AriaAttributes; -export type CustomContainerComponentProps = React.ComponentPropsWithRef +export interface CustomContainerComponentProps { + style: CSSProperties; + children: ReactNode; + /** + * only available after React 19 + */ + ref?: LegacyRef; +} -export type CustomContainerComponent = React.FunctionComponent>; +export type CustomContainerComponent = + ComponentType; /** * Props of customized item component for {@link Virtualizer} or {@link WindowVirtualizer}. */ -export type CustomItemComponentProps = React.ComponentPropsWithRef & { +export interface CustomItemComponentProps { + style: CSSProperties; index: number; -}; + children: ReactNode; + /** + * only available after React 19 + */ + ref?: LegacyRef; +} -export type CustomItemComponent = React.FunctionComponent>; +export type CustomItemComponent = ComponentType;