@mui/x-virtualizer 0.2.10 → 0.2.12

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +248 -0
  2. package/constants.d.ts +22 -0
  3. package/constants.js +26 -0
  4. package/esm/constants.d.ts +22 -0
  5. package/esm/constants.js +20 -0
  6. package/esm/features/colspan.d.ts +4 -4
  7. package/esm/features/dimensions.d.ts +14 -8
  8. package/esm/features/dimensions.js +26 -7
  9. package/esm/features/index.d.ts +1 -1
  10. package/esm/features/index.js +1 -1
  11. package/esm/features/keyboard.d.ts +3 -3
  12. package/esm/features/keyboard.js +1 -1
  13. package/esm/features/rowspan.d.ts +4 -4
  14. package/esm/features/virtualization/index.d.ts +2 -0
  15. package/esm/features/virtualization/index.js +2 -0
  16. package/esm/features/virtualization/layout.d.ts +129 -0
  17. package/esm/features/virtualization/layout.js +152 -0
  18. package/esm/features/{virtualization.d.ts → virtualization/virtualization.d.ts} +35 -58
  19. package/esm/features/{virtualization.js → virtualization/virtualization.js} +97 -134
  20. package/esm/index.d.ts +2 -1
  21. package/esm/index.js +3 -2
  22. package/esm/models/core.d.ts +7 -0
  23. package/esm/models/core.js +7 -0
  24. package/esm/models/dimensions.d.ts +8 -0
  25. package/esm/useVirtualizer.d.ts +25 -69
  26. package/esm/useVirtualizer.js +21 -4
  27. package/features/colspan.d.ts +4 -4
  28. package/features/dimensions.d.ts +14 -8
  29. package/features/dimensions.js +26 -7
  30. package/features/index.d.ts +1 -1
  31. package/features/keyboard.d.ts +3 -3
  32. package/features/rowspan.d.ts +4 -4
  33. package/features/virtualization/index.d.ts +2 -0
  34. package/features/virtualization/index.js +27 -0
  35. package/features/virtualization/layout.d.ts +129 -0
  36. package/features/virtualization/layout.js +163 -0
  37. package/features/{virtualization.d.ts → virtualization/virtualization.d.ts} +35 -58
  38. package/features/{virtualization.js → virtualization/virtualization.js} +97 -134
  39. package/index.d.ts +2 -1
  40. package/index.js +12 -1
  41. package/models/core.d.ts +7 -0
  42. package/models/core.js +8 -1
  43. package/models/dimensions.d.ts +8 -0
  44. package/package.json +2 -2
  45. package/useVirtualizer.d.ts +25 -69
  46. package/useVirtualizer.js +20 -3
@@ -11,9 +11,9 @@ import * as platform from '@mui/x-internals/platform';
11
11
  import { useRunOnce } from '@mui/x-internals/useRunOnce';
12
12
  import { createSelector, useStore, useStoreEffect } from '@mui/x-internals/store';
13
13
  import reactMajor from '@mui/x-internals/reactMajor';
14
- import { PinnedRows, PinnedColumns } from "../models/core.js";
15
- import { Dimensions, observeRootNode } from "./dimensions.js";
16
- import { ScrollDirection } from "../models/index.js";
14
+ import { PinnedRows, PinnedColumns } from "../../models/core.js";
15
+ import { Dimensions, observeRootNode } from "../dimensions.js";
16
+ import { ScrollPosition, ScrollDirection } from "../../models/index.js";
17
17
 
18
18
  /* eslint-disable import/export, @typescript-eslint/no-redeclare */
19
19
 
@@ -30,12 +30,18 @@ export const EMPTY_RENDER_CONTEXT = {
30
30
  firstColumnIndex: 0,
31
31
  lastColumnIndex: 0
32
32
  };
33
- const selectors = {
34
- store: createSelector(state => state.virtualization),
35
- renderContext: createSelector(state => state.virtualization.renderContext),
36
- enabledForRows: createSelector(state => state.virtualization.enabledForRows),
37
- enabledForColumns: createSelector(state => state.virtualization.enabledForColumns)
38
- };
33
+ const selectors = (() => {
34
+ const firstRowIndexSelector = createSelector(state => state.virtualization.renderContext.firstRowIndex);
35
+ return {
36
+ store: createSelector(state => state.virtualization),
37
+ renderContext: createSelector(state => state.virtualization.renderContext),
38
+ enabledForRows: createSelector(state => state.virtualization.enabledForRows),
39
+ enabledForColumns: createSelector(state => state.virtualization.enabledForColumns),
40
+ offsetTop: createSelector(Dimensions.selectors.rowPositions, firstRowIndexSelector, (rowPositions, firstRowIndex) => rowPositions[firstRowIndex] ?? 0),
41
+ context: createSelector(state => state.virtualization.context),
42
+ scrollPosition: createSelector(state => state.virtualization.scrollPosition)
43
+ };
44
+ })();
39
45
  export const Virtualization = {
40
46
  initialize: initializeState,
41
47
  use: useVirtualization,
@@ -47,7 +53,12 @@ function initializeState(params) {
47
53
  enabled: !platform.isJSDOM,
48
54
  enabledForRows: !platform.isJSDOM,
49
55
  enabledForColumns: !platform.isJSDOM,
50
- renderContext: EMPTY_RENDER_CONTEXT
56
+ renderContext: EMPTY_RENDER_CONTEXT,
57
+ props: params.layout.constructor.elements.reduce((acc, key) => (acc[key], acc), {}),
58
+ context: {},
59
+ scrollPosition: {
60
+ current: ScrollPosition.EMPTY
61
+ }
51
62
  }, params.initialState?.virtualization),
52
63
  // FIXME: refactor once the state shape is settled
53
64
  getters: null
@@ -59,10 +70,10 @@ function initializeState(params) {
59
70
 
60
71
  function useVirtualization(store, params, api) {
61
72
  const {
62
- refs,
73
+ layout,
63
74
  dimensions: {
64
75
  rowHeight,
65
- columnsTotalWidth
76
+ columnsTotalWidth = 0
66
77
  },
67
78
  virtualization: {
68
79
  isRtl = false,
@@ -76,8 +87,6 @@ function useVirtualization(store, params, api) {
76
87
  columns,
77
88
  pinnedRows = PinnedRows.EMPTY,
78
89
  pinnedColumns = PinnedColumns.EMPTY,
79
- minimalContentHeight,
80
- autoHeight,
81
90
  onWheel,
82
91
  onTouchMove,
83
92
  onRenderContextChange,
@@ -86,7 +95,6 @@ function useVirtualization(store, params, api) {
86
95
  renderRow,
87
96
  renderInfiniteLoadingTrigger
88
97
  } = params;
89
- const needsHorizontalScrollbar = useStore(store, Dimensions.selectors.needsHorizontalScrollbar);
90
98
  const hasBottomPinnedRows = pinnedRows.bottom.length > 0;
91
99
  const [panels, setPanels] = React.useState(EMPTY_DETAIL_PANELS);
92
100
  const isUpdateScheduled = React.useRef(false);
@@ -94,7 +102,6 @@ function useVirtualization(store, params, api) {
94
102
  const renderContext = useStore(store, selectors.renderContext);
95
103
  const enabledForRows = useStore(store, selectors.enabledForRows);
96
104
  const enabledForColumns = useStore(store, selectors.enabledForColumns);
97
- const rowsMeta = useStore(store, Dimensions.selectors.rowsMeta);
98
105
  const contentHeight = useStore(store, Dimensions.selectors.contentHeight);
99
106
 
100
107
  /*
@@ -122,7 +129,10 @@ function useVirtualization(store, params, api) {
122
129
  const updateRenderContext = React.useCallback(nextRenderContext => {
123
130
  if (!areRenderContextsEqual(nextRenderContext, store.state.virtualization.renderContext)) {
124
131
  store.set('virtualization', _extends({}, store.state.virtualization, {
125
- renderContext: nextRenderContext
132
+ renderContext: nextRenderContext,
133
+ scrollPosition: {
134
+ current: _extends({}, scrollPosition.current)
135
+ }
126
136
  }));
127
137
  }
128
138
 
@@ -138,7 +148,7 @@ function useVirtualization(store, params, api) {
138
148
  previousContextScrollPosition.current = scrollPosition.current;
139
149
  }, [store, onRenderContextChange]);
140
150
  const triggerUpdateRenderContext = useEventCallback(() => {
141
- const scroller = refs.scroller.current;
151
+ const scroller = layout.refs.scroller.current;
142
152
  if (!scroller) {
143
153
  return undefined;
144
154
  }
@@ -166,6 +176,11 @@ function useVirtualization(store, params, api) {
166
176
  const didChangeDirection = scrollCache.direction !== direction;
167
177
  const shouldUpdate = didCrossThreshold || didChangeDirection;
168
178
  if (!shouldUpdate) {
179
+ store.set('virtualization', _extends({}, store.state.virtualization, {
180
+ scrollPosition: {
181
+ current: _extends({}, scrollPosition.current)
182
+ }
183
+ }));
169
184
  return renderContext;
170
185
  }
171
186
 
@@ -232,9 +247,6 @@ function useVirtualization(store, params, api) {
232
247
  onScrollChange?.(scrollPosition.current, nextRenderContext);
233
248
  }
234
249
  });
235
- const getOffsetTop = () => {
236
- return rowsMeta.positions[renderContext.firstRowIndex] ?? 0;
237
- };
238
250
 
239
251
  /**
240
252
  * HACK: unstable_rowTree fixes the issue described below, but does it by tightly coupling this
@@ -363,34 +375,13 @@ function useVirtualization(store, params, api) {
363
375
  if (panel) {
364
376
  rowElements.push(panel);
365
377
  }
366
- if (rowParams.position === undefined && isLastVisibleInSection) {
378
+ if (rowParams.position === undefined && isLastVisibleInSection && renderInfiniteLoadingTrigger) {
367
379
  rowElements.push(renderInfiniteLoadingTrigger(id));
368
380
  }
369
381
  });
370
382
  return rowElements;
371
383
  };
372
- const scrollerStyle = React.useMemo(() => ({
373
- overflowX: !needsHorizontalScrollbar ? 'hidden' : undefined,
374
- overflowY: autoHeight ? 'hidden' : undefined
375
- }), [needsHorizontalScrollbar, autoHeight]);
376
- const contentSize = React.useMemo(() => {
377
- const size = {
378
- width: needsHorizontalScrollbar ? columnsTotalWidth : 'auto',
379
- flexBasis: contentHeight,
380
- flexShrink: 0
381
- };
382
- if (size.flexBasis === 0) {
383
- size.flexBasis = minimalContentHeight; // Give room to show the overlay when there no rows.
384
- }
385
- return size;
386
- }, [columnsTotalWidth, contentHeight, needsHorizontalScrollbar, minimalContentHeight]);
387
384
  const scrollRestoreCallback = React.useRef(null);
388
- const contentNodeRef = React.useCallback(node => {
389
- if (!node) {
390
- return;
391
- }
392
- scrollRestoreCallback.current?.(columnsTotalWidth, contentHeight);
393
- }, [columnsTotalWidth, contentHeight]);
394
385
  useEnhancedEffect(() => {
395
386
  if (!isRenderContextReady.current) {
396
387
  return;
@@ -398,15 +389,15 @@ function useVirtualization(store, params, api) {
398
389
  forceUpdateRenderContextCallback();
399
390
  }, [enabledForColumns, enabledForRows, forceUpdateRenderContextCallback]);
400
391
  useEnhancedEffect(() => {
401
- if (refs.scroller.current) {
402
- refs.scroller.current.scrollLeft = 0;
392
+ if (layout.refs.scroller.current) {
393
+ layout.refs.scroller.current.scrollLeft = 0;
403
394
  }
404
- }, [refs.scroller, scrollReset]);
395
+ }, [layout.refs.scroller, scrollReset]);
405
396
  useRunOnce(renderContext !== EMPTY_RENDER_CONTEXT, () => {
406
397
  onScrollChange?.(scrollPosition.current, renderContext);
407
398
  isRenderContextReady.current = true;
408
- if (initialState?.scroll && refs.scroller.current) {
409
- const scroller = refs.scroller.current;
399
+ if (initialState?.scroll && layout.refs.scroller.current) {
400
+ const scroller = layout.refs.scroller.current;
410
401
  const {
411
402
  top,
412
403
  left
@@ -449,20 +440,14 @@ function useVirtualization(store, params, api) {
449
440
  }
450
441
  });
451
442
  useStoreEffect(store, Dimensions.selectors.dimensions, forceUpdateRenderContext);
452
- const refSetter = name => node => {
453
- if (node && refs[name].current !== node) {
454
- refs[name].current = node;
443
+ useEnhancedEffect(() => {
444
+ if (layout.refs.scroller) {
445
+ scrollRestoreCallback.current?.(columnsTotalWidth, contentHeight);
455
446
  }
456
- };
447
+ }, [layout.refs.scroller, columnsTotalWidth, contentHeight]);
457
448
  const isFirstSizing = React.useRef(true);
458
- const containerCleanup = React.useRef(undefined);
459
- const containerRef = useEventCallback(node => {
460
- if (!node) {
461
- // Cleanup for R18
462
- containerCleanup.current?.();
463
- return;
464
- }
465
- refs.container.current = node;
449
+ const containerRef = useRefCallback(node => {
450
+ layout.refs.container.current = node;
466
451
  const unsubscribe = observeRootNode(node, store, rootSize => {
467
452
  if (rootSize.width === 0 && rootSize.height === 0 && store.state.rootSize.height !== 0 && store.state.rootSize.width !== 0) {
468
453
  return;
@@ -476,98 +461,58 @@ function useVirtualization(store, params, api) {
476
461
  api.debouncedUpdateDimensions();
477
462
  }
478
463
  });
479
- containerCleanup.current = () => {
464
+ return () => {
480
465
  unsubscribe?.();
481
- refs.container.current = null;
466
+ layout.refs.container.current = null;
482
467
  };
483
- if (reactMajor >= 19) {
484
- /* eslint-disable-next-line consistent-return */
485
- return containerCleanup.current;
486
- }
487
468
  });
488
- const scrollerCleanup = React.useRef(undefined);
489
- const scrollerRef = useEventCallback(node => {
490
- if (!node) {
491
- // Cleanup for R18
492
- scrollerCleanup.current?.();
493
- return;
494
- }
495
- scrollerCleanup.current?.();
496
- refs.scroller.current = node;
469
+ const scrollerRef = useRefCallback(node => {
470
+ layout.refs.scroller.current = node;
497
471
  const opts = {
498
472
  passive: true
499
473
  };
500
474
  node.addEventListener('scroll', handleScroll, opts);
501
475
  node.addEventListener('wheel', onWheel, opts);
502
476
  node.addEventListener('touchmove', onTouchMove, opts);
503
- scrollerCleanup.current = () => {
477
+ return () => {
504
478
  node.removeEventListener('scroll', handleScroll, opts);
505
479
  node.removeEventListener('wheel', onWheel, opts);
506
480
  node.removeEventListener('touchmove', onTouchMove, opts);
507
- refs.scroller.current = null;
481
+ layout.refs.scroller.current = null;
508
482
  };
509
- if (reactMajor >= 19) {
510
- /* eslint-disable-next-line consistent-return */
511
- return scrollerCleanup.current;
512
- }
513
483
  });
514
- const scrollbarVerticalRef = useEventCallback(refSetter('scrollbarVertical'));
515
- const scrollbarHorizontalRef = useEventCallback(refSetter('scrollbarHorizontal'));
516
- const getters = {
484
+ const layoutParams = {
485
+ containerRef,
486
+ scrollerRef
487
+ };
488
+ const layoutAPI = layout.use(store, params, api, layoutParams);
489
+ const getters = _extends({
517
490
  setPanels,
518
- getOffsetTop,
519
491
  getRows,
520
- rows: params.rows,
521
- getContainerProps: () => ({
522
- ref: containerRef
523
- }),
524
- getScrollerProps: () => ({
525
- ref: scrollerRef,
526
- style: scrollerStyle,
527
- role: 'presentation',
528
- // `tabIndex` shouldn't be used along role=presentation, but it fixes a Firefox bug
529
- // https://github.com/mui/mui-x/pull/13891#discussion_r1683416024
530
- tabIndex: platform.isFirefox ? -1 : undefined
531
- }),
532
- getContentProps: () => ({
533
- ref: contentNodeRef,
534
- style: contentSize,
535
- role: 'presentation'
536
- }),
537
- getScrollbarVerticalProps: () => ({
538
- ref: scrollbarVerticalRef,
539
- scrollPosition
540
- }),
541
- getScrollbarHorizontalProps: () => ({
542
- ref: scrollbarHorizontalRef,
543
- scrollPosition
544
- }),
545
- getScrollAreaProps: () => ({
546
- scrollPosition
547
- })
548
- };
549
-
550
- /* Placeholder API functions for colspan & rowspan to re-implement */
551
-
552
- const getCellColSpanInfo = () => {
553
- throw new Error('Unimplemented: colspan feature is required');
554
- };
555
- const calculateColSpan = () => {
556
- throw new Error('Unimplemented: colspan feature is required');
557
- };
558
- const getHiddenCellsOrigin = () => {
559
- throw new Error('Unimplemented: rowspan feature is required');
560
- };
561
- return {
492
+ rows: params.rows
493
+ }, layoutAPI);
494
+ return _extends({
562
495
  getters,
563
- useVirtualization: () => useStore(store, state => state),
564
496
  setPanels,
565
497
  forceUpdateRenderContext,
566
- scheduleUpdateRenderContext,
567
- getCellColSpanInfo,
568
- calculateColSpan,
569
- getHiddenCellsOrigin
570
- };
498
+ scheduleUpdateRenderContext
499
+ }, createSpanningAPI());
500
+ }
501
+ function useRefCallback(fn) {
502
+ const refCleanup = React.useRef(undefined);
503
+ const refCallback = useEventCallback(node => {
504
+ if (!node) {
505
+ // Cleanup for R18
506
+ refCleanup.current?.();
507
+ return;
508
+ }
509
+ refCleanup.current = fn(node);
510
+ if (reactMajor >= 19) {
511
+ /* eslint-disable-next-line consistent-return */
512
+ return refCleanup.current;
513
+ }
514
+ });
515
+ return refCallback;
571
516
  }
572
517
  function inputsSelector(store, params, api, enabledForRows, enabledForColumns) {
573
518
  const dimensions = Dimensions.selectors.dimensions(store.state);
@@ -581,7 +526,7 @@ function inputsSelector(store, params, api, enabledForRows, enabledForColumns) {
581
526
  api,
582
527
  enabledForRows,
583
528
  enabledForColumns,
584
- autoHeight: params.autoHeight,
529
+ autoHeight: dimensions.autoHeight,
585
530
  rowBufferPx: params.virtualization.rowBufferPx,
586
531
  columnBufferPx: params.virtualization.columnBufferPx,
587
532
  leftPinnedWidth: dimensions.leftPinnedWidth,
@@ -886,6 +831,24 @@ function getFirstNonSpannedColumnToRender({
886
831
  }
887
832
  return firstNonSpannedColumnToRender;
888
833
  }
834
+
835
+ /** Placeholder API functions for colspan & rowspan to re-implement */
836
+ function createSpanningAPI() {
837
+ const getCellColSpanInfo = () => {
838
+ throw new Error('Unimplemented: colspan feature is required');
839
+ };
840
+ const calculateColSpan = () => {
841
+ throw new Error('Unimplemented: colspan feature is required');
842
+ };
843
+ const getHiddenCellsOrigin = () => {
844
+ throw new Error('Unimplemented: rowspan feature is required');
845
+ };
846
+ return {
847
+ getCellColSpanInfo,
848
+ calculateColSpan,
849
+ getHiddenCellsOrigin
850
+ };
851
+ }
889
852
  export function roundToDecimalPlaces(value, decimals) {
890
853
  return Math.round(value * 10 ** decimals) / 10 ** decimals;
891
854
  }
package/esm/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./useVirtualizer.js";
2
- export * from "./features/index.js";
2
+ export * from "./features/index.js";
3
+ export * from "./constants.js";
package/esm/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  /**
2
- * @mui/x-virtualizer v0.2.10
2
+ * @mui/x-virtualizer v0.2.12
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  export * from "./useVirtualizer.js";
9
- export * from "./features/index.js";
9
+ export * from "./features/index.js";
10
+ export * from "./constants.js";
@@ -62,6 +62,13 @@ export type ScrollPosition = {
62
62
  top: number;
63
63
  left: number;
64
64
  };
65
+ export declare const ScrollPosition: {
66
+ EMPTY: {
67
+ top: number;
68
+ left: number;
69
+ };
70
+ equals: (a: ScrollPosition, b: ScrollPosition) => boolean;
71
+ };
65
72
  export declare enum ScrollDirection {
66
73
  NONE = 0,
67
74
  UP = 1,
@@ -22,6 +22,13 @@ export const PinnedColumns = {
22
22
  right: []
23
23
  }
24
24
  };
25
+ export const ScrollPosition = {
26
+ EMPTY: {
27
+ top: 0,
28
+ left: 0
29
+ },
30
+ equals: (a, b) => a.top === b.top && a.left === b.left
31
+ };
25
32
  export let ScrollDirection = /*#__PURE__*/function (ScrollDirection) {
26
33
  ScrollDirection[ScrollDirection["NONE"] = 0] = "NONE";
27
34
  ScrollDirection[ScrollDirection["UP"] = 1] = "UP";
@@ -65,6 +65,14 @@ export interface DimensionsState {
65
65
  * Size of the bottom container.
66
66
  */
67
67
  bottomContainerHeight: number;
68
+ /**
69
+ * Indicates that the container takes the height of its content.
70
+ */
71
+ autoHeight: boolean;
72
+ /**
73
+ * Minimal height to display the content area.
74
+ */
75
+ minimalContentHeight: string | number | undefined;
68
76
  }
69
77
  /**
70
78
  * The rows total height and positions.
@@ -1,25 +1,21 @@
1
1
  import * as React from 'react';
2
- import { integer, RefObject } from '@mui/x-internals/types';
2
+ import { integer } from '@mui/x-internals/types';
3
3
  import { Store } from '@mui/x-internals/store';
4
4
  import { Colspan } from "./features/colspan.js";
5
5
  import { Dimensions } from "./features/dimensions.js";
6
6
  import { Rowspan } from "./features/rowspan.js";
7
- import { Virtualization } from "./features/virtualization.js";
7
+ import { Virtualization } from "./features/virtualization/index.js";
8
+ import type { Layout } from "./features/virtualization/layout.js";
8
9
  import type { HeightEntry, RowSpacing } from "./models/dimensions.js";
9
10
  import type { ColspanParams } from "./features/colspan.js";
10
11
  import type { DimensionsParams } from "./features/dimensions.js";
11
- import type { VirtualizationParams } from "./features/virtualization.js";
12
+ import type { VirtualizationParams } from "./features/virtualization/index.js";
12
13
  import { ColumnWithWidth, FocusedCell, Size, PinnedRows, PinnedColumns, RenderContext, Row, RowEntry } from "./models/index.js";
13
14
  export type Virtualizer = ReturnType<typeof useVirtualizer>;
14
- export type VirtualScrollerCompat = Virtualization.State['getters'];
15
- export type BaseState = Virtualization.State & Dimensions.State;
16
- export type VirtualizerParams = {
17
- refs: {
18
- container: RefObject<HTMLDivElement | null>;
19
- scroller: RefObject<HTMLDivElement | null>;
20
- scrollbarVertical: RefObject<HTMLDivElement | null>;
21
- scrollbarHorizontal: RefObject<HTMLDivElement | null>;
22
- };
15
+ export type VirtualScrollerCompat<L extends Layout = Layout> = Virtualization.State<L>['getters'];
16
+ export type BaseState<L extends Layout = Layout> = Virtualization.State<L> & Dimensions.State;
17
+ export type VirtualizerParams<L extends Layout = Layout> = {
18
+ layout: L;
23
19
  dimensions: DimensionsParams;
24
20
  virtualization: VirtualizationParams;
25
21
  colspan?: ColspanParams;
@@ -29,7 +25,7 @@ export type VirtualizerParams = {
29
25
  left: number;
30
26
  };
31
27
  rowSpanning?: Rowspan.State['rowSpanning'];
32
- virtualization?: Partial<Virtualization.State['virtualization']>;
28
+ virtualization?: Partial<Virtualization.State<L>['virtualization']>;
33
29
  };
34
30
  /** current page rows */
35
31
  rows: RowEntry[];
@@ -39,13 +35,11 @@ export type VirtualizerParams = {
39
35
  lastRowIndex: integer;
40
36
  } | null;
41
37
  rowCount: integer;
42
- columns: ColumnWithWidth[];
38
+ columns?: ColumnWithWidth[];
43
39
  pinnedRows?: PinnedRows;
44
40
  pinnedColumns?: PinnedColumns;
45
- autoHeight: boolean;
46
41
  disableHorizontalScroll?: boolean;
47
42
  disableVerticalScroll?: boolean;
48
- minimalContentHeight?: number | string;
49
43
  getRowHeight?: (row: RowEntry) => number | null | undefined | 'auto';
50
44
  /**
51
45
  * Function that returns the estimated height for a row.
@@ -68,7 +62,7 @@ export type VirtualizerParams = {
68
62
  */
69
63
  applyRowHeight?: (entry: HeightEntry, rowEntry: RowEntry) => void;
70
64
  virtualizeColumnsWithAutoRowHeight?: boolean;
71
- resizeThrottleMs: number;
65
+ resizeThrottleMs?: number;
72
66
  onResize?: (lastSize: Size) => void;
73
67
  onWheel?: (event: React.WheelEvent) => void;
74
68
  onTouchMove?: (event: React.TouchEvent) => void;
@@ -94,10 +88,15 @@ export type VirtualizerParams = {
94
88
  isVirtualFocusRow: boolean;
95
89
  showBottomBorder: boolean;
96
90
  }) => React.ReactElement;
97
- renderInfiniteLoadingTrigger: (id: any) => React.ReactElement;
91
+ renderInfiniteLoadingTrigger?: (id: any) => React.ReactElement;
92
+ };
93
+ type RequiredFields<T, K extends keyof T> = T & Required<Pick<T, K>>;
94
+ export type ParamsWithDefaults = RequiredFields<VirtualizerParams, 'resizeThrottleMs' | 'columns'> & {
95
+ dimensions: RequiredFields<VirtualizerParams['dimensions'], 'columnsTotalWidth' | 'leftPinnedWidth' | 'rightPinnedWidth' | 'topPinnedHeight' | 'bottomPinnedHeight' | 'autoHeight'>;
96
+ virtualization: RequiredFields<VirtualizerParams['virtualization'], 'isRtl' | 'rowBufferPx' | 'columnBufferPx'>;
98
97
  };
99
- export declare const useVirtualizer: (params: VirtualizerParams) => {
100
- store: Store<Dimensions.State & Virtualization.State & Colspan.State & Rowspan.State>;
98
+ export declare const useVirtualizer: <L extends Layout = Layout>(params: VirtualizerParams<L>) => {
99
+ store: Store<Dimensions.State & Virtualization.State<L> & Colspan.State & Rowspan.State>;
101
100
  api: {
102
101
  updateDimensions: (firstUpdate?: boolean) => void;
103
102
  debouncedUpdateDimensions: (((firstUpdate?: boolean) => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
@@ -113,57 +112,13 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
113
112
  resetRowHeights: () => void;
114
113
  };
115
114
  } & {
116
- getters: {
117
- setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
118
- getOffsetTop: () => number;
119
- getRows: (rowParams?: {
120
- rows?: RowEntry[];
121
- position?: import("./models/index.js").PinnedRowPosition;
122
- renderContext?: RenderContext;
123
- }, unstable_rowTree?: Record<import("./models/index.js").RowId, any>) => React.ReactNode[];
124
- rows: RowEntry[];
125
- getContainerProps: () => {
126
- ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
127
- };
128
- getScrollerProps: () => {
129
- ref: (node: HTMLDivElement | null) => (() => void | undefined) | undefined;
130
- style: React.CSSProperties;
131
- role: string;
132
- tabIndex: number | undefined;
133
- };
134
- getContentProps: () => {
135
- ref: (node: HTMLDivElement | null) => void;
136
- style: React.CSSProperties;
137
- role: string;
138
- };
139
- getScrollbarVerticalProps: () => {
140
- ref: (node: HTMLDivElement | null) => void;
141
- scrollPosition: React.RefObject<{
142
- top: number;
143
- left: number;
144
- }>;
145
- };
146
- getScrollbarHorizontalProps: () => {
147
- ref: (node: HTMLDivElement | null) => void;
148
- scrollPosition: React.RefObject<{
149
- top: number;
150
- left: number;
151
- }>;
152
- };
153
- getScrollAreaProps: () => {
154
- scrollPosition: React.RefObject<{
155
- top: number;
156
- left: number;
157
- }>;
158
- };
159
- };
160
- useVirtualization: () => BaseState;
161
- setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
162
- forceUpdateRenderContext: () => void;
163
- scheduleUpdateRenderContext: () => void;
164
115
  getCellColSpanInfo: (rowId: import("./models/index.js").RowId, columnIndex: integer) => import("./models/index.js").CellColSpanInfo;
165
116
  calculateColSpan: (rowId: import("./models/index.js").RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;
166
117
  getHiddenCellsOrigin: () => Record<import("./models/index.js").RowId, Record<number, number>>;
118
+ getters: any;
119
+ setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
120
+ forceUpdateRenderContext: () => void;
121
+ scheduleUpdateRenderContext: () => void;
167
122
  } & {
168
123
  resetColSpan: () => void;
169
124
  getCellColSpanInfo: (rowId: import("./models/index.js").RowId, columnIndex: integer) => import("./models/index.js").CellColSpanInfo | undefined;
@@ -173,4 +128,5 @@ export declare const useVirtualizer: (params: VirtualizerParams) => {
173
128
  } & {
174
129
  getViewportPageSize: () => number;
175
130
  };
176
- };
131
+ };
132
+ export {};
@@ -1,10 +1,12 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
1
2
  import useLazyRef from '@mui/utils/useLazyRef';
2
3
  import { Store } from '@mui/x-internals/store';
3
4
  import { Colspan } from "./features/colspan.js";
4
5
  import { Dimensions } from "./features/dimensions.js";
5
6
  import { Keyboard } from "./features/keyboard.js";
6
7
  import { Rowspan } from "./features/rowspan.js";
7
- import { Virtualization } from "./features/virtualization.js";
8
+ import { Virtualization } from "./features/virtualization/index.js";
9
+ import { DEFAULT_PARAMS } from "./constants.js";
8
10
 
9
11
  /* eslint-disable jsdoc/require-param-type */
10
12
  /* eslint-disable jsdoc/require-param-description */
@@ -12,15 +14,30 @@ import { Virtualization } from "./features/virtualization.js";
12
14
 
13
15
  const FEATURES = [Dimensions, Virtualization, Colspan, Rowspan, Keyboard];
14
16
  export const useVirtualizer = params => {
17
+ const paramsWithDefault = mergeDefaults(params, DEFAULT_PARAMS);
15
18
  const store = useLazyRef(() => {
16
- return new Store(FEATURES.map(f => f.initialize(params)).reduce((state, partial) => Object.assign(state, partial), {}));
19
+ return new Store(FEATURES.map(f => f.initialize(paramsWithDefault)).reduce((state, partial) => Object.assign(state, partial), {}));
17
20
  }).current;
18
21
  const api = {};
19
22
  for (const feature of FEATURES) {
20
- Object.assign(api, feature.use(store, params, api));
23
+ Object.assign(api, feature.use(store, paramsWithDefault, api));
21
24
  }
22
25
  return {
23
26
  store,
24
27
  api
25
28
  };
26
- };
29
+ };
30
+ function mergeDefaults(params, defaults) {
31
+ const result = _extends({}, params);
32
+ for (const key in defaults) {
33
+ if (Object.hasOwn(defaults, key)) {
34
+ const value = defaults[key];
35
+ if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
36
+ result[key] = mergeDefaults(params[key] ?? {}, value);
37
+ } else {
38
+ result[key] = params[key] ?? value;
39
+ }
40
+ }
41
+ }
42
+ return result;
43
+ }
@@ -1,9 +1,9 @@
1
1
  import { Store } from '@mui/x-internals/store';
2
2
  import type { integer } from '@mui/x-internals/types';
3
- import type { BaseState, VirtualizerParams } from "../useVirtualizer.js";
3
+ import type { BaseState, ParamsWithDefaults } from "../useVirtualizer.js";
4
4
  import type { ColumnWithWidth, RowId } from "../models/index.js";
5
5
  import type { CellColSpanInfo } from "../models/colspan.js";
6
- import { Virtualization } from "./virtualization.js";
6
+ import { Virtualization } from "./virtualization/index.js";
7
7
  type ColumnIndex = number;
8
8
  type ColspanMap = Map<RowId, Record<ColumnIndex, CellColSpanInfo>>;
9
9
  export type ColspanParams = {
@@ -21,10 +21,10 @@ export declare namespace Colspan {
21
21
  };
22
22
  type API = ReturnType<typeof useColspan>;
23
23
  }
24
- declare function initializeState(_params: VirtualizerParams): {
24
+ declare function initializeState(_params: ParamsWithDefaults): {
25
25
  colspanMap: Map<any, any>;
26
26
  };
27
- declare function useColspan(store: Store<BaseState & Colspan.State>, params: VirtualizerParams, api: Virtualization.API): {
27
+ declare function useColspan(store: Store<BaseState & Colspan.State>, params: ParamsWithDefaults, api: Virtualization.API): {
28
28
  resetColSpan: () => void;
29
29
  getCellColSpanInfo: (rowId: RowId, columnIndex: integer) => CellColSpanInfo | undefined;
30
30
  calculateColSpan: (rowId: RowId, minFirstColumn: integer, maxLastColumn: integer, columns: ColumnWithWidth[]) => void;