From a4a1c5d49fd0e61afc0bf5050415a4164a101970 Mon Sep 17 00:00:00 2001 From: inokawa <48897392+inokawa@users.noreply.github.com> Date: Tue, 1 Aug 2023 18:55:15 +0900 Subject: [PATCH] Rename element props to components --- src/index.ts | 21 +------ src/react/VGrid.spec.tsx | 4 +- src/react/VGrid.tsx | 56 ++++++++++-------- src/react/VList.spec.tsx | 6 +- src/react/VList.tsx | 58 +++++++++++-------- src/react/{Window.tsx => Viewport.tsx} | 10 ++-- src/react/WVList.spec.tsx | 6 +- src/react/WVList.tsx | 58 +++++++++++-------- src/react/index.ts | 17 ++++++ src/react/utils.ts | 2 + stories/advanced/PullToRefresh.stories.tsx | 6 +- stories/advanced/Table.stories.tsx | 7 +-- .../advanced/With react-select.stories.tsx | 6 +- stories/advanced/Zoomable.stories.tsx | 2 +- stories/basics/VList.stories.tsx | 7 +-- 15 files changed, 147 insertions(+), 119 deletions(-) rename src/react/{Window.tsx => Viewport.tsx} (83%) create mode 100644 src/react/index.ts diff --git a/src/index.ts b/src/index.ts index 16e85e9e3..9342b569d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,2 @@ export type { CacheSnapshot } from "./core/types"; -export { VList } from "./react/VList"; -export type { VListProps, VListHandle, ScrollMode } from "./react/VList"; -export { VGrid } from "./react/VGrid"; -export type { - VGridProps, - VGridHandle, - CustomCellComponent, - CustomCellComponentProps, -} from "./react/VGrid"; -export { WVList } from "./react/WVList"; -export type { WVListProps, WVListHandle } from "./react/WVList"; -export type { - WindowComponentAttributes, - CustomWindowComponent, - CustomWindowComponentProps, -} from "./react/Window"; -export type { - CustomItemComponent, - CustomItemComponentProps, -} from "./react/ListItem"; +export * from "./react"; diff --git a/src/react/VGrid.spec.tsx b/src/react/VGrid.spec.tsx index c7def5578..83e5975d7 100644 --- a/src/react/VGrid.spec.tsx +++ b/src/react/VGrid.spec.tsx @@ -104,7 +104,7 @@ it("should pass attributes to element", async () => { }); // it("should change components", async () => { -// const UlList = forwardRef( +// const UlList = forwardRef( // ({ children, attrs, scrollSize }, ref) => { // return ( //
@@ -116,7 +116,7 @@ it("should pass attributes to element", async () => { // } // ); // const { asFragment } = render( -// +// //
0
//
1
//
2
diff --git a/src/react/VGrid.tsx b/src/react/VGrid.tsx index 189008913..4e27963f4 100644 --- a/src/react/VGrid.tsx +++ b/src/react/VGrid.tsx @@ -20,15 +20,15 @@ import { } from "./useSelector"; import { max, min, values } from "../core/utils"; import { createScroller } from "../core/scroller"; -import { refKey } from "./utils"; +import { emptyComponents, refKey } from "./utils"; import { useStatic } from "./useStatic"; import { - CustomWindowComponent, - CustomWindowComponentProps, - WindowComponentAttributes, + CustomViewportComponent, + CustomViewportComponentProps, + ViewportComponentAttributes, } from ".."; import { createGridResizer, GridResizer } from "../core/resizer"; -import { Window as DefaultWindow } from "./Window"; +import { Viewport as DefaultViewport } from "./Viewport"; const genKey = (i: number, j: number) => `${i}-${j}`; @@ -178,7 +178,7 @@ export interface VGridHandle { /** * Props of {@link VGrid}. */ -export interface VGridProps extends WindowComponentAttributes { +export interface VGridProps extends ViewportComponentAttributes { /** * A function to create elements rendered by this component. */ @@ -228,15 +228,20 @@ export interface VGridProps extends WindowComponentAttributes { */ rtl?: boolean; /** - * Customized element type for scrollable element. This element will get {@link CustomWindowComponentProps} as props. - * @defaultValue {@link Window} + * Customized components for advanced usage. */ - element?: CustomWindowComponent; - /** - * Customized element type for cell element. This element will get {@link CustomCellComponentProps} as props. - * @defaultValue "div" - */ - cellElement?: CustomCellComponentOrElement; + components?: { + /** + * Component for scrollable element. This component will get {@link CustomViewportComponentProps} as props. + * @defaultValue {@link DefaultViewport} + */ + Root?: CustomViewportComponent; + /** + * Component or element type for cell element. This component will get {@link CustomCellComponentProps} as props. + * @defaultValue "div" + */ + Cell?: CustomCellComponentOrElement; + }; } /** @@ -254,9 +259,14 @@ export const VGrid = forwardRef( initialRowCount, initialColCount, rtl: rtlProp, - element: Window = DefaultWindow, - cellElement: itemElement = "div", - ...windowAttrs + components: { + Root: Viewport = DefaultViewport, + Cell: ItemElement = "div", + } = emptyComponents as { + Root?: CustomViewportComponent; + Cell?: CustomCellComponentOrElement; + }, + ...viewportAttrs }, ref ): ReactElement => { @@ -421,7 +431,7 @@ export const VGrid = forwardRef( _hStore={hStore} _rowIndex={i} _colIndex={j} - _element={itemElement as "div"} + _element={ItemElement as "div"} _children={render(i, j)} _isRtl={isRtl} /> @@ -439,14 +449,14 @@ export const VGrid = forwardRef( ]); return ( - ({ - ...windowAttrs, + ...viewportAttrs, style: { overflow: "auto", contain: "strict", @@ -457,14 +467,14 @@ export const VGrid = forwardRef( height: "100%", padding: 0, margin: 0, - ...windowAttrs.style, + ...viewportAttrs.style, }, }), - values(windowAttrs) + values(viewportAttrs) )} > {items} - + ); } ); diff --git a/src/react/VList.spec.tsx b/src/react/VList.spec.tsx index 3838a65a9..3bce859b8 100644 --- a/src/react/VList.spec.tsx +++ b/src/react/VList.spec.tsx @@ -9,7 +9,7 @@ import { useRef, useState, } from "react"; -import { CustomWindowComponentProps } from ".."; +import { CustomViewportComponentProps } from ".."; const ITEM_HEIGHT = 50; const ITEM_WIDTH = 100; @@ -107,7 +107,7 @@ it("should pass attributes to element", async () => { }); it("should change components", async () => { - const UlList = forwardRef( + const UlList = forwardRef( ({ children, attrs, height }, ref) => { return (
@@ -119,7 +119,7 @@ it("should change components", async () => { } ); const { asFragment } = render( - +
0
1
2
diff --git a/src/react/VList.tsx b/src/react/VList.tsx index 408054f37..49305402c 100644 --- a/src/react/VList.tsx +++ b/src/react/VList.tsx @@ -18,16 +18,16 @@ import { } from "./useSelector"; import { exists, max, min, values } from "../core/utils"; import { createScroller } from "../core/scroller"; -import { MayHaveKey, flattenChildren, refKey } from "./utils"; +import { MayHaveKey, emptyComponents, flattenChildren, refKey } from "./utils"; import { useStatic } from "./useStatic"; import { useRefWithUpdate } from "./useRefWithUpdate"; import { createResizer } from "../core/resizer"; -import { WindowComponentAttributes } from ".."; +import { ViewportComponentAttributes } from ".."; import { - CustomWindowComponent, - CustomWindowComponentProps, - Window as DefaultWindow, -} from "./Window"; + CustomViewportComponent, + CustomViewportComponentProps, + Viewport as DefaultViewport, +} from "./Viewport"; import { CustomItemComponent, ListItem } from "./ListItem"; import { CacheSnapshot } from "../core/types"; @@ -77,7 +77,7 @@ export interface VListHandle { /** * Props of {@link VList}. */ -export interface VListProps extends WindowComponentAttributes { +export interface VListProps extends ViewportComponentAttributes { /** * Elements rendered by this component. */ @@ -114,15 +114,20 @@ export interface VListProps extends WindowComponentAttributes { */ cache?: CacheSnapshot; /** - * Customized element type for scrollable element. This element will get {@link CustomWindowComponentProps} as props. - * @defaultValue {@link Window} + * Customized components for advanced usage. */ - element?: CustomWindowComponent; - /** - * Customized element type for item element. This element will get {@link CustomItemComponentProps} as props. - * @defaultValue "div" - */ - itemElement?: CustomItemComponentOrElement; + components?: { + /** + * Component for scrollable element. This component will get {@link CustomViewportComponentProps} as props. + * @defaultValue {@link DefaultViewport} + */ + Root?: CustomViewportComponent; + /** + * Component or element type for item element. This component will get {@link CustomItemComponentProps} as props. + * @defaultValue "div" + */ + Item?: CustomItemComponentOrElement; + }; /** * Callback invoked whenever scroll offset changes. * @param offset Current scrollTop or scrollLeft. @@ -160,12 +165,17 @@ export const VList = forwardRef( horizontal: horizontalProp, mode, cache, - element: Window = DefaultWindow, - itemElement = "div", + components: { + Root: Viewport = DefaultViewport, + Item: ItemElement = "div", + } = emptyComponents as { + Root?: CustomViewportComponent; + Item?: CustomItemComponentOrElement; + }, onScroll: onScrollProp, onScrollStop: onScrollStopProp, onRangeChange: onRangeChangeProp, - ...windowAttrs + ...viewportAttrs }, ref ): ReactElement => { @@ -293,7 +303,7 @@ export const VList = forwardRef( _resizer={resizer} _store={store} _index={i} - _element={itemElement as "div"} + _element={ItemElement as "div"} _children={e} _isHorizontal={isHorizontal} _isRtl={isRtl} @@ -305,14 +315,14 @@ export const VList = forwardRef( }, [elements, overscanedStartIndex, overscanedEndIndex]); return ( - ({ - ...windowAttrs, + ...viewportAttrs, style: { overflow: isHorizontal ? "auto hidden" : "hidden auto", display: isHorizontal ? "inline-block" : "block", @@ -326,14 +336,14 @@ export const VList = forwardRef( height: "100%", padding: 0, margin: 0, - ...windowAttrs.style, + ...viewportAttrs.style, }, }), - values(windowAttrs) + values(viewportAttrs) )} > {items} - + ); } ); diff --git a/src/react/Window.tsx b/src/react/Viewport.tsx similarity index 83% rename from src/react/Window.tsx rename to src/react/Viewport.tsx index 6de77611c..527677fac 100644 --- a/src/react/Window.tsx +++ b/src/react/Viewport.tsx @@ -6,7 +6,7 @@ import { useMemo, } from "react"; -export type WindowComponentAttributes = Pick< +export type ViewportComponentAttributes = Pick< React.HTMLAttributes, "className" | "style" | "id" | "role" | "tabIndex" > & @@ -15,7 +15,7 @@ export type WindowComponentAttributes = Pick< /** * Props of customized scrollable component. */ -export interface CustomWindowComponentProps { +export interface CustomViewportComponentProps { /** * Renderable item elements. */ @@ -23,7 +23,7 @@ export interface CustomWindowComponentProps { /** * Attributes that should be passed to the scrollable element. */ - attrs: WindowComponentAttributes; + attrs: ViewportComponentAttributes; /** * Total height of items. It's undefined if component is not vertically scrollable. */ @@ -38,7 +38,7 @@ export interface CustomWindowComponentProps { scrolling: boolean; } -export const Window = forwardRef( +export const Viewport = forwardRef( ({ children, attrs, width, height, scrolling }, ref): ReactElement => { return (
@@ -60,4 +60,4 @@ export const Window = forwardRef( } ); -export type CustomWindowComponent = typeof Window; +export type CustomViewportComponent = typeof Viewport; diff --git a/src/react/WVList.spec.tsx b/src/react/WVList.spec.tsx index 9b657b024..764509fac 100644 --- a/src/react/WVList.spec.tsx +++ b/src/react/WVList.spec.tsx @@ -2,7 +2,7 @@ import { afterEach, it, expect, describe, jest } from "@jest/globals"; import { render, cleanup } from "@testing-library/react"; import { WVList } from "./WVList"; import { Profiler, ReactElement, forwardRef, useEffect, useState } from "react"; -import { CustomWindowComponentProps } from ".."; +import { CustomViewportComponentProps } from ".."; const ITEM_HEIGHT = 50; const ITEM_WIDTH = 100; @@ -77,7 +77,7 @@ it("should pass attributes to element", async () => { }); it("should change components", async () => { - const UlList = forwardRef( + const UlList = forwardRef( ({ children, attrs, height }, ref) => { return (
@@ -89,7 +89,7 @@ it("should change components", async () => { } ); const { asFragment } = render( - +
0
1
2
diff --git a/src/react/WVList.tsx b/src/react/WVList.tsx index 8468a537c..3906ef6d7 100644 --- a/src/react/WVList.tsx +++ b/src/react/WVList.tsx @@ -18,16 +18,16 @@ import { } from "./useSelector"; import { exists, max, min, values } from "../core/utils"; import { createWindowScroller } from "../core/scroller"; -import { MayHaveKey, flattenChildren, refKey } from "./utils"; +import { MayHaveKey, emptyComponents, flattenChildren, refKey } from "./utils"; import { useStatic } from "./useStatic"; import { useRefWithUpdate } from "./useRefWithUpdate"; import { createWindowResizer } from "../core/resizer"; -import { CacheSnapshot, WindowComponentAttributes } from ".."; +import { CacheSnapshot, ViewportComponentAttributes } from ".."; import { - CustomWindowComponent, - CustomWindowComponentProps, - Window as DefaultWindow, -} from "./Window"; + CustomViewportComponent, + CustomViewportComponentProps, + Viewport as DefaultViewport, +} from "./Viewport"; import { CustomItemComponent, ListItem } from "./ListItem"; type CustomItemComponentOrElement = @@ -47,7 +47,7 @@ export interface WVListHandle { /** * Props of {@link WVList}. */ -export interface WVListProps extends WindowComponentAttributes { +export interface WVListProps extends ViewportComponentAttributes { /** * Elements rendered by this component. */ @@ -77,15 +77,20 @@ export interface WVListProps extends WindowComponentAttributes { */ cache?: CacheSnapshot; /** - * Customized element type for scrollable element. This element will get {@link CustomWindowComponentProps} as props. - * @defaultValue {@link Window} + * Customized components for advanced usage. */ - element?: CustomWindowComponent; - /** - * Customized element type for item element. This element will get {@link CustomItemComponentProps} as props. - * @defaultValue "div" - */ - itemElement?: CustomItemComponentOrElement; + components?: { + /** + * Component for scrollable element. This component will get {@link CustomViewportComponentProps} as props. + * @defaultValue {@link DefaultViewport} + */ + Root?: CustomViewportComponent; + /** + * Component or element type for item element. This component will get {@link CustomItemComponentProps} as props. + * @defaultValue "div" + */ + Item?: CustomItemComponentOrElement; + }; /** * Callback invoked when scrolling stops. */ @@ -117,11 +122,16 @@ export const WVList = forwardRef( initialItemCount, horizontal: horizontalProp, cache, - element: Window = DefaultWindow, - itemElement = "div", + components: { + Root: Viewport = DefaultViewport, + Item: ItemElement = "div", + } = emptyComponents as { + Root?: CustomViewportComponent; + Item?: CustomItemComponentOrElement; + }, onScrollStop: onScrollStopProp, onRangeChange: onRangeChangeProp, - ...windowAttrs + ...viewportAttrs }, ref ): ReactElement => { @@ -229,7 +239,7 @@ export const WVList = forwardRef( _resizer={resizer} _store={store} _index={i} - _element={itemElement as "div"} + _element={ItemElement as "div"} _children={e} _isHorizontal={isHorizontal} _isRtl={false} @@ -241,14 +251,14 @@ export const WVList = forwardRef( }, [elements, overscanedStartIndex, overscanedEndIndex]); return ( - ({ - ...windowAttrs, + ...viewportAttrs, style: { overflow: "visible", display: isHorizontal ? "inline-block" : "block", @@ -261,14 +271,14 @@ export const WVList = forwardRef( height: isHorizontal ? "100%" : "auto", padding: 0, margin: 0, - ...windowAttrs.style, + ...viewportAttrs.style, }, }), - values(windowAttrs) + values(viewportAttrs) )} > {items} - + ); } ); diff --git a/src/react/index.ts b/src/react/index.ts new file mode 100644 index 000000000..d40cf32c4 --- /dev/null +++ b/src/react/index.ts @@ -0,0 +1,17 @@ +export { VList } from "./VList"; +export type { VListProps, VListHandle, ScrollMode } from "./VList"; +export { VGrid } from "./VGrid"; +export type { + VGridProps, + VGridHandle, + CustomCellComponent, + CustomCellComponentProps, +} from "./VGrid"; +export { WVList } from "./WVList"; +export type { WVListProps, WVListHandle } from "./WVList"; +export type { + ViewportComponentAttributes, + CustomViewportComponent, + CustomViewportComponentProps, +} from "./Viewport"; +export type { CustomItemComponent, CustomItemComponentProps } from "./ListItem"; diff --git a/src/react/utils.ts b/src/react/utils.ts index ed3651ef2..91544e431 100644 --- a/src/react/utils.ts +++ b/src/react/utils.ts @@ -3,6 +3,8 @@ import { exists } from "../core/utils"; export const refKey = "current"; +export const emptyComponents = {}; + export const flattenChildren = (children: ReactNode) => { const arr: (ReactElement | ReactFragment | string | number)[] = []; Children.forEach(children, (e) => { diff --git a/stories/advanced/PullToRefresh.stories.tsx b/stories/advanced/PullToRefresh.stories.tsx index bc2b816aa..bc56c6c05 100644 --- a/stories/advanced/PullToRefresh.stories.tsx +++ b/stories/advanced/PullToRefresh.stories.tsx @@ -1,5 +1,5 @@ import { Meta, StoryObj } from "@storybook/react"; -import { CustomWindowComponentProps, VList } from "../../src"; +import { CustomViewportComponentProps, VList } from "../../src"; import React, { createContext, forwardRef, @@ -20,7 +20,7 @@ const RefreshContext = createContext(async () => {}); const listStyle = { width: 400, height: 600 }; -const Window = forwardRef( +const Viewport = forwardRef( ({ children, attrs, height }, ref) => { const onRefresh = useContext(RefreshContext); @@ -56,7 +56,7 @@ export const Default: StoryObj = { setItems(refreshItems()); }, [])} > - + {items.map((d) => { return (
(({ children, height, attrs }, ref) => { const [headerHeight, setHeaderHeight] = useState(0); const headerRef = useRef(null); @@ -89,8 +89,7 @@ export const Table: StoryObj = { background: "#fff", overflow: "auto", }} - element={TableList} - itemElement="tr" + components={{ Root: TableList, Item: "tr" }} > {Array.from({ length: 1000 }).map((_, i) => ( diff --git a/stories/advanced/With react-select.stories.tsx b/stories/advanced/With react-select.stories.tsx index c50cc8935..e585236d8 100644 --- a/stories/advanced/With react-select.stories.tsx +++ b/stories/advanced/With react-select.stories.tsx @@ -1,7 +1,7 @@ import { Meta, StoryObj } from "@storybook/react"; import { CustomItemComponentProps, - CustomWindowComponentProps, + CustomViewportComponentProps, VList, VListHandle, } from "../../src"; @@ -44,7 +44,7 @@ const OptionContext = createContext<{ ref: Ref; }>(null!); -const Window = forwardRef( +const Viewport = forwardRef( ({ children, attrs, height }, ref) => { const { maxHeight, innerProps, innerRef } = useContext(MenuListContext); return ( @@ -91,7 +91,7 @@ const MenuList = ({ children, ...rest }: MenuListProps) => { return ( - + {children} diff --git a/stories/advanced/Zoomable.stories.tsx b/stories/advanced/Zoomable.stories.tsx index 9545888c6..96557689f 100644 --- a/stories/advanced/Zoomable.stories.tsx +++ b/stories/advanced/Zoomable.stories.tsx @@ -65,7 +65,7 @@ export const Default: StoryObj = { }} > - + {Array.from({ length: 1000 }).map((_, i) => { return (
( +const UlList = forwardRef( ({ children, attrs, height }, ref) => { return (
@@ -573,8 +573,7 @@ export const Ul: StoryObj = { flex: 1, background: "#fff", }} - element={UlList} - itemElement={Li} + components={{ Root: UlList, Item: Li }} overscan={20} > {Array.from({ length: 1000 }).map((_, i) => i)}