@toolbox-web/grid 1.17.0 → 1.19.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.
Files changed (66) hide show
  1. package/README.md +126 -41
  2. package/all.js +1065 -933
  3. package/all.js.map +1 -1
  4. package/index.js +39 -33
  5. package/index.js.map +1 -1
  6. package/lib/core/grid.d.ts +12 -2
  7. package/lib/core/grid.d.ts.map +1 -1
  8. package/lib/core/internal/header.d.ts.map +1 -1
  9. package/lib/core/internal/keyboard.d.ts.map +1 -1
  10. package/lib/core/types.d.ts +34 -1
  11. package/lib/core/types.d.ts.map +1 -1
  12. package/lib/plugins/clipboard/index.js.map +1 -1
  13. package/lib/plugins/column-virtualization/index.js.map +1 -1
  14. package/lib/plugins/context-menu/index.js.map +1 -1
  15. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  16. package/lib/plugins/editing/index.js +155 -145
  17. package/lib/plugins/editing/index.js.map +1 -1
  18. package/lib/plugins/export/index.js.map +1 -1
  19. package/lib/plugins/filtering/FilteringPlugin.d.ts +31 -0
  20. package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
  21. package/lib/plugins/filtering/filter-model.d.ts +30 -3
  22. package/lib/plugins/filtering/filter-model.d.ts.map +1 -1
  23. package/lib/plugins/filtering/index.d.ts +1 -0
  24. package/lib/plugins/filtering/index.d.ts.map +1 -1
  25. package/lib/plugins/filtering/index.js +471 -361
  26. package/lib/plugins/filtering/index.js.map +1 -1
  27. package/lib/plugins/filtering/types.d.ts +32 -0
  28. package/lib/plugins/filtering/types.d.ts.map +1 -1
  29. package/lib/plugins/grouping-columns/index.js.map +1 -1
  30. package/lib/plugins/grouping-rows/index.js.map +1 -1
  31. package/lib/plugins/master-detail/index.js.map +1 -1
  32. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts +4 -0
  33. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts.map +1 -1
  34. package/lib/plugins/multi-sort/index.js +49 -39
  35. package/lib/plugins/multi-sort/index.js.map +1 -1
  36. package/lib/plugins/pinned-columns/index.js.map +1 -1
  37. package/lib/plugins/pinned-rows/index.js.map +1 -1
  38. package/lib/plugins/pivot/index.js.map +1 -1
  39. package/lib/plugins/print/index.js.map +1 -1
  40. package/lib/plugins/reorder/index.js +81 -78
  41. package/lib/plugins/reorder/index.js.map +1 -1
  42. package/lib/plugins/responsive/index.js +58 -55
  43. package/lib/plugins/responsive/index.js.map +1 -1
  44. package/lib/plugins/row-reorder/index.js +5 -2
  45. package/lib/plugins/row-reorder/index.js.map +1 -1
  46. package/lib/plugins/selection/SelectionPlugin.d.ts +18 -0
  47. package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
  48. package/lib/plugins/selection/index.js +110 -71
  49. package/lib/plugins/selection/index.js.map +1 -1
  50. package/lib/plugins/server-side/index.js.map +1 -1
  51. package/lib/plugins/tree/index.js.map +1 -1
  52. package/lib/plugins/undo-redo/index.js.map +1 -1
  53. package/lib/plugins/visibility/index.js.map +1 -1
  54. package/package.json +1 -1
  55. package/umd/grid.all.umd.js +29 -29
  56. package/umd/grid.all.umd.js.map +1 -1
  57. package/umd/grid.umd.js +2 -2
  58. package/umd/grid.umd.js.map +1 -1
  59. package/umd/plugins/editing.umd.js +1 -1
  60. package/umd/plugins/editing.umd.js.map +1 -1
  61. package/umd/plugins/filtering.umd.js +1 -1
  62. package/umd/plugins/filtering.umd.js.map +1 -1
  63. package/umd/plugins/multi-sort.umd.js +1 -1
  64. package/umd/plugins/multi-sort.umd.js.map +1 -1
  65. package/umd/plugins/selection.umd.js +2 -2
  66. package/umd/plugins/selection.umd.js.map +1 -1
@@ -89,6 +89,10 @@ export declare class MultiSortPlugin extends BaseGridPlugin<MultiSortConfig> {
89
89
  /** @internal */
90
90
  protected get defaultConfig(): Partial<MultiSortConfig>;
91
91
  private sortModel;
92
+ /** Cached sort result — returned as-is while a row edit is active to prevent
93
+ * the edited row from jumping to a new sorted position mid-edit. Row data
94
+ * mutations are still visible because the array holds shared object refs. */
95
+ private cachedSortResult;
92
96
  /** @internal */
93
97
  detach(): void;
94
98
  /** @internal */
@@ -1 +1 @@
1
- {"version":3,"file":"MultiSortPlugin.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/multi-sort/MultiSortPlugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,qBAAa,eAAgB,SAAQ,cAAc,CAAC,eAAe,CAAC;IAClE,gBAAgB;IAChB,QAAQ,CAAC,IAAI,eAAe;IAC5B,gBAAgB;IAChB,SAAkB,MAAM,SAAU;IAElC,gBAAgB;IAChB,cAAuB,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC,CAK/D;IAGD,OAAO,CAAC,SAAS,CAAmB;IAKpC,gBAAgB;IACP,MAAM,IAAI,IAAI;IAOvB,gBAAgB;IACP,WAAW,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE;IAOzD,gBAAgB;IACP,aAAa,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO;IAexD,gBAAgB;IACP,WAAW,IAAI,IAAI;IAoE5B;;;OAGG;IACH,YAAY,IAAI,SAAS,EAAE;IAI3B;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI;IAMtC;;OAEG;IACH,SAAS,IAAI,IAAI;IAMjB;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI/C;;;;OAIG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS;IAO3D;;;OAGG;IACM,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,SAAS;IAaxE;;;;OAIG;IACM,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;CA2BnE"}
1
+ {"version":3,"file":"MultiSortPlugin.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/multi-sort/MultiSortPlugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,qBAAa,eAAgB,SAAQ,cAAc,CAAC,eAAe,CAAC;IAClE,gBAAgB;IAChB,QAAQ,CAAC,IAAI,eAAe;IAC5B,gBAAgB;IAChB,SAAkB,MAAM,SAAU;IAElC,gBAAgB;IAChB,cAAuB,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC,CAK/D;IAGD,OAAO,CAAC,SAAS,CAAmB;IACpC;;kFAE8E;IAC9E,OAAO,CAAC,gBAAgB,CAA0B;IAKlD,gBAAgB;IACP,MAAM,IAAI,IAAI;IAQvB,gBAAgB;IACP,WAAW,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE;IAyBzD,gBAAgB;IACP,aAAa,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO;IAgBxD,gBAAgB;IACP,WAAW,IAAI,IAAI;IAoE5B;;;OAGG;IACH,YAAY,IAAI,SAAS,EAAE;IAI3B;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI;IAOtC;;OAEG;IACH,SAAS,IAAI,IAAI;IAOjB;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI/C;;;;OAIG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS;IAO3D;;;OAGG;IACM,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,SAAS;IAaxE;;;;OAIG;IACM,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;CA2BnE"}
@@ -1,4 +1,4 @@
1
- const h = '<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>', v = {
1
+ const f = '<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>', S = {
2
2
  expand: "▶",
3
3
  collapse: "▼",
4
4
  sortAsc: "▲",
@@ -7,11 +7,11 @@ const h = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentCo
7
7
  submenuArrow: "▶",
8
8
  dragHandle: "⋮⋮",
9
9
  toolPanel: "☰",
10
- filter: h,
11
- filterActive: h,
10
+ filter: f,
11
+ filterActive: f,
12
12
  print: "🖨️"
13
13
  };
14
- class x {
14
+ class C {
15
15
  /**
16
16
  * Plugin dependencies - declare other plugins this one requires.
17
17
  *
@@ -146,8 +146,8 @@ class x {
146
146
  * @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
147
147
  */
148
148
  emitCancelable(t, e) {
149
- const o = new CustomEvent(t, { detail: e, bubbles: !0, cancelable: !0 });
150
- return this.grid?.dispatchEvent?.(o), o.defaultPrevented;
149
+ const n = new CustomEvent(t, { detail: e, bubbles: !0, cancelable: !0 });
150
+ return this.grid?.dispatchEvent?.(n), n.defaultPrevented;
151
151
  }
152
152
  // =========================================================================
153
153
  // Event Bus - Plugin-to-Plugin Communication
@@ -301,7 +301,7 @@ class x {
301
301
  */
302
302
  get gridIcons() {
303
303
  const t = this.grid?.gridConfig?.icons ?? {};
304
- return { ...v, ...t };
304
+ return { ...S, ...t };
305
305
  }
306
306
  // #region Animation Helpers
307
307
  /**
@@ -342,8 +342,8 @@ class x {
342
342
  get animationDuration() {
343
343
  const t = this.gridElement;
344
344
  if (t) {
345
- const e = getComputedStyle(t).getPropertyValue("--tbw-animation-duration").trim(), o = parseInt(e, 10);
346
- if (!isNaN(o)) return o;
345
+ const e = getComputedStyle(t).getPropertyValue("--tbw-animation-duration").trim(), n = parseInt(e, 10);
346
+ if (!isNaN(n)) return n;
347
347
  }
348
348
  return 200;
349
349
  }
@@ -377,32 +377,32 @@ class x {
377
377
  }
378
378
  // #endregion
379
379
  }
380
- function C(i, t, e) {
381
- return t.length ? [...i].sort((o, r) => {
382
- for (const n of t) {
383
- const d = e.find((u) => u.field === n.field)?.sortComparator ?? S, g = o[n.field], c = r[n.field], s = d(g, c, o, r);
384
- if (s !== 0)
385
- return n.direction === "asc" ? s : -s;
380
+ function v(i, t, e) {
381
+ return t.length ? [...i].sort((n, r) => {
382
+ for (const s of t) {
383
+ const d = e.find((u) => u.field === s.field)?.sortComparator ?? x, g = n[s.field], c = r[s.field], o = d(g, c, n, r);
384
+ if (o !== 0)
385
+ return s.direction === "asc" ? o : -o;
386
386
  }
387
387
  return 0;
388
388
  }) : [...i];
389
389
  }
390
- function S(i, t) {
390
+ function x(i, t) {
391
391
  return i == null && t == null ? 0 : i == null ? 1 : t == null ? -1 : typeof i == "number" && typeof t == "number" ? i - t : i instanceof Date && t instanceof Date ? i.getTime() - t.getTime() : typeof i == "boolean" && typeof t == "boolean" ? i === t ? 0 : i ? -1 : 1 : String(i).localeCompare(String(t));
392
392
  }
393
- function M(i, t, e, o) {
394
- const r = i.find((n) => n.field === t);
395
- return e ? r ? r.direction === "asc" ? i.map((n) => n.field === t ? { ...n, direction: "desc" } : n) : i.filter((n) => n.field !== t) : i.length < o ? [...i, { field: t, direction: "asc" }] : i : r?.direction === "asc" ? [{ field: t, direction: "desc" }] : r?.direction === "desc" ? [] : [{ field: t, direction: "asc" }];
393
+ function M(i, t, e, n) {
394
+ const r = i.find((s) => s.field === t);
395
+ return e ? r ? r.direction === "asc" ? i.map((s) => s.field === t ? { ...s, direction: "desc" } : s) : i.filter((s) => s.field !== t) : i.length < n ? [...i, { field: t, direction: "asc" }] : i : r?.direction === "asc" ? [{ field: t, direction: "desc" }] : r?.direction === "desc" ? [] : [{ field: t, direction: "asc" }];
396
396
  }
397
397
  function m(i, t) {
398
- const e = i.findIndex((o) => o.field === t);
398
+ const e = i.findIndex((n) => n.field === t);
399
399
  return e >= 0 ? e + 1 : void 0;
400
400
  }
401
401
  function p(i, t) {
402
402
  return i.find((e) => e.field === t)?.direction;
403
403
  }
404
404
  const w = '@layer tbw-plugins{.header-cell[data-sort=asc]:after{content:"↑";margin-left:var(--tbw-spacing-xs, .25em);opacity:.8}.header-cell[data-sort=desc]:after{content:"↓";margin-left:var(--tbw-spacing-xs, .25em);opacity:.8}.sort-indicator{margin-left:var(--tbw-spacing-xs, .25em);opacity:.8}.sort-index{font-size:var(--tbw-font-size-2xs, .7em);background:var(--tbw-multi-sort-badge-bg, var(--tbw-color-panel-bg));color:var(--tbw-multi-sort-badge-color, var(--tbw-color-fg));border-radius:50%;width:var(--tbw-multi-sort-badge-size, 1em);height:var(--tbw-multi-sort-badge-size, 1em);display:inline-flex;align-items:center;justify-content:center;margin-left:var(--tbw-spacing-xs, .125em);font-weight:600}}';
405
- class y extends x {
405
+ class y extends C {
406
406
  /** @internal */
407
407
  name = "multiSort";
408
408
  /** @internal */
@@ -416,23 +416,33 @@ class y extends x {
416
416
  }
417
417
  // #region Internal State
418
418
  sortModel = [];
419
+ /** Cached sort result — returned as-is while a row edit is active to prevent
420
+ * the edited row from jumping to a new sorted position mid-edit. Row data
421
+ * mutations are still visible because the array holds shared object refs. */
422
+ cachedSortResult = null;
419
423
  // #endregion
420
424
  // #region Lifecycle
421
425
  /** @internal */
422
426
  detach() {
423
- this.sortModel = [];
427
+ this.sortModel = [], this.cachedSortResult = null;
424
428
  }
425
429
  // #endregion
426
430
  // #region Hooks
427
431
  /** @internal */
428
432
  processRows(t) {
429
- return this.sortModel.length === 0 ? [...t] : C([...t], this.sortModel, [...this.columns]);
433
+ if (this.sortModel.length === 0)
434
+ return this.cachedSortResult = null, [...t];
435
+ const e = this.gridElement;
436
+ if (e && !e._isGridEditMode && typeof e._activeEditRows == "number" && e._activeEditRows !== -1 && this.cachedSortResult && this.cachedSortResult.length === t.length)
437
+ return [...this.cachedSortResult];
438
+ const n = v([...t], this.sortModel, [...this.columns]);
439
+ return this.cachedSortResult = n, n;
430
440
  }
431
441
  /** @internal */
432
442
  onHeaderClick(t) {
433
- if (!this.columns.find((n) => n.field === t.field)?.sortable) return !1;
434
- const o = t.originalEvent.shiftKey, r = this.config.maxSortColumns ?? 3;
435
- return this.sortModel = M(this.sortModel, t.field, o, r), this.emit("sort-change", { sortModel: [...this.sortModel] }), this.requestRender(), !0;
443
+ if (!this.columns.find((s) => s.field === t.field)?.sortable) return !1;
444
+ const n = t.originalEvent.shiftKey, r = this.config.maxSortColumns ?? 3;
445
+ return this.sortModel = M(this.sortModel, t.field, n, r), this.emit("sort-change", { sortModel: [...this.sortModel] }), this.requestRender(), this.grid?.requestStateChange?.(), !0;
436
446
  }
437
447
  /** @internal */
438
448
  afterRender() {
@@ -440,17 +450,17 @@ class y extends x {
440
450
  if (!t) return;
441
451
  const e = this.config.showSortIndex !== !1;
442
452
  t.querySelectorAll(".header-row .cell[data-field]").forEach((r) => {
443
- const n = r.getAttribute("data-field");
444
- if (!n) return;
445
- const a = m(this.sortModel, n), d = p(this.sortModel, n);
453
+ const s = r.getAttribute("data-field");
454
+ if (!s) return;
455
+ const a = m(this.sortModel, s), d = p(this.sortModel, s);
446
456
  if (r.querySelector(".sort-index")?.remove(), d) {
447
457
  r.querySelector('[part~="sort-indicator"], .sort-indicator')?.remove(), r.setAttribute("data-sort", d);
448
- const s = document.createElement("span");
449
- s.className = "sort-indicator", this.setIcon(s, this.resolveIcon(d === "asc" ? "sortAsc" : "sortDesc"));
450
- const u = r.querySelector(".tbw-filter-btn"), b = r.querySelector(".resize-handle"), f = u ?? b;
451
- if (f ? r.insertBefore(s, f) : r.appendChild(s), e && this.sortModel.length > 1 && a !== void 0) {
458
+ const o = document.createElement("span");
459
+ o.className = "sort-indicator", this.setIcon(o, this.resolveIcon(d === "asc" ? "sortAsc" : "sortDesc"));
460
+ const u = r.querySelector(".tbw-filter-btn"), b = r.querySelector(".resize-handle"), h = u ?? b;
461
+ if (h ? r.insertBefore(o, h) : r.appendChild(o), e && this.sortModel.length > 1 && a !== void 0) {
452
462
  const l = document.createElement("span");
453
- l.className = "sort-index", l.textContent = String(a), s.nextSibling ? r.insertBefore(l, s.nextSibling) : r.appendChild(l);
463
+ l.className = "sort-index", l.textContent = String(a), o.nextSibling ? r.insertBefore(l, o.nextSibling) : r.appendChild(l);
454
464
  }
455
465
  } else
456
466
  r.removeAttribute("data-sort"), r.querySelector('[part~="sort-indicator"], .sort-indicator')?.remove();
@@ -470,13 +480,13 @@ class y extends x {
470
480
  * @param model - New sort model to apply
471
481
  */
472
482
  setSortModel(t) {
473
- this.sortModel = [...t], this.emit("sort-change", { sortModel: [...t] }), this.requestRender();
483
+ this.sortModel = [...t], this.emit("sort-change", { sortModel: [...t] }), this.requestRender(), this.grid?.requestStateChange?.();
474
484
  }
475
485
  /**
476
486
  * Clear all sorting.
477
487
  */
478
488
  clearSort() {
479
- this.sortModel = [], this.emit("sort-change", { sortModel: [] }), this.requestRender();
489
+ this.sortModel = [], this.emit("sort-change", { sortModel: [] }), this.requestRender(), this.grid?.requestStateChange?.();
480
490
  }
481
491
  /**
482
492
  * Get the sort index (1-based) for a specific field.
@@ -516,14 +526,14 @@ class y extends x {
516
526
  */
517
527
  applyColumnState(t, e) {
518
528
  if (!e.sort) {
519
- this.sortModel = this.sortModel.filter((n) => n.field !== t);
529
+ this.sortModel = this.sortModel.filter((s) => s.field !== t);
520
530
  return;
521
531
  }
522
- const o = this.sortModel.findIndex((n) => n.field === t), r = {
532
+ const n = this.sortModel.findIndex((s) => s.field === t), r = {
523
533
  field: t,
524
534
  direction: e.sort.direction
525
535
  };
526
- o !== -1 ? this.sortModel[o] = r : this.sortModel.splice(e.sort.priority, 0, r);
536
+ n !== -1 ? this.sortModel[n] = r : this.sortModel.splice(e.sort.priority, 0, r);
527
537
  }
528
538
  // #endregion
529
539
  }