@rozie-ui/data-table-lit 0.7.0 → 0.7.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.
package/src/DataTable.ts CHANGED
@@ -46,63 +46,167 @@ import { columnSpecsEquivalent } from './helpers/columnDefUtils';
46
46
 
47
47
  // The registry API handed to <Column> children (whole-object-replace — T-48-PP guard).
48
48
 
49
+ import type { Column as TableColumn, ColumnDef, ColumnFiltersState, ColumnOrderState, ColumnPinningState, ColumnSizingState, ExpandedState, GroupingState, PaginationState, RowSelectionState, SortingState, VisibilityState } from '@tanstack/table-core';
50
+
51
+ /** A cell position as integers over the visible (display-order) model. */
52
+ export interface DataTableCellPosition {
53
+ rowIndex: number;
54
+ colIndex: number;
55
+ }
56
+ /** The active (roving-focus) cell. A header cell reports `rowIndex: null` and `isHeader: true`. */
57
+ export interface DataTableActiveCell {
58
+ rowIndex: number | null;
59
+ colIndex: number;
60
+ isHeader: boolean;
61
+ }
62
+ /** The rectangular cell-range selection. Both corners are `null` when there is no range. */
63
+ export interface DataTableRange {
64
+ anchor: DataTableCellPosition | null;
65
+ focus: DataTableCellPosition | null;
66
+ }
67
+ /** One data column offered to the `#groupBar` slot. */
68
+ export interface DataTableGroupableColumn {
69
+ id: string;
70
+ label: string;
71
+ }
72
+ /** One changed cell inside a row edit commit. */
73
+ export interface DataTableCellChange {
74
+ columnId: string;
75
+ oldValue: any;
76
+ newValue: any;
77
+ }
78
+
79
+ /** The `activecell-change` payload. `isHeader` is set when the move landed on or left a header cell. */
80
+ export interface DataTableActiveCellChangePayload {
81
+ rowIndex: number | null;
82
+ colIndex: number;
83
+ isHeader?: boolean;
84
+ }
85
+ /** The `cell-edit-commit` payload: one committed cell. */
86
+ export interface DataTableCellEditCommitPayload {
87
+ rowId: string;
88
+ columnId: string;
89
+ oldValue: any;
90
+ newValue: any;
91
+ }
92
+ /** The `row-edit-commit` payload: the row and every cell the save changed. */
93
+ export interface DataTableRowEditCommitPayload {
94
+ rowId: string;
95
+ changes: DataTableCellChange[];
96
+ }
97
+ /** The `filter-change` payload: `globalFilter` for the search box, `columnFilters` for a per-column filter. Exactly one key is set. */
98
+ export interface DataTableFilterChangePayload {
99
+ globalFilter?: string;
100
+ columnFilters?: ColumnFiltersState;
101
+ }
102
+ /** The `history-change` payload: undo/redo availability. */
103
+ export interface DataTableHistoryChangePayload {
104
+ canUndo: boolean;
105
+ canRedo: boolean;
106
+ }
107
+ /** The `range-change` payload: the new range corners (both `null` when the range cleared). */
108
+ export type DataTableRangeChangePayload = DataTableRange;
109
+ /** The `row-activate` payload. `row` is the original data object and `index` its position in the rendered model. */
110
+ export interface DataTableRowActivatePayload {
111
+ row: any;
112
+ index: number;
113
+ trigger: 'keyboard' | 'click';
114
+ }
115
+ /** The `visible-range-change` payload: the rendered row window, `end` exclusive. */
116
+ export interface DataTableVisibleRangeChangePayload {
117
+ start: number;
118
+ end: number;
119
+ }
120
+
121
+ export interface RozieDataTableEventMap extends Omit<HTMLElementEventMap, 'activecell-change' | 'cell-edit-commit' | 'expand-change' | 'filter-change' | 'group-change' | 'history-change' | 'page-change' | 'pin-change' | 'range-change' | 'reorder-change' | 'resize-change' | 'row-activate' | 'row-edit-commit' | 'selection-change' | 'sort-change' | 'visibility-change' | 'visible-range-change' | 'data-change' | 'sorting-change' | 'global-filter-change' | 'column-filters-change' | 'pagination-change' | 'expanded-change' | 'grouping-change' | 'row-selection-change' | 'column-visibility-change' | 'column-sizing-change' | 'column-order-change' | 'column-pinning-change'> {
122
+ 'activecell-change': CustomEvent<DataTableActiveCellChangePayload>;
123
+ 'cell-edit-commit': CustomEvent<DataTableCellEditCommitPayload>;
124
+ 'expand-change': CustomEvent<ExpandedState>;
125
+ 'filter-change': CustomEvent<DataTableFilterChangePayload>;
126
+ 'group-change': CustomEvent<GroupingState>;
127
+ 'history-change': CustomEvent<DataTableHistoryChangePayload>;
128
+ 'page-change': CustomEvent<PaginationState>;
129
+ 'pin-change': CustomEvent<ColumnPinningState>;
130
+ 'range-change': CustomEvent<DataTableRangeChangePayload>;
131
+ 'reorder-change': CustomEvent<ColumnOrderState>;
132
+ 'resize-change': CustomEvent<ColumnSizingState>;
133
+ 'row-activate': CustomEvent<DataTableRowActivatePayload>;
134
+ 'row-edit-commit': CustomEvent<DataTableRowEditCommitPayload>;
135
+ 'selection-change': CustomEvent<RowSelectionState>;
136
+ 'sort-change': CustomEvent<SortingState>;
137
+ 'visibility-change': CustomEvent<VisibilityState>;
138
+ 'visible-range-change': CustomEvent<DataTableVisibleRangeChangePayload>;
139
+ 'data-change': CustomEvent<any[]>;
140
+ 'sorting-change': CustomEvent<any[]>;
141
+ 'global-filter-change': CustomEvent<string>;
142
+ 'column-filters-change': CustomEvent<any[]>;
143
+ 'pagination-change': CustomEvent<any>;
144
+ 'expanded-change': CustomEvent<any | boolean>;
145
+ 'grouping-change': CustomEvent<any[]>;
146
+ 'row-selection-change': CustomEvent<any>;
147
+ 'column-visibility-change': CustomEvent<any>;
148
+ 'column-sizing-change': CustomEvent<any>;
149
+ 'column-order-change': CustomEvent<any[]>;
150
+ 'column-pinning-change': CustomEvent<any>;
151
+ }
152
+
49
153
  const __rozieCtx_data_table_columns = createContext(Symbol.for("rozie:data-table:columns"));
50
154
 
51
155
  interface RozieGroupBarSlotCtx {
52
- grouping: any;
53
- groupableColumns: any;
54
- applyGrouping: any;
55
- clearGrouping: any;
156
+ grouping: string[];
157
+ groupableColumns: DataTableGroupableColumn[];
158
+ applyGrouping: (cols: string[]) => void;
159
+ clearGrouping: () => void;
56
160
  }
57
161
 
58
162
  interface RozieSelectAllSlotCtx {
59
- checked: any;
60
- indeterminate: any;
61
- toggle: any;
163
+ checked: boolean;
164
+ indeterminate: boolean;
165
+ toggle: (event: any) => void;
62
166
  }
63
167
 
64
168
  interface RozieDynamicColHeaderSlotCtx {
65
- columnId: any;
66
- column: any;
67
- label: any;
169
+ columnId: string;
170
+ column: TableColumn<any, unknown>;
171
+ label: string;
68
172
  }
69
173
 
70
174
  interface RozieDynamicFilterSlotCtx {
71
- columnId: any;
175
+ columnId: string;
72
176
  value: any;
73
- uniqueValues: any;
74
- minMax: any;
75
- columnLabel: any;
76
- setFilter: any;
177
+ uniqueValues: any[];
178
+ minMax: [number, number] | null;
179
+ columnLabel: string;
180
+ setFilter: (columnId: string, value: any) => void;
77
181
  }
78
182
 
79
183
  interface RoziePlaceholderSlotCtx {
80
- index: any;
81
- columnId: any;
184
+ index: number;
185
+ columnId: string;
82
186
  }
83
187
 
84
188
  interface RozieSelectCellSlotCtx {
85
189
  row: any;
86
- checked: any;
87
- toggle: any;
190
+ checked: boolean;
191
+ toggle: (event: any) => void;
88
192
  }
89
193
 
90
194
  interface RozieDynamicCellSlotCtx {
91
- columnId: any;
92
- column: any;
195
+ columnId: string;
196
+ column: TableColumn<any, unknown>;
93
197
  row: any;
94
198
  value: any;
95
199
  }
96
200
 
97
201
  interface RozieDynamicEditorSlotCtx {
98
- columnId: any;
99
- column: any;
202
+ columnId: string;
203
+ column: TableColumn<any, unknown>;
100
204
  row: any;
101
205
  value: any;
102
- commit: any;
103
- cancel: any;
104
- columnLabel: any;
105
- autofocus: any;
206
+ commit: (value: any) => void;
207
+ cancel: () => void;
208
+ columnLabel: string;
209
+ autofocus: boolean;
106
210
  }
107
211
 
108
212
  interface RozieDetailSlotCtx {
@@ -110,36 +214,36 @@ interface RozieDetailSlotCtx {
110
214
  }
111
215
 
112
216
  interface RozieColHeaderSlotCtx {
113
- columnId: any;
114
- column: any;
115
- label: any;
217
+ columnId: string;
218
+ column: TableColumn<any, unknown>;
219
+ label: string;
116
220
  }
117
221
 
118
222
  interface RozieFilterSlotCtx {
119
- columnId: any;
223
+ columnId: string;
120
224
  value: any;
121
- uniqueValues: any;
122
- minMax: any;
123
- columnLabel: any;
124
- setFilter: any;
225
+ uniqueValues: any[];
226
+ minMax: [number, number] | null;
227
+ columnLabel: string;
228
+ setFilter: (columnId: string, value: any) => void;
125
229
  }
126
230
 
127
231
  interface RozieCellSlotCtx {
128
- columnId: any;
129
- column: any;
232
+ columnId: string;
233
+ column: TableColumn<any, unknown>;
130
234
  row: any;
131
235
  value: any;
132
236
  }
133
237
 
134
238
  interface RozieEditorSlotCtx {
135
- columnId: any;
136
- column: any;
239
+ columnId: string;
240
+ column: TableColumn<any, unknown>;
137
241
  row: any;
138
242
  value: any;
139
- commit: any;
140
- cancel: any;
141
- columnLabel: any;
142
- autofocus: any;
243
+ commit: (value: any) => void;
244
+ cancel: () => void;
245
+ columnLabel: string;
246
+ autofocus: boolean;
143
247
  }
144
248
 
145
249
  @customElement('rozie-data-table')
@@ -585,7 +689,7 @@ export default class DataTable extends SignalWatcher(LitElement) {
585
689
  /**
586
690
  * Row-selection mode: `'none'` | `'single'` | `'multiple'`. `'multiple'` auto-injects a leading checkbox column with a select-all header.
587
691
  */
588
- @property({ type: String, reflect: true }) selectionMode: string = 'none';
692
+ @property({ type: String, reflect: true, attribute: 'selection-mode' }) selectionMode: string = 'none';
589
693
  /**
590
694
  * `SortingState` — `[{ id, desc }]`. Uncontrolled fallback when unbound. Two-way: writes funnel a fresh value through the `sort-change` event regardless of binding.
591
695
  */
@@ -619,11 +723,11 @@ export default class DataTable extends SignalWatcher(LitElement) {
619
723
  /**
620
724
  * Total server-side row count for `manual` pagination; lets the table compute page count when it doesn't hold the full dataset.
621
725
  */
622
- @property({ type: Number, reflect: true }) rowCount: number | null = null;
726
+ @property({ type: Number, reflect: true, attribute: 'row-count' }) rowCount: number | null = null;
623
727
  /**
624
728
  * Explicit total page count for `manual` pagination; overrides rowCount-derived count.
625
729
  */
626
- @property({ type: Number, reflect: true }) pageCount: number | null = null;
730
+ @property({ type: Number, reflect: true, attribute: 'page-count' }) pageCount: number | null = null;
627
731
  /**
628
732
  * Opt-in **expandable rows**. When `true`, a leading chevron expander column auto-injects (after the select column) and `getExpandedRowModel` activates; default `false` is byte-identical-off. Every row can expand to reveal a `#detail` panel unless `getSubRows` is supplied (then only rows with children expand). Pass `expandable` as a real boolean — a valueless attribute only coerces to `true` on Vue and Lit.
629
733
  */
@@ -636,11 +740,11 @@ export default class DataTable extends SignalWatcher(LitElement) {
636
740
  /**
637
741
  * Row identity `(originalRow, index, parentRow?) => string | number` — the key `rowSelection`, `expanded` and the per-row caches use. Default null → table-core keys rows by position (`"0"`, `"1"`, … and `"0.1"` for sub-rows), so inserting or removing rows above a selected or expanded row moves that state onto whatever row now sits at its index. Supply it whenever rows can be added or removed while state is held (server push, live lists); the result is coerced to a string.
638
742
  */
639
- @property({ type: Function }) getRowId: ((...args: any[]) => any) | null = null;
743
+ @property({ type: Function, attribute: 'get-row-id' }) getRowId: ((...args: any[]) => any) | null = null;
640
744
  /**
641
745
  * Table-level child-row accessor `(originalRow, index) => TData[] | undefined` that drives nested sub-rows. When supplied (with `expandable`), table-core flattens the hierarchy and the expand seam reveals depth-indented child rows. Null → the `#detail` scoped slot is the expand mode.
642
746
  */
643
- @property({ type: Function }) getSubRows: ((...args: any[]) => any) | null = null;
747
+ @property({ type: Function, attribute: 'get-sub-rows' }) getSubRows: ((...args: any[]) => any) | null = null;
644
748
  /**
645
749
  * Opt-in gate for the **headless `#groupBar`** host region. Default `false` is byte-identical-off. `getGroupedRowModel` is wired unconditionally (inert when `grouping` is empty), so grouping is driven by the `grouping` model; this flag only gates the consumer-facing group-bar surface (the component ships **no** built-in drag UI).
646
750
  */
@@ -684,15 +788,15 @@ export default class DataTable extends SignalWatcher(LitElement) {
684
788
  /**
685
789
  * Pure-CSS sticky header: the `<thead>` sticks to the top of the scroll container.
686
790
  */
687
- @property({ type: Boolean, reflect: true }) stickyHeader: boolean = false;
791
+ @property({ type: Boolean, reflect: true, attribute: 'sticky-header' }) stickyHeader: boolean = false;
688
792
  /**
689
793
  * `'table'` (default, row-oriented, byte-behaviorally identical to a plain accessible table) | `'grid'` — lights up the full WAI-ARIA **[grid interaction mode](/components/data-table-grid-mode)**: `role="grid"`, a roving single tab-stop, 2-D APG arrow-key cell navigation, range selection, and clipboard support.
690
794
  */
691
- @property({ type: String, reflect: true }) interactionMode: string = 'table';
795
+ @property({ type: String, reflect: true, attribute: 'interaction-mode' }) interactionMode: string = 'table';
692
796
  /**
693
797
  * Grid mode only. When `true`, a plain click on an **editable** cell opens its editor immediately (single-click-to-edit) instead of just activating the cell. Default `false` keeps click-to-activate (double-click opens the editor). Shift+click (range selection) and clicks on non-editable cells are unaffected.
694
798
  */
695
- @property({ type: Boolean, reflect: true }) singleClickEdit: boolean = false;
799
+ @property({ type: Boolean, reflect: true, attribute: 'single-click-edit' }) singleClickEdit: boolean = false;
696
800
  /**
697
801
  * Grid mode. When `true`, every committed data mutation (cell/row edit, paste, fill, cut, clear) becomes one undo step: Ctrl/Cmd+Z undoes, Ctrl/Cmd+Y or Ctrl/Cmd+Shift+Z redoes. Default `false` records no history and Ctrl+Z/Y are inert.
698
802
  */
@@ -700,7 +804,7 @@ export default class DataTable extends SignalWatcher(LitElement) {
700
804
  /**
701
805
  * The maximum number of undo steps retained (oldest evicted past this depth). Only consulted when `undoable` is `true`.
702
806
  */
703
- @property({ type: Number, reflect: true }) undoLimit: number = 100;
807
+ @property({ type: Number, reflect: true, attribute: 'undo-limit' }) undoLimit: number = 100;
704
808
  /**
705
809
  * Opt-in windowing grammar: `false` (default, off — byte-identical to a non-virtual table) | `true` or `'rows'` (vertical row windowing; `true` is byte-behavior-identical to every existing consumer, zero churn) | `'columns'` (horizontal column windowing) | `'both'` (both axes windowed). Row windowing renders only the visible slice of rows inside a bounded `rdt-scroll` container (with leading/trailing spacer rows preserving total scroll height), windowing over the full filtered + sorted (pre-pagination) model and suppressing the client pagination chrome. Column windowing renders only the visible slice of leaf columns inside the same `rdt-scroll` container. An unrecognised string behaves as `false`.
706
810
  */
@@ -708,15 +812,15 @@ export default class DataTable extends SignalWatcher(LitElement) {
708
812
  /**
709
813
  * Estimated row height (px) — the first-paint seed for the windowing engine before any row has been measured. Only consulted when rows are windowed. When `autoMeasure` is `true`, later renders progressively refine the estimate from measured content; when `autoMeasure` is `false` this remains the explicit override for every render.
710
814
  */
711
- @property({ type: Number, reflect: true }) estimateRowHeight: number = 40;
815
+ @property({ type: Number, reflect: true, attribute: 'estimate-row-height' }) estimateRowHeight: number = 40;
712
816
  /**
713
817
  * Opt-in content-driven row-size estimation. When `true`, the windowing engine feeds `estimateSize()` a running mean of measured row heights instead of the fixed `estimateRowHeight` seed, so `getTotalSize()` converges to the true content total on a large table with variable-height rows. Falls back to `estimateRowHeight` before any row has been measured. Default `false` keeps the estimate fixed at `estimateRowHeight` for every render (today's behavior).
714
818
  */
715
- @property({ type: Boolean, reflect: true }) autoMeasure: boolean = false;
819
+ @property({ type: Boolean, reflect: true, attribute: 'auto-measure' }) autoMeasure: boolean = false;
716
820
  /**
717
821
  * A CSS length string bounding the `rdt-scroll` container when `virtual` is on (e.g. `'400px'`). Mirrored to the `--rozie-data-table-max-height` custom property; the prop wins, the token is the fallback.
718
822
  */
719
- @property({ type: String, reflect: true }) maxHeight: string = '';
823
+ @property({ type: String, reflect: true, attribute: 'max-height' }) maxHeight: string = '';
720
824
  private _dataDefault = signal<any[]>([]);
721
825
  private _sortingDefault = signal<any[]>([]);
722
826
  private _globalFilterDefault = signal('');
@@ -806,20 +910,20 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
806
910
  @queryAssignedElements({ flatten: true }) private _slotDefaultElements!: Element[];
807
911
  @state() private _hasSlotGroupBar = false;
808
912
  @queryAssignedElements({ slot: 'groupBar', flatten: true }) private _slotGroupBarElements!: Element[];
809
- @property({ attribute: false }) groupBar?: (scope: { grouping: any; groupableColumns: any; applyGrouping: any; clearGrouping: any }) => unknown;
913
+ @property({ attribute: false }) groupBar?: (scope: { grouping: string[]; groupableColumns: DataTableGroupableColumn[]; applyGrouping: (cols: string[]) => void; clearGrouping: () => void }) => unknown;
810
914
  @state() private _hasSlotSelectAll = false;
811
915
  @queryAssignedElements({ slot: 'selectAll', flatten: true }) private _slotSelectAllElements!: Element[];
812
- @property({ attribute: false }) selectAll?: (scope: { checked: any; indeterminate: any; toggle: any }) => unknown;
916
+ @property({ attribute: false }) selectAll?: (scope: { checked: boolean; indeterminate: boolean; toggle: (event: any) => void }) => unknown;
813
917
  @state() private _hasSlotDynamicColHeader = false;
814
918
  @queryAssignedElements({ flatten: true }) private _slotDynamicColHeaderElements!: Element[];
815
919
  @state() private _hasSlotDynamicFilter = false;
816
920
  @queryAssignedElements({ flatten: true }) private _slotDynamicFilterElements!: Element[];
817
921
  @state() private _hasSlotPlaceholder = false;
818
922
  @queryAssignedElements({ slot: 'placeholder', flatten: true }) private _slotPlaceholderElements!: Element[];
819
- @property({ attribute: false }) placeholder?: (scope: { index: any; columnId: any }) => unknown;
923
+ @property({ attribute: false }) placeholder?: (scope: { index: number; columnId: string }) => unknown;
820
924
  @state() private _hasSlotSelectCell = false;
821
925
  @queryAssignedElements({ slot: 'selectCell', flatten: true }) private _slotSelectCellElements!: Element[];
822
- @property({ attribute: false }) selectCell?: (scope: { row: any; checked: any; toggle: any }) => unknown;
926
+ @property({ attribute: false }) selectCell?: (scope: { row: any; checked: boolean; toggle: (event: any) => void }) => unknown;
823
927
  @state() private _hasSlotDynamicCell = false;
824
928
  @queryAssignedElements({ flatten: true }) private _slotDynamicCellElements!: Element[];
825
929
  @state() private _hasSlotDynamicEditor = false;
@@ -829,16 +933,16 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
829
933
  @property({ attribute: false }) detail?: (scope: { row: any }) => unknown;
830
934
  @state() private _hasSlotColHeader = false;
831
935
  @queryAssignedElements({ slot: 'colHeader', flatten: true }) private _slotColHeaderElements!: Element[];
832
- @property({ attribute: false }) colHeader?: (scope: { columnId: any; column: any; label: any }) => unknown;
936
+ @property({ attribute: false }) colHeader?: (scope: { columnId: string; column: TableColumn<any, unknown>; label: string }) => unknown;
833
937
  @state() private _hasSlotFilter = false;
834
938
  @queryAssignedElements({ slot: 'filter', flatten: true }) private _slotFilterElements!: Element[];
835
- @property({ attribute: false }) filter?: (scope: { columnId: any; value: any; uniqueValues: any; minMax: any; columnLabel: any; setFilter: any }) => unknown;
939
+ @property({ attribute: false }) filter?: (scope: { columnId: string; value: any; uniqueValues: any[]; minMax: [number, number] | null; columnLabel: string; setFilter: (columnId: string, value: any) => void }) => unknown;
836
940
  @state() private _hasSlotCell = false;
837
941
  @queryAssignedElements({ slot: 'cell', flatten: true }) private _slotCellElements!: Element[];
838
- @property({ attribute: false }) cell?: (scope: { columnId: any; column: any; row: any; value: any }) => unknown;
942
+ @property({ attribute: false }) cell?: (scope: { columnId: string; column: TableColumn<any, unknown>; row: any; value: any }) => unknown;
839
943
  @state() private _hasSlotEditor = false;
840
944
  @queryAssignedElements({ slot: 'editor', flatten: true }) private _slotEditorElements!: Element[];
841
- @property({ attribute: false }) editor?: (scope: { columnId: any; column: any; row: any; value: any; commit: any; cancel: any; columnLabel: any; autofocus: any }) => unknown;
945
+ @property({ attribute: false }) editor?: (scope: { columnId: string; column: TableColumn<any, unknown>; row: any; value: any; commit: (value: any) => void; cancel: () => void; columnLabel: string; autofocus: boolean }) => unknown;
842
946
  // Phase 79 Plan 08 (R4) contract for 79-09: the record intake for
843
947
  // record-routed slot fills. 79-09's consumer-side emitSlotFiller
844
948
  // accumulates an object literal onto the SAME `.rozieSlots=${{ ... }}`
@@ -848,7 +952,7 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
848
952
  // named function-prop / <slot> fallback (AC-9). Attribute
849
953
  // deserialization is disabled — this is a function-valued record,
850
954
  // never reflected to/from an HTML attribute.
851
- @property({ attribute: false }) rozieSlots?: { [key: `colHeader-${string}`]: (scope: { columnId: any; column: any; label: any }) => unknown; [key: `filter-${string}`]: (scope: { columnId: any; value: any; uniqueValues: any; minMax: any; columnLabel: any; setFilter: any }) => unknown; [key: `cell-${string}`]: (scope: { columnId: any; column: any; row: any; value: any }) => unknown; [key: `editor-${string}`]: (scope: { columnId: any; column: any; row: any; value: any; commit: any; cancel: any; columnLabel: any; autofocus: any }) => unknown; } & Record<string, (scope: any) => unknown>;
955
+ @property({ attribute: false }) rozieSlots?: { [key: `colHeader-${string}`]: (scope: { columnId: string; column: TableColumn<any, unknown>; label: string }) => unknown; [key: `filter-${string}`]: (scope: { columnId: string; value: any; uniqueValues: any[]; minMax: [number, number] | null; columnLabel: string; setFilter: (columnId: string, value: any) => void }) => unknown; [key: `cell-${string}`]: (scope: { columnId: string; column: TableColumn<any, unknown>; row: any; value: any }) => unknown; [key: `editor-${string}`]: (scope: { columnId: string; column: TableColumn<any, unknown>; row: any; value: any; commit: (value: any) => void; cancel: () => void; columnLabel: string; autofocus: boolean }) => unknown; } & Record<string, (scope: any) => unknown>;
852
956
 
853
957
  private _disconnectCleanups: Array<() => void> = [];
854
958
  // Re-parenting guard: set true once the deferred teardown has actually
@@ -1542,7 +1646,7 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1542
1646
  queueMicrotask(() => {
1543
1647
  if (this.isConnected || this._rozieTornDown) return;
1544
1648
  this._rozieTornDown = true;
1545
- () => {
1649
+ (() => {
1546
1650
  // B-02: drop the document click-away listener (it is attached for the instance's lifetime,
1547
1651
  // not per edit session — attaching it per session would freeze a stale closure on React).
1548
1652
  if (this.docPointerDown && typeof document !== 'undefined') {
@@ -1565,7 +1669,7 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1565
1669
  this.teardownFillDrag();
1566
1670
  // §6 (260709-3qt): remove any live drag-select document listeners on a mid-drag unmount.
1567
1671
  this.teardownRangeDrag();
1568
- };
1672
+ })();
1569
1673
  for (const fn of this._disconnectCleanups) fn();
1570
1674
  this._disconnectCleanups = [];
1571
1675
  });
@@ -2458,7 +2562,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2458
2562
  this.programmatic++;
2459
2563
  this._sortingDefault.value = next; // fresh array only (never in-place)
2460
2564
  this._sortingControllable.write(next); // two-way emit if bound (no-op-diff if not)
2461
- this.dispatchEvent(new CustomEvent("sort-change", {
2565
+ this.dispatchEvent(new CustomEvent<SortingState>("sort-change", {
2462
2566
  detail: next,
2463
2567
  bubbles: true,
2464
2568
  composed: true
@@ -2488,7 +2592,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2488
2592
  // → duplicate-identifier TS2300 (the model-prop==emit-name collision class). Every
2489
2593
  // sibling slice avoids this by stemming the event off a DISTINCT name (sorting→
2490
2594
  // sort-change, rowSelection→selection-change); `expanded`→`expand-change` follows suit.
2491
- this.dispatchEvent(new CustomEvent("expand-change", {
2595
+ this.dispatchEvent(new CustomEvent<ExpandedState>("expand-change", {
2492
2596
  detail: next,
2493
2597
  bubbles: true,
2494
2598
  composed: true
@@ -2512,7 +2616,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2512
2616
  this.programmatic++;
2513
2617
  this._groupingDefault.value = next; // fresh ordered array only (never in-place push)
2514
2618
  this._groupingControllable.write(next); // two-way emit if bound (no-op-diff if not)
2515
- this.dispatchEvent(new CustomEvent("group-change", {
2619
+ this.dispatchEvent(new CustomEvent<GroupingState>("group-change", {
2516
2620
  detail: next,
2517
2621
  bubbles: true,
2518
2622
  composed: true
@@ -2528,7 +2632,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2528
2632
  this.programmatic++;
2529
2633
  this._globalFilterDefault.value = next;
2530
2634
  this._globalFilterControllable.write(next);
2531
- this.dispatchEvent(new CustomEvent("filter-change", {
2635
+ this.dispatchEvent(new CustomEvent<DataTableFilterChangePayload>("filter-change", {
2532
2636
  detail: {
2533
2637
  globalFilter: next
2534
2638
  },
@@ -2547,7 +2651,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2547
2651
  this.programmatic++;
2548
2652
  this._columnFiltersDefault.value = next;
2549
2653
  this._columnFiltersControllable.write(next);
2550
- this.dispatchEvent(new CustomEvent("filter-change", {
2654
+ this.dispatchEvent(new CustomEvent<DataTableFilterChangePayload>("filter-change", {
2551
2655
  detail: {
2552
2656
  columnFilters: next
2553
2657
  },
@@ -2564,7 +2668,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2564
2668
  this.programmatic++;
2565
2669
  this._paginationDefault.value = next;
2566
2670
  this._paginationControllable.write(next);
2567
- this.dispatchEvent(new CustomEvent("page-change", {
2671
+ this.dispatchEvent(new CustomEvent<PaginationState>("page-change", {
2568
2672
  detail: next,
2569
2673
  bubbles: true,
2570
2674
  composed: true
@@ -2580,7 +2684,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2580
2684
  this.programmatic++;
2581
2685
  this._rowSelectionDefault.value = next;
2582
2686
  this._rowSelectionControllable.write(next);
2583
- this.dispatchEvent(new CustomEvent("selection-change", {
2687
+ this.dispatchEvent(new CustomEvent<RowSelectionState>("selection-change", {
2584
2688
  detail: next,
2585
2689
  bubbles: true,
2586
2690
  composed: true
@@ -2596,7 +2700,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2596
2700
  this.programmatic++;
2597
2701
  this._columnVisibilityDefault.value = next;
2598
2702
  this._columnVisibilityControllable.write(next);
2599
- this.dispatchEvent(new CustomEvent("visibility-change", {
2703
+ this.dispatchEvent(new CustomEvent<VisibilityState>("visibility-change", {
2600
2704
  detail: next,
2601
2705
  bubbles: true,
2602
2706
  composed: true
@@ -2612,7 +2716,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2612
2716
  this.programmatic++;
2613
2717
  this._columnSizingDefault.value = next;
2614
2718
  this._columnSizingControllable.write(next);
2615
- this.dispatchEvent(new CustomEvent("resize-change", {
2719
+ this.dispatchEvent(new CustomEvent<ColumnSizingState>("resize-change", {
2616
2720
  detail: next,
2617
2721
  bubbles: true,
2618
2722
  composed: true
@@ -2628,7 +2732,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2628
2732
  this.programmatic++;
2629
2733
  this._columnOrderDefault.value = next;
2630
2734
  this._columnOrderControllable.write(next);
2631
- this.dispatchEvent(new CustomEvent("reorder-change", {
2735
+ this.dispatchEvent(new CustomEvent<ColumnOrderState>("reorder-change", {
2632
2736
  detail: next,
2633
2737
  bubbles: true,
2634
2738
  composed: true
@@ -2655,7 +2759,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2655
2759
  this.programmatic++;
2656
2760
  this._columnPinningDefault.value = clean;
2657
2761
  this._columnPinningControllable.write(clean);
2658
- this.dispatchEvent(new CustomEvent("pin-change", {
2762
+ this.dispatchEvent(new CustomEvent<ColumnPinningState>("pin-change", {
2659
2763
  detail: clean,
2660
2764
  bubbles: true,
2661
2765
  composed: true
@@ -2767,13 +2871,13 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2767
2871
  this.redoStack = [];
2768
2872
  };
2769
2873
 
2770
- canUndo = () => this.undoStack.length > 0;
2874
+ canUndo: () => boolean = () => this.undoStack.length > 0;
2771
2875
 
2772
- canRedo = () => this.redoStack.length > 0;
2876
+ canRedo: () => boolean = () => this.redoStack.length > 0;
2773
2877
 
2774
2878
  // Both stacks empty — the external-swap latch (DataTable.rozie reFeed) and the
2775
2879
  // clearHistory() $expose verb share this single implementation.
2776
- clearHistory = () => {
2880
+ clearHistory: () => void = () => {
2777
2881
  this.undoStack = [];
2778
2882
  this.redoStack = [];
2779
2883
  };
@@ -2783,7 +2887,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2783
2887
  // per call per the design — NOT edge-gated there; only the writeData-triggered recording path
2784
2888
  // below is edge-gated, since a routine sequence of edits would otherwise spam the event).
2785
2889
  emitHistoryChange = () => {
2786
- this.dispatchEvent(new CustomEvent("history-change", {
2890
+ this.dispatchEvent(new CustomEvent<DataTableHistoryChangePayload>("history-change", {
2787
2891
  detail: {
2788
2892
  canUndo: this.canUndo(),
2789
2893
  canRedo: this.canRedo()
@@ -2809,7 +2913,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2809
2913
  // re-capture this replay (which would corrupt the stack). Replaying through writeData
2810
2914
  // (rather than writing $data/$model directly) is deliberate: the two-way $model.data
2811
2915
  // writeback, the re-feed $watch, and the echo guard all keep working with zero new code.
2812
- undo = () => {
2916
+ undo: () => void = () => {
2813
2917
  if (!this.canUndo()) return;
2814
2918
  const prev = this.undoStack.pop();
2815
2919
  this.redoStack.push(this.currentData());
@@ -2821,7 +2925,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
2821
2925
 
2822
2926
  // redo(): symmetric — pop the redo stack, push the CURRENT data back onto the undo stack,
2823
2927
  // replay through the same guarded writeData seam.
2824
- redo = () => {
2928
+ redo: () => void = () => {
2825
2929
  if (!this.canRedo()) return;
2826
2930
  const next = this.redoStack.pop();
2827
2931
  this.undoStack.push(this.currentData());
@@ -3410,7 +3514,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
3410
3514
  if (start === this.lastRangeStart && end === this.lastRangeEnd) return;
3411
3515
  this.lastRangeStart = start;
3412
3516
  this.lastRangeEnd = end;
3413
- this.dispatchEvent(new CustomEvent("visible-range-change", {
3517
+ this.dispatchEvent(new CustomEvent<DataTableVisibleRangeChangePayload>("visible-range-change", {
3414
3518
  detail: {
3415
3519
  start,
3416
3520
  end
@@ -3447,7 +3551,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
3447
3551
  // into the internal `.rdt-scroll` class selector. Returns null when nothing is windowed:
3448
3552
  // gridScrollEl is only ever assigned inside the isWindowed() guard, so no extra gate is
3449
3553
  // needed here beyond that natural null.
3450
- getScrollElement = (): any => this.gridScrollEl;
3554
+ getScrollElement: () => HTMLElement | null = (): any => this.gridScrollEl;
3451
3555
 
3452
3556
  // ══ Generic vertical windowing math (Phase 64, D-04) — the target-agnostic virtual-core bridge ══
3453
3557
  // Lifted verbatim from the DataTable virtualization.rzts (the Phase 53/63 B13 baseline). This partial
@@ -5024,39 +5128,39 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
5024
5128
  // is dropped on ALL SIX targets, only the by-reference key survives → a
5025
5129
  // runtime ReferenceError at `defineExpose`/`useImperativeHandle`). Sorting verbs +
5026
5130
  // a fresh column-def readout, selection, pagination, and column-management verbs.
5027
- sortColumn = (colId: any, desc: any) => {
5131
+ sortColumn: (colId: string, desc?: boolean) => void = (colId: any, desc: any) => {
5028
5132
  if (this.table) this.table.getColumn(colId) && this.table.getColumn(colId).toggleSorting(desc, false);
5029
5133
  };
5030
5134
 
5031
- clearSorting = () => {
5135
+ clearSorting: () => void = () => {
5032
5136
  if (this.table) this.table.resetSorting(true);
5033
5137
  };
5034
5138
 
5035
- getColumnDefs = () => this.columnDefs();
5139
+ getColumnDefs: () => ColumnDef<any, any>[] = () => this.columnDefs();
5036
5140
 
5037
5141
  // selection verbs (req-7) — drive table-core so the onRowSelectionChange funnel
5038
5142
  // emits the fresh state + selection-change.
5039
- toggleAllRows = (value: any) => {
5143
+ toggleAllRows: (value?: boolean) => void = (value: any) => {
5040
5144
  if (this.table) this.table.toggleAllRowsSelected(value);
5041
5145
  };
5042
5146
 
5043
- clearSelection = () => {
5147
+ clearSelection: () => void = () => {
5044
5148
  if (this.table) this.table.resetRowSelection(true);
5045
5149
  };
5046
5150
 
5047
- getSelectedRows = () => this.table ? this.table.getSelectedRowModel().rows.map((r: any) => r.original) : [];
5151
+ getSelectedRows: () => any[] = () => this.table ? this.table.getSelectedRowModel().rows.map((r: any) => r.original) : [];
5048
5152
 
5049
5153
  // pagination verbs.
5050
- setPage = (idx: any) => {
5154
+ setPage: (idx: number) => void = (idx: any) => {
5051
5155
  if (this.table) this.table.setPageIndex(idx);
5052
5156
  };
5053
5157
 
5054
- setRowsPerPage = (size: any) => {
5158
+ setRowsPerPage: (size: number) => void = (size: any) => {
5055
5159
  if (this.table) this.table.setPageSize(size);
5056
5160
  };
5057
5161
 
5058
5162
  // column-management verbs (req-8/9/10/11) — drive table-core so the funnels fire.
5059
- toggleColumnVisibility = (colId: any) => {
5163
+ toggleColumnVisibility: (colId: string) => void = (colId: any) => {
5060
5164
  if (this.table) {
5061
5165
  const c = this.table.getColumn(colId);
5062
5166
  if (c && c.toggleVisibility) c.toggleVisibility();
@@ -5070,17 +5174,17 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
5070
5174
  // off-limits). So the public verb is `applyColumnOrder` (semantically: apply a
5071
5175
  // new column order). The other set* verbs (setPage/setRowsPerPage) do NOT match
5072
5176
  // any model prop's setter, so they are collision-free.
5073
- applyColumnOrder = (order: any) => {
5177
+ applyColumnOrder: (order: string[]) => void = (order: any) => {
5074
5178
  if (this.table) this.table.setColumnOrder(order);
5075
5179
  };
5076
5180
 
5077
- resetColumnSizing = () => {
5181
+ resetColumnSizing: () => void = () => {
5078
5182
  if (this.table) this.table.resetColumnSizing(true);
5079
5183
  };
5080
5184
 
5081
5185
  // pinColumn: the verb that drives column.pin; distinct from the template handler
5082
5186
  // onPinColumn (no shadow — the deferred-items finding #4 collision check).
5083
- pinColumn = (colId: any, side: any) => {
5187
+ pinColumn: (colId: string, side: 'left' | 'right' | false) => void = (colId: any, side: any) => {
5084
5188
  if (this.table) {
5085
5189
  const c = this.table.getColumn(colId);
5086
5190
  if (c && c.pin) c.pin(side);
@@ -5094,7 +5198,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
5094
5198
  // there is no page (windowing replaces pagination) → the windowed model IS the full model, so it
5095
5199
  // returns the absolute index unchanged. Collision-safe: no *-change event, prop, React auto-setter,
5096
5200
  // or inherited Lit DOM method named getRowIndexRelativeToPage (ROZ121/124/137 clear).
5097
- getRowIndexRelativeToPage = (absRow: any) => {
5201
+ getRowIndexRelativeToPage: (absRow?: number) => number = (absRow: any) => {
5098
5202
  const abs = absRow == null ? this.toAbsRow(this._activeRow.value) : Math.trunc(Number(absRow)) || 0;
5099
5203
  if (this.rowsWindowed()) return abs;
5100
5204
  return abs - this.pageRowOffset();
@@ -5106,7 +5210,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
5106
5210
  // active cell, so it cuts the current selection even when the call arrives off a control that
5107
5211
  // moved DOM focus off the grid. Collision-safe: no `cut` event / model prop / React auto-setter /
5108
5212
  // inherited Lit DOM method named `cut` (ROZ121/124/137 clear) — `cut` is not on HTMLElement.
5109
- cut = () => this.cutRange();
5213
+ cut: () => void = () => this.cutRange();
5110
5214
 
5111
5215
  // 260709-8ct (grid-wide undo/redo): NO pass-through wrapper lands here for
5112
5216
  // undo/redo/canUndo/canRedo/clearHistory. Unlike `cut` above (which delegates to a
@@ -6117,7 +6221,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
6117
6221
  // SAME language): a header cell has no body-row index, so emit rowIndex:null + isHeader:true
6118
6222
  // rather than a bogus toAbsRow(nextRow) — which would compute a real body-row absolute index
6119
6223
  // for a HEADER move, misleading a consumer into thinking that body row is the active cell.
6120
- this.dispatchEvent(new CustomEvent("activecell-change", {
6224
+ this.dispatchEvent(new CustomEvent<DataTableActiveCellChangePayload>("activecell-change", {
6121
6225
  detail: nextIsHeader ? {
6122
6226
  rowIndex: null,
6123
6227
  colIndex: nextCol,
@@ -6327,7 +6431,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
6327
6431
  activateRowAt = (index: any, trigger: any) => {
6328
6432
  const row = (this._rows.value || [])[index];
6329
6433
  if (!row || this.rowIsGrouped(row) || this.rowIsLazyPlaceholder(row)) return;
6330
- this.dispatchEvent(new CustomEvent("row-activate", {
6434
+ this.dispatchEvent(new CustomEvent<DataTableRowActivatePayload>("row-activate", {
6331
6435
  detail: {
6332
6436
  row: row.original,
6333
6437
  index,
@@ -6734,7 +6838,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
6734
6838
  // { rowIndex, colIndex } pair (or null when no range). T-49-02: positions only, no row
6735
6839
  // data, no DOM node. Used by the getSelectedRange $expose verb AND every range-change emit
6736
6840
  // (the single payload source) AND copyRange/fillRange (the rectangle they operate over).
6737
- getSelectedRange = () => {
6841
+ getSelectedRange: () => DataTableRange = () => {
6738
6842
  // B8: clamp the corners to the CURRENT bounds ON READ so the verb (and the range-change emit
6739
6843
  // payload) never reports a corner past a shrunken model — React-stale-safe (the eager
6740
6844
  // refreshRowModel clamp is async-defeated on React; this read-time clamp is the guarantee).
@@ -6799,7 +6903,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
6799
6903
 
6800
6904
  emitRangeChange = (anchor: any, focus: any) => {
6801
6905
  this._rangeAnnounce.value = this.rangeSummary(anchor, focus);
6802
- this.dispatchEvent(new CustomEvent("range-change", {
6906
+ this.dispatchEvent(new CustomEvent<DataTableRangeChangePayload>("range-change", {
6803
6907
  detail: {
6804
6908
  anchor,
6805
6909
  focus
@@ -7242,7 +7346,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
7242
7346
  // is the first-party code that actually escapes.
7243
7347
  for (let i = 0; i < committed.length; i++) {
7244
7348
  try {
7245
- this.dispatchEvent(new CustomEvent("cell-edit-commit", {
7349
+ this.dispatchEvent(new CustomEvent<DataTableCellEditCommitPayload>("cell-edit-commit", {
7246
7350
  detail: committed[i],
7247
7351
  bubbles: true,
7248
7352
  composed: true
@@ -8241,7 +8345,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
8241
8345
  const next = replaceRowValue(this.currentData(), srcIndex, field, newValue);
8242
8346
  this.writeData(next);
8243
8347
  // Exactly one emit per commit, from this single call site (writeData does NOT emit).
8244
- this.dispatchEvent(new CustomEvent("cell-edit-commit", {
8348
+ this.dispatchEvent(new CustomEvent<DataTableCellEditCommitPayload>("cell-edit-commit", {
8245
8349
  detail: {
8246
8350
  rowId,
8247
8351
  columnId: colId,
@@ -8326,7 +8430,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
8326
8430
  this.writeData(replaceRowValue(this.currentData(), srcIndex, field, newValue));
8327
8431
  // Exactly one emit per toggle, from this single call site (writeData does NOT emit) —
8328
8432
  // mirrors commitEdit's D-07 single-emit discipline.
8329
- this.dispatchEvent(new CustomEvent("cell-edit-commit", {
8433
+ this.dispatchEvent(new CustomEvent<DataTableCellEditCommitPayload>("cell-edit-commit", {
8330
8434
  detail: {
8331
8435
  rowId,
8332
8436
  columnId: colId,
@@ -8562,7 +8666,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
8562
8666
  const next = replaceRowValues(this.currentData(), srcIndex, fieldValues);
8563
8667
  this.writeData(next);
8564
8668
  // EXACTLY ONE emit per row commit, from THIS single call site (React multi-emit dedup, D-07).
8565
- this.dispatchEvent(new CustomEvent("row-edit-commit", {
8669
+ this.dispatchEvent(new CustomEvent<DataTableRowEditCommitPayload>("row-edit-commit", {
8566
8670
  detail: {
8567
8671
  rowId,
8568
8672
  changes
@@ -9107,7 +9211,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9107
9211
  // editCell(rowIndex, colIndex) — programmatic edit-entry ($expose, req-3). Coerces +
9108
9212
  // clamps indices, moves the active cell, and opens the editor (no-op on a non-editable
9109
9213
  // cell). Collision-clean (RESEARCH name-check): not a verb/event/prop/ROZ137 member.
9110
- editCell = (rowIndex: any, colIndex: any) => {
9214
+ editCell: (rowIndex: number, colIndex: number) => void = (rowIndex: any, colIndex: any) => {
9111
9215
  const lastRow = this.bodyRowCount() - 1;
9112
9216
  const maxRow = lastRow < 0 ? 0 : lastRow;
9113
9217
  const maxCol = this.visibleColCount() - 1;
@@ -9126,7 +9230,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9126
9230
  // edit (editRow()/Shift+F2) drives editingRowIndex and leaves editingRow at -1, so the
9127
9231
  // single-cell commitEdit guard (editingRow >= 0) is false during a row edit — route to
9128
9232
  // commitRow() first so a programmatic commit of a row editor is not a silent no-op.
9129
- commitEditing = () => {
9233
+ commitEditing: () => void = () => {
9130
9234
  if (this.inRowEdit()) {
9131
9235
  this.commitRow();
9132
9236
  return;
@@ -9140,7 +9244,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9140
9244
  // name-check): `editRow` is not in the 15 existing verbs, not a prop, not a *-change/commit
9141
9245
  // event, not a Lit ROZ137-reserved host member. Moves the active cell to the row first so the
9142
9246
  // commit/cancel focus-return lands in the right row.
9143
- editRow = (rowIndex: any) => {
9247
+ editRow: (rowIndex: number) => void = (rowIndex: any) => {
9144
9248
  const lastRow = this.bodyRowCount() - 1;
9145
9249
  const maxRow = lastRow < 0 ? 0 : lastRow;
9146
9250
  const r = clamp(Math.trunc(Number(rowIndex)) || 0, 0, maxRow);
@@ -9203,7 +9307,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9203
9307
  // data-* selector is built (T-49-01/T-63-06-01: never interpolate a raw consumer string; clamp
9204
9308
  // the abs index into getPrePaginationRowModel bounds). The activecell-change payload + getActiveCell
9205
9309
  // speak the SAME absolute language (toAbsRow).
9206
- focusCell = (rowIndex: any, colIndex: any) => {
9310
+ focusCell: (rowIndex: number, colIndex: number) => void = (rowIndex: any, colIndex: any) => {
9207
9311
  // B16: isGrid()-gate the verb. In 'table' mode there is no roving active cell, so focusCell
9208
9312
  // is a NO-OP (never an activecell-change emit) — the keyboard path (onGridKeyDown) is already
9209
9313
  // isGrid-gated; the exposed verb must mirror that so a consumer's focusCell on a table-mode
@@ -9267,7 +9371,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9267
9371
  }
9268
9372
  }
9269
9373
  if (absRow !== prevAbs || c !== prevCol || prevIsHeader) {
9270
- this.dispatchEvent(new CustomEvent("activecell-change", {
9374
+ this.dispatchEvent(new CustomEvent<DataTableActiveCellChangePayload>("activecell-change", {
9271
9375
  detail: {
9272
9376
  rowIndex: absRow,
9273
9377
  colIndex: c
@@ -9287,7 +9391,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9287
9391
  // is unchanged for the body case).
9288
9392
  // C1: a body cell returns the ABSOLUTE display-order rowIndex (toAbsRow) — matching focusCell's
9289
9393
  // addressing + the activecell-change payload — in BOTH paginated and virtual modes.
9290
- getActiveCell = () => this._activeIsHeader.value ? {
9394
+ getActiveCell: () => DataTableActiveCell = () => this._activeIsHeader.value ? {
9291
9395
  rowIndex: null,
9292
9396
  colIndex: this._activeColIndex.value,
9293
9397
  isHeader: true
@@ -9301,7 +9405,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9301
9405
  // exit interaction mode; the next Tab-in re-enters at the entry cell (D-01). Does NOT emit
9302
9406
  // (no move to a new addressable cell — a reset, not a navigation). B16: isGrid()-gated — a
9303
9407
  // table-mode instance has no roving active cell, so the verb is a no-op there.
9304
- clearActiveCell = () => {
9408
+ clearActiveCell: () => void = () => {
9305
9409
  if (!this.isGrid()) return;
9306
9410
  this._activeIsHeader.value = false;
9307
9411
  this._activeInControl.value = false;
@@ -9318,7 +9422,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9318
9422
  // toggleRowExpanded(rowId) — toggle ONE row's expanded state, addressed by the consumer's
9319
9423
  // row id (the data `id` field) OR the table-core row id. Scans the core flat-row set (all
9320
9424
  // rows regardless of current expansion) so a collapsed parent is still resolvable.
9321
- toggleRowExpanded = (rowId: any) => {
9425
+ toggleRowExpanded: (rowId: string | number) => void = (rowId: any) => {
9322
9426
  if (!this.table) return;
9323
9427
  const target = String(rowId);
9324
9428
  const flat = this.table.getCoreRowModel().flatRows;
@@ -9332,14 +9436,14 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9332
9436
 
9333
9437
  // expandAll() — open every expandable row (table-core sets ExpandedState to the `true`
9334
9438
  // literal under the hood → Pitfall 2: writeExpanded passes it through verbatim).
9335
- expandAll = () => {
9439
+ expandAll: () => void = () => {
9336
9440
  if (!this.table) return;
9337
9441
  this.table.toggleAllRowsExpanded(true);
9338
9442
  };
9339
9443
 
9340
9444
  // collapseAll() — reset to a blank expanded state ({}). resetExpanded(true) forces the
9341
9445
  // blank reset (NOT the initialState) and fires onExpandedChange → one expanded-change.
9342
- collapseAll = () => {
9446
+ collapseAll: () => void = () => {
9343
9447
  if (!this.table) return;
9344
9448
  this.table.resetExpanded(true);
9345
9449
  };
@@ -9347,7 +9451,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9347
9451
  // getExpandedRows() — return the original row data for every currently-expanded row
9348
9452
  // (read-verb twin of expanded-change). Integers/data only — scans the core flat rows and
9349
9453
  // filters by getIsExpanded(). Empty when nothing is expanded.
9350
- getExpandedRows = () => {
9454
+ getExpandedRows: () => any[] = () => {
9351
9455
  if (!this.table) return [];
9352
9456
  const out = [];
9353
9457
  const flat = this.table.getCoreRowModel().flatRows;
@@ -9362,11 +9466,11 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9362
9466
  // setColumnOrder→applyColumnOrder) + clearGrouping. Both drive @tanstack/table-core's
9363
9467
  // table.setGrouping so the onGroupingChange → writeGrouping funnel fires one group-change with
9364
9468
  // the fresh ordered key list. Also handed to the headless #groupBar slot as apply/clear helpers.
9365
- applyGrouping = (cols: any) => {
9469
+ applyGrouping: (cols: string[]) => void = (cols: any) => {
9366
9470
  if (this.table) this.table.setGrouping(cols);
9367
9471
  };
9368
9472
 
9369
- clearGrouping = () => {
9473
+ clearGrouping: () => void = () => {
9370
9474
  if (this.table) this.table.setGrouping([]);
9371
9475
  };
9372
9476
 
@@ -9384,7 +9488,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9384
9488
  // column/table. NAMED to match the $expose verb exactly (the ExposedMethod.name shorthand
9385
9489
  // contract: an exposed verb lowers to `{ getFacetedUniqueValues }`, which must resolve to THIS
9386
9490
  // helper — the table-core factory was aliased to makeFacetedUniqueValues to free this name).
9387
- getFacetedUniqueValues = (colId: any) => {
9491
+ getFacetedUniqueValues: (colId: string) => any[] = (colId: any) => {
9388
9492
  if (this.tick() < 0 || !this.table) return [];
9389
9493
  const col = this.table.getColumn(colId);
9390
9494
  if (!col || !col.getFacetedUniqueValues) return [];
@@ -9394,7 +9498,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9394
9498
 
9395
9499
  // getFacetedMinMaxValues: the column's [min, max] numeric range, or null when unavailable.
9396
9500
  // Named to match the $expose verb (same shorthand contract as getFacetedUniqueValues above).
9397
- getFacetedMinMaxValues = (colId: any) => {
9501
+ getFacetedMinMaxValues: (colId: string) => [number, number] | null = (colId: any) => {
9398
9502
  if (this.tick() < 0 || !this.table) return null;
9399
9503
  const col = this.table.getColumn(colId);
9400
9504
  if (!col || !col.getFacetedMinMaxValues) return null;
@@ -9425,4 +9529,15 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9425
9529
  set columnOrder(v: any[]) { this._columnOrderControllable.notifyPropertyWrite(v); }
9426
9530
  get columnPinning(): any { return this._columnPinningControllable.read(); }
9427
9531
  set columnPinning(v: any) { this._columnPinningControllable.notifyPropertyWrite(v); }
9532
+
9533
+ addEventListener<K extends keyof RozieDataTableEventMap>(type: K, listener: (this: DataTable, ev: RozieDataTableEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
9534
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
9535
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void {
9536
+ super.addEventListener(type, listener, options);
9537
+ }
9538
+ removeEventListener<K extends keyof RozieDataTableEventMap>(type: K, listener: (this: DataTable, ev: RozieDataTableEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
9539
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
9540
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void {
9541
+ super.removeEventListener(type, listener, options);
9542
+ }
9428
9543
  }