@rozie-ui/data-table-lit 0.3.1 → 0.4.0
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 +48 -2
- package/dist/index.cjs +541 -146
- package/dist/index.d.cts +66 -18
- package/dist/index.d.mts +66 -18
- package/dist/index.mjs +541 -146
- package/package.json +2 -2
- package/src/DataTable.ts +511 -141
- package/src/helpers/columnDefUtils.ts +77 -1
package/src/DataTable.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { RozieSlotDistributor, createLitControllableProperty, rozieAttr, rozieDi
|
|
|
5
5
|
import { ContextProvider, createContext } from '@lit/context';
|
|
6
6
|
import { repeat } from 'lit/directives/repeat.js';
|
|
7
7
|
import '@rozie-ui/popover-lit';
|
|
8
|
-
import { isSafeKey, wrapAggregationFn } from './helpers/columnDefUtils';
|
|
8
|
+
import { isSafeKey, wrapAggregationFn, indexDefsById, collectGroupableLeafDefs } from './helpers/columnDefUtils';
|
|
9
9
|
import { applyUpdater, clamp, focusables } from './helpers/indexMath';
|
|
10
10
|
import { escapeTsvField, parseTsv, tileGridToBox, tileIndex } from './helpers/tsvGrid';
|
|
11
11
|
import { replaceRowValue, indexOfRowIn, replaceRowValues } from './helpers/rowValueUtils';
|
|
@@ -52,13 +52,13 @@ interface RozieSelectAllSlotCtx {
|
|
|
52
52
|
toggle: any;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
interface
|
|
55
|
+
interface RozieDynamicColHeaderSlotCtx {
|
|
56
56
|
columnId: any;
|
|
57
57
|
column: any;
|
|
58
58
|
label: any;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
interface
|
|
61
|
+
interface RozieDynamicFilterSlotCtx {
|
|
62
62
|
columnId: any;
|
|
63
63
|
value: any;
|
|
64
64
|
uniqueValues: any;
|
|
@@ -72,14 +72,14 @@ interface RozieSelectCellSlotCtx {
|
|
|
72
72
|
toggle: any;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
interface
|
|
75
|
+
interface RozieDynamicCellSlotCtx {
|
|
76
76
|
columnId: any;
|
|
77
77
|
column: any;
|
|
78
78
|
row: any;
|
|
79
79
|
value: any;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
interface
|
|
82
|
+
interface RozieDynamicEditorSlotCtx {
|
|
83
83
|
columnId: any;
|
|
84
84
|
column: any;
|
|
85
85
|
row: any;
|
|
@@ -93,6 +93,37 @@ interface RozieDetailSlotCtx {
|
|
|
93
93
|
row: any;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
interface RozieColHeaderSlotCtx {
|
|
97
|
+
columnId: any;
|
|
98
|
+
column: any;
|
|
99
|
+
label: any;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
interface RozieFilterSlotCtx {
|
|
103
|
+
columnId: any;
|
|
104
|
+
value: any;
|
|
105
|
+
uniqueValues: any;
|
|
106
|
+
minMax: any;
|
|
107
|
+
setFilter: any;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface RozieCellSlotCtx {
|
|
111
|
+
columnId: any;
|
|
112
|
+
column: any;
|
|
113
|
+
row: any;
|
|
114
|
+
value: any;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface RozieEditorSlotCtx {
|
|
118
|
+
columnId: any;
|
|
119
|
+
column: any;
|
|
120
|
+
row: any;
|
|
121
|
+
value: any;
|
|
122
|
+
commit: any;
|
|
123
|
+
cancel: any;
|
|
124
|
+
autofocus: any;
|
|
125
|
+
}
|
|
126
|
+
|
|
96
127
|
@customElement('rozie-data-table')
|
|
97
128
|
export default class DataTable extends SignalWatcher(LitElement) {
|
|
98
129
|
static shadowRootOptions: ShadowRootInit = { ...LitElement.shadowRootOptions, slotAssignment: 'manual' };
|
|
@@ -658,24 +689,32 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
|
|
|
658
689
|
@state() private _hasSlotSelectAll = false;
|
|
659
690
|
@queryAssignedElements({ slot: 'selectAll', flatten: true }) private _slotSelectAllElements!: Element[];
|
|
660
691
|
@property({ attribute: false }) selectAll?: (scope: { checked: any; indeterminate: any; toggle: any }) => unknown;
|
|
692
|
+
@state() private _hasSlotDynamicColHeader = false;
|
|
693
|
+
@queryAssignedElements({ flatten: true }) private _slotDynamicColHeaderElements!: Element[];
|
|
694
|
+
@state() private _hasSlotDynamicFilter = false;
|
|
695
|
+
@queryAssignedElements({ flatten: true }) private _slotDynamicFilterElements!: Element[];
|
|
696
|
+
@state() private _hasSlotSelectCell = false;
|
|
697
|
+
@queryAssignedElements({ slot: 'selectCell', flatten: true }) private _slotSelectCellElements!: Element[];
|
|
698
|
+
@property({ attribute: false }) selectCell?: (scope: { row: any; checked: any; toggle: any }) => unknown;
|
|
699
|
+
@state() private _hasSlotDynamicCell = false;
|
|
700
|
+
@queryAssignedElements({ flatten: true }) private _slotDynamicCellElements!: Element[];
|
|
701
|
+
@state() private _hasSlotDynamicEditor = false;
|
|
702
|
+
@queryAssignedElements({ flatten: true }) private _slotDynamicEditorElements!: Element[];
|
|
703
|
+
@state() private _hasSlotDetail = false;
|
|
704
|
+
@queryAssignedElements({ slot: 'detail', flatten: true }) private _slotDetailElements!: Element[];
|
|
705
|
+
@property({ attribute: false }) detail?: (scope: { row: any }) => unknown;
|
|
661
706
|
@state() private _hasSlotColHeader = false;
|
|
662
707
|
@queryAssignedElements({ slot: 'colHeader', flatten: true }) private _slotColHeaderElements!: Element[];
|
|
663
708
|
@property({ attribute: false }) colHeader?: (scope: { columnId: any; column: any; label: any }) => unknown;
|
|
664
709
|
@state() private _hasSlotFilter = false;
|
|
665
710
|
@queryAssignedElements({ slot: 'filter', flatten: true }) private _slotFilterElements!: Element[];
|
|
666
711
|
@property({ attribute: false }) filter?: (scope: { columnId: any; value: any; uniqueValues: any; minMax: any; setFilter: any }) => unknown;
|
|
667
|
-
@state() private _hasSlotSelectCell = false;
|
|
668
|
-
@queryAssignedElements({ slot: 'selectCell', flatten: true }) private _slotSelectCellElements!: Element[];
|
|
669
|
-
@property({ attribute: false }) selectCell?: (scope: { row: any; checked: any; toggle: any }) => unknown;
|
|
670
712
|
@state() private _hasSlotCell = false;
|
|
671
713
|
@queryAssignedElements({ slot: 'cell', flatten: true }) private _slotCellElements!: Element[];
|
|
672
714
|
@property({ attribute: false }) cell?: (scope: { columnId: any; column: any; row: any; value: any }) => unknown;
|
|
673
715
|
@state() private _hasSlotEditor = false;
|
|
674
716
|
@queryAssignedElements({ slot: 'editor', flatten: true }) private _slotEditorElements!: Element[];
|
|
675
717
|
@property({ attribute: false }) editor?: (scope: { columnId: any; column: any; row: any; value: any; commit: any; cancel: any; autofocus: any }) => unknown;
|
|
676
|
-
@state() private _hasSlotDetail = false;
|
|
677
|
-
@queryAssignedElements({ slot: 'detail', flatten: true }) private _slotDetailElements!: Element[];
|
|
678
|
-
@property({ attribute: false }) detail?: (scope: { row: any }) => unknown;
|
|
679
718
|
// Phase 79 Plan 08 (R4) contract for 79-09: the record intake for
|
|
680
719
|
// record-routed slot fills. 79-09's consumer-side emitSlotFiller
|
|
681
720
|
// accumulates an object literal onto the SAME `.rozieSlots=${{ ... }}`
|
|
@@ -685,7 +724,7 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
|
|
|
685
724
|
// named function-prop / <slot> fallback (AC-9). Attribute
|
|
686
725
|
// deserialization is disabled — this is a function-valued record,
|
|
687
726
|
// never reflected to/from an HTML attribute.
|
|
688
|
-
@property({ attribute: false }) rozieSlots?: Record<string, (scope: any) => unknown>;
|
|
727
|
+
@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; 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; autofocus: any }) => unknown; } & Record<string, (scope: any) => unknown>;
|
|
689
728
|
|
|
690
729
|
private _disconnectCleanups: Array<() => void> = [];
|
|
691
730
|
// Re-parenting guard: set true once the deferred teardown has actually
|
|
@@ -727,9 +766,9 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
|
|
|
727
766
|
}
|
|
728
767
|
|
|
729
768
|
{
|
|
730
|
-
const slotEl = this.shadowRoot?.querySelector('slot[name
|
|
769
|
+
const slotEl = this.shadowRoot?.querySelector('slot:not([name])');
|
|
731
770
|
if (slotEl !== null && slotEl !== undefined) {
|
|
732
|
-
const update = () => { this.
|
|
771
|
+
const update = () => { this._hasSlotDynamicColHeader = this._slotDynamicColHeaderElements.length > 0; };
|
|
733
772
|
slotEl.addEventListener('slotchange', update);
|
|
734
773
|
// CR-05 fix: push cleanup so the listener is removed on disconnectedCallback.
|
|
735
774
|
this._disconnectCleanups.push(() => slotEl.removeEventListener('slotchange', update));
|
|
@@ -738,9 +777,9 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
|
|
|
738
777
|
}
|
|
739
778
|
|
|
740
779
|
{
|
|
741
|
-
const slotEl = this.shadowRoot?.querySelector('slot[name
|
|
780
|
+
const slotEl = this.shadowRoot?.querySelector('slot:not([name])');
|
|
742
781
|
if (slotEl !== null && slotEl !== undefined) {
|
|
743
|
-
const update = () => { this.
|
|
782
|
+
const update = () => { this._hasSlotDynamicFilter = this._slotDynamicFilterElements.length > 0; };
|
|
744
783
|
slotEl.addEventListener('slotchange', update);
|
|
745
784
|
// CR-05 fix: push cleanup so the listener is removed on disconnectedCallback.
|
|
746
785
|
this._disconnectCleanups.push(() => slotEl.removeEventListener('slotchange', update));
|
|
@@ -760,9 +799,9 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
|
|
|
760
799
|
}
|
|
761
800
|
|
|
762
801
|
{
|
|
763
|
-
const slotEl = this.shadowRoot?.querySelector('slot[name
|
|
802
|
+
const slotEl = this.shadowRoot?.querySelector('slot:not([name])');
|
|
764
803
|
if (slotEl !== null && slotEl !== undefined) {
|
|
765
|
-
const update = () => { this.
|
|
804
|
+
const update = () => { this._hasSlotDynamicCell = this._slotDynamicCellElements.length > 0; };
|
|
766
805
|
slotEl.addEventListener('slotchange', update);
|
|
767
806
|
// CR-05 fix: push cleanup so the listener is removed on disconnectedCallback.
|
|
768
807
|
this._disconnectCleanups.push(() => slotEl.removeEventListener('slotchange', update));
|
|
@@ -771,9 +810,9 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
|
|
|
771
810
|
}
|
|
772
811
|
|
|
773
812
|
{
|
|
774
|
-
const slotEl = this.shadowRoot?.querySelector('slot[name
|
|
813
|
+
const slotEl = this.shadowRoot?.querySelector('slot:not([name])');
|
|
775
814
|
if (slotEl !== null && slotEl !== undefined) {
|
|
776
|
-
const update = () => { this.
|
|
815
|
+
const update = () => { this._hasSlotDynamicEditor = this._slotDynamicEditorElements.length > 0; };
|
|
777
816
|
slotEl.addEventListener('slotchange', update);
|
|
778
817
|
// CR-05 fix: push cleanup so the listener is removed on disconnectedCallback.
|
|
779
818
|
this._disconnectCleanups.push(() => slotEl.removeEventListener('slotchange', update));
|
|
@@ -791,6 +830,50 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
|
|
|
791
830
|
update();
|
|
792
831
|
}
|
|
793
832
|
}
|
|
833
|
+
|
|
834
|
+
{
|
|
835
|
+
const slotEl = this.shadowRoot?.querySelector('slot[name="colHeader"]');
|
|
836
|
+
if (slotEl !== null && slotEl !== undefined) {
|
|
837
|
+
const update = () => { this._hasSlotColHeader = this._slotColHeaderElements.length > 0; };
|
|
838
|
+
slotEl.addEventListener('slotchange', update);
|
|
839
|
+
// CR-05 fix: push cleanup so the listener is removed on disconnectedCallback.
|
|
840
|
+
this._disconnectCleanups.push(() => slotEl.removeEventListener('slotchange', update));
|
|
841
|
+
update();
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
{
|
|
846
|
+
const slotEl = this.shadowRoot?.querySelector('slot[name="filter"]');
|
|
847
|
+
if (slotEl !== null && slotEl !== undefined) {
|
|
848
|
+
const update = () => { this._hasSlotFilter = this._slotFilterElements.length > 0; };
|
|
849
|
+
slotEl.addEventListener('slotchange', update);
|
|
850
|
+
// CR-05 fix: push cleanup so the listener is removed on disconnectedCallback.
|
|
851
|
+
this._disconnectCleanups.push(() => slotEl.removeEventListener('slotchange', update));
|
|
852
|
+
update();
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
{
|
|
857
|
+
const slotEl = this.shadowRoot?.querySelector('slot[name="cell"]');
|
|
858
|
+
if (slotEl !== null && slotEl !== undefined) {
|
|
859
|
+
const update = () => { this._hasSlotCell = this._slotCellElements.length > 0; };
|
|
860
|
+
slotEl.addEventListener('slotchange', update);
|
|
861
|
+
// CR-05 fix: push cleanup so the listener is removed on disconnectedCallback.
|
|
862
|
+
this._disconnectCleanups.push(() => slotEl.removeEventListener('slotchange', update));
|
|
863
|
+
update();
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
{
|
|
868
|
+
const slotEl = this.shadowRoot?.querySelector('slot[name="editor"]');
|
|
869
|
+
if (slotEl !== null && slotEl !== undefined) {
|
|
870
|
+
const update = () => { this._hasSlotEditor = this._slotEditorElements.length > 0; };
|
|
871
|
+
slotEl.addEventListener('slotchange', update);
|
|
872
|
+
// CR-05 fix: push cleanup so the listener is removed on disconnectedCallback.
|
|
873
|
+
this._disconnectCleanups.push(() => slotEl.removeEventListener('slotchange', update));
|
|
874
|
+
update();
|
|
875
|
+
}
|
|
876
|
+
}
|
|
794
877
|
}
|
|
795
878
|
|
|
796
879
|
connectedCallback(): void {
|
|
@@ -798,12 +881,16 @@ private __rozieCtxProvider_data_table_columns = new ContextProvider(this, { cont
|
|
|
798
881
|
this._hasSlotDefault = Array.from(this.children).some((el) => !el.hasAttribute('slot') && (el.nodeType !== 3 || (el.textContent?.trim().length ?? 0) > 0));
|
|
799
882
|
this._hasSlotGroupBar = Array.from(this.children).some((el) => el.getAttribute('slot') === 'groupBar');
|
|
800
883
|
this._hasSlotSelectAll = Array.from(this.children).some((el) => el.getAttribute('slot') === 'selectAll');
|
|
884
|
+
this._hasSlotDynamicColHeader = Array.from(this.children).some((el) => !el.hasAttribute('slot') && (el.nodeType !== 3 || (el.textContent?.trim().length ?? 0) > 0));
|
|
885
|
+
this._hasSlotDynamicFilter = Array.from(this.children).some((el) => !el.hasAttribute('slot') && (el.nodeType !== 3 || (el.textContent?.trim().length ?? 0) > 0));
|
|
886
|
+
this._hasSlotSelectCell = Array.from(this.children).some((el) => el.getAttribute('slot') === 'selectCell');
|
|
887
|
+
this._hasSlotDynamicCell = Array.from(this.children).some((el) => !el.hasAttribute('slot') && (el.nodeType !== 3 || (el.textContent?.trim().length ?? 0) > 0));
|
|
888
|
+
this._hasSlotDynamicEditor = Array.from(this.children).some((el) => !el.hasAttribute('slot') && (el.nodeType !== 3 || (el.textContent?.trim().length ?? 0) > 0));
|
|
889
|
+
this._hasSlotDetail = Array.from(this.children).some((el) => el.getAttribute('slot') === 'detail');
|
|
801
890
|
this._hasSlotColHeader = Array.from(this.children).some((el) => el.getAttribute('slot') === 'colHeader');
|
|
802
891
|
this._hasSlotFilter = Array.from(this.children).some((el) => el.getAttribute('slot') === 'filter');
|
|
803
|
-
this._hasSlotSelectCell = Array.from(this.children).some((el) => el.getAttribute('slot') === 'selectCell');
|
|
804
892
|
this._hasSlotCell = Array.from(this.children).some((el) => el.getAttribute('slot') === 'cell');
|
|
805
893
|
this._hasSlotEditor = Array.from(this.children).some((el) => el.getAttribute('slot') === 'editor');
|
|
806
|
-
this._hasSlotDetail = Array.from(this.children).some((el) => el.getAttribute('slot') === 'detail');
|
|
807
894
|
super.connectedCallback();
|
|
808
895
|
if (this.hasUpdated && this._rozieTornDown) { this._rozieTornDown = false; this._armListeners(); }
|
|
809
896
|
}
|
|
@@ -1288,19 +1375,23 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
1288
1375
|
<thead class="rdt-thead" role="rowgroup" data-rozie-s-d5dcab4c>
|
|
1289
1376
|
${repeat<any>(this._headerGroups.value, (hg, hgLevel) => hg.id, (hg, hgLevel) => html`<tr class="rdt-tr" role="row" aria-rowindex=${rozieAttr(hgLevel + 1)} data-rozie-s-d5dcab4c>
|
|
1290
1377
|
|
|
1291
|
-
${this.colsWindowed() ? html`<th class="rdt-col-spacer" aria-hidden="true" style=${rozieStyle('width:' + this.colPadLeft() + 'px;padding:0;border:0')} data-rozie-s-d5dcab4c></th>` : nothing}${repeat<any>(this.windowedHeadersFor(hg, hgLevel), (wh, _idx) => wh.header.id, (wh, _idx) => html`<th class="${Object.entries({ "rdt-th": true, 'rdt-select-th': this.isSelectColumn(wh.header.column.id), 'rdt-expander-th': this.isExpanderColumn(wh.header.column.id), 'rdt-th-resizing': this.columnIsResizing(wh.header.column.id), 'rdt-cell-active': this.isActiveCell('__header', this.headerColIndexOf(hg, wh.header), hgLevel) }).filter(([, v]) => v).map(([k]) => k).join(' ')}" role="columnheader" data-col=${rozieAttr(wh.header.column.id)} data-grid-cell="" data-row="__header" data-header-level=${rozieAttr(hgLevel)} colspan=${rozieAttr(wh.span > 1 ? wh.span : null)} data-col-index=${rozieAttr(this.headerColIndexOf(hg, wh.header))} tabindex=${rozieAttr(this.cellTabindex('__header', this.headerColIndexOf(hg, wh.header), hgLevel))} aria-sort=${rozieAttr(this.ariaSortFor(wh.header.column.id))} style=${rozieStyle(this.thStyle(wh.header
|
|
1378
|
+
${this.colsWindowed() ? html`<th class="rdt-col-spacer" aria-hidden="true" style=${rozieStyle('width:' + this.colPadLeft() + 'px;padding:0;border:0')} data-rozie-s-d5dcab4c></th>` : nothing}${repeat<any>(this.windowedHeadersFor(hg, hgLevel), (wh, _idx) => wh.header.id, (wh, _idx) => html`<th class="${Object.entries({ "rdt-th": true, 'rdt-select-th': this.isSelectColumn(wh.header.column.id), 'rdt-expander-th': this.isExpanderColumn(wh.header.column.id), 'rdt-th-resizing': this.columnIsResizing(wh.header.column.id), 'rdt-cell-active': this.isActiveCell('__header', this.headerColIndexOf(hg, wh.header), hgLevel) }).filter(([, v]) => v).map(([k]) => k).join(' ')}" role="columnheader" data-col=${rozieAttr(wh.header.column.id)} data-grid-cell="" data-row="__header" data-header-level=${rozieAttr(hgLevel)} colspan=${rozieAttr(wh.span > 1 ? wh.span : null)} data-col-index=${rozieAttr(this.headerColIndexOf(hg, wh.header))} tabindex=${rozieAttr(this.cellTabindex('__header', this.headerColIndexOf(hg, wh.header), hgLevel))} aria-sort=${rozieAttr(this.ariaSortFor(wh.header.column.id))} style=${rozieStyle(this.thStyle(wh.header))} data-rozie-s-d5dcab4c>
|
|
1292
1379
|
${this.isSelectColumn(wh.header.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1293
1380
|
${this.selectAll !== undefined ? this.selectAll({checked: this.isAllRowsSelected(), indeterminate: this.isSomeRowsSelected(), toggle: this.onToggleAllRows}) : html`<slot name="selectAll" data-rozie-params=${(() => { try { return JSON.stringify({checked: this.isAllRowsSelected(), indeterminate: this.isSomeRowsSelected()}); } catch { return '{}'; } })()} @rozie-select-all-toggle=${($event: CustomEvent) => ((this.onToggleAllRows) as (...args: any[]) => any)($event.detail)}>
|
|
1294
1381
|
${this.selectionMode === 'multiple' ? html`<input class="rdt-select-all" type="checkbox" aria-label="Select all rows" ?checked=${this.isAllRowsSelected()} @change=${($event: Event & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onToggleAllRows($event); }} data-rozie-s-d5dcab4c />` : nothing}</slot>`}
|
|
1295
1382
|
</span>` : this.isExpanderColumn(wh.header.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c></span>` : html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1296
1383
|
${wh.header.column.getCanSort && wh.header.column.getCanSort() ? html`<button class="rdt-sort-btn" type="button" @click=${($event: MouseEvent & { currentTarget: HTMLButtonElement; target: HTMLButtonElement }) => { this.onHeaderSort(wh.header.column.id, $event); }} data-rozie-s-d5dcab4c>
|
|
1297
1384
|
<span class="rdt-header-label" data-rozie-s-d5dcab4c>
|
|
1298
|
-
${this.colHeader !== undefined ? this.colHeader({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}) : html`<slot name="colHeader" data-rozie-params=${(() => { try { return JSON.stringify({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}); } catch { return '{}'; } })()}
|
|
1385
|
+
${this.rozieSlots?.[`colHeader-${wh.header.column.id}`] !== undefined ? this.rozieSlots?.[`colHeader-${wh.header.column.id}`]!({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}) : html`<slot name="${`colHeader-${wh.header.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}); } catch { return '{}'; } })()}>
|
|
1386
|
+
${this.colHeader !== undefined ? this.colHeader({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}) : html`<slot name="colHeader" data-rozie-params=${(() => { try { return JSON.stringify({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}); } catch { return '{}'; } })()}>${rozieDisplay(this.headerLabel(wh.header.column.id))}</slot>`}
|
|
1387
|
+
</slot>`}
|
|
1299
1388
|
</span>
|
|
1300
1389
|
<span class="rdt-sort-ind" aria-hidden="true" data-rozie-s-d5dcab4c>${rozieDisplay(this.sortIndicator(wh.header.column.id))}</span>
|
|
1301
1390
|
</button>` : html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1302
1391
|
<span class="rdt-header-label" data-rozie-s-d5dcab4c>
|
|
1303
|
-
${this.colHeader !== undefined ? this.colHeader({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}) : html`<slot name="colHeader" data-rozie-params=${(() => { try { return JSON.stringify({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}); } catch { return '{}'; } })()}
|
|
1392
|
+
${this.rozieSlots?.[`colHeader-${wh.header.column.id}`] !== undefined ? this.rozieSlots?.[`colHeader-${wh.header.column.id}`]!({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}) : html`<slot name="${`colHeader-${wh.header.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}); } catch { return '{}'; } })()}>
|
|
1393
|
+
${this.colHeader !== undefined ? this.colHeader({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}) : html`<slot name="colHeader" data-rozie-params=${(() => { try { return JSON.stringify({columnId: wh.header.column.id, column: wh.header.column, label: this.headerLabel(wh.header.column.id)}); } catch { return '{}'; } })()}>${rozieDisplay(this.headerLabel(wh.header.column.id))}</slot>`}
|
|
1394
|
+
</slot>`}
|
|
1304
1395
|
</span>
|
|
1305
1396
|
</span>`}<rozie-popover trigger="click" placement="bottom-end" strategy="fixed" .offset=${4} data-rozie-s-d5dcab4c><button class="rdt-col-menu-trigger" type="button" aria-label=${rozieAttr('Column options for ' + this.headerLabel(wh.header.column.id))} data-rozie-s-d5dcab4c slot="anchor">⋯</button><div class="rdt-col-menu" role="menu" data-rozie-s-d5dcab4c>
|
|
1306
1397
|
<button class="rdt-col-menu-item" type="button" role="menuitem" aria-pressed=${this.columnPinSide(wh.header.column.id) === 'left'} @click=${($event: MouseEvent & { currentTarget: HTMLButtonElement; target: HTMLButtonElement }) => { this.onPinColumn(wh.header.column.id, 'left', $event); }} data-rozie-s-d5dcab4c>Pin left</button>
|
|
@@ -1317,8 +1408,12 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
1317
1408
|
${this.hasAnyFilterableColumn() ? html`<tr class="rdt-filter-row" data-rozie-s-d5dcab4c>
|
|
1318
1409
|
${this.colsWindowed() ? html`<th class="rdt-col-spacer" aria-hidden="true" style=${rozieStyle('width:' + this.colPadLeft() + 'px;padding:0;border:0')} data-rozie-s-d5dcab4c></th>` : nothing}${repeat<any>(this.windowedHeadersFor(this._headerGroups.value[this._headerGroups.value.length - 1], this._headerGroups.value.length - 1), (wh, _idx) => wh.header.id, (wh, _idx) => html`<th class="rdt-filter-cell" role="presentation" data-col=${rozieAttr(wh.header.column.id)} style=${rozieStyle(this.pinStyle(wh.header.column.id))} data-rozie-s-d5dcab4c>
|
|
1319
1410
|
${this.isSelectColumn(wh.header.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c></span>` : this.isExpanderColumn(wh.header.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c></span>` : html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1320
|
-
${this.columnIsFilterable(wh.header.column.id)
|
|
1321
|
-
${this.filter !== undefined ? this.filter({columnId: wh.header.column.id, value: this.columnFilterValue(wh.header.column.id), uniqueValues: this.getFacetedUniqueValues(wh.header.column.id), minMax: this.getFacetedMinMaxValues(wh.header.column.id), setFilter: this.setColumnFilter}) : html`<slot name="filter" data-rozie-params=${(() => { try { return JSON.stringify({columnId: wh.header.column.id, value: this.columnFilterValue(wh.header.column.id), uniqueValues: this.getFacetedUniqueValues(wh.header.column.id), minMax: this.getFacetedMinMaxValues(wh.header.column.id)}); } catch { return '{}'; } })()} @rozie-
|
|
1411
|
+
${this.columnIsFilterable(wh.header.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1412
|
+
${this.rozieSlots?.[`filter-${wh.header.column.id}`] !== undefined ? this.rozieSlots?.[`filter-${wh.header.column.id}`]!({columnId: wh.header.column.id, value: this.columnFilterValue(wh.header.column.id), uniqueValues: this.getFacetedUniqueValues(wh.header.column.id), minMax: this.getFacetedMinMaxValues(wh.header.column.id), setFilter: this.setColumnFilter}) : html`<slot name="${`filter-${wh.header.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: wh.header.column.id, value: this.columnFilterValue(wh.header.column.id), uniqueValues: this.getFacetedUniqueValues(wh.header.column.id), minMax: this.getFacetedMinMaxValues(wh.header.column.id)}); } catch { return '{}'; } })()} @rozie-default-set-filter=${($event: CustomEvent) => ((this.setColumnFilter) as (...args: any[]) => any)($event.detail)}>
|
|
1413
|
+
${this.filter !== undefined ? this.filter({columnId: wh.header.column.id, value: this.columnFilterValue(wh.header.column.id), uniqueValues: this.getFacetedUniqueValues(wh.header.column.id), minMax: this.getFacetedMinMaxValues(wh.header.column.id), setFilter: this.setColumnFilter}) : html`<slot name="filter" data-rozie-params=${(() => { try { return JSON.stringify({columnId: wh.header.column.id, value: this.columnFilterValue(wh.header.column.id), uniqueValues: this.getFacetedUniqueValues(wh.header.column.id), minMax: this.getFacetedMinMaxValues(wh.header.column.id)}); } catch { return '{}'; } })()} @rozie-filter-set-filter=${($event: CustomEvent) => ((this.setColumnFilter) as (...args: any[]) => any)($event.detail)}>
|
|
1414
|
+
<input class="rdt-col-filter" type="text" aria-label=${rozieAttr('Filter ' + this.headerLabel(wh.header.column.id))} .value=${this.columnFilterValue(wh.header.column.id)} @input=${($event: InputEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onColumnFilterInput(wh.header.column.id, $event); }} @click=${($event: MouseEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.stopEvent($event); }} data-rozie-s-d5dcab4c />
|
|
1415
|
+
</slot>`}
|
|
1416
|
+
</slot>`}
|
|
1322
1417
|
</span>` : nothing}</span>`}</th>`)}
|
|
1323
1418
|
${this.colsWindowed() ? html`<th class="rdt-col-spacer" aria-hidden="true" style=${rozieStyle('width:' + this.colPadRight() + 'px;padding:0;border:0')} data-rozie-s-d5dcab4c></th>` : nothing}</tr>` : nothing}</thead>
|
|
1324
1419
|
|
|
@@ -1335,22 +1430,30 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
1335
1430
|
|
|
1336
1431
|
${this.isExpanderColumn(cell.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1337
1432
|
${this.rowCanExpand(wr.row) ? html`<button class="rdt-expander" type="button" data-expander="" aria-expanded=${!!this.rowIsExpanded(wr.row)} aria-label=${rozieAttr(this.rowIsExpanded(wr.row) ? 'Collapse row' : 'Expand row')} @click=${($event: MouseEvent & { currentTarget: HTMLButtonElement; target: HTMLButtonElement }) => { this.onToggleExpand(wr.row, $event); }} data-rozie-s-d5dcab4c>${rozieDisplay(this.rowIsExpanded(wr.row) ? '▾' : '▸')}</button>` : nothing}</span>` : this.isSelectColumn(cell.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1338
|
-
${this.selectCell !== undefined ? this.selectCell({row: wr.row
|
|
1433
|
+
${this.selectCell !== undefined ? this.selectCell({row: this.cellSlotRow(wr.row), checked: this.rowIsSelected(wr.row), toggle: e => this.onToggleRow(wr.row, e)}) : html`<slot name="selectCell" data-rozie-params=${(() => { try { return JSON.stringify({row: this.cellSlotRow(wr.row), checked: this.rowIsSelected(wr.row)}); } catch { return '{}'; } })()} @rozie-select-cell-toggle=${($event: CustomEvent) => ((e => this.onToggleRow(wr.row, e)) as (...args: any[]) => any)($event.detail)}>
|
|
1339
1434
|
<input class="rdt-select-row" type="checkbox" aria-label="Select row" ?checked=${this.rowIsSelected(wr.row)} @change=${($event: Event & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onToggleRow(wr.row, $event); }} data-rozie-s-d5dcab4c />
|
|
1340
1435
|
</slot>`}
|
|
1341
1436
|
</span>` : this.cellIsGrouped(cell) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1342
1437
|
<button class="rdt-expander rdt-group-toggle" type="button" data-expander="" aria-expanded=${!!this.rowIsExpanded(wr.row)} aria-label=${rozieAttr(this.rowIsExpanded(wr.row) ? 'Collapse group' : 'Expand group')} @click=${($event: MouseEvent & { currentTarget: HTMLButtonElement; target: HTMLButtonElement }) => { this.onToggleExpand(wr.row, $event); }} data-rozie-s-d5dcab4c>${rozieDisplay(this.rowIsExpanded(wr.row) ? '▾' : '▸')}</button>
|
|
1343
1438
|
<span class="rdt-group-value" data-rozie-s-d5dcab4c>
|
|
1344
|
-
${this.cell !== undefined ? this.cell({columnId: cell.column.id, column: cell.column, row: wr.row
|
|
1439
|
+
${this.rozieSlots?.[`cell-${cell.column.id}`] !== undefined ? this.rozieSlots?.[`cell-${cell.column.id}`]!({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), value: cell.getValue()}) : html`<slot name="${`cell-${cell.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), value: cell.getValue()}); } catch { return '{}'; } })()}>
|
|
1440
|
+
${this.cell !== undefined ? this.cell({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), value: cell.getValue()}) : html`<slot name="cell" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), value: cell.getValue()}); } catch { return '{}'; } })()}>${rozieDisplay(cell.getValue())}</slot>`}
|
|
1441
|
+
</slot>`}
|
|
1345
1442
|
</span>
|
|
1346
1443
|
<span class="rdt-group-count" data-rozie-s-d5dcab4c>${rozieDisplay('(' + this.groupSubRowCount(wr.row) + ')')}</span>
|
|
1347
1444
|
</span>` : this.isEditing(wr.vi.index, this.colIndexOf(wr.row, cell)) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1348
|
-
${this.
|
|
1349
|
-
${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>`}
|
|
1350
|
-
</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>
|
|
1445
|
+
${this.editorTypeOf(cell.column.id) === 'number' ? html`<input class="rdt-cell-editor" type="number" data-editing-cell="" data-builtin-editor="" .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="" data-builtin-editor="" .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>
|
|
1351
1446
|
${repeat<any>(this.editorOptionsOf(cell.column.id), (opt, _idx) => opt.value, (opt, _idx) => html`<option value=${rozieAttr(opt.value)} data-rozie-s-d5dcab4c>${rozieDisplay(opt.label)}</option>`)}
|
|
1352
|
-
</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 />` :
|
|
1353
|
-
|
|
1447
|
+
</select>` : this.editorTypeOf(cell.column.id) === 'checkbox' ? html`<input class="rdt-cell-editor" type="checkbox" data-editing-cell="" data-builtin-editor="" ?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 />` : this.editorTypeOf(cell.column.id) === 'custom' ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1448
|
+
${this.rozieSlots?.[`editor-${cell.column.id}`] !== undefined ? this.rozieSlots?.[`editor-${cell.column.id}`]!({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), 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-${cell.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), 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 '{}'; } })()}>
|
|
1449
|
+
${this.editor !== undefined ? this.editor({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), 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: this.cellSlotRow(wr.row), 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 '{}'; } })()}>
|
|
1450
|
+
<input class="rdt-cell-editor" type="text" data-editing-cell="" data-builtin-editor="" .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 />
|
|
1451
|
+
</slot>`}
|
|
1452
|
+
</slot>`}
|
|
1453
|
+
</span>` : html`<input class="rdt-cell-editor" type="text" data-editing-cell="" data-builtin-editor="" .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>
|
|
1454
|
+
${this.rozieSlots?.[`cell-${cell.column.id}`] !== undefined ? this.rozieSlots?.[`cell-${cell.column.id}`]!({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), value: cell.getValue()}) : html`<slot name="${`cell-${cell.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), value: cell.getValue()}); } catch { return '{}'; } })()}>
|
|
1455
|
+
${this.cell !== undefined ? this.cell({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), value: cell.getValue()}) : html`<slot name="cell" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(wr.row), value: cell.getValue()}); } catch { return '{}'; } })()}>${rozieDisplay(cell.getValue())}</slot>`}
|
|
1456
|
+
</slot>`}
|
|
1354
1457
|
</span>`}${this.isFillHandleCell(wr.vi.index, this.colIndexOf(wr.row, cell)) ? html`<span class="rdt-fill-handle" data-fill-handle="" data-testid="fill-handle" aria-hidden="true" @pointerdown=${($event: PointerEvent & { currentTarget: HTMLSpanElement; target: HTMLSpanElement }) => { this.onFillHandlePointerDown($event); }} data-rozie-s-d5dcab4c></span>` : nothing}</td>`)}
|
|
1355
1458
|
|
|
1356
1459
|
${this.colsWindowed() ? html`<td class="rdt-col-spacer" aria-hidden="true" style=${rozieStyle('width:' + this.colPadRight() + 'px;padding:0;border:0')} data-rozie-s-d5dcab4c></td>` : nothing}</tr>
|
|
@@ -1369,7 +1472,7 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
1369
1472
|
</div>` : html`<table class="${Object.entries({ "rozie-data-table": true, 'rdt-sticky': this.stickyHeader }).filter(([, v]) => v).map(([k]) => k).join(' ')}" role=${rozieAttr(this.tableRole())} aria-rowcount=${rozieAttr(this.gridAriaRowCount())} @keydown=${($event: KeyboardEvent & { currentTarget: HTMLTableElement; target: HTMLTableElement }) => { this.onGridKeyDown($event); }} @focusin=${($event: Event & { currentTarget: HTMLTableElement; target: HTMLTableElement }) => { this.syncActiveFromEvent($event); }} @focusout=${($event: Event & { currentTarget: HTMLTableElement; target: HTMLTableElement }) => { this.onGridFocusOut($event); }} @mousedown=${($event: MouseEvent & { currentTarget: HTMLTableElement; target: HTMLTableElement }) => { this.onGridMouseDown($event); }} @dblclick=${($event: Event & { currentTarget: HTMLTableElement; target: HTMLTableElement }) => { this.onGridDblClick($event); }} @click=${($event: MouseEvent & { currentTarget: HTMLTableElement; target: HTMLTableElement }) => { this.onGridClick($event); }} data-rozie-s-d5dcab4c>
|
|
1370
1473
|
<thead class="rdt-thead" role="rowgroup" data-rozie-s-d5dcab4c>
|
|
1371
1474
|
${repeat<any>(this._headerGroups.value, (hg, hgLevel) => hg.id, (hg, hgLevel) => html`<tr class="rdt-tr" role="row" aria-rowindex=${rozieAttr(hgLevel + 1)} data-rozie-s-d5dcab4c>
|
|
1372
|
-
${repeat<any>(hg.headers, (header, _idx) => header.id, (header, _idx) => html`<th class="${Object.entries({ "rdt-th": true, 'rdt-select-th': this.isSelectColumn(header.column.id), 'rdt-expander-th': this.isExpanderColumn(header.column.id), 'rdt-th-resizing': this.columnIsResizing(header.column.id), 'rdt-cell-active': this.isActiveCell('__header', this.headerColIndexOf(hg, header), hgLevel) }).filter(([, v]) => v).map(([k]) => k).join(' ')}" role="columnheader" data-col=${rozieAttr(header.column.id)} data-grid-cell="" data-row="__header" data-header-level=${rozieAttr(hgLevel)} colspan=${rozieAttr(header.colSpan > 1 ? header.colSpan : null)} data-col-index=${rozieAttr(this.headerColIndexOf(hg, header))} tabindex=${rozieAttr(this.cellTabindex('__header', this.headerColIndexOf(hg, header), hgLevel))} aria-sort=${rozieAttr(this.ariaSortFor(header.column.id))} style=${rozieStyle(this.thStyle(header
|
|
1475
|
+
${repeat<any>(hg.headers, (header, _idx) => header.id, (header, _idx) => html`<th class="${Object.entries({ "rdt-th": true, 'rdt-select-th': this.isSelectColumn(header.column.id), 'rdt-expander-th': this.isExpanderColumn(header.column.id), 'rdt-th-resizing': this.columnIsResizing(header.column.id), 'rdt-cell-active': this.isActiveCell('__header', this.headerColIndexOf(hg, header), hgLevel) }).filter(([, v]) => v).map(([k]) => k).join(' ')}" role="columnheader" data-col=${rozieAttr(header.column.id)} data-grid-cell="" data-row="__header" data-header-level=${rozieAttr(hgLevel)} colspan=${rozieAttr(header.colSpan > 1 ? header.colSpan : null)} data-col-index=${rozieAttr(this.headerColIndexOf(hg, header))} tabindex=${rozieAttr(this.cellTabindex('__header', this.headerColIndexOf(hg, header), hgLevel))} aria-sort=${rozieAttr(this.ariaSortFor(header.column.id))} style=${rozieStyle(this.thStyle(header))} data-rozie-s-d5dcab4c>
|
|
1373
1476
|
|
|
1374
1477
|
|
|
1375
1478
|
${this.isSelectColumn(header.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
@@ -1381,12 +1484,16 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
1381
1484
|
${header.column.getCanSort && header.column.getCanSort() ? html`<button class="rdt-sort-btn" type="button" @click=${($event: MouseEvent & { currentTarget: HTMLButtonElement; target: HTMLButtonElement }) => { this.onHeaderSort(header.column.id, $event); }} data-rozie-s-d5dcab4c>
|
|
1382
1485
|
|
|
1383
1486
|
<span class="rdt-header-label" data-rozie-s-d5dcab4c>
|
|
1384
|
-
${this.colHeader !== undefined ? this.colHeader({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}) : html`<slot name="colHeader" data-rozie-params=${(() => { try { return JSON.stringify({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}); } catch { return '{}'; } })()}
|
|
1487
|
+
${this.rozieSlots?.[`colHeader-${header.column.id}`] !== undefined ? this.rozieSlots?.[`colHeader-${header.column.id}`]!({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}) : html`<slot name="${`colHeader-${header.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}); } catch { return '{}'; } })()}>
|
|
1488
|
+
${this.colHeader !== undefined ? this.colHeader({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}) : html`<slot name="colHeader" data-rozie-params=${(() => { try { return JSON.stringify({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}); } catch { return '{}'; } })()}>${rozieDisplay(this.headerLabel(header.column.id))}</slot>`}
|
|
1489
|
+
</slot>`}
|
|
1385
1490
|
</span>
|
|
1386
1491
|
<span class="rdt-sort-ind" aria-hidden="true" data-rozie-s-d5dcab4c>${rozieDisplay(this.sortIndicator(header.column.id))}</span>
|
|
1387
1492
|
</button>` : html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1388
1493
|
<span class="rdt-header-label" data-rozie-s-d5dcab4c>
|
|
1389
|
-
${this.colHeader !== undefined ? this.colHeader({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}) : html`<slot name="colHeader" data-rozie-params=${(() => { try { return JSON.stringify({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}); } catch { return '{}'; } })()}
|
|
1494
|
+
${this.rozieSlots?.[`colHeader-${header.column.id}`] !== undefined ? this.rozieSlots?.[`colHeader-${header.column.id}`]!({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}) : html`<slot name="${`colHeader-${header.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}); } catch { return '{}'; } })()}>
|
|
1495
|
+
${this.colHeader !== undefined ? this.colHeader({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}) : html`<slot name="colHeader" data-rozie-params=${(() => { try { return JSON.stringify({columnId: header.column.id, column: header.column, label: this.headerLabel(header.column.id)}); } catch { return '{}'; } })()}>${rozieDisplay(this.headerLabel(header.column.id))}</slot>`}
|
|
1496
|
+
</slot>`}
|
|
1390
1497
|
</span>
|
|
1391
1498
|
</span>`}<rozie-popover trigger="click" placement="bottom-end" strategy="fixed" .offset=${4} data-rozie-s-d5dcab4c><button class="rdt-col-menu-trigger" type="button" aria-label=${rozieAttr('Column options for ' + this.headerLabel(header.column.id))} data-rozie-s-d5dcab4c slot="anchor">⋯</button><div class="rdt-col-menu" role="menu" data-rozie-s-d5dcab4c>
|
|
1392
1499
|
<button class="rdt-col-menu-item" type="button" role="menuitem" aria-pressed=${this.columnPinSide(header.column.id) === 'left'} @click=${($event: MouseEvent & { currentTarget: HTMLButtonElement; target: HTMLButtonElement }) => { this.onPinColumn(header.column.id, 'left', $event); }} data-rozie-s-d5dcab4c>Pin left</button>
|
|
@@ -1403,8 +1510,12 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
1403
1510
|
${this.hasAnyFilterableColumn() ? html`<tr class="rdt-filter-row" data-rozie-s-d5dcab4c>
|
|
1404
1511
|
${repeat<any>(this._headerGroups.value[this._headerGroups.value.length - 1].headers, (header, _idx) => header.id, (header, _idx) => html`<th class="rdt-filter-cell" role="presentation" style=${rozieStyle(this.pinStyle(header.column.id))} data-rozie-s-d5dcab4c>
|
|
1405
1512
|
${this.isSelectColumn(header.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c></span>` : this.isExpanderColumn(header.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c></span>` : html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1406
|
-
${this.columnIsFilterable(header.column.id)
|
|
1407
|
-
${this.filter !== undefined ? this.filter({columnId: header.column.id, value: this.columnFilterValue(header.column.id), uniqueValues: this.getFacetedUniqueValues(header.column.id), minMax: this.getFacetedMinMaxValues(header.column.id), setFilter: this.setColumnFilter}) : html`<slot name="filter" data-rozie-params=${(() => { try { return JSON.stringify({columnId: header.column.id, value: this.columnFilterValue(header.column.id), uniqueValues: this.getFacetedUniqueValues(header.column.id), minMax: this.getFacetedMinMaxValues(header.column.id)}); } catch { return '{}'; } })()} @rozie-
|
|
1513
|
+
${this.columnIsFilterable(header.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1514
|
+
${this.rozieSlots?.[`filter-${header.column.id}`] !== undefined ? this.rozieSlots?.[`filter-${header.column.id}`]!({columnId: header.column.id, value: this.columnFilterValue(header.column.id), uniqueValues: this.getFacetedUniqueValues(header.column.id), minMax: this.getFacetedMinMaxValues(header.column.id), setFilter: this.setColumnFilter}) : html`<slot name="${`filter-${header.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: header.column.id, value: this.columnFilterValue(header.column.id), uniqueValues: this.getFacetedUniqueValues(header.column.id), minMax: this.getFacetedMinMaxValues(header.column.id)}); } catch { return '{}'; } })()} @rozie-default-set-filter=${($event: CustomEvent) => ((this.setColumnFilter) as (...args: any[]) => any)($event.detail)}>
|
|
1515
|
+
${this.filter !== undefined ? this.filter({columnId: header.column.id, value: this.columnFilterValue(header.column.id), uniqueValues: this.getFacetedUniqueValues(header.column.id), minMax: this.getFacetedMinMaxValues(header.column.id), setFilter: this.setColumnFilter}) : html`<slot name="filter" data-rozie-params=${(() => { try { return JSON.stringify({columnId: header.column.id, value: this.columnFilterValue(header.column.id), uniqueValues: this.getFacetedUniqueValues(header.column.id), minMax: this.getFacetedMinMaxValues(header.column.id)}); } catch { return '{}'; } })()} @rozie-filter-set-filter=${($event: CustomEvent) => ((this.setColumnFilter) as (...args: any[]) => any)($event.detail)}>
|
|
1516
|
+
<input class="rdt-col-filter" type="text" aria-label=${rozieAttr('Filter ' + this.headerLabel(header.column.id))} .value=${this.columnFilterValue(header.column.id)} @input=${($event: InputEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onColumnFilterInput(header.column.id, $event); }} @click=${($event: MouseEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.stopEvent($event); }} data-rozie-s-d5dcab4c />
|
|
1517
|
+
</slot>`}
|
|
1518
|
+
</slot>`}
|
|
1408
1519
|
</span>` : nothing}</span>`}</th>`)}
|
|
1409
1520
|
</tr>` : nothing}</thead>
|
|
1410
1521
|
|
|
@@ -1416,22 +1527,30 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
1416
1527
|
|
|
1417
1528
|
${this.isExpanderColumn(cell.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1418
1529
|
${this.rowCanExpand(row) ? html`<button class="rdt-expander" type="button" data-expander="" aria-expanded=${!!this.rowIsExpanded(row)} aria-label=${rozieAttr(this.rowIsExpanded(row) ? 'Collapse row' : 'Expand row')} @click=${($event: MouseEvent & { currentTarget: HTMLButtonElement; target: HTMLButtonElement }) => { this.onToggleExpand(row, $event); }} data-rozie-s-d5dcab4c>${rozieDisplay(this.rowIsExpanded(row) ? '▾' : '▸')}</button>` : nothing}</span>` : this.isSelectColumn(cell.column.id) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1419
|
-
${this.selectCell !== undefined ? this.selectCell({row: row
|
|
1530
|
+
${this.selectCell !== undefined ? this.selectCell({row: this.cellSlotRow(row), checked: this.rowIsSelected(row), toggle: e => this.onToggleRow(row, e)}) : html`<slot name="selectCell" data-rozie-params=${(() => { try { return JSON.stringify({row: this.cellSlotRow(row), checked: this.rowIsSelected(row)}); } catch { return '{}'; } })()} @rozie-select-cell-toggle=${($event: CustomEvent) => ((e => this.onToggleRow(row, e)) as (...args: any[]) => any)($event.detail)}>
|
|
1420
1531
|
<input class="rdt-select-row" type="checkbox" aria-label="Select row" ?checked=${this.rowIsSelected(row)} @change=${($event: Event & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => { this.onToggleRow(row, $event); }} data-rozie-s-d5dcab4c />
|
|
1421
1532
|
</slot>`}
|
|
1422
1533
|
</span>` : this.cellIsGrouped(cell) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1423
1534
|
<button class="rdt-expander rdt-group-toggle" type="button" data-expander="" aria-expanded=${!!this.rowIsExpanded(row)} aria-label=${rozieAttr(this.rowIsExpanded(row) ? 'Collapse group' : 'Expand group')} @click=${($event: MouseEvent & { currentTarget: HTMLButtonElement; target: HTMLButtonElement }) => { this.onToggleExpand(row, $event); }} data-rozie-s-d5dcab4c>${rozieDisplay(this.rowIsExpanded(row) ? '▾' : '▸')}</button>
|
|
1424
1535
|
<span class="rdt-group-value" data-rozie-s-d5dcab4c>
|
|
1425
|
-
${this.cell !== undefined ? this.cell({columnId: cell.column.id, column: cell.column, row: row
|
|
1536
|
+
${this.rozieSlots?.[`cell-${cell.column.id}`] !== undefined ? this.rozieSlots?.[`cell-${cell.column.id}`]!({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), value: cell.getValue()}) : html`<slot name="${`cell-${cell.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), value: cell.getValue()}); } catch { return '{}'; } })()}>
|
|
1537
|
+
${this.cell !== undefined ? this.cell({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), value: cell.getValue()}) : html`<slot name="cell" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), value: cell.getValue()}); } catch { return '{}'; } })()}>${rozieDisplay(cell.getValue())}</slot>`}
|
|
1538
|
+
</slot>`}
|
|
1426
1539
|
</span>
|
|
1427
1540
|
<span class="rdt-group-count" data-rozie-s-d5dcab4c>${rozieDisplay('(' + this.groupSubRowCount(row) + ')')}</span>
|
|
1428
1541
|
</span>` : this.isEditing(this.rowIndexOf(row), this.colIndexOf(row, cell)) ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1429
|
-
${this.
|
|
1430
|
-
${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>`}
|
|
1431
|
-
</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>
|
|
1542
|
+
${this.editorTypeOf(cell.column.id) === 'number' ? html`<input class="rdt-cell-editor" type="number" data-editing-cell="" data-builtin-editor="" .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="" data-builtin-editor="" .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>
|
|
1432
1543
|
${repeat<any>(this.editorOptionsOf(cell.column.id), (opt, _idx) => opt.value, (opt, _idx) => html`<option value=${rozieAttr(opt.value)} data-rozie-s-d5dcab4c>${rozieDisplay(opt.label)}</option>`)}
|
|
1433
|
-
</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 />` :
|
|
1434
|
-
|
|
1544
|
+
</select>` : this.editorTypeOf(cell.column.id) === 'checkbox' ? html`<input class="rdt-cell-editor" type="checkbox" data-editing-cell="" data-builtin-editor="" ?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 />` : this.editorTypeOf(cell.column.id) === 'custom' ? html`<span style="display:contents" data-rozie-s-d5dcab4c>
|
|
1545
|
+
${this.rozieSlots?.[`editor-${cell.column.id}`] !== undefined ? this.rozieSlots?.[`editor-${cell.column.id}`]!({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), 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-${cell.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), 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 '{}'; } })()}>
|
|
1546
|
+
${this.editor !== undefined ? this.editor({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), 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: this.cellSlotRow(row), 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 '{}'; } })()}>
|
|
1547
|
+
<input class="rdt-cell-editor" type="text" data-editing-cell="" data-builtin-editor="" .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 />
|
|
1548
|
+
</slot>`}
|
|
1549
|
+
</slot>`}
|
|
1550
|
+
</span>` : html`<input class="rdt-cell-editor" type="text" data-editing-cell="" data-builtin-editor="" .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>
|
|
1551
|
+
${this.rozieSlots?.[`cell-${cell.column.id}`] !== undefined ? this.rozieSlots?.[`cell-${cell.column.id}`]!({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), value: cell.getValue()}) : html`<slot name="${`cell-${cell.column.id}`}" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), value: cell.getValue()}); } catch { return '{}'; } })()}>
|
|
1552
|
+
${this.cell !== undefined ? this.cell({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), value: cell.getValue()}) : html`<slot name="cell" data-rozie-params=${(() => { try { return JSON.stringify({columnId: cell.column.id, column: cell.column, row: this.cellSlotRow(row), value: cell.getValue()}); } catch { return '{}'; } })()}>${rozieDisplay(cell.getValue())}</slot>`}
|
|
1553
|
+
</slot>`}
|
|
1435
1554
|
</span>`}${this.isFillHandleCell(this.rowIndexOf(row), this.colIndexOf(row, cell)) ? html`<span class="rdt-fill-handle" data-fill-handle="" data-testid="fill-handle" aria-hidden="true" @pointerdown=${($event: PointerEvent & { currentTarget: HTMLSpanElement; target: HTMLSpanElement }) => { this.onFillHandlePointerDown($event); }} data-rozie-s-d5dcab4c></span>` : nothing}</td>`)}
|
|
1436
1555
|
</tr>
|
|
1437
1556
|
|
|
@@ -1770,6 +1889,13 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
1770
1889
|
|
|
1771
1890
|
columnDefsCacheColRegRef: any = undefined;
|
|
1772
1891
|
|
|
1892
|
+
// B1 (quick 260906-afh) — the def-lookup index, populated INSIDE this SAME memo block on
|
|
1893
|
+
// a cache MISS only (never rebuilt per call — a per-call recursive scan would restore the
|
|
1894
|
+
// O(N^2 x M) blowup D-23 removed, T-AFH-03). A top-level `let` lowers to a per-instance
|
|
1895
|
+
// `useRef` on React (verified in the emitted leaf), so this is instance-scoped like
|
|
1896
|
+
// columnDefsCache above.
|
|
1897
|
+
columnDefsIndexCache: any = null;
|
|
1898
|
+
|
|
1773
1899
|
columnDefs = () => {
|
|
1774
1900
|
const cfg = this.columns || [];
|
|
1775
1901
|
const reg = this._colReg.value || {};
|
|
@@ -1818,9 +1944,20 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
1818
1944
|
this.columnDefsCache = out;
|
|
1819
1945
|
this.columnDefsCacheColumnsRef = this.columns;
|
|
1820
1946
|
this.columnDefsCacheColRegRef = this._colReg.value;
|
|
1947
|
+
this.columnDefsIndexCache = indexDefsById(out);
|
|
1821
1948
|
return out;
|
|
1822
1949
|
};
|
|
1823
1950
|
|
|
1951
|
+
// defIndex: the def-lookup map for the CURRENT columnDefs() array. Calling columnDefs()
|
|
1952
|
+
// first is deliberate — either an O(1) reference-equality cache hit (columnDefsIndexCache
|
|
1953
|
+
// is already fresh) or a miss that repopulates BOTH slots together, so the index can never
|
|
1954
|
+
// go stale relative to the array. Falls back to an empty null-prototype map (never null/
|
|
1955
|
+
// undefined) so a caller can read it unconditionally.
|
|
1956
|
+
defIndex = () => {
|
|
1957
|
+
this.columnDefs();
|
|
1958
|
+
return this.columnDefsIndexCache || Object.create(null);
|
|
1959
|
+
};
|
|
1960
|
+
|
|
1824
1961
|
// The constant id of the auto-injected leading checkbox column (D-04). Distinct from
|
|
1825
1962
|
// any consumer column id (the registry/config guard never produces a leading "__").
|
|
1826
1963
|
SELECT_COL_ID = '__rdt_select';
|
|
@@ -3560,10 +3697,18 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
3560
3697
|
|
|
3561
3698
|
// Template helpers reading the resolved column-def metadata by id (plain fns — used
|
|
3562
3699
|
// in template predicates + interpolation; uniform on all 6, no $computed alias trap).
|
|
3700
|
+
// B1 (quick 260906-afh): reads the O(1) def-lookup index (defIndex(), columnBuilders.rzts)
|
|
3701
|
+
// instead of linearly scanning columnDefs() — which only ever held TOP-LEVEL entries, so a
|
|
3702
|
+
// NESTED group leaf (a `columns:` group child) was invisible to every caller (headerLabel,
|
|
3703
|
+
// columnIsFilterable, editMetaOf/columnEditable/editorTypeOf/editorOptionsOf) and silently
|
|
3704
|
+
// took the "no def" fallback. defIndex() resolves both top-level AND nested leaf ids. This
|
|
3705
|
+
// also removes the per-cell O(N) scan D-23 left in place — defIndex() is memoized in the
|
|
3706
|
+
// SAME cache-invalidation block as columnDefs() itself, never rebuilt per call.
|
|
3563
3707
|
defFor = (colId: any) => {
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3708
|
+
if (colId == null) return null;
|
|
3709
|
+
const idx = this.defIndex();
|
|
3710
|
+
const d = idx[String(colId)];
|
|
3711
|
+
return d != null ? d : null;
|
|
3567
3712
|
};
|
|
3568
3713
|
|
|
3569
3714
|
// Per-row visible cells for the body loop. table-core memoizes row objects by id,
|
|
@@ -3606,17 +3751,6 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
3606
3751
|
return m && m.editorOptions != null ? m.editorOptions : [];
|
|
3607
3752
|
};
|
|
3608
3753
|
|
|
3609
|
-
// hasEditorSlot: this column routes through the consumer's #editor scoped slot (req-2)
|
|
3610
|
-
// — true only when the column declared editor='custom' AND the consumer actually
|
|
3611
|
-
// provided an #editor slot. Falls through to the built-in editor otherwise (e.g. a
|
|
3612
|
-
// column marked 'custom' with no slot supplied degrades to the text editor, never blank).
|
|
3613
|
-
hasEditorSlot = (colId: any) => this.editorTypeOf(colId) === 'custom' && !!(this._hasSlotEditor || this.editor !== undefined);
|
|
3614
|
-
|
|
3615
|
-
// hasFilterSlot: the consumer supplied a #filter scoped slot, so it OWNS the per-column
|
|
3616
|
-
// filter UI (re-added in 72-05 alongside the dedicated filter row's `<slot name="filter">`
|
|
3617
|
-
// host — see the 72-03 removal note in that plan's SUMMARY for why this was briefly gone).
|
|
3618
|
-
hasFilterSlot = () => !!(this._hasSlotFilter || this.filter !== undefined);
|
|
3619
|
-
|
|
3620
3754
|
columnIsFilterable = (colId: any) => {
|
|
3621
3755
|
const d = this.defFor(colId);
|
|
3622
3756
|
return !!(d && d.filterable);
|
|
@@ -3628,13 +3762,27 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
3628
3762
|
};
|
|
3629
3763
|
|
|
3630
3764
|
// ── Column-management chrome (req-8/9/10/11) ────────────────────────────────────────
|
|
3631
|
-
// Live header width (px) for a
|
|
3632
|
-
//
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3765
|
+
// Live header width (px) for a <th> — drives the :style width binding. Takes the table-core
|
|
3766
|
+
// HEADER object (not a column id / Column lookup) and reads header.getSize() — deliberately,
|
|
3767
|
+
// NOT column.getSize(). table-core's own ColumnSizing feature (createHeader, always present —
|
|
3768
|
+
// it is in table-core's builtInFeatures, never opt-in) gives Header.getSize() a recursive
|
|
3769
|
+
// implementation: a LEAF header returns its own column's getSize() (identical to the old
|
|
3770
|
+
// column.getSize() path — byte-identical output there), but a GROUP header (one with
|
|
3771
|
+
// subHeaders, e.g. a multi-level `columns:` entry from buildConfigDef) SUMS every descendant
|
|
3772
|
+
// leaf column's getSize() instead of returning the group's own meaningless single-column
|
|
3773
|
+
// default (150px, table-core's defaultColumnSizing.size — group ColumnDefs never set `size`).
|
|
3774
|
+
// Before this fix, a colspan-N grouped <th> asked the browser for ONE column's worth of width
|
|
3775
|
+
// (150px) while spanning N columns; under `table-layout:fixed` the browser then divides that
|
|
3776
|
+
// single declared width ACROSS all N spanned <th>s (150/5 = 30px for this codebase's 5-column
|
|
3777
|
+
// "Group A" fixture) — a 5x collapse of the actual rendered column width, independent of (and
|
|
3778
|
+
// invisible to) columnSize()/the column virtualizer's windowing math, which reads
|
|
3779
|
+
// table.getVisibleLeafColumns()[i].getSize() directly and was never affected. Root cause +
|
|
3780
|
+
// fix confirmed via .planning/debug/datatable-d13-column-axis-all-targets.md and previously
|
|
3781
|
+
// documented as "Gap 1" in .planning/phases/87-.../deferred-items.md (the identical grouped-
|
|
3782
|
+
// header/colspan mismatch, found independently during 87-05/87-06 authoring and deferred).
|
|
3783
|
+
headerWidth = (header: any) => {
|
|
3784
|
+
if (this.tick() < 0 || !header || typeof header.getSize !== 'function') return null;
|
|
3785
|
+
const w = header.getSize();
|
|
3638
3786
|
return w != null && w > 0 ? w + 'px' : null;
|
|
3639
3787
|
};
|
|
3640
3788
|
|
|
@@ -3758,15 +3906,18 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
3758
3906
|
return '';
|
|
3759
3907
|
};
|
|
3760
3908
|
|
|
3761
|
-
// Combined inline style for a <th> (width + pin)
|
|
3762
|
-
//
|
|
3763
|
-
//
|
|
3764
|
-
//
|
|
3765
|
-
|
|
3909
|
+
// Combined inline style for a <th> (width + pin). Plain string concat — uniform on all 6, no
|
|
3910
|
+
// bound-object trap. zIndex=2 (see pinStyle) so a pinned header cell — which hosts the ⋯ menu's
|
|
3911
|
+
// floating content — always stacks above the pinned filter-row cell for the same column
|
|
3912
|
+
// (zIndex=1, its own default). Takes the HEADER object (not a bare colId) so headerWidth() can
|
|
3913
|
+
// read header.getSize() — the group-aware size (see headerWidth's own comment). pinStyle still
|
|
3914
|
+
// keys off the plain column id (pinning is a leaf-column-only concern; a grouped header never
|
|
3915
|
+
// pins as a unit in this codebase's model).
|
|
3916
|
+
thStyle = (header: any) => {
|
|
3766
3917
|
let s = '';
|
|
3767
|
-
const w = this.headerWidth(
|
|
3918
|
+
const w = this.headerWidth(header);
|
|
3768
3919
|
if (w) s += 'width:' + w + ';';
|
|
3769
|
-
s += this.pinStyle(
|
|
3920
|
+
s += this.pinStyle(header && header.column ? header.column.id : null, 2);
|
|
3770
3921
|
return s;
|
|
3771
3922
|
};
|
|
3772
3923
|
|
|
@@ -3925,6 +4076,15 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
3925
4076
|
// rowIsGrouped: this flattened row is a group-header row.
|
|
3926
4077
|
rowIsGrouped = (row: any) => !!(this.tick() >= 0 && row && row.getIsGrouped && row.getIsGrouped());
|
|
3927
4078
|
|
|
4079
|
+
// rowIndexIsGrouped (quick 260906-cvo, C1/C2): THE single row-level editability/writability
|
|
4080
|
+
// predicate — a group-header row is a SYNTHETIC row whose `original` is table-core's
|
|
4081
|
+
// `leafRows[0].original` (the same fact cellSlotRow's header comment documents), so any
|
|
4082
|
+
// edit or bulk write resolved through it silently lands on an UNRELATED record. Every edit/
|
|
4083
|
+
// write guard in this component calls THIS predicate — never a re-implemented inline
|
|
4084
|
+
// `getIsGrouped()` check — so the invariant has one definition. Indexes into the SAME
|
|
4085
|
+
// `$data.rows` flattened row list rowIsGrouped reads.
|
|
4086
|
+
rowIndexIsGrouped = (rowIndex: any) => this.rowIsGrouped((this._rows.value || [])[rowIndex]);
|
|
4087
|
+
|
|
3928
4088
|
// groupingActive: grouping is currently engaged (a non-empty ordered key list). Drives the
|
|
3929
4089
|
// data-group-leaf marker so it is ABSENT when ungrouped (byte-identical-off, req-10).
|
|
3930
4090
|
groupingActive = () => this.tick() >= 0 && (this.currentState().grouping || []).length > 0;
|
|
@@ -3937,34 +4097,119 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
3937
4097
|
|
|
3938
4098
|
cellIsAggregated = (cellCtx: any) => !!(this.tick() >= 0 && cellCtx && cellCtx.getIsAggregated && cellCtx.getIsAggregated());
|
|
3939
4099
|
|
|
3940
|
-
// cellIsPlaceholder:
|
|
3941
|
-
//
|
|
3942
|
-
//
|
|
3943
|
-
//
|
|
3944
|
-
//
|
|
4100
|
+
// cellIsPlaceholder: VERIFIED against @tanstack/table-core@8.21.3 (ColumnGrouping.js:120-121,
|
|
4101
|
+
// quick 260906-afh premise correction). A placeholder cell is a cell IN A GROUPING COLUMN
|
|
4102
|
+
// that is NOT the row's OWN grouping column — `!cell.getIsGrouped() && column.getIsGrouped()`.
|
|
4103
|
+
// That is true both on a group-header row (for every OTHER grouping column) and on every leaf
|
|
4104
|
+
// row (for every grouping column) — it is NOT "never true on a group-header row" and it is NOT
|
|
4105
|
+
// "any non-grouped, non-aggregated cell". The operative consequence for this component: a
|
|
4106
|
+
// placeholder can only EVER be a grouping-column cell, so this branch can never reach a
|
|
4107
|
+
// non-grouping column — it does NOT and CANNOT guard the AGGREGATED-cell `row` leak
|
|
4108
|
+
// (cellSlotRow, below) fixes. Where it DOES apply (e.g. under multi-level grouping, the
|
|
4109
|
+
// OTHER grouping column on a group-header row), table-core still fills cell.getValue() with
|
|
4110
|
+
// the FIRST leaf row's value (cell.getValue() leaks e.g. "Oslo" onto a region-level group
|
|
4111
|
+
// line whose grouping is 'region', not 'city'); this branch renders BLANK via a dedicated
|
|
4112
|
+
// empty template so that leaked value never paints. Tick-gated exactly like cellIsGrouped so
|
|
4113
|
+
// the group chrome re-derives on a re-pull on the fine-grained targets (Solid/Lit).
|
|
3945
4114
|
cellIsPlaceholder = (cellCtx: any) => !!(this.tick() >= 0 && cellCtx && cellCtx.getIsPlaceholder && cellCtx.getIsPlaceholder());
|
|
3946
4115
|
|
|
3947
|
-
// groupSubRowCount: the number of underlying LEAF RECORDS under a group-header row (the
|
|
3948
|
-
// shown in the header, e.g. "North (40)"). row.subRows is the IMMEDIATE members — for
|
|
3949
|
-
// grouping those are sub-GROUPS, not records, so "North" with 2 categories / 40
|
|
3950
|
-
// "North (2)"
|
|
3951
|
-
// subRows
|
|
3952
|
-
//
|
|
3953
|
-
|
|
4116
|
+
// groupSubRowCount: the number of underlying TRUE LEAF RECORDS under a group-header row (the
|
|
4117
|
+
// count shown in the header, e.g. "North (40)"). row.subRows is the IMMEDIATE members — for
|
|
4118
|
+
// MULTI-LEVEL grouping those are sub-GROUPS, not records, so "North" with 2 categories / 40
|
|
4119
|
+
// records would show "North (2)" off subRows alone. row.getLeafRows() is table-core's
|
|
4120
|
+
// `flattenBy(row.subRows, d => d.subRows)` (ColumnGrouping.js / utils.js, verified against
|
|
4121
|
+
// @tanstack/table-core@8.21.3) — it pushes EVERY node it walks, INCLUDING intermediate group
|
|
4122
|
+
// nodes, so under multi-level grouping it over-counts by exactly the number of sub-group
|
|
4123
|
+
// nodes between the row and its true leaves (C4, quick 260906-cvo: North with 2 city
|
|
4124
|
+
// sub-groups + 3 records reported 5, not 3). `row.getIsGrouped()` is `!!row.groupingColumnId`
|
|
4125
|
+
// — precisely the predicate that separates a group node from a real record — so filter the
|
|
4126
|
+
// flattened list on it rather than hand-rolling a recursive `subRows` walk (getLeafRows()
|
|
4127
|
+
// already flattens; the defect is purely that it does not filter). Single-level grouping is
|
|
4128
|
+
// numerically UNCHANGED: a leaf row has no `subRows`, so no node was ever miscounted there.
|
|
4129
|
+
groupSubRowCount = (row: any) => {
|
|
4130
|
+
if (row && row.getLeafRows) {
|
|
4131
|
+
const leaves = row.getLeafRows();
|
|
4132
|
+
let n = 0;
|
|
4133
|
+
for (let i = 0; i < leaves.length; i++) {
|
|
4134
|
+
const r = leaves[i];
|
|
4135
|
+
if (!(r && r.getIsGrouped && r.getIsGrouped())) n = n + 1;
|
|
4136
|
+
}
|
|
4137
|
+
return n;
|
|
4138
|
+
}
|
|
4139
|
+
return row && row.subRows ? row.subRows.length : 0;
|
|
4140
|
+
};
|
|
4141
|
+
|
|
4142
|
+
// ── B2 (quick 260906-afh) — group-header row #cell slot descriptor ─────────────────────
|
|
4143
|
+
// PROBLEM: table-core builds a flattened group-header row via
|
|
4144
|
+
// `createRow(table, id, leafRows[0].original, …)` (getGroupedRowModel.js), so `row.original`
|
|
4145
|
+
// on a group row IS the FIRST LEAF's record. The #cell scoped slot's existing 4 call sites
|
|
4146
|
+
// all bound `:row="row.original"` (or `wr.row.original`), so an AGGREGATED cell (a
|
|
4147
|
+
// non-grouping column on a group row — cellIsGrouped()===false, cellIsPlaceholder()===false,
|
|
4148
|
+
// so it takes the #cell r-else branch, same as any ordinary leaf cell) silently handed a
|
|
4149
|
+
// consumer template the WRONG record's fields (T-AFH-05). The grouped cell itself (the
|
|
4150
|
+
// group's own column, .rdt-group-value) has the same #cell binding and the same leak.
|
|
4151
|
+
//
|
|
4152
|
+
// FIX: `cellSlotRow(row)` returns a STABLE GROUP DESCRIPTOR — never `row.original` — for a
|
|
4153
|
+
// group-header row, and `row.original` unchanged for every other row. The descriptor is an
|
|
4154
|
+
// OBJECT, never `null` (T-AFH-06 — a consumer already reading `row.foo` would throw on
|
|
4155
|
+
// Vue/Angular if handed null).
|
|
4156
|
+
//
|
|
4157
|
+
// Descriptor cache (T-AFH-02/T-AFH-04): a null-prototype map keyed on `String(row.id)`,
|
|
4158
|
+
// invalidated wholesale whenever `$data.rowModelVer` (bumped by every refreshRowModel, the
|
|
4159
|
+
// SAME reactive re-derivation discipline visibleCellsFor/rowIsGrouped use) differs from the
|
|
4160
|
+
// generation the map was built for — so the descriptor's REFERENCE IDENTITY is stable
|
|
4161
|
+
// across every cell of one group row within a row-model generation (an unstable reference
|
|
4162
|
+
// would thrash the fine-grained targets, Solid/Lit) and refreshed the moment the grouping
|
|
4163
|
+
// changes. Group row ids are built from consumer grouping VALUES, so the map MUST be
|
|
4164
|
+
// null-prototype — a `__proto__` grouping value must not reach Object.prototype.
|
|
4165
|
+
groupRowDescriptorCache: any = null;
|
|
4166
|
+
|
|
4167
|
+
groupRowDescriptorCacheVer: any = undefined;
|
|
4168
|
+
|
|
4169
|
+
groupRowDescriptor = (row: any) => {
|
|
4170
|
+
const ver = this._rowModelVer.value;
|
|
4171
|
+
if (!this.groupRowDescriptorCache || this.groupRowDescriptorCacheVer !== ver) {
|
|
4172
|
+
this.groupRowDescriptorCache = Object.create(null);
|
|
4173
|
+
this.groupRowDescriptorCacheVer = ver;
|
|
4174
|
+
}
|
|
4175
|
+
const key = String(row.id);
|
|
4176
|
+
let d = this.groupRowDescriptorCache[key];
|
|
4177
|
+
if (!d) {
|
|
4178
|
+
const groupingColumnId = row.groupingColumnId != null ? row.groupingColumnId : '';
|
|
4179
|
+
const groupingValue = row.getGroupingValue ? row.getGroupingValue(groupingColumnId) : row.groupingValue;
|
|
4180
|
+
d = {
|
|
4181
|
+
isGroupRow: true,
|
|
4182
|
+
groupId: row.id,
|
|
4183
|
+
groupingColumnId,
|
|
4184
|
+
groupingValue,
|
|
4185
|
+
leafCount: this.groupSubRowCount(row)
|
|
4186
|
+
};
|
|
4187
|
+
this.groupRowDescriptorCache[key] = d;
|
|
4188
|
+
}
|
|
4189
|
+
return d;
|
|
4190
|
+
};
|
|
4191
|
+
|
|
4192
|
+
// cellSlotRow: the #cell slot's `:row=` value. A group-header row gets the stable
|
|
4193
|
+
// descriptor above (never the leaked first-leaf record); every other row is unchanged.
|
|
4194
|
+
cellSlotRow = (row: any) => this.rowIsGrouped(row) ? this.groupRowDescriptor(row) : row ? row.original : null;
|
|
3954
4195
|
|
|
3955
4196
|
// groupingKeys: the live ordered grouping array — slot prop for the headless #groupBar + the
|
|
3956
4197
|
// default styled-token reflection. Reads currentState() ($props.grouping ?? $data.groupingDefault),
|
|
3957
4198
|
// both reactive sources, so the bar re-renders on a grouping change across all six targets.
|
|
3958
4199
|
groupingKeys = () => this.currentState().grouping || [];
|
|
3959
4200
|
|
|
3960
|
-
// groupableColumns: the data columns OFFERED to the headless #groupBar
|
|
3961
|
-
//
|
|
3962
|
-
//
|
|
4201
|
+
// groupableColumns: the data columns OFFERED to the headless #groupBar — `[{ id, label }]`.
|
|
4202
|
+
// Excludes the chrome columns (select/expander are not in columnDefs()). C5+C6 (quick
|
|
4203
|
+
// 260906-cvo): delegates the actual walk to collectGroupableLeafDefs (columnDefUtils.ts) —
|
|
4204
|
+
// a GROUP column (a `columns:` group's own entry) is NEVER offered (it has no accessor and
|
|
4205
|
+
// cannot produce a grouping value, regardless of any `groupable` flag on it), and every
|
|
4206
|
+
// groupable NESTED leaf (a `columns:` group child, opted out via `groupable: false` like any
|
|
4207
|
+
// top-level leaf) IS offered, in declaration order. The consumer builds any bar/drag UI from
|
|
4208
|
+
// this; the component ships none.
|
|
3963
4209
|
groupableColumns = () => {
|
|
3964
4210
|
const out = [];
|
|
3965
|
-
const defs = this.columnDefs();
|
|
4211
|
+
const defs = collectGroupableLeafDefs(this.columnDefs());
|
|
3966
4212
|
for (const d of defs as any) {
|
|
3967
|
-
if (!d || d.groupable === false) continue;
|
|
3968
4213
|
out.push({
|
|
3969
4214
|
id: d.id,
|
|
3970
4215
|
label: d.header != null ? d.header : d.id
|
|
@@ -4976,11 +5221,18 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
4976
5221
|
return;
|
|
4977
5222
|
}
|
|
4978
5223
|
// ── C2 (phase 63 wave-8): Enter on a GROUP-HEADER cell toggles that group's collapse/
|
|
4979
|
-
// expand (APG treegrid).
|
|
4980
|
-
//
|
|
4981
|
-
//
|
|
4982
|
-
//
|
|
4983
|
-
//
|
|
5224
|
+
// expand (APG treegrid). C1 (quick 260906-cvo) CORRECTION: the comment here used to claim
|
|
5225
|
+
// "a group cell is non-editable" as "the verified invariant" — that was FALSE AS WRITTEN.
|
|
5226
|
+
// It held only for the grouping column's OWN cell (cellIsGrouped's branch renders before
|
|
5227
|
+
// the editor branch); a non-grouping EDITABLE column's cell on a group row fell straight
|
|
5228
|
+
// through the branch chain to isEditing(...) and opened an editor (the C1 defect this
|
|
5229
|
+
// quick task closed). What is now TRUE, and WHY: isActiveCellEditable() carries an
|
|
5230
|
+
// explicit rowIndexIsGrouped(...) row guard (filterPaginationRowChrome.rzts), so EVERY
|
|
5231
|
+
// editable column's cell on a group row is non-editable — that is what makes the four
|
|
5232
|
+
// edit-entry branches above fall through to this one, not an incidental property of the
|
|
5233
|
+
// grouping column alone. Route it to the SAME onToggleExpand path the chevron uses (group
|
|
5234
|
+
// rows ride the expand model) so one Enter toggles the group. Body cells only (a
|
|
5235
|
+
// header-active Enter is unchanged);
|
|
4984
5236
|
// ($data.rows || [])[$data.activeRow] is the active flattened row (page-relative non-virtual /
|
|
4985
5237
|
// full-model virtual — both index $data.rows). Placed BEFORE the reserved enterControl branch.
|
|
4986
5238
|
else if (key === 'Enter' && !this._activeIsHeader.value && this.rowIsGrouped((this._rows.value || [])[this._activeRow.value])) {
|
|
@@ -5777,6 +6029,11 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
5777
6029
|
// rangeToTsv(): serialize the current range to TSV — rows joined by '\n', cells by '\t',
|
|
5778
6030
|
// reading each cell's value off the visible model by index (cellValueAt). A single active
|
|
5779
6031
|
// cell (no range) serializes that one cell. Each field is B10-escaped. Pure read — never writes.
|
|
6032
|
+
// C2 (quick 260906-cvo) — DELIBERATE NON-CHANGE: this is a READ, unlike applyGridToRange's
|
|
6033
|
+
// write funnel, and stays UNGUARDED for a group-header row on purpose. cellValueAt reads the
|
|
6034
|
+
// column's DISPLAYED aggregate value on a group row (table-core's cell.getValue()), which is
|
|
6035
|
+
// exactly what the user sees — serializing it is correct behavior, not a leak. Do not "fix"
|
|
6036
|
+
// this asymmetry; it is intentional.
|
|
5780
6037
|
rangeToTsv = () => {
|
|
5781
6038
|
const box = this.normalizedRange();
|
|
5782
6039
|
const r0 = box ? box.r0 : this._activeRow.value;
|
|
@@ -5830,11 +6087,22 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
5830
6087
|
for (let gr = 0; gr < grid.length; gr++) {
|
|
5831
6088
|
const r = originRow + gr;
|
|
5832
6089
|
if (r > maxRow) break;
|
|
6090
|
+
// C2 (quick 260906-cvo) — hoisted ONCE per ROW (never per cell): a group-header row's
|
|
6091
|
+
// `original` is table-core's `leafRows[0].original` (a synthetic row), so a write
|
|
6092
|
+
// resolved through it silently lands on an unrelated record. This ONE placement closes
|
|
6093
|
+
// pasteRange, cutRange, clearActiveRange AND fillRange — all four build a grid and hand
|
|
6094
|
+
// it to this single funnel, so guarding the four callers individually would be four
|
|
6095
|
+
// chances to miss one.
|
|
6096
|
+
const rowGrouped = this.rowIndexIsGrouped(r);
|
|
5833
6097
|
const cols = grid[gr] || [];
|
|
5834
6098
|
for (let gc = 0; gc < cols.length; gc++) {
|
|
5835
6099
|
const c = originCol + gc;
|
|
5836
6100
|
if (c > maxCol) break;
|
|
6101
|
+
// A group-row cell still counts toward `total` — it is a skipped TARGET, exactly like
|
|
6102
|
+
// a non-editable or validator-rejected cell — so the "N of M cells pasted" / "no cells
|
|
6103
|
+
// pasted" announce keeps its existing semantics (never silently under-reports M).
|
|
5837
6104
|
total = total + 1;
|
|
6105
|
+
if (rowGrouped) continue;
|
|
5838
6106
|
const colId = this.columnIdAt(r, c);
|
|
5839
6107
|
if (colId == null || !this.columnEditable(colId)) continue;
|
|
5840
6108
|
const rowObj = this.rowOriginalAt(r);
|
|
@@ -6125,8 +6393,26 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6125
6393
|
}
|
|
6126
6394
|
};
|
|
6127
6395
|
|
|
6128
|
-
|
|
6129
|
-
|
|
6396
|
+
// FILL_HITTEST_PROBE_RADIUS_PX / FILL_HITTEST_PROBE_STEP_PX (hardening, authorized alongside the
|
|
6397
|
+
// D-13 grouped-header width fix — .planning/debug/datatable-d13-column-axis-all-targets.md):
|
|
6398
|
+
// resolveCellAt() below hit-tests document.elementFromPoint at ONE exact pixel — structurally
|
|
6399
|
+
// fragile against a scrolling DOM by construction: any narrow column transiting past that fixed
|
|
6400
|
+
// screen point (the edge-auto-scroll rAF loop in fillDrag re-probes the SAME fixed point every
|
|
6401
|
+
// frame while gridScrollEl's content slides underneath it) has only a single-frame-scale window
|
|
6402
|
+
// to be caught, and a probe pixel landing exactly on a border/rounding edge between two adjacent
|
|
6403
|
+
// `<td>`/`<th>`s can miss both. cellIndexFromPoint widens the miss case ONLY: it tries the exact
|
|
6404
|
+
// point first (byte-identical to the pre-hardening behavior on a hit — this is not a behavior
|
|
6405
|
+
// change to the common case) and, only if that misses, fans out a small nearest-first horizontal
|
|
6406
|
+
// search before giving up. Vertical-only misses are not probed (rows are >=24px tall by design —
|
|
6407
|
+
// FILL_EDGE_SCROLL_PX itself — so a row is never narrower than a single scroll step; only COLUMN
|
|
6408
|
+
// width has no such floor, hence a horizontal-only widening).
|
|
6409
|
+
FILL_HITTEST_PROBE_RADIUS_PX = 8;
|
|
6410
|
+
|
|
6411
|
+
FILL_HITTEST_PROBE_STEP_PX = 2;
|
|
6412
|
+
|
|
6413
|
+
// resolveCellAt: the exact-point hit-test (identical logic to the pre-hardening
|
|
6414
|
+
// cellIndexFromPoint body) extracted so it can be re-tried at nearby x-offsets below.
|
|
6415
|
+
resolveCellAt = (clientX: any, clientY: any) => {
|
|
6130
6416
|
let el = document.elementFromPoint(clientX, clientY);
|
|
6131
6417
|
// Pierce OPEN shadow roots (Lit): document.elementFromPoint retargets to the shadow HOST, so
|
|
6132
6418
|
// a drag over the Lit data-table's shadow content would otherwise resolve the host (no cell)
|
|
@@ -6152,6 +6438,23 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6152
6438
|
};
|
|
6153
6439
|
};
|
|
6154
6440
|
|
|
6441
|
+
cellIndexFromPoint = (clientX: any, clientY: any) => {
|
|
6442
|
+
if (typeof document === 'undefined' || !document.elementFromPoint) return null;
|
|
6443
|
+
const direct = this.resolveCellAt(clientX, clientY);
|
|
6444
|
+
if (direct) return direct;
|
|
6445
|
+
// Widened nearest-cell search: only reached when the exact point misses. Fans outward
|
|
6446
|
+
// (nearest-first, alternating +/-x) up to FILL_HITTEST_PROBE_RADIUS_PX before giving up —
|
|
6447
|
+
// catches a narrow column that transited past the fixed probe point on this exact frame
|
|
6448
|
+
// without changing which cell wins on an ordinary (non-edge-case) hit.
|
|
6449
|
+
for (let d = this.FILL_HITTEST_PROBE_STEP_PX; d <= this.FILL_HITTEST_PROBE_RADIUS_PX; d += this.FILL_HITTEST_PROBE_STEP_PX) {
|
|
6450
|
+
const right = this.resolveCellAt(clientX + d, clientY);
|
|
6451
|
+
if (right) return right;
|
|
6452
|
+
const left = this.resolveCellAt(clientX - d, clientY);
|
|
6453
|
+
if (left) return left;
|
|
6454
|
+
}
|
|
6455
|
+
return null;
|
|
6456
|
+
};
|
|
6457
|
+
|
|
6155
6458
|
onFillHandlePointerDown = (e: any) => {
|
|
6156
6459
|
if (!e) return;
|
|
6157
6460
|
if (e.preventDefault) e.preventDefault();
|
|
@@ -6356,7 +6659,13 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6356
6659
|
// isActiveCellEditable: the active cell sits in an editable column AND is a body cell
|
|
6357
6660
|
// (req-1). Gates the F2/Enter/printable edit-entry branches in onGridKeyDown; a
|
|
6358
6661
|
// non-editable active cell falls through to the reserved enterControl path.
|
|
6662
|
+
// C1 (quick 260906-cvo) — Layer 1: a group-header row is NEVER editable, regardless of
|
|
6663
|
+
// column. This is the single highest-value guard in the cluster: it closes Shift+F2, the
|
|
6664
|
+
// checkbox toggle, and the F2/Enter/printable edit-entry branches in ONE edit (they are all
|
|
6665
|
+
// `else if` branches gated on this predicate), AND restores fallthrough so Enter on a group
|
|
6666
|
+
// row reaches the group-toggle branch below them instead of opening an editor.
|
|
6359
6667
|
isActiveCellEditable = () => {
|
|
6668
|
+
if (this.rowIndexIsGrouped(this._activeRow.value)) return false;
|
|
6360
6669
|
const colId = this.activeCellColumnId();
|
|
6361
6670
|
return colId != null && this.columnEditable(colId);
|
|
6362
6671
|
};
|
|
@@ -6374,6 +6683,14 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6374
6683
|
// non-virtual, wr.vi.index virtual).
|
|
6375
6684
|
isEditing = (rowIndex: any, colIndex: any) => {
|
|
6376
6685
|
if (this._editVer.value < 0) return false;
|
|
6686
|
+
// C1 (quick 260906-cvo) — Layer 6: the ONLY layer whose reachability does not depend on a
|
|
6687
|
+
// keystroke. Editing state is INDEX-based over the visible model, and nothing clears it
|
|
6688
|
+
// when the row model re-derives — a consumer that changes the grouping model WHILE a cell
|
|
6689
|
+
// editor is open can move a group-header row under the index $data.editingRow/
|
|
6690
|
+
// editingRowIndex still holds, rendering the editor on a group row with no beginEdit
|
|
6691
|
+
// involved. Placed AFTER the editVer read (preserves the Svelte/Solid re-derivation
|
|
6692
|
+
// discipline the header comment above documents).
|
|
6693
|
+
if (this.rowIndexIsGrouped(rowIndex)) return false;
|
|
6377
6694
|
if (this._editingRowIndex.value != null && this._editingRowIndex.value === rowIndex) {
|
|
6378
6695
|
const colId = this.columnIdAt(rowIndex, colIndex);
|
|
6379
6696
|
return colId != null && this.columnEditable(colId);
|
|
@@ -6467,39 +6784,73 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6467
6784
|
return row ? row.id : null;
|
|
6468
6785
|
};
|
|
6469
6786
|
|
|
6787
|
+
// resolveEditFocusCellEl(rowIndex, colIndex): the DOM cell element for an edit-focus
|
|
6788
|
+
// target, given an EXPLICIT index pair — NEVER a $data re-read inside this function or its
|
|
6789
|
+
// caller's poll closure. Every call site already knows this pair SYNCHRONOUSLY at the
|
|
6790
|
+
// moment it calls (beginEdit's own rowIndex/colIndex params; commitEdit's stable, already-
|
|
6791
|
+
// settled $data.editingRow/editingCol; beginRowEdit's rowIndex + the target column's
|
|
6792
|
+
// editable[].colIndex from editableColumnsForRow) — threading them through as PARAMETERS,
|
|
6793
|
+
// mirroring focusRowEditorAt's already-proven resolveCellEl(String(rowIndex), colIndex)
|
|
6794
|
+
// shape, closes the React batched-setState staleness class 88-05-SUMMARY.md documented
|
|
6795
|
+
// (REACT_STALE_GATE_SINGLE_CELL_BUG): the OLD gate read $data.editFocusColId SYNCHRONOUSLY,
|
|
6796
|
+
// in the SAME tick beginEdit's own setState call set it, and React's batching meant that
|
|
6797
|
+
// read saw the PRE-edit (null) value. A plain function argument threaded through — never a
|
|
6798
|
+
// reactive re-read — is not subject to that race, uniformly on all 6 targets.
|
|
6799
|
+
resolveEditFocusCellEl = (rowIndex: any, colIndex: any) => {
|
|
6800
|
+
if (rowIndex == null || colIndex == null || rowIndex < 0 || colIndex < 0) return null;
|
|
6801
|
+
return this.resolveCellEl(String(rowIndex), colIndex);
|
|
6802
|
+
};
|
|
6803
|
+
|
|
6470
6804
|
// Focus the freshly-mounted editor (Pitfall 1, ROZ123): after beginEdit flips the editing
|
|
6471
6805
|
// state, the editor <input> does not exist until the framework commits the r-if branch
|
|
6472
|
-
// (React setState async; Solid/Lit/Svelte next reactive tick). Poll for the
|
|
6473
|
-
//
|
|
6474
|
-
//
|
|
6806
|
+
// (React setState async; Solid/Lit/Svelte next reactive tick). Poll for the target CELL's
|
|
6807
|
+
// marked built-in editor for ~30 frames — the five fast targets resolve on attempt 1, React
|
|
6808
|
+
// retries across its async commit. NEVER read $refs eagerly.
|
|
6475
6809
|
// B2: selectAll gates the post-focus el.select(). Select-all is right when entering
|
|
6476
6810
|
// edit IN PLACE (F2/Enter/click/row-edit/validation-reject — no seeded char, the user
|
|
6477
6811
|
// retypes), but WRONG on a type-to-edit entry where a printable key already seeded the
|
|
6478
6812
|
// draft (selecting the seeded char makes the next keystroke replace it: Zeta → eta).
|
|
6479
6813
|
// beginEdit threads `seed == null` so a seeded entry skips the select and the caret sits
|
|
6480
6814
|
// AFTER the seeded char; every other caller keeps the default select-all.
|
|
6481
|
-
//
|
|
6482
|
-
//
|
|
6483
|
-
//
|
|
6484
|
-
//
|
|
6485
|
-
//
|
|
6486
|
-
//
|
|
6487
|
-
//
|
|
6488
|
-
|
|
6815
|
+
// D-01/D-02 (88-07): REPLACES the deleted presence-check early-return gate AND the
|
|
6816
|
+
// gridRoot-wide `[data-editing-cell]` first-match query with a column-scoped, marker-driven
|
|
6817
|
+
// poll. Resolves the TARGET cell first (resolveEditFocusCellEl, mirroring
|
|
6818
|
+
// focusRowEditorAt's already-shipped two-step resolve), then queries for an editor carrying
|
|
6819
|
+
// BOTH `data-editing-cell` and the host-owned `data-builtin-editor` marker WITHIN that one
|
|
6820
|
+
// cell — "no marker found" (a drop-in target, D-01) bails immediately rather than reaching
|
|
6821
|
+
// into DOM the host does not own; "no editor at all yet" keeps polling (the framework hasn't
|
|
6822
|
+
// committed the r-if branch). This closes the D-02 wrong-column hole the old grid-wide query
|
|
6823
|
+
// left open (every editable cell mounts an editor at once in row-edit mode) AND fixes the
|
|
6824
|
+
// React staleness race documented above, as a side effect of no longer reading
|
|
6825
|
+
// $data.editFocusColId anywhere in this function.
|
|
6826
|
+
focusEditorWhenReady = (rowIndex: any, colIndex: any, selectAll = true) => {
|
|
6489
6827
|
if (!this.gridRoot) return;
|
|
6490
|
-
// Editor-owns-focus contract: when the CURRENT focus target is a #editor drop-in, the host
|
|
6491
|
-
// does NOT reach into its DOM — the drop-in self-focuses via its own autofocus prop.
|
|
6492
|
-
if (this._editFocusColId.value != null && this.hasEditorSlot(this._editFocusColId.value)) return;
|
|
6493
6828
|
let attempts = 0;
|
|
6494
6829
|
const tryFocus = () => {
|
|
6495
|
-
const
|
|
6830
|
+
const cellEl = this.resolveEditFocusCellEl(rowIndex, colIndex);
|
|
6831
|
+
const el = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell][data-builtin-editor]') : null;
|
|
6832
|
+
if (!el) {
|
|
6833
|
+
// Editor-owns-focus contract (quick 260711-i5m, D-01): if the cell ALREADY holds an
|
|
6834
|
+
// editor that carries only the base marker, it's a consumer drop-in — it owns its own
|
|
6835
|
+
// focus (EditorText's own $onMount + reactive `autofocus`). Bail immediately, zero
|
|
6836
|
+
// wasted frames, rather than burning the retry ceiling on DOM the host does not own.
|
|
6837
|
+
const anyEditor = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell]') : null;
|
|
6838
|
+
if (anyEditor) return;
|
|
6839
|
+
attempts = attempts + 1;
|
|
6840
|
+
if (attempts >= 30) return;
|
|
6841
|
+
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 16);
|
|
6842
|
+
return;
|
|
6843
|
+
}
|
|
6496
6844
|
// Do NOT stomp focus a later interaction already placed in a DIFFERENT column's editor of
|
|
6497
6845
|
// this row: focusEditorWhenReady only needs to get focus INTO the (first) freshly-mounted
|
|
6498
6846
|
// editor; if focus already sits in another editable cell, a late rAF re-focus would steal it
|
|
6499
6847
|
// back to the first editor and break row-mode Tab containment (the non-deterministic B21
|
|
6500
6848
|
// focus-theft). Compare the OWNING cell's data-col-index (NOT node identity) so a stale
|
|
6501
6849
|
// SAME-column editor node on Solid's node-replacing re-render still resolves as the target —
|
|
6502
|
-
// a genuinely dropped focus is still recovered.
|
|
6850
|
+
// a genuinely dropped focus is still recovered. Stays BROAD on `data-editing-cell` (NOT
|
|
6851
|
+
// narrowed to the builtin marker, D-02): focus validly placed inside a drop-in must still
|
|
6852
|
+
// count as "already placed" — narrowing this check would let a late rAF poll steal focus
|
|
6853
|
+
// back from a drop-in that legitimately holds it.
|
|
6503
6854
|
const ae = this.gridRoot && this.gridRoot.getRootNode ? this.gridRoot.getRootNode().activeElement : null;
|
|
6504
6855
|
if (ae && el && ae !== el && ae.closest && this.gridRoot.contains(ae) && ae.hasAttribute && ae.hasAttribute('data-editing-cell')) {
|
|
6505
6856
|
const aeCell = ae.closest('[data-grid-cell]');
|
|
@@ -6508,18 +6859,12 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6508
6859
|
const elCol = elCell ? elCell.getAttribute('data-col-index') : null;
|
|
6509
6860
|
if (aeCol != null && aeCol !== elCol) return;
|
|
6510
6861
|
}
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
} catch (e: any) {}
|
|
6517
|
-
}
|
|
6518
|
-
return;
|
|
6862
|
+
el.focus();
|
|
6863
|
+
if (selectAll && el.select) {
|
|
6864
|
+
try {
|
|
6865
|
+
el.select();
|
|
6866
|
+
} catch (e: any) {}
|
|
6519
6867
|
}
|
|
6520
|
-
attempts = attempts + 1;
|
|
6521
|
-
if (attempts >= 30) return;
|
|
6522
|
-
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 16);
|
|
6523
6868
|
};
|
|
6524
6869
|
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 0);
|
|
6525
6870
|
};
|
|
@@ -6551,6 +6896,10 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6551
6896
|
// $data) so a Tab-advance that just setState'd activeRow/Col works on React. Clears any
|
|
6552
6897
|
// prior invalid state. Focus moves into the editor.
|
|
6553
6898
|
beginEdit = (rowIndex: any, colIndex: any, seed: any) => {
|
|
6899
|
+
// C1 (quick 260906-cvo) — Layer 2: closes the `onGridClick` (singleClickEdit) path, which
|
|
6900
|
+
// calls beginEdit directly gated ONLY on columnEditable — isActiveCellEditable (Layer 1)
|
|
6901
|
+
// does not run on that path at all.
|
|
6902
|
+
if (this.rowIndexIsGrouped(rowIndex)) return;
|
|
6554
6903
|
const colId = this.columnIdAt(rowIndex, colIndex);
|
|
6555
6904
|
if (colId == null || !this.columnEditable(colId)) return;
|
|
6556
6905
|
// A new edit session starts — reset the sync idempotency latch so THIS session's eventual
|
|
@@ -6571,8 +6920,10 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6571
6920
|
// from it. Cleared on endEdit.
|
|
6572
6921
|
this._editFocusColId.value = colId;
|
|
6573
6922
|
// B2: a seeded (type-to-edit) entry must NOT select-all — keep the caret after the
|
|
6574
|
-
// seeded char so subsequent typing appends instead of replacing it.
|
|
6575
|
-
|
|
6923
|
+
// seeded char so subsequent typing appends instead of replacing it. rowIndex/colIndex
|
|
6924
|
+
// are THIS call's own params — passed through directly (D-02), never re-read off
|
|
6925
|
+
// $data.editingRow/editingCol inside the poll.
|
|
6926
|
+
this.focusEditorWhenReady(rowIndex, colIndex, seed == null);
|
|
6576
6927
|
};
|
|
6577
6928
|
|
|
6578
6929
|
// Return focus to a body cell AFTER the editor unmounts (commit/cancel). The display↔
|
|
@@ -6686,8 +7037,10 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6686
7037
|
const err = this.runValidator(colId, newValue, rowOriginal);
|
|
6687
7038
|
if (err !== true) {
|
|
6688
7039
|
// D-01: reject — keep the editor open, announce, re-trap focus, NEVER write the model.
|
|
7040
|
+
// $data.editingRow/editingCol are STABLE here (set by a prior beginEdit call, not this
|
|
7041
|
+
// same tick) — safe to read directly, unlike the deleted $data.editFocusColId gate.
|
|
6689
7042
|
this.setInvalid(err);
|
|
6690
|
-
this.focusEditorWhenReady();
|
|
7043
|
+
this.focusEditorWhenReady(this._editingRow.value, this._editingCol.value);
|
|
6691
7044
|
return false;
|
|
6692
7045
|
}
|
|
6693
7046
|
this.setInvalid('');
|
|
@@ -6761,6 +7114,11 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6761
7114
|
// editor:'checkbox' columns only (Space/Enter/F2), full-row edit mode is unaffected (the
|
|
6762
7115
|
// editingRowIndex early return in onGridKeyDown already excludes it).
|
|
6763
7116
|
toggleActiveBooleanCell = () => {
|
|
7117
|
+
// C1 (quick 260906-cvo) — Layer 4: the only write funnel bypassing both beginEdit/
|
|
7118
|
+
// commitEdit and applyGridToRange. Reachable today only through the Layer-1-gated
|
|
7119
|
+
// checkbox branch, so this line is redundant AT HEAD — it earns its place by making "no
|
|
7120
|
+
// write ever targets a group row" a property of the write funnels themselves.
|
|
7121
|
+
if (this.rowIndexIsGrouped(this._activeRow.value)) return;
|
|
6764
7122
|
const colId = this.columnIdAt(this._activeRow.value, this._activeColIndex.value);
|
|
6765
7123
|
if (colId == null || !this.columnEditable(colId)) return;
|
|
6766
7124
|
const rowList = this._rows.value || [];
|
|
@@ -6851,22 +7209,22 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6851
7209
|
|
|
6852
7210
|
// B21/B22: focus the row-mode editor at a given VISIBLE col index. In full-row edit every
|
|
6853
7211
|
// editable cell is already mounted as an editor, so this resolves the cell off gridRoot and
|
|
6854
|
-
// focuses its [data-editing-cell] control. Bounded rAF-poll (mirrors
|
|
6855
|
-
// so a React re-render that recreates the input across the focus call
|
|
6856
|
-
// all on text/number editors (a no-op try/catch on select/checkbox).
|
|
6857
|
-
//
|
|
6858
|
-
//
|
|
6859
|
-
//
|
|
6860
|
-
//
|
|
6861
|
-
//
|
|
7212
|
+
// focuses its [data-editing-cell][data-builtin-editor] control. Bounded rAF-poll (mirrors
|
|
7213
|
+
// focusEditorWhenReady) so a React re-render that recreates the input across the focus call
|
|
7214
|
+
// still lands it. select-all on text/number editors (a no-op try/catch on select/checkbox).
|
|
7215
|
+
// D-01/D-02 (88-07): the old columnIdAt + presence-check early-return gate is DELETED — the
|
|
7216
|
+
// host-owned data-builtin-editor marker replaces it. If the resolved cell already holds an
|
|
7217
|
+
// editor carrying ONLY the base data-editing-cell marker (no builtin marker), that's a
|
|
7218
|
+
// consumer drop-in — bail immediately, it owns its own focus (EditorText's own $onMount +
|
|
7219
|
+
// reactive `autofocus`, which the caller already flips via $data.editFocusColId). This
|
|
7220
|
+
// two-step resolve (resolveCellEl THEN a scoped query within that one cell) was ALREADY
|
|
7221
|
+
// column-scoped and correct — it is the shape focusEditorWhenReady's D-02 rework adopts.
|
|
6862
7222
|
focusRowEditorAt = (rowIndex: any, colIndex: any) => {
|
|
6863
7223
|
if (!this.gridRoot) return;
|
|
6864
|
-
const colId = this.columnIdAt(rowIndex, colIndex);
|
|
6865
|
-
if (colId != null && this.hasEditorSlot(colId)) return;
|
|
6866
7224
|
let attempts = 0;
|
|
6867
7225
|
const tryFocus = () => {
|
|
6868
7226
|
const cellEl = this.resolveCellEl(String(rowIndex), colIndex);
|
|
6869
|
-
const ed = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell]') : null;
|
|
7227
|
+
const ed = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell][data-builtin-editor]') : null;
|
|
6870
7228
|
if (ed) {
|
|
6871
7229
|
ed.focus();
|
|
6872
7230
|
if (ed.select) {
|
|
@@ -6876,6 +7234,11 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6876
7234
|
}
|
|
6877
7235
|
return;
|
|
6878
7236
|
}
|
|
7237
|
+
// No marked built-in editor yet in this cell: a drop-in mounted there owns its own
|
|
7238
|
+
// focus — bail immediately (D-02) rather than burning the retry ceiling on DOM the
|
|
7239
|
+
// host does not own. No editor at all yet just means "keep polling."
|
|
7240
|
+
const any = cellEl && cellEl.querySelector ? cellEl.querySelector('[data-editing-cell]') : null;
|
|
7241
|
+
if (any) return;
|
|
6879
7242
|
attempts = attempts + 1;
|
|
6880
7243
|
if (attempts >= 30) return;
|
|
6881
7244
|
if (typeof requestAnimationFrame === 'function') requestAnimationFrame(tryFocus);else setTimeout(tryFocus, 16);
|
|
@@ -6892,6 +7255,11 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6892
7255
|
beginRowEdit = (row: any) => {
|
|
6893
7256
|
const rowIndex = this.rowIndexOf(row);
|
|
6894
7257
|
if (rowIndex < 0) return;
|
|
7258
|
+
// C1 (quick 260906-cvo) — Layer 5: a second, independent editing-state funnel that takes a
|
|
7259
|
+
// row OBJECT from its caller. Reachable today only via Shift+F2 (Layer 1), so also
|
|
7260
|
+
// redundant at HEAD; kept for the same reason as Layer 4 — it is a mutation entry point,
|
|
7261
|
+
// and the natural call site for a future #rowActions "Edit" drop-in button.
|
|
7262
|
+
if (this.rowIndexIsGrouped(rowIndex)) return;
|
|
6895
7263
|
const editable = this.editableColumnsForRow(rowIndex);
|
|
6896
7264
|
if (editable.length === 0) return;
|
|
6897
7265
|
// A new edit session starts — reset the sync idempotency latch (see editCellLifecycle.rzts).
|
|
@@ -6917,9 +7285,11 @@ ${this.groupable ? html`<div class="rdt-group-bar-host" data-rozie-s-d5dcab4c>
|
|
|
6917
7285
|
// Editor-owns-focus contract (quick 260711-i5m): the row's FIRST editable column is the
|
|
6918
7286
|
// initial focus target — editorAutofocusFor derives the reactive `autofocus` #editor scope
|
|
6919
7287
|
// prop from it (a built-in column is also host-focused below via focusEditorWhenReady; a
|
|
6920
|
-
// drop-in column self-focuses via its own $onMount, gated off the host reach-in
|
|
7288
|
+
// drop-in column self-focuses via its own $onMount, gated off the host reach-in via D-01's
|
|
7289
|
+
// marker). editable[0].colIndex is THIS call's own already-resolved value (D-02) — passed
|
|
7290
|
+
// through directly, never re-read off $data.editFocusColId inside the poll.
|
|
6921
7291
|
this._editFocusColId.value = editable[0].colId;
|
|
6922
|
-
this.focusEditorWhenReady();
|
|
7292
|
+
this.focusEditorWhenReady(rowIndex, editable[0].colIndex);
|
|
6923
7293
|
};
|
|
6924
7294
|
|
|
6925
7295
|
// commitRow(): validate EVERY edited column (D-01 — keep the row open if ANY fails: set
|