@toolbox-web/grid 1.12.1 → 1.14.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/all.js +1171 -943
- package/all.js.map +1 -1
- package/index.js +735 -737
- package/index.js.map +1 -1
- package/lib/core/grid.d.ts.map +1 -1
- package/lib/core/internal/row-animation.d.ts.map +1 -1
- package/lib/core/internal/sanitize.d.ts.map +1 -1
- package/lib/core/internal/validate-config.d.ts.map +1 -1
- package/lib/core/plugin/types.d.ts +1 -1
- package/lib/core/plugin/types.d.ts.map +1 -1
- package/lib/core/types.d.ts +48 -1
- package/lib/core/types.d.ts.map +1 -1
- package/lib/plugins/clipboard/ClipboardPlugin.d.ts +69 -8
- 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 +257 -192
- package/lib/plugins/clipboard/index.js.map +1 -1
- package/lib/plugins/clipboard/types.d.ts +31 -0
- package/lib/plugins/clipboard/types.d.ts.map +1 -1
- package/lib/plugins/column-virtualization/index.js.map +1 -1
- package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +8 -0
- package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
- package/lib/plugins/context-menu/index.js +75 -60
- package/lib/plugins/context-menu/index.js.map +1 -1
- package/lib/plugins/context-menu/types.d.ts +7 -0
- package/lib/plugins/context-menu/types.d.ts.map +1 -1
- package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
- package/lib/plugins/editing/editors.d.ts +2 -2
- package/lib/plugins/editing/editors.d.ts.map +1 -1
- package/lib/plugins/editing/index.d.ts +1 -1
- package/lib/plugins/editing/index.d.ts.map +1 -1
- package/lib/plugins/editing/index.js +393 -337
- package/lib/plugins/editing/index.js.map +1 -1
- package/lib/plugins/editing/types.d.ts +50 -23
- package/lib/plugins/editing/types.d.ts.map +1 -1
- package/lib/plugins/export/ExportPlugin.d.ts.map +1 -1
- package/lib/plugins/export/index.js +75 -66
- package/lib/plugins/export/index.js.map +1 -1
- package/lib/plugins/filtering/index.d.ts +1 -1
- package/lib/plugins/filtering/index.d.ts.map +1 -1
- package/lib/plugins/filtering/index.js +9 -9
- package/lib/plugins/filtering/index.js.map +1 -1
- package/lib/plugins/grouping-columns/index.js.map +1 -1
- package/lib/plugins/grouping-rows/index.js.map +1 -1
- package/lib/plugins/master-detail/index.js +57 -56
- package/lib/plugins/master-detail/index.js.map +1 -1
- package/lib/plugins/multi-sort/index.js.map +1 -1
- package/lib/plugins/pinned-columns/index.js.map +1 -1
- package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts +1 -0
- package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -1
- package/lib/plugins/pinned-rows/index.js +118 -87
- package/lib/plugins/pinned-rows/index.js.map +1 -1
- package/lib/plugins/pinned-rows/pinned-rows.d.ts +2 -1
- package/lib/plugins/pinned-rows/pinned-rows.d.ts.map +1 -1
- package/lib/plugins/pinned-rows/types.d.ts +23 -2
- package/lib/plugins/pinned-rows/types.d.ts.map +1 -1
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/print/index.js.map +1 -1
- package/lib/plugins/reorder/index.js.map +1 -1
- package/lib/plugins/responsive/index.js +40 -39
- package/lib/plugins/responsive/index.js.map +1 -1
- package/lib/plugins/row-reorder/index.js.map +1 -1
- package/lib/plugins/selection/SelectionPlugin.d.ts +51 -0
- package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
- package/lib/plugins/selection/index.js +347 -145
- package/lib/plugins/selection/index.js.map +1 -1
- package/lib/plugins/selection/types.d.ts +18 -0
- package/lib/plugins/selection/types.d.ts.map +1 -1
- package/lib/plugins/server-side/index.js.map +1 -1
- package/lib/plugins/shared/data-collection.d.ts +33 -0
- package/lib/plugins/shared/data-collection.d.ts.map +1 -0
- package/lib/plugins/tree/index.js.map +1 -1
- package/lib/plugins/undo-redo/index.js.map +1 -1
- package/lib/plugins/visibility/index.js.map +1 -1
- package/package.json +1 -1
- package/public.d.ts +2 -0
- package/public.d.ts.map +1 -1
- package/themes/dg-theme-bootstrap.css +192 -8
- package/themes/dg-theme-material.css +243 -0
- package/umd/grid.all.umd.js +42 -42
- package/umd/grid.all.umd.js.map +1 -1
- package/umd/grid.umd.js +19 -19
- package/umd/grid.umd.js.map +1 -1
- package/umd/plugins/clipboard.umd.js +5 -5
- package/umd/plugins/clipboard.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 +7 -7
- 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/pinned-rows.umd.js +1 -1
- package/umd/plugins/pinned-rows.umd.js.map +1 -1
- package/umd/plugins/selection.umd.js +2 -2
- package/umd/plugins/selection.umd.js.map +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const b = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>',
|
|
1
|
+
const b = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>', R = {
|
|
2
2
|
expand: "▶",
|
|
3
3
|
collapse: "▼",
|
|
4
4
|
sortAsc: "▲",
|
|
@@ -11,7 +11,7 @@ const b = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentCo
|
|
|
11
11
|
filterActive: b,
|
|
12
12
|
print: "🖨️"
|
|
13
13
|
};
|
|
14
|
-
class
|
|
14
|
+
class x {
|
|
15
15
|
/**
|
|
16
16
|
* Plugin dependencies - declare other plugins this one requires.
|
|
17
17
|
*
|
|
@@ -74,7 +74,7 @@ class v {
|
|
|
74
74
|
* Created fresh in attach(), aborted in detach().
|
|
75
75
|
* This ensures event listeners are properly cleaned up when plugins are re-attached.
|
|
76
76
|
*/
|
|
77
|
-
#
|
|
77
|
+
#e;
|
|
78
78
|
/**
|
|
79
79
|
* Default configuration - subclasses should override this getter.
|
|
80
80
|
* Note: This must be a getter (not property initializer) for proper inheritance
|
|
@@ -83,8 +83,8 @@ class v {
|
|
|
83
83
|
get defaultConfig() {
|
|
84
84
|
return {};
|
|
85
85
|
}
|
|
86
|
-
constructor(
|
|
87
|
-
this.userConfig =
|
|
86
|
+
constructor(e = {}) {
|
|
87
|
+
this.userConfig = e;
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
90
|
* Called when the plugin is attached to a grid.
|
|
@@ -101,8 +101,8 @@ class v {
|
|
|
101
101
|
* }
|
|
102
102
|
* ```
|
|
103
103
|
*/
|
|
104
|
-
attach(
|
|
105
|
-
this.#
|
|
104
|
+
attach(e) {
|
|
105
|
+
this.#e?.abort(), this.#e = new AbortController(), this.grid = e, this.config = { ...this.defaultConfig, ...this.userConfig };
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
108
|
* Called when the plugin is detached from a grid.
|
|
@@ -118,7 +118,7 @@ class v {
|
|
|
118
118
|
* ```
|
|
119
119
|
*/
|
|
120
120
|
detach() {
|
|
121
|
-
this.#
|
|
121
|
+
this.#e?.abort(), this.#e = void 0;
|
|
122
122
|
}
|
|
123
123
|
/**
|
|
124
124
|
* Get another plugin instance from the same grid.
|
|
@@ -132,22 +132,22 @@ class v {
|
|
|
132
132
|
* }
|
|
133
133
|
* ```
|
|
134
134
|
*/
|
|
135
|
-
getPlugin(
|
|
136
|
-
return this.grid?.getPlugin(
|
|
135
|
+
getPlugin(e) {
|
|
136
|
+
return this.grid?.getPlugin(e);
|
|
137
137
|
}
|
|
138
138
|
/**
|
|
139
139
|
* Emit a custom event from the grid.
|
|
140
140
|
*/
|
|
141
|
-
emit(
|
|
142
|
-
this.grid?.dispatchEvent?.(new CustomEvent(
|
|
141
|
+
emit(e, t) {
|
|
142
|
+
this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
|
|
143
143
|
}
|
|
144
144
|
/**
|
|
145
145
|
* Emit a cancelable custom event from the grid.
|
|
146
146
|
* @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
|
|
147
147
|
*/
|
|
148
|
-
emitCancelable(
|
|
149
|
-
const
|
|
150
|
-
return this.grid?.dispatchEvent?.(
|
|
148
|
+
emitCancelable(e, t) {
|
|
149
|
+
const n = new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 });
|
|
150
|
+
return this.grid?.dispatchEvent?.(n), n.defaultPrevented;
|
|
151
151
|
}
|
|
152
152
|
// =========================================================================
|
|
153
153
|
// Event Bus - Plugin-to-Plugin Communication
|
|
@@ -168,8 +168,8 @@ class v {
|
|
|
168
168
|
* });
|
|
169
169
|
* ```
|
|
170
170
|
*/
|
|
171
|
-
on(
|
|
172
|
-
this.grid?._pluginManager?.subscribe(this,
|
|
171
|
+
on(e, t) {
|
|
172
|
+
this.grid?._pluginManager?.subscribe(this, e, t);
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
175
175
|
* Unsubscribe from a plugin event.
|
|
@@ -182,8 +182,8 @@ class v {
|
|
|
182
182
|
* this.off('filter-change');
|
|
183
183
|
* ```
|
|
184
184
|
*/
|
|
185
|
-
off(
|
|
186
|
-
this.grid?._pluginManager?.unsubscribe(this,
|
|
185
|
+
off(e) {
|
|
186
|
+
this.grid?._pluginManager?.unsubscribe(this, e);
|
|
187
187
|
}
|
|
188
188
|
/**
|
|
189
189
|
* Emit an event to other plugins via the Event Bus.
|
|
@@ -203,8 +203,8 @@ class v {
|
|
|
203
203
|
* this.emit('filter-change', { field: 'name', value: 'Alice' });
|
|
204
204
|
* ```
|
|
205
205
|
*/
|
|
206
|
-
emitPluginEvent(
|
|
207
|
-
this.grid?._pluginManager?.emitPluginEvent(
|
|
206
|
+
emitPluginEvent(e, t) {
|
|
207
|
+
this.grid?._pluginManager?.emitPluginEvent(e, t);
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
210
|
* Request a re-render of the grid.
|
|
@@ -293,15 +293,15 @@ class v {
|
|
|
293
293
|
* document.addEventListener('keydown', handler, { signal: this.disconnectSignal });
|
|
294
294
|
*/
|
|
295
295
|
get disconnectSignal() {
|
|
296
|
-
return this.#
|
|
296
|
+
return this.#e?.signal ?? this.grid?.disconnectSignal;
|
|
297
297
|
}
|
|
298
298
|
/**
|
|
299
299
|
* Get the grid-level icons configuration.
|
|
300
300
|
* Returns merged icons (user config + defaults).
|
|
301
301
|
*/
|
|
302
302
|
get gridIcons() {
|
|
303
|
-
const
|
|
304
|
-
return { ...
|
|
303
|
+
const e = this.grid?.gridConfig?.icons ?? {};
|
|
304
|
+
return { ...R, ...e };
|
|
305
305
|
}
|
|
306
306
|
// #region Animation Helpers
|
|
307
307
|
/**
|
|
@@ -321,11 +321,11 @@ class v {
|
|
|
321
321
|
* ```
|
|
322
322
|
*/
|
|
323
323
|
get isAnimationEnabled() {
|
|
324
|
-
const
|
|
325
|
-
if (
|
|
326
|
-
if (
|
|
327
|
-
const
|
|
328
|
-
return
|
|
324
|
+
const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
|
|
325
|
+
if (e === !1 || e === "off") return !1;
|
|
326
|
+
if (e === !0 || e === "on") return !0;
|
|
327
|
+
const t = this.gridElement;
|
|
328
|
+
return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
|
|
329
329
|
}
|
|
330
330
|
/**
|
|
331
331
|
* Get the animation duration in milliseconds from CSS variable.
|
|
@@ -340,10 +340,10 @@ class v {
|
|
|
340
340
|
* ```
|
|
341
341
|
*/
|
|
342
342
|
get animationDuration() {
|
|
343
|
-
const
|
|
344
|
-
if (
|
|
345
|
-
const
|
|
346
|
-
if (!isNaN(
|
|
343
|
+
const e = this.gridElement;
|
|
344
|
+
if (e) {
|
|
345
|
+
const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), n = parseInt(t, 10);
|
|
346
|
+
if (!isNaN(n)) return n;
|
|
347
347
|
}
|
|
348
348
|
return 200;
|
|
349
349
|
}
|
|
@@ -356,8 +356,8 @@ class v {
|
|
|
356
356
|
* @param pluginOverride - Optional plugin-level override
|
|
357
357
|
* @returns The resolved icon value
|
|
358
358
|
*/
|
|
359
|
-
resolveIcon(
|
|
360
|
-
return
|
|
359
|
+
resolveIcon(e, t) {
|
|
360
|
+
return t !== void 0 ? t : this.gridIcons[e];
|
|
361
361
|
}
|
|
362
362
|
/**
|
|
363
363
|
* Set an icon value on an element.
|
|
@@ -366,75 +366,86 @@ class v {
|
|
|
366
366
|
* @param element - The element to set the icon on
|
|
367
367
|
* @param icon - The icon value (string or HTMLElement)
|
|
368
368
|
*/
|
|
369
|
-
setIcon(
|
|
370
|
-
typeof
|
|
369
|
+
setIcon(e, t) {
|
|
370
|
+
typeof t == "string" ? e.innerHTML = t : t instanceof HTMLElement && (e.innerHTML = "", e.appendChild(t.cloneNode(!0)));
|
|
371
371
|
}
|
|
372
372
|
/**
|
|
373
373
|
* Log a warning message.
|
|
374
374
|
*/
|
|
375
|
-
warn(
|
|
376
|
-
console.warn(`[tbw-grid:${this.name}] ${
|
|
375
|
+
warn(e) {
|
|
376
|
+
console.warn(`[tbw-grid:${this.name}] ${e}`);
|
|
377
377
|
}
|
|
378
378
|
// #endregion
|
|
379
379
|
}
|
|
380
|
-
function
|
|
381
|
-
|
|
380
|
+
function C(a, e, t = !0) {
|
|
381
|
+
let n = a;
|
|
382
|
+
if (t && (n = n.filter((s) => !s.hidden && !s.field.startsWith("__") && s.meta?.utility !== !0)), e?.length) {
|
|
383
|
+
const s = new Set(e);
|
|
384
|
+
n = n.filter((r) => s.has(r.field));
|
|
385
|
+
}
|
|
386
|
+
return n;
|
|
387
|
+
}
|
|
388
|
+
function E(a, e) {
|
|
389
|
+
return e?.length ? [...e].sort((t, n) => t - n).map((t) => a[t]).filter((t) => t != null) : a;
|
|
382
390
|
}
|
|
383
|
-
|
|
391
|
+
function I(a) {
|
|
392
|
+
return a == null ? "" : a instanceof Date ? a.toISOString() : typeof a == "object" ? JSON.stringify(a) : String(a);
|
|
393
|
+
}
|
|
394
|
+
async function v(a) {
|
|
384
395
|
try {
|
|
385
|
-
return await navigator.clipboard.writeText(
|
|
396
|
+
return await navigator.clipboard.writeText(a), !0;
|
|
386
397
|
} catch {
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
const
|
|
390
|
-
return document.body.removeChild(
|
|
398
|
+
const e = document.createElement("textarea");
|
|
399
|
+
e.value = a, e.style.position = "fixed", e.style.opacity = "0", e.style.pointerEvents = "none", document.body.appendChild(e), e.select();
|
|
400
|
+
const t = document.execCommand("copy");
|
|
401
|
+
return document.body.removeChild(e), t;
|
|
391
402
|
}
|
|
392
403
|
}
|
|
393
|
-
function y(
|
|
394
|
-
const
|
|
395
|
-
`,
|
|
404
|
+
function y(a, e) {
|
|
405
|
+
const t = e.delimiter ?? " ", n = e.newline ?? `
|
|
406
|
+
`, s = a.replace(/\r\n/g, `
|
|
396
407
|
`).replace(/\r/g, `
|
|
397
|
-
`),
|
|
398
|
-
let
|
|
399
|
-
for (let i = 0; i <
|
|
400
|
-
const
|
|
401
|
-
|
|
408
|
+
`), r = [];
|
|
409
|
+
let o = [], l = "", c = !1;
|
|
410
|
+
for (let i = 0; i < s.length; i++) {
|
|
411
|
+
const d = s[i];
|
|
412
|
+
d === '"' && !c ? c = !0 : d === '"' && c ? s[i + 1] === '"' ? (l += '"', i++) : c = !1 : d === t && !c ? (o.push(l), l = "") : d === n && !c ? (o.push(l), l = "", (o.length > 1 || o.some((u) => u.trim() !== "")) && r.push(o), o = []) : l += d;
|
|
402
413
|
}
|
|
403
|
-
return
|
|
414
|
+
return o.push(l), (o.length > 1 || o.some((i) => i.trim() !== "")) && r.push(o), r;
|
|
404
415
|
}
|
|
405
|
-
async function
|
|
416
|
+
async function S() {
|
|
406
417
|
try {
|
|
407
418
|
return await navigator.clipboard.readText();
|
|
408
419
|
} catch {
|
|
409
420
|
return "";
|
|
410
421
|
}
|
|
411
422
|
}
|
|
412
|
-
function _(
|
|
413
|
-
const { rows:
|
|
414
|
-
if (!
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
423
|
+
function _(a, e) {
|
|
424
|
+
const { rows: t, target: n, fields: s } = a;
|
|
425
|
+
if (!n) return;
|
|
426
|
+
const r = e.rows, o = e.effectiveConfig.columns ?? [], l = o.map((u) => u.field), c = /* @__PURE__ */ new Map();
|
|
427
|
+
o.forEach((u) => {
|
|
428
|
+
c.set(u.field, u.editable === !0);
|
|
418
429
|
});
|
|
419
|
-
const i = [...
|
|
420
|
-
|
|
421
|
-
const
|
|
422
|
-
if (!(
|
|
423
|
-
if (
|
|
424
|
-
if (
|
|
430
|
+
const i = [...r], d = n.bounds ? n.bounds.endRow : 1 / 0;
|
|
431
|
+
t.forEach((u, g) => {
|
|
432
|
+
const f = n.row + g;
|
|
433
|
+
if (!(f > d)) {
|
|
434
|
+
if (n.bounds) {
|
|
435
|
+
if (f >= i.length)
|
|
425
436
|
return;
|
|
426
|
-
} else for (;
|
|
427
|
-
const
|
|
428
|
-
|
|
437
|
+
} else for (; f >= i.length; ) {
|
|
438
|
+
const m = {};
|
|
439
|
+
l.forEach((p) => m[p] = ""), i.push(m);
|
|
429
440
|
}
|
|
430
|
-
i[
|
|
431
|
-
const
|
|
432
|
-
|
|
441
|
+
i[f] = { ...i[f] }, u.forEach((m, p) => {
|
|
442
|
+
const h = s[p];
|
|
443
|
+
h && c.get(h) && (i[f][h] = m);
|
|
433
444
|
});
|
|
434
445
|
}
|
|
435
|
-
}),
|
|
446
|
+
}), e.rows = i;
|
|
436
447
|
}
|
|
437
|
-
class
|
|
448
|
+
class M extends x {
|
|
438
449
|
/**
|
|
439
450
|
* Plugin dependencies - ClipboardPlugin works best with SelectionPlugin.
|
|
440
451
|
*
|
|
@@ -463,10 +474,10 @@ class D extends v {
|
|
|
463
474
|
// #endregion
|
|
464
475
|
// #region Lifecycle
|
|
465
476
|
/** @internal */
|
|
466
|
-
attach(
|
|
467
|
-
super.attach(
|
|
477
|
+
attach(e) {
|
|
478
|
+
super.attach(e), e.addEventListener(
|
|
468
479
|
"paste",
|
|
469
|
-
(
|
|
480
|
+
(t) => this.#r(t),
|
|
470
481
|
{ signal: this.disconnectSignal }
|
|
471
482
|
);
|
|
472
483
|
}
|
|
@@ -477,51 +488,28 @@ class D extends v {
|
|
|
477
488
|
// #endregion
|
|
478
489
|
// #region Event Handlers
|
|
479
490
|
/** @internal */
|
|
480
|
-
onKeyDown(
|
|
481
|
-
return (
|
|
491
|
+
onKeyDown(e) {
|
|
492
|
+
return (e.ctrlKey || e.metaKey) && e.key === "c" ? (this.#e(e.target), !0) : !1;
|
|
482
493
|
}
|
|
483
494
|
// #endregion
|
|
484
495
|
// #region Private Methods
|
|
485
496
|
/**
|
|
486
|
-
* Handle copy operation.
|
|
497
|
+
* Handle copy operation from keyboard shortcut.
|
|
487
498
|
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
startRow: i.from.row,
|
|
501
|
-
startCol: 0,
|
|
502
|
-
endRow: i.to.row,
|
|
503
|
-
endCol: o
|
|
504
|
-
} : n = {
|
|
505
|
-
startRow: i.from.row,
|
|
506
|
-
startCol: i.from.col,
|
|
507
|
-
endRow: i.to.row,
|
|
508
|
-
endCol: i.to.col
|
|
509
|
-
};
|
|
510
|
-
} else if (!e)
|
|
511
|
-
n = { startRow: 0, startCol: 0, endRow: l, endCol: o };
|
|
512
|
-
else {
|
|
513
|
-
const r = this.#r(t);
|
|
514
|
-
if (!r) return;
|
|
515
|
-
n = { startRow: r.row, startCol: r.col, endRow: r.row, endCol: r.col };
|
|
499
|
+
* For keyboard-triggered copies, respects the current selection or
|
|
500
|
+
* falls back to the focused cell from the DOM.
|
|
501
|
+
*/
|
|
502
|
+
#e(e) {
|
|
503
|
+
const t = this.#t();
|
|
504
|
+
if (t && t.ranges.length === 0) {
|
|
505
|
+
const n = this.#o(e);
|
|
506
|
+
if (!n) return;
|
|
507
|
+
const s = this.columns[n.col];
|
|
508
|
+
if (!s) return;
|
|
509
|
+
this.copy({ rowIndices: [n.row], columns: [s.field] });
|
|
510
|
+
return;
|
|
516
511
|
}
|
|
517
|
-
|
|
518
|
-
R(s.text).then(() => {
|
|
519
|
-
this.lastCopied = { text: s.text, timestamp: Date.now() }, this.emit("copy", {
|
|
520
|
-
text: s.text,
|
|
521
|
-
rowCount: s.rowCount,
|
|
522
|
-
columnCount: s.columnCount
|
|
523
|
-
});
|
|
524
|
-
});
|
|
512
|
+
this.copy();
|
|
525
513
|
}
|
|
526
514
|
/**
|
|
527
515
|
* Handle native paste event (preferred method - works in iframes).
|
|
@@ -538,17 +526,17 @@ class D extends v {
|
|
|
538
526
|
* - Range/row: paste is clipped to fit within selection bounds
|
|
539
527
|
* - No selection: paste starts at row 0, col 0
|
|
540
528
|
*/
|
|
541
|
-
#
|
|
542
|
-
const
|
|
543
|
-
if (!
|
|
544
|
-
|
|
545
|
-
const
|
|
546
|
-
for (let
|
|
547
|
-
const
|
|
548
|
-
|
|
529
|
+
#r(e) {
|
|
530
|
+
const t = e.clipboardData?.getData("text/plain");
|
|
531
|
+
if (!t) return;
|
|
532
|
+
e.preventDefault();
|
|
533
|
+
const n = y(t, this.config), s = this.#t(), r = s?.ranges?.[0], o = r?.from.row ?? 0, l = r?.from.col ?? 0, i = r && (s?.mode === "range" || s?.mode === "row") && (r.from.row !== r.to.row || r.from.col !== r.to.col) ? { endRow: r.to.row, endCol: r.to.col } : null, d = i?.endCol ?? this.columns.length - 1, u = this.columns[l], g = u ? { row: o, col: l, field: u.field, bounds: i } : null, f = [], m = n[0]?.length ?? 0;
|
|
534
|
+
for (let h = 0; h < m && l + h <= d; h++) {
|
|
535
|
+
const w = this.columns[l + h];
|
|
536
|
+
w && !w.hidden && f.push(w.field);
|
|
549
537
|
}
|
|
550
|
-
const
|
|
551
|
-
this.emit("paste",
|
|
538
|
+
const p = { rows: n, text: t, target: g, fields: f };
|
|
539
|
+
this.emit("paste", p), this.#i(p);
|
|
552
540
|
}
|
|
553
541
|
/**
|
|
554
542
|
* Apply the paste handler to update grid data.
|
|
@@ -556,102 +544,179 @@ class D extends v {
|
|
|
556
544
|
* Uses the configured `pasteHandler`, or the default handler if not specified.
|
|
557
545
|
* Set `pasteHandler: null` in config to disable auto-paste.
|
|
558
546
|
*/
|
|
559
|
-
#
|
|
547
|
+
#i(e) {
|
|
560
548
|
if (!this.grid) return;
|
|
561
|
-
const { pasteHandler:
|
|
562
|
-
if (
|
|
563
|
-
(
|
|
549
|
+
const { pasteHandler: t } = this.config;
|
|
550
|
+
if (t === null) return;
|
|
551
|
+
(t ?? _)(e, this.grid);
|
|
564
552
|
}
|
|
565
553
|
/**
|
|
566
554
|
* Get the current selection via Query System.
|
|
567
555
|
* Returns undefined if no selection plugin is loaded or nothing is selected.
|
|
568
556
|
*/
|
|
569
|
-
#
|
|
570
|
-
return this.grid?.query("getSelection"
|
|
557
|
+
#t() {
|
|
558
|
+
return this.grid?.query("getSelection")?.[0];
|
|
571
559
|
}
|
|
572
560
|
/**
|
|
573
|
-
*
|
|
574
|
-
*
|
|
561
|
+
* Resolve columns and rows to include based on options and/or current selection.
|
|
562
|
+
*
|
|
563
|
+
* Priority for columns:
|
|
564
|
+
* 1. `options.columns` (explicit field list)
|
|
565
|
+
* 2. Selection range column bounds (range/cell mode only)
|
|
566
|
+
* 3. All visible non-utility columns
|
|
567
|
+
*
|
|
568
|
+
* Priority for rows:
|
|
569
|
+
* 1. `options.rowIndices` (explicit indices)
|
|
570
|
+
* 2. Selection range row bounds
|
|
571
|
+
* 3. All rows
|
|
575
572
|
*/
|
|
576
|
-
#n(
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
if (
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
573
|
+
#n(e) {
|
|
574
|
+
const t = this.#t();
|
|
575
|
+
let n;
|
|
576
|
+
if (e?.columns)
|
|
577
|
+
n = C(this.columns, e.columns);
|
|
578
|
+
else if (t?.ranges.length && t.mode !== "row") {
|
|
579
|
+
const r = t.ranges[t.ranges.length - 1], o = Math.min(r.from.col, r.to.col), l = Math.max(r.from.col, r.to.col);
|
|
580
|
+
n = C(this.columns.slice(o, l + 1));
|
|
581
|
+
} else
|
|
582
|
+
n = C(this.columns);
|
|
583
|
+
let s;
|
|
584
|
+
if (e?.rowIndices)
|
|
585
|
+
s = E(this.rows, e.rowIndices);
|
|
586
|
+
else if (t?.ranges.length) {
|
|
587
|
+
const r = t.ranges[t.ranges.length - 1], o = Math.min(r.from.row, r.to.row), l = Math.max(r.from.row, r.to.row);
|
|
588
|
+
s = [];
|
|
589
|
+
for (let c = o; c <= l; c++) {
|
|
590
|
+
const i = this.rows[c];
|
|
591
|
+
i && s.push(i);
|
|
592
|
+
}
|
|
593
|
+
} else
|
|
594
|
+
s = this.rows;
|
|
595
|
+
return { columns: n, rows: s };
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Build delimited text from resolved columns and rows.
|
|
599
|
+
*/
|
|
600
|
+
#s(e, t, n) {
|
|
601
|
+
const s = n?.delimiter ?? this.config.delimiter ?? " ", r = n?.newline ?? this.config.newline ?? `
|
|
602
|
+
`, o = n?.includeHeaders ?? this.config.includeHeaders ?? !1, l = n?.processCell ?? this.config.processCell, c = [];
|
|
603
|
+
o && c.push(e.map((i) => i.header || i.field).join(s));
|
|
604
|
+
for (const i of t) {
|
|
605
|
+
const d = e.map((u) => {
|
|
606
|
+
const g = i[u.field];
|
|
607
|
+
return l ? l(g, u.field, i) : I(g);
|
|
589
608
|
});
|
|
590
|
-
|
|
609
|
+
c.push(d.join(s));
|
|
591
610
|
}
|
|
592
|
-
return
|
|
593
|
-
text: w.join(d),
|
|
594
|
-
rowCount: r - s + 1,
|
|
595
|
-
columnCount: i - a + 1
|
|
596
|
-
};
|
|
611
|
+
return c.join(r);
|
|
597
612
|
}
|
|
598
613
|
/**
|
|
599
614
|
* Get focused cell coordinates from DOM.
|
|
600
615
|
* Used as fallback when SelectionPlugin has no selection.
|
|
601
616
|
*/
|
|
602
|
-
#
|
|
603
|
-
const
|
|
604
|
-
if (!
|
|
605
|
-
const
|
|
606
|
-
if (!
|
|
607
|
-
const
|
|
608
|
-
if (isNaN(
|
|
609
|
-
const
|
|
610
|
-
return
|
|
617
|
+
#o(e) {
|
|
618
|
+
const t = e.closest("[data-field-cache]");
|
|
619
|
+
if (!t) return null;
|
|
620
|
+
const n = t.dataset.fieldCache, s = t.dataset.row;
|
|
621
|
+
if (!n || !s) return null;
|
|
622
|
+
const r = parseInt(s, 10);
|
|
623
|
+
if (isNaN(r)) return null;
|
|
624
|
+
const o = this.columns.findIndex((l) => l.field === n);
|
|
625
|
+
return o === -1 ? null : { row: r, col: o };
|
|
611
626
|
}
|
|
612
627
|
// #endregion
|
|
613
628
|
// #region Public API
|
|
614
629
|
/**
|
|
615
|
-
*
|
|
630
|
+
* Get the text representation of the current selection (or specified data)
|
|
631
|
+
* without writing to the system clipboard.
|
|
632
|
+
*
|
|
633
|
+
* Useful for previewing what would be copied, or for feeding the text into
|
|
634
|
+
* a custom UI (e.g., a "copy with column picker" dialog).
|
|
635
|
+
*
|
|
636
|
+
* @param options - Control which columns/rows to include
|
|
637
|
+
* @returns Delimited text, or empty string if nothing to copy
|
|
638
|
+
*
|
|
639
|
+
* @example Get text for specific columns
|
|
640
|
+
* ```ts
|
|
641
|
+
* const clipboard = grid.getPlugin(ClipboardPlugin);
|
|
642
|
+
* const text = clipboard.getSelectionAsText({
|
|
643
|
+
* columns: ['name', 'email'],
|
|
644
|
+
* includeHeaders: true,
|
|
645
|
+
* });
|
|
646
|
+
* console.log(text);
|
|
647
|
+
* // "Name\tEmail\nAlice\talice@example.com\n..."
|
|
648
|
+
* ```
|
|
649
|
+
*/
|
|
650
|
+
getSelectionAsText(e) {
|
|
651
|
+
const { columns: t, rows: n } = this.#n(e);
|
|
652
|
+
return t.length === 0 || n.length === 0 ? "" : this.#s(t, n, e);
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Copy data to the system clipboard.
|
|
656
|
+
*
|
|
657
|
+
* Without options, copies the current selection (or entire grid if no selection).
|
|
658
|
+
* With options, copies exactly the specified columns and/or rows — ideal for
|
|
659
|
+
* "copy with column picker" workflows where the user selects rows first,
|
|
660
|
+
* then chooses which columns to include via a dialog.
|
|
661
|
+
*
|
|
662
|
+
* @param options - Control which columns/rows to include
|
|
616
663
|
* @returns The copied text
|
|
664
|
+
*
|
|
665
|
+
* @example Copy current selection (default)
|
|
666
|
+
* ```ts
|
|
667
|
+
* const clipboard = grid.getPlugin(ClipboardPlugin);
|
|
668
|
+
* await clipboard.copy();
|
|
669
|
+
* ```
|
|
670
|
+
*
|
|
671
|
+
* @example Copy specific columns from specific rows
|
|
672
|
+
* ```ts
|
|
673
|
+
* // User selected rows in the grid, then picked columns in a dialog
|
|
674
|
+
* const selectedRowIndices = [0, 3, 7];
|
|
675
|
+
* const chosenColumns = ['name', 'department', 'salary'];
|
|
676
|
+
* await clipboard.copy({
|
|
677
|
+
* rowIndices: selectedRowIndices,
|
|
678
|
+
* columns: chosenColumns,
|
|
679
|
+
* includeHeaders: true,
|
|
680
|
+
* });
|
|
681
|
+
* ```
|
|
617
682
|
*/
|
|
618
|
-
async copy() {
|
|
619
|
-
const t = this.#e
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
endCol: n.to.col
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
const l = this.#n(o);
|
|
631
|
-
return await R(l.text), this.lastCopied = { text: l.text, timestamp: Date.now() }, l.text;
|
|
683
|
+
async copy(e) {
|
|
684
|
+
const { columns: t, rows: n } = this.#n(e);
|
|
685
|
+
if (t.length === 0 || n.length === 0) return "";
|
|
686
|
+
const s = this.#s(t, n, e);
|
|
687
|
+
return await v(s), this.lastCopied = { text: s, timestamp: Date.now() }, this.emit("copy", {
|
|
688
|
+
text: s,
|
|
689
|
+
rowCount: n.length,
|
|
690
|
+
columnCount: t.length
|
|
691
|
+
}), s;
|
|
632
692
|
}
|
|
633
693
|
/**
|
|
634
694
|
* Copy specific rows by index to clipboard.
|
|
695
|
+
*
|
|
696
|
+
* Convenience wrapper around {@link copy} for row-based workflows.
|
|
697
|
+
* Supports non-contiguous row indices (e.g., `[0, 3, 7]`).
|
|
698
|
+
*
|
|
635
699
|
* @param indices - Array of row indices to copy
|
|
700
|
+
* @param options - Additional copy options (columns, headers, etc.)
|
|
636
701
|
* @returns The copied text
|
|
702
|
+
*
|
|
703
|
+
* @example
|
|
704
|
+
* ```ts
|
|
705
|
+
* const clipboard = grid.getPlugin(ClipboardPlugin);
|
|
706
|
+
* // Copy only rows 0 and 5, including just name and email columns
|
|
707
|
+
* await clipboard.copyRows([0, 5], { columns: ['name', 'email'] });
|
|
708
|
+
* ```
|
|
637
709
|
*/
|
|
638
|
-
async copyRows(t) {
|
|
639
|
-
|
|
640
|
-
const e = [...t].sort((s, r) => s - r), o = this.columns.length - 1, l = {
|
|
641
|
-
startRow: e[0],
|
|
642
|
-
startCol: 0,
|
|
643
|
-
endRow: e[e.length - 1],
|
|
644
|
-
endCol: o
|
|
645
|
-
}, n = this.#n(l);
|
|
646
|
-
return await R(n.text), this.lastCopied = { text: n.text, timestamp: Date.now() }, n.text;
|
|
710
|
+
async copyRows(e, t) {
|
|
711
|
+
return e.length === 0 ? "" : this.copy({ ...t, rowIndices: e });
|
|
647
712
|
}
|
|
648
713
|
/**
|
|
649
714
|
* Read and parse clipboard content.
|
|
650
715
|
* @returns Parsed 2D array of cell values, or null if clipboard is empty
|
|
651
716
|
*/
|
|
652
717
|
async paste() {
|
|
653
|
-
const
|
|
654
|
-
return
|
|
718
|
+
const e = await S();
|
|
719
|
+
return e ? y(e, this.config) : null;
|
|
655
720
|
}
|
|
656
721
|
/**
|
|
657
722
|
* Get the last copied text and timestamp.
|
|
@@ -663,7 +728,7 @@ class D extends v {
|
|
|
663
728
|
// #endregion
|
|
664
729
|
}
|
|
665
730
|
export {
|
|
666
|
-
|
|
731
|
+
M as ClipboardPlugin,
|
|
667
732
|
_ as defaultPasteHandler
|
|
668
733
|
};
|
|
669
734
|
//# sourceMappingURL=index.js.map
|