simple-table-core 3.9.0 → 3.9.2

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 (27) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/cjs/src/consts/general-consts.d.ts +2 -0
  3. package/dist/cjs/src/managers/DimensionManager.d.ts +11 -0
  4. package/dist/cjs/src/types/AnimationsConfig.d.ts +2 -0
  5. package/dist/cjs/src/utils/bodyCell/styling.d.ts +2 -0
  6. package/dist/cjs/src/utils/headerCell/eventTracking.d.ts +1 -1
  7. package/dist/cjs/src/utils/headerCell/types.d.ts +6 -0
  8. package/dist/cjs/src/utils/headerWidthUtils.d.ts +6 -0
  9. package/dist/cjs/src/utils/horizontalScrollbarRenderer.d.ts +7 -0
  10. package/dist/cjs/stories/tests/43-CollapseExpandAnimationsTests.stories.d.ts +2 -2
  11. package/dist/cjs/stories/tests/46-AutoSizeColumnsTests.stories.d.ts +49 -1
  12. package/dist/cjs/stories/tests/50-ContainerResizePerformanceTests.stories.d.ts +56 -0
  13. package/dist/cjs/stories/tests/51-RowGroupReExpandTests.stories.d.ts +78 -0
  14. package/dist/index.es.js +1 -1
  15. package/dist/src/consts/general-consts.d.ts +2 -0
  16. package/dist/src/managers/DimensionManager.d.ts +11 -0
  17. package/dist/src/types/AnimationsConfig.d.ts +2 -0
  18. package/dist/src/utils/bodyCell/styling.d.ts +2 -0
  19. package/dist/src/utils/headerCell/eventTracking.d.ts +1 -1
  20. package/dist/src/utils/headerCell/types.d.ts +6 -0
  21. package/dist/src/utils/headerWidthUtils.d.ts +6 -0
  22. package/dist/src/utils/horizontalScrollbarRenderer.d.ts +7 -0
  23. package/dist/stories/tests/43-CollapseExpandAnimationsTests.stories.d.ts +2 -2
  24. package/dist/stories/tests/46-AutoSizeColumnsTests.stories.d.ts +49 -1
  25. package/dist/stories/tests/50-ContainerResizePerformanceTests.stories.d.ts +56 -0
  26. package/dist/stories/tests/51-RowGroupReExpandTests.stories.d.ts +78 -0
  27. package/package.json +1 -1
@@ -19,3 +19,5 @@ export declare const AUTO_SIZE_OUTLIER_PERCENTILE = 95;
19
19
  export declare const AUTO_SIZE_OUTLIER_THRESHOLD = 0.5;
20
20
  export declare const AUTO_SIZE_MIN_SAMPLE_FOR_CLIP = 20;
21
21
  export declare const AUTO_SIZE_WIDTH_BUFFER = 2;
22
+ /** Extra padding reserved around header icons (sort / collapse) during auto-size. */
23
+ export declare const AUTO_SIZE_HEADER_ICON_PADDING = 4;
@@ -21,12 +21,20 @@ export interface DimensionManagerState {
21
21
  contentHeight: number | undefined;
22
22
  }
23
23
  type StateChangeCallback = (state: DimensionManagerState) => void;
24
+ /**
25
+ * Wait this long after the last container-width ResizeObserver tick before
26
+ * notifying subscribers. Coalesces CSS-transition / animated layout shifts
27
+ * (e.g. a collapsible nav) into a single trailing update instead of one full
28
+ * table render per animation frame.
29
+ */
30
+ export declare const CONTAINER_RESIZE_NOTIFY_DEBOUNCE_MS = 50;
24
31
  export declare class DimensionManager {
25
32
  private config;
26
33
  private state;
27
34
  private subscribers;
28
35
  private resizeObserver;
29
36
  private rafId;
37
+ private resizeNotifyDebounceId;
30
38
  /** Set when applyContainerWidthSync updates state before any subscriber exists. */
31
39
  private initialNotifyPending;
32
40
  constructor(config: DimensionManagerConfig);
@@ -35,6 +43,9 @@ export declare class DimensionManager {
35
43
  private calculateHeaderHeight;
36
44
  private convertHeightToPixels;
37
45
  private calculateContentHeight;
46
+ private cancelPendingResizeNotify;
47
+ /** Trailing debounce for animated / continuous container resizes. */
48
+ private scheduleResizeNotify;
38
49
  private observeContainer;
39
50
  private applyContainerWidthSync;
40
51
  updateConfig(config: Partial<DimensionManagerConfig>): void;
@@ -3,6 +3,8 @@
3
3
  *
4
4
  * The animation coordinator runs FLIP-style transitions when cells move between
5
5
  * positions. All fields are optional; omit the prop entirely to use defaults.
6
+ *
7
+ * Row group expand/collapse never animates when `rowGrouping` is configured.
6
8
  */
7
9
  export interface AnimationsConfig {
8
10
  /** Master toggle. Defaults to `true`. When `false`, no other field has effect. */
@@ -2,6 +2,8 @@ import { AbsoluteBodyCell, CellRegistryEntry, CellRenderContext } from "./types"
2
2
  import { CellLiveRef, cellLiveRefMap } from "./cellLiveRef";
3
3
  export { cellLiveRefMap };
4
4
  export type { CellLiveRef };
5
+ /** Drop the content memo so the next `updateBodyCellElement` rebuilds. */
6
+ export declare const invalidateBodyCellContentMemo: (cellElement: HTMLElement) => void;
5
7
  export declare const untrackCellByRow: (rowId: string, cellElement: HTMLElement) => void;
6
8
  export declare const unregisterCellFromRegistry: (cellElement: HTMLElement, cellRegistry?: Map<string, CellRegistryEntry>) => void;
7
9
  export declare const createBodyCellElement: (cell: AbsoluteBodyCell, context: CellRenderContext) => HTMLElement;
@@ -25,4 +25,4 @@ export declare const addTrackedEventListener: (element: HTMLElement, event: stri
25
25
  /** Header tooltips are portaled under .simple-table-root; remove them when header DOM is torn down
26
26
  * without pointer leave (e.g. sort/filter invalidates context cache and removes header cells). */
27
27
  export declare const removeFloatingHeaderTooltips: (fromElement: HTMLElement) => void;
28
- export declare const cleanupHeaderCellRendering: (container?: HTMLElement) => void;
28
+ export declare const cleanupHeaderCellRendering: (container?: HTMLElement, onHostDiscard?: ((host: HTMLElement) => void) | undefined) => void;
@@ -96,5 +96,11 @@ export interface HeaderRenderContext {
96
96
  * driving the unfold animation.
97
97
  */
98
98
  animationCoordinator?: AnimationCoordinator;
99
+ /**
100
+ * Called immediately before a header host (or its label content) is permanently
101
+ * discarded so adapters can tear down renderer subtrees (e.g. React portals).
102
+ * Mirrors {@link CellRenderContext.onRendererHostDiscard}.
103
+ */
104
+ onRendererHostDiscard?: (host: HTMLElement) => void;
99
105
  }
100
106
  export {};
@@ -96,4 +96,10 @@ export declare const calculateHeaderContentWidth: (accessor: Accessor, options?:
96
96
  * column), so sorting later does not push the label into ellipsis.
97
97
  */
98
98
  sortIcon?: string | HTMLElement | SVGSVGElement;
99
+ /**
100
+ * The table's resolved expand/collapse icon. Used to reserve space on
101
+ * collapsible headers when the header cell is virtualized out of the
102
+ * horizontal band (so the icon is not in the DOM to measure directly).
103
+ */
104
+ expandIcon?: string | HTMLElement | SVGSVGElement;
99
105
  }) => number;
@@ -9,6 +9,13 @@ export interface HorizontalScrollbarProps {
9
9
  tableBodyContainerRef: HTMLDivElement;
10
10
  editColumns: boolean;
11
11
  sectionScrollController?: SectionScrollController | null;
12
+ /**
13
+ * When true, skip the DOM scrollWidth check and always build the scrollbar.
14
+ * Used after the caller has already verified content overflow (e.g. empty
15
+ * tables where the header scrollport is sized to content and reports no
16
+ * DOM overflow even though columns exceed the viewport).
17
+ */
18
+ forceScrollable?: boolean;
12
19
  }
13
20
  export declare const createHorizontalScrollbar: (props: HorizontalScrollbarProps) => HTMLElement | null;
14
21
  /**
@@ -34,7 +34,7 @@ export declare const ColumnExpand_IncomingCellsStartAtZeroWidth: {
34
34
  canvasElement: HTMLElement;
35
35
  }) => Promise<void>;
36
36
  };
37
- export declare const RowExpand_AddsAccordionClass: {
37
+ export declare const RowExpand_NoAccordionClass: {
38
38
  tags: string[];
39
39
  render: () => HTMLDivElement & {
40
40
  _table?: import("../../src/index").SimpleTableVanilla | undefined;
@@ -43,7 +43,7 @@ export declare const RowExpand_AddsAccordionClass: {
43
43
  canvasElement: HTMLElement;
44
44
  }) => Promise<void>;
45
45
  };
46
- export declare const RowExpand_IncomingCellsStartAtZeroHeight: {
46
+ export declare const RowExpand_NoAccordionGrow: {
47
47
  tags: string[];
48
48
  render: () => HTMLDivElement & {
49
49
  _table?: import("../../src/index").SimpleTableVanilla | undefined;
@@ -4,7 +4,7 @@
4
4
  * Comprehensive coverage for content-fit columns (`width: "auto"`):
5
5
  * - shrink / grow, per-column `maxWidth` cap and `minWidth` floor
6
6
  * - `autoSizeMode: "header"`
7
- * - custom (vanilla) renderers, valueFormatter, valueGetter, chart columns
7
+ * - custom (vanilla) renderers, valueFormatter (incl. multi-line), valueGetter, chart columns
8
8
  * - outliers (single giant value clipped) vs. a legitimate wide minority (kept)
9
9
  * - very large datasets (50k rows) with bounded sampling
10
10
  * - re-fit on data change, sort stability, empty data, mixed/pinned layouts
@@ -117,6 +117,23 @@ export declare const AutoSizeMeasuresFormattedValue: {
117
117
  canvasElement: HTMLElement;
118
118
  }) => Promise<void>;
119
119
  };
120
+ /**
121
+ * valueFormatter may return explicit multi-line text (e.g. an address). When the
122
+ * cell is allowed to wrap (`white-space: pre-line`), auto-size must fit the
123
+ * longest line — not the full string measured as one nowrap run (newlines
124
+ * collapse to spaces under `white-space: nowrap` measurement).
125
+ */
126
+ export declare const AutoSizeMultilineFormattedValueUsesLongestLine: {
127
+ parameters: {
128
+ tags: string[];
129
+ };
130
+ render: () => HTMLDivElement & {
131
+ _table?: SimpleTableVanilla | undefined;
132
+ };
133
+ play: ({ canvasElement }: {
134
+ canvasElement: HTMLElement;
135
+ }) => Promise<void>;
136
+ };
120
137
  export declare const AutoSizeMeasuresValueGetter: {
121
138
  parameters: {
122
139
  tags: string[];
@@ -302,6 +319,37 @@ export declare const AutoSizeEmptyStateAsyncHeaderRenderer: {
302
319
  canvasElement: HTMLElement;
303
320
  }) => Promise<void>;
304
321
  };
322
+ export declare const AutoSizeCollapsibleHeaderReservesIconWidth: {
323
+ parameters: {
324
+ tags: string[];
325
+ };
326
+ render: () => HTMLDivElement & {
327
+ _table?: SimpleTableVanilla | undefined;
328
+ };
329
+ play: ({ canvasElement }: {
330
+ canvasElement: HTMLElement;
331
+ }) => Promise<void>;
332
+ };
333
+ export declare const AutoSizeLongHeaderConsistentAcrossContainerWidths: {
334
+ parameters: {
335
+ tags: string[];
336
+ };
337
+ render: () => HTMLDivElement;
338
+ play: ({ canvasElement }: {
339
+ canvasElement: HTMLElement;
340
+ }) => Promise<void>;
341
+ };
342
+ export declare const HorizontalScrollbarShowsWhenHeaderOverflowsEmptyState: {
343
+ parameters: {
344
+ tags: string[];
345
+ };
346
+ render: () => HTMLDivElement & {
347
+ _table?: SimpleTableVanilla | undefined;
348
+ };
349
+ play: ({ canvasElement }: {
350
+ canvasElement: HTMLElement;
351
+ }) => Promise<void>;
352
+ };
305
353
  export declare const SamplingAndOutlierHelpers: {
306
354
  parameters: {
307
355
  tags: string[];
@@ -0,0 +1,56 @@
1
+ /**
2
+ * CONTAINER RESIZE PERFORMANCE REPRO
3
+ *
4
+ * Simulates a collapsible global left nav that animates width and squeezes the
5
+ * main content area — the layout pattern reported on Artist/Platform pages.
6
+ *
7
+ * During the CSS transition, the table container's ResizeObserver fires on
8
+ * successive frames. DimensionManager coalesces those ticks (trailing debounce)
9
+ * so subscribers / full renders fire once after the transition settles.
10
+ *
11
+ * Use the HUD while toggling the nav, or run the automated play test.
12
+ * The play test asserts coalesced table relayouts (header width updates), not
13
+ * raw container ResizeObserver ticks — the DOM still resizes every animation frame.
14
+ */
15
+ import type { Meta } from "@storybook/html";
16
+ declare const meta: Meta;
17
+ export default meta;
18
+ interface ContainerResizePerfSnapshot {
19
+ contentWidthChanges: number;
20
+ tableContainerWidthChanges: number;
21
+ /** Batched header relayout passes (one per table render), not per-cell updates. */
22
+ tableRelayouts: number;
23
+ lastContentWidth: number;
24
+ }
25
+ declare global {
26
+ interface Window {
27
+ __containerResizePerf?: ContainerResizePerfSnapshot;
28
+ }
29
+ }
30
+ export declare const resetContainerResizePerf: (lastContentWidth?: number) => void;
31
+ export declare const CollapsibleNavWithTable: {
32
+ tags: string[];
33
+ render: () => HTMLDivElement;
34
+ };
35
+ export declare const CollapsibleNavTableNoAutoExpand: {
36
+ tags: string[];
37
+ render: () => HTMLDivElement;
38
+ };
39
+ export declare const CollapsibleNavBaseline: {
40
+ tags: string[];
41
+ render: () => HTMLDivElement;
42
+ };
43
+ export declare const NavToggleCoalescesTableRelayout: {
44
+ tags: string[];
45
+ render: () => HTMLDivElement;
46
+ play: ({ canvasElement }: {
47
+ canvasElement: HTMLElement;
48
+ }) => Promise<void>;
49
+ };
50
+ export declare const BaselineNavHasNoTableGridChurn: {
51
+ tags: string[];
52
+ render: () => HTMLDivElement;
53
+ play: ({ canvasElement }: {
54
+ canvasElement: HTMLElement;
55
+ }) => Promise<void>;
56
+ };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * ROW GROUP RE-EXPAND REGRESSION TESTS
3
+ *
4
+ * Reproduces bugs when a lazy-loaded grouped row is collapsed and re-expanded:
5
+ *
6
+ * 1. onRowGroupExpand receives a stale `row` snapshot (missing cached children),
7
+ * so consumer guards like `if (row[groupingKey]?.length) return` fail and
8
+ * every re-expand re-triggers setLoading + fetch.
9
+ *
10
+ * 2. Re-expand must not re-enter loading state or spuriously animate sibling
11
+ * rows below the expanded group.
12
+ *
13
+ * Mirrors packages/react/src/__tests__/onRowGroupExpandReExpand.test.tsx.
14
+ * All play tests should FAIL until the stale-row fix lands.
15
+ */
16
+ import type { Meta } from "@storybook/html";
17
+ declare const meta: Meta;
18
+ export default meta;
19
+ interface ReExpandProbe {
20
+ expandSnapshots: Array<{
21
+ childCount: number;
22
+ isExpanded: boolean;
23
+ }>;
24
+ fetchCount: number;
25
+ loadingTrueCount: number;
26
+ }
27
+ declare global {
28
+ interface Window {
29
+ __rowGroupReExpandProbe?: ReExpandProbe;
30
+ }
31
+ }
32
+ export declare const ReExpand_PassesCachedRowSnapshot: {
33
+ tags: string[];
34
+ render: () => HTMLDivElement;
35
+ play: ({ canvasElement }: {
36
+ canvasElement: HTMLElement;
37
+ }) => Promise<void>;
38
+ };
39
+ export declare const ReExpand_SkipsRefetch: {
40
+ tags: string[];
41
+ render: () => HTMLDivElement;
42
+ play: ({ canvasElement }: {
43
+ canvasElement: HTMLElement;
44
+ }) => Promise<void>;
45
+ };
46
+ export declare const ReExpand_SkipsSetLoading: {
47
+ tags: string[];
48
+ render: () => HTMLDivElement;
49
+ play: ({ canvasElement }: {
50
+ canvasElement: HTMLElement;
51
+ }) => Promise<void>;
52
+ };
53
+ /** Manual QA: status panel shows fetch/loading counts while toggling Engineering. */
54
+ export declare const ReExpand_LazyLoad_StatusPanel: {
55
+ tags: string[];
56
+ render: () => HTMLDivElement;
57
+ };
58
+ export declare const ReExpand_NoLoadingSkeletonOnLazyReExpand: {
59
+ tags: string[];
60
+ render: () => HTMLDivElement;
61
+ play: ({ canvasElement }: {
62
+ canvasElement: HTMLElement;
63
+ }) => Promise<void>;
64
+ };
65
+ export declare const ReExpand_SiblingRowsNoAccordionGrow: {
66
+ tags: string[];
67
+ render: () => HTMLDivElement;
68
+ play: ({ canvasElement }: {
69
+ canvasElement: HTMLElement;
70
+ }) => Promise<void>;
71
+ };
72
+ export declare const ReExpand_NoAccordionGrowOnReExpand: {
73
+ tags: string[];
74
+ render: () => HTMLDivElement;
75
+ play: ({ canvasElement }: {
76
+ canvasElement: HTMLElement;
77
+ }) => Promise<void>;
78
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simple-table-core",
3
- "version": "3.9.0",
3
+ "version": "3.9.2",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/index.es.js",
6
6
  "types": "dist/src/index.d.ts",