@toolbox-web/grid 0.0.7 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/all.d.ts +156 -95
- package/all.js +1561 -1502
- package/all.js.map +1 -1
- package/custom-elements.json +89 -7
- package/index.d.ts +68 -23
- package/index.js +1617 -1388
- package/index.js.map +1 -1
- package/lib/plugins/clipboard/index.js +48 -49
- package/lib/plugins/clipboard/index.js.map +1 -1
- package/lib/plugins/column-virtualization/index.js +6 -6
- package/lib/plugins/column-virtualization/index.js.map +1 -1
- package/lib/plugins/context-menu/index.js +64 -109
- package/lib/plugins/context-menu/index.js.map +1 -1
- package/lib/plugins/export/index.js +7 -7
- package/lib/plugins/export/index.js.map +1 -1
- package/lib/plugins/filtering/index.js +5 -38
- package/lib/plugins/filtering/index.js.map +1 -1
- package/lib/plugins/grouping-columns/index.js +4 -32
- package/lib/plugins/grouping-columns/index.js.map +1 -1
- package/lib/plugins/grouping-rows/index.js +8 -45
- package/lib/plugins/grouping-rows/index.js.map +1 -1
- package/lib/plugins/master-detail/index.js +7 -31
- package/lib/plugins/master-detail/index.js.map +1 -1
- package/lib/plugins/multi-sort/index.js +19 -42
- package/lib/plugins/multi-sort/index.js.map +1 -1
- package/lib/plugins/pinned-columns/index.js +5 -6
- package/lib/plugins/pinned-columns/index.js.map +1 -1
- package/lib/plugins/pinned-rows/index.js +14 -88
- package/lib/plugins/pinned-rows/index.js.map +1 -1
- package/lib/plugins/pivot/index.js +673 -145
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/reorder/index.js +22 -51
- package/lib/plugins/reorder/index.js.map +1 -1
- package/lib/plugins/selection/index.js +76 -83
- package/lib/plugins/selection/index.js.map +1 -1
- package/lib/plugins/server-side/index.js +2 -2
- package/lib/plugins/server-side/index.js.map +1 -1
- package/lib/plugins/tree/index.js +6 -14
- package/lib/plugins/tree/index.js.map +1 -1
- package/lib/plugins/undo-redo/index.js +2 -3
- package/lib/plugins/undo-redo/index.js.map +1 -1
- package/lib/plugins/visibility/index.js +13 -105
- package/lib/plugins/visibility/index.js.map +1 -1
- package/package.json +1 -1
- package/themes/dg-theme-bootstrap.css +73 -0
- package/themes/dg-theme-material.css +71 -0
- package/umd/grid.all.umd.js +43 -469
- package/umd/grid.all.umd.js.map +1 -1
- package/umd/grid.umd.js +35 -66
- package/umd/grid.umd.js.map +1 -1
- package/umd/plugins/clipboard.umd.js +4 -4
- 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 -52
- package/umd/plugins/context-menu.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 +2 -34
- package/umd/plugins/filtering.umd.js.map +1 -1
- package/umd/plugins/grouping-columns.umd.js +1 -28
- package/umd/plugins/grouping-columns.umd.js.map +1 -1
- package/umd/plugins/grouping-rows.umd.js +1 -39
- package/umd/plugins/grouping-rows.umd.js.map +1 -1
- package/umd/plugins/master-detail.umd.js +1 -26
- package/umd/plugins/master-detail.umd.js.map +1 -1
- package/umd/plugins/multi-sort.umd.js +1 -25
- 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 -72
- package/umd/plugins/pinned-rows.umd.js.map +1 -1
- package/umd/plugins/pivot.umd.js +1 -7
- package/umd/plugins/pivot.umd.js.map +1 -1
- package/umd/plugins/reorder.umd.js +1 -30
- package/umd/plugins/reorder.umd.js.map +1 -1
- package/umd/plugins/selection.umd.js +1 -33
- 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 -10
- 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 -93
- package/umd/plugins/visibility.umd.js.map +1 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
const
|
|
1
|
+
const y = {
|
|
2
2
|
expand: "▶",
|
|
3
3
|
collapse: "▼",
|
|
4
4
|
sortAsc: "▲",
|
|
5
5
|
sortDesc: "▼",
|
|
6
6
|
sortNone: "⇅",
|
|
7
7
|
submenuArrow: "▶",
|
|
8
|
-
dragHandle: "⋮⋮"
|
|
8
|
+
dragHandle: "⋮⋮",
|
|
9
|
+
toolPanel: "☰"
|
|
9
10
|
};
|
|
10
|
-
class
|
|
11
|
+
class C {
|
|
11
12
|
/** Plugin version - override in subclass if needed */
|
|
12
13
|
version = "1.0.0";
|
|
13
14
|
/** CSS styles to inject into the grid's shadow DOM */
|
|
@@ -132,7 +133,7 @@ class y {
|
|
|
132
133
|
*/
|
|
133
134
|
get gridIcons() {
|
|
134
135
|
const e = this.grid?.gridConfig?.icons ?? {};
|
|
135
|
-
return { ...
|
|
136
|
+
return { ...y, ...e };
|
|
136
137
|
}
|
|
137
138
|
/**
|
|
138
139
|
* Resolve an icon value to string or HTMLElement.
|
|
@@ -162,109 +163,59 @@ class y {
|
|
|
162
163
|
console.warn(`[tbw-grid:${this.name}] ${e}`);
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
|
-
|
|
166
|
+
const I = ".tbw-context-menu{position:fixed;background:light-dark(#f5f5f5,#2a2a2a);color:light-dark(#222,#eee);border:1px solid light-dark(#d0d0d4,#454545);border-radius:4px;box-shadow:0 2px 10px #00000026;min-width:160px;padding:4px 0;z-index:10000;font-size:13px;font-family:system-ui,sans-serif}.tbw-context-menu-item{display:flex;align-items:center;padding:6px 12px;cursor:pointer;gap:8px}.tbw-context-menu-item:hover:not(.disabled){background:light-dark(#e8e8e8,#3a3a3a)}.tbw-context-menu-item.disabled{opacity:.5;cursor:default}.tbw-context-menu-item.danger{color:light-dark(#c00,#f66)}.tbw-context-menu-icon{width:16px;text-align:center}.tbw-context-menu-label{flex:1}.tbw-context-menu-shortcut{color:light-dark(#888,#888);font-size:11px}.tbw-context-menu-arrow{font-size:10px;color:light-dark(#888,#888)}.tbw-context-menu-separator{height:1px;background:light-dark(#d0d0d4,#454545);margin:4px 0}";
|
|
167
|
+
function x(s, e) {
|
|
166
168
|
return (typeof s == "function" ? s(e) : s).filter((i) => !(i.hidden === !0 || typeof i.hidden == "function" && i.hidden(e)));
|
|
167
169
|
}
|
|
168
|
-
function
|
|
170
|
+
function M(s, e) {
|
|
169
171
|
return s.disabled === !0 ? !0 : typeof s.disabled == "function" ? s.disabled(e) : !1;
|
|
170
172
|
}
|
|
171
|
-
function
|
|
172
|
-
const
|
|
173
|
-
|
|
173
|
+
function w(s, e, n, i = y.submenuArrow) {
|
|
174
|
+
const r = document.createElement("div");
|
|
175
|
+
r.className = "tbw-context-menu", r.setAttribute("role", "menu");
|
|
174
176
|
for (const o of s) {
|
|
175
177
|
if (o.separator) {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
+
const l = document.createElement("div");
|
|
179
|
+
l.className = "tbw-context-menu-separator", l.setAttribute("role", "separator"), r.appendChild(l);
|
|
178
180
|
continue;
|
|
179
181
|
}
|
|
180
182
|
const t = document.createElement("div");
|
|
181
183
|
t.className = "tbw-context-menu-item", o.cssClass && t.classList.add(o.cssClass), t.setAttribute("role", "menuitem"), t.setAttribute("data-id", o.id);
|
|
182
|
-
const c =
|
|
184
|
+
const c = M(o, e);
|
|
183
185
|
if (c && (t.classList.add("disabled"), t.setAttribute("aria-disabled", "true")), o.icon) {
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
+
const l = document.createElement("span");
|
|
187
|
+
l.className = "tbw-context-menu-icon", l.innerHTML = o.icon, t.appendChild(l);
|
|
186
188
|
}
|
|
187
189
|
const d = document.createElement("span");
|
|
188
190
|
if (d.className = "tbw-context-menu-label", d.textContent = o.name, t.appendChild(d), o.shortcut) {
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
+
const l = document.createElement("span");
|
|
192
|
+
l.className = "tbw-context-menu-shortcut", l.textContent = o.shortcut, t.appendChild(l);
|
|
191
193
|
}
|
|
192
194
|
if (o.subMenu?.length) {
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
+
const l = document.createElement("span");
|
|
196
|
+
l.className = "tbw-context-menu-arrow", typeof i == "string" ? l.innerHTML = i : i instanceof HTMLElement && l.appendChild(i.cloneNode(!0)), t.appendChild(l), t.addEventListener("mouseenter", () => {
|
|
195
197
|
if (t.querySelector(".tbw-context-menu") || !o.subMenu) return;
|
|
196
|
-
const
|
|
198
|
+
const h = x(o.subMenu, e), a = w(h, e, n, i);
|
|
197
199
|
a.classList.add("tbw-context-submenu"), a.style.position = "absolute", a.style.left = "100%", a.style.top = "0", t.style.position = "relative", t.appendChild(a);
|
|
198
200
|
}), t.addEventListener("mouseleave", () => {
|
|
199
201
|
const u = t.querySelector(".tbw-context-menu");
|
|
200
202
|
u && u.remove();
|
|
201
203
|
});
|
|
202
204
|
}
|
|
203
|
-
!c && o.action && !o.subMenu && t.addEventListener("click", (
|
|
204
|
-
|
|
205
|
-
}),
|
|
205
|
+
!c && o.action && !o.subMenu && t.addEventListener("click", (l) => {
|
|
206
|
+
l.stopPropagation(), n(o);
|
|
207
|
+
}), r.appendChild(t);
|
|
206
208
|
}
|
|
207
|
-
return
|
|
209
|
+
return r;
|
|
208
210
|
}
|
|
209
211
|
function E(s, e, n) {
|
|
210
212
|
s.style.position = "fixed", s.style.left = `${e}px`, s.style.top = `${n}px`, s.style.visibility = "hidden", s.style.zIndex = "10000";
|
|
211
|
-
const i = s.getBoundingClientRect(),
|
|
213
|
+
const i = s.getBoundingClientRect(), r = window.innerWidth, o = window.innerHeight;
|
|
212
214
|
let t = e, c = n;
|
|
213
|
-
e + i.width >
|
|
215
|
+
e + i.width > r && (t = e - i.width), n + i.height > o && (c = n - i.height), t = Math.max(0, t), c = Math.max(0, c), s.style.left = `${t}px`, s.style.top = `${c}px`, s.style.visibility = "visible";
|
|
214
216
|
}
|
|
215
|
-
let f = null, p = null,
|
|
216
|
-
const
|
|
217
|
-
.tbw-context-menu {
|
|
218
|
-
position: fixed;
|
|
219
|
-
background: light-dark(#f5f5f5, #2a2a2a);
|
|
220
|
-
color: light-dark(#222, #eee);
|
|
221
|
-
border: 1px solid light-dark(#d0d0d4, #454545);
|
|
222
|
-
border-radius: 4px;
|
|
223
|
-
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
|
|
224
|
-
min-width: 160px;
|
|
225
|
-
padding: 4px 0;
|
|
226
|
-
z-index: 10000;
|
|
227
|
-
font-size: 13px;
|
|
228
|
-
font-family: system-ui, sans-serif;
|
|
229
|
-
}
|
|
230
|
-
.tbw-context-menu-item {
|
|
231
|
-
display: flex;
|
|
232
|
-
align-items: center;
|
|
233
|
-
padding: 6px 12px;
|
|
234
|
-
cursor: pointer;
|
|
235
|
-
gap: 8px;
|
|
236
|
-
}
|
|
237
|
-
.tbw-context-menu-item:hover:not(.disabled) {
|
|
238
|
-
background: light-dark(#e8e8e8, #3a3a3a);
|
|
239
|
-
}
|
|
240
|
-
.tbw-context-menu-item.disabled {
|
|
241
|
-
opacity: 0.5;
|
|
242
|
-
cursor: default;
|
|
243
|
-
}
|
|
244
|
-
.tbw-context-menu-item.danger {
|
|
245
|
-
color: light-dark(#c00, #f66);
|
|
246
|
-
}
|
|
247
|
-
.tbw-context-menu-icon {
|
|
248
|
-
width: 16px;
|
|
249
|
-
text-align: center;
|
|
250
|
-
}
|
|
251
|
-
.tbw-context-menu-label {
|
|
252
|
-
flex: 1;
|
|
253
|
-
}
|
|
254
|
-
.tbw-context-menu-shortcut {
|
|
255
|
-
color: light-dark(#888, #888);
|
|
256
|
-
font-size: 11px;
|
|
257
|
-
}
|
|
258
|
-
.tbw-context-menu-arrow {
|
|
259
|
-
font-size: 10px;
|
|
260
|
-
color: light-dark(#888, #888);
|
|
261
|
-
}
|
|
262
|
-
.tbw-context-menu-separator {
|
|
263
|
-
height: 1px;
|
|
264
|
-
background: light-dark(#d0d0d4, #454545);
|
|
265
|
-
margin: 4px 0;
|
|
266
|
-
}
|
|
267
|
-
`, g = [
|
|
217
|
+
let f = null, p = null, m = null, g = 0;
|
|
218
|
+
const b = [
|
|
268
219
|
{
|
|
269
220
|
id: "copy",
|
|
270
221
|
name: "Copy",
|
|
@@ -282,13 +233,12 @@ const I = `
|
|
|
282
233
|
}
|
|
283
234
|
}
|
|
284
235
|
];
|
|
285
|
-
class
|
|
236
|
+
class H extends C {
|
|
286
237
|
name = "contextMenu";
|
|
287
238
|
version = "1.0.0";
|
|
288
239
|
get defaultConfig() {
|
|
289
240
|
return {
|
|
290
|
-
|
|
291
|
-
items: g
|
|
241
|
+
items: b
|
|
292
242
|
};
|
|
293
243
|
}
|
|
294
244
|
// ===== Internal State =====
|
|
@@ -298,67 +248,72 @@ class M extends y {
|
|
|
298
248
|
menuElement = null;
|
|
299
249
|
// ===== Lifecycle =====
|
|
300
250
|
attach(e) {
|
|
301
|
-
super.attach(e), this.installGlobalHandlers()
|
|
251
|
+
super.attach(e), this.installGlobalHandlers(), g++;
|
|
302
252
|
}
|
|
303
253
|
detach() {
|
|
304
|
-
this.menuElement && (this.menuElement.remove(), this.menuElement = null), this.isOpen = !1, this.params = null;
|
|
254
|
+
this.menuElement && (this.menuElement.remove(), this.menuElement = null), this.isOpen = !1, this.params = null, this.uninstallGlobalHandlers();
|
|
305
255
|
}
|
|
306
256
|
// ===== Private Methods =====
|
|
307
257
|
installGlobalHandlers() {
|
|
308
|
-
!
|
|
258
|
+
!m && typeof document < "u" && (m = document.createElement("style"), m.id = "tbw-context-menu-styles", m.textContent = I, document.head.appendChild(m)), f || (f = () => {
|
|
309
259
|
document.querySelectorAll(".tbw-context-menu").forEach((n) => n.remove());
|
|
310
260
|
}, document.addEventListener("click", f)), p || (p = (e) => {
|
|
311
261
|
e.key === "Escape" && document.querySelectorAll(".tbw-context-menu").forEach((i) => i.remove());
|
|
312
262
|
}, document.addEventListener("keydown", p));
|
|
313
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Clean up global handlers when the last instance detaches.
|
|
266
|
+
* Uses reference counting to ensure handlers persist while any grid uses the plugin.
|
|
267
|
+
*/
|
|
268
|
+
uninstallGlobalHandlers() {
|
|
269
|
+
g--, !(g > 0) && (f && (document.removeEventListener("click", f), f = null), p && (document.removeEventListener("keydown", p), p = null), m && (m.remove(), m = null));
|
|
270
|
+
}
|
|
314
271
|
// ===== Hooks =====
|
|
315
272
|
afterRender() {
|
|
316
|
-
if (!this.config.enabled) return;
|
|
317
273
|
const e = this.shadowRoot;
|
|
318
274
|
if (!e) return;
|
|
319
275
|
const n = e.children[0];
|
|
320
276
|
n && n.getAttribute("data-context-menu-bound") !== "true" && (n.setAttribute("data-context-menu-bound", "true"), n.addEventListener("contextmenu", (i) => {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
const o = l.target, t = o.closest("[data-row][data-col]"), c = o.closest(".header-cell");
|
|
277
|
+
const r = i;
|
|
278
|
+
r.preventDefault();
|
|
279
|
+
const o = r.target, t = o.closest("[data-row][data-col]"), c = o.closest(".header-cell");
|
|
325
280
|
let d;
|
|
326
281
|
if (t) {
|
|
327
|
-
const u = parseInt(t.getAttribute("data-row") ?? "-1", 10),
|
|
282
|
+
const u = parseInt(t.getAttribute("data-row") ?? "-1", 10), h = parseInt(t.getAttribute("data-col") ?? "-1", 10), a = this.columns[h], v = this.rows[u];
|
|
328
283
|
d = {
|
|
329
|
-
row:
|
|
284
|
+
row: v,
|
|
330
285
|
rowIndex: u,
|
|
331
286
|
column: a,
|
|
332
|
-
columnIndex:
|
|
287
|
+
columnIndex: h,
|
|
333
288
|
field: a?.field ?? "",
|
|
334
|
-
value:
|
|
289
|
+
value: v?.[a?.field] ?? null,
|
|
335
290
|
isHeader: !1,
|
|
336
|
-
event:
|
|
291
|
+
event: r
|
|
337
292
|
};
|
|
338
293
|
} else if (c) {
|
|
339
|
-
const u = parseInt(c.getAttribute("data-col") ?? "-1", 10),
|
|
294
|
+
const u = parseInt(c.getAttribute("data-col") ?? "-1", 10), h = this.columns[u];
|
|
340
295
|
d = {
|
|
341
296
|
row: null,
|
|
342
297
|
rowIndex: -1,
|
|
343
|
-
column:
|
|
298
|
+
column: h,
|
|
344
299
|
columnIndex: u,
|
|
345
|
-
field:
|
|
300
|
+
field: h?.field ?? "",
|
|
346
301
|
value: null,
|
|
347
302
|
isHeader: !0,
|
|
348
|
-
event:
|
|
303
|
+
event: r
|
|
349
304
|
};
|
|
350
305
|
} else
|
|
351
306
|
return;
|
|
352
|
-
this.params = d, this.position = { x:
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
307
|
+
this.params = d, this.position = { x: r.clientX, y: r.clientY };
|
|
308
|
+
const l = x(this.config.items ?? b, d);
|
|
309
|
+
l.length && (this.menuElement && this.menuElement.remove(), this.menuElement = w(
|
|
310
|
+
l,
|
|
356
311
|
d,
|
|
357
312
|
(u) => {
|
|
358
313
|
u.action && u.action(d), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
|
|
359
314
|
},
|
|
360
315
|
this.gridIcons.submenuArrow
|
|
361
|
-
), document.body.appendChild(this.menuElement), E(this.menuElement,
|
|
316
|
+
), document.body.appendChild(this.menuElement), E(this.menuElement, r.clientX, r.clientY), this.isOpen = !0, this.emit("context-menu-open", { params: d, items: l }));
|
|
362
317
|
}));
|
|
363
318
|
}
|
|
364
319
|
// ===== Public API =====
|
|
@@ -369,7 +324,7 @@ class M extends y {
|
|
|
369
324
|
* @param params - Partial context menu parameters
|
|
370
325
|
*/
|
|
371
326
|
showMenu(e, n, i) {
|
|
372
|
-
const
|
|
327
|
+
const r = {
|
|
373
328
|
row: i.row ?? null,
|
|
374
329
|
rowIndex: i.rowIndex ?? -1,
|
|
375
330
|
column: i.column ?? null,
|
|
@@ -378,12 +333,12 @@ class M extends y {
|
|
|
378
333
|
value: i.value ?? null,
|
|
379
334
|
isHeader: i.isHeader ?? !1,
|
|
380
335
|
event: i.event ?? new MouseEvent("contextmenu")
|
|
381
|
-
}, o =
|
|
382
|
-
this.menuElement && this.menuElement.remove(), this.menuElement =
|
|
336
|
+
}, o = x(this.config.items ?? b, r);
|
|
337
|
+
this.menuElement && this.menuElement.remove(), this.menuElement = w(
|
|
383
338
|
o,
|
|
384
|
-
|
|
339
|
+
r,
|
|
385
340
|
(t) => {
|
|
386
|
-
t.action && t.action(
|
|
341
|
+
t.action && t.action(r), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
|
|
387
342
|
},
|
|
388
343
|
this.gridIcons.submenuArrow
|
|
389
344
|
), document.body.appendChild(this.menuElement), E(this.menuElement, e, n), this.isOpen = !0;
|
|
@@ -404,6 +359,6 @@ class M extends y {
|
|
|
404
359
|
// Styles are injected globally via installGlobalHandlers() since menu renders in document.body
|
|
405
360
|
}
|
|
406
361
|
export {
|
|
407
|
-
|
|
362
|
+
H as ContextMenuPlugin
|
|
408
363
|
};
|
|
409
364
|
//# sourceMappingURL=index.js.map
|