simple-table-core 3.9.3 → 3.9.7

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 (62) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/cjs/src/consts/general-consts.d.ts +9 -0
  3. package/dist/cjs/src/core/SimpleTableVanilla.d.ts +11 -0
  4. package/dist/cjs/src/core/api/TableAPIImpl.d.ts +2 -0
  5. package/dist/cjs/src/core/initialization/TableInitializer.d.ts +1 -0
  6. package/dist/cjs/src/core/rendering/RenderOrchestrator.d.ts +5 -0
  7. package/dist/cjs/src/core/rendering/TableRenderer.d.ts +2 -0
  8. package/dist/cjs/src/hooks/expandedDepths.d.ts +5 -1
  9. package/dist/cjs/src/index.d.ts +2 -1
  10. package/dist/cjs/src/managers/DimensionManager.d.ts +25 -2
  11. package/dist/cjs/src/managers/RowSelectionManager.d.ts +38 -2
  12. package/dist/cjs/src/types/ColumnEditorConfig.d.ts +8 -1
  13. package/dist/cjs/src/types/RowSelectionMode.d.ts +8 -0
  14. package/dist/cjs/src/types/SimpleTableConfig.d.ts +7 -0
  15. package/dist/cjs/src/types/SimpleTableProps.d.ts +18 -0
  16. package/dist/cjs/src/types/TableAPI.d.ts +12 -0
  17. package/dist/cjs/src/utils/bodyCell/types.d.ts +12 -0
  18. package/dist/cjs/src/utils/headerCell/types.d.ts +2 -0
  19. package/dist/cjs/src/utils/headerWidthUtils.d.ts +12 -2
  20. package/dist/cjs/src/utils/horizontalScrollbarRenderer.d.ts +1 -0
  21. package/dist/cjs/src/utils/rowSelectionUtils.d.ts +24 -1
  22. package/dist/cjs/src/utils/stickyParentsRenderer.d.ts +1 -0
  23. package/dist/cjs/stories/examples/RowSelectionExample.d.ts +1 -0
  24. package/dist/cjs/stories/tests/07-RowSelectionTests.stories.d.ts +32 -0
  25. package/dist/cjs/stories/tests/12-CellSelectionTests.stories.d.ts +40 -0
  26. package/dist/cjs/stories/tests/15-ColumnVisibilityTests.stories.d.ts +8 -0
  27. package/dist/cjs/stories/tests/22-LoadingStateTests.stories.d.ts +32 -0
  28. package/dist/cjs/stories/tests/32-ThemesTests.stories.d.ts +6 -0
  29. package/dist/cjs/stories/tests/46-AutoSizeColumnsTests.stories.d.ts +11 -16
  30. package/dist/cjs/styles.css +1 -1
  31. package/dist/index.es.js +1 -1
  32. package/dist/src/consts/general-consts.d.ts +9 -0
  33. package/dist/src/core/SimpleTableVanilla.d.ts +11 -0
  34. package/dist/src/core/api/TableAPIImpl.d.ts +2 -0
  35. package/dist/src/core/initialization/TableInitializer.d.ts +1 -0
  36. package/dist/src/core/rendering/RenderOrchestrator.d.ts +5 -0
  37. package/dist/src/core/rendering/TableRenderer.d.ts +2 -0
  38. package/dist/src/hooks/expandedDepths.d.ts +5 -1
  39. package/dist/src/index.d.ts +2 -1
  40. package/dist/src/managers/DimensionManager.d.ts +25 -2
  41. package/dist/src/managers/RowSelectionManager.d.ts +38 -2
  42. package/dist/src/types/ColumnEditorConfig.d.ts +8 -1
  43. package/dist/src/types/RowSelectionMode.d.ts +8 -0
  44. package/dist/src/types/SimpleTableConfig.d.ts +7 -0
  45. package/dist/src/types/SimpleTableProps.d.ts +18 -0
  46. package/dist/src/types/TableAPI.d.ts +12 -0
  47. package/dist/src/utils/bodyCell/types.d.ts +12 -0
  48. package/dist/src/utils/headerCell/types.d.ts +2 -0
  49. package/dist/src/utils/headerWidthUtils.d.ts +12 -2
  50. package/dist/src/utils/horizontalScrollbarRenderer.d.ts +1 -0
  51. package/dist/src/utils/rowSelectionUtils.d.ts +24 -1
  52. package/dist/src/utils/stickyParentsRenderer.d.ts +1 -0
  53. package/dist/stories/examples/RowSelectionExample.d.ts +1 -0
  54. package/dist/stories/tests/07-RowSelectionTests.stories.d.ts +32 -0
  55. package/dist/stories/tests/12-CellSelectionTests.stories.d.ts +40 -0
  56. package/dist/stories/tests/15-ColumnVisibilityTests.stories.d.ts +8 -0
  57. package/dist/stories/tests/22-LoadingStateTests.stories.d.ts +32 -0
  58. package/dist/stories/tests/32-ThemesTests.stories.d.ts +6 -0
  59. package/dist/stories/tests/46-AutoSizeColumnsTests.stories.d.ts +11 -16
  60. package/dist/styles.css +1 -1
  61. package/package.json +1 -1
  62. package/src/styles/base.css +28 -3
@@ -8,6 +8,15 @@ export declare const UNVIRTUALIZED_ROW_WARNING_THRESHOLD = 500;
8
8
  export declare const OVERSCAN_PIXELS = 800;
9
9
  export declare const calculateBufferRowCount: (rowHeight: number) => number;
10
10
  export declare const COLUMN_EDIT_WIDTH = 29.5;
11
+ /**
12
+ * Horizontal space reserved for the built-in column-editor toggle strip.
13
+ * Returns 0 when editing is off or the strip is hidden via `showToggle: false`.
14
+ */
15
+ export declare const getColumnEditorStripWidth: (editColumns: boolean | undefined, showToggle?: boolean) => number;
16
+ /**
17
+ * Whether the built-in column-editor toggle strip is visible and takes layout space.
18
+ */
19
+ export declare const isColumnEditorStripVisible: (editColumns: boolean | undefined, showToggle?: boolean) => boolean;
11
20
  export declare const TABLE_HEADER_CELL_WIDTH_DEFAULT = 150;
12
21
  export declare const PINNED_BORDER_WIDTH = 1;
13
22
  export declare const CHART_COLUMN_TYPES: string[];
@@ -60,6 +60,12 @@ export declare class SimpleTableVanilla {
60
60
  private rowStateMap;
61
61
  private announcement;
62
62
  private cellRegistry;
63
+ private static nextHoverScopeId;
64
+ /**
65
+ * Unique id for this table instance. Scopes the module-level row-hover cell
66
+ * map so multiple tables on one page with overlapping rowIds don't cross-hover.
67
+ */
68
+ private readonly hoverScopeId;
63
69
  private headerRegistry;
64
70
  private rowIndexMap;
65
71
  private animationCoordinator;
@@ -337,6 +343,11 @@ export declare class SimpleTableVanilla {
337
343
  update(config: Partial<SimpleTableConfig>): void;
338
344
  /** @deprecated Use {@link update} — same behavior. */
339
345
  updateConfig(config: Partial<SimpleTableConfig>): void;
346
+ /**
347
+ * Create, update, or destroy the RowSelectionManager when enableRowSelection
348
+ * (and related props) change at runtime.
349
+ */
350
+ private syncRowSelectionManager;
340
351
  destroy(): void;
341
352
  getAPI(): TableAPI;
342
353
  }
@@ -5,6 +5,7 @@ import Row from "../../types/Row";
5
5
  import { CustomTheme } from "../../types/CustomTheme";
6
6
  import RowState from "../../types/RowState";
7
7
  import { SelectionManager } from "../../managers/SelectionManager";
8
+ import { RowSelectionManager } from "../../managers/RowSelectionManager";
8
9
  import { SortManager } from "../../managers/SortManager";
9
10
  import { FilterManager } from "../../managers/FilterManager";
10
11
  import { FlattenRowsResult } from "../../utils/rowFlattening";
@@ -43,6 +44,7 @@ export interface TableAPIContext {
43
44
  columnEditorOpen: boolean;
44
45
  expandedDepthsManager: any;
45
46
  selectionManager: SelectionManager | null;
47
+ rowSelectionManager: RowSelectionManager | null;
46
48
  sortManager: SortManager | null;
47
49
  filterManager: FilterManager | null;
48
50
  getCachedFlattenResult?: () => FlattenRowsResult | null;
@@ -16,6 +16,7 @@ export interface ResolvedIcons {
16
16
  }
17
17
  export interface MergedColumnEditorConfig {
18
18
  text: string;
19
+ showToggle: boolean;
19
20
  searchEnabled: boolean;
20
21
  searchPlaceholder: string;
21
22
  allowColumnPinning: boolean;
@@ -49,6 +49,11 @@ export interface RenderContext {
49
49
  getRowStateMap: () => Map<string | number, RowState>;
50
50
  headerRegistry: Map<string, any>;
51
51
  headers: HeaderObject[];
52
+ /**
53
+ * Unique id for this table instance. Scopes row-hover cell tracking so
54
+ * multiple tables on one page with overlapping rowIds don't cross-hover.
55
+ */
56
+ hoverScopeId: string;
52
57
  hoveredHeaderRef: {
53
58
  current: HeaderObject | null;
54
59
  };
@@ -46,6 +46,8 @@ export interface TableRendererDeps {
46
46
  getRowStateMap: () => Map<string | number, any>;
47
47
  headerRegistry: Map<string, any>;
48
48
  headers: HeaderObject[];
49
+ /** Unique id for this table instance — scopes row-hover cell tracking. */
50
+ hoverScopeId: string;
49
51
  hoveredHeaderRef: {
50
52
  current: HeaderObject | null;
51
53
  };
@@ -10,6 +10,8 @@ export declare const initializeExpandedDepths: (expandAll: boolean, rowGrouping?
10
10
  export declare class ExpandedDepthsManager {
11
11
  private expandedDepths;
12
12
  private observers;
13
+ /** Coalesce sync collapseAll→expandDepth into a single observer notification. */
14
+ private notifyMicrotaskScheduled;
13
15
  constructor(expandAll: boolean, rowGrouping?: Accessor[]);
14
16
  /**
15
17
  * Updates the expanded depths when rowGrouping changes
@@ -34,7 +36,9 @@ export declare class ExpandedDepthsManager {
34
36
  */
35
37
  subscribe(callback: (depths: Set<number>) => void): () => void;
36
38
  /**
37
- * Notifies all observers of depth changes
39
+ * Notifies all observers of depth changes.
40
+ * Batched to a microtask so collapseAll() + expandDepth(0) in one turn
41
+ * (marketing "Only Divisions") triggers a single render with the final depths.
38
42
  */
39
43
  private notifyObservers;
40
44
  /**
@@ -23,6 +23,7 @@ import type { FilterCondition, TableFilterState, FilterOperator, StringFilterOpe
23
23
  import type { QuickFilterConfig, QuickFilterGetter, QuickFilterGetterProps, QuickFilterMode } from "./types/QuickFilterTypes";
24
24
  import type { ColumnVisibilityState } from "./types/ColumnVisibilityTypes";
25
25
  import type RowSelectionChangeProps from "./types/RowSelectionChangeProps";
26
+ import type { RowSelectionMode } from "./types/RowSelectionMode";
26
27
  import type CellClickProps from "./types/CellClickProps";
27
28
  import type CellRendererProps from "./types/CellRendererProps";
28
29
  import type { CellRenderer } from "./types/CellRendererProps";
@@ -48,4 +49,4 @@ import type { RowId } from "./types/RowId";
48
49
  import type { PinnedSectionsState } from "./types/PinnedSectionsState";
49
50
  export { SimpleTableVanilla };
50
51
  export { asRows } from "./utils/asRows";
51
- export type { Accessor, AggregationConfig, AggregationType, AnimationsConfig, BoundingBox, Cell, CellChangeProps, CellClickProps, CellRenderer, CellRendererProps, CellValue, ChartOptions, ColumnEditorConfig, ColumnEditorCustomRenderer, ColumnEditorCustomRendererProps, ColumnEditorRowRenderer, ColumnEditorRowRendererComponents, ColumnEditorRowRendererProps, ColumnEditorSearchFunction, ColumnType, ColumnVisibilityState, Comparator, ComparatorProps, CustomTheme, CustomThemeProps, DragHandlerProps, EmptyStateRenderer, EmptyStateRendererProps, EnumOption, ErrorStateRenderer, ErrorStateRendererProps, ExportToCSVProps, ExportValueGetter, ExportValueProps, FilterCondition, FilterOperator, StringFilterOperator, NumberFilterOperator, BooleanFilterOperator, DateFilterOperator, EnumFilterOperator, FooterRendererProps, FooterPosition, GetRowId, GetRowIdParams, IconsConfig, LoadingStateRenderer, LoadingStateRendererProps, HeaderDropdown, HeaderDropdownProps, HeaderObject, HeaderRenderer, HeaderRendererProps, HeaderRendererComponents, OnRowGroupExpandProps, OnSortProps, QuickFilterConfig, QuickFilterGetter, QuickFilterGetterProps, QuickFilterMode, Row, RowButtonProps, RowId, RowSelectionChangeProps, RowState, SetHeaderRenameProps, SharedTableProps, ShowWhen, SimpleTableConfig, SimpleTableProps, SortColumn, TableAPI, TableFilterState, TableHeaderProps, TableRowProps, Theme, PinnedSectionsState, UpdateDataProps, ValueFormatter, ValueFormatterProps, ValueGetter, ValueGetterProps, };
52
+ export type { Accessor, AggregationConfig, AggregationType, AnimationsConfig, BoundingBox, Cell, CellChangeProps, CellClickProps, CellRenderer, CellRendererProps, CellValue, ChartOptions, ColumnEditorConfig, ColumnEditorCustomRenderer, ColumnEditorCustomRendererProps, ColumnEditorRowRenderer, ColumnEditorRowRendererComponents, ColumnEditorRowRendererProps, ColumnEditorSearchFunction, ColumnType, ColumnVisibilityState, Comparator, ComparatorProps, CustomTheme, CustomThemeProps, DragHandlerProps, EmptyStateRenderer, EmptyStateRendererProps, EnumOption, ErrorStateRenderer, ErrorStateRendererProps, ExportToCSVProps, ExportValueGetter, ExportValueProps, FilterCondition, FilterOperator, StringFilterOperator, NumberFilterOperator, BooleanFilterOperator, DateFilterOperator, EnumFilterOperator, FooterRendererProps, FooterPosition, GetRowId, GetRowIdParams, IconsConfig, LoadingStateRenderer, LoadingStateRendererProps, HeaderDropdown, HeaderDropdownProps, HeaderObject, HeaderRenderer, HeaderRendererProps, HeaderRendererComponents, OnRowGroupExpandProps, OnSortProps, QuickFilterConfig, QuickFilterGetter, QuickFilterGetterProps, QuickFilterMode, Row, RowButtonProps, RowId, RowSelectionChangeProps, RowSelectionMode, RowState, SetHeaderRenameProps, SharedTableProps, ShowWhen, SimpleTableConfig, SimpleTableProps, SortColumn, TableAPI, TableFilterState, TableHeaderProps, TableRowProps, Theme, PinnedSectionsState, UpdateDataProps, ValueFormatter, ValueFormatterProps, ValueGetter, ValueGetterProps, };
@@ -26,8 +26,17 @@ type StateChangeCallback = (state: DimensionManagerState) => void;
26
26
  * notifying subscribers. Coalesces CSS-transition / animated layout shifts
27
27
  * (e.g. a collapsible nav) into a single trailing update instead of one full
28
28
  * table render per animation frame.
29
+ *
30
+ * Kept above typical frame-budget jank (~50–80ms) so a hitch mid-transition
31
+ * does not look like "animation ended" and fire an extra full relayout.
29
32
  */
30
- export declare const CONTAINER_RESIZE_NOTIFY_DEBOUNCE_MS = 50;
33
+ export declare const CONTAINER_RESIZE_NOTIFY_DEBOUNCE_MS = 100;
34
+ /**
35
+ * After a trailing notify, keep the burst open this long. A jank-sized quiet
36
+ * gap mid-animation must not start a fresh burst (which would allow another
37
+ * pair of notifies and thrash subscribers).
38
+ */
39
+ export declare const CONTAINER_RESIZE_BURST_END_MS = 150;
31
40
  export declare class DimensionManager {
32
41
  private config;
33
42
  private state;
@@ -35,6 +44,11 @@ export declare class DimensionManager {
35
44
  private resizeObserver;
36
45
  private rafId;
37
46
  private resizeNotifyDebounceId;
47
+ private resizeBurstEndId;
48
+ /** Notifies emitted in the current continuous resize burst (capped at 2). */
49
+ private resizeBurstNotifyCount;
50
+ /** True when a 3rd+ trailing tick was suppressed; flush latest width on burst end. */
51
+ private resizeBurstNeedsFinalFlush;
38
52
  /** Set when applyContainerWidthSync updates state before any subscriber exists. */
39
53
  private initialNotifyPending;
40
54
  constructor(config: DimensionManagerConfig);
@@ -44,7 +58,16 @@ export declare class DimensionManager {
44
58
  private convertHeightToPixels;
45
59
  private calculateContentHeight;
46
60
  private cancelPendingResizeNotify;
47
- /** Trailing debounce for animated / continuous container resizes. */
61
+ private cancelResizeBurstEnd;
62
+ private scheduleResizeBurstEnd;
63
+ /**
64
+ * Trailing debounce for animated / continuous container resizes.
65
+ *
66
+ * Per burst (continuous RO ticks separated by less than {@link CONTAINER_RESIZE_BURST_END_MS}):
67
+ * - 1st quiet gap → notify immediately (sole update, or mid-animation pass)
68
+ * - later quiet gaps → defer to burst-end so subscribers always see the final
69
+ * width without a 3rd+ notify when frame timing is janky
70
+ */
48
71
  private scheduleResizeNotify;
49
72
  private observeContainer;
50
73
  private applyContainerWidthSync;
@@ -1,36 +1,72 @@
1
1
  import TableRow from "../types/TableRow";
2
+ import Row from "../types/Row";
2
3
  import RowSelectionChangeProps from "../types/RowSelectionChangeProps";
4
+ import type { RowSelectionMode } from "../types/RowSelectionMode";
3
5
  export interface RowSelectionManagerConfig {
4
6
  tableRows: TableRow[];
5
7
  onRowSelectionChange?: (props: RowSelectionChangeProps) => void;
6
8
  enableRowSelection?: boolean;
9
+ rowSelectionMode?: RowSelectionMode;
10
+ selectRowOnClick?: boolean;
11
+ showRowSelectionColumn?: boolean;
12
+ /** When true, Arrow/Home/End/Ctrl+A are left to SelectionManager; Space still toggles rows. */
13
+ selectableCells?: boolean;
14
+ /** Table root element used to decide whether keyboard events apply. */
15
+ tableRoot?: HTMLElement | null;
7
16
  }
8
17
  export interface RowSelectionManagerState {
9
18
  selectedRows: Set<string>;
10
19
  selectedRowCount: number;
11
- selectedRowsData: any[];
20
+ selectedRowsData: Row[];
21
+ /** Keyboard focus / navigation target row id */
22
+ activeRowId: string | null;
12
23
  }
13
24
  type StateChangeCallback = (state: RowSelectionManagerState) => void;
14
25
  export declare class RowSelectionManager {
15
26
  private config;
16
27
  private state;
17
28
  private subscribers;
29
+ /** Anchor for Shift+range selection */
30
+ private anchorRowId;
31
+ private keydownHandler;
18
32
  constructor(config: RowSelectionManagerConfig);
19
33
  updateConfig(config: Partial<RowSelectionManagerConfig>): void;
34
+ private getMode;
20
35
  private updateDerivedState;
21
36
  subscribe(callback: StateChangeCallback): () => void;
22
37
  private notifySubscribers;
38
+ private fireChange;
39
+ private applySelection;
23
40
  isRowSelected(rowId: string): boolean;
24
41
  areAllRowsSelected(): boolean;
25
42
  getSelectedRows(): Set<string>;
26
43
  getSelectedRowCount(): number;
27
- getSelectedRowsData(): any[];
44
+ getSelectedRowsData(): Row[];
45
+ getRow(rowId: string): Row | undefined;
46
+ getActiveRowId(): string | null;
47
+ setActiveRowId(rowId: string | null): void;
28
48
  setSelectedRows(selectedRows: Set<string>): void;
49
+ /**
50
+ * Set a row's selected state (does not toggle). Respects single/multiple mode.
51
+ */
29
52
  handleRowSelect(rowId: string, isSelected: boolean): void;
53
+ selectRow(rowId: string): void;
54
+ deselectRow(rowId: string): void;
30
55
  handleSelectAll(isSelected: boolean): void;
31
56
  handleToggleRow(rowId: string): void;
57
+ /**
58
+ * Click-to-select: multiple toggles; single replaces.
59
+ */
60
+ handleRowClickSelect(rowId: string): void;
32
61
  clearSelection(): void;
33
62
  getState(): RowSelectionManagerState;
63
+ private setupKeyboardNavigation;
64
+ private isEventInsideTable;
65
+ private isTypingInFormField;
66
+ private findRowIndex;
67
+ private resolveActiveRowId;
68
+ private moveActiveRow;
69
+ private handleKeyDown;
34
70
  destroy(): void;
35
71
  }
36
72
  export {};
@@ -14,6 +14,13 @@ export type ColumnEditorSearchFunction = (header: HeaderObject, searchTerm: stri
14
14
  export interface ColumnEditorConfig {
15
15
  /** Text displayed on the column editor button (default: "Columns") */
16
16
  text?: string;
17
+ /**
18
+ * When false, hides the built-in vertical "Columns" toggle strip while keeping
19
+ * the column editor popout and `toggleColumnEditor()` API available.
20
+ * Use this when opening the editor from an external toolbar button.
21
+ * Default: true.
22
+ */
23
+ showToggle?: boolean;
17
24
  /** Enable search functionality in the column editor (default: true) */
18
25
  searchEnabled?: boolean;
19
26
  /** Placeholder text for the search input (default: "Search columns...") */
@@ -32,4 +39,4 @@ export interface ColumnEditorConfig {
32
39
  }
33
40
  export declare const DEFAULT_COLUMN_EDITOR_CONFIG: Required<Omit<ColumnEditorConfig, "searchFunction" | "rowRenderer" | "customRenderer">>;
34
41
  /** Column editor config with defaults applied (text, searchEnabled, searchPlaceholder are required) */
35
- export type MergedColumnEditorConfig = Required<Pick<ColumnEditorConfig, "text" | "searchEnabled" | "searchPlaceholder" | "allowColumnPinning">> & Pick<ColumnEditorConfig, "searchFunction" | "rowRenderer" | "customRenderer">;
42
+ export type MergedColumnEditorConfig = Required<Pick<ColumnEditorConfig, "text" | "showToggle" | "searchEnabled" | "searchPlaceholder" | "allowColumnPinning">> & Pick<ColumnEditorConfig, "searchFunction" | "rowRenderer" | "customRenderer">;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Row selection mode.
3
+ * - `multiple` (default): select any number of rows; select-all is available when the checkbox column is shown
4
+ * - `single`: selecting a row replaces the previous selection; select-all is hidden
5
+ */
6
+ type RowSelectionMode = "single" | "multiple";
7
+ export type { RowSelectionMode };
8
+ export default RowSelectionMode;
@@ -11,6 +11,7 @@ import { TableFilterState } from "./FilterTypes";
11
11
  import OnNextPage from "./OnNextPage";
12
12
  import OnRowGroupExpandProps from "./OnRowGroupExpandProps";
13
13
  import RowSelectionChangeProps from "./RowSelectionChangeProps";
14
+ import type { RowSelectionMode } from "./RowSelectionMode";
14
15
  import { RowButton } from "./RowButton";
15
16
  import Theme from "./Theme";
16
17
  import { CustomThemeProps } from "./CustomTheme";
@@ -45,6 +46,12 @@ export interface SimpleTableConfig {
45
46
  emptyStateRenderer?: VanillaEmptyStateRenderer;
46
47
  enableHeaderEditing?: boolean;
47
48
  enableRowSelection?: boolean;
49
+ /** @see SimpleTableProps.rowSelectionMode */
50
+ rowSelectionMode?: RowSelectionMode;
51
+ /** @see SimpleTableProps.selectRowOnClick */
52
+ selectRowOnClick?: boolean;
53
+ /** @see SimpleTableProps.showRowSelectionColumn */
54
+ showRowSelectionColumn?: boolean;
48
55
  enableStickyParents?: boolean;
49
56
  errorStateRenderer?: VanillaErrorStateRenderer;
50
57
  expandAll?: boolean;
@@ -11,6 +11,7 @@ import { TableFilterState } from "./FilterTypes";
11
11
  import OnNextPage from "./OnNextPage";
12
12
  import OnRowGroupExpandProps from "./OnRowGroupExpandProps";
13
13
  import RowSelectionChangeProps from "./RowSelectionChangeProps";
14
+ import type { RowSelectionMode } from "./RowSelectionMode";
14
15
  import { RowButton } from "./RowButton";
15
16
  import Theme from "./Theme";
16
17
  import { CustomThemeProps } from "./CustomTheme";
@@ -38,6 +39,23 @@ export interface SimpleTableProps {
38
39
  emptyStateRenderer?: EmptyStateRenderer;
39
40
  enableHeaderEditing?: boolean;
40
41
  enableRowSelection?: boolean;
42
+ /**
43
+ * Row selection mode when `enableRowSelection` is true.
44
+ * - `"multiple"` (default): select any number of rows
45
+ * - `"single"`: selecting a row replaces the previous selection
46
+ */
47
+ rowSelectionMode?: RowSelectionMode;
48
+ /**
49
+ * When true, clicking a data cell selects the row (toggles in multiple mode,
50
+ * replaces selection in single mode). Default false.
51
+ */
52
+ selectRowOnClick?: boolean;
53
+ /**
54
+ * When false, the checkbox selection column is not shown; selection still works
55
+ * via click, keyboard, or TableAPI. Default true. The column is still shown when
56
+ * `rowButtons` is set (buttons need a home).
57
+ */
58
+ showRowSelectionColumn?: boolean;
41
59
  enableStickyParents?: boolean;
42
60
  errorStateRenderer?: ErrorStateRenderer;
43
61
  expandAll?: boolean;
@@ -1,6 +1,7 @@
1
1
  import UpdateDataProps from "./UpdateCellProps";
2
2
  import HeaderObject, { Accessor } from "./HeaderObject";
3
3
  import TableRow from "./TableRow";
4
+ import Row from "./Row";
4
5
  import SortColumn, { SortDirection } from "./SortColumn";
5
6
  import { TableFilterState, FilterCondition } from "./FilterTypes";
6
7
  import Cell from "./Cell";
@@ -59,4 +60,15 @@ export type TableAPI = {
59
60
  clearSelection: () => void;
60
61
  selectCell: (cell: Cell) => void;
61
62
  selectCellRange: (startCell: Cell, endCell: Cell) => void;
63
+ /** Selected row IDs when row selection is enabled. */
64
+ getSelectedRows: () => Set<string>;
65
+ /** Row data objects for currently selected rows (resolved from visible/current table rows). */
66
+ getSelectedRowsData: () => Row[];
67
+ /** Look up a row by its string row id in the current table rows. */
68
+ getRow: (rowId: string) => Row | undefined;
69
+ selectRow: (rowId: string) => void;
70
+ deselectRow: (rowId: string) => void;
71
+ toggleRowSelection: (rowId: string) => void;
72
+ /** Clears row selection only (does not clear cell selection). */
73
+ clearRowSelection: () => void;
62
74
  };
@@ -64,11 +64,21 @@ export interface CellRenderContext {
64
64
  rowsWithSelectedCells: Set<string>;
65
65
  columnBorders: boolean;
66
66
  enableRowSelection?: boolean;
67
+ /** When true, clicking a data cell selects/toggles the row. */
68
+ selectRowOnClick?: boolean;
69
+ rowSelectionMode?: "single" | "multiple";
67
70
  /** Used for context cache invalidation when row selection changes */
68
71
  selectedRowCount?: number;
72
+ /** Keyboard active row id for focus styling */
73
+ activeRowId?: string | null;
69
74
  cellUpdateFlash?: boolean;
70
75
  useOddColumnBackground?: boolean;
71
76
  useHoverRowBackground?: boolean;
77
+ /**
78
+ * Unique id for this table instance. Scopes the module-level row-hover cell
79
+ * map so multiple tables on one page with overlapping rowIds don't cross-hover.
80
+ */
81
+ hoverScopeId: string;
72
82
  useOddEvenRowBackground?: boolean;
73
83
  rowGrouping?: string[];
74
84
  headers: HeaderObject[];
@@ -102,6 +112,8 @@ export interface CellRenderContext {
102
112
  onCellClick?: (params: CellClickParams) => void;
103
113
  onRowGroupExpand?: (props: OnRowGroupExpandProps) => void | Promise<void>;
104
114
  handleRowSelect?: (rowId: string, checked: boolean) => void;
115
+ /** Click-to-select / keyboard toggle entry point (mode-aware). */
116
+ handleToggleRow?: (rowId: string) => void;
105
117
  handleMouseDown: (cell: CellData) => void;
106
118
  handleMouseOver: (cell: CellData, clientX: number, clientY: number) => void;
107
119
  /**
@@ -35,6 +35,8 @@ export interface HeaderRenderContext {
35
35
  draggedHeaderRef: MutableRefObject<HeaderObject | null>;
36
36
  enableHeaderEditing?: boolean;
37
37
  enableRowSelection?: boolean;
38
+ /** When `"single"`, header select-all checkbox is hidden. */
39
+ rowSelectionMode?: "single" | "multiple";
38
40
  filters: TableFilterState;
39
41
  forceUpdate: () => void;
40
42
  getCollapsedHeaders?: () => Set<Accessor>; /** Get current collapsed headers (avoids stale closure in toggle handler). */
@@ -68,7 +68,14 @@ export declare const getAllVisibleLeafHeaders: (headers: HeaderObject[], collaps
68
68
  *
69
69
  * @param accessor - The accessor of the header to measure
70
70
  * @param options - Configuration options
71
- * @returns The optimal width in pixels
71
+ * @returns Measured width plus whether the result is final (`settled`). When a
72
+ * custom `cellRenderer` / `headerRenderer` exists but its real DOM is not
73
+ * measurable yet (async portal / loading skeleton), `settled` is false and
74
+ * the width is provisional (header / minWidth only — never `valueFormatter`
75
+ * or plain `label` as a stand-in for renderer output). Callers should apply
76
+ * that provisional width once and re-measure later via an explicit refit
77
+ * (rows / isLoading / `refitAutoSizeColumns`) — not by leaving the column
78
+ * pending across every render.
72
79
  */
73
80
  export declare const calculateHeaderContentWidth: (accessor: Accessor, options?: {
74
81
  rows?: any[] | undefined;
@@ -108,4 +115,7 @@ export declare const calculateHeaderContentWidth: (accessor: Accessor, options?:
108
115
  * without this, autofit sampling leaks those registrations.
109
116
  */
110
117
  onRendererHostDiscard?: ((host: HTMLElement) => void) | undefined;
111
- } | undefined) => number;
118
+ } | undefined) => {
119
+ width: number;
120
+ settled: boolean;
121
+ };
@@ -7,6 +7,7 @@ export interface HorizontalScrollbarProps {
7
7
  pinnedLeftContentWidth: number;
8
8
  pinnedRightContentWidth: number;
9
9
  tableBodyContainerRef: HTMLDivElement;
10
+ /** True when the column-editor toggle strip is visible and reserves horizontal space. */
10
11
  editColumns: boolean;
11
12
  sectionScrollController?: SectionScrollController | null;
12
13
  /**
@@ -1,6 +1,16 @@
1
1
  import Row from "../types/Row";
2
2
  import TableRow from "../types/TableRow";
3
3
  import HeaderObject from "../types/HeaderObject";
4
+ import type { RowSelectionMode } from "../types/RowSelectionMode";
5
+ /**
6
+ * Whether the checkbox / row-buttons column should be injected into headers.
7
+ * Always shown when `rowButtons` is set (buttons need a home).
8
+ */
9
+ export declare const shouldShowRowSelectionColumn: (config: {
10
+ enableRowSelection?: boolean;
11
+ showRowSelectionColumn?: boolean;
12
+ rowButtons?: unknown[];
13
+ }) => boolean;
4
14
  /**
5
15
  * Get the set of selected row IDs from an array of table rows
6
16
  */
@@ -14,9 +24,18 @@ export declare const isRowSelected: (rowId: string, selectedRows: Set<string>) =
14
24
  */
15
25
  export declare const areAllRowsSelected: (tableRows: TableRow[], selectedRows: Set<string>) => boolean;
16
26
  /**
17
- * Toggle selection of a single row
27
+ * Toggle selection of a single row (multiple mode).
18
28
  */
19
29
  export declare const toggleRowSelection: (rowId: string, selectedRows: Set<string>) => Set<string>;
30
+ /**
31
+ * Set whether a row is selected, respecting selection mode.
32
+ */
33
+ export declare const setRowSelected: (rowId: string, isSelected: boolean, selectedRows: Set<string>, mode?: RowSelectionMode) => Set<string>;
34
+ /**
35
+ * Select a range of visible rows (inclusive) by index into `tableRows`.
36
+ * Used for Shift+arrow keyboard range selection in multiple mode.
37
+ */
38
+ export declare const selectRowRange: (tableRows: TableRow[], startIndex: number, endIndex: number, baseSelection?: Set<string>) => Set<string>;
20
39
  /**
21
40
  * Select all rows
22
41
  */
@@ -29,6 +48,10 @@ export declare const deselectAllRows: () => Set<string>;
29
48
  * Get the selected rows from the table rows array
30
49
  */
31
50
  export declare const getSelectedRows: (tableRows: TableRow[], selectedRows: Set<string>) => Row[];
51
+ /**
52
+ * Find a row by its string row id in the current table rows.
53
+ */
54
+ export declare const findRowById: (tableRows: TableRow[], rowId: string) => Row | undefined;
32
55
  /**
33
56
  * Get the count of selected rows
34
57
  */
@@ -41,6 +41,7 @@ export interface StickyParentsContainerProps {
41
41
  export interface StickyParentsRenderContext {
42
42
  collapsedHeaders: Set<string>;
43
43
  customTheme: CustomTheme;
44
+ /** True when the column-editor toggle strip is visible and reserves horizontal space. */
44
45
  editColumns: boolean;
45
46
  headers: HeaderObject[];
46
47
  rowHeight: number;
@@ -5,6 +5,7 @@ export declare const rowSelectionExampleDefaults: {
5
5
  selectableCells: boolean;
6
6
  columnReordering: boolean;
7
7
  enableRowSelection: boolean;
8
+ selectRowOnClick: boolean;
8
9
  height: string;
9
10
  };
10
11
  export declare function renderRowSelectionExample(args?: Partial<UniversalVanillaArgs>): HTMLElement;
@@ -67,3 +67,35 @@ export declare const SelectionPersistsThroughFilter: {
67
67
  canvasElement: HTMLElement;
68
68
  }) => Promise<void>;
69
69
  };
70
+ export declare const SingleSelectionMode: {
71
+ render: () => HTMLDivElement & {
72
+ _table?: SimpleTableVanilla | undefined;
73
+ };
74
+ play: ({ canvasElement }: {
75
+ canvasElement: HTMLElement;
76
+ }) => Promise<void>;
77
+ };
78
+ export declare const ClickToSelectWithoutCheckboxColumn: {
79
+ render: () => HTMLDivElement & {
80
+ _table?: SimpleTableVanilla | undefined;
81
+ };
82
+ play: ({ canvasElement }: {
83
+ canvasElement: HTMLElement;
84
+ }) => Promise<void>;
85
+ };
86
+ export declare const KeyboardRowSelection: {
87
+ render: () => HTMLDivElement & {
88
+ _table?: SimpleTableVanilla | undefined;
89
+ };
90
+ play: ({ canvasElement }: {
91
+ canvasElement: HTMLElement;
92
+ }) => Promise<void>;
93
+ };
94
+ export declare const TableAPIRowSelection: {
95
+ render: () => HTMLDivElement & {
96
+ _table?: SimpleTableVanilla | undefined;
97
+ };
98
+ play: ({ canvasElement }: {
99
+ canvasElement: HTMLElement;
100
+ }) => Promise<void>;
101
+ };
@@ -154,6 +154,46 @@ export declare const ShiftArrowExtendsSelection: {
154
154
  canvasElement: HTMLElement;
155
155
  }) => Promise<void>;
156
156
  };
157
+ /**
158
+ * Spreadsheet-style Shift+Arrow: expand a range, then contract it back toward the
159
+ * anchor. Shift+ArrowUp after expanding downward must shrink the selection (not
160
+ * jump/expand the opposite edge).
161
+ */
162
+ export declare const ShiftArrowContractsSelection: {
163
+ tags: string[];
164
+ render: () => HTMLDivElement & {
165
+ _table?: import("../../src/index").SimpleTableVanilla | undefined;
166
+ };
167
+ play: ({ canvasElement }: {
168
+ canvasElement: HTMLElement;
169
+ }) => Promise<void>;
170
+ };
171
+ /**
172
+ * After a mouse-drag range, Shift+Arrow must continue from the drag endpoint
173
+ * (spreadsheet active cell), contracting/expanding that free end — not restart
174
+ * from the mousedown anchor and collapse the range.
175
+ */
176
+ export declare const ShiftArrowContractsAfterMouseDrag: {
177
+ tags: string[];
178
+ render: () => HTMLDivElement & {
179
+ _table?: import("../../src/index").SimpleTableVanilla | undefined;
180
+ };
181
+ play: ({ canvasElement }: {
182
+ canvasElement: HTMLElement;
183
+ }) => Promise<void>;
184
+ };
185
+ /**
186
+ * Horizontal Shift+Arrow expand then contract toward the column anchor.
187
+ */
188
+ export declare const ShiftArrowContractsHorizontalSelection: {
189
+ tags: string[];
190
+ render: () => HTMLDivElement & {
191
+ _table?: import("../../src/index").SimpleTableVanilla | undefined;
192
+ };
193
+ play: ({ canvasElement }: {
194
+ canvasElement: HTMLElement;
195
+ }) => Promise<void>;
196
+ };
157
197
  export declare const CtrlASelectsAllCells: {
158
198
  render: () => HTMLDivElement & {
159
199
  _table?: import("../../src/index").SimpleTableVanilla | undefined;
@@ -133,3 +133,11 @@ export declare const ColumnEditorRowRenderer: {
133
133
  canvasElement: HTMLElement;
134
134
  }) => Promise<void>;
135
135
  };
136
+ export declare const ColumnEditorConfigShowToggleFalse: {
137
+ render: () => HTMLDivElement & {
138
+ _table?: import("../../src/index").SimpleTableVanilla | undefined;
139
+ };
140
+ play: ({ canvasElement }: {
141
+ canvasElement: HTMLElement;
142
+ }) => Promise<void>;
143
+ };
@@ -53,3 +53,35 @@ export declare const LoadingToLoadedRemovesStaleCells: {
53
53
  canvasElement: HTMLElement;
54
54
  }) => Promise<void>;
55
55
  };
56
+ /**
57
+ * Repro: `updateBodyCellElement` skips content rebuilds for expandable cells
58
+ * so the expand-icon DOM node survives for CSS transitions. That bypass also
59
+ * skips loading-skeleton swaps, so toggling `isLoading` on already-rendered
60
+ * row-grouped rows leaves the expandable column out of sync with every other
61
+ * column.
62
+ *
63
+ * Entering loading: non-expandable columns show skeletons; expandable columns
64
+ * keep their stale expand icon + value.
65
+ */
66
+ export declare const ExpandableCellsShowSkeletonWhenEnteringLoading: {
67
+ render: () => HTMLDivElement & {
68
+ _table?: SimpleTableVanilla | undefined;
69
+ };
70
+ play: ({ canvasElement }: {
71
+ canvasElement: HTMLElement;
72
+ }) => Promise<void>;
73
+ };
74
+ /**
75
+ * Repro (exit path): expandable cells created while `isLoading` is true render
76
+ * as skeletons. When loading ends, content updates are still skipped for
77
+ * expandable cells, so they stay stuck on the skeleton instead of restoring
78
+ * the expand icon + value.
79
+ */
80
+ export declare const ExpandableCellsRestoreContentWhenLeavingLoading: {
81
+ render: () => HTMLDivElement & {
82
+ _table?: SimpleTableVanilla | undefined;
83
+ };
84
+ play: ({ canvasElement }: {
85
+ canvasElement: HTMLElement;
86
+ }) => Promise<void>;
87
+ };
@@ -53,6 +53,12 @@ export declare const UseHoverRowBackground: {
53
53
  canvasElement: HTMLElement;
54
54
  }) => Promise<void>;
55
55
  };
56
+ export declare const UseHoverRowBackgroundIsolatedAcrossTables: {
57
+ render: () => HTMLDivElement;
58
+ play: ({ canvasElement }: {
59
+ canvasElement: HTMLElement;
60
+ }) => Promise<void>;
61
+ };
56
62
  export declare const UseOddEvenRowBackground: {
57
63
  tags: string[];
58
64
  render: () => HTMLDivElement & {