simple-table-core 3.8.4 → 3.8.5

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.
@@ -4,6 +4,7 @@ export declare const PAGE_SIZE = 20;
4
4
  export declare const CSS_VAR_BORDER_WIDTH = "--st-border-width";
5
5
  export declare const DEFAULT_BORDER_WIDTH = 1;
6
6
  export declare const VIRTUALIZATION_THRESHOLD = 20;
7
+ export declare const UNVIRTUALIZED_ROW_WARNING_THRESHOLD = 500;
7
8
  export declare const OVERSCAN_PIXELS = 800;
8
9
  export declare const calculateBufferRowCount: (rowHeight: number) => number;
9
10
  export declare const COLUMN_EDIT_WIDTH = 29.5;
@@ -60,6 +60,10 @@ export declare class SimpleTableVanilla {
60
60
  private scrollEndTimeoutId;
61
61
  private lastScrollTop;
62
62
  private isUpdating;
63
+ /** Set once the dev-only "too many unvirtualized rows" warning has fired, so it never repeats. */
64
+ private hasWarnedUnvirtualizedRows;
65
+ /** Pending deferred check for the unvirtualized-rows warning (lets external-scroll seeding settle first). */
66
+ private unvirtualizedRowsCheckTimeoutId;
63
67
  /** Currently resolved external scroll parent (HTMLElement or window). Null when external scroll mode is inactive. */
64
68
  private resolvedScrollParent;
65
69
  /** Bound scroll handler attached to the external scroll parent. */
@@ -164,6 +168,13 @@ export declare class SimpleTableVanilla {
164
168
  */
165
169
  private didColumnVisibilityChange;
166
170
  private captureAnimationSnapshot;
171
+ /**
172
+ * Push the visible vertical viewport into the animation coordinator when
173
+ * external/page scroll is active (or clear it otherwise). Keeps the FLIP
174
+ * distance-scaling viewport-relative so cells don't slide the full
175
+ * conceptual distance when the table grows to its natural height.
176
+ */
177
+ private updateAnimationVerticalScroll;
167
178
  /**
168
179
  * Open the accordion animation window for the next render: capture a FLIP
169
180
  * snapshot, mark the active axis so cell renderers initialize incoming
@@ -267,6 +278,17 @@ export declare class SimpleTableVanilla {
267
278
  */
268
279
  refitAutoSizeColumns(): void;
269
280
  private render;
281
+ /**
282
+ * Dev-only safeguard. Schedules a one-shot, deferred check that warns when the
283
+ * table is about to render a very large number of rows with no virtualization
284
+ * active (no `height` / `maxHeight` and no bounded `scrollParent`). The check
285
+ * is deferred so external-scroll viewport seeding (which can momentarily leave
286
+ * `contentHeight` undefined on the first paint) has time to settle and we
287
+ * don't cry wolf for a correctly-configured table. Compiled out of production
288
+ * via the NODE_ENV guard. Never throws.
289
+ */
290
+ private maybeScheduleUnvirtualizedRowsWarning;
291
+ private evaluateUnvirtualizedRowsWarning;
270
292
  update(config: Partial<SimpleTableConfig>): void;
271
293
  /** @deprecated Use {@link update} — same behavior. */
272
294
  updateConfig(config: Partial<SimpleTableConfig>): void;
@@ -29,6 +29,15 @@ export interface TableAPIContext {
29
29
  cellRegistry?: Map<string, {
30
30
  updateContent: (value: any) => void;
31
31
  }>;
32
+ /**
33
+ * Whether a cell (by its `getCellId` key) is currently mid-FLIP-animation.
34
+ * Live `updateData` content writes are skipped for animating cells so a
35
+ * data tick doesn't re-render / mutate a cell that is sliding to a new
36
+ * position (which causes visible jank). The underlying row data is still
37
+ * updated; only the in-place DOM refresh is deferred to the next tick or
38
+ * re-render once the animation settles.
39
+ */
40
+ isCellAnimating?: (cellId: string) => boolean;
32
41
  columnEditorOpen: boolean;
33
42
  expandedDepthsManager: any;
34
43
  selectionManager: SelectionManager | null;
@@ -12,6 +12,7 @@ import { SelectionManager } from "../../managers/SelectionManager";
12
12
  import { RowSelectionManager } from "../../managers/RowSelectionManager";
13
13
  import type { AnimationCoordinator, CellPosition } from "../../managers/AnimationCoordinator";
14
14
  import type { AccordionAxis } from "../../utils/accordionAnimation";
15
+ import type { NestedTableFactory } from "../../utils/nestedGridRowRenderer";
15
16
  import { FlattenRowsResult } from "../../utils/rowFlattening";
16
17
  import { ProcessRowsResult } from "../../utils/rowProcessing";
17
18
  import { MergedColumnEditorConfig, ResolvedIcons } from "../initialization/TableInitializer";
@@ -52,6 +53,8 @@ export interface RenderContext {
52
53
  internalIsLoading: boolean;
53
54
  isResizing: boolean;
54
55
  localRows: Row[];
56
+ /** Injected factory for nested grid tables (breaks the SimpleTableVanilla import cycle). */
57
+ createNestedTable?: NestedTableFactory;
55
58
  mainBodyRef: {
56
59
  current: HTMLDivElement | null;
57
60
  };
@@ -9,6 +9,7 @@ import { SelectionManager } from "../../managers/SelectionManager";
9
9
  import { RowSelectionManager } from "../../managers/RowSelectionManager";
10
10
  import type { AnimationCoordinator, CellPosition } from "../../managers/AnimationCoordinator";
11
11
  import type { AccordionAxis } from "../../utils/accordionAnimation";
12
+ import type { NestedTableFactory } from "../../utils/nestedGridRowRenderer";
12
13
  export interface TableRendererDeps {
13
14
  /** Accordion animation axis for the in-flight collapse/expand. See {@link RenderContext.accordionAxis}. */
14
15
  accordionAxis?: AccordionAxis;
@@ -81,6 +82,8 @@ export interface TableRendererDeps {
81
82
  setIsResizing: (value: boolean) => void;
82
83
  setRowStateMap: (map: Map<string | number, any>) => void;
83
84
  sortManager: SortManager | null;
85
+ /** Injected factory for nested grid tables (breaks the SimpleTableVanilla import cycle). */
86
+ createNestedTable?: NestedTableFactory;
84
87
  }
85
88
  export declare class TableRenderer {
86
89
  private sectionRenderer;
@@ -57,6 +57,31 @@ export declare class AnimationCoordinator {
57
57
  * stable within a single sort.
58
58
  */
59
59
  private scrollerMetricsCache;
60
+ /**
61
+ * Vertical scroller metrics override for external/page-scroll mode. When the
62
+ * table has no internal vertical overflow (it grows to its natural height and
63
+ * a parent element / the window scrolls), the body container's own
64
+ * clientHeight/scrollHeight no longer describe the visible viewport, so
65
+ * {@link scaleFlipDistance} can't bound the FLIP journey and sort cells slide
66
+ * the full conceptual distance. The vanilla table pushes the real visible
67
+ * viewport here (from the same `getExternalScrollMetrics` the virtualizer
68
+ * uses) so the y-axis FLIP scaling matches the on-screen viewport. `null`
69
+ * when external scroll is inactive — internal scroller metrics are used as-is.
70
+ */
71
+ private externalVerticalScroll;
72
+ /**
73
+ * The currently-scheduled (not-yet-started) FLIP frame. play() defers the
74
+ * transition start by two animation frames so the inverted "First" frame
75
+ * gets painted before the transition fires. Spam-clicking sort triggers a
76
+ * full re-render + play() inside that two-frame window: without coalescing,
77
+ * the stale chain's startTransition zeroes the transforms the newer cycle
78
+ * just inverted (a frame early), so the final transition animates
79
+ * identity→identity and nothing visibly moves — and many captured nodes are
80
+ * detached by the intervening render before they ever transition. Tracking
81
+ * the pending frame lets a new play() cancel the prior cycle and reset the
82
+ * transforms it left behind, so only the latest sort animates.
83
+ */
84
+ private scheduledFlip;
60
85
  constructor(opts?: AnimationCoordinatorOptions);
61
86
  setEnabled(enabled: boolean): void;
62
87
  setDuration(duration: number): void;
@@ -84,6 +109,18 @@ export declare class AnimationCoordinator {
84
109
  * mutation in the loop.
85
110
  */
86
111
  private getScrollerMetrics;
112
+ /**
113
+ * Supply (or clear) the vertical scroller metrics override used by
114
+ * {@link scaleFlipDistance} in external/page-scroll mode. Must be set before
115
+ * `captureSnapshot`/`retainCell`/`play` so the whole FLIP cycle scales
116
+ * against the real visible viewport. Pass `null` to fall back to the body
117
+ * container's own metrics (internal scroll).
118
+ */
119
+ setExternalVerticalScroll(metrics: {
120
+ clientHeight: number;
121
+ scrollHeight: number;
122
+ scrollTop: number;
123
+ } | null): void;
87
124
  private clearScrollerMetricsCache;
88
125
  /**
89
126
  * Capture pre-change positions for cells we may want to animate.
@@ -0,0 +1,9 @@
1
+ import type Row from "../../types/Row";
2
+ import type TableRow from "../../types/TableRow";
3
+ import { CellRenderContext } from "./types";
4
+ export interface CellLiveRef {
5
+ row: Row;
6
+ tableRow: TableRow;
7
+ context: CellRenderContext;
8
+ }
9
+ export declare const cellLiveRefMap: WeakMap<HTMLElement, CellLiveRef>;
@@ -1,12 +1,7 @@
1
- import type Row from "../../types/Row";
2
- import type TableRow from "../../types/TableRow";
3
1
  import { AbsoluteBodyCell, CellRegistryEntry, CellRenderContext } from "./types";
4
- export interface CellLiveRef {
5
- row: Row;
6
- tableRow: TableRow;
7
- context: CellRenderContext;
8
- }
9
- export declare const cellLiveRefMap: WeakMap<HTMLElement, CellLiveRef>;
2
+ import { CellLiveRef, cellLiveRefMap } from "./cellLiveRef";
3
+ export { cellLiveRefMap };
4
+ export type { CellLiveRef };
10
5
  export declare const untrackCellByRow: (rowId: string, cellElement: HTMLElement) => void;
11
6
  export declare const unregisterCellFromRegistry: (cellElement: HTMLElement, cellRegistry?: Map<string, CellRegistryEntry>) => void;
12
7
  export declare const createBodyCellElement: (cell: AbsoluteBodyCell, context: CellRenderContext) => HTMLElement;
@@ -10,6 +10,7 @@ import type { CustomTheme } from "../../types/CustomTheme";
10
10
  import type { HeightOffsets } from "../infiniteScrollUtils";
11
11
  import type { AccordionAxis } from "../accordionAnimation";
12
12
  import type { VanillaEmptyStateRenderer, VanillaErrorStateRenderer, VanillaLoadingStateRenderer } from "../../types/RowStateRendererProps";
13
+ import type { NestedTableFactory } from "../nestedGridRowRenderer";
13
14
  type SetStateAction<T> = T | ((prevState: T) => T);
14
15
  type Dispatch<A> = (value: A) => void;
15
16
  export interface AbsoluteBodyCell {
@@ -115,6 +116,12 @@ export interface CellRenderContext {
115
116
  loadingStateRenderer?: VanillaLoadingStateRenderer;
116
117
  errorStateRenderer?: VanillaErrorStateRenderer;
117
118
  emptyStateRenderer?: VanillaEmptyStateRenderer;
119
+ /**
120
+ * Factory used to instantiate nested grid tables. Injected by the host table
121
+ * so {@link nestedGridRowRenderer} never has to import the concrete
122
+ * `SimpleTableVanilla` class (which would create a render-module import cycle).
123
+ */
124
+ createNestedTable?: NestedTableFactory;
118
125
  getBorderClass: (cell: CellData) => string;
119
126
  isSelected: (cell: CellData) => boolean;
120
127
  isInitialFocusedCell: (cell: CellData) => boolean;
@@ -6,6 +6,20 @@ import type TableRow from "../types/TableRow";
6
6
  import type { CustomTheme } from "../types/CustomTheme";
7
7
  import type { SimpleTableConfig } from "../types/SimpleTableConfig";
8
8
  import { type HeightOffsets } from "./infiniteScrollUtils";
9
+ /**
10
+ * Minimal surface of a table instance this renderer drives. Declared
11
+ * structurally so this module never has to statically import the concrete
12
+ * `SimpleTableVanilla` class — that import would close a cycle
13
+ * (SimpleTableVanilla → RenderOrchestrator → TableRenderer → SectionRenderer →
14
+ * nestedGridRowRenderer → SimpleTableVanilla). The class is injected at render
15
+ * time via {@link NestedTableFactory} instead.
16
+ */
17
+ export interface NestedTableInstance {
18
+ mount: () => void;
19
+ destroy: () => void;
20
+ }
21
+ /** Factory injected by the host table to instantiate a nested table. */
22
+ export type NestedTableFactory = (container: HTMLElement, config: SimpleTableConfig) => NestedTableInstance;
9
23
  export interface NestedGridRowRenderContext {
10
24
  rowHeight: number;
11
25
  heightOffsets: HeightOffsets | undefined;
@@ -17,6 +31,8 @@ export interface NestedGridRowRenderContext {
17
31
  errorStateRenderer?: SimpleTableConfig["errorStateRenderer"];
18
32
  emptyStateRenderer?: SimpleTableConfig["emptyStateRenderer"];
19
33
  icons?: SimpleTableConfig["icons"];
34
+ /** Injected constructor for nested tables (breaks the import cycle). */
35
+ createNestedTable?: NestedTableFactory;
20
36
  }
21
37
  /**
22
38
  * Creates a nested grid row element: a div with class "st-row st-nested-grid-row"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simple-table-core",
3
- "version": "3.8.4",
3
+ "version": "3.8.5",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/index.es.js",
6
6
  "types": "dist/src/index.d.ts",