@toolbox-web/grid 0.4.1 → 0.5.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 +9 -13
- package/all.js +1678 -1588
- package/all.js.map +1 -1
- package/index.js +762 -568
- package/index.js.map +1 -1
- package/lib/core/grid.d.ts +21 -0
- package/lib/core/grid.d.ts.map +1 -1
- package/lib/core/internal/config-manager.d.ts +1 -0
- package/lib/core/internal/config-manager.d.ts.map +1 -1
- package/lib/core/internal/dom-builder.d.ts +2 -0
- package/lib/core/internal/dom-builder.d.ts.map +1 -1
- package/lib/core/internal/header.d.ts.map +1 -1
- package/lib/core/internal/keyboard.d.ts.map +1 -1
- package/lib/core/internal/resize.d.ts.map +1 -1
- package/lib/core/internal/rows.d.ts.map +1 -1
- package/lib/core/internal/shell.d.ts +19 -13
- package/lib/core/internal/shell.d.ts.map +1 -1
- package/lib/core/internal/utils.d.ts +1 -0
- package/lib/core/internal/utils.d.ts.map +1 -1
- package/lib/core/plugin/base-plugin.d.ts +70 -3
- package/lib/core/plugin/base-plugin.d.ts.map +1 -1
- package/lib/core/plugin/expander-column.d.ts +51 -0
- package/lib/core/plugin/expander-column.d.ts.map +1 -0
- package/lib/core/plugin/plugin-manager.d.ts +6 -2
- package/lib/core/plugin/plugin-manager.d.ts.map +1 -1
- package/lib/core/plugin/types.d.ts +117 -1
- package/lib/core/plugin/types.d.ts.map +1 -1
- package/lib/core/types.d.ts +10 -5
- package/lib/core/types.d.ts.map +1 -1
- package/lib/plugins/clipboard/ClipboardPlugin.d.ts +5 -4
- package/lib/plugins/clipboard/ClipboardPlugin.d.ts.map +1 -1
- package/lib/plugins/clipboard/index.d.ts +1 -1
- package/lib/plugins/clipboard/index.d.ts.map +1 -1
- package/lib/plugins/clipboard/index.js +295 -190
- package/lib/plugins/clipboard/index.js.map +1 -1
- package/lib/plugins/clipboard/types.d.ts +72 -2
- package/lib/plugins/clipboard/types.d.ts.map +1 -1
- package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts +0 -1
- package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -1
- package/lib/plugins/column-virtualization/index.js +143 -56
- package/lib/plugins/column-virtualization/index.js.map +1 -1
- package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +0 -1
- package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
- package/lib/plugins/context-menu/index.js +189 -102
- package/lib/plugins/context-menu/index.js.map +1 -1
- package/lib/plugins/editing/EditingPlugin.d.ts +2 -7
- package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
- package/lib/plugins/editing/index.js +227 -150
- package/lib/plugins/editing/index.js.map +1 -1
- package/lib/plugins/export/ExportPlugin.d.ts +0 -1
- package/lib/plugins/export/ExportPlugin.d.ts.map +1 -1
- package/lib/plugins/export/index.js +184 -97
- package/lib/plugins/export/index.js.map +1 -1
- package/lib/plugins/filtering/FilteringPlugin.d.ts +14 -3
- package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
- package/lib/plugins/filtering/index.js +296 -176
- package/lib/plugins/filtering/index.js.map +1 -1
- package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +2 -2
- package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
- package/lib/plugins/grouping-columns/grouping-columns.d.ts +1 -1
- package/lib/plugins/grouping-columns/grouping-columns.d.ts.map +1 -1
- package/lib/plugins/grouping-columns/index.js +169 -61
- package/lib/plugins/grouping-columns/index.js.map +1 -1
- package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts +14 -2
- package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts.map +1 -1
- package/lib/plugins/grouping-rows/index.js +243 -140
- package/lib/plugins/grouping-rows/index.js.map +1 -1
- package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +13 -11
- package/lib/plugins/master-detail/MasterDetailPlugin.d.ts.map +1 -1
- package/lib/plugins/master-detail/index.js +278 -196
- package/lib/plugins/master-detail/index.js.map +1 -1
- package/lib/plugins/master-detail/types.d.ts +0 -10
- package/lib/plugins/master-detail/types.d.ts.map +1 -1
- package/lib/plugins/multi-sort/MultiSortPlugin.d.ts +1 -2
- package/lib/plugins/multi-sort/MultiSortPlugin.d.ts.map +1 -1
- package/lib/plugins/multi-sort/index.js +125 -40
- package/lib/plugins/multi-sort/index.js.map +1 -1
- package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +0 -1
- package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -1
- package/lib/plugins/pinned-columns/index.js +156 -75
- package/lib/plugins/pinned-columns/index.js.map +1 -1
- package/lib/plugins/pinned-columns/pinned-columns.d.ts +2 -2
- package/lib/plugins/pinned-columns/pinned-columns.d.ts.map +1 -1
- package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts +1 -2
- package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -1
- package/lib/plugins/pinned-rows/index.js +202 -117
- package/lib/plugins/pinned-rows/index.js.map +1 -1
- package/lib/plugins/pivot/PivotPlugin.d.ts +26 -4
- package/lib/plugins/pivot/PivotPlugin.d.ts.map +1 -1
- package/lib/plugins/pivot/index.js +413 -314
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/pivot/pivot-rows.d.ts +2 -1
- package/lib/plugins/pivot/pivot-rows.d.ts.map +1 -1
- package/lib/plugins/reorder/ReorderPlugin.d.ts +13 -10
- package/lib/plugins/reorder/ReorderPlugin.d.ts.map +1 -1
- package/lib/plugins/reorder/index.d.ts +1 -1
- package/lib/plugins/reorder/index.d.ts.map +1 -1
- package/lib/plugins/reorder/index.js +296 -223
- package/lib/plugins/reorder/index.js.map +1 -1
- package/lib/plugins/selection/SelectionPlugin.d.ts +21 -3
- package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
- package/lib/plugins/selection/index.d.ts +2 -2
- package/lib/plugins/selection/index.d.ts.map +1 -1
- package/lib/plugins/selection/index.js +282 -141
- package/lib/plugins/selection/index.js.map +1 -1
- package/lib/plugins/selection/types.d.ts +24 -0
- package/lib/plugins/selection/types.d.ts.map +1 -1
- package/lib/plugins/server-side/ServerSidePlugin.d.ts +0 -1
- package/lib/plugins/server-side/ServerSidePlugin.d.ts.map +1 -1
- package/lib/plugins/server-side/index.js +96 -9
- package/lib/plugins/server-side/index.js.map +1 -1
- package/lib/plugins/tree/TreePlugin.d.ts +5 -1
- package/lib/plugins/tree/TreePlugin.d.ts.map +1 -1
- package/lib/plugins/tree/index.js +209 -113
- package/lib/plugins/tree/index.js.map +1 -1
- package/lib/plugins/tree/types.d.ts +0 -10
- package/lib/plugins/tree/types.d.ts.map +1 -1
- package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +0 -1
- package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts.map +1 -1
- package/lib/plugins/undo-redo/index.js +98 -11
- package/lib/plugins/undo-redo/index.js.map +1 -1
- package/lib/plugins/visibility/VisibilityPlugin.d.ts +7 -4
- package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -1
- package/lib/plugins/visibility/index.js +155 -64
- package/lib/plugins/visibility/index.js.map +1 -1
- package/package.json +1 -1
- package/themes/dg-theme-bootstrap.css +55 -53
- package/themes/dg-theme-contrast.css +42 -40
- package/themes/dg-theme-large.css +38 -37
- package/themes/dg-theme-material.css +54 -52
- package/themes/dg-theme-standard.css +19 -17
- package/themes/dg-theme-vibrant.css +16 -14
- package/umd/grid.all.umd.js +23 -24
- package/umd/grid.all.umd.js.map +1 -1
- package/umd/grid.umd.js +12 -11
- package/umd/grid.umd.js.map +1 -1
- package/umd/plugins/clipboard.umd.js +5 -7
- package/umd/plugins/clipboard.umd.js.map +1 -1
- package/umd/plugins/column-virtualization.umd.js +1 -1
- package/umd/plugins/column-virtualization.umd.js.map +1 -1
- package/umd/plugins/context-menu.umd.js +1 -1
- package/umd/plugins/context-menu.umd.js.map +1 -1
- package/umd/plugins/editing.umd.js +1 -1
- package/umd/plugins/editing.umd.js.map +1 -1
- package/umd/plugins/export.umd.js +1 -1
- package/umd/plugins/export.umd.js.map +1 -1
- package/umd/plugins/filtering.umd.js +1 -1
- package/umd/plugins/filtering.umd.js.map +1 -1
- package/umd/plugins/grouping-columns.umd.js +1 -1
- package/umd/plugins/grouping-columns.umd.js.map +1 -1
- package/umd/plugins/grouping-rows.umd.js +1 -1
- package/umd/plugins/grouping-rows.umd.js.map +1 -1
- package/umd/plugins/master-detail.umd.js +1 -1
- package/umd/plugins/master-detail.umd.js.map +1 -1
- package/umd/plugins/multi-sort.umd.js +1 -1
- package/umd/plugins/multi-sort.umd.js.map +1 -1
- package/umd/plugins/pinned-columns.umd.js +1 -1
- package/umd/plugins/pinned-columns.umd.js.map +1 -1
- package/umd/plugins/pinned-rows.umd.js +1 -1
- package/umd/plugins/pinned-rows.umd.js.map +1 -1
- package/umd/plugins/pivot.umd.js +1 -1
- package/umd/plugins/pivot.umd.js.map +1 -1
- package/umd/plugins/reorder.umd.js +1 -1
- package/umd/plugins/reorder.umd.js.map +1 -1
- package/umd/plugins/selection.umd.js +1 -1
- package/umd/plugins/selection.umd.js.map +1 -1
- package/umd/plugins/server-side.umd.js +1 -1
- package/umd/plugins/server-side.umd.js.map +1 -1
- package/umd/plugins/tree.umd.js +1 -1
- package/umd/plugins/tree.umd.js.map +1 -1
- package/umd/plugins/undo-redo.umd.js +1 -1
- package/umd/plugins/undo-redo.umd.js.map +1 -1
- package/umd/plugins/visibility.umd.js +1 -1
- package/umd/plugins/visibility.umd.js.map +1 -1
- package/lib/core/internal/editing.d.ts +0 -76
- package/lib/core/internal/editing.d.ts.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const _ = {
|
|
2
2
|
expand: "▶",
|
|
3
3
|
collapse: "▼",
|
|
4
4
|
sortAsc: "▲",
|
|
@@ -8,7 +8,7 @@ const R = {
|
|
|
8
8
|
dragHandle: "⋮⋮",
|
|
9
9
|
toolPanel: "☰"
|
|
10
10
|
};
|
|
11
|
-
class
|
|
11
|
+
class S {
|
|
12
12
|
/**
|
|
13
13
|
* Plugin dependencies - declare other plugins this one requires.
|
|
14
14
|
*
|
|
@@ -25,8 +25,11 @@ class _ {
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
static dependencies;
|
|
28
|
-
/**
|
|
29
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Plugin version - defaults to grid version for built-in plugins.
|
|
30
|
+
* Third-party plugins can override with their own semver.
|
|
31
|
+
*/
|
|
32
|
+
version = typeof __GRID_VERSION__ < "u" ? __GRID_VERSION__ : "dev";
|
|
30
33
|
/** CSS styles to inject into the grid's shadow DOM */
|
|
31
34
|
styles;
|
|
32
35
|
/** Custom cell renderers keyed by type name */
|
|
@@ -113,12 +116,28 @@ class _ {
|
|
|
113
116
|
emit(e, t) {
|
|
114
117
|
this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
|
|
115
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Emit a cancelable custom event from the grid.
|
|
121
|
+
* @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
|
|
122
|
+
*/
|
|
123
|
+
emitCancelable(e, t) {
|
|
124
|
+
const i = new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 });
|
|
125
|
+
return this.grid?.dispatchEvent?.(i), i.defaultPrevented;
|
|
126
|
+
}
|
|
116
127
|
/**
|
|
117
128
|
* Request a re-render of the grid.
|
|
118
129
|
*/
|
|
119
130
|
requestRender() {
|
|
120
131
|
this.grid?.requestRender?.();
|
|
121
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Request a re-render and restore focus styling afterward.
|
|
135
|
+
* Use this when a plugin action (like expand/collapse) triggers a render
|
|
136
|
+
* but needs to maintain keyboard navigation focus.
|
|
137
|
+
*/
|
|
138
|
+
requestRenderWithFocus() {
|
|
139
|
+
this.grid?.requestRenderWithFocus?.();
|
|
140
|
+
}
|
|
122
141
|
/**
|
|
123
142
|
* Request a lightweight style update without rebuilding DOM.
|
|
124
143
|
* Use this instead of requestRender() when only CSS classes need updating.
|
|
@@ -153,10 +172,34 @@ class _ {
|
|
|
153
172
|
return this.grid?._visibleColumns ?? [];
|
|
154
173
|
}
|
|
155
174
|
/**
|
|
156
|
-
* Get the
|
|
175
|
+
* Get the grid as an HTMLElement for direct DOM operations.
|
|
176
|
+
* Use sparingly - prefer the typed GridElementRef API when possible.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* const width = this.gridElement.clientWidth;
|
|
181
|
+
* this.gridElement.classList.add('my-plugin-active');
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
get gridElement() {
|
|
185
|
+
return this.grid;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get the render root of the grid for DOM queries.
|
|
189
|
+
* @deprecated Use `gridElement` instead. This getter exists only for backward compatibility.
|
|
190
|
+
*
|
|
191
|
+
* With Shadow DOM removed, the grid element itself is the render root.
|
|
192
|
+
* All new code should use `this.gridElement` for DOM queries.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* // OLD (deprecated)
|
|
196
|
+
* const rows = this.shadowRoot?.querySelector('.rows');
|
|
197
|
+
*
|
|
198
|
+
* // NEW (preferred)
|
|
199
|
+
* const rows = this.gridElement.querySelector('.rows');
|
|
157
200
|
*/
|
|
158
201
|
get shadowRoot() {
|
|
159
|
-
return this.
|
|
202
|
+
return this.gridElement;
|
|
160
203
|
}
|
|
161
204
|
/**
|
|
162
205
|
* Get the disconnect signal for event listener cleanup.
|
|
@@ -184,8 +227,53 @@ class _ {
|
|
|
184
227
|
*/
|
|
185
228
|
get gridIcons() {
|
|
186
229
|
const e = this.grid?.gridConfig?.icons ?? {};
|
|
187
|
-
return { ...
|
|
230
|
+
return { ..._, ...e };
|
|
188
231
|
}
|
|
232
|
+
// #region Animation Helpers
|
|
233
|
+
/**
|
|
234
|
+
* Check if animations are enabled at the grid level.
|
|
235
|
+
* Respects gridConfig.animation.mode and the CSS variable set by the grid.
|
|
236
|
+
*
|
|
237
|
+
* Plugins should use this to skip animations when:
|
|
238
|
+
* - Animation mode is 'off' or `false`
|
|
239
|
+
* - User prefers reduced motion and mode is 'reduced-motion' (default)
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```ts
|
|
243
|
+
* private get animationStyle(): 'slide' | 'fade' | false {
|
|
244
|
+
* if (!this.isAnimationEnabled) return false;
|
|
245
|
+
* return this.config.animation ?? 'slide';
|
|
246
|
+
* }
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
get isAnimationEnabled() {
|
|
250
|
+
const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
|
|
251
|
+
if (e === !1 || e === "off") return !1;
|
|
252
|
+
if (e === !0 || e === "on") return !0;
|
|
253
|
+
const t = this.gridElement;
|
|
254
|
+
return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get the animation duration in milliseconds from CSS variable.
|
|
258
|
+
* Falls back to 200ms if not set.
|
|
259
|
+
*
|
|
260
|
+
* Plugins can use this for their animation timing to stay consistent
|
|
261
|
+
* with the grid-level animation.duration setting.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```ts
|
|
265
|
+
* element.animate(keyframes, { duration: this.animationDuration });
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
get animationDuration() {
|
|
269
|
+
const e = this.gridElement;
|
|
270
|
+
if (e) {
|
|
271
|
+
const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), i = parseInt(t, 10);
|
|
272
|
+
if (!isNaN(i)) return i;
|
|
273
|
+
}
|
|
274
|
+
return 200;
|
|
275
|
+
}
|
|
276
|
+
// #endregion
|
|
189
277
|
/**
|
|
190
278
|
* Resolve an icon value to string or HTMLElement.
|
|
191
279
|
* Checks plugin config first, then grid-level icons, then defaults.
|
|
@@ -215,8 +303,9 @@ class _ {
|
|
|
215
303
|
}
|
|
216
304
|
// #endregion
|
|
217
305
|
}
|
|
218
|
-
|
|
219
|
-
|
|
306
|
+
const L = "@layer tbw-plugins{tbw-grid{--tbw-editing-bg: var(--tbw-color-selection);--tbw-editing-row-bg: var(--tbw-editing-bg);--tbw-editing-border: var(--tbw-border-input, 1px solid var(--tbw-color-border-strong));--tbw-padding-editing-input: var(--tbw-cell-padding-input, 2px 6px);--tbw-font-size-editor: inherit;--tbw-editing-row-outline-color: var(--tbw-color-accent);--tbw-editing-row-outline-width: 1px}tbw-grid .data-grid-row:has(.editing){background:var(--tbw-editing-row-bg);outline:var(--tbw-editing-row-outline-width) solid var(--tbw-editing-row-outline-color);outline-offset:calc(-1 * var(--tbw-editing-row-outline-width))}tbw-grid .data-grid-row>.cell.editing{overflow:hidden;padding:0;display:flex;min-height:calc(var(--tbw-row-height) + 2px);align-items:center;justify-content:center}tbw-grid .data-grid-row>.cell.editing input:not([type=checkbox]),tbw-grid .data-grid-row>.cell.editing select,tbw-grid .data-grid-row>.cell.editing textarea{width:100%;height:100%;flex:1 1 auto;min-width:0;border:var(--tbw-editing-border);padding:var(--tbw-padding-editing-input);font-size:var(--tbw-font-size-editor)}tbw-grid .tbw-editor-host{display:contents}}";
|
|
307
|
+
function k(l) {
|
|
308
|
+
switch (l.type) {
|
|
220
309
|
case "number":
|
|
221
310
|
return (e) => {
|
|
222
311
|
const t = document.createElement("input");
|
|
@@ -243,19 +332,19 @@ function k(f) {
|
|
|
243
332
|
i.multi && (t.multiple = !0);
|
|
244
333
|
const s = i.options;
|
|
245
334
|
(typeof s == "function" ? s() : s || []).forEach((r) => {
|
|
246
|
-
const
|
|
247
|
-
|
|
335
|
+
const a = document.createElement("option");
|
|
336
|
+
a.value = String(r.value), a.textContent = r.label, (i.multi && Array.isArray(e.value) && e.value.includes(r.value) || !i.multi && e.value === r.value) && (a.selected = !0), t.appendChild(a);
|
|
248
337
|
});
|
|
249
|
-
const
|
|
338
|
+
const o = () => {
|
|
250
339
|
if (i.multi) {
|
|
251
340
|
const r = [];
|
|
252
|
-
Array.from(t.selectedOptions).forEach((
|
|
253
|
-
r.push(
|
|
341
|
+
Array.from(t.selectedOptions).forEach((a) => {
|
|
342
|
+
r.push(a.value);
|
|
254
343
|
}), e.commit(r);
|
|
255
344
|
} else
|
|
256
345
|
e.commit(t.value);
|
|
257
346
|
};
|
|
258
|
-
return t.addEventListener("change",
|
|
347
|
+
return t.addEventListener("change", o), t.addEventListener("blur", o), t.addEventListener("keydown", (r) => {
|
|
259
348
|
r.key === "Escape" && e.cancel();
|
|
260
349
|
}), t;
|
|
261
350
|
};
|
|
@@ -268,31 +357,32 @@ function k(f) {
|
|
|
268
357
|
};
|
|
269
358
|
}
|
|
270
359
|
}
|
|
271
|
-
const
|
|
272
|
-
function
|
|
273
|
-
return !(typeof
|
|
360
|
+
const C = 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])';
|
|
361
|
+
function w(l) {
|
|
362
|
+
return !(typeof l != "string" || l === "__proto__" || l === "constructor" || l === "prototype");
|
|
363
|
+
}
|
|
364
|
+
function O(l) {
|
|
365
|
+
return (l.__editingCellCount ?? 0) > 0;
|
|
274
366
|
}
|
|
275
|
-
function
|
|
276
|
-
|
|
367
|
+
function A(l) {
|
|
368
|
+
const e = (l.__editingCellCount ?? 0) + 1;
|
|
369
|
+
l.__editingCellCount = e, l.setAttribute("data-has-editing", "");
|
|
277
370
|
}
|
|
278
|
-
function
|
|
279
|
-
|
|
280
|
-
f.__editingCellCount = e, f.setAttribute("data-has-editing", "");
|
|
371
|
+
function q(l) {
|
|
372
|
+
l.__editingCellCount = 0, l.removeAttribute("data-has-editing");
|
|
281
373
|
}
|
|
282
|
-
function
|
|
283
|
-
|
|
374
|
+
function v(l, e) {
|
|
375
|
+
return l instanceof HTMLInputElement ? l.type === "checkbox" ? l.checked : l.type === "number" ? l.value === "" ? null : Number(l.value) : l.type === "date" ? l.valueAsDate : l.value : e?.type === "number" && l.value !== "" ? Number(l.value) : l.value;
|
|
284
376
|
}
|
|
285
|
-
function
|
|
286
|
-
const i =
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
i.addEventListener("
|
|
290
|
-
t(s());
|
|
291
|
-
}), i instanceof HTMLInputElement && i.type === "checkbox" ? i.addEventListener("change", () => t(i.checked)) : i instanceof HTMLSelectElement && i.addEventListener("change", () => t(s()));
|
|
377
|
+
function T(l, e, t) {
|
|
378
|
+
const i = l.querySelector("input,textarea,select");
|
|
379
|
+
i && (i.addEventListener("blur", () => {
|
|
380
|
+
t(v(i, e));
|
|
381
|
+
}), i instanceof HTMLInputElement && i.type === "checkbox" ? i.addEventListener("change", () => t(i.checked)) : i instanceof HTMLSelectElement && i.addEventListener("change", () => t(v(i, e))));
|
|
292
382
|
}
|
|
293
|
-
class
|
|
383
|
+
class N extends S {
|
|
294
384
|
name = "editing";
|
|
295
|
-
|
|
385
|
+
styles = L;
|
|
296
386
|
get defaultConfig() {
|
|
297
387
|
return {
|
|
298
388
|
editOn: "click"
|
|
@@ -344,15 +434,6 @@ class q extends _ {
|
|
|
344
434
|
this.#e = -1, this.#r = -1, this.#s.clear(), this.#t.clear(), this.#n.clear(), super.detach();
|
|
345
435
|
}
|
|
346
436
|
// #endregion
|
|
347
|
-
// #region Config Augmentation (processColumns hook)
|
|
348
|
-
/**
|
|
349
|
-
* Augment columns with editing metadata.
|
|
350
|
-
* This enables the grid to recognize editable columns without core knowledge.
|
|
351
|
-
*/
|
|
352
|
-
processColumns(e) {
|
|
353
|
-
return e;
|
|
354
|
-
}
|
|
355
|
-
// #endregion
|
|
356
437
|
// #region Event Handlers (event distribution)
|
|
357
438
|
/**
|
|
358
439
|
* Handle cell clicks - start editing if configured for click mode.
|
|
@@ -377,12 +458,12 @@ class q extends _ {
|
|
|
377
458
|
if (e.key === " " || e.key === "Spacebar") {
|
|
378
459
|
const i = t._focusRow, s = t._focusCol;
|
|
379
460
|
if (i >= 0 && s >= 0) {
|
|
380
|
-
const n = t._visibleColumns[s],
|
|
381
|
-
if (n?.editable && n.type === "boolean" &&
|
|
461
|
+
const n = t._visibleColumns[s], o = t._rows[i];
|
|
462
|
+
if (n?.editable && n.type === "boolean" && o) {
|
|
382
463
|
const r = n.field;
|
|
383
|
-
if (
|
|
384
|
-
const
|
|
385
|
-
return this.#
|
|
464
|
+
if (w(r)) {
|
|
465
|
+
const f = !o[r];
|
|
466
|
+
return this.#a(i, n, f, o), e.preventDefault(), this.requestRender(), !0;
|
|
386
467
|
}
|
|
387
468
|
}
|
|
388
469
|
}
|
|
@@ -394,7 +475,7 @@ class q extends _ {
|
|
|
394
475
|
const i = this.config.editOn ?? t.effectiveConfig?.editOn;
|
|
395
476
|
if (i === !1 || i === "manual") return !1;
|
|
396
477
|
const s = t._focusRow;
|
|
397
|
-
return s >= 0 && t._columns?.some((
|
|
478
|
+
return s >= 0 && t._columns?.some((o) => o.editable) ? (this.beginBulkEdit(s), !0) : !1;
|
|
398
479
|
}
|
|
399
480
|
return !1;
|
|
400
481
|
}
|
|
@@ -409,12 +490,12 @@ class q extends _ {
|
|
|
409
490
|
const e = this.grid;
|
|
410
491
|
if (this.#o && (this.#o = !1, this.#u(e)), this.#n.size !== 0)
|
|
411
492
|
for (const t of this.#n) {
|
|
412
|
-
const [i, s] = t.split(":"), n = parseInt(i, 10),
|
|
493
|
+
const [i, s] = t.split(":"), n = parseInt(i, 10), o = parseInt(s, 10), r = e.findRenderedRowElement?.(n);
|
|
413
494
|
if (!r) continue;
|
|
414
|
-
const
|
|
415
|
-
if (!
|
|
416
|
-
const
|
|
417
|
-
|
|
495
|
+
const a = r.querySelector(`.cell[data-col="${o}"]`);
|
|
496
|
+
if (!a || a.classList.contains("editing")) continue;
|
|
497
|
+
const f = e._rows[n], d = e._visibleColumns[o];
|
|
498
|
+
f && d && this.#c(f, n, d, o, a, !0);
|
|
418
499
|
}
|
|
419
500
|
}
|
|
420
501
|
/**
|
|
@@ -479,7 +560,7 @@ class q extends _ {
|
|
|
479
560
|
* Programmatically begin editing a cell.
|
|
480
561
|
*/
|
|
481
562
|
beginCellEdit(e, t) {
|
|
482
|
-
const i = this.grid, s = i._visibleColumns.findIndex((
|
|
563
|
+
const i = this.grid, s = i._visibleColumns.findIndex((a) => a.field === t);
|
|
483
564
|
if (s === -1 || !i._visibleColumns[s]?.editable) return;
|
|
484
565
|
const r = i.findRenderedRowElement?.(e)?.querySelector(`.cell[data-col="${s}"]`);
|
|
485
566
|
r && this.#f(e, s, r);
|
|
@@ -492,19 +573,19 @@ class q extends _ {
|
|
|
492
573
|
if ((this.config.editOn ?? t.effectiveConfig?.editOn) === !1 || !t._columns?.some((r) => r.editable)) return;
|
|
493
574
|
const n = t.findRenderedRowElement?.(e);
|
|
494
575
|
if (!n) return;
|
|
495
|
-
const
|
|
496
|
-
this.#d(e,
|
|
497
|
-
const
|
|
498
|
-
if (
|
|
499
|
-
const
|
|
500
|
-
|
|
576
|
+
const o = t._rows[e];
|
|
577
|
+
this.#d(e, o), Array.from(n.children).forEach((r, a) => {
|
|
578
|
+
const f = t._visibleColumns[a];
|
|
579
|
+
if (f?.editable) {
|
|
580
|
+
const d = r;
|
|
581
|
+
d.classList.contains("editing") || this.#c(o, e, f, a, d, !0);
|
|
501
582
|
}
|
|
502
583
|
}), setTimeout(() => {
|
|
503
584
|
let r = n.querySelector(`.cell[data-col="${t._focusCol}"]`);
|
|
504
585
|
if (r?.classList.contains("editing") || (r = n.querySelector(".cell.editing")), r?.classList.contains("editing")) {
|
|
505
|
-
const
|
|
586
|
+
const a = r.querySelector(C);
|
|
506
587
|
try {
|
|
507
|
-
|
|
588
|
+
a?.focus({ preventScroll: !0 });
|
|
508
589
|
} catch {
|
|
509
590
|
}
|
|
510
591
|
}
|
|
@@ -528,8 +609,8 @@ class q extends _ {
|
|
|
528
609
|
* Begin editing a single cell.
|
|
529
610
|
*/
|
|
530
611
|
#f(e, t, i) {
|
|
531
|
-
const s = this.grid, n = s._rows[e],
|
|
532
|
-
!n || !
|
|
612
|
+
const s = this.grid, n = s._rows[e], o = s._visibleColumns[t];
|
|
613
|
+
!n || !o?.editable || i.classList.contains("editing") || (this.#e !== e && this.#d(e, n), this.#r = t, this.#c(n, e, o, t, i, !1));
|
|
533
614
|
}
|
|
534
615
|
/**
|
|
535
616
|
* Sync the internal grid state with the plugin's editing state.
|
|
@@ -549,16 +630,16 @@ class q extends _ {
|
|
|
549
630
|
*/
|
|
550
631
|
#i(e, t) {
|
|
551
632
|
if (this.#e !== e) return;
|
|
552
|
-
const i = this.grid, s = this.#s.get(e), n = i._rows[e],
|
|
553
|
-
if (!t &&
|
|
554
|
-
const
|
|
555
|
-
if (isNaN(
|
|
556
|
-
const
|
|
557
|
-
if (!
|
|
558
|
-
const
|
|
559
|
-
if (
|
|
560
|
-
|
|
561
|
-
|
|
633
|
+
const i = this.grid, s = this.#s.get(e), n = i._rows[e], o = i.findRenderedRowElement?.(e);
|
|
634
|
+
if (!t && o && n && o.querySelectorAll(".cell.editing").forEach((a) => {
|
|
635
|
+
const f = Number(a.getAttribute("data-col"));
|
|
636
|
+
if (isNaN(f)) return;
|
|
637
|
+
const d = i._visibleColumns[f];
|
|
638
|
+
if (!d) return;
|
|
639
|
+
const b = a.querySelector("input,textarea,select");
|
|
640
|
+
if (b) {
|
|
641
|
+
const c = v(b, d);
|
|
642
|
+
n[d.field] !== c && this.#a(e, d, c, n);
|
|
562
643
|
}
|
|
563
644
|
}), t && s && n)
|
|
564
645
|
Object.keys(s).forEach((r) => {
|
|
@@ -577,119 +658,115 @@ class q extends _ {
|
|
|
577
658
|
this.#s.delete(e), this.#e = -1, this.#r = -1, this.#l();
|
|
578
659
|
for (const r of this.#n)
|
|
579
660
|
r.startsWith(`${e}:`) && this.#n.delete(r);
|
|
580
|
-
|
|
581
|
-
r.classList.remove("editing"),
|
|
582
|
-
}), this.requestRender()), this.#o = !0,
|
|
661
|
+
o && (o.querySelectorAll(".cell.editing").forEach((r) => {
|
|
662
|
+
r.classList.remove("editing"), q(r.parentElement);
|
|
663
|
+
}), this.requestRender()), this.#o = !0, o || (this.#u(i), this.#o = !1);
|
|
583
664
|
}
|
|
584
665
|
/**
|
|
585
666
|
* Commit a single cell value change.
|
|
586
667
|
*/
|
|
587
|
-
#
|
|
668
|
+
#a(e, t, i, s) {
|
|
588
669
|
const n = t.field;
|
|
589
|
-
if (!
|
|
590
|
-
s[n]
|
|
670
|
+
if (!w(n)) return;
|
|
671
|
+
const o = s[n];
|
|
672
|
+
if (o === i) return;
|
|
591
673
|
const r = !this.#t.has(e);
|
|
592
|
-
this
|
|
593
|
-
const u = this.grid.findRenderedRowElement?.(e);
|
|
594
|
-
u && u.classList.add("changed"), this.emit("cell-commit", {
|
|
674
|
+
if (this.emitCancelable("cell-commit", {
|
|
595
675
|
row: s,
|
|
596
676
|
field: n,
|
|
677
|
+
oldValue: o,
|
|
597
678
|
value: i,
|
|
598
679
|
rowIndex: e,
|
|
599
680
|
changedRows: this.changedRows,
|
|
600
681
|
changedRowIndices: this.changedRowIndices,
|
|
601
682
|
firstTimeForRow: r
|
|
602
|
-
});
|
|
683
|
+
})) return;
|
|
684
|
+
s[n] = i, this.#t.add(e), this.#l();
|
|
685
|
+
const d = this.grid.findRenderedRowElement?.(e);
|
|
686
|
+
d && d.classList.add("changed");
|
|
603
687
|
}
|
|
604
688
|
/**
|
|
605
689
|
* Inject an editor into a cell.
|
|
606
690
|
*/
|
|
607
|
-
#
|
|
691
|
+
#c(e, t, i, s, n, o) {
|
|
608
692
|
if (!i.editable || n.classList.contains("editing")) return;
|
|
609
|
-
const r =
|
|
693
|
+
const r = w(i.field) ? e[i.field] : void 0;
|
|
610
694
|
n.classList.add("editing"), this.#n.add(`${t}:${s}`);
|
|
611
|
-
const
|
|
612
|
-
|
|
613
|
-
let
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
},
|
|
617
|
-
|
|
618
|
-
},
|
|
619
|
-
|
|
620
|
-
h.key === "Enter" && (h.stopPropagation(), h.preventDefault(),
|
|
695
|
+
const a = n.parentElement;
|
|
696
|
+
a && A(a);
|
|
697
|
+
let f = !1;
|
|
698
|
+
const d = (h) => {
|
|
699
|
+
f || this.#e === -1 || this.#a(t, i, h, e);
|
|
700
|
+
}, b = () => {
|
|
701
|
+
f = !0, w(i.field) && (e[i.field] = r);
|
|
702
|
+
}, c = document.createElement("div");
|
|
703
|
+
c.className = "tbw-editor-host", n.innerHTML = "", n.appendChild(c), c.addEventListener("keydown", (h) => {
|
|
704
|
+
h.key === "Enter" && (h.stopPropagation(), h.preventDefault(), f = !0, this.#i(t, !1)), h.key === "Escape" && (h.stopPropagation(), h.preventDefault(), b(), this.#i(t, !0));
|
|
621
705
|
});
|
|
622
|
-
const
|
|
623
|
-
if (
|
|
624
|
-
this.#h(
|
|
625
|
-
else if (typeof
|
|
626
|
-
const h = document.createElement(
|
|
627
|
-
h.value = m, h.addEventListener("change", () =>
|
|
628
|
-
|
|
706
|
+
const g = i, E = g.__editorTemplate, u = g.editor || (E ? "template" : k(i)), m = r;
|
|
707
|
+
if (u === "template" && E)
|
|
708
|
+
this.#h(c, g, e, r, d, b, o, t);
|
|
709
|
+
else if (typeof u == "string") {
|
|
710
|
+
const h = document.createElement(u);
|
|
711
|
+
h.value = m, h.addEventListener("change", () => d(h.value)), c.appendChild(h), o || queueMicrotask(() => {
|
|
712
|
+
c.querySelector(C)?.focus({ preventScroll: !0 });
|
|
629
713
|
});
|
|
630
|
-
} else if (typeof
|
|
631
|
-
const h = { row: e, value: m, field: i.field, column: i, commit:
|
|
632
|
-
typeof
|
|
633
|
-
|
|
714
|
+
} else if (typeof u == "function") {
|
|
715
|
+
const h = { row: e, value: m, field: i.field, column: i, commit: d, cancel: b }, p = u(h);
|
|
716
|
+
typeof p == "string" ? (c.innerHTML = p, T(c, i, d)) : p instanceof Node && c.appendChild(p), o || queueMicrotask(() => {
|
|
717
|
+
c.querySelector(C)?.focus({ preventScroll: !0 });
|
|
634
718
|
});
|
|
635
|
-
} else if (
|
|
636
|
-
const h = this.grid,
|
|
637
|
-
|
|
638
|
-
const y = { row: e, value: m, field: i.field, column: i, commit:
|
|
639
|
-
if (
|
|
719
|
+
} else if (u && typeof u == "object") {
|
|
720
|
+
const h = this.grid, p = document.createElement("div");
|
|
721
|
+
p.setAttribute("data-external-editor", ""), p.setAttribute("data-field", i.field), c.appendChild(p);
|
|
722
|
+
const y = { row: e, value: m, field: i.field, column: i, commit: d, cancel: b };
|
|
723
|
+
if (u.mount)
|
|
640
724
|
try {
|
|
641
|
-
|
|
642
|
-
} catch (
|
|
643
|
-
console.warn(`[tbw-grid] External editor mount error for column '${i.field}':`,
|
|
725
|
+
u.mount({ placeholder: p, context: y, spec: u });
|
|
726
|
+
} catch (R) {
|
|
727
|
+
console.warn(`[tbw-grid] External editor mount error for column '${i.field}':`, R);
|
|
644
728
|
}
|
|
645
729
|
else
|
|
646
730
|
h.dispatchEvent(
|
|
647
|
-
new CustomEvent("mount-external-editor", { detail: { placeholder:
|
|
731
|
+
new CustomEvent("mount-external-editor", { detail: { placeholder: p, spec: u, context: y } })
|
|
648
732
|
);
|
|
649
733
|
}
|
|
650
734
|
}
|
|
651
735
|
/**
|
|
652
736
|
* Render a template-based editor.
|
|
653
737
|
*/
|
|
654
|
-
#h(e, t, i, s, n,
|
|
655
|
-
const
|
|
656
|
-
if (!
|
|
657
|
-
const
|
|
658
|
-
|
|
738
|
+
#h(e, t, i, s, n, o, r, a) {
|
|
739
|
+
const f = t.__editorTemplate;
|
|
740
|
+
if (!f) return;
|
|
741
|
+
const d = f.cloneNode(!0), b = t.__compiledEditor;
|
|
742
|
+
b ? d.innerHTML = b({
|
|
659
743
|
row: i,
|
|
660
744
|
value: s,
|
|
661
745
|
field: t.field,
|
|
662
746
|
column: t,
|
|
663
747
|
commit: n,
|
|
664
|
-
cancel:
|
|
665
|
-
}) :
|
|
666
|
-
|
|
667
|
-
if (!
|
|
668
|
-
const m = i[
|
|
748
|
+
cancel: o
|
|
749
|
+
}) : d.querySelectorAll("*").forEach((g) => {
|
|
750
|
+
g.childNodes.length === 1 && g.firstChild?.nodeType === Node.TEXT_NODE && (g.textContent = g.textContent?.replace(/{{\s*value\s*}}/g, s == null ? "" : String(s)).replace(/{{\s*row\.([a-zA-Z0-9_]+)\s*}}/g, (E, u) => {
|
|
751
|
+
if (!w(u)) return "";
|
|
752
|
+
const m = i[u];
|
|
669
753
|
return m == null ? "" : String(m);
|
|
670
754
|
}) || "");
|
|
671
755
|
});
|
|
672
|
-
const
|
|
756
|
+
const c = d.querySelector(
|
|
673
757
|
"input,textarea,select"
|
|
674
758
|
);
|
|
675
|
-
if (
|
|
676
|
-
|
|
677
|
-
let
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
if (d.key === "Enter") {
|
|
685
|
-
d.stopPropagation(), d.preventDefault(), p = !0;
|
|
686
|
-
const m = o instanceof HTMLInputElement && o.type === "checkbox" ? o.checked : o.value;
|
|
687
|
-
n(m), this.#i(c, !1);
|
|
688
|
-
}
|
|
689
|
-
d.key === "Escape" && (d.stopPropagation(), d.preventDefault(), l(), this.#i(c, !0));
|
|
690
|
-
}), o instanceof HTMLInputElement && o.type === "checkbox" && o.addEventListener("change", () => n(o.checked)), r || setTimeout(() => o.focus({ preventScroll: !0 }), 0);
|
|
759
|
+
if (c) {
|
|
760
|
+
c instanceof HTMLInputElement && c.type === "checkbox" ? c.checked = !!s : c.value = String(s ?? "");
|
|
761
|
+
let g = !1;
|
|
762
|
+
c.addEventListener("blur", () => {
|
|
763
|
+
g || n(v(c, t));
|
|
764
|
+
}), c.addEventListener("keydown", (E) => {
|
|
765
|
+
const u = E;
|
|
766
|
+
u.key === "Enter" && (u.stopPropagation(), u.preventDefault(), g = !0, n(v(c, t)), this.#i(a, !1)), u.key === "Escape" && (u.stopPropagation(), u.preventDefault(), o(), this.#i(a, !0));
|
|
767
|
+
}), c instanceof HTMLInputElement && c.type === "checkbox" && c.addEventListener("change", () => n(c.checked)), r || setTimeout(() => c.focus({ preventScroll: !0 }), 0);
|
|
691
768
|
}
|
|
692
|
-
e.appendChild(
|
|
769
|
+
e.appendChild(d);
|
|
693
770
|
}
|
|
694
771
|
/**
|
|
695
772
|
* Restore focus to cell after exiting edit mode.
|
|
@@ -700,7 +777,7 @@ class q extends _ {
|
|
|
700
777
|
const t = e._focusRow, i = e._focusCol, s = e.findRenderedRowElement?.(t);
|
|
701
778
|
if (s) {
|
|
702
779
|
Array.from(e._bodyEl.querySelectorAll(".cell-focus")).forEach(
|
|
703
|
-
(
|
|
780
|
+
(o) => o.classList.remove("cell-focus")
|
|
704
781
|
);
|
|
705
782
|
const n = s.querySelector(`.cell[data-row="${t}"][data-col="${i}"]`);
|
|
706
783
|
n && (n.classList.add("cell-focus"), n.setAttribute("aria-selected", "true"), n.hasAttribute("tabindex") || n.setAttribute("tabindex", "-1"), n.focus({ preventScroll: !0 }));
|
|
@@ -712,10 +789,10 @@ class q extends _ {
|
|
|
712
789
|
// #endregion
|
|
713
790
|
}
|
|
714
791
|
export {
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
792
|
+
N as EditingPlugin,
|
|
793
|
+
C as FOCUSABLE_EDITOR_SELECTOR,
|
|
794
|
+
q as clearEditingState,
|
|
718
795
|
k as defaultEditorFor,
|
|
719
|
-
|
|
796
|
+
O as hasEditingCells
|
|
720
797
|
};
|
|
721
798
|
//# sourceMappingURL=index.js.map
|