@rozie-ui/data-table-lit 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -494,5 +494,5 @@ The `detail` (expandable rows), `groupBar` (grouping) and `filter` (faceted filt
494
494
  | filter | columnId, value, uniqueValues, minMax, setFilter |
495
495
  | selectCell | row, checked, toggle |
496
496
  | cell | columnId, column, row, value |
497
- | editor | columnId, column, row, value, commit, cancel |
497
+ | editor | columnId, column, row, value, commit, cancel, autofocus |
498
498
  | detail | row |
package/dist/index.cjs CHANGED
@@ -175,6 +175,7 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
175
175
  this._draftValue = (0, _lit_labs_preact_signals.signal)(null);
176
176
  this._invalidMsg = (0, _lit_labs_preact_signals.signal)("");
177
177
  this._editVer = (0, _lit_labs_preact_signals.signal)(0);
178
+ this._editFocusColId = (0, _lit_labs_preact_signals.signal)(null);
178
179
  this._editingRowIndex = (0, _lit_labs_preact_signals.signal)(null);
179
180
  this._rowDraft = (0, _lit_labs_preact_signals.signal)({});
180
181
  this._rangeAnchor = (0, _lit_labs_preact_signals.signal)(null);
@@ -2476,6 +2477,7 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
2476
2477
  };
2477
2478
  this.focusEditorWhenReady = (selectAll = true) => {
2478
2479
  if (!this.gridRoot) return;
2480
+ if (this._editFocusColId.value != null && this.hasEditorSlot(this._editFocusColId.value)) return;
2479
2481
  let attempts = 0;
2480
2482
  const tryFocus = () => {
2481
2483
  const el = this.gridRoot ? this.gridRoot.querySelector("[data-editing-cell]") : null;
@@ -2526,6 +2528,7 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
2526
2528
  this._draftValue.value = seed != null ? seed : this.cellValueAt(rowIndex, colIndex);
2527
2529
  this._activeInControl.value = true;
2528
2530
  this._editVer.value = this._editVer.value + 1;
2531
+ this._editFocusColId.value = colId;
2529
2532
  this.focusEditorWhenReady(seed == null);
2530
2533
  };
2531
2534
  this.focusCellWhenReady = (row, col) => {
@@ -2562,6 +2565,7 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
2562
2565
  this._invalidMsg.value = "";
2563
2566
  this._activeInControl.value = false;
2564
2567
  this._editVer.value = this._editVer.value + 1;
2568
+ this._editFocusColId.value = null;
2565
2569
  };
2566
2570
  this.endRowEdit = () => {
2567
2571
  this._editingRowIndex.value = null;
@@ -2569,6 +2573,14 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
2569
2573
  this._invalidMsg.value = "";
2570
2574
  this._activeInControl.value = false;
2571
2575
  this._editVer.value = this._editVer.value + 1;
2576
+ this._editFocusColId.value = null;
2577
+ };
2578
+ this.editorAutofocusFor = (colId, rowIndex) => {
2579
+ if (this._editVer.value < 0) return false;
2580
+ if (this._editingRowIndex.value != null) {
2581
+ if (this._editingRowIndex.value !== rowIndex) return false;
2582
+ } else if (this._editingRow.value !== rowIndex) return false;
2583
+ return this._editFocusColId.value != null && this._editFocusColId.value === colId;
2572
2584
  };
2573
2585
  this.coerceCellValue = (colId, raw) => {
2574
2586
  if (this.editorTypeOf(colId) !== "number") return raw;
@@ -2697,6 +2709,8 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
2697
2709
  };
2698
2710
  this.focusRowEditorAt = (rowIndex, colIndex) => {
2699
2711
  if (!this.gridRoot) return;
2712
+ const colId = this.columnIdAt(rowIndex, colIndex);
2713
+ if (colId != null && this.hasEditorSlot(colId)) return;
2700
2714
  let attempts = 0;
2701
2715
  const tryFocus = () => {
2702
2716
  const cellEl = this.resolveCellEl(String(rowIndex), colIndex);
@@ -2737,6 +2751,7 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
2737
2751
  this._editingRowIndex.value = rowIndex;
2738
2752
  this._activeInControl.value = true;
2739
2753
  this._editVer.value = this._editVer.value + 1;
2754
+ this._editFocusColId.value = editable[0].colId;
2740
2755
  this.focusEditorWhenReady();
2741
2756
  };
2742
2757
  this.commitRow = () => {
@@ -2756,6 +2771,8 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
2756
2771
  const err = this.runValidator(ec.colId, this.coerceCellValue(ec.colId, draft[ec.colId]), rowOriginal);
2757
2772
  if (err !== true) {
2758
2773
  this.setInvalid(err);
2774
+ this._editFocusColId.value = ec.colId;
2775
+ this._editVer.value = this._editVer.value + 1;
2759
2776
  this.focusRowEditorAt(rowIndex, ec.colIndex);
2760
2777
  return false;
2761
2778
  }
@@ -2925,6 +2942,8 @@ let DataTable = class DataTable extends (0, _lit_labs_preact_signals.SignalWatch
2925
2942
  if (pos < 0) pos = 0;
2926
2943
  const len = cols.length;
2927
2944
  const nextPos = backward ? (pos - 1 + len) % len : (pos + 1) % len;
2945
+ this._editFocusColId.value = editable[nextPos].colId;
2946
+ this._editVer.value = this._editVer.value + 1;
2928
2947
  this.focusRowEditorAt(rowIndex, cols[nextPos]);
2929
2948
  };
2930
2949
  this.onEditorKeyDown = (e) => {
@@ -4023,7 +4042,8 @@ ${this.groupable ? lit.html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4
4023
4042
  row: wr.row.original,
4024
4043
  value: this.editorValueFor(cell.column.id),
4025
4044
  commit: this.editorCommitFor(cell.column.id),
4026
- cancel: this.editorCancelFor()
4045
+ cancel: this.editorCancelFor(),
4046
+ autofocus: this.editorAutofocusFor(cell.column.id, wr.vi.index)
4027
4047
  }) : lit.html`<slot name="editor" data-rozie-params=${(() => {
4028
4048
  try {
4029
4049
  return JSON.stringify({
@@ -4032,7 +4052,8 @@ ${this.groupable ? lit.html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4
4032
4052
  row: wr.row.original,
4033
4053
  value: this.editorValueFor(cell.column.id),
4034
4054
  commit: this.editorCommitFor(cell.column.id),
4035
- cancel: this.editorCancelFor()
4055
+ cancel: this.editorCancelFor(),
4056
+ autofocus: this.editorAutofocusFor(cell.column.id, wr.vi.index)
4036
4057
  });
4037
4058
  } catch {
4038
4059
  return "{}";
@@ -4314,7 +4335,8 @@ ${this.groupable ? lit.html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4
4314
4335
  row: row.original,
4315
4336
  value: this.editorValueFor(cell.column.id),
4316
4337
  commit: this.editorCommitFor(cell.column.id),
4317
- cancel: this.editorCancelFor()
4338
+ cancel: this.editorCancelFor(),
4339
+ autofocus: this.editorAutofocusFor(cell.column.id, this.rowIndexOf(row))
4318
4340
  }) : lit.html`<slot name="editor" data-rozie-params=${(() => {
4319
4341
  try {
4320
4342
  return JSON.stringify({
@@ -4323,7 +4345,8 @@ ${this.groupable ? lit.html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4
4323
4345
  row: row.original,
4324
4346
  value: this.editorValueFor(cell.column.id),
4325
4347
  commit: this.editorCommitFor(cell.column.id),
4326
- cancel: this.editorCancelFor()
4348
+ cancel: this.editorCancelFor(),
4349
+ autofocus: this.editorAutofocusFor(cell.column.id, this.rowIndexOf(row))
4327
4350
  });
4328
4351
  } catch {
4329
4352
  return "{}";
@@ -4796,7 +4819,9 @@ let EditorText = class EditorText extends (0, _lit_labs_preact_signals.SignalWat
4796
4819
  this.value = null;
4797
4820
  this.commit = null;
4798
4821
  this.cancel = null;
4822
+ this.autofocus = false;
4799
4823
  this._draft = (0, _lit_labs_preact_signals.signal)("");
4824
+ this.__rozieFirstUpdateDone = false;
4800
4825
  this._disconnectCleanups = [];
4801
4826
  this._rozieTornDown = false;
4802
4827
  this.onInput = (e) => {
@@ -4828,6 +4853,13 @@ let EditorText = class EditorText extends (0, _lit_labs_preact_signals.SignalWat
4828
4853
  }
4829
4854
  firstUpdated() {
4830
4855
  this._draft.value = this.value != null ? String(this.value) : "";
4856
+ if (this.autofocus) this._refInputEl?.focus();
4857
+ }
4858
+ updated(changedProperties) {
4859
+ if (this.__rozieFirstUpdateDone && changedProperties.has("autofocus")) ((v) => {
4860
+ if (v) this._refInputEl?.focus();
4861
+ })(this.autofocus);
4862
+ this.__rozieFirstUpdateDone = true;
4831
4863
  }
4832
4864
  disconnectedCallback() {
4833
4865
  super.disconnectedCallback();
@@ -4846,7 +4878,7 @@ let EditorText = class EditorText extends (0, _lit_labs_preact_signals.SignalWat
4846
4878
  this.onKeydown($event);
4847
4879
  }} @blur=${($event) => {
4848
4880
  this.onBlur();
4849
- }} data-rozie-s-0d17f43a />
4881
+ }} data-rozie-ref="inputEl" data-rozie-s-0d17f43a />
4850
4882
  `;
4851
4883
  }
4852
4884
  };
@@ -4859,6 +4891,11 @@ __decorate([(0, lit_decorators_js.property)({ type: Object })], EditorText.proto
4859
4891
  __decorate([(0, lit_decorators_js.property)({ type: Object })], EditorText.prototype, "value", void 0);
4860
4892
  __decorate([(0, lit_decorators_js.property)({ type: Function })], EditorText.prototype, "commit", void 0);
4861
4893
  __decorate([(0, lit_decorators_js.property)({ type: Function })], EditorText.prototype, "cancel", void 0);
4894
+ __decorate([(0, lit_decorators_js.property)({
4895
+ type: Boolean,
4896
+ reflect: true
4897
+ })], EditorText.prototype, "autofocus", void 0);
4898
+ __decorate([(0, lit_decorators_js.query)("[data-rozie-ref=\"inputEl\"]")], EditorText.prototype, "_refInputEl", void 0);
4862
4899
  EditorText = __decorate([(0, lit_decorators_js.customElement)("rozie-editor-text")], EditorText);
4863
4900
  var EditorText_default = EditorText;
4864
4901
  //#endregion
package/dist/index.d.cts CHANGED
@@ -159,6 +159,7 @@ declare class DataTable extends DataTable_base {
159
159
  private _draftValue;
160
160
  private _invalidMsg;
161
161
  private _editVer;
162
+ private _editFocusColId;
162
163
  private _editingRowIndex;
163
164
  private _rowDraft;
164
165
  private _rangeAnchor;
@@ -226,6 +227,7 @@ declare class DataTable extends DataTable_base {
226
227
  value: unknown;
227
228
  commit: unknown;
228
229
  cancel: unknown;
230
+ autofocus: unknown;
229
231
  }) => unknown;
230
232
  private _hasSlotDetail;
231
233
  private _slotDetailElements;
@@ -581,6 +583,7 @@ declare class DataTable extends DataTable_base {
581
583
  indexOfRowIn: (rows: any, rowOriginal: any, rowId: any) => number;
582
584
  endEdit: () => void;
583
585
  endRowEdit: () => void;
586
+ editorAutofocusFor: (colId: any, rowIndex: any) => boolean;
584
587
  coerceCellValue: (colId: any, raw: any) => any;
585
588
  commitEdit: (overrideValue?: any, skipFocusReturn?: boolean) => boolean;
586
589
  toggleActiveBooleanCell: () => void;
@@ -778,10 +781,17 @@ declare class EditorText extends EditorText_base {
778
781
  * `() => void` — revert the edit and close the editor (from the `#editor` slot scope). Null-guarded at call sites.
779
782
  */
780
783
  cancel: ((...args: unknown[]) => unknown) | null;
784
+ /**
785
+ * Focus this editor's primary input when true — the host sets it for the one editor that should hold focus; reactive.
786
+ */
787
+ autofocus: boolean;
781
788
  private _draft;
789
+ private _refInputEl;
790
+ private __rozieFirstUpdateDone;
782
791
  private _disconnectCleanups;
783
792
  private _rozieTornDown;
784
793
  firstUpdated(): void;
794
+ updated(changedProperties: Map<string, unknown>): void;
785
795
  disconnectedCallback(): void;
786
796
  render(): _$lit.TemplateResult<1>;
787
797
  onInput: (e: any) => void;
package/dist/index.d.mts CHANGED
@@ -159,6 +159,7 @@ declare class DataTable extends DataTable_base {
159
159
  private _draftValue;
160
160
  private _invalidMsg;
161
161
  private _editVer;
162
+ private _editFocusColId;
162
163
  private _editingRowIndex;
163
164
  private _rowDraft;
164
165
  private _rangeAnchor;
@@ -226,6 +227,7 @@ declare class DataTable extends DataTable_base {
226
227
  value: unknown;
227
228
  commit: unknown;
228
229
  cancel: unknown;
230
+ autofocus: unknown;
229
231
  }) => unknown;
230
232
  private _hasSlotDetail;
231
233
  private _slotDetailElements;
@@ -581,6 +583,7 @@ declare class DataTable extends DataTable_base {
581
583
  indexOfRowIn: (rows: any, rowOriginal: any, rowId: any) => number;
582
584
  endEdit: () => void;
583
585
  endRowEdit: () => void;
586
+ editorAutofocusFor: (colId: any, rowIndex: any) => boolean;
584
587
  coerceCellValue: (colId: any, raw: any) => any;
585
588
  commitEdit: (overrideValue?: any, skipFocusReturn?: boolean) => boolean;
586
589
  toggleActiveBooleanCell: () => void;
@@ -778,10 +781,17 @@ declare class EditorText extends EditorText_base {
778
781
  * `() => void` — revert the edit and close the editor (from the `#editor` slot scope). Null-guarded at call sites.
779
782
  */
780
783
  cancel: ((...args: unknown[]) => unknown) | null;
784
+ /**
785
+ * Focus this editor's primary input when true — the host sets it for the one editor that should hold focus; reactive.
786
+ */
787
+ autofocus: boolean;
781
788
  private _draft;
789
+ private _refInputEl;
790
+ private __rozieFirstUpdateDone;
782
791
  private _disconnectCleanups;
783
792
  private _rozieTornDown;
784
793
  firstUpdated(): void;
794
+ updated(changedProperties: Map<string, unknown>): void;
785
795
  disconnectedCallback(): void;
786
796
  render(): _$lit.TemplateResult<1>;
787
797
  onInput: (e: any) => void;
package/dist/index.mjs CHANGED
@@ -171,6 +171,7 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
171
171
  this._draftValue = signal(null);
172
172
  this._invalidMsg = signal("");
173
173
  this._editVer = signal(0);
174
+ this._editFocusColId = signal(null);
174
175
  this._editingRowIndex = signal(null);
175
176
  this._rowDraft = signal({});
176
177
  this._rangeAnchor = signal(null);
@@ -2472,6 +2473,7 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
2472
2473
  };
2473
2474
  this.focusEditorWhenReady = (selectAll = true) => {
2474
2475
  if (!this.gridRoot) return;
2476
+ if (this._editFocusColId.value != null && this.hasEditorSlot(this._editFocusColId.value)) return;
2475
2477
  let attempts = 0;
2476
2478
  const tryFocus = () => {
2477
2479
  const el = this.gridRoot ? this.gridRoot.querySelector("[data-editing-cell]") : null;
@@ -2522,6 +2524,7 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
2522
2524
  this._draftValue.value = seed != null ? seed : this.cellValueAt(rowIndex, colIndex);
2523
2525
  this._activeInControl.value = true;
2524
2526
  this._editVer.value = this._editVer.value + 1;
2527
+ this._editFocusColId.value = colId;
2525
2528
  this.focusEditorWhenReady(seed == null);
2526
2529
  };
2527
2530
  this.focusCellWhenReady = (row, col) => {
@@ -2558,6 +2561,7 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
2558
2561
  this._invalidMsg.value = "";
2559
2562
  this._activeInControl.value = false;
2560
2563
  this._editVer.value = this._editVer.value + 1;
2564
+ this._editFocusColId.value = null;
2561
2565
  };
2562
2566
  this.endRowEdit = () => {
2563
2567
  this._editingRowIndex.value = null;
@@ -2565,6 +2569,14 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
2565
2569
  this._invalidMsg.value = "";
2566
2570
  this._activeInControl.value = false;
2567
2571
  this._editVer.value = this._editVer.value + 1;
2572
+ this._editFocusColId.value = null;
2573
+ };
2574
+ this.editorAutofocusFor = (colId, rowIndex) => {
2575
+ if (this._editVer.value < 0) return false;
2576
+ if (this._editingRowIndex.value != null) {
2577
+ if (this._editingRowIndex.value !== rowIndex) return false;
2578
+ } else if (this._editingRow.value !== rowIndex) return false;
2579
+ return this._editFocusColId.value != null && this._editFocusColId.value === colId;
2568
2580
  };
2569
2581
  this.coerceCellValue = (colId, raw) => {
2570
2582
  if (this.editorTypeOf(colId) !== "number") return raw;
@@ -2693,6 +2705,8 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
2693
2705
  };
2694
2706
  this.focusRowEditorAt = (rowIndex, colIndex) => {
2695
2707
  if (!this.gridRoot) return;
2708
+ const colId = this.columnIdAt(rowIndex, colIndex);
2709
+ if (colId != null && this.hasEditorSlot(colId)) return;
2696
2710
  let attempts = 0;
2697
2711
  const tryFocus = () => {
2698
2712
  const cellEl = this.resolveCellEl(String(rowIndex), colIndex);
@@ -2733,6 +2747,7 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
2733
2747
  this._editingRowIndex.value = rowIndex;
2734
2748
  this._activeInControl.value = true;
2735
2749
  this._editVer.value = this._editVer.value + 1;
2750
+ this._editFocusColId.value = editable[0].colId;
2736
2751
  this.focusEditorWhenReady();
2737
2752
  };
2738
2753
  this.commitRow = () => {
@@ -2752,6 +2767,8 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
2752
2767
  const err = this.runValidator(ec.colId, this.coerceCellValue(ec.colId, draft[ec.colId]), rowOriginal);
2753
2768
  if (err !== true) {
2754
2769
  this.setInvalid(err);
2770
+ this._editFocusColId.value = ec.colId;
2771
+ this._editVer.value = this._editVer.value + 1;
2755
2772
  this.focusRowEditorAt(rowIndex, ec.colIndex);
2756
2773
  return false;
2757
2774
  }
@@ -2921,6 +2938,8 @@ let DataTable = class DataTable extends SignalWatcher(LitElement) {
2921
2938
  if (pos < 0) pos = 0;
2922
2939
  const len = cols.length;
2923
2940
  const nextPos = backward ? (pos - 1 + len) % len : (pos + 1) % len;
2941
+ this._editFocusColId.value = editable[nextPos].colId;
2942
+ this._editVer.value = this._editVer.value + 1;
2924
2943
  this.focusRowEditorAt(rowIndex, cols[nextPos]);
2925
2944
  };
2926
2945
  this.onEditorKeyDown = (e) => {
@@ -4019,7 +4038,8 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4019
4038
  row: wr.row.original,
4020
4039
  value: this.editorValueFor(cell.column.id),
4021
4040
  commit: this.editorCommitFor(cell.column.id),
4022
- cancel: this.editorCancelFor()
4041
+ cancel: this.editorCancelFor(),
4042
+ autofocus: this.editorAutofocusFor(cell.column.id, wr.vi.index)
4023
4043
  }) : html`<slot name="editor" data-rozie-params=${(() => {
4024
4044
  try {
4025
4045
  return JSON.stringify({
@@ -4028,7 +4048,8 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4028
4048
  row: wr.row.original,
4029
4049
  value: this.editorValueFor(cell.column.id),
4030
4050
  commit: this.editorCommitFor(cell.column.id),
4031
- cancel: this.editorCancelFor()
4051
+ cancel: this.editorCancelFor(),
4052
+ autofocus: this.editorAutofocusFor(cell.column.id, wr.vi.index)
4032
4053
  });
4033
4054
  } catch {
4034
4055
  return "{}";
@@ -4310,7 +4331,8 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4310
4331
  row: row.original,
4311
4332
  value: this.editorValueFor(cell.column.id),
4312
4333
  commit: this.editorCommitFor(cell.column.id),
4313
- cancel: this.editorCancelFor()
4334
+ cancel: this.editorCancelFor(),
4335
+ autofocus: this.editorAutofocusFor(cell.column.id, this.rowIndexOf(row))
4314
4336
  }) : html`<slot name="editor" data-rozie-params=${(() => {
4315
4337
  try {
4316
4338
  return JSON.stringify({
@@ -4319,7 +4341,8 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4319
4341
  row: row.original,
4320
4342
  value: this.editorValueFor(cell.column.id),
4321
4343
  commit: this.editorCommitFor(cell.column.id),
4322
- cancel: this.editorCancelFor()
4344
+ cancel: this.editorCancelFor(),
4345
+ autofocus: this.editorAutofocusFor(cell.column.id, this.rowIndexOf(row))
4323
4346
  });
4324
4347
  } catch {
4325
4348
  return "{}";
@@ -4792,7 +4815,9 @@ let EditorText = class EditorText extends SignalWatcher(LitElement) {
4792
4815
  this.value = null;
4793
4816
  this.commit = null;
4794
4817
  this.cancel = null;
4818
+ this.autofocus = false;
4795
4819
  this._draft = signal("");
4820
+ this.__rozieFirstUpdateDone = false;
4796
4821
  this._disconnectCleanups = [];
4797
4822
  this._rozieTornDown = false;
4798
4823
  this.onInput = (e) => {
@@ -4824,6 +4849,13 @@ let EditorText = class EditorText extends SignalWatcher(LitElement) {
4824
4849
  }
4825
4850
  firstUpdated() {
4826
4851
  this._draft.value = this.value != null ? String(this.value) : "";
4852
+ if (this.autofocus) this._refInputEl?.focus();
4853
+ }
4854
+ updated(changedProperties) {
4855
+ if (this.__rozieFirstUpdateDone && changedProperties.has("autofocus")) ((v) => {
4856
+ if (v) this._refInputEl?.focus();
4857
+ })(this.autofocus);
4858
+ this.__rozieFirstUpdateDone = true;
4827
4859
  }
4828
4860
  disconnectedCallback() {
4829
4861
  super.disconnectedCallback();
@@ -4842,7 +4874,7 @@ let EditorText = class EditorText extends SignalWatcher(LitElement) {
4842
4874
  this.onKeydown($event);
4843
4875
  }} @blur=${($event) => {
4844
4876
  this.onBlur();
4845
- }} data-rozie-s-0d17f43a />
4877
+ }} data-rozie-ref="inputEl" data-rozie-s-0d17f43a />
4846
4878
  `;
4847
4879
  }
4848
4880
  };
@@ -4855,6 +4887,11 @@ __decorate([property({ type: Object })], EditorText.prototype, "row", void 0);
4855
4887
  __decorate([property({ type: Object })], EditorText.prototype, "value", void 0);
4856
4888
  __decorate([property({ type: Function })], EditorText.prototype, "commit", void 0);
4857
4889
  __decorate([property({ type: Function })], EditorText.prototype, "cancel", void 0);
4890
+ __decorate([property({
4891
+ type: Boolean,
4892
+ reflect: true
4893
+ })], EditorText.prototype, "autofocus", void 0);
4894
+ __decorate([query("[data-rozie-ref=\"inputEl\"]")], EditorText.prototype, "_refInputEl", void 0);
4858
4895
  EditorText = __decorate([customElement("rozie-editor-text")], EditorText);
4859
4896
  var EditorText_default = EditorText;
4860
4897
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rozie-ui/data-table-lit",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "license": "MIT",
@@ -45,7 +45,7 @@
45
45
  "src"
46
46
  ],
47
47
  "dependencies": {
48
- "@rozie/runtime-lit": "0.1.3"
48
+ "@rozie/runtime-lit": "0.1.4"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "lit": "^3.2",
package/src/DataTable.ts CHANGED
@@ -87,6 +87,7 @@ interface RozieEditorSlotCtx {
87
87
  value: unknown;
88
88
  commit: unknown;
89
89
  cancel: unknown;
90
+ autofocus: unknown;
90
91
  }
91
92
 
92
93
  interface RozieDetailSlotCtx {
@@ -605,6 +606,7 @@ export default class DataTable extends SignalWatcher(LitElement) {
605
606
  private _draftValue = signal<any>(null);
606
607
  private _invalidMsg = signal('');
607
608
  private _editVer = signal(0);
609
+ private _editFocusColId = signal<any>(null);
608
610
  private _editingRowIndex = signal<any>(null);
609
611
  private _rowDraft = signal<any>({});
610
612
  private _rangeAnchor = signal<any>(null);
@@ -656,7 +658,7 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
656
658
  @property({ attribute: false }) cell?: (scope: { columnId: unknown; column: unknown; row: unknown; value: unknown }) => unknown;
657
659
  @state() private _hasSlotEditor = false;
658
660
  @queryAssignedElements({ slot: 'editor', flatten: true }) private _slotEditorElements!: Element[];
659
- @property({ attribute: false }) editor?: (scope: { columnId: unknown; column: unknown; row: unknown; value: unknown; commit: unknown; cancel: unknown }) => unknown;
661
+ @property({ attribute: false }) editor?: (scope: { columnId: unknown; column: unknown; row: unknown; value: unknown; commit: unknown; cancel: unknown; autofocus: unknown }) => unknown;
660
662
  @state() private _hasSlotDetail = false;
661
663
  @queryAssignedElements({ slot: 'detail', flatten: true }) private _slotDetailElements!: Element[];
662
664
  @property({ attribute: false }) detail?: (scope: { row: unknown }) => unknown;
@@ -1229,7 +1231,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
1229
1231
  <span class="rdt-group-count" data-rozie-s-d5dcab4c>${rozieDisplay('(' + this.groupSubRowCount(wr.row) + ')')}</span>
1230
1232
  </span>` : this.isEditing(wr.vi.index, this.colIndexOf(wr.row, cell)) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
1231
1233
  ${this.hasEditorSlot(cell.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
1232
- ${this.editor !== undefined ? this.editor({columnId: cell.column.id, column: cell.column, row: wr.row.original, value: this.editorValueFor(cell.column.id), commit: this.editorCommitFor(cell.column.id), cancel: this.editorCancelFor()}) : html`<slot name="editor" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: wr.row.original, value: this.editorValueFor(cell.column.id), commit: this.editorCommitFor(cell.column.id), cancel: this.editorCancelFor()}); } catch { return '{}'; } })()}></slot>`}
1234
+ ${this.editor !== undefined ? this.editor({columnId: cell.column.id, column: cell.column, row: wr.row.original, value: this.editorValueFor(cell.column.id), commit: this.editorCommitFor(cell.column.id), cancel: this.editorCancelFor(), autofocus: this.editorAutofocusFor(cell.column.id, wr.vi.index)}) : html`<slot name="editor" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: wr.row.original, value: this.editorValueFor(cell.column.id), commit: this.editorCommitFor(cell.column.id), cancel: this.editorCancelFor(), autofocus: this.editorAutofocusFor(cell.column.id, wr.vi.index)}); } catch { return '{}'; } })()}></slot>`}
1233
1235
  </span>` : this.editorTypeOf(cell.column.id) === 'number' ? html`<input class="rdt-cell-editor" type="number" data-editing-cell="" .value=${this.editorValueFor(cell.column.id)} @input=${($event: InputEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onCellEditorInput(cell.column.id, $event); }} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorKeyDown($event); }} @blur=${($event: FocusEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorBlur($event); }} data-rozie-s-d5dcab4c />` : this.editorTypeOf(cell.column.id) === 'select' ? html`<select class="rdt-cell-editor" data-editing-cell="" .value=${this.editorValueFor(cell.column.id)} @change=${($event: Event & { currentTarget: HTMLSelectElement; target: HTMLSelectElement }) => { this.onCellEditorInput(cell.column.id, $event); }} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLSelectElement; target: HTMLSelectElement }) => { this.onEditorKeyDown($event); }} @blur=${($event: FocusEvent & { currentTarget: HTMLSelectElement; target: HTMLSelectElement }) => { this.onEditorBlur($event); }} data-rozie-s-d5dcab4c>
1234
1236
  ${repeat<any>(this.editorOptionsOf(cell.column.id), (opt, _idx) => opt.value, (opt, _idx) => html`<option key=${rozieAttr(opt.value)} value=${rozieAttr(opt.value)} data-rozie-s-d5dcab4c>${rozieDisplay(opt.label)}</option>`)}
1235
1237
  </select>` : this.editorTypeOf(cell.column.id) === 'checkbox' ? html`<input class="rdt-cell-editor" type="checkbox" data-editing-cell="" ?checked=${this.editorCheckedFor(cell.column.id)} @change=${($event: Event & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onCellEditorCheckbox(cell.column.id, $event); }} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorKeyDown($event); }} @blur=${($event: FocusEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorBlur($event); }} data-rozie-s-d5dcab4c />` : html`<input class="rdt-cell-editor" type="text" data-editing-cell="" .value=${this.editorValueFor(cell.column.id)} @input=${($event: InputEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onCellEditorInput(cell.column.id, $event); }} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorKeyDown($event); }} @blur=${($event: FocusEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorBlur($event); }} data-rozie-s-d5dcab4c />`}</span>` : this.cellIsPlaceholder(cell) ? html`<span style="display:contents" data-rozie-s-d5dcab4c></span>` : html`<span class="rdt-cell-value" data-rozie-s-d5dcab4c>
@@ -1309,7 +1311,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
1309
1311
  <span class="rdt-group-count" data-rozie-s-d5dcab4c>${rozieDisplay('(' + this.groupSubRowCount(row) + ')')}</span>
1310
1312
  </span>` : this.isEditing(this.rowIndexOf(row), this.colIndexOf(row, cell)) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
1311
1313
  ${this.hasEditorSlot(cell.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
1312
- ${this.editor !== undefined ? this.editor({columnId: cell.column.id, column: cell.column, row: row.original, value: this.editorValueFor(cell.column.id), commit: this.editorCommitFor(cell.column.id), cancel: this.editorCancelFor()}) : html`<slot name="editor" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: row.original, value: this.editorValueFor(cell.column.id), commit: this.editorCommitFor(cell.column.id), cancel: this.editorCancelFor()}); } catch { return '{}'; } })()}></slot>`}
1314
+ ${this.editor !== undefined ? this.editor({columnId: cell.column.id, column: cell.column, row: row.original, value: this.editorValueFor(cell.column.id), commit: this.editorCommitFor(cell.column.id), cancel: this.editorCancelFor(), autofocus: this.editorAutofocusFor(cell.column.id, this.rowIndexOf(row))}) : html`<slot name="editor" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: row.original, value: this.editorValueFor(cell.column.id), commit: this.editorCommitFor(cell.column.id), cancel: this.editorCancelFor(), autofocus: this.editorAutofocusFor(cell.column.id, this.rowIndexOf(row))}); } catch { return '{}'; } })()}></slot>`}
1313
1315
  </span>` : this.editorTypeOf(cell.column.id) === 'number' ? html`<input class="rdt-cell-editor" type="number" data-editing-cell="" .value=${this.editorValueFor(cell.column.id)} @input=${($event: InputEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onCellEditorInput(cell.column.id, $event); }} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorKeyDown($event); }} @blur=${($event: FocusEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorBlur($event); }} data-rozie-s-d5dcab4c />` : this.editorTypeOf(cell.column.id) === 'select' ? html`<select class="rdt-cell-editor" data-editing-cell="" .value=${this.editorValueFor(cell.column.id)} @change=${($event: Event & { currentTarget: HTMLSelectElement; target: HTMLSelectElement }) => { this.onCellEditorInput(cell.column.id, $event); }} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLSelectElement; target: HTMLSelectElement }) => { this.onEditorKeyDown($event); }} @blur=${($event: FocusEvent & { currentTarget: HTMLSelectElement; target: HTMLSelectElement }) => { this.onEditorBlur($event); }} data-rozie-s-d5dcab4c>
1314
1316
  ${repeat<any>(this.editorOptionsOf(cell.column.id), (opt, _idx) => opt.value, (opt, _idx) => html`<option key=${rozieAttr(opt.value)} value=${rozieAttr(opt.value)} data-rozie-s-d5dcab4c>${rozieDisplay(opt.label)}</option>`)}
1315
1317
  </select>` : this.editorTypeOf(cell.column.id) === 'checkbox' ? html`<input class="rdt-cell-editor" type="checkbox" data-editing-cell="" ?checked=${this.editorCheckedFor(cell.column.id)} @change=${($event: Event & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onCellEditorCheckbox(cell.column.id, $event); }} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorKeyDown($event); }} @blur=${($event: FocusEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorBlur($event); }} data-rozie-s-d5dcab4c />` : html`<input class="rdt-cell-editor" type="text" data-editing-cell="" .value=${this.editorValueFor(cell.column.id)} @input=${($event: InputEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onCellEditorInput(cell.column.id, $event); }} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorKeyDown($event); }} @blur=${($event: FocusEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onEditorBlur($event); }} data-rozie-s-d5dcab4c />`}</span>` : this.cellIsPlaceholder(cell) ? html`<span style="display:contents" data-rozie-s-d5dcab4c></span>` : html`<span class="rdt-cell-value" data-rozie-s-d5dcab4c>
@@ -4507,6 +4509,9 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4507
4509
 
4508
4510
  focusEditorWhenReady = (selectAll = true) => {
4509
4511
  if (!this.gridRoot) return;
4512
+ // Editor-owns-focus contract: when the CURRENT focus target is a #editor drop-in, the host
4513
+ // does NOT reach into its DOM — the drop-in self-focuses via its own autofocus prop.
4514
+ if (this._editFocusColId.value != null && this.hasEditorSlot(this._editFocusColId.value)) return;
4510
4515
  let attempts = 0;
4511
4516
  const tryFocus = () => {
4512
4517
  const el = this.gridRoot ? this.gridRoot.querySelector('[data-editing-cell]') : null;
@@ -4575,6 +4580,10 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4575
4580
  this._draftValue.value = seed != null ? seed : this.cellValueAt(rowIndex, colIndex);
4576
4581
  this._activeInControl.value = true;
4577
4582
  this._editVer.value = this._editVer.value + 1;
4583
+ // Editor-owns-focus contract (quick 260711-i5m): THIS cell's column is the current
4584
+ // focus target — editorAutofocusFor derives the reactive `autofocus` #editor scope prop
4585
+ // from it. Cleared on endEdit.
4586
+ this._editFocusColId.value = colId;
4578
4587
  // B2: a seeded (type-to-edit) entry must NOT select-all — keep the caret after the
4579
4588
  // seeded char so subsequent typing appends instead of replacing it.
4580
4589
  this.focusEditorWhenReady(seed == null);
@@ -4614,6 +4623,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4614
4623
  this._invalidMsg.value = '';
4615
4624
  this._activeInControl.value = false;
4616
4625
  this._editVer.value = this._editVer.value + 1;
4626
+ this._editFocusColId.value = null;
4617
4627
  };
4618
4628
 
4619
4629
  endRowEdit = () => {
@@ -4622,6 +4632,17 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4622
4632
  this._invalidMsg.value = '';
4623
4633
  this._activeInControl.value = false;
4624
4634
  this._editVer.value = this._editVer.value + 1;
4635
+ this._editFocusColId.value = null;
4636
+ };
4637
+
4638
+ editorAutofocusFor = (colId: any, rowIndex: any) => {
4639
+ if (this._editVer.value < 0) return false;
4640
+ if (this._editingRowIndex.value != null) {
4641
+ if (this._editingRowIndex.value !== rowIndex) return false;
4642
+ } else {
4643
+ if (this._editingRow.value !== rowIndex) return false;
4644
+ }
4645
+ return this._editFocusColId.value != null && this._editFocusColId.value === colId;
4625
4646
  };
4626
4647
 
4627
4648
  coerceCellValue = (colId: any, raw: any) => {
@@ -4811,6 +4832,8 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4811
4832
 
4812
4833
  focusRowEditorAt = (rowIndex: any, colIndex: any) => {
4813
4834
  if (!this.gridRoot) return;
4835
+ const colId = this.columnIdAt(rowIndex, colIndex);
4836
+ if (colId != null && this.hasEditorSlot(colId)) return;
4814
4837
  let attempts = 0;
4815
4838
  const tryFocus = () => {
4816
4839
  const cellEl = this.resolveCellEl(String(rowIndex), colIndex);
@@ -4856,6 +4879,11 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4856
4879
  this._editingRowIndex.value = rowIndex;
4857
4880
  this._activeInControl.value = true;
4858
4881
  this._editVer.value = this._editVer.value + 1;
4882
+ // Editor-owns-focus contract (quick 260711-i5m): the row's FIRST editable column is the
4883
+ // initial focus target — editorAutofocusFor derives the reactive `autofocus` #editor scope
4884
+ // prop from it (a built-in column is also host-focused below via focusEditorWhenReady; a
4885
+ // drop-in column self-focuses via its own $onMount, gated off the host reach-in in Task 3).
4886
+ this._editFocusColId.value = editable[0].colId;
4859
4887
  this.focusEditorWhenReady();
4860
4888
  };
4861
4889
 
@@ -4883,9 +4911,18 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
4883
4911
  const err = this.runValidator(ec.colId, this.coerceCellValue(ec.colId, draft[ec.colId]), rowOriginal);
4884
4912
  if (err !== true) {
4885
4913
  this.setInvalid(err);
4914
+ // Editor-owns-focus contract (quick 260711-i5m): the OFFENDING column becomes the new
4915
+ // reactive focus target BEFORE the host-focus call below — a #editor drop-in already
4916
+ // mounted (full-row edit opens every editable cell at once) picks this up via its own
4917
+ // lazy $watch on the `autofocus` scope prop flipping false→true. Bump editVer so the
4918
+ // coarse-render targets (React/Vue/Angular/Svelte) re-derive the slot binding (Solid's
4919
+ // fine-grained accessor re-runs without the bump, but the bump keeps all 6 in lockstep).
4920
+ this._editFocusColId.value = ec.colId;
4921
+ this._editVer.value = this._editVer.value + 1;
4886
4922
  // B22: focus the OFFENDING column's editor (the one whose validator rejected), NOT
4887
4923
  // unconditionally the first editor (focusEditorWhenReady resolves the first
4888
4924
  // [data-editing-cell] in DOM order). ec.colIndex is the offending cell's visible col.
4925
+ // Gated (Task 3) so a #editor drop-in self-focuses instead of a host DOM reach-in.
4889
4926
  this.focusRowEditorAt(rowIndex, ec.colIndex);
4890
4927
  return false;
4891
4928
  }
@@ -5108,6 +5145,11 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
5108
5145
  if (pos < 0) pos = 0;
5109
5146
  const len = cols.length;
5110
5147
  const nextPos = backward ? (pos - 1 + len) % len : (pos + 1) % len;
5148
+ // Editor-owns-focus contract (quick 260711-i5m): the Tab target becomes the new reactive
5149
+ // focus target BEFORE the host-focus call below, so Tab onto an already-mounted #editor
5150
+ // drop-in (row mode) also refocuses it via its own lazy $watch.
5151
+ this._editFocusColId.value = editable[nextPos].colId;
5152
+ this._editVer.value = this._editVer.value + 1;
5111
5153
  this.focusRowEditorAt(rowIndex, cols[nextPos]);
5112
5154
  };
5113
5155
 
package/src/EditorText.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { LitElement, css, html } from 'lit';
2
- import { customElement, property } from 'lit/decorators.js';
2
+ import { customElement, property, query } from 'lit/decorators.js';
3
3
  import { SignalWatcher, signal } from '@lit-labs/preact-signals';
4
4
 
5
5
  @customElement('rozie-editor-text')
@@ -32,7 +32,13 @@ export default class EditorText extends SignalWatcher(LitElement) {
32
32
  * `() => void` — revert the edit and close the editor (from the `#editor` slot scope). Null-guarded at call sites.
33
33
  */
34
34
  @property({ type: Function }) cancel: ((...args: unknown[]) => unknown) | null = null;
35
+ /**
36
+ * Focus this editor's primary input when true — the host sets it for the one editor that should hold focus; reactive.
37
+ */
38
+ @property({ type: Boolean, reflect: true }) autofocus: boolean = false;
35
39
  private _draft = signal('');
40
+ @query('[data-rozie-ref="inputEl"]') private _refInputEl!: HTMLElement;
41
+ private __rozieFirstUpdateDone = false;
36
42
 
37
43
  private _disconnectCleanups: Array<() => void> = [];
38
44
  // Re-parenting guard: set true once the deferred teardown has actually
@@ -46,6 +52,15 @@ export default class EditorText extends SignalWatcher(LitElement) {
46
52
 
47
53
  // Untyped handler param neutralizes to `any`, so reading e.target.value typechecks
48
54
  // ×6 (the global-filter idiom). Never inline `$data.x = $event.target.value`.
55
+
56
+ if (this.autofocus) this._refInputEl?.focus();
57
+ }
58
+
59
+ updated(changedProperties: Map<string, unknown>): void {
60
+ if (this.__rozieFirstUpdateDone && (changedProperties.has('autofocus'))) { const __watchVal = (() => this.autofocus)(); ((v: any) => {
61
+ if (v) this._refInputEl?.focus();
62
+ })(__watchVal); }
63
+ this.__rozieFirstUpdateDone = true;
49
64
  }
50
65
 
51
66
  disconnectedCallback(): void {
@@ -60,7 +75,7 @@ export default class EditorText extends SignalWatcher(LitElement) {
60
75
 
61
76
  render() {
62
77
  return html`
63
- <input class="rdt-cell-editor" type="text" data-editing-cell="" aria-label=${this.columnId} .value=${this._draft.value} @input=${($event: InputEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onInput($event); }} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onKeydown($event); }} @blur=${($event: FocusEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onBlur(); }} data-rozie-s-0d17f43a />
78
+ <input class="rdt-cell-editor" type="text" data-editing-cell="" aria-label=${this.columnId} .value=${this._draft.value} @input=${($event: InputEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onInput($event); }} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onKeydown($event); }} @blur=${($event: FocusEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onBlur(); }} data-rozie-ref="inputEl" data-rozie-s-0d17f43a />
64
79
  `;
65
80
  }
66
81