@toolbox-web/grid 1.0.0 → 1.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.
Files changed (87) hide show
  1. package/all.d.ts +1 -0
  2. package/all.d.ts.map +1 -1
  3. package/all.js +1655 -1444
  4. package/all.js.map +1 -1
  5. package/index.js +438 -401
  6. package/index.js.map +1 -1
  7. package/lib/core/grid.d.ts.map +1 -1
  8. package/lib/core/internal/rows.d.ts.map +1 -1
  9. package/lib/core/internal/validate-config.d.ts +10 -0
  10. package/lib/core/internal/validate-config.d.ts.map +1 -1
  11. package/lib/core/plugin/base-plugin.d.ts +101 -0
  12. package/lib/core/plugin/base-plugin.d.ts.map +1 -1
  13. package/lib/core/plugin/index.d.ts +1 -1
  14. package/lib/core/plugin/index.d.ts.map +1 -1
  15. package/lib/plugins/clipboard/index.js +22 -0
  16. package/lib/plugins/clipboard/index.js.map +1 -1
  17. package/lib/plugins/column-virtualization/index.js +48 -26
  18. package/lib/plugins/column-virtualization/index.js.map +1 -1
  19. package/lib/plugins/context-menu/index.js +64 -42
  20. package/lib/plugins/context-menu/index.js.map +1 -1
  21. package/lib/plugins/editing/EditingPlugin.d.ts +6 -1
  22. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  23. package/lib/plugins/editing/index.js +50 -4
  24. package/lib/plugins/editing/index.js.map +1 -1
  25. package/lib/plugins/export/index.js +36 -14
  26. package/lib/plugins/export/index.js.map +1 -1
  27. package/lib/plugins/filtering/index.js +63 -41
  28. package/lib/plugins/filtering/index.js.map +1 -1
  29. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +6 -1
  30. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
  31. package/lib/plugins/grouping-columns/index.js +47 -6
  32. package/lib/plugins/grouping-columns/index.js.map +1 -1
  33. package/lib/plugins/grouping-rows/index.js +22 -0
  34. package/lib/plugins/grouping-rows/index.js.map +1 -1
  35. package/lib/plugins/master-detail/index.js +22 -0
  36. package/lib/plugins/master-detail/index.js.map +1 -1
  37. package/lib/plugins/multi-sort/index.js +22 -0
  38. package/lib/plugins/multi-sort/index.js.map +1 -1
  39. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +6 -1
  40. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -1
  41. package/lib/plugins/pinned-columns/index.js +36 -0
  42. package/lib/plugins/pinned-columns/index.js.map +1 -1
  43. package/lib/plugins/pinned-rows/index.js +22 -0
  44. package/lib/plugins/pinned-rows/index.js.map +1 -1
  45. package/lib/plugins/pivot/index.js +22 -0
  46. package/lib/plugins/pivot/index.js.map +1 -1
  47. package/lib/plugins/reorder/index.js +22 -0
  48. package/lib/plugins/reorder/index.js.map +1 -1
  49. package/lib/plugins/responsive/ResponsivePlugin.d.ts +123 -0
  50. package/lib/plugins/responsive/ResponsivePlugin.d.ts.map +1 -0
  51. package/lib/plugins/responsive/index.d.ts +11 -0
  52. package/lib/plugins/responsive/index.d.ts.map +1 -0
  53. package/lib/plugins/responsive/index.js +589 -0
  54. package/lib/plugins/responsive/index.js.map +1 -0
  55. package/lib/plugins/responsive/types.d.ts +133 -0
  56. package/lib/plugins/responsive/types.d.ts.map +1 -0
  57. package/lib/plugins/selection/SelectionPlugin.d.ts +6 -1
  58. package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
  59. package/lib/plugins/selection/index.d.ts +1 -1
  60. package/lib/plugins/selection/index.d.ts.map +1 -1
  61. package/lib/plugins/selection/index.js +105 -63
  62. package/lib/plugins/selection/index.js.map +1 -1
  63. package/lib/plugins/selection/types.d.ts +26 -0
  64. package/lib/plugins/selection/types.d.ts.map +1 -1
  65. package/lib/plugins/server-side/index.js +22 -0
  66. package/lib/plugins/server-side/index.js.map +1 -1
  67. package/lib/plugins/tree/index.js +22 -0
  68. package/lib/plugins/tree/index.js.map +1 -1
  69. package/lib/plugins/undo-redo/index.js +27 -5
  70. package/lib/plugins/undo-redo/index.js.map +1 -1
  71. package/lib/plugins/visibility/index.js +22 -0
  72. package/lib/plugins/visibility/index.js.map +1 -1
  73. package/package.json +1 -1
  74. package/umd/grid.all.umd.js +28 -22
  75. package/umd/grid.all.umd.js.map +1 -1
  76. package/umd/grid.umd.js +18 -14
  77. package/umd/grid.umd.js.map +1 -1
  78. package/umd/plugins/editing.umd.js +1 -1
  79. package/umd/plugins/editing.umd.js.map +1 -1
  80. package/umd/plugins/grouping-columns.umd.js +1 -1
  81. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  82. package/umd/plugins/pinned-columns.umd.js +1 -1
  83. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  84. package/umd/plugins/responsive.umd.js +2 -0
  85. package/umd/plugins/responsive.umd.js.map +1 -0
  86. package/umd/plugins/selection.umd.js +3 -1
  87. package/umd/plugins/selection.umd.js.map +1 -1
@@ -1,9 +1,9 @@
1
1
  function P(h) {
2
- const { totalRows: e, viewportHeight: t, scrollTop: r, rowHeight: n, overscan: l } = h, i = Math.ceil(t / n);
3
- let a = Math.floor(r / n) - l;
2
+ const { totalRows: e, viewportHeight: t, scrollTop: r, rowHeight: n, overscan: i } = h, l = Math.ceil(t / n);
3
+ let a = Math.floor(r / n) - i;
4
4
  a < 0 && (a = 0);
5
- let o = a + i + l * 2;
6
- return o > e && (o = e), o === e && a > 0 && (a = Math.max(0, o - i - l * 2)), {
5
+ let o = a + l + i * 2;
6
+ return o > e && (o = e), o === e && a > 0 && (a = Math.max(0, o - l - i * 2)), {
7
7
  start: a,
8
8
  end: o,
9
9
  offsetY: a * n,
@@ -40,6 +40,28 @@ class M {
40
40
  * ```
41
41
  */
42
42
  static dependencies;
43
+ /**
44
+ * Plugin manifest - declares owned properties, config rules, and hook priorities.
45
+ *
46
+ * This is read by the configuration validator to:
47
+ * - Validate that required plugins are loaded when their properties are used
48
+ * - Execute configRules to detect invalid/conflicting settings
49
+ * - Order hook execution based on priority
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * static override readonly manifest: PluginManifest<MyConfig> = {
54
+ * ownedProperties: [
55
+ * { property: 'myProp', level: 'column', description: 'the "myProp" column property' },
56
+ * ],
57
+ * configRules: [
58
+ * { id: 'myPlugin/conflict', severity: 'warn', message: '...', check: (c) => c.a && c.b },
59
+ * ],
60
+ * };
61
+ * ```
62
+ */
63
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
+ static manifest;
43
65
  /**
44
66
  * Plugin version - defaults to grid version for built-in plugins.
45
67
  * Third-party plugins can override with their own semver.
@@ -311,21 +333,21 @@ function q(h, e, t = !1) {
311
333
  if (e.operator === "notBlank")
312
334
  return r != null && r !== "";
313
335
  if (r == null) return !1;
314
- const n = String(r), l = t ? n : n.toLowerCase(), i = t ? String(e.value) : String(e.value).toLowerCase();
336
+ const n = String(r), i = t ? n : n.toLowerCase(), l = t ? String(e.value) : String(e.value).toLowerCase();
315
337
  switch (e.operator) {
316
338
  // Text operators
317
339
  case "contains":
318
- return l.includes(i);
340
+ return i.includes(l);
319
341
  case "notContains":
320
- return !l.includes(i);
342
+ return !i.includes(l);
321
343
  case "equals":
322
- return l === i;
344
+ return i === l;
323
345
  case "notEquals":
324
- return l !== i;
346
+ return i !== l;
325
347
  case "startsWith":
326
- return l.startsWith(i);
348
+ return i.startsWith(l);
327
349
  case "endsWith":
328
- return l.endsWith(i);
350
+ return i.endsWith(l);
329
351
  // Number/Date operators (use raw numeric values)
330
352
  case "lessThan":
331
353
  return Number(r) < Number(e.value);
@@ -437,18 +459,18 @@ class g extends M {
437
459
  e.querySelectorAll('[part~="header-cell"]').forEach((r) => {
438
460
  const n = r.getAttribute("data-col");
439
461
  if (n === null) return;
440
- const l = this.visibleColumns[parseInt(n, 10)];
441
- if (!l || l.filterable === !1 || z(l)) return;
442
- const i = l.field;
443
- if (!i) return;
444
- const a = this.filters.has(i);
462
+ const i = this.visibleColumns[parseInt(n, 10)];
463
+ if (!i || i.filterable === !1 || z(i)) return;
464
+ const l = i.field;
465
+ if (!l) return;
466
+ const a = this.filters.has(l);
445
467
  let o = r.querySelector(".tbw-filter-btn");
446
468
  if (o) {
447
469
  o.classList.toggle("active", a), r.classList.toggle("filtered", a);
448
470
  return;
449
471
  }
450
- o = document.createElement("button"), o.className = "tbw-filter-btn", o.setAttribute("aria-label", `Filter ${l.header ?? i}`), o.innerHTML = '<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>', a && (o.classList.add("active"), r.classList.add("filtered")), o.addEventListener("click", (b) => {
451
- b.stopPropagation(), this.toggleFilterPanel(i, l, o);
472
+ o = document.createElement("button"), o.className = "tbw-filter-btn", o.setAttribute("aria-label", `Filter ${i.header ?? l}`), o.innerHTML = '<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>', a && (o.classList.add("active"), r.classList.add("filtered")), o.addEventListener("click", (b) => {
473
+ b.stopPropagation(), this.toggleFilterPanel(l, i, o);
452
474
  });
453
475
  const p = r.querySelector(".resize-handle");
454
476
  p ? r.insertBefore(o, p) : r.appendChild(o);
@@ -565,26 +587,26 @@ class g extends M {
565
587
  this.closeFilterPanel();
566
588
  const n = document.createElement("div");
567
589
  if (n.className = "tbw-filter-panel", this.isAnimationEnabled && n.classList.add("tbw-filter-panel-animated"), this.panelElement = n, this.openPanelField = e, this.config.valuesHandler) {
568
- n.innerHTML = '<div class="tbw-filter-loading">Loading...</div>', document.body.appendChild(n), this.positionPanel(n, r), this.setupPanelCloseHandler(n, r), this.config.valuesHandler(e, t).then((i) => {
569
- this.openPanelField !== e || !this.panelElement || (n.innerHTML = "", this.renderPanelContent(e, t, n, i));
590
+ n.innerHTML = '<div class="tbw-filter-loading">Loading...</div>', document.body.appendChild(n), this.positionPanel(n, r), this.setupPanelCloseHandler(n, r), this.config.valuesHandler(e, t).then((l) => {
591
+ this.openPanelField !== e || !this.panelElement || (n.innerHTML = "", this.renderPanelContent(e, t, n, l));
570
592
  });
571
593
  return;
572
594
  }
573
- const l = H(this.sourceRows, e);
574
- this.renderPanelContent(e, t, n, l), document.body.appendChild(n), this.positionPanel(n, r), this.setupPanelCloseHandler(n, r);
595
+ const i = H(this.sourceRows, e);
596
+ this.renderPanelContent(e, t, n, i), document.body.appendChild(n), this.positionPanel(n, r), this.setupPanelCloseHandler(n, r);
575
597
  }
576
598
  /**
577
599
  * Render filter panel content with given values
578
600
  */
579
601
  renderPanelContent(e, t, r, n) {
580
- let l = this.excludedValues.get(e);
581
- l || (l = /* @__PURE__ */ new Set(), this.excludedValues.set(e, l));
582
- const i = this.searchText.get(e) ?? "", a = {
602
+ let i = this.excludedValues.get(e);
603
+ i || (i = /* @__PURE__ */ new Set(), this.excludedValues.set(e, i));
604
+ const l = this.searchText.get(e) ?? "", a = {
583
605
  field: e,
584
606
  column: t,
585
607
  uniqueValues: n,
586
- excludedValues: l,
587
- searchText: i,
608
+ excludedValues: i,
609
+ searchText: l,
588
610
  applySetFilter: (p) => {
589
611
  this.applySetFilter(e, p), this.closeFilterPanel();
590
612
  },
@@ -597,7 +619,7 @@ class g extends M {
597
619
  closePanel: () => this.closeFilterPanel()
598
620
  };
599
621
  let o = !1;
600
- this.config.filterPanelRenderer && (this.config.filterPanelRenderer(r, a), o = r.children.length > 0), o || this.renderDefaultFilterPanel(r, a, n, l);
622
+ this.config.filterPanelRenderer && (this.config.filterPanelRenderer(r, a), o = r.children.length > 0), o || this.renderDefaultFilterPanel(r, a, n, i);
601
623
  }
602
624
  /**
603
625
  * Setup click-outside handler to close the panel
@@ -636,25 +658,25 @@ class g extends M {
636
658
  const n = t.closest(".cell") ?? t;
637
659
  if (n.style.anchorName = "--tbw-filter-anchor", this.panelAnchorElement = n, g.checkAnchorPositioningSupport()) {
638
660
  requestAnimationFrame(() => {
639
- const i = e.getBoundingClientRect(), a = n.getBoundingClientRect();
640
- i.top < a.top && e.classList.add("tbw-filter-panel-above");
661
+ const l = e.getBoundingClientRect(), a = n.getBoundingClientRect();
662
+ l.top < a.top && e.classList.add("tbw-filter-panel-above");
641
663
  });
642
664
  return;
643
665
  }
644
- const l = n.getBoundingClientRect();
645
- e.style.position = "fixed", e.style.top = `${l.bottom + 4}px`, e.style.left = `${l.left}px`, requestAnimationFrame(() => {
646
- const i = e.getBoundingClientRect();
647
- i.right > window.innerWidth - 8 && (e.style.left = `${l.right - i.width}px`), i.bottom > window.innerHeight - 8 && (e.style.top = `${l.top - i.height - 4}px`, e.classList.add("tbw-filter-panel-above"));
666
+ const i = n.getBoundingClientRect();
667
+ e.style.position = "fixed", e.style.top = `${i.bottom + 4}px`, e.style.left = `${i.left}px`, requestAnimationFrame(() => {
668
+ const l = e.getBoundingClientRect();
669
+ l.right > window.innerWidth - 8 && (e.style.left = `${i.right - l.width}px`), l.bottom > window.innerHeight - 8 && (e.style.top = `${i.top - l.height - 4}px`, e.classList.add("tbw-filter-panel-above"));
648
670
  });
649
671
  }
650
672
  /**
651
673
  * Render the default filter panel content
652
674
  */
653
675
  renderDefaultFilterPanel(e, t, r, n) {
654
- const { field: l } = t, i = document.createElement("div");
655
- i.className = "tbw-filter-search";
676
+ const { field: i } = t, l = document.createElement("div");
677
+ l.className = "tbw-filter-search";
656
678
  const a = document.createElement("input");
657
- a.type = "text", a.placeholder = "Search...", a.className = "tbw-filter-search-input", a.value = this.searchText.get(l) ?? "", i.appendChild(a), e.appendChild(i);
679
+ a.type = "text", a.placeholder = "Search...", a.className = "tbw-filter-search-input", a.value = this.searchText.get(i) ?? "", l.appendChild(a), e.appendChild(l);
658
680
  const o = document.createElement("div");
659
681
  o.className = "tbw-filter-actions";
660
682
  const p = document.createElement("label");
@@ -735,7 +757,7 @@ class g extends M {
735
757
  let L;
736
758
  a.addEventListener("input", () => {
737
759
  clearTimeout(L), L = setTimeout(() => {
738
- this.searchText.set(l, a.value), I(a.value);
760
+ this.searchText.set(i, a.value), I(a.value);
739
761
  }, this.config.debounceMs ?? 150);
740
762
  });
741
763
  const S = document.createElement("div");
@@ -790,10 +812,10 @@ class g extends M {
790
812
  if (this.config.filterHandler) {
791
813
  const t = this.grid;
792
814
  t.setAttribute("aria-busy", "true");
793
- const r = this.config.filterHandler(e, this.sourceRows), n = (l) => {
794
- t.removeAttribute("aria-busy"), this.cachedResult = l, this.grid.rows = l, this.emit("filter-change", {
815
+ const r = this.config.filterHandler(e, this.sourceRows), n = (i) => {
816
+ t.removeAttribute("aria-busy"), this.cachedResult = i, this.grid.rows = i, this.emit("filter-change", {
795
817
  filters: e,
796
- filteredRowCount: l.length
818
+ filteredRowCount: i.length
797
819
  }), this.requestRender();
798
820
  };
799
821
  r && typeof r.then == "function" ? r.then(n) : n(r);