simple-table-core 3.8.4 → 3.8.6

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 (32) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/cjs/src/consts/general-consts.d.ts +1 -0
  3. package/dist/cjs/src/core/SimpleTableVanilla.d.ts +30 -0
  4. package/dist/cjs/src/core/api/TableAPIImpl.d.ts +9 -0
  5. package/dist/cjs/src/core/rendering/RenderOrchestrator.d.ts +4 -0
  6. package/dist/cjs/src/core/rendering/SectionRenderer.d.ts +8 -0
  7. package/dist/cjs/src/core/rendering/TableRenderer.d.ts +4 -0
  8. package/dist/cjs/src/managers/AnimationCoordinator.d.ts +81 -0
  9. package/dist/cjs/src/types/SimpleTableConfig.d.ts +10 -0
  10. package/dist/cjs/src/utils/bodyCell/cellLiveRef.d.ts +9 -0
  11. package/dist/cjs/src/utils/bodyCell/eventTracking.d.ts +1 -1
  12. package/dist/cjs/src/utils/bodyCell/styling.d.ts +3 -8
  13. package/dist/cjs/src/utils/bodyCell/types.d.ts +15 -0
  14. package/dist/cjs/src/utils/nestedGridRowRenderer.d.ts +16 -0
  15. package/dist/cjs/styles.css +1 -1
  16. package/dist/index.es.js +1 -1
  17. package/dist/src/consts/general-consts.d.ts +1 -0
  18. package/dist/src/core/SimpleTableVanilla.d.ts +30 -0
  19. package/dist/src/core/api/TableAPIImpl.d.ts +9 -0
  20. package/dist/src/core/rendering/RenderOrchestrator.d.ts +4 -0
  21. package/dist/src/core/rendering/SectionRenderer.d.ts +8 -0
  22. package/dist/src/core/rendering/TableRenderer.d.ts +4 -0
  23. package/dist/src/managers/AnimationCoordinator.d.ts +81 -0
  24. package/dist/src/types/SimpleTableConfig.d.ts +10 -0
  25. package/dist/src/utils/bodyCell/cellLiveRef.d.ts +9 -0
  26. package/dist/src/utils/bodyCell/eventTracking.d.ts +1 -1
  27. package/dist/src/utils/bodyCell/styling.d.ts +3 -8
  28. package/dist/src/utils/bodyCell/types.d.ts +15 -0
  29. package/dist/src/utils/nestedGridRowRenderer.d.ts +16 -0
  30. package/dist/styles.css +1 -1
  31. package/package.json +1 -1
  32. package/src/styles/base.css +12 -0
@@ -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
@@ -177,6 +188,14 @@ export declare class SimpleTableVanilla {
177
188
  * No-op when animations are disabled (which already includes the
178
189
  * prefers-reduced-motion check via {@link AnimationCoordinator.isEnabled}).
179
190
  */
191
+ /**
192
+ * Walk the CURRENT (pre-change) header tree and collect every accessor that
193
+ * is renderable as a header cell given the current collapsed/hidden state —
194
+ * group headers plus the leaf columns visible under them (honoring
195
+ * `showWhen` and the collapsed set). Used by {@link beginAccordionAnimation}
196
+ * to seed the animation coordinator's re-entry guard.
197
+ */
198
+ private collectAccordionRenderableAccessors;
180
199
  private beginAccordionAnimation;
181
200
  private initializeManagers;
182
201
  mount(): void;
@@ -267,6 +286,17 @@ export declare class SimpleTableVanilla {
267
286
  */
268
287
  refitAutoSizeColumns(): void;
269
288
  private render;
289
+ /**
290
+ * Dev-only safeguard. Schedules a one-shot, deferred check that warns when the
291
+ * table is about to render a very large number of rows with no virtualization
292
+ * active (no `height` / `maxHeight` and no bounded `scrollParent`). The check
293
+ * is deferred so external-scroll viewport seeding (which can momentarily leave
294
+ * `contentHeight` undefined on the first paint) has time to settle and we
295
+ * don't cry wolf for a correctly-configured table. Compiled out of production
296
+ * via the NODE_ENV guard. Never throws.
297
+ */
298
+ private maybeScheduleUnvirtualizedRowsWarning;
299
+ private evaluateUnvirtualizedRowsWarning;
270
300
  update(config: Partial<SimpleTableConfig>): void;
271
301
  /** @deprecated Use {@link update} — same behavior. */
272
302
  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
  };
@@ -122,6 +125,7 @@ export declare class RenderOrchestrator {
122
125
  getLastProcessedResult(): ProcessRowsResult | null;
123
126
  /** See {@link TableRenderer.getCurrentBodyLayouts}. */
124
127
  getCurrentBodyLayouts(): Map<HTMLElement, Map<string, CellPosition>>;
128
+ setOnRendererHostDiscard(cb: ((host: HTMLElement) => void) | undefined): void;
125
129
  invalidateCache(type?: "body" | "header" | "context" | "all"): void;
126
130
  computeEffectiveHeaders(headers: HeaderObject[], config: SimpleTableConfig, customTheme: CustomTheme, containerWidth?: number): HeaderObject[];
127
131
  /**
@@ -44,6 +44,13 @@ export interface BodySectionParams {
44
44
  export declare class SectionRenderer {
45
45
  private headerSections;
46
46
  private bodySections;
47
+ /**
48
+ * Callback fired before a body cell host element is permanently removed in
49
+ * the {@link invalidateCache} "all" path (which wipes every rendered cell).
50
+ * Threaded down from the table config so framework adapters can tear down
51
+ * renderer subtrees (React portals, etc.) before the nodes are discarded.
52
+ */
53
+ private onRendererHostDiscard?;
47
54
  private bodyCellsCache;
48
55
  private headerCellsCache;
49
56
  private contextCache;
@@ -64,6 +71,7 @@ export declare class SectionRenderer {
64
71
  private getCachedBodyCells;
65
72
  private getCachedHeaderCells;
66
73
  private getCachedContext;
74
+ setOnRendererHostDiscard(cb: ((host: HTMLElement) => void) | undefined): void;
67
75
  invalidateCache(type?: "body" | "header" | "context" | "all"): void;
68
76
  /**
69
77
  * Get the next colIndex after rendering a section
@@ -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;
@@ -96,6 +99,7 @@ export declare class TableRenderer {
96
99
  private pendingRenderCallback;
97
100
  constructor();
98
101
  private scheduleRender;
102
+ setOnRendererHostDiscard(cb: ((host: HTMLElement) => void) | undefined): void;
99
103
  invalidateCache(type?: "body" | "header" | "context" | "all"): void;
100
104
  /** See {@link SectionRenderer.getCurrentBodyLayouts}. */
101
105
  getCurrentBodyLayouts(): Map<HTMLElement, Map<string, CellPosition>>;
@@ -41,6 +41,21 @@ export declare class AnimationCoordinator {
41
41
  * rather than appearing in place. Cleared at the end of {@link play}.
42
42
  */
43
43
  private incomingOrigins;
44
+ /**
45
+ * Accessors that were already renderable (visible leaf/group columns) in the
46
+ * pre-change layout for an in-flight accordion-horizontal toggle. Set once
47
+ * per collapse/expand render and consumed by the renderers' grow-from-zero
48
+ * gate so a column that merely re-enters the virtualization band (because the
49
+ * collapsed group shrank the content width and clamped scrollLeft) is NOT
50
+ * mistaken for a freshly-expanded column and animated from width 0.
51
+ *
52
+ * Header cells have no full pre-change conceptual layout the way body cells do
53
+ * (see SectionRenderer.getCurrentBodyLayouts), so `hasSnapshotEntry` alone
54
+ * can't tell "newly visible" apart from "scrolled back into view". This set
55
+ * supplies the missing pre-change visibility signal. Cleared at the end of
56
+ * {@link play}.
57
+ */
58
+ private accordionPreVisibleAccessors;
44
59
  private inFlight;
45
60
  /** Outgoing cells the renderer handed off; keyed per container so play() finds them. */
46
61
  private retainedCells;
@@ -57,7 +72,46 @@ export declare class AnimationCoordinator {
57
72
  * stable within a single sort.
58
73
  */
59
74
  private scrollerMetricsCache;
75
+ /**
76
+ * Vertical scroller metrics override for external/page-scroll mode. When the
77
+ * table has no internal vertical overflow (it grows to its natural height and
78
+ * a parent element / the window scrolls), the body container's own
79
+ * clientHeight/scrollHeight no longer describe the visible viewport, so
80
+ * {@link scaleFlipDistance} can't bound the FLIP journey and sort cells slide
81
+ * the full conceptual distance. The vanilla table pushes the real visible
82
+ * viewport here (from the same `getExternalScrollMetrics` the virtualizer
83
+ * uses) so the y-axis FLIP scaling matches the on-screen viewport. `null`
84
+ * when external scroll is inactive — internal scroller metrics are used as-is.
85
+ */
86
+ private externalVerticalScroll;
87
+ /**
88
+ * The currently-scheduled (not-yet-started) FLIP frame. play() defers the
89
+ * transition start by two animation frames so the inverted "First" frame
90
+ * gets painted before the transition fires. Spam-clicking sort triggers a
91
+ * full re-render + play() inside that two-frame window: without coalescing,
92
+ * the stale chain's startTransition zeroes the transforms the newer cycle
93
+ * just inverted (a frame early), so the final transition animates
94
+ * identity→identity and nothing visibly moves — and many captured nodes are
95
+ * detached by the intervening render before they ever transition. Tracking
96
+ * the pending frame lets a new play() cancel the prior cycle and reset the
97
+ * transforms it left behind, so only the latest sort animates.
98
+ */
99
+ private scheduledFlip;
100
+ /**
101
+ * Invoked immediately BEFORE a retained/ghost element is permanently removed
102
+ * from the DOM (FLIP/shrink/cancel/destroy teardown). Lets framework adapters
103
+ * tear down renderer subtrees (React portals, etc.) mounted into the element
104
+ * before it's discarded. NOT called on reuse/reparent paths
105
+ * ({@link claimRetainedForReuse} success), so a reclaimed ghost keeps its
106
+ * content.
107
+ */
108
+ private onHostDiscard?;
60
109
  constructor(opts?: AnimationCoordinatorOptions);
110
+ /**
111
+ * Register the callback fired before a ghost/retained element is permanently
112
+ * removed (see {@link onHostDiscard}). Additive: passing `undefined` disables it.
113
+ */
114
+ setOnHostDiscard(cb: ((host: HTMLElement) => void) | undefined): void;
61
115
  setEnabled(enabled: boolean): void;
62
116
  setDuration(duration: number): void;
63
117
  setEasing(easing: string): void;
@@ -76,6 +130,21 @@ export declare class AnimationCoordinator {
76
130
  * the corresponding cells.
77
131
  */
78
132
  setIncomingOrigins(origins: Map<string, CellPosition> | null): void;
133
+ /**
134
+ * Register the set of accessors that were renderable in the pre-change layout
135
+ * of an accordion-horizontal toggle. Must be set after `captureSnapshot` and
136
+ * before the render that creates cells. Consumed and cleared by the next
137
+ * {@link play}. Pass `null` (e.g. for vertical/row accordions) to disable the
138
+ * re-entry guard so behavior is unchanged.
139
+ */
140
+ setAccordionPreVisibleAccessors(accessors: Set<string> | null): void;
141
+ /**
142
+ * True when `accessor` was already a renderable column before the current
143
+ * accordion-horizontal toggle. Renderers use this to skip the grow-from-zero
144
+ * animation for columns that only re-entered the virtualization band rather
145
+ * than genuinely becoming visible from an expand.
146
+ */
147
+ wasRenderableBeforeAccordion(accessor: string): boolean;
79
148
  /**
80
149
  * Read scroller layout metrics for `container`, caching the result for the
81
150
  * remainder of the current render cycle. Subsequent calls in the same
@@ -84,6 +153,18 @@ export declare class AnimationCoordinator {
84
153
  * mutation in the loop.
85
154
  */
86
155
  private getScrollerMetrics;
156
+ /**
157
+ * Supply (or clear) the vertical scroller metrics override used by
158
+ * {@link scaleFlipDistance} in external/page-scroll mode. Must be set before
159
+ * `captureSnapshot`/`retainCell`/`play` so the whole FLIP cycle scales
160
+ * against the real visible viewport. Pass `null` to fall back to the body
161
+ * container's own metrics (internal scroll).
162
+ */
163
+ setExternalVerticalScroll(metrics: {
164
+ clientHeight: number;
165
+ scrollHeight: number;
166
+ scrollTop: number;
167
+ } | null): void;
87
168
  private clearScrollerMetricsCache;
88
169
  /**
89
170
  * Capture pre-change positions for cells we may want to animate.
@@ -72,6 +72,16 @@ export interface SimpleTableConfig {
72
72
  onPageChange?: (page: number) => void | Promise<void>;
73
73
  onRowGroupExpand?: (props: OnRowGroupExpandProps) => void | Promise<void>;
74
74
  onRowSelectionChange?: (props: RowSelectionChangeProps) => void;
75
+ /**
76
+ * Called by the renderer immediately BEFORE it permanently discards a host
77
+ * element that may contain async-framework renderer output (e.g. React
78
+ * portals): innerHTML clears on cell rebuild/edit, plain cell removal, and
79
+ * the animation coordinator's ghost/FLIP/shrink teardown paths. Framework
80
+ * adapters use this to tear down the renderer subtree mounted into `host`
81
+ * (or any descendant) so it isn't orphaned. Reuse/reparent paths never fire
82
+ * it, so a reused node keeps its renderer content.
83
+ */
84
+ onRendererHostDiscard?: (host: HTMLElement) => void;
75
85
  onSortChange?: (sort: SortColumn | null) => void;
76
86
  quickFilter?: QuickFilterConfig;
77
87
  rowButtons?: RowButton[];
@@ -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,3 +1,3 @@
1
1
  export declare const addTrackedEventListener: (element: HTMLElement, event: string, handler: EventListener, options?: AddEventListenerOptions) => void;
2
2
  export declare const getRenderedCells: (container: HTMLElement) => Map<string, HTMLElement>;
3
- export declare const cleanupBodyCellRendering: (container?: HTMLElement) => void;
3
+ export declare const cleanupBodyCellRendering: (container?: HTMLElement, onHostDiscard?: ((host: HTMLElement) => void) | undefined) => void;
@@ -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 {
@@ -103,6 +104,14 @@ export interface CellRenderContext {
103
104
  handleRowSelect?: (rowId: string, checked: boolean) => void;
104
105
  handleMouseDown: (cell: CellData) => void;
105
106
  handleMouseOver: (cell: CellData, clientX: number, clientY: number) => void;
107
+ /**
108
+ * Called immediately BEFORE the renderer permanently discards a host element
109
+ * (e.g. `innerHTML = ""` on cell rebuild/edit, or a plain `element.remove()`).
110
+ * Framework adapters use this to tear down any renderer subtree (React
111
+ * portal, etc.) mounted into `host` or one of its descendants. Reuse paths
112
+ * never call it, so a reused node keeps its content.
113
+ */
114
+ onRendererHostDiscard?: (host: HTMLElement) => void;
106
115
  cellRegistry?: Map<string, CellRegistryEntry>;
107
116
  setCollapsedRows: Dispatch<SetStateAction<Map<string, number>>>;
108
117
  setExpandedRows: Dispatch<SetStateAction<Map<string, number>>>;
@@ -115,6 +124,12 @@ export interface CellRenderContext {
115
124
  loadingStateRenderer?: VanillaLoadingStateRenderer;
116
125
  errorStateRenderer?: VanillaErrorStateRenderer;
117
126
  emptyStateRenderer?: VanillaEmptyStateRenderer;
127
+ /**
128
+ * Factory used to instantiate nested grid tables. Injected by the host table
129
+ * so {@link nestedGridRowRenderer} never has to import the concrete
130
+ * `SimpleTableVanilla` class (which would create a render-module import cycle).
131
+ */
132
+ createNestedTable?: NestedTableFactory;
118
133
  getBorderClass: (cell: CellData) => string;
119
134
  isSelected: (cell: CellData) => boolean;
120
135
  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"