@rozie-ui/data-table-lit 0.7.3 → 0.8.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/CHANGELOG.md +19 -0
- package/README.md +5 -1
- package/dist/index.cjs +534 -33
- package/dist/index.d.cts +79 -9
- package/dist/index.d.mts +79 -9
- package/dist/index.mjs +534 -33
- package/package.json +2 -2
- package/src/Column.ts +59 -23
- package/src/DataTable.ts +516 -37
- package/src/helpers/activeFollow.ts +42 -0
- package/src/helpers/columnRuleUtils.ts +105 -0
- package/src/helpers/heldView.ts +185 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rozie-ui/data-table-lit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"CHANGELOG.md"
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@rozie/runtime-lit": "^0.10.
|
|
49
|
+
"@rozie/runtime-lit": "^0.10.1"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"lit": "^3.2",
|
package/src/Column.ts
CHANGED
|
@@ -54,6 +54,14 @@ export default class Column extends SignalWatcher(LitElement) {
|
|
|
54
54
|
* The table-core aggregation for this column inside a group-header cell. Either a built-in name string — `'sum'` | `'min'` | `'max'` | `'extent'` | `'mean'` | `'median'` | `'unique'` | `'uniqueCount'` | `'count'` — or a custom function `(columnId, leafRows, childRows) => any` (defensively wrapped by the parent so a throw cannot crash grouping). Null → no aggregation (the group-header cell renders as a placeholder).
|
|
55
55
|
*/
|
|
56
56
|
@property({ type: String, attribute: 'aggregation-fn' }) aggregationFn: string | (((...args: any[]) => any) | null) = null;
|
|
57
|
+
/**
|
|
58
|
+
* The table-core filter rule for this column. Either a built-in name string (e.g. `'arrIncludesSome'`, `'equalsString'`) or a custom function `(value, filterValue, row) => boolean`, where `row` is the original data object. Null → table-core's auto rule for the column's value type.
|
|
59
|
+
*/
|
|
60
|
+
@property({ type: String, attribute: 'filter-fn' }) filterFn: string | (((...args: any[]) => any) | null) = null;
|
|
61
|
+
/**
|
|
62
|
+
* The table-core sort rule for this column. Either a built-in name string (e.g. `'alphanumeric'`, `'basic'`) or a custom ascending comparator `(a, b, rowA, rowB) => number` over the cell values, with the original data objects as `rowA` / `rowB`. Null → table-core's auto rule for the column's value type.
|
|
63
|
+
*/
|
|
64
|
+
@property({ type: String, attribute: 'sorting-fn' }) sortingFn: string | (((...args: any[]) => any) | null) = null;
|
|
57
65
|
/**
|
|
58
66
|
* Whether this column's cells are editable (opt-in). Default `false` → the column is read-only and the display↔editor branch never mounts an editor. Bind `:editable="true"` (a bare attr only coerces on Vue+Lit).
|
|
59
67
|
*/
|
|
@@ -96,7 +104,9 @@ private get registry() { return this.__rozieCtxConsumer_data_table_columns.value
|
|
|
96
104
|
}
|
|
97
105
|
|
|
98
106
|
updated(changedProperties: Map<string, unknown>): void {
|
|
99
|
-
if (this.__rozieFirstUpdateDone && (changedProperties.has('id') || changedProperties.has('field') || changedProperties.has('header') || changedProperties.has('sortable') || changedProperties.has('filterable') || changedProperties.has('pinned') || changedProperties.has('width') || changedProperties.has('expandable') || changedProperties.has('groupable') || changedProperties.has('aggregationFn') || changedProperties.has('editable') || changedProperties.has('editor') || changedProperties.has('editorOptions') || changedProperties.has('validate'))) { const __watchVal = (() => [this.id, this.field, this.header, this.sortable, this.filterable, this.pinned, this.width, this.expandable, this.groupable, this.aggregationFn, this.editable, this.editor, this.editorOptions, this.validate])(); (() => {
|
|
107
|
+
if (this.__rozieFirstUpdateDone && (changedProperties.has('id') || changedProperties.has('field') || changedProperties.has('header') || changedProperties.has('sortable') || changedProperties.has('filterable') || changedProperties.has('pinned') || changedProperties.has('width') || changedProperties.has('expandable') || changedProperties.has('groupable') || changedProperties.has('aggregationFn') || changedProperties.has('filterFn') || changedProperties.has('sortingFn') || changedProperties.has('editable') || changedProperties.has('editor') || changedProperties.has('editorOptions') || changedProperties.has('validate'))) { const __watchVal = (() => [this.id, this.field, this.header, this.sortable, this.filterable, this.pinned, this.width, this.expandable, this.groupable, this.aggregationFn, this.filterFn, this.sortingFn, this.editable, this.editor, this.editorOptions, this.validate])(); (() => {
|
|
108
|
+
this.latestFilterFn = this.filterFn;
|
|
109
|
+
this.latestSortingFn = this.sortingFn;
|
|
100
110
|
if (this.reg) this.reg.registerColumn(this.colId(), this.buildSpec());
|
|
101
111
|
})(); }
|
|
102
112
|
this.__rozieFirstUpdateDone = true;
|
|
@@ -141,31 +151,57 @@ private get registry() { return this.__rozieCtxConsumer_data_table_columns.value
|
|
|
141
151
|
// REQ-30) and the $onMount registration never double-register the column.
|
|
142
152
|
registered = false;
|
|
143
153
|
|
|
154
|
+
// Stable trampolines for custom filterFn/sortingFn. An inline arrow is a new identity every
|
|
155
|
+
// consumer render; registering it directly would defeat the registerColumn equivalence guard
|
|
156
|
+
// (a function compares by source, but table-core would hold a stale closure). The spec holds
|
|
157
|
+
// ONE trampoline per column that always calls the latest function, refreshed in the re-register
|
|
158
|
+
// watch below BEFORE the equivalence check. A mutable top-level `let` (a ref on React).
|
|
159
|
+
// table-core reads `autoRemove` / `resolveFilterValue` OFF the filter function itself, so the
|
|
160
|
+
// filter trampoline carries stable forwarders that read the CURRENT latestFilterFn (absent on
|
|
161
|
+
// the consumer's fn => table-core's own defaults: never auto-remove, value passes through).
|
|
162
|
+
latestFilterFn: any = null;
|
|
163
|
+
|
|
164
|
+
latestSortingFn: any = null;
|
|
165
|
+
|
|
166
|
+
filterTrampoline: any = Object.assign((...args: any[]) => typeof this.latestFilterFn === 'function' ? this.latestFilterFn(...args) : true, {
|
|
167
|
+
autoRemove: (value: any, column: any) => typeof this.latestFilterFn === 'function' && typeof this.latestFilterFn.autoRemove === 'function' ? this.latestFilterFn.autoRemove(value, column) : false,
|
|
168
|
+
resolveFilterValue: (value: any) => typeof this.latestFilterFn === 'function' && typeof this.latestFilterFn.resolveFilterValue === 'function' ? this.latestFilterFn.resolveFilterValue(value) : value
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
sortingTrampoline = (...args: any[]) => typeof this.latestSortingFn === 'function' ? this.latestSortingFn(...args) : 0;
|
|
172
|
+
|
|
144
173
|
// the column SPEC builder — shared by the $onMount register and the late-context
|
|
145
174
|
// $onUpdate below. Carries METADATA ONLY (no cell/header render callbacks — D-A moved
|
|
146
175
|
// per-cell rendering to the parent's #cell/#header scoped slot, dispatched by columnId).
|
|
147
176
|
colId = () => this.id !== '' ? this.id : this.field;
|
|
148
177
|
|
|
149
|
-
buildSpec = () =>
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
178
|
+
buildSpec = () => {
|
|
179
|
+
// Seed the trampolines' targets at first registration (Lit props may not exist earlier).
|
|
180
|
+
this.latestFilterFn = this.filterFn;
|
|
181
|
+
this.latestSortingFn = this.sortingFn;
|
|
182
|
+
return {
|
|
183
|
+
id: this.colId(),
|
|
184
|
+
field: this.field !== '' ? this.field : this.colId(),
|
|
185
|
+
header: this.header,
|
|
186
|
+
sortable: this.sortable,
|
|
187
|
+
filterable: this.filterable,
|
|
188
|
+
pinned: this.pinned,
|
|
189
|
+
width: this.width,
|
|
190
|
+
// Expandable-rows reserved metadata (phase 50, D-04) — carried via the parent registry.
|
|
191
|
+
expandable: this.expandable,
|
|
192
|
+
// Grouping + aggregation metadata (phase 50, reqs 4-7, D-05) — carried via the parent
|
|
193
|
+
// registry; the parent resolves aggregationFn onto the ColumnDef (defensive-wrapping a
|
|
194
|
+
// custom fn) and filters groupableColumns by `groupable`.
|
|
195
|
+
groupable: this.groupable,
|
|
196
|
+
aggregationFn: this.aggregationFn,
|
|
197
|
+
filterFn: typeof this.filterFn === 'function' ? this.filterTrampoline : this.filterFn,
|
|
198
|
+
sortingFn: typeof this.sortingFn === 'function' ? this.sortingTrampoline : this.sortingFn,
|
|
199
|
+
// Editable-cell config (Phase 51) — carried into ColumnDef.meta via the parent
|
|
200
|
+
// registry (the existing per-column metadata path; NO parallel registry).
|
|
201
|
+
editable: this.editable,
|
|
202
|
+
editor: this.editor,
|
|
203
|
+
editorOptions: this.editorOptions,
|
|
204
|
+
validate: this.validate
|
|
205
|
+
};
|
|
206
|
+
};
|
|
171
207
|
}
|