virtua 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![npm](https://img.shields.io/npm/v/virtua) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/virtua) ![npm](https://img.shields.io/npm/dw/virtua) [![check](https://github.com/inokawa/virtua/actions/workflows/check.yml/badge.svg)](https://github.com/inokawa/virtua/actions/workflows/check.yml) [![demo](https://github.com/inokawa/virtua/actions/workflows/demo.yml/badge.svg)](https://github.com/inokawa/virtua/actions/workflows/demo.yml)
4
4
 
5
- A zero-config, fast and small (3kB) virtual list component for [React](https://github.com/facebook/react).
5
+ A zero-config, fast and small (~3kB) virtual list and grid component for [React](https://github.com/facebook/react).
6
6
 
7
7
  If you want to check the difference with the alternatives right away, [see comparison section](#comparison).
8
8
 
@@ -12,9 +12,9 @@ This project is a challenge to rethink virtualization. The goals are...
12
12
 
13
13
  - **Minimal setup:** This library is designed to give the best performance with no configuration, not like alternatives, and also it handles common hard things in the real world (dynamic size measurement, scroll position adjustment in bottom-up scrolling and imperative scrolling, etc).
14
14
  - **Fast:** Scrolling without frame drop needs optimization in many aspects (reduce CPU usage, reduce GC, [reduce layout recalculation](https://gist.github.com/paulirish/5d52fb081b3570c81e3a), optimize for frameworks, etc). We are trying to combine the best of them.
15
- - **Small:** Its bundle size should be small as much as possible to be friendly with modern web development. Currently [about 3kB gzipped](https://bundlephobia.com/package/virtua).
15
+ - **Small:** Its bundle size should be small as much as possible to be friendly with modern web development. Currently each components are ~3kB gzipped and the total is [~4kB gzipped](https://bundlephobia.com/package/virtua).
16
16
  - **Flexible:** Aiming to support many usecases - fixed size, dynamic size, horizontal scrolling, reverse scrolling, rtl direction, sticky, infinite scrolling, placeholder, scrollTo, dnd, table, and more. See [live demo](#demo).
17
- - **Framework agnostic (WIP):** Currently only for React but we could support Vue, Svelte, Solid, Web Components and more in the future.
17
+ - **Framework agnostic (WIP):** Currently only for [React](https://react.dev/) but we could support [Vue](https://vuejs.org/), [Svelte](https://svelte.dev/), [Solid](https://www.solidjs.com/), [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) and more in the future.
18
18
 
19
19
  ## Demo
20
20
 
@@ -32,8 +32,12 @@ npm install virtua
32
32
 
33
33
  If you use ESM and webpack 5, use react >= 18 to avoid [Can't resolve `react/jsx-runtime` error](https://github.com/facebook/react/issues/20235).
34
34
 
35
+ If you use this lib in [legacy browsers which does not have ResizeObserver](https://caniuse.com/?search=resizeobserver), you should use [polyfill](https://github.com/juggle/resize-observer#switching-between-native-and-polyfilled-versions).
36
+
35
37
  ## Usage
36
38
 
39
+ ### Vertical scroll
40
+
37
41
  ```tsx
38
42
  import { VList } from "virtua";
39
43
 
@@ -57,6 +61,55 @@ export const App = () => {
57
61
  };
58
62
  ```
59
63
 
64
+ ### Horizontal scroll
65
+
66
+ ```tsx
67
+ import { VList } from "virtua";
68
+
69
+ export const App = () => {
70
+ return (
71
+ <VList style={{ height: 400 }} horizontal>
72
+ {Array.from({ length: 1000 }).map((_, i) => (
73
+ <div
74
+ key={i}
75
+ style={{
76
+ width: Math.floor(Math.random() * 10) * 10 + 10,
77
+ borderRight: "solid 1px gray",
78
+ background: "white",
79
+ }}
80
+ >
81
+ {i}
82
+ </div>
83
+ ))}
84
+ </VList>
85
+ );
86
+ };
87
+ ```
88
+
89
+ ### Vertical and horizontal scroll
90
+
91
+ ```tsx
92
+ import { VGrid } from "virtua";
93
+
94
+ export const App = () => {
95
+ return (
96
+ <VGrid style={{ height: 800 }} row={1000} col={500}>
97
+ {({ rowIndex, colIndex }) => (
98
+ <div
99
+ style={{
100
+ width: ((colIndex % 3) + 1) * 100,
101
+ border: "solid 1px gray",
102
+ background: "white",
103
+ }}
104
+ >
105
+ {rowIndex} / {colIndex}
106
+ </div>
107
+ )}
108
+ </VGrid>
109
+ );
110
+ };
111
+ ```
112
+
60
113
  And see [examples](./stories) for more usages.
61
114
 
62
115
  ## Documentation
@@ -71,20 +124,21 @@ WIP
71
124
 
72
125
  ### Features
73
126
 
74
- | | [virtua](https://github.com/inokawa/virtua) | [react-virtuoso](https://github.com/petyosi/react-virtuoso) | [react-virtualized](https://github.com/bvaughn/react-virtualized) | [react-window](https://github.com/bvaughn/react-window) | [@tanstack/react-virtual](https://github.com/TanStack/virtual) | [react-cool-virtual](https://github.com/wellyshen/react-cool-virtual) |
75
- | :------------------------------------------------- | :------------------------------------------------------- | :---------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------ | :-------------------------------------------------------------------- |
76
- | Bundle size | [3.1kB gzipped](https://bundlephobia.com/package/virtua) | [16.3kB gzipped](https://bundlephobia.com/package/react-virtuoso) | [27.3kB gzipped](https://bundlephobia.com/package/react-virtualized) | [6.4kB gzipped](https://bundlephobia.com/package/react-window) | [2.3kB gzipped](https://bundlephobia.com/package/@tanstack/react-virtual) | [3.1kB gzipped](https://bundlephobia.com/package/react-cool-virtual) |
77
- | Vertical scroll | ✅ | ✅ | ✅ | ✅ | 🟠 (needs customization) | 🟠 (needs customization) |
78
- | Horizontal scroll | ✅ | ✅ | ✅ | ✅ | 🟠 (needs customization) | 🟠 (needs customization) |
79
- | Grid | | | ✅ | ✅ | 🟠 (needs customization) | 🟠 (needs customization) |
80
- | Table | 🟠 (needs customization) | ✅ | | 🟠 (needs customization) | 🟠 (needs customization) | 🟠 (needs customization) |
81
- | Window scroller | ❌ | ✅ | ✅ ([WindowScroller](https://github.com/bvaughn/react-virtualized/blob/master/docs/WindowScroller.md)) | ❌ | ✅ | ❌ |
82
- | Dynamic list size | ✅ | ✅ | 🟠 (needs [AutoSizer](https://github.com/bvaughn/react-virtualized/blob/master/docs/AutoSizer.md)) | 🟠 (needs [AutoSizer](https://github.com/bvaughn/react-virtualized/blob/master/docs/AutoSizer.md)) | ✅ | ✅ |
83
- | Dynamic item size | ✅ | ✅ | 🟠 (needs [CellMeasurer](https://github.com/bvaughn/react-virtualized/blob/master/docs/CellMeasurer.md) and has wrong destination when scrolling to item imperatively) | 🟠 (needs additional codes and has wrong destination when scrolling to item imperatively) | 🟠 (has wrong destination when scrolling to item imperatively) | 🟠 (has wrong destination when scrolling to item imperatively) |
84
- | Reverse scroll | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
85
- | Infinite scroll | ✅ | ✅ | 🟠 (needs [InfiniteLoader](https://github.com/bvaughn/react-virtualized/blob/master/docs/InfiniteLoader.md)) | 🟠 (needs [react-window-infinite-loader](https://github.com/bvaughn/react-window-infinite-loader)) | ✅ | ✅ |
86
- | RTL | ✅ | ❌ | ✅ | | ❌ | ❌ |
87
- | Display exceeding browser's max element size limit | | | ✅ | | | |
127
+ | | [virtua](https://github.com/inokawa/virtua) | [react-virtuoso](https://github.com/petyosi/react-virtuoso) | [react-window](https://github.com/bvaughn/react-window) | [react-virtualized](https://github.com/bvaughn/react-virtualized) | [@tanstack/react-virtual](https://github.com/TanStack/virtual) | [react-cool-virtual](https://github.com/wellyshen/react-cool-virtual) |
128
+ | :------------------------------------------------- | :------------------------------------------------------- | :---------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------ | :-------------------------------------------------------------------- |
129
+ | Bundle size | [4.2kB gzipped](https://bundlephobia.com/package/virtua) | [16.3kB gzipped](https://bundlephobia.com/package/react-virtuoso) | [6.4kB gzipped](https://bundlephobia.com/package/react-window) | [27.3kB gzipped](https://bundlephobia.com/package/react-virtualized) | [2.3kB gzipped](https://bundlephobia.com/package/@tanstack/react-virtual) | [3.1kB gzipped](https://bundlephobia.com/package/react-cool-virtual) |
130
+ | Vertical scroll | ✅ | ✅ | ✅ | ✅ | 🟠 (needs customization) | 🟠 (needs customization) |
131
+ | Horizontal scroll | ✅ | ✅ | ✅ | ✅ | 🟠 (needs customization) | 🟠 (needs customization) |
132
+ | Grid (Virtualization for two dimension) | | | ✅ (FixedSizeGrid / VariableSizeGrid) | ✅ ([Grid](https://github.com/bvaughn/react-virtualized/blob/master/docs/Grid.md)) | 🟠 (needs customization) | 🟠 (needs customization) |
133
+ | Table | 🟠 (needs customization) | ✅ (TableVirtuoso) | 🟠 (needs customization) | ✅ ([Table](https://github.com/bvaughn/react-virtualized/blob/master/docs/Table.md)) | 🟠 (needs customization) | 🟠 (needs customization) |
134
+ | Window scroller | ❌ | ✅ | ❌ | ✅ ([WindowScroller](https://github.com/bvaughn/react-virtualized/blob/master/docs/WindowScroller.md)) | ✅ | ❌ |
135
+ | Dynamic list size | ✅ | ✅ | 🟠 (needs [AutoSizer](https://github.com/bvaughn/react-virtualized/blob/master/docs/AutoSizer.md)) | 🟠 (needs [AutoSizer](https://github.com/bvaughn/react-virtualized/blob/master/docs/AutoSizer.md)) | ✅ | ✅ |
136
+ | Dynamic item size | ✅ | ✅ | 🟠 (needs additional codes and has wrong destination when scrolling to item imperatively) | 🟠 (needs [CellMeasurer](https://github.com/bvaughn/react-virtualized/blob/master/docs/CellMeasurer.md) and has wrong destination when scrolling to item imperatively) | 🟠 (has wrong destination when scrolling to item imperatively) | 🟠 (has wrong destination when scrolling to item imperatively) |
137
+ | Reverse scroll | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
138
+ | Infinite scroll | ✅ | ✅ | 🟠 (needs [react-window-infinite-loader](https://github.com/bvaughn/react-window-infinite-loader)) | 🟠 (needs [InfiniteLoader](https://github.com/bvaughn/react-virtualized/blob/master/docs/InfiniteLoader.md)) | ✅ | ✅ |
139
+ | RTL | ✅ | ❌ | ✅ | | ❌ | ❌ |
140
+ | SSR support | | | ✅ | | | |
141
+ | Display exceeding browser's max element size limit | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
88
142
 
89
143
  - ✅ - Built-in supported
90
144
  - 🟠 - Supported but partial, limited or requires some user custom code
@@ -0,0 +1 @@
1
+ export declare const hasNegativeOffsetInRtl: (scrollable: HTMLElement) => boolean;
@@ -0,0 +1,13 @@
1
+ import { VirtualStore } from "./store";
2
+ export declare const createResizer: (store: VirtualStore) => {
3
+ _observeRoot(root: HTMLElement): () => void;
4
+ _observeItem(el: HTMLElement, i: number): () => void;
5
+ _isJustResized(): boolean;
6
+ };
7
+ export type Resizer = ReturnType<typeof createResizer>;
8
+ export declare const createGridResizer: (vStore: VirtualStore, hStore: VirtualStore) => {
9
+ _observeRoot(root: HTMLElement): () => void;
10
+ _observeItem(el: HTMLElement, rowIndex: number, colIndex: number): () => void;
11
+ _isJustResized(horizontal?: boolean): boolean;
12
+ };
13
+ export type GridResizer = ReturnType<typeof createGridResizer>;
@@ -1,14 +1,9 @@
1
1
  import { ScrollJump, VirtualStore } from "./store";
2
- export declare const SCROLL_STOP = 0;
3
- export declare const SCROLL_DOWN = 1;
4
- export declare const SCROLL_UP = 2;
5
- export declare const SCROLL_MANUAL = 3;
6
2
  export type Scroller = {
7
3
  _initRoot: (rootElement: HTMLElement) => () => void;
8
- _initItem: (itemElement: HTMLElement, index: number) => () => void;
9
4
  _getActualScrollSize: () => number;
10
5
  _scrollTo: (offset: number) => void;
11
6
  _scrollToIndex: (index: number, count: number) => void;
12
7
  _fixScrollJump: (jump: ScrollJump, startIndex: number) => void;
13
8
  };
14
- export declare const createScroller: (store: VirtualStore, emitScrollOffsetChange: (offset: number) => void, emitScrollStateChange: (scrolling: boolean) => void) => Scroller;
9
+ export declare const createScroller: (store: VirtualStore, isJustResized: () => boolean) => Scroller;
@@ -1,21 +1,23 @@
1
- export type ScrollJump = Readonly<[index: number, sizeDiff: number][]>;
1
+ type ItemJump = [sizeDiff: number, index: number];
2
+ export type ScrollJump = Readonly<ItemJump[]>;
2
3
  export type ItemResize = [index: number, size: number];
3
4
  type ItemsRange = [startIndex: number, endIndex: number];
4
- export declare const ACTION_UPDATE_ITEM_SIZES = 1;
5
- export declare const ACTION_UPDATE_VIEWPORT = 2;
6
- export declare const ACTION_HANDLE_SCROLL = 3;
7
- type Actions = [type: typeof ACTION_UPDATE_ITEM_SIZES, entries: ItemResize[]] | [
8
- type: typeof ACTION_UPDATE_VIEWPORT,
9
- rect: {
10
- _width: number;
11
- _height: number;
12
- }
13
- ] | [type: typeof ACTION_HANDLE_SCROLL, offset: number];
5
+ export declare const SCROLL_STOP = 0;
6
+ export declare const SCROLL_DOWN = 1;
7
+ export declare const SCROLL_UP = 2;
8
+ export declare const SCROLL_MANUAL = 3;
9
+ type ScrollDirection = typeof SCROLL_STOP | typeof SCROLL_DOWN | typeof SCROLL_UP | typeof SCROLL_MANUAL;
10
+ export declare const ACTION_ITEM_RESIZE = 1;
11
+ export declare const ACTION_WINDOW_RESIZE = 2;
12
+ export declare const ACTION_SCROLL = 3;
13
+ export declare const ACTION_MANUAL_SCROLL = 4;
14
+ type Actions = [type: typeof ACTION_ITEM_RESIZE, entries: ItemResize[]] | [type: typeof ACTION_WINDOW_RESIZE, size: number] | [type: typeof ACTION_SCROLL, offset: number] | [type: typeof ACTION_MANUAL_SCROLL, offset: number];
14
15
  export type VirtualStore = {
15
16
  _getRange(): ItemsRange;
16
17
  _isUnmeasuredItem(index: number): boolean;
17
18
  _hasUnmeasuredItemsInRange(startIndex: number): boolean;
18
19
  _getItemOffset(index: number): number;
20
+ _getItemSize(index: number): number;
19
21
  _getScrollOffset(): number;
20
22
  _getViewportSize(): number;
21
23
  _getScrollSize(): number;
@@ -26,7 +28,9 @@ export type VirtualStore = {
26
28
  _waitForScrollDestinationItemsMeasured(): Promise<void>;
27
29
  _subscribe(cb: () => void): () => void;
28
30
  _update(...action: Actions): void;
31
+ _getScrollDirection(): ScrollDirection;
32
+ _setScrollDirection(direction: ScrollDirection): void;
29
33
  _updateCacheLength(length: number): void;
30
34
  };
31
- export declare const createVirtualStore: (itemCount: number, itemSize: number, isHorizontal: boolean, isRtl: boolean) => VirtualStore;
35
+ export declare const createVirtualStore: (itemCount: number, itemSize: number, isHorizontal: boolean, isRtl: boolean, initialItemCount: number | undefined, onScrollStateChange: (scrolling: boolean) => void, onScrollOffsetChange: (offset: number) => void) => VirtualStore;
32
36
  export {};
@@ -1,6 +1,5 @@
1
1
  export declare const min: (...values: number[]) => number;
2
2
  export declare const max: (...values: number[]) => number;
3
- export declare const abs: (x: number) => number;
4
3
  export declare const now: () => number;
5
4
  export declare const exists: <T>(v: T) => v is Exclude<T, null | undefined>;
6
5
  export declare const range: <T>(length: number, cb: (i: number) => T) => T[];
@@ -9,3 +8,4 @@ export declare const debounce: <T extends (...args: any[]) => void>(fn: T, ms: n
9
8
  _cancel: () => void;
10
9
  };
11
10
  export declare const throttle: <T extends (...args: any[]) => void>(fn: T, ms: number) => (...args: Parameters<T>) => void;
11
+ export declare const once: <F extends (...args: any[]) => any>(fn: F) => F;
package/lib/index.d.ts CHANGED
@@ -1,2 +1,5 @@
1
1
  export { VList } from "./react/VList";
2
- export type { VListProps, VListHandle, CustomItemComponent, CustomItemComponentProps, CustomWindowComponent, CustomWindowComponentProps, WindowComponentAttributes, } from "./react/VList";
2
+ export type { VListProps, VListHandle, CustomItemComponent, CustomItemComponentProps, CustomWindowComponent, CustomWindowComponentProps, } from "./react/VList";
3
+ export { VGrid } from "./react/VGrid";
4
+ export type { VGridProps, VGridHandle, CustomCellComponent, CustomCellComponentProps, CustomGridWindowComponent, CustomGridWindowComponentProps, } from "./react/VGrid";
5
+ export type { WindowComponentAttributes } from "./react/types";
package/lib/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var e=require("react/jsx-runtime"),t=require("react"),r=require("use-sync-external-store/shim/index.js");const n=Math.min,o=Math.max,s=Math.abs,l=Date.now,i=e=>null!=e,c=(e,t)=>Array.from({length:e},((e,r)=>t(r))),u=(e,t)=>{const r=e.t[t];return-1===r?e.o:r},a=(e,t,r)=>{if(!e.l)return 0;if(e.i>=t)return r?e.u[t]+u(e,t):e.u[t];let n=e.i,o=e.u[n];for(;n<=t&&(e.u[n]=o,n!==t||r);)o+=u(e,n),n++;return e.i=t,o},d=(e,t)=>a(e,t),_=(e,t,r)=>{let s=0;if(r>=0)for(;t<e.l-1;){const n=u(e,t++);if((s+=n)>=r){s-n/2>=r&&t--;break}}else for(;t>0;){const n=u(e,--t);if((s-=n)<=r){s+n/2<r&&t++;break}}return n(o(t,0),e.l-1)},f=(e,t,r,n)=>_(e,r,t-n),h=_,g=(e,t,r)=>({o:t,l:e,i:r?n(r.i,e-1):0,t:c(e,(e=>{const t=r&&r.t[e];return i(t)?t:-1})),u:c(e,(e=>{if(0===e)return 0;const t=r&&r.u[e];return i(t)?t:-1}))}),m="undefined"!=typeof window?t.useLayoutEffect:t.useEffect,w=(e,t)=>r.useSyncExternalStore(e,t,t),S="current",p=e=>{const r=t.useRef();return r[S]||(r[S]=e())},v=e=>{const r=t.useRef(e);return m((()=>{r[S]=e}),[e]),r},z=t.memo((({_:r,h:n,g:o,m:s,S:l})=>{const i=t.useRef(null),c=w(o.p,(()=>o.v(s))),u=w(o.p,(()=>o.I(s)));return m((()=>n.T(i[S],s)),[s]),e.jsx(l,{ref:i,style:t.useMemo((()=>{const e=o.R(),t=o.M()?"right":"left",r={margin:0,padding:0,position:"absolute",[e?"height":"width"]:"100%",[e?"top":t]:0,[e?t:"top"]:c,visibility:u?"hidden":"visible"};return e&&(r.display="flex"),r}),[c,u]),children:r})})),x=t.forwardRef((({children:r,scrollSize:n,scrolling:o,horizontal:s,attrs:l},i)=>e.jsx("div",{ref:i,...l,children:e.jsx("div",{style:t.useMemo((()=>({position:"relative",visibility:"hidden",width:s?n:"100%",height:s?"100%":n,pointerEvents:o?"none":"auto"})),[n,o]),children:r})}))),y=({_:r,O:n,g:o,S:s,k:l,q:i})=>{const c=w(o.p,o.j),u=o.R();return e.jsx(s,{ref:n,scrollSize:c,scrolling:l,horizontal:u,attrs:t.useMemo((()=>({...i,style:{overflow:u?"auto hidden":"hidden auto",contain:"strict",width:"100%",height:"100%",padding:0,margin:0,...i.style}})),[i]),children:r})},I=t.forwardRef((({children:r,itemSize:c=40,overscan:_=4,horizontal:I,rtl:b,element:T=x,itemElement:R="div",onScroll:M,onScrollStop:O,onRangeChange:k,...q},j)=>{const A=t.useMemo((()=>{const e=[];return t.Children.forEach(r,(t=>{(e=>!i(e)||"boolean"==typeof e)(t)||e.push(t)})),e}),[r]),C=A.length,D=p((()=>((e,t,r,o)=>{let s,l=0,i=0,c=0,_=[],m=g(e,t),w=[0,0];const S=new Set,p=()=>r?l:i;return{A(){const[e,t]=w,r=d(m,e),n=f(m,c,e,r),o=h(m,n,p());return e===n&&t===o?w:w=[n,o]},I:e=>-1===m.t[e],C:e=>((e,t,r)=>{for(let n=t;n<=r;n++)if(-1===e.t[n])return!0;return!1})(m,e,h(m,e,p())),v:e=>d(m,e),D:()=>c,F:()=>p(),j:()=>(e=>a(e,e.l-1,!0))(m),J:()=>_,R:()=>r,M:()=>o,L:e=>f(m,e,0,0),P:()=>(s&&s[1](),new Promise(((e,t)=>{s=[()=>{Promise.resolve().then((()=>{e(),s=void 0}))},t]}))),p:e=>(S.add(e),()=>{S.delete(e)}),U(e,t){const r=(()=>{switch(e){case 1:{const e=t.filter((([e,t])=>m.t[e]!==t));if(!e.length)return!1;const r=[];return e.forEach((([e,t])=>{r.push([e,t-u(m,e)]),((e,t,r)=>{e.t[t]=r,e.i=n(t,e.i)})(m,e,t)})),_=r,!0}case 2:return(l!==t.B||i!==t.H)&&(l=t.B,i=t.H,!0);case 3:{const e=c;return(c=t)!==e}}})();r&&(S.forEach((e=>{e()})),s&&1===e&&s[0]())},V(e){m.l!==e&&(m=g(e,t,m))}}})(C,c,!!I,!!b)));D.V(C);const[E,F]=w(D.p,D.A),J=w(D.p,D.J),L=t.useRef(null),P=v(M),U=v(O),[B,H]=t.useState(new Set),[V,W]=t.useState(!1),G=p((()=>((e,t,r)=>{let c,u,a,d=-1,_=0,f=!1;const h=e.R(),g=e.M(),m=h?"scrollLeft":"scrollTop",w=new WeakMap,S=()=>a||(a=new ResizeObserver((t=>{const r=[];for(const n of t)if(n.target===u)e.U(2,{B:n.contentRect.width,H:n.contentRect.height});else{const e=w.get(n.target);i(e)&&r.push([e,n.contentRect[h?"width":"height"]])}r.length&&(e.U(1,r),f=!0)}))),p=()=>u?e.R()?u.scrollWidth:u.scrollHeight:0,v=(e,t)=>{if(u){if(g){if(!i(c)){const e=u[m];u[m]=1,c=0===u[m],u[m]=e}c&&(e*=-1)}t?u[m]+=e:(u[m]=e,_=3)}},z=async(t,r)=>{const n=()=>{let t=r();const n=p(),o=e.F();return n-(t+o)<=0&&(t=n-o),t};if(e.C(t)){do{e.U(3,n());try{await e.P()}catch(e){return}}while(e.C(t));v(n())}else{const t=n();v(t),e.U(3,t)}},x=e=>e.reduce(((e,[,t])=>e+t),0);return{W(n){u=n;const o=S(),c=()=>{let r=n[m];g&&(r=s(r)),d!==r&&(0!==_&&f?f=!1:3!==_&&(_=d>r?2:1),e.U(3,d=r),t(r))},a=(()=>{let e;const t=()=>{i(e)&&clearTimeout(e)},n=()=>{t(),e=setTimeout((()=>{e=null,c(),_=0,r(!1)}),150)};return n.G=t,n})(),w=()=>{const e=0===_;c(),e&&r(!0),a()},p=(()=>{let t=l()-50;return(...r)=>{const n=l();t+50<n&&(t=n,(t=>{0!==_&&(t.ctrlKey||(h?t.deltaX:t.deltaY)&&d>0&&d<e.j()-e.F()&&a())})(...r))}})();return o.observe(n),n.addEventListener("scroll",w),n.addEventListener("wheel",p,{passive:!0}),()=>{o.disconnect(),n.removeEventListener("scroll",w),n.removeEventListener("wheel",p),a.G()}},T(e,t){const r=S();return w.set(e,t),r.observe(e),()=>{w.delete(e),r.unobserve(e)}},K:p,N(t){t=o(t,0),z(e.L(t),(()=>t))},X(t,r){t=o(n(t,r-1),0),z(t,(()=>e.v(t)))},Y:(t,r)=>{if(2===_){const e=x(t);e&&v(e,!0)}else if(3===_){const n=e.D();if(0===n);else{const o=x(t);if(e.j()-(n+e.F()+o)<=0)o&&v(n+o);else{const e=t.reduce(((e,[t,n])=>(t<r&&(e+=n),e)),0);e&&v(e,!0)}}}}}})(D,(e=>{P[S]&&P[S](e)}),(e=>{W(e),e||(H(new Set),U[S]&&U[S]())}))));m((()=>G.W(L[S])),[]),m((()=>{J.length&&G.Y(J,E)}),[J]),t.useEffect((()=>{k&&k({start:E,end:F,count:C})}),[E,F]),t.useImperativeHandle(j,(()=>({get scrollOffset(){return D.D()},get scrollSize(){return G.K()},get viewportSize(){return D.F()},scrollToIndex(e){G.X(e,C)},scrollTo:G.N,scrollBy(e){G.N(D.D()+e)}})),[C]);const K=o(E-_,0),N=n(F+_,C-1),Q=t.useMemo((()=>{const t=[];for(let e=K;e<=N;e++)B.add(e);return B.forEach((r=>{const n=A[r];i(n)&&t.push(e.jsx(z,{h:G,g:D,m:r,S:R,_:n},(null==n?void 0:n.key)||r))})),t}),[A,B,K,N]);return e.jsx(y,{O:L,g:D,S:T,k:V,_:Q,q})}));exports.VList=I;
1
+ var e=require("react/jsx-runtime"),t=require("react"),r=require("use-sync-external-store/shim/index.js");const n=Math.min,o=Math.max,i=Date.now,l=e=>null!=e,s=(e,t)=>Array.from({length:e},((e,r)=>t(r))),c=e=>{let t,r;return(...n)=>(t||(t=!0,r=e(...n)),r)},u=(e,t)=>{const r=e.t[t];return-1===r?e.o:r},d=(e,t,r)=>{if(!e.i)return 0;if(e.l>=t)return r?e.u[t]+u(e,t):e.u[t];let n=e.l,o=e.u[n];for(;n<=t&&(e.u[n]=o,n!==t||r);)o+=u(e,n),n++;return e.l=t,o},a=(e,t)=>d(e,t),_=(e,t,r)=>{let i=0;if(r>=0)for(;t<e.i-1;){const n=u(e,t++);if((i+=n)>=r){i-n/2>=r&&t--;break}}else for(;t>0;){const n=u(e,--t);if((i-=n)<=r){i+n/2<r&&t++;break}}return n(o(t,0),e.i-1)},h=(e,t,r,n)=>_(e,r,t-n),f=_,g=(e,t,r)=>({o:t,i:e,l:r?n(r.l,e-1):0,t:s(e,(e=>{const t=r&&r.t[e];return l(t)?t:-1})),u:s(e,(e=>{if(0===e)return 0;const t=r&&r.u[e];return l(t)?t:-1}))}),m=(e,t,r,i,l=0,s,c)=>{let _,m=t*o(l-1,0),w=0,S=[],v=g(e,t),p=0,z=[0,l];const I=new Set;return{_(){const[e,t]=z,r=a(v,e),n=h(v,w,e,r),o=f(v,n,m);return e===n&&t===o?z:z=[n,o]},h:e=>-1===v.t[e],g:e=>((e,t,r)=>{for(let n=t;n<=r;n++)if(-1===e.t[n])return!0;return!1})(v,e,f(v,e,m)),m:e=>a(v,e),S:e=>u(v,e),v:()=>w,p:()=>m,I:()=>(e=>d(e,e.i-1,!0))(v),R:()=>S,T:()=>r,M:()=>i,C:e=>h(v,e,0,0),O:()=>(_&&_[1](),new Promise(((e,t)=>{_=[()=>{Promise.resolve().then((()=>{e(),_=void 0}))},t]}))),W:e=>(I.add(e),()=>{I.delete(e)}),H(e,t){const r=(()=>{switch(e){case 1:{const e=t.filter((([e,t])=>v.t[e]!==t));if(!e.length)return!1;const r=[];return e.forEach((([e,t])=>{r.push([t-u(v,e),e]),((e,t,r)=>{e.t[t]=r,e.l=n(t,e.l)})(v,e,t)})),S=r,!0}case 2:return m!==t&&(m=t,!0);case 3:case 4:{const e=w;return(w=t)!==e}}})();r&&(I.forEach((e=>{e()})),3===e?c(w):_&&1===e&&_[0]())},k:()=>p,D(e){const t=p;p=e,0===p?s(!1):0!==t||1!==p&&2!==p||s(!0)},J(e){v.i!==e&&(v=g(e,t,v))}}},w="undefined"!=typeof window?t.useLayoutEffect:t.useEffect,S=(e,t)=>r.useSyncExternalStore(e,t,t),v=c((e=>{const t="scrollLeft",r=e[t];e[t]=1;const n=e[t]<1;return e[t]=r,n})),p=(e,t)=>{let r;const s=e.T(),c=e.M(),u=s?"scrollLeft":"scrollTop",d=()=>r?s?r.scrollWidth:r.scrollHeight:0,a=(t,n)=>v(r)||n?-t:e.I()-e.p()-t,_=(t,n)=>{r&&(s&&c&&(t=a(t,n)),n?r[u]+=t:(r[u]=t,e.D(3)))},h=async(t,r)=>{const n=()=>{let t=r();const n=d(),o=e.p();return n-(t+o)<=0&&(t=n-o),t};if(e.g(t)){do{e.H(4,n());try{await e.O()}catch(e){return}}while(e.g(t));_(n())}else{const t=n();_(t),e.H(4,t)}},f=e=>e.reduce(((e,[t])=>e+t),0);return{$(n){r=n;const o=()=>{let r=n[u];s&&c&&(r=a(r));const o=e.v();if(o===r)return;const i=e.k(),l=t();0!==i&&l||3===i||e.D(o>r?2:1),e.H(3,r)},d=(()=>{let t;const r=()=>{l(t)&&clearTimeout(t)},n=()=>{r(),t=setTimeout((()=>{t=null,o(),e.D(0)}),150)};return n.q=r,n})(),_=()=>{o(),d()},h=(()=>{let t=i()-50;return(...r)=>{const n=i();t+50<n&&(t=n,(t=>{if(0!==e.k()&&!t.ctrlKey&&(s?t.deltaX:t.deltaY)){const t=e.v();t>0&&t<e.I()-e.p()&&d()}})(...r))}})();return n.addEventListener("scroll",_),n.addEventListener("wheel",h,{passive:!0}),()=>{n.removeEventListener("scroll",_),n.removeEventListener("wheel",h),d.q()}},L:d,j(t){t=o(t,0),h(e.C(t),(()=>t))},A(t,r){t=o(n(t,r-1),0),h(t,(()=>e.m(t)))},F:(t,r)=>{const n=e.k();if(2===n){const e=f(t);e&&_(e,!0)}else if(3===n){const n=e.v();if(0===n);else{const o=f(t);if(e.I()-(n+e.p()+o)<=0)o&&_(n+o);else{const e=t.reduce(((e,[t,n])=>(n<r&&(e+=t),e)),0);e&&_(e,!0)}}}}}},z="current",I=e=>{const r=t.useRef();return r[z]||(r[z]=e())},b=e=>{const r=t.useRef(e);return w((()=>{r[z]=e}),[e]),r},x=t.memo((({P:r,U:n,B:o,V:i,G:l})=>{const s=t.useRef(null),c=S(o.W,(()=>o.m(i))),u=S(o.W,(()=>o.h(i)));return w((()=>n.K(s[z],i)),[i]),e.jsx(l,{ref:s,style:t.useMemo((()=>{const e=o.T(),t=o.M()?"right":"left",r={margin:0,padding:0,position:"absolute",[e?"height":"width"]:"100%",[e?"top":t]:0,[e?t:"top"]:c,visibility:u?"hidden":"visible"};return e&&(r.display="flex"),r}),[c,u]),children:r})})),y=t.forwardRef((({children:r,scrollSize:n,scrolling:o,horizontal:i,attrs:l},s)=>e.jsx("div",{ref:s,...l,children:e.jsx("div",{style:t.useMemo((()=>({position:"relative",visibility:"hidden",width:i?n:"100%",height:i?"100%":n,pointerEvents:o?"none":"auto"})),[n,o]),children:r})}))),R=({P:r,N:n,B:o,G:i,X:l,Y:s})=>{const c=S(o.W,o.I),u=o.T();return e.jsx(i,{ref:n,scrollSize:c,scrolling:l,horizontal:u,attrs:t.useMemo((()=>({...s,style:{overflow:u?"auto hidden":"hidden auto",contain:"strict",width:"100%",height:"100%",padding:0,margin:0,...s.style}})),[s]),children:r})},T=t.forwardRef((({children:r,itemSize:i=40,overscan:s=4,initialItemCount:u,horizontal:d,rtl:a,element:_=y,itemElement:h="div",onScroll:f,onScrollStop:g,onRangeChange:v,...T},M)=>{const C=t.useMemo((()=>{const e=[];return t.Children.forEach(r,(t=>{(e=>!l(e)||"boolean"==typeof e)(t)||e.push(t)})),e}),[r]),O=C.length,W=b(f),H=b(g),[k,D]=t.useState(new Set),[E,J]=t.useState(!1),[$,q,L]=I((()=>{const e=m(O,i,!!d,!!a,u,(e=>{J(e),e||(D(new Set),H[z]&&H[z]())}),(e=>{W[z]&&W[z](e)})),t=(e=>{let t,r=!1;const n=e.T()?"width":"height",o=new WeakMap,i=c((()=>new ResizeObserver((i=>{const s=[];for(const{target:r,contentRect:c}of i)if(r===t)e.H(2,c[n]);else{const e=o.get(r);l(e)&&s.push([e,c[n]])}s.length&&(e.H(1,s),r=!0)}))));return{Z(e){t=e;const r=i();return r.observe(e),()=>{r.disconnect()}},K(e,t){const r=i();return o.set(e,t),r.observe(e),()=>{o.delete(e),r.unobserve(e)}},ee(){const e=r;return r=!1,e}}})(e);return[e,t,p(e,t.ee)]}));$.J(O);const[j,A]=S($.W,$._),F=S($.W,$.R),P=t.useRef(null);w((()=>{const e=P[z],t=q.Z(e),r=L.$(e);return()=>{t(),r()}}),[]),w((()=>{F.length&&L.F(F,j)}),[F]),t.useEffect((()=>{v&&v({start:j,end:A,count:O})}),[j,A]),t.useImperativeHandle(M,(()=>({get scrollOffset(){return $.v()},get scrollSize(){return L.L()},get viewportSize(){return $.p()},scrollToIndex(e){L.A(e,O)},scrollTo:L.j,scrollBy(e){L.j($.v()+e)}})),[O]);const U=o(j-s,0),B=n(A+s,O-1),V=t.useMemo((()=>{const t=[];for(let e=U;e<=B;e++)k.add(e);return k.forEach((r=>{const n=C[r];l(n)&&t.push(e.jsx(x,{U:q,B:$,V:r,G:h,P:n},(null==n?void 0:n.key)||r))})),t}),[C,k,U,B]);return e.jsx(R,{N:P,B:$,G:_,X:E,P:V,Y:T})})),M=(e,t)=>`${e}-${t}`,C=t.memo((({P:r,U:n,te:o,re:i,ne:l,oe:s,G:c})=>{const u=t.useRef(null),d=S(o.W,(()=>o.m(l))),a=S(i.W,(()=>i.m(s))),_=S(o.W,(()=>o.h(l))),h=S(i.W,(()=>i.h(s))),f=S(o.W,(()=>o.S(l))),g=S(i.W,(()=>i.S(s)));return w((()=>n.K(u[z],l,s)),[s,l]),e.jsx(c,{ref:u,style:t.useMemo((()=>({display:"grid",margin:0,padding:0,position:"absolute",top:d,[o.M()?"right":"left"]:a,visibility:_||h?"hidden":"visible",minHeight:f,minWidth:g})),[d,a,g,f,_,h]),children:r})})),O=t.forwardRef((({children:r,scrollWidth:n,scrollHeight:o,scrolling:i,attrs:l},s)=>e.jsx("div",{ref:s,...l,children:e.jsx("div",{style:t.useMemo((()=>({position:"relative",visibility:"hidden",width:n,height:o,pointerEvents:i?"none":"auto"})),[n,o,i]),children:r})}))),W=({P:r,N:n,ie:o,le:i,G:l,X:s,Y:c})=>{const u=S(o.W,o.I),d=S(i.W,i.I);return e.jsx(l,{ref:n,scrollWidth:d,scrollHeight:u,scrolling:s,attrs:t.useMemo((()=>({...c,style:{overflow:"auto",contain:"strict",width:"100%",height:"100%",padding:0,margin:0,...c.style}})),[c]),children:r})},H=t.forwardRef((({children:r,row:i,col:l,cellHeight:s=40,cellWidth:u=100,overscan:d=2,initialRowCount:a,initialColCount:_,rtl:h,element:f=O,cellElement:g="div",...v})=>{const[b,x]=t.useState(!1),[y,R]=t.useState(!1),[T,H,k,D,E]=I((()=>{const e=()=>{},t=m(i,s,!1,!!h,a,x,e),r=m(l,u,!0,!!h,_,R,e),n=((e,t)=>{let r,n=!1,i=!1;const l="height",s="width",u=new WeakMap,d=new Set,a=new Set,_=new Map,h=(e,t)=>`${e}-${t}`,f=c((()=>new ResizeObserver((c=>{const f=new Set,g=new Set;for(const{target:n,contentRect:o}of c)if(n===r)e.H(2,o[l]),t.H(2,o[s]);else{const e=u.get(n);if(e){const[t,r]=e,n=h(t,r),i=_.get(n),c=[o[l],o[s]];let u,d;i?(i[0]!==c[0]&&(u=!0),i[1]!==c[1]&&(d=!0)):u=d=!0,u&&f.add(t),d&&g.add(r),(u||d)&&_.set(n,c)}}if(f.size){const t=[];f.forEach((e=>{let r=0;a.forEach((t=>{const n=_.get(h(e,t));n&&(r=o(r,n[0]))})),r&&t.push([e,r])})),e.H(1,t),n=!0}if(g.size){const e=[];g.forEach((t=>{let r=0;d.forEach((e=>{const n=_.get(h(e,t));n&&(r=o(r,n[1]))})),r&&e.push([t,r])})),t.H(1,e),i=!0}}))));return{Z(e){r=e;const t=f();return t.observe(e),()=>{t.disconnect()}},K(e,t,r){const n=f();return u.set(e,[t,r]),d.add(t),a.add(r),n.observe(e),()=>{u.delete(e),n.unobserve(e)}},ee(e){const t=e?i:n;return e?i=!1:n=!1,t}}})(t,r);return[t,r,n,p(t,(()=>n.ee())),p(r,(()=>n.ee(!0)))]}));T.J(i),H.J(l);const[J,$]=S(T.W,T._),[q,L]=S(H.W,H._),j=S(T.W,T.R),A=S(H.W,H.R),F=t.useRef(null);w((()=>{const e=F[z],t=k.Z(e),r=D.$(e),n=E.$(e);return()=>{t(),r(),n()}}),[]),w((()=>{j.length&&D.F(j,J)}),[j]),w((()=>{A.length&&E.F(A,q)}),[A]);const P=t.useMemo((()=>{const e=new Map;return(t,n)=>{let o=e.get(M(t,n));return o||e.set(M(t,n),o=r({rowIndex:t,colIndex:n})),o}}),[r]),U=o(J-d,0),B=n($+d,i-1),V=o(q-d,0),G=n(L+d,l-1),K=t.useMemo((()=>{const t=[];for(let r=U;r<=B;r++)for(let n=V;n<=G;n++)t.push(e.jsx(C,{U:k,te:T,re:H,ne:r,oe:n,G:g,P:P(r,n)},M(r,n)));return t}),[P,U,B,V,G]);return e.jsx(W,{N:F,ie:T,le:H,G:f,X:b||y,P:K,Y:v})}));exports.VGrid=H,exports.VList=T;
2
2
  //# sourceMappingURL=index.js.map