@rozie-ui/data-table-lit 0.7.2 → 0.7.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @rozie-ui/data-table-lit
2
2
 
3
+ ## 0.7.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 05cb9db: Regenerated with the Lit nullable model prop typing fix: the two-way `grouping` property is now typed `any[] | null` (its default is `null`, so the narrower `any[]` was never true), which a strict TypeScript consumer reading `element.grouping` now sees. Rendered markup and runtime behaviour are unchanged.
8
+ - @rozie/runtime-lit@0.10.1
9
+
10
+ ## 0.7.3
11
+
12
+ ### Patch Changes
13
+
14
+ - cf49212: Regenerated with the compiler fixes found while building `@rozie-ui/select`. Depending on the target and the component:
15
+ - Angular: a two-way (`model: true`) prop is now controlled while the consumer binds a value — a write by the component only emits `<name>Change`, so a consumer that refuses the change keeps the control on its value. The prop keeps its `ModelSignal` type. `$onUpdate` hooks now run (after every render); they never ran before. An output named like a native bubbling event (`change`, `submit`, `reset`, `select`) no longer also delivers the native event to a consumer's binding.
16
+ - Vue: a two-way prop bound one-way (`:value` without `v-model`) is now controlled too: the component's write emits `update:value` and the control keeps the consumer's value.
17
+ - React: an `$expose` verb now runs in `flushSync`, so calls made in one tick each see what the call before left; primitive script constants are plain `const`s; a body statement no longer reads a binding declared after it on the first render.
18
+ - Svelte, Solid: a `$watch` now sees a `$data` write made in `$onMount`.
19
+ - Lit: a `$watch` whose getter reads both props and `$data` re-runs when only the prop changes; duplicated comments in lifecycle bodies are gone.
20
+ - @rozie/runtime-lit@0.10.0
21
+
3
22
  ## 0.7.2
4
23
 
5
24
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -421,6 +421,7 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
421
421
  this.__rozieWatchInitial_0 = true;
422
422
  this.__rozieWatchInitial_1 = true;
423
423
  this.__rozieWatchInitial_2 = true;
424
+ this.__rozieFirstUpdateDone = false;
424
425
  this.__rozieCtxProvider_data_table_columns = new _lit_context.ContextProvider(this, {
425
426
  context: __rozieCtx_data_table_columns$1,
426
427
  initialValue: ((__rozieCtxHost) => ({
@@ -4664,8 +4665,31 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
4664
4665
  });
4665
4666
  }));
4666
4667
  this._disconnectCleanups.push((0, _lit_labs_preact_signals.effect)(() => {
4667
- this.sorting, this.globalFilter, this.columnFilters, this.pagination, this.rowCount, this.pageCount, this.rowSelection, this.expanded, this.expandable, this.grouping, this.groupable, this.columnVisibility, this.columnSizing, this.columnOrder, this.columnPinning, this.selectionMode, (this.data || []).length, this.data, this._dataDefault.value, this.columns, this._colReg.value;
4668
+ const __watchVal = [
4669
+ this.sorting,
4670
+ this.globalFilter,
4671
+ this.columnFilters,
4672
+ this.pagination,
4673
+ this.rowCount,
4674
+ this.pageCount,
4675
+ this.rowSelection,
4676
+ this.expanded,
4677
+ this.expandable,
4678
+ this.grouping,
4679
+ this.groupable,
4680
+ this.columnVisibility,
4681
+ this.columnSizing,
4682
+ this.columnOrder,
4683
+ this.columnPinning,
4684
+ this.selectionMode,
4685
+ (this.data || []).length,
4686
+ this.data,
4687
+ this._dataDefault.value,
4688
+ this.columns,
4689
+ this._colReg.value
4690
+ ];
4668
4691
  (0, _lit_labs_preact_signals.untracked)(() => {
4692
+ this.__rozieWatchPrev_1 = __watchVal;
4669
4693
  if (this.__rozieWatchInitial_1) {
4670
4694
  this.__rozieWatchInitial_1 = false;
4671
4695
  return;
@@ -4833,15 +4857,51 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
4833
4857
  this.announceState.globalFilter = this.effectiveGlobalFilter();
4834
4858
  }
4835
4859
  updated(changedProperties) {
4836
- this.maybeClearHistoryOnExternalSwap();
4837
- this.emitVisibleRangeIfChanged();
4838
- this.remeasureColumnSizes();
4839
- if (!this.table) return;
4840
- const d = this.currentData() || [];
4841
- if (d === this.lastData && d.length === this.lastDataLen) return;
4842
- this.lastData = d;
4843
- this.lastDataLen = d.length;
4844
- this.reFeed();
4860
+ if (this.__rozieFirstUpdateDone && (changedProperties.has("rowCount") || changedProperties.has("pageCount") || changedProperties.has("expandable") || changedProperties.has("groupable") || changedProperties.has("selectionMode") || changedProperties.has("columns"))) {
4861
+ const __watchVal = (0, _lit_labs_preact_signals.untracked)(() => [
4862
+ this.sorting,
4863
+ this.globalFilter,
4864
+ this.columnFilters,
4865
+ this.pagination,
4866
+ this.rowCount,
4867
+ this.pageCount,
4868
+ this.rowSelection,
4869
+ this.expanded,
4870
+ this.expandable,
4871
+ this.grouping,
4872
+ this.groupable,
4873
+ this.columnVisibility,
4874
+ this.columnSizing,
4875
+ this.columnOrder,
4876
+ this.columnPinning,
4877
+ this.selectionMode,
4878
+ (this.data || []).length,
4879
+ this.data,
4880
+ this._dataDefault.value,
4881
+ this.columns,
4882
+ this._colReg.value
4883
+ ]);
4884
+ if (!Object.is(__watchVal, this.__rozieWatchPrev_1)) {
4885
+ this.__rozieWatchPrev_1 = __watchVal;
4886
+ (0, _lit_labs_preact_signals.untracked)(() => (() => {
4887
+ this.seedColumnPinning();
4888
+ this.reFeed();
4889
+ this.maybeClearHistoryOnExternalSwap();
4890
+ })());
4891
+ }
4892
+ }
4893
+ this.__rozieFirstUpdateDone = true;
4894
+ (() => {
4895
+ this.maybeClearHistoryOnExternalSwap();
4896
+ this.emitVisibleRangeIfChanged();
4897
+ this.remeasureColumnSizes();
4898
+ if (!this.table) return;
4899
+ const d = this.currentData() || [];
4900
+ if (d === this.lastData && d.length === this.lastDataLen) return;
4901
+ this.lastData = d;
4902
+ this.lastDataLen = d.length;
4903
+ this.reFeed();
4904
+ })();
4845
4905
  }
4846
4906
  disconnectedCallback() {
4847
4907
  super.disconnectedCallback();
@@ -6166,12 +6226,14 @@ let Column = class Column extends (0, _lit_labs_preact_signals.SignalWatcher)(li
6166
6226
  })();
6167
6227
  }
6168
6228
  this.__rozieFirstUpdateDone = true;
6169
- if (this.registered) return;
6170
- const live = this.registry;
6171
- if (live == null) return;
6172
- this.reg = live;
6173
- this.registered = true;
6174
- this.reg.registerColumn(this.colId(), this.buildSpec());
6229
+ (() => {
6230
+ if (this.registered) return;
6231
+ const live = this.registry;
6232
+ if (live == null) return;
6233
+ this.reg = live;
6234
+ this.registered = true;
6235
+ this.reg.registerColumn(this.colId(), this.buildSpec());
6236
+ })();
6175
6237
  }
6176
6238
  disconnectedCallback() {
6177
6239
  super.disconnectedCallback();
@@ -6899,6 +6961,7 @@ let FilterNumberRange = class FilterNumberRange extends (0, _lit_labs_preact_sig
6899
6961
  this._maxDraft = (0, _lit_labs_preact_signals.signal)("");
6900
6962
  this._touched = (0, _lit_labs_preact_signals.signal)(false);
6901
6963
  this.__rozieWatchInitial_0 = true;
6964
+ this.__rozieFirstUpdateDone = false;
6902
6965
  this._disconnectCleanups = [];
6903
6966
  this._rozieTornDown = false;
6904
6967
  this.minDraftValue = () => this._touched.value ? this._minDraft.value : Array.isArray(this.value) && this.value[0] != null ? String(this.value[0]) : "";
@@ -6937,8 +7000,9 @@ let FilterNumberRange = class FilterNumberRange extends (0, _lit_labs_preact_sig
6937
7000
  }
6938
7001
  firstUpdated() {
6939
7002
  this._disconnectCleanups.push((0, _lit_labs_preact_signals.effect)(() => {
6940
- Array.isArray(this.value) && String(this.value[0]) + "" + String(this.value[1]);
7003
+ const __watchVal = Array.isArray(this.value) ? String(this.value[0]) + "\0" + String(this.value[1]) : "";
6941
7004
  (0, _lit_labs_preact_signals.untracked)(() => {
7005
+ this.__rozieWatchPrev_0 = __watchVal;
6942
7006
  if (this.__rozieWatchInitial_0) {
6943
7007
  this.__rozieWatchInitial_0 = false;
6944
7008
  return;
@@ -6947,6 +7011,16 @@ let FilterNumberRange = class FilterNumberRange extends (0, _lit_labs_preact_sig
6947
7011
  });
6948
7012
  }));
6949
7013
  }
7014
+ updated(changedProperties) {
7015
+ if (this.__rozieFirstUpdateDone && changedProperties.has("value")) {
7016
+ const __watchVal = (0, _lit_labs_preact_signals.untracked)(() => Array.isArray(this.value) ? String(this.value[0]) + "\0" + String(this.value[1]) : "");
7017
+ if (!Object.is(__watchVal, this.__rozieWatchPrev_0)) {
7018
+ this.__rozieWatchPrev_0 = __watchVal;
7019
+ (0, _lit_labs_preact_signals.untracked)(() => (this._touched.value = false, void 0));
7020
+ }
7021
+ }
7022
+ this.__rozieFirstUpdateDone = true;
7023
+ }
6950
7024
  disconnectedCallback() {
6951
7025
  super.disconnectedCallback();
6952
7026
  queueMicrotask(() => {
package/dist/index.d.cts CHANGED
@@ -278,8 +278,10 @@ declare class DataTable extends DataTable_base {
278
278
  private _liveAnnounce;
279
279
  private _ref__rozieRoot;
280
280
  private __rozieWatchInitial_0;
281
+ private __rozieWatchPrev_1;
281
282
  private __rozieWatchInitial_1;
282
283
  private __rozieWatchInitial_2;
284
+ private __rozieFirstUpdateDone;
283
285
  private __rozieCtxProvider_data_table_columns;
284
286
  private _rozieSlotDistributor;
285
287
  private _hasSlotDefault;
@@ -900,8 +902,8 @@ declare class DataTable extends DataTable_base {
900
902
  set pagination(v: any);
901
903
  get expanded(): any | boolean;
902
904
  set expanded(v: any | boolean);
903
- get grouping(): any[];
904
- set grouping(v: any[]);
905
+ get grouping(): any[] | null;
906
+ set grouping(v: any[] | null);
905
907
  get rowSelection(): any;
906
908
  set rowSelection(v: any);
907
909
  get columnVisibility(): any;
@@ -1356,10 +1358,13 @@ declare class FilterNumberRange extends FilterNumberRange_base {
1356
1358
  private _minDraft;
1357
1359
  private _maxDraft;
1358
1360
  private _touched;
1361
+ private __rozieWatchPrev_0;
1359
1362
  private __rozieWatchInitial_0;
1363
+ private __rozieFirstUpdateDone;
1360
1364
  private _disconnectCleanups;
1361
1365
  private _rozieTornDown;
1362
1366
  firstUpdated(): void;
1367
+ updated(changedProperties: Map<string, unknown>): void;
1363
1368
  disconnectedCallback(): void;
1364
1369
  render(): _$lit.TemplateResult<1>;
1365
1370
  minDraftValue: () => string;
package/dist/index.d.mts CHANGED
@@ -278,8 +278,10 @@ declare class DataTable extends DataTable_base {
278
278
  private _liveAnnounce;
279
279
  private _ref__rozieRoot;
280
280
  private __rozieWatchInitial_0;
281
+ private __rozieWatchPrev_1;
281
282
  private __rozieWatchInitial_1;
282
283
  private __rozieWatchInitial_2;
284
+ private __rozieFirstUpdateDone;
283
285
  private __rozieCtxProvider_data_table_columns;
284
286
  private _rozieSlotDistributor;
285
287
  private _hasSlotDefault;
@@ -900,8 +902,8 @@ declare class DataTable extends DataTable_base {
900
902
  set pagination(v: any);
901
903
  get expanded(): any | boolean;
902
904
  set expanded(v: any | boolean);
903
- get grouping(): any[];
904
- set grouping(v: any[]);
905
+ get grouping(): any[] | null;
906
+ set grouping(v: any[] | null);
905
907
  get rowSelection(): any;
906
908
  set rowSelection(v: any);
907
909
  get columnVisibility(): any;
@@ -1356,10 +1358,13 @@ declare class FilterNumberRange extends FilterNumberRange_base {
1356
1358
  private _minDraft;
1357
1359
  private _maxDraft;
1358
1360
  private _touched;
1361
+ private __rozieWatchPrev_0;
1359
1362
  private __rozieWatchInitial_0;
1363
+ private __rozieFirstUpdateDone;
1360
1364
  private _disconnectCleanups;
1361
1365
  private _rozieTornDown;
1362
1366
  firstUpdated(): void;
1367
+ updated(changedProperties: Map<string, unknown>): void;
1363
1368
  disconnectedCallback(): void;
1364
1369
  render(): _$lit.TemplateResult<1>;
1365
1370
  minDraftValue: () => string;
package/dist/index.mjs CHANGED
@@ -417,6 +417,7 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
417
417
  this.__rozieWatchInitial_0 = true;
418
418
  this.__rozieWatchInitial_1 = true;
419
419
  this.__rozieWatchInitial_2 = true;
420
+ this.__rozieFirstUpdateDone = false;
420
421
  this.__rozieCtxProvider_data_table_columns = new ContextProvider(this, {
421
422
  context: __rozieCtx_data_table_columns$1,
422
423
  initialValue: ((__rozieCtxHost) => ({
@@ -4660,8 +4661,31 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
4660
4661
  });
4661
4662
  }));
4662
4663
  this._disconnectCleanups.push(effect(() => {
4663
- this.sorting, this.globalFilter, this.columnFilters, this.pagination, this.rowCount, this.pageCount, this.rowSelection, this.expanded, this.expandable, this.grouping, this.groupable, this.columnVisibility, this.columnSizing, this.columnOrder, this.columnPinning, this.selectionMode, (this.data || []).length, this.data, this._dataDefault.value, this.columns, this._colReg.value;
4664
+ const __watchVal = [
4665
+ this.sorting,
4666
+ this.globalFilter,
4667
+ this.columnFilters,
4668
+ this.pagination,
4669
+ this.rowCount,
4670
+ this.pageCount,
4671
+ this.rowSelection,
4672
+ this.expanded,
4673
+ this.expandable,
4674
+ this.grouping,
4675
+ this.groupable,
4676
+ this.columnVisibility,
4677
+ this.columnSizing,
4678
+ this.columnOrder,
4679
+ this.columnPinning,
4680
+ this.selectionMode,
4681
+ (this.data || []).length,
4682
+ this.data,
4683
+ this._dataDefault.value,
4684
+ this.columns,
4685
+ this._colReg.value
4686
+ ];
4664
4687
  untracked(() => {
4688
+ this.__rozieWatchPrev_1 = __watchVal;
4665
4689
  if (this.__rozieWatchInitial_1) {
4666
4690
  this.__rozieWatchInitial_1 = false;
4667
4691
  return;
@@ -4829,15 +4853,51 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
4829
4853
  this.announceState.globalFilter = this.effectiveGlobalFilter();
4830
4854
  }
4831
4855
  updated(changedProperties) {
4832
- this.maybeClearHistoryOnExternalSwap();
4833
- this.emitVisibleRangeIfChanged();
4834
- this.remeasureColumnSizes();
4835
- if (!this.table) return;
4836
- const d = this.currentData() || [];
4837
- if (d === this.lastData && d.length === this.lastDataLen) return;
4838
- this.lastData = d;
4839
- this.lastDataLen = d.length;
4840
- this.reFeed();
4856
+ if (this.__rozieFirstUpdateDone && (changedProperties.has("rowCount") || changedProperties.has("pageCount") || changedProperties.has("expandable") || changedProperties.has("groupable") || changedProperties.has("selectionMode") || changedProperties.has("columns"))) {
4857
+ const __watchVal = untracked(() => [
4858
+ this.sorting,
4859
+ this.globalFilter,
4860
+ this.columnFilters,
4861
+ this.pagination,
4862
+ this.rowCount,
4863
+ this.pageCount,
4864
+ this.rowSelection,
4865
+ this.expanded,
4866
+ this.expandable,
4867
+ this.grouping,
4868
+ this.groupable,
4869
+ this.columnVisibility,
4870
+ this.columnSizing,
4871
+ this.columnOrder,
4872
+ this.columnPinning,
4873
+ this.selectionMode,
4874
+ (this.data || []).length,
4875
+ this.data,
4876
+ this._dataDefault.value,
4877
+ this.columns,
4878
+ this._colReg.value
4879
+ ]);
4880
+ if (!Object.is(__watchVal, this.__rozieWatchPrev_1)) {
4881
+ this.__rozieWatchPrev_1 = __watchVal;
4882
+ untracked(() => (() => {
4883
+ this.seedColumnPinning();
4884
+ this.reFeed();
4885
+ this.maybeClearHistoryOnExternalSwap();
4886
+ })());
4887
+ }
4888
+ }
4889
+ this.__rozieFirstUpdateDone = true;
4890
+ (() => {
4891
+ this.maybeClearHistoryOnExternalSwap();
4892
+ this.emitVisibleRangeIfChanged();
4893
+ this.remeasureColumnSizes();
4894
+ if (!this.table) return;
4895
+ const d = this.currentData() || [];
4896
+ if (d === this.lastData && d.length === this.lastDataLen) return;
4897
+ this.lastData = d;
4898
+ this.lastDataLen = d.length;
4899
+ this.reFeed();
4900
+ })();
4841
4901
  }
4842
4902
  disconnectedCallback() {
4843
4903
  super.disconnectedCallback();
@@ -6162,12 +6222,14 @@ let Column$1 = class Column extends SignalWatcher(LitElement) {
6162
6222
  })();
6163
6223
  }
6164
6224
  this.__rozieFirstUpdateDone = true;
6165
- if (this.registered) return;
6166
- const live = this.registry;
6167
- if (live == null) return;
6168
- this.reg = live;
6169
- this.registered = true;
6170
- this.reg.registerColumn(this.colId(), this.buildSpec());
6225
+ (() => {
6226
+ if (this.registered) return;
6227
+ const live = this.registry;
6228
+ if (live == null) return;
6229
+ this.reg = live;
6230
+ this.registered = true;
6231
+ this.reg.registerColumn(this.colId(), this.buildSpec());
6232
+ })();
6171
6233
  }
6172
6234
  disconnectedCallback() {
6173
6235
  super.disconnectedCallback();
@@ -6895,6 +6957,7 @@ let FilterNumberRange = class FilterNumberRange extends SignalWatcher(LitElement
6895
6957
  this._maxDraft = signal("");
6896
6958
  this._touched = signal(false);
6897
6959
  this.__rozieWatchInitial_0 = true;
6960
+ this.__rozieFirstUpdateDone = false;
6898
6961
  this._disconnectCleanups = [];
6899
6962
  this._rozieTornDown = false;
6900
6963
  this.minDraftValue = () => this._touched.value ? this._minDraft.value : Array.isArray(this.value) && this.value[0] != null ? String(this.value[0]) : "";
@@ -6933,8 +6996,9 @@ let FilterNumberRange = class FilterNumberRange extends SignalWatcher(LitElement
6933
6996
  }
6934
6997
  firstUpdated() {
6935
6998
  this._disconnectCleanups.push(effect(() => {
6936
- Array.isArray(this.value) && String(this.value[0]) + "" + String(this.value[1]);
6999
+ const __watchVal = Array.isArray(this.value) ? String(this.value[0]) + "\0" + String(this.value[1]) : "";
6937
7000
  untracked(() => {
7001
+ this.__rozieWatchPrev_0 = __watchVal;
6938
7002
  if (this.__rozieWatchInitial_0) {
6939
7003
  this.__rozieWatchInitial_0 = false;
6940
7004
  return;
@@ -6943,6 +7007,16 @@ let FilterNumberRange = class FilterNumberRange extends SignalWatcher(LitElement
6943
7007
  });
6944
7008
  }));
6945
7009
  }
7010
+ updated(changedProperties) {
7011
+ if (this.__rozieFirstUpdateDone && changedProperties.has("value")) {
7012
+ const __watchVal = untracked(() => Array.isArray(this.value) ? String(this.value[0]) + "\0" + String(this.value[1]) : "");
7013
+ if (!Object.is(__watchVal, this.__rozieWatchPrev_0)) {
7014
+ this.__rozieWatchPrev_0 = __watchVal;
7015
+ untracked(() => (this._touched.value = false, void 0));
7016
+ }
7017
+ }
7018
+ this.__rozieFirstUpdateDone = true;
7019
+ }
6946
7020
  disconnectedCallback() {
6947
7021
  super.disconnectedCallback();
6948
7022
  queueMicrotask(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rozie-ui/data-table-lit",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "license": "MIT",
@@ -46,7 +46,7 @@
46
46
  "CHANGELOG.md"
47
47
  ],
48
48
  "dependencies": {
49
- "@rozie/runtime-lit": "^0.9.0"
49
+ "@rozie/runtime-lit": "^0.10.1"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "lit": "^3.2",
package/src/Column.ts CHANGED
@@ -101,12 +101,14 @@ private get registry() { return this.__rozieCtxConsumer_data_table_columns.value
101
101
  })(); }
102
102
  this.__rozieFirstUpdateDone = true;
103
103
 
104
- if (this.registered) return;
105
- const live = this.registry;
106
- if (live == null) return;
107
- this.reg = live;
108
- this.registered = true;
109
- this.reg.registerColumn(this.colId(), this.buildSpec());
104
+ (() => {
105
+ if (this.registered) return;
106
+ const live = this.registry;
107
+ if (live == null) return;
108
+ this.reg = live;
109
+ this.registered = true;
110
+ this.reg.registerColumn(this.colId(), this.buildSpec());
111
+ })();
110
112
  }
111
113
 
112
114
  disconnectedCallback(): void {
package/src/DataTable.ts CHANGED
@@ -753,7 +753,7 @@ export default class DataTable extends SignalWatcher(LitElement) {
753
753
  * `GroupingState` — an ordered `string[]` of column ids (multi-column → nested groups, e.g. `['region','category']`). An empty/unbound list is ungrouped (byte-identical-off). Group-header rows are collapsible (they ride the expand model). Surfaces through `group-change`; uncontrolled fallback (`$data.groupingDefault`, default `[]`) when unbound — the default is `null` (mirroring `expanded`) so the uncontrolled fallback is reachable and the grouping auto-expand default can activate when a consumer applies grouping without binding the two-way `grouping` model (a non-null `[]` default would short-circuit it). All reads are null-guarded, so table-core still receives an array.
754
754
  */
755
755
  @property({ type: Array, attribute: 'grouping' }) _grouping_attr: any[] | null = null;
756
- private _groupingControllable = createLitControllableProperty<any[]>({ host: this, eventName: 'grouping-change', defaultValue: null, initialControlledValue: undefined });
756
+ private _groupingControllable = createLitControllableProperty<any[] | null>({ host: this, eventName: 'grouping-change', defaultValue: null, initialControlledValue: undefined });
757
757
  /**
758
758
  * `RowSelectionState` — `{ [rowId]: true }`. Checkbox-only toggle (the row body does not select). Driven by the `selectionMode` chrome. Two-way: fires `selection-change` regardless of binding.
759
759
  */
@@ -872,8 +872,10 @@ export default class DataTable extends SignalWatcher(LitElement) {
872
872
  private _liveAnnounce = signal('');
873
873
  @query('[data-rozie-ref="__rozieRoot"]') private _ref__rozieRoot!: HTMLElement;
874
874
  private __rozieWatchInitial_0 = true;
875
+ private __rozieWatchPrev_1: unknown;
875
876
  private __rozieWatchInitial_1 = true;
876
877
  private __rozieWatchInitial_2 = true;
878
+ private __rozieFirstUpdateDone = false;
877
879
  private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { context: __rozieCtx_data_table_columns, initialValue: ((__rozieCtxHost) => ({
878
880
  registerColumn: (id: any, spec: any) => {
879
881
  if (id == null) return;
@@ -1152,7 +1154,7 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1152
1154
  // columnDefs()/tableColumns() build the UNION of both, and reFeed re-passes columns.
1153
1155
  // (Consumers memoize the array as with $props.data/$props.sorting; the uncontrolled
1154
1156
  // <Column>-children path leaves $props.columns undefined — a stable no-op getter.)
1155
- this.columns, this._colReg.value])(); untracked(() => { if (this.__rozieWatchInitial_1) { this.__rozieWatchInitial_1 = false; return; } (() => {
1157
+ this.columns, this._colReg.value])(); untracked(() => { this.__rozieWatchPrev_1 = __watchVal; if (this.__rozieWatchInitial_1) { this.__rozieWatchInitial_1 = false; return; } (() => {
1156
1158
  // Seed BEFORE the re-feed so the pinning this call may write is part of the state object
1157
1159
  // table-core receives on this same tick (rather than landing a frame late and re-ordering
1158
1160
  // getVisibleCells() a render after the columns appear). One-shot and self-latching — see
@@ -1208,15 +1210,8 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1208
1210
  // re-ordering a render later. Covers the `:columns` config-array form, which is available
1209
1211
  // now; `<Column>` children register during mount and are covered by the re-feed watch's own
1210
1212
  // call. One-shot and self-latching — see seedColumnPinning() in stateAssembly.rzts.
1211
- // Apply any per-column `pinned` declaration as the INITIAL pinning state BEFORE createTable
1212
- // reads currentState() below, so the first row model table-core builds is already correctly
1213
- // ordered (getVisibleCells() returns [left-pinned, center, right-pinned]) rather than
1214
- // re-ordering a render later. Covers the `:columns` config-array form, which is available
1215
- // now; `<Column>` children register during mount and are covered by the re-feed watch's own
1216
- // call. One-shot and self-latching — see seedColumnPinning() in stateAssembly.rzts.
1217
1213
  this.seedColumnPinning();
1218
1214
  // Build the table instance HERE so the closures below capture the live `table`.
1219
- // Build the table instance HERE so the closures below capture the live `table`.
1220
1215
  this.table = createTable({
1221
1216
  // Plain value (NOT a `get data()` getter): an object-literal getter rebinds
1222
1217
  // `this` to the options object, and the Angular/Lit emitters resolve $props via
@@ -1399,14 +1394,9 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1399
1394
  if (typeof queueMicrotask !== 'undefined') queueMicrotask(this.syncIndeterminate);else Promise.resolve().then(this.syncIndeterminate);
1400
1395
  };
1401
1396
 
1402
- // initial pull
1403
1397
  // initial pull
1404
1398
  this.refreshRowModel();
1405
1399
 
1406
- // ── Grid mode: capture the table root ──────────────────────────────────────────────
1407
- // $el is the component root; the <table class="rozie-data-table"> is the grid root the
1408
- // cell selectors hang off (the exact idiom proven ×6 by plan 01's probe). Captured here
1409
- // (post-mount) so it is non-null and ROZ123-clean.
1410
1400
  // ── Grid mode: capture the table root ──────────────────────────────────────────────
1411
1401
  // $el is the component root; the <table class="rozie-data-table"> is the grid root the
1412
1402
  // cell selectors hang off (the exact idiom proven ×6 by plan 01's probe). Captured here
@@ -1415,9 +1405,6 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1415
1405
  // B-02: the click-away detector. `composedPath()` rather than `ev.target` because on Lit the
1416
1406
  // grid lives in a shadow root and a document-level listener sees the retargeted HOST element,
1417
1407
  // which is never `gridRoot.contains(...)` — every in-grid click would read as "outside".
1418
- // B-02: the click-away detector. `composedPath()` rather than `ev.target` because on Lit the
1419
- // grid lives in a shadow root and a document-level listener sees the retargeted HOST element,
1420
- // which is never `gridRoot.contains(...)` — every in-grid click would read as "outside".
1421
1408
  if (typeof document !== 'undefined') {
1422
1409
  this.docPointerDown = (ev: any) => {
1423
1410
  if (!this.gridRoot) {
@@ -1436,20 +1423,6 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1436
1423
  // cell IS the first Tab-in target (matching the Wave-0 probe's "no auto-focus on
1437
1424
  // mount"); the consumer drives focus by Tabbing/clicking in, never the component.
1438
1425
 
1439
- // ── Windowing: capture the scroll element + construct the row virtualizer (req-1/2 — the
1440
- // row virtual-core instance ONLY when rows are windowed; the scroll-element capture whenever
1441
- // EITHER axis is windowed, since both axes observe the SAME .rdt-scroll element — D-03). Built
1442
- // HERE (post-mount) so getScrollElement resolves the rendered .rdt-scroll div and
1443
- // getPrePaginationRowModel reads the live table. ENTIRELY inside the isWindowed()/rowsWindowed()
1444
- // guards: when both axes are off, NO virtual-core runtime code executes (byte-identical-off).
1445
- // _didMount() registers the scroll-element ResizeObserver and returns the teardown stored for
1446
- // $onUnmount.
1447
- // WR-04: NO on-mount auto-focus of the entry cell. Auto-focusing here stole focus on
1448
- // page load AND was non-deterministic on React/Solid (the entry cell may not be
1449
- // committed to the DOM yet at the $onMount microtask). The roving tabindex="0" entry
1450
- // cell IS the first Tab-in target (matching the Wave-0 probe's "no auto-focus on
1451
- // mount"); the consumer drives focus by Tabbing/clicking in, never the component.
1452
-
1453
1426
  // ── Windowing: capture the scroll element + construct the row virtualizer (req-1/2 — the
1454
1427
  // row virtual-core instance ONLY when rows are windowed; the scroll-element capture whenever
1455
1428
  // EITHER axis is windowed, since both axes observe the SAME .rdt-scroll element — D-03). Built
@@ -1468,9 +1441,6 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1468
1441
  // Phase 87 87-04: construct the SECOND, horizontal Virtualizer instance when the COLUMN
1469
1442
  // axis is windowed — entirely inside its own colsWindowed() guard, byte-identical-off for
1470
1443
  // 'rows'/true/false.
1471
- // Phase 87 87-04: construct the SECOND, horizontal Virtualizer instance when the COLUMN
1472
- // axis is windowed — entirely inside its own colsWindowed() guard, byte-identical-off for
1473
- // 'rows'/true/false.
1474
1444
  if (this.colsWindowed()) {
1475
1445
  this.colVirtualizer = new Virtualizer(this.columnVirtualizerOptions());
1476
1446
  this.colVirtualizerCleanup = this.colVirtualizer._didMount();
@@ -1493,24 +1463,6 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1493
1463
  // idiom lowers to a functional React setState update and is safe regardless of ordering, the
1494
1464
  // same reasoning virtualizerOptions()'s onChange documents), but collapsing to one bump avoids
1495
1465
  // manufacturing the false-positive warning at all rather than accepting it.
1496
- // FINE-GRAINED FIRST-WINDOW KICK (Solid/Svelte), either axis: the windowed <For>/{#each}
1497
- // accessor was first evaluated at initial render — while `virtualizer`/`colVirtualizer` were
1498
- // still null — and (because windowedRows()/windowedColIndices() read $data.windowVer up top)
1499
- // subscribed to windowVer then returned []/the full set. Both `let`s are non-reactive, so
1500
- // their assignment above does NOT notify the accessor; we must bump the SIGNAL it subscribed
1501
- // to. _didMount() computes the first window synchronously but its onChange only fires on
1502
- // SUBSEQUENT scroll/resize, so without this explicit bump the first window would never paint
1503
- // on the fine-grained targets. Idempotent + harmless on the coarse targets (they re-render
1504
- // wholesale anyway). ONE bump here (not one per axis, Rule 1 — see the ROZ138 note below)
1505
- // covers both: windowedRows()/windowedColIndices() each simply re-derive against their own
1506
- // now-non-null virtualizer instance off the SAME counter (87-02 checkpoint decision (b): no
1507
- // separate $data.colWindowVer). Gated on isWindowed() (either axis) rather than two separate
1508
- // per-axis bumps: a second `$data.windowVer = $data.windowVer + 1` write later in this SAME
1509
- // $onMount body would dominate-flag ROZ138 (React stale-read) on its own right-hand-side read
1510
- // of the counter it had just written a few lines above — a false positive (this increment
1511
- // idiom lowers to a functional React setState update and is safe regardless of ordering, the
1512
- // same reasoning virtualizerOptions()'s onChange documents), but collapsing to one bump avoids
1513
- // manufacturing the false-positive warning at all rather than accepting it.
1514
1466
  if (this.isWindowed()) {
1515
1467
  this._windowVer.value = this._windowVer.value + 1;
1516
1468
  }
@@ -1520,12 +1472,6 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1520
1472
  // row-specific measurement + warns stay further guarded by rowsWindowed() (byte-identical to
1521
1473
  // before this restructure); the column-axis warn (Phase 87 D-07(a)) is guarded by
1522
1474
  // colsWindowed() so it can fire ONLY on the 'columns'/'both' path, never on 'rows'/true/false.
1523
- // After the first window commits (next frame), refine heights + fire the dev-mode warns ONCE.
1524
- // Entirely inside the isWindowed() guard so the off (neither axis windowed) emitted path adds
1525
- // NO code and these warns can never fire there (req-1 byte-identical-off preserved). The
1526
- // row-specific measurement + warns stay further guarded by rowsWindowed() (byte-identical to
1527
- // before this restructure); the column-axis warn (Phase 87 D-07(a)) is guarded by
1528
- // colsWindowed() so it can fire ONLY on the 'columns'/'both' path, never on 'rows'/true/false.
1529
1475
  if (this.isWindowed()) {
1530
1476
  const afterFirstFrame = () => {
1531
1477
  if (this.rowsWindowed()) {
@@ -1592,9 +1538,6 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1592
1538
  if (typeof requestAnimationFrame === 'function') requestAnimationFrame(() => requestAnimationFrame(afterFirstFrame));else setTimeout(afterFirstFrame, 0);
1593
1539
  }
1594
1540
 
1595
- // #14: seed the sort/filter announce baseline from the initial (post-mount) state so the LAZY
1596
- // watch's first fire — a real user sort/filter — compares against the true starting values and
1597
- // is classified correctly (a null sentinel would misread the first filter change as a sort change).
1598
1541
  // #14: seed the sort/filter announce baseline from the initial (post-mount) state so the LAZY
1599
1542
  // watch's first fire — a real user sort/filter — compares against the true starting values and
1600
1543
  // is classified correctly (a null sentinel would misread the first filter change as a sort change).
@@ -1604,41 +1547,55 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1604
1547
  }
1605
1548
 
1606
1549
  updated(changedProperties: Map<string, unknown>): void {
1607
- this.maybeClearHistoryOnExternalSwap();
1608
- // visible-range-change backstop (quick 260925-dtl part 2): a re-render from new data can move
1609
- // the rendered window WITHOUT a window-version bump (measured on React: filling placeholders
1610
- // shifted the window by two rows and nothing was reported). Deduped, so a render that leaves
1611
- // the window where it was emits nothing.
1612
- // visible-range-change backstop (quick 260925-dtl part 2): a re-render from new data can move
1613
- // the rendered window WITHOUT a window-version bump (measured on React: filling placeholders
1614
- // shifted the window by two rows and nothing was reported). Deduped, so a render that leaves
1615
- // the window where it was emits nothing.
1616
- this.emitVisibleRangeIfChanged();
1617
- // A-02: the post-render hook is the one place that observes EVERY column-width change on all
1618
- // six targets — an interactive resize writes `columnSizing` through table-core under
1619
- // `columnResizeMode: 'onChange'` and never reaches the coarse re-feed watch (which keys on
1620
- // `$props.columnSizing`, undefined on the uncontrolled path). Self-guarded on the width
1621
- // signature, so a tick that changed no width costs one loop over the leaf columns.
1622
- // A-02: the post-render hook is the one place that observes EVERY column-width change on all
1623
- // six targets — an interactive resize writes `columnSizing` through table-core under
1624
- // `columnResizeMode: 'onChange'` and never reaches the coarse re-feed watch (which keys on
1625
- // `$props.columnSizing`, undefined on the uncontrolled path). Self-guarded on the width
1626
- // signature, so a tick that changed no width costs one loop over the leaf columns.
1627
- this.remeasureColumnSizes();
1628
- if (!this.table) return;
1629
- // Phase 51 req-4: track currentData() (the bound prop OR the uncontrolled
1630
- // $data.dataDefault) so a committed edit re-feeds on Lit whether or not the two-way
1631
- // `data` model is bound. Compare by reference AND length so a same-length single-cell edit (fresh array,
1632
- // identical length) still re-feeds.
1633
- // Phase 51 req-4: track currentData() (the bound prop OR the uncontrolled
1634
- // $data.dataDefault) so a committed edit re-feeds on Lit whether or not the two-way
1635
- // `data` model is bound. Compare by reference AND length so a same-length single-cell edit (fresh array,
1636
- // identical length) still re-feeds.
1637
- const d = this.currentData() || [];
1638
- if (d === this.lastData && d.length === this.lastDataLen) return;
1639
- this.lastData = d;
1640
- this.lastDataLen = d.length;
1641
- this.reFeed();
1550
+ if (this.__rozieFirstUpdateDone && (changedProperties.has('rowCount') || changedProperties.has('pageCount') || changedProperties.has('expandable') || changedProperties.has('groupable') || changedProperties.has('selectionMode') || changedProperties.has('columns'))) { const __watchVal = untracked(() => [this.sorting, this.globalFilter, this.columnFilters, this.pagination, // Server-side page-count sources (#2): re-feed when the consumer's rowCount/pageCount
1551
+ // changes at runtime (e.g. a server response updates the total) so getPageCount() and the
1552
+ // Next button availability track the new total.
1553
+ this.rowCount, this.pageCount, this.rowSelection, this.expanded, this.expandable, this.grouping, this.groupable, this.columnVisibility, this.columnSizing, this.columnOrder, this.columnPinning, this.selectionMode, (this.data || []).length, // Phase 51 req-4: key on the data REFERENCE (both sinks) so a committed edit re-feeds
1554
+ // even when the fresh array is the SAME length (a single-cell edit replaces one row
1555
+ // object → new array ref, identical length → the .length key alone would miss it). The
1556
+ // controlled path observes $props.data; the uncontrolled path observes $data.dataDefault.
1557
+ // writeData is echo-guarded (programmatic) and reFeed writes neither sink, so no loop.
1558
+ this.data, this._dataDefault.value, // Column CONFIG prop (the `:columns` array form) — the sibling column source to
1559
+ // $data.colReg (the `<Column>` children). Watch it so a runtime `:columns` swap re-feeds:
1560
+ // columnDefs()/tableColumns() build the UNION of both, and reFeed re-passes columns.
1561
+ // (Consumers memoize the array as with $props.data/$props.sorting; the uncontrolled
1562
+ // <Column>-children path leaves $props.columns undefined — a stable no-op getter.)
1563
+ this.columns, this._colReg.value]); if (!Object.is(__watchVal, this.__rozieWatchPrev_1)) { this.__rozieWatchPrev_1 = __watchVal; untracked(() => (() => {
1564
+ // Seed BEFORE the re-feed so the pinning this call may write is part of the state object
1565
+ // table-core receives on this same tick (rather than landing a frame late and re-ordering
1566
+ // getVisibleCells() a render after the columns appear). One-shot and self-latching — see
1567
+ // seedColumnPinning() in stateAssembly.rzts. This is the `<Column>`-children entry point:
1568
+ // those register during mount, so the $onMount call below can find zero columns.
1569
+ this.seedColumnPinning();
1570
+ this.reFeed();
1571
+ this.maybeClearHistoryOnExternalSwap();
1572
+ })()); } }
1573
+ this.__rozieFirstUpdateDone = true;
1574
+
1575
+ (() => {
1576
+ this.maybeClearHistoryOnExternalSwap();
1577
+ // visible-range-change backstop (quick 260925-dtl part 2): a re-render from new data can move
1578
+ // the rendered window WITHOUT a window-version bump (measured on React: filling placeholders
1579
+ // shifted the window by two rows and nothing was reported). Deduped, so a render that leaves
1580
+ // the window where it was emits nothing.
1581
+ this.emitVisibleRangeIfChanged();
1582
+ // A-02: the post-render hook is the one place that observes EVERY column-width change on all
1583
+ // six targets — an interactive resize writes `columnSizing` through table-core under
1584
+ // `columnResizeMode: 'onChange'` and never reaches the coarse re-feed watch (which keys on
1585
+ // `$props.columnSizing`, undefined on the uncontrolled path). Self-guarded on the width
1586
+ // signature, so a tick that changed no width costs one loop over the leaf columns.
1587
+ this.remeasureColumnSizes();
1588
+ if (!this.table) return;
1589
+ // Phase 51 req-4: track currentData() (the bound prop OR the uncontrolled
1590
+ // $data.dataDefault) so a committed edit re-feeds on Lit whether or not the two-way
1591
+ // `data` model is bound. Compare by reference AND length so a same-length single-cell edit (fresh array,
1592
+ // identical length) still re-feeds.
1593
+ const d = this.currentData() || [];
1594
+ if (d === this.lastData && d.length === this.lastDataLen) return;
1595
+ this.lastData = d;
1596
+ this.lastDataLen = d.length;
1597
+ this.reFeed();
1598
+ })();
1642
1599
  }
1643
1600
 
1644
1601
  disconnectedCallback(): void {
@@ -1683,7 +1640,7 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
1683
1640
  if (name === 'column-filters') this._columnFiltersControllable.notifyAttributeChange(value as unknown as any[]);
1684
1641
  if (name === 'pagination') this._paginationControllable.notifyAttributeChange(value as unknown as any);
1685
1642
  if (name === 'expanded') this._expandedControllable.notifyAttributeChange(value as unknown as any | boolean);
1686
- if (name === 'grouping') this._groupingControllable.notifyAttributeChange(value as unknown as any[]);
1643
+ if (name === 'grouping') this._groupingControllable.notifyAttributeChange(value as unknown as any[] | null);
1687
1644
  if (name === 'row-selection') this._rowSelectionControllable.notifyAttributeChange(value as unknown as any);
1688
1645
  if (name === 'column-visibility') this._columnVisibilityControllable.notifyAttributeChange(value as unknown as any);
1689
1646
  if (name === 'column-sizing') this._columnSizingControllable.notifyAttributeChange(value as unknown as any);
@@ -5278,9 +5235,6 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
5278
5235
  // page-relative active row → absolute (display-order) index.
5279
5236
  toAbsRow = (localRow: any) => localRow + this.pageRowOffset();
5280
5237
 
5281
- // A body row's ABSOLUTE display-order index = its page-relative index + the page offset. Drives
5282
- // aria-rowindex on the non-virtual paginated body (B27); the virtual path uses wr.vi.index
5283
- // directly (already absolute). Reactive via rowIndexOf's tick().
5284
5238
  // Total filtered+sorted PRE-pagination row count — the clamp bound for an absolute focusCell.
5285
5239
  // In virtual mode $data.rows IS the full pre-pagination model (bodyRowCount suffices); in the
5286
5240
  // non-virtual paginated body $data.rows is only the page slice, so read the live model.
@@ -9517,8 +9471,8 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
9517
9471
  set pagination(v: any) { this._paginationControllable.notifyPropertyWrite(v); }
9518
9472
  get expanded(): any | boolean { return this._expandedControllable.read(); }
9519
9473
  set expanded(v: any | boolean) { this._expandedControllable.notifyPropertyWrite(v); }
9520
- get grouping(): any[] { return this._groupingControllable.read(); }
9521
- set grouping(v: any[]) { this._groupingControllable.notifyPropertyWrite(v); }
9474
+ get grouping(): any[] | null { return this._groupingControllable.read(); }
9475
+ set grouping(v: any[] | null) { this._groupingControllable.notifyPropertyWrite(v); }
9522
9476
  get rowSelection(): any { return this._rowSelectionControllable.read(); }
9523
9477
  set rowSelection(v: any) { this._rowSelectionControllable.notifyPropertyWrite(v); }
9524
9478
  get columnVisibility(): any { return this._columnVisibilityControllable.read(); }
@@ -36,7 +36,9 @@ export default class FilterNumberRange extends SignalWatcher(LitElement) {
36
36
  private _minDraft = signal('');
37
37
  private _maxDraft = signal('');
38
38
  private _touched = signal(false);
39
+ private __rozieWatchPrev_0: unknown;
39
40
  private __rozieWatchInitial_0 = true;
41
+ private __rozieFirstUpdateDone = false;
40
42
 
41
43
  private _disconnectCleanups: Array<() => void> = [];
42
44
  // Re-parenting guard: set true once the deferred teardown has actually
@@ -44,11 +46,18 @@ private __rozieWatchInitial_0 = true;
44
46
  private _rozieTornDown = false;
45
47
 
46
48
  firstUpdated(): void {
47
- this._disconnectCleanups.push(effect(() => { const __watchVal = (() => Array.isArray(this.value) ? String(this.value[0]) + '\u0000' + String(this.value[1]) : '')(); untracked(() => { if (this.__rozieWatchInitial_0) { this.__rozieWatchInitial_0 = false; return; } (() => {
49
+ this._disconnectCleanups.push(effect(() => { const __watchVal = (() => Array.isArray(this.value) ? String(this.value[0]) + '\u0000' + String(this.value[1]) : '')(); untracked(() => { this.__rozieWatchPrev_0 = __watchVal; if (this.__rozieWatchInitial_0) { this.__rozieWatchInitial_0 = false; return; } (() => {
48
50
  this._touched.value = false;
49
51
  })(); }); }));
50
52
  }
51
53
 
54
+ updated(changedProperties: Map<string, unknown>): void {
55
+ if (this.__rozieFirstUpdateDone && (changedProperties.has('value'))) { const __watchVal = untracked(() => Array.isArray(this.value) ? String(this.value[0]) + '\u0000' + String(this.value[1]) : ''); if (!Object.is(__watchVal, this.__rozieWatchPrev_0)) { this.__rozieWatchPrev_0 = __watchVal; untracked(() => (() => {
56
+ this._touched.value = false;
57
+ })()); } }
58
+ this.__rozieFirstUpdateDone = true;
59
+ }
60
+
52
61
  disconnectedCallback(): void {
53
62
  super.disconnectedCallback();
54
63
  queueMicrotask(() => {