xv-webcomponents 2.0.0-beta.2 → 2.0.0-beta.28

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 (166) hide show
  1. package/README.md +3 -2
  2. package/dist/angular/index.d.ts +1 -1
  3. package/dist/angular/index.js +3 -4
  4. package/dist/angular/proxies.d.ts +60 -34
  5. package/dist/angular/proxies.js +51 -67
  6. package/dist/angular/web-components.module.d.ts +1 -1
  7. package/dist/angular/web-components.module.js +10 -13
  8. package/dist/cjs/{index-Cfa6bBQW.js → index-DaTpiyaU.js} +1 -1
  9. package/dist/cjs/{index-Cixkr3sz.js → index-Dwhgrew8.js} +15 -10
  10. package/dist/cjs/index.cjs.js +2 -2
  11. package/dist/cjs/loader.cjs.js +2 -2
  12. package/dist/cjs/{xv-accordion-v2_50.cjs.entry.js → xv-accordion-v2_49.cjs.entry.js} +1529 -147
  13. package/dist/cjs/xv-header-next.cjs.entry.js +2 -2
  14. package/dist/cjs/xv-mega-menu-next.cjs.entry.js +2 -2
  15. package/dist/cjs/xv-webcomponents.cjs.js +3 -3
  16. package/dist/collection/collection-manifest.json +1 -2
  17. package/dist/collection/components/xv-overflow-menu/xv-overflow-menu.js +9 -8
  18. package/dist/collection/components/xv-table/xv-table-cell/xv-table-cell.css +129 -61
  19. package/dist/collection/components/xv-table/xv-table-cell/xv-table-cell.js +277 -78
  20. package/dist/collection/components/xv-table/xv-table-row/xv-table-row.css +138 -24
  21. package/dist/collection/components/xv-table/xv-table-row/xv-table-row.js +334 -168
  22. package/dist/collection/components/xv-table/xv-table.css +240 -99
  23. package/dist/collection/components/xv-table/xv-table.js +2056 -63
  24. package/dist/collection/components/xv-table/xv-table.model.js +10 -0
  25. package/dist/collection/components/xv-table/xv-table.utils.js +243 -0
  26. package/dist/collection/components/xv-tabs/xv-tab/xv-tab.js +1 -1
  27. package/dist/collection/components/xv-tag/xv-tag.js +1 -1
  28. package/dist/collection/components/xv-tag-combobox/xv-tag-combobox.js +2 -2
  29. package/dist/collection/components/xv-text-input/xv-text-input.js +2 -2
  30. package/dist/collection/components/xv-textarea/xv-textarea.js +2 -2
  31. package/dist/collection/components/xv-tile/xv-tile.js +2 -2
  32. package/dist/collection/components/xv-toggle/xv-toggle.js +1 -1
  33. package/dist/collection/components/xv-toggle-tip/xv-toggle-tip.js +1 -1
  34. package/dist/collection/components/xv-tooltip/xv-tooltip.js +2 -2
  35. package/dist/collection/utils/table-layout.js +130 -0
  36. package/dist/components/index.js +1 -1
  37. package/dist/components/p-B0kwaJ8n.js +1 -0
  38. package/dist/components/{p-CbVZCn2p.js → p-BEoh0dZI.js} +1 -1
  39. package/dist/components/{p-ZYJfCCwX.js → p-BaZ-srfu.js} +1 -1
  40. package/dist/components/{p-DyGMZIub.js → p-Bej2l-wN.js} +1 -1
  41. package/dist/components/{p-Ddx5DwV5.js → p-BfhvpeQh.js} +1 -1
  42. package/dist/components/{p-kQVUwJXZ.js → p-CSYnNMKb.js} +1 -1
  43. package/dist/components/{p-BNP2Lw34.js → p-CspyoLL9.js} +1 -1
  44. package/dist/components/p-CvgDDcjp.js +1 -0
  45. package/dist/components/{p-COoj5JkZ.js → p-D4FwGeDJ.js} +1 -1
  46. package/dist/components/p-DCvH_Br_.js +1 -0
  47. package/dist/components/{p-CEjlxnKY.js → p-DFe9Mtw_.js} +1 -1
  48. package/dist/components/{p-BRZwUlfE.js → p-DFtMwE-h.js} +1 -1
  49. package/dist/components/p-DIvi4fI3.js +1 -0
  50. package/dist/components/{p-DTwz9Fsh.js → p-DNRISLNf.js} +1 -1
  51. package/dist/components/p-DPnvoOYj.js +1 -0
  52. package/dist/components/{p-Dzz9jxLm.js → p-Dwbe941A.js} +1 -1
  53. package/dist/components/{p-CMAJWZsP.js → p-JClekcEh.js} +1 -1
  54. package/dist/components/{p-DtUNYh73.js → p-NoM9oIJn.js} +1 -1
  55. package/dist/components/{p-DlLBjhuH.js → p-XEk4dHG3.js} +1 -1
  56. package/dist/components/p-i7_81si-.js +1 -0
  57. package/dist/components/{p-BRYrLHiz.js → p-i82EFiq6.js} +1 -1
  58. package/dist/components/{p-BXB4D7j4.js → p-jD7nSJaM.js} +1 -1
  59. package/dist/components/xv-accordion-v2-item.js +1 -1
  60. package/dist/components/xv-accordion-v2.js +1 -1
  61. package/dist/components/xv-breadcrumbs-v2.js +1 -1
  62. package/dist/components/xv-button-group-v2.js +1 -1
  63. package/dist/components/xv-button-v2.js +1 -1
  64. package/dist/components/xv-card-v2.js +1 -1
  65. package/dist/components/xv-checkbox-v2.js +1 -1
  66. package/dist/components/xv-content-switcher-item-v2.js +1 -1
  67. package/dist/components/xv-content-switcher-v2.js +1 -1
  68. package/dist/components/xv-data-table-cell.js +1 -1
  69. package/dist/components/xv-data-table-collapse.js +1 -1
  70. package/dist/components/xv-data-table-row.js +1 -1
  71. package/dist/components/xv-data-table.js +2 -2
  72. package/dist/components/xv-date-picker.js +1 -1
  73. package/dist/components/xv-datepicker.js +1 -1
  74. package/dist/components/xv-dropdown-v2-item.js +1 -1
  75. package/dist/components/xv-dropdown-v2.js +1 -1
  76. package/dist/components/xv-file-uploader.js +1 -1
  77. package/dist/components/xv-footer.js +1 -1
  78. package/dist/components/xv-geo-map-v2.js +1 -1
  79. package/dist/components/xv-header-next.js +1 -1
  80. package/dist/components/xv-header.js +1 -1
  81. package/dist/components/xv-image-viewer.js +1 -1
  82. package/dist/components/xv-link-v2.js +1 -1
  83. package/dist/components/xv-loader-v2.js +1 -1
  84. package/dist/components/xv-login-modal.js +1 -1
  85. package/dist/components/xv-mega-menu-next.js +1 -1
  86. package/dist/components/xv-mega-menu.js +1 -1
  87. package/dist/components/xv-modal-v2.js +1 -1
  88. package/dist/components/xv-notification-v2.js +1 -1
  89. package/dist/components/xv-number-input-v2.js +1 -1
  90. package/dist/components/xv-overflow-menu-v2-item.js +1 -1
  91. package/dist/components/xv-overflow-menu-v2.js +1 -1
  92. package/dist/components/xv-pagination.js +1 -1
  93. package/dist/components/xv-progress-indicator-v2-item.js +1 -1
  94. package/dist/components/xv-progress-indicator-v2.js +1 -1
  95. package/dist/components/xv-radio-v2.js +1 -1
  96. package/dist/components/xv-slider-v2.js +1 -1
  97. package/dist/components/xv-tab-v2.js +1 -1
  98. package/dist/components/{xv-table-v2-row.d.ts → xv-table-cell.d.ts} +4 -4
  99. package/dist/components/xv-table-cell.js +1 -0
  100. package/dist/components/{xv-table-v2-cell.d.ts → xv-table-row.d.ts} +4 -4
  101. package/dist/components/xv-table-row.js +1 -0
  102. package/dist/components/{xv-table-v2.d.ts → xv-table.d.ts} +4 -4
  103. package/dist/components/xv-table.js +1 -0
  104. package/dist/components/xv-tabs-v2.js +1 -1
  105. package/dist/components/xv-tag-combobox.js +1 -1
  106. package/dist/components/xv-tag-v2.js +1 -1
  107. package/dist/components/xv-text-input-v2.js +1 -1
  108. package/dist/components/xv-textarea.js +1 -1
  109. package/dist/components/xv-tile.js +1 -1
  110. package/dist/components/xv-toggle-tip.js +1 -1
  111. package/dist/components/xv-toggle.js +1 -1
  112. package/dist/components/xv-tooltip-v2.js +1 -1
  113. package/dist/custom-elements.json +1765 -294
  114. package/dist/docs.json +2749 -443
  115. package/dist/esm/{index-B6cY-_U1.js → index-ClusqSO5.js} +1 -1
  116. package/dist/esm/{index-Bu8SrOeR.js → index-DJC3-dS3.js} +15 -10
  117. package/dist/esm/index.js +2 -2
  118. package/dist/esm/loader.js +3 -3
  119. package/dist/esm/{xv-accordion-v2_50.entry.js → xv-accordion-v2_49.entry.js} +1527 -144
  120. package/dist/esm/xv-header-next.entry.js +2 -2
  121. package/dist/esm/xv-mega-menu-next.entry.js +2 -2
  122. package/dist/esm/xv-webcomponents.js +4 -4
  123. package/dist/react/components.d.ts +3 -4
  124. package/dist/react/components.js +3 -4
  125. package/dist/react/{xv-table-v2-expand.d.ts → xv-table-cell.d.ts} +3 -3
  126. package/dist/react/xv-table-cell.js +14 -0
  127. package/dist/react/{xv-table-v2.d.ts → xv-table-row.d.ts} +3 -3
  128. package/dist/react/{xv-table-v2.js → xv-table-row.js} +5 -5
  129. package/dist/react/xv-table.d.ts +18 -0
  130. package/dist/react/xv-table.js +22 -0
  131. package/dist/types/components/xv-table/xv-table-cell/xv-table-cell.d.ts +43 -8
  132. package/dist/types/components/xv-table/xv-table-row/xv-table-row.d.ts +57 -18
  133. package/dist/types/components/xv-table/xv-table.d.ts +298 -9
  134. package/dist/types/components/xv-table/xv-table.model.d.ts +78 -0
  135. package/dist/types/components/xv-table/xv-table.utils.d.ts +47 -0
  136. package/dist/types/components.d.ts +899 -118
  137. package/dist/types/stencil-public-runtime.d.ts +61 -55
  138. package/dist/types/utils/table-layout.d.ts +7 -0
  139. package/dist/vscode-data.json +347 -56
  140. package/dist/xv-webcomponents/index.esm.js +1 -1
  141. package/dist/xv-webcomponents/{p-1ffb0b4f.entry.js → p-0c30d09f.entry.js} +1 -1
  142. package/dist/xv-webcomponents/{p-eb9d7750.entry.js → p-6b58979e.entry.js} +2 -2
  143. package/dist/xv-webcomponents/{p-Bu8SrOeR.js → p-DJC3-dS3.js} +2 -2
  144. package/dist/xv-webcomponents/{p-DB4KqDJz.js → p-DSFVdw3w.js} +1 -1
  145. package/dist/xv-webcomponents/{p-d4d26ff2.entry.js → p-c4173686.entry.js} +1 -1
  146. package/dist/xv-webcomponents/xv-webcomponents.esm.js +1 -1
  147. package/package.json +139 -139
  148. package/dist/collection/components/xv-table/_vars.js +0 -2
  149. package/dist/collection/components/xv-table/xv-table-expand/xv-table-expand.css +0 -58
  150. package/dist/collection/components/xv-table/xv-table-expand/xv-table-expand.js +0 -75
  151. package/dist/components/p-CHtssNO9.js +0 -1
  152. package/dist/components/p-CILNPUHH.js +0 -1
  153. package/dist/components/p-DVZ2BlIP.js +0 -1
  154. package/dist/components/p-bdaoJ1tx.js +0 -1
  155. package/dist/components/xv-table-v2-cell.js +0 -1
  156. package/dist/components/xv-table-v2-expand.d.ts +0 -11
  157. package/dist/components/xv-table-v2-expand.js +0 -1
  158. package/dist/components/xv-table-v2-row.js +0 -1
  159. package/dist/components/xv-table-v2.js +0 -1
  160. package/dist/react/xv-table-v2-cell.d.ts +0 -12
  161. package/dist/react/xv-table-v2-cell.js +0 -14
  162. package/dist/react/xv-table-v2-expand.js +0 -14
  163. package/dist/react/xv-table-v2-row.d.ts +0 -13
  164. package/dist/react/xv-table-v2-row.js +0 -17
  165. package/dist/types/components/xv-table/_vars.d.ts +0 -15
  166. package/dist/types/components/xv-table/xv-table-expand/xv-table-expand.d.ts +0 -8
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var index$1 = require('./index-Cixkr3sz.js');
4
- var index$2 = require('./index-Cfa6bBQW.js');
3
+ var index$1 = require('./index-Dwhgrew8.js');
4
+ var index$2 = require('./index-DaTpiyaU.js');
5
5
  var _vars = require('./_vars-DMytunQw.js');
6
6
 
7
7
  const xvAccordionCss = () => `:host{display:block}`;
@@ -83212,20 +83212,21 @@ const XvOverflowMenu = class {
83212
83212
  document.removeEventListener('click', this.handleClickOutside, { capture: true });
83213
83213
  };
83214
83214
  this.handleClickOutside = (ev) => {
83215
- var _a, _b, _c;
83215
+ var _a, _b;
83216
83216
  if (!this.open)
83217
83217
  return;
83218
- // A shadow-DOM click retargets ev.target to the host in the browser (covered by el.contains).
83219
- // Also check the shadow trigger/list directly so it works when there is no retargeting (jsdom).
83220
- const target = ev.target;
83221
- if (this.el.contains(target))
83218
+ // composedPath is the only check that survives shadow-DOM retargeting: a click inside a menu
83219
+ // that lives in another component's shadow root arrives here retargeted to that outer host.
83220
+ const path = (_b = (_a = ev.composedPath) === null || _a === void 0 ? void 0 : _a.call(ev)) !== null && _b !== void 0 ? _b : [];
83221
+ const inside = (node) => !!node && (path.includes(node) || (path.length === 0 && node.contains(ev.target)));
83222
+ if (inside(this.el))
83222
83223
  return;
83223
- if ((_a = this.triggerButtonEl) === null || _a === void 0 ? void 0 : _a.contains(target))
83224
+ if (inside(this.triggerButtonEl))
83224
83225
  return;
83225
- if ((_b = this.listEl) === null || _b === void 0 ? void 0 : _b.contains(target))
83226
+ if (inside(this.listEl))
83226
83227
  return;
83227
83228
  // A click on the anchor is handled by its own listener (toggle) — don't treat it as "outside".
83228
- if ((_c = this.anchorEl) === null || _c === void 0 ? void 0 : _c.contains(target))
83229
+ if (inside(this.anchorEl))
83229
83230
  return;
83230
83231
  this.open = false;
83231
83232
  };
@@ -83871,174 +83872,1556 @@ const XvTab = class {
83871
83872
  this.loading = false;
83872
83873
  }
83873
83874
  render() {
83874
- return (index$1.h(index$1.Host, { key: '8dcdf7d006b2e187067bf598828007175d15cae8', disabled: this.disabled, name: this.name }, this.loading ? index$1.h("xv-loader-v2", { size: _vars.SIZE_VAR.LG }) : index$1.h("slot", null)));
83875
+ return (index$1.h(index$1.Host, { key: '7147f87058327e099ad257d3821447dac8e3affb', disabled: this.disabled, name: this.name }, this.loading ? index$1.h("xv-loader-v2", { size: _vars.SIZE_VAR.LG }) : index$1.h("slot", null)));
83875
83876
  }
83876
83877
  };
83877
83878
  XvTab.style = xvTabCss();
83878
83879
 
83879
- const xvTableCss = () => `:host{--xv-table-min-height:51.11px;--xv-table-padding-x:16px;--xv-table-padding-y:15px;--xv-table-cols-template:repeat(auto-fit, minmax(0, 1fr));display:block}:host .batch-actions{user-select:none;pointer-events:none;position:absolute;left:0;bottom:100%;width:0;min-height:48px;overflow:hidden;border-radius:3px 3px 0 0;background-color:var(--interactive-01, #273435);display:flex;align-items:center;justify-content:space-between;column-gap:var(--spacing-04);flex-wrap:nowrap;box-sizing:border-box;transition:250ms ease-in-out height, 250ms ease-in-out width, 250ms ease-in-out padding-inline;color:var(--text-on-color, #fff)}:host .batch-actions_content{display:block;overflow:hidden;white-space:nowrap}:host .batch-actions_count{margin:0;white-space:nowrap;font-family:var(--ff-body, Tahoma);font-size:var(--fz-md, 14px);font-style:normal;font-weight:400;line-height:var(--fz-lg, 18px);letter-spacing:0.16px}:host .xv-table{display:flex;flex-direction:column;position:relative}:host .xv-table_wrapper{display:flex;flex-direction:column;position:relative;overflow-x:auto;scrollbar-width:thin;scrollbar-color:var(--layer-accent-03) transparent}:host .xv-table_wrapper ::slotted(*){min-width:1000px}:host .xv-table ::slotted([checked]){background-color:var(--layer-selected-01, #E3E3E3)}:host .xv-table ::slotted([checked]:not([header]):hover){background-color:var(--layer-selected-hover-01, #DADADA)}:host .xv-table ::slotted(xv-table-v2-row[disabled]){pointer-events:none;opacity:0.4;cursor:not-allowed;user-select:none}:host .xv-table ::slotted([slot=footer]:hover),:host .xv-table ::slotted([slot=footer]){background-color:var(--layer-accent-02, #E3E3E3)}:host .xv-table_loading{z-index:10;display:flex;align-items:center;justify-content:center;min-height:var(--xv-table-min-height, 51.11px);position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(255, 255, 255, 0.8)}:host .xv-table-title,:host ::slotted([slot=title]){color:var(--text-primary, #333) !important;font-size:var(--fz-xl, 21px) !important;margin-top:var(--spacing-05, 16px) !important;margin-bottom:var(--spacing-06, 24px) !important;font-family:var(--ff-heading, "Gill Sans");font-style:normal;font-weight:400;line-height:normal}:host([hover]) .xv-table ::slotted(:hover:not([header])){background-color:var(--layer-hover-01, #E9E9E9)}:host(.batchVisible) .batch-actions{pointer-events:initial;user-select:initial;width:100%;padding-inline:var(--xv-table-padding-x)}:host([expandable]) ::slotted(xv-table-v2-row){padding-inline-start:calc(max(10px, var(--xv-table-padding-x)) * 2 + 10px)}:host([variant-checkbox]) ::slotted([slot=footer]:not([variant])){padding-inline-start:calc(max(10px, var(--xv-table-padding-x)) * 2 + 57.97px)}:host([size=xs]){--xv-table-padding-y:7px;--xv-table-min-height:35.1px}:host([size=sm]){--xv-table-padding-y:10px;--xv-table-min-height:41.11px}:host([size=lg]){--xv-table-padding-y:21px;--xv-table-min-height:63.09px}:host([size=xl]){--xv-table-padding-y:31px;--xv-table-min-height:78.77px}`;
83880
+ const DB_NAME = 'xv-webcomponents';
83881
+ const DB_VERSION = 1;
83882
+ const STORE = 'table-layouts';
83883
+ const MAX_AGE_MS = 180 * 24 * 60 * 60 * 1000;
83884
+ const READ_TIMEOUT_MS = 1500;
83885
+ let connection = null;
83886
+ let pruned = false;
83887
+ const layoutId = (owner, storageKey) => `${owner || 'anonymous'}:${storageKey}`;
83888
+ const request = (req) => new Promise((resolve, reject) => {
83889
+ req.onsuccess = () => resolve(req.result);
83890
+ req.onerror = () => reject(req.error);
83891
+ });
83892
+ /**
83893
+ * Our own database on purpose. XvMarketplaceNG's origin already carries a Dexie database, and Dexie
83894
+ * multiplies its version by ten — sharing a name loses the version race and kills the feature (MAR-15943).
83895
+ */
83896
+ const openDb = () => {
83897
+ if (connection)
83898
+ return connection;
83899
+ connection = new Promise(resolve => {
83900
+ if (typeof indexedDB === 'undefined')
83901
+ return resolve(null);
83902
+ let req;
83903
+ try {
83904
+ req = indexedDB.open(DB_NAME, DB_VERSION);
83905
+ }
83906
+ catch (_a) {
83907
+ return resolve(null);
83908
+ }
83909
+ req.onupgradeneeded = () => {
83910
+ const db = req.result;
83911
+ if (db.objectStoreNames.contains(STORE))
83912
+ return;
83913
+ const store = db.createObjectStore(STORE, { keyPath: 'id' });
83914
+ store.createIndex('owner', 'owner');
83915
+ store.createIndex('updatedAt', 'updatedAt');
83916
+ };
83917
+ req.onsuccess = () => resolve(req.result);
83918
+ req.onerror = () => resolve(null);
83919
+ req.onblocked = () => resolve(null);
83920
+ });
83921
+ return connection;
83922
+ };
83923
+ const store = async (mode) => {
83924
+ const db = await openDb();
83925
+ if (!db)
83926
+ return null;
83927
+ try {
83928
+ return db.transaction(STORE, mode).objectStore(STORE);
83929
+ }
83930
+ catch (_a) {
83931
+ return null;
83932
+ }
83933
+ };
83934
+ /** A cold database must not hold the first paint hostage — past this, the declared columns win. */
83935
+ const withTimeout = (promise, fallback, ms = READ_TIMEOUT_MS) => Promise.race([promise, new Promise(resolve => setTimeout(() => resolve(fallback), ms))]);
83936
+ const readLayout = async (owner, storageKey) => {
83937
+ if (!storageKey)
83938
+ return null;
83939
+ const read = (async () => {
83940
+ var _a;
83941
+ try {
83942
+ const objectStore = await store('readonly');
83943
+ if (!objectStore)
83944
+ return null;
83945
+ const record = await request(objectStore.get(layoutId(owner, storageKey)));
83946
+ return (_a = record === null || record === void 0 ? void 0 : record.layout) !== null && _a !== void 0 ? _a : null;
83947
+ }
83948
+ catch (_b) {
83949
+ return null;
83950
+ }
83951
+ })();
83952
+ const layout = await withTimeout(read, null);
83953
+ void pruneLayouts();
83954
+ return layout;
83955
+ };
83956
+ const writeLayout = async (owner, storageKey, layout) => {
83957
+ if (!storageKey)
83958
+ return;
83959
+ try {
83960
+ const objectStore = await store('readwrite');
83961
+ if (!objectStore)
83962
+ return;
83963
+ const record = {
83964
+ id: layoutId(owner, storageKey),
83965
+ owner: owner || 'anonymous',
83966
+ storageKey,
83967
+ layout,
83968
+ updatedAt: Date.now(),
83969
+ };
83970
+ await request(objectStore.put(record));
83971
+ }
83972
+ catch (_a) {
83973
+ // Private mode and a full quota both degrade to "this table does not remember".
83974
+ }
83975
+ };
83976
+ const deleteLayout = async (owner, storageKey) => {
83977
+ if (!storageKey)
83978
+ return;
83979
+ try {
83980
+ const objectStore = await store('readwrite');
83981
+ if (!objectStore)
83982
+ return;
83983
+ await request(objectStore.delete(layoutId(owner, storageKey)));
83984
+ }
83985
+ catch (_a) {
83986
+ // See writeLayout.
83987
+ }
83988
+ };
83989
+ const pruneLayouts = async () => {
83990
+ if (pruned)
83991
+ return;
83992
+ pruned = true;
83993
+ try {
83994
+ const objectStore = await store('readwrite');
83995
+ if (!objectStore)
83996
+ return;
83997
+ const range = IDBKeyRange.upperBound(Date.now() - MAX_AGE_MS);
83998
+ const stale = await request(objectStore.index('updatedAt').getAll(range));
83999
+ stale.forEach(record => objectStore.delete(record.id));
84000
+ }
84001
+ catch (_a) {
84002
+ // See writeLayout.
84003
+ }
84004
+ };
84005
+
84006
+ const XV_TABLE_ROW_TAG = 'xv-table-row';
84007
+ const XV_TABLE_CELL_TAG = 'xv-table-cell';
84008
+ const XV_TABLE_LAYOUT_VERSION = 1;
84009
+ /** The floor a resize drag may not cross, when the column names no minWidth. */
84010
+ const XV_TABLE_MIN_COLUMN_WIDTH = 64;
84011
+ /** Per visible column, the width below which the table scrolls instead of squeezing. */
84012
+ const XV_TABLE_SCROLL_COLUMN_WIDTH = 120;
84013
+ const XV_TABLE_CONTROL_WIDTH = 48;
84014
+ const XV_TABLE_DEFAULT_PAGE_SIZES = [10, 20, 30, 40, 50, 100];
84015
+
84016
+ const ORDER_BY = /^(asc|desc)\((.+)\)$/;
84017
+ /** Array and object props accept their JSON string form so they stay settable from plain markup. */
84018
+ const parseProp = (value, fallback) => {
84019
+ if (typeof value !== 'string')
84020
+ return value !== null && value !== void 0 ? value : fallback;
84021
+ if (!value.trim())
84022
+ return fallback;
84023
+ try {
84024
+ return JSON.parse(value);
84025
+ }
84026
+ catch (_a) {
84027
+ return fallback;
84028
+ }
84029
+ };
84030
+ const parsePageSizes = (value) => {
84031
+ const parsed = typeof value === 'string' && value.includes(',')
84032
+ ? value.split(',').map(part => Number(part.trim()))
84033
+ : parseProp(value, XV_TABLE_DEFAULT_PAGE_SIZES);
84034
+ const sizes = (parsed || []).filter(size => Number.isFinite(size) && size > 0);
84035
+ return sizes.length ? sizes : XV_TABLE_DEFAULT_PAGE_SIZES;
84036
+ };
84037
+ const parseSortBy = (value) => {
84038
+ if (!value)
84039
+ return null;
84040
+ if (typeof value !== 'string') {
84041
+ return value.name ? { name: value.name, direction: value.direction || _vars.XV_SORT_DIR.ASC } : null;
84042
+ }
84043
+ const match = ORDER_BY.exec(value.trim());
84044
+ if (!match)
84045
+ return null;
84046
+ return { name: match[2], direction: match[1] };
84047
+ };
84048
+ const nextSortDirection = (current) => current === _vars.XV_SORT_DIR.ASC ? _vars.XV_SORT_DIR.DESC : _vars.XV_SORT_DIR.ASC;
84049
+ const sortName = (column) => column.sortName || column.id;
84050
+ const cellValue = (row, column) => {
84051
+ if (typeof column.value === 'function')
84052
+ return column.value(row);
84053
+ const key = column.value || column.id;
84054
+ return row === null || row === void 0 ? void 0 : row[key];
84055
+ };
84056
+ const isEmpty = (value) => value === null || value === undefined || value === '';
84057
+ // Only a date-shaped string is read as a date: an article number must not sort as a year.
84058
+ const DATE_LIKE = /^\d{4}-\d{2}-\d{2}([T ]|$)|^\d{1,2}[./-]\d{1,2}[./-]\d{2,4}$/;
84059
+ const toComparable = (value) => {
84060
+ if (value instanceof Date)
84061
+ return value.getTime();
84062
+ if (typeof value === 'number' || typeof value === 'boolean')
84063
+ return value;
84064
+ const text = String(value);
84065
+ const asDate = DATE_LIKE.test(text.trim()) ? Date.parse(text) : NaN;
84066
+ return Number.isNaN(asDate) ? text : asDate;
84067
+ };
84068
+ /** Empty values sort last in both directions — a blank cell is not "smallest", it is missing. */
84069
+ const compareValues = (a, b, locale) => {
84070
+ if (isEmpty(a) && isEmpty(b))
84071
+ return 0;
84072
+ if (isEmpty(a))
84073
+ return 1;
84074
+ if (isEmpty(b))
84075
+ return -1;
84076
+ if (typeof a === 'number' && typeof b === 'number')
84077
+ return a - b;
84078
+ const left = toComparable(a);
84079
+ const right = toComparable(b);
84080
+ if (typeof left === 'string' || typeof right === 'string') {
84081
+ return String(left).localeCompare(String(right), locale, { numeric: true, sensitivity: 'base' });
84082
+ }
84083
+ return Number(left) - Number(right);
84084
+ };
84085
+ const sortRows = (rows, column, direction, locale) => {
84086
+ if (!column || direction === _vars.XV_SORT_DIR.NONE)
84087
+ return rows;
84088
+ const factor = direction === _vars.XV_SORT_DIR.DESC ? -1 : 1;
84089
+ // Read each cell once rather than four times per comparison.
84090
+ const decorated = rows.map(row => ({ row, key: cellValue(row, column) }));
84091
+ decorated.sort((a, b) => {
84092
+ const result = compareValues(a.key, b.key, locale);
84093
+ // Empty always trails, so it must not be flipped by a descending sort.
84094
+ if (isEmpty(a.key) !== isEmpty(b.key))
84095
+ return result;
84096
+ return result * factor;
84097
+ });
84098
+ return decorated.map(item => item.row);
84099
+ };
84100
+ const totalPages = (total, pageSize) => Math.ceil((total || 0) / (pageSize || 10)) || 1;
84101
+ const clampPage = (page, pages) => Math.min(Math.max(page || 1, 1), Math.max(pages, 1));
84102
+ const pageSlice = (rows, page, pageSize) => {
84103
+ const size = pageSize || 10;
84104
+ const start = (clampPage(page, totalPages(rows.length, size)) - 1) * size;
84105
+ return rows.slice(start, start + size);
84106
+ };
84107
+ const visibleColumns = (columns) => columns.filter(column => !column.hidden);
84108
+ const hideableColumns = (columns) => columns.filter(column => column.hideable);
84109
+ /** A column may narrow a table-level switch, never widen it. */
84110
+ const columnAllows = (column, table, key) => { var _a; return table && ((_a = column[key]) !== null && _a !== void 0 ? _a : true); };
84111
+ const clampWidth = (width, column) => {
84112
+ const min = column.minWidth || XV_TABLE_MIN_COLUMN_WIDTH;
84113
+ const max = column.maxWidth || Number.MAX_SAFE_INTEGER;
84114
+ return Math.round(Math.min(Math.max(width, min), max));
84115
+ };
84116
+ /**
84117
+ * What the rigid parts of the table actually need. A pixel column needs its width; a percentage
84118
+ * column squeezes by definition and asks for nothing; a column that named no width gets the
84119
+ * scroll-width guess. Guessing for all of them made a table of narrow columns scroll for nothing.
84120
+ */
84121
+ const tableMinWidth = (columns, minWidth, controls = 0) => {
84122
+ if (minWidth)
84123
+ return minWidth + controls;
84124
+ const declared = visibleColumns(columns).reduce((total, column) => {
84125
+ if (typeof column.width === 'number')
84126
+ return total + column.width;
84127
+ return column.width ? total : total + XV_TABLE_SCROLL_COLUMN_WIDTH;
84128
+ }, 0);
84129
+ return declared + controls;
84130
+ };
84131
+ /**
84132
+ * The grid track list. Resize rewrites this one string on the host, which is a single DOM write
84133
+ * per pointermove — a colgroup would need one per `<col>`. One track per control column: a grip
84134
+ * and a checkbox are separate cells, so they need separate tracks.
84135
+ */
84136
+ const buildColumnTracks = (columns, leading = [], trailing = []) => {
84137
+ const shown = visibleColumns(columns);
84138
+ // `table-layout: fixed`, which is what these tables were written against: while some column left
84139
+ // its width open, a declared width is exact and the open ones take what is left. Once every
84140
+ // column has named a width, the widths also become proportions and the table scales up to fit —
84141
+ // but never below what was declared, so a narrow column keeps the room its content needs.
84142
+ const proportional = shown.length > 0 && shown.every(column => !!column.width);
84143
+ return [
84144
+ ...leading.map(width => `${width}px`),
84145
+ // No space inside minmax(): the track list is indexed as an array during a resize drag.
84146
+ ...shown.map(column => {
84147
+ if (!column.width)
84148
+ return `minmax(${column.minWidth || XV_TABLE_MIN_COLUMN_WIDTH}px,1fr)`;
84149
+ if (typeof column.width === 'number') {
84150
+ return proportional
84151
+ ? `minmax(${column.width}px,${column.width}fr)`
84152
+ : `${column.width}px`;
84153
+ }
84154
+ // A percentage keeps its exact share of the table and squeezes with it, never forcing a scroll.
84155
+ const percent = /^([0-9.]+)%$/.test(column.width);
84156
+ return percent ? `minmax(0,${column.width})` : column.width;
84157
+ }),
84158
+ ...trailing.map(width => `${width}px`),
84159
+ ];
84160
+ };
84161
+ const buildColumnTemplate = (columns, leading = [], trailing = []) => buildColumnTracks(columns, leading, trailing).join(' ');
84162
+ const moveItem = (items, from, to) => {
84163
+ const next = [...items];
84164
+ next.splice(to, 0, next.splice(from, 1)[0]);
84165
+ return next;
84166
+ };
84167
+ /** Hidden columns keep their absolute slot while the visible ones move around them. */
84168
+ const mergeVisibleOrder = (columns, ordered) => {
84169
+ const queue = [...ordered];
84170
+ return columns.map(column => (column.hidden ? column : queue.shift() || column));
84171
+ };
84172
+ /**
84173
+ * Only the deviations from the declared columns are stored. An untouched column follows the code,
84174
+ * so a later default still reaches everyone who once dragged a column edge.
84175
+ */
84176
+ const diffLayout = (columns, declared) => {
84177
+ const defaults = new Map(declared.map(column => [column.id, column]));
84178
+ const order = columns.map(column => column.id);
84179
+ const widths = {};
84180
+ const hidden = {};
84181
+ columns.forEach(column => {
84182
+ const base = defaults.get(column.id);
84183
+ // Only a resize writes a width, and a resize always writes pixels: a declared `25%` is not a
84184
+ // deviation, and storing it would freeze the layout the next time the code changes.
84185
+ if (typeof column.width === 'number' && column.width !== (base === null || base === void 0 ? void 0 : base.width)) {
84186
+ widths[column.id] = column.width;
84187
+ }
84188
+ if (!!column.hidden !== !!(base === null || base === void 0 ? void 0 : base.hidden))
84189
+ hidden[column.id] = !!column.hidden;
84190
+ });
84191
+ return {
84192
+ v: XV_TABLE_LAYOUT_VERSION,
84193
+ order: order.join() === declared.map(column => column.id).join() ? [] : order,
84194
+ widths,
84195
+ hidden,
84196
+ };
84197
+ };
84198
+ const isLayoutChanged = (layout) => !!layout && (!!layout.order.length || !!Object.keys(layout.widths).length || !!Object.keys(layout.hidden).length);
84199
+ /** Merges onto clones, so a stored width never writes back into the page's declared preset. */
84200
+ const applyLayout = (declared, layout) => {
84201
+ const clones = declared.map(column => (Object.assign({}, column)));
84202
+ if (!layout || layout.v !== XV_TABLE_LAYOUT_VERSION)
84203
+ return clones;
84204
+ const byId = new Map(clones.map(column => [column.id, column]));
84205
+ const ordered = layout.order.map(id => byId.get(id)).filter(Boolean);
84206
+ clones.forEach((column, index) => {
84207
+ if (!ordered.includes(column))
84208
+ ordered.splice(Math.min(index, ordered.length), 0, column);
84209
+ });
84210
+ ordered.forEach(column => {
84211
+ const width = layout.widths[column.id];
84212
+ if (width)
84213
+ column.width = width;
84214
+ const hidden = layout.hidden[column.id];
84215
+ if (hidden !== undefined && column.hideable)
84216
+ column.hidden = hidden;
84217
+ });
84218
+ return ordered;
84219
+ };
84220
+ const formatCell = (value, column, locale) => {
84221
+ if (isEmpty(value))
84222
+ return '';
84223
+ switch (column.format) {
84224
+ case 'number':
84225
+ return new Intl.NumberFormat(locale).format(Number(value));
84226
+ case 'currency':
84227
+ return new Intl.NumberFormat(locale, {
84228
+ style: 'currency',
84229
+ currency: column.formatArg || 'EUR',
84230
+ }).format(Number(value));
84231
+ case 'date': {
84232
+ const date = value instanceof Date ? value : new Date(String(value));
84233
+ return Number.isNaN(date.getTime()) ? String(value) : new Intl.DateTimeFormat(locale).format(date);
84234
+ }
84235
+ case 'period': {
84236
+ const [start, end] = Array.isArray(value) ? value : [];
84237
+ const part = (input, options) => {
84238
+ if (isEmpty(input))
84239
+ return '';
84240
+ const date = input instanceof Date ? input : new Date(String(input));
84241
+ return Number.isNaN(date.getTime()) ? '' : new Intl.DateTimeFormat(locale, options).format(date);
84242
+ };
84243
+ // A missing end leaves no dangling separator, and the year is only spelled once.
84244
+ return [
84245
+ part(start, { day: '2-digit', month: '2-digit' }),
84246
+ part(end, { day: '2-digit', month: '2-digit', year: '2-digit' }),
84247
+ ].filter(Boolean).join(' - ');
84248
+ }
84249
+ case 'list':
84250
+ return Array.isArray(value) ? value.join(column.formatArg || ', ') : String(value);
84251
+ default:
84252
+ return String(value);
84253
+ }
84254
+ };
84255
+
84256
+ const xvTableCss = () => `@charset "UTF-8";:host{--xv-table-columns:1fr;--xv-table-height:40px;--xv-table-padding-x:var(--spacing-05);--xv-table-padding-y:var(--spacing-03);--xv-table-border-color:var(--border-subtle-01);--xv-table-header-bg:var(--layer-accent-01);--xv-table-loading-bg:var(--layer-02);--xv-table-loading-opacity:0.8;--xv-table-max-height:none;--xv-table-scroll-width:1180px;display:block;position:relative;color:var(--text-primary);font-family:var(--ff-body);font-size:var(--fz-md)}:host([block]){width:100%}:host([size=xs]){--xv-table-height:24px;--xv-table-padding-x:var(--spacing-03);--xv-table-padding-y:var(--spacing-01)}:host([size=sm]){--xv-table-height:32px;--xv-table-padding-x:var(--spacing-04);--xv-table-padding-y:var(--spacing-02)}:host([size=md]){--xv-table-height:40px;--xv-table-padding-x:var(--spacing-05);--xv-table-padding-y:var(--spacing-03)}:host([size=lg]){--xv-table-height:48px;--xv-table-padding-x:var(--spacing-05);--xv-table-padding-y:var(--spacing-04)}:host([size=xl]){--xv-table-height:64px;--xv-table-padding-x:var(--spacing-06);--xv-table-padding-y:var(--spacing-05)}:host(.is-dragging){cursor:grabbing;user-select:none}.heading{padding:var(--spacing-05) var(--spacing-05) var(--spacing-06)}.heading_title{margin:0;font-family:var(--ff-heading);font-size:var(--fz-xl);font-weight:400;line-height:28px}.heading_description{margin:var(--spacing-02) 0 0;color:var(--text-secondary);line-height:18px}.bar{position:sticky;left:0;z-index:10}.bar_toolbar{display:flex;align-items:center;gap:var(--spacing-03);min-height:var(--xv-table-height)}.bar_toolbar ::slotted(*){flex:1 1 auto;min-width:0}.bar_batch{position:absolute;inset:0;z-index:2;display:flex;align-items:center;gap:var(--spacing-03);padding:0 var(--spacing-05);border-radius:3px 3px 0 0;background:var(--interactive-01);color:var(--text-on-color)}.bar_count{margin-left:auto;font-weight:600}.scroll{position:relative}@media screen and (max-width: 1180px){.scroll{overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;scrollbar-color:var(--layer-accent-03) transparent}.grid{min-width:max(var(--xv-table-min-width), var(--xv-table-scroll-width))}}.scroll--overflowing{overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;scrollbar-color:var(--layer-accent-03) transparent}:host([min-width]:not([min-width="0"])) .scroll{overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;scrollbar-color:var(--layer-accent-03) transparent}:host([min-width]:not([min-width="0"])) .grid{min-width:var(--xv-table-min-width)}:host([sticky-header]) .scroll{min-height:0;max-height:var(--xv-table-max-height);overflow-y:auto}.grid{display:grid;grid-template-columns:var(--xv-table-columns);box-sizing:border-box;border:1px solid var(--xv-table-border-color);border-bottom:0}:host([sticky-header]) ::slotted(xv-table-row[header]),:host([sticky-header]) xv-table-row[header]{position:sticky;top:0;z-index:5}.body{grid-column:1/-1;display:grid;grid-template-columns:subgrid}.body[hidden]{display:none}.skeleton_row{grid-column:1/-1;display:grid;grid-template-columns:subgrid;min-height:var(--xv-table-height);box-shadow:inset 0 -1px 0 0 var(--border-subtle-00)}.skeleton_cell{display:flex;align-items:center;padding:var(--xv-table-padding-y) var(--xv-table-padding-x)}.skeleton_bar{width:100%;height:12px;border-radius:2px;background:var(--layer-accent-01);animation:xv-table-pulse 1.4s ease-in-out infinite}@keyframes xv-table-pulse{0%,100%{opacity:1}50%{opacity:0.4}}.empty{display:flex;align-items:center;justify-content:center;min-height:calc(var(--xv-table-height) * 2);border:1px solid var(--xv-table-border-color);border-top:0;color:var(--text-secondary)}.loading{position:absolute;inset:0;z-index:10;display:flex;align-items:center;justify-content:center}.loading::before{content:"";position:absolute;inset:0;background:var(--xv-table-loading-bg);opacity:var(--xv-table-loading-opacity)}.picker{margin-left:auto}.picker_list{display:flex;flex-direction:column;gap:var(--spacing-02);max-height:320px;overflow-y:auto;padding:var(--spacing-03)}.picker_trigger{position:relative;display:inline-flex;color:var(--icon-primary)}.picker_marker{position:absolute;top:-2px;right:-4px;width:6px;height:6px;border-radius:50%;background:var(--background-brand)}.pagination{border:1px solid var(--xv-table-border-color);border-top:0}`;
83880
84257
 
84258
+ const CHECKBOX_EVENT = 'eventChange';
84259
+ const INTERACTIVE = 'a,button,input,select,textarea,[role="button"],xv-button-v2,xv-link-v2,xv-checkbox-v2,xv-radio-v2,xv-overflow-menu-v2,xv-tooltip-v2';
83881
84260
  const XvTable = class {
83882
84261
  constructor(hostRef) {
83883
84262
  index$1.registerInstance(this, hostRef);
84263
+ this.sortChange = index$1.createEvent(this, "sortChange", 7);
84264
+ this.selectedChange = index$1.createEvent(this, "selectedChange", 7);
84265
+ this.expandedChange = index$1.createEvent(this, "expandedChange", 7);
84266
+ this.pageChange = index$1.createEvent(this, "pageChange", 7);
84267
+ this.layoutChange = index$1.createEvent(this, "layoutChange", 7);
84268
+ this.rowClick = index$1.createEvent(this, "rowClick", 7);
84269
+ this.rowOrderChange = index$1.createEvent(this, "rowOrderChange", 7);
84270
+ /** Column definitions. Accepts its JSON string form so it is settable from plain markup. */
84271
+ this.columns = [];
84272
+ /** Row data. Ignored when `xv-table-row` children are slotted. */
84273
+ this.rows = [];
84274
+ /** Property of a row object that identifies it in selection and expansion payloads. */
84275
+ this.rowKey = 'id';
84276
+ /** Row height ladder. */
83884
84277
  this.size = _vars.SIZE_VAR.MD;
83885
- this.selected = new Map();
83886
- this.selectedCount = 0;
84278
+ /** Stretches the table to the full width of its container. */
84279
+ this.block = false;
84280
+ /** Covers the body with a loading state. */
84281
+ this.loading = false;
84282
+ /** Placeholder rows drawn while `loading`. Zero draws a spinner instead. */
84283
+ this.skeletonRows = 0;
84284
+ /** Highlights a row on pointer hover. */
84285
+ this.hover = false;
84286
+ /** Emits `rowClick` when a row is clicked outside an interactive element. */
84287
+ this.rowClickable = false;
84288
+ /** Title above the table. */
84289
+ this.label = '';
84290
+ /** Supporting text under the title. */
84291
+ this.description = '';
84292
+ /** Shown when there are no rows. */
84293
+ this.emptyLabel = '';
84294
+ /** Text of the batch bar counter. `{count}` is replaced with the number of selected rows. */
84295
+ this.selectedLabel = '';
84296
+ /** Tooltip on the column picker trigger. */
84297
+ this.columnsLabel = 'Columns';
84298
+ /** Text of the button that restores the declared column layout. */
84299
+ this.resetLabel = 'Reset';
84300
+ /** Accessible name of a row's expand toggle. */
84301
+ this.expandLabel = 'Toggle row';
84302
+ /** Accessible name of a row's drag grip. */
84303
+ this.reorderLabel = 'Drag to reorder';
84304
+ /**
84305
+ * `none` makes headers inert whatever the column says; `client` sorts the `rows` prop itself;
84306
+ * `server` offers the affordance and only emits `sortChange` for the consumer to reload.
84307
+ */
84308
+ this.sortMode = 'none';
84309
+ /** Active sort, as `asc(field)` / `desc(field)` or an object. */
84310
+ this.sortBy = '';
84311
+ /** `multiple` renders checkboxes, `single` renders radios. */
84312
+ this.selection = 'none';
84313
+ /** Values of the selected rows. */
84314
+ this.selected = [];
84315
+ /** Whether rows expand, and whether more than one may be open. */
84316
+ this.expandMode = 'none';
84317
+ /** Values of the expanded rows. */
84318
+ this.expanded = [];
84319
+ /** `client` slices the `rows` prop; `server` only emits `pageChange`. */
84320
+ this.paginationMode = 'none';
84321
+ /** Current page, 1-based. */
84322
+ this.page = 1;
84323
+ /** Rows per page. */
84324
+ this.pageSize = 10;
84325
+ /** Total row count, for `server` pagination. */
84326
+ this.total = 0;
84327
+ /** Page size choices. Accepts a comma-separated attribute. */
84328
+ this.pageSizeOptions = [10, 20, 30, 40, 50, 100];
84329
+ /**
84330
+ * Allows dragging column edges. Off by default: no handle is rendered and nothing is bound
84331
+ * until it is switched on. A column may switch itself off, never on.
84332
+ */
84333
+ this.resizable = false;
84334
+ /** Allows dragging column headers into a new order. Off by default, like `resizable`. */
84335
+ this.reorderable = false;
84336
+ /**
84337
+ * Allows dragging rows into a new order. Off by default: nothing is bound and no handle is
84338
+ * rendered until it is switched on.
84339
+ */
84340
+ this.rowReorderable = false;
84341
+ /** Whether the whole row drags, or only a grip in a leading control cell. */
84342
+ this.rowReorderHandle = 'icon';
84343
+ /** Keeps the header visible while the body scrolls. */
84344
+ this.stickyHeader = false;
84345
+ /**
84346
+ * Width below which the table scrolls instead of squeezing, at any viewport. Left unset, a table
84347
+ * only stops squeezing below 1180px, where it scrolls at the width its columns declared.
84348
+ */
84349
+ this.minWidth = 0;
84350
+ /** Persists the column layout under this key. Empty means the layout is not remembered. */
84351
+ this.storageKey = '';
84352
+ /** Scopes the stored layout to a user. */
84353
+ this.storageOwner = 'anonymous';
84354
+ /** Controlled column layout. Overrides whatever is stored. */
84355
+ this.layout = null;
84356
+ /** Locale used for sorting and cell formatting. Falls back to the nearest `[lang]` ancestor. */
84357
+ this.locale = '';
84358
+ this.columnState = [];
84359
+ this.sortState = null;
84360
+ this.selectedValues = [];
84361
+ this.expandedValues = [];
84362
+ this.layoutPending = false;
84363
+ this.columnDragging = false;
84364
+ this.dragOverId = '';
84365
+ this.dropRowIndex = -1;
84366
+ this.slottedRowCount = 0;
84367
+ this.derivedTracks = [];
84368
+ this.hasSlottedHeader = false;
84369
+ this.hasSlottedHeading = false;
84370
+ this.hasSlottedEmpty = false;
84371
+ this.overflowing = false;
84372
+ this.declared = [];
84373
+ this.declaredSignature = '';
84374
+ /** Whether the columns came from a slotted header rather than the `columns` prop. */
84375
+ this.fromMarkup = false;
84376
+ this.rowData = [];
84377
+ this.seededExpanded = false;
84378
+ // Only rows this table collapsed are re-shown, so a consumer's own [hidden] is left alone.
84379
+ this.collapsed = new WeakSet();
84380
+ this.dragRowIndex = -1;
84381
+ this.layoutToken = 0;
84382
+ this.dragColumnId = '';
84383
+ /**
84384
+ * A declared width is a floor, so columns that cannot fit overflow rather than squeeze. The table
84385
+ * scrolls them into reach instead of letting them hang outside the block they were given.
84386
+ */
84387
+ this.measureOverflow = () => {
84388
+ if (!this.scrollEl)
84389
+ return;
84390
+ const overflowing = this.scrollEl.scrollWidth - this.scrollEl.clientWidth > 1;
84391
+ if (overflowing !== this.overflowing)
84392
+ this.overflowing = overflowing;
84393
+ };
84394
+ this.toggleSort = (column) => {
84395
+ var _a;
84396
+ // A finished column drag still fires a click on the header — that must not sort it.
84397
+ if (!this.isSortable(column) || this.columnDragging)
84398
+ return;
84399
+ const name = sortName(column);
84400
+ const direction = nextSortDirection(((_a = this.sortState) === null || _a === void 0 ? void 0 : _a.name) === name ? this.sortState.direction : null);
84401
+ this.sortState = { name, direction };
84402
+ this.sortChange.emit(this.sortState);
84403
+ };
84404
+ this.resizeStart = (event, column, handle) => {
84405
+ if (event.button !== 0)
84406
+ return;
84407
+ event.preventDefault();
84408
+ event.stopPropagation();
84409
+ const shown = this.visible;
84410
+ const index = shown.indexOf(column);
84411
+ // Trading with a neighbour keeps the total, so the table never stops filling its container.
84412
+ const pairIndex = index + 1 < shown.length ? index + 1 : index - 1;
84413
+ const pair = shown[pairIndex];
84414
+ const cells = this.headerCells();
84415
+ const startWidth = cells[index].getBoundingClientRect().width;
84416
+ const pairStart = pair ? cells[pairIndex].getBoundingClientRect().width : 0;
84417
+ const startX = event.clientX;
84418
+ const offset = this.leadingTracks.length;
84419
+ let width = startWidth;
84420
+ let pairWidth = pairStart;
84421
+ handle.setPointerCapture(event.pointerId);
84422
+ // Written straight onto the grid: a re-render per pointermove stutters on a full page.
84423
+ const move = (moveEvent) => {
84424
+ var _a;
84425
+ width = clampWidth(startWidth + moveEvent.clientX - startX, column);
84426
+ if (pair) {
84427
+ // The neighbour's own floor caps the drag, so neither column is squeezed past its minimum.
84428
+ pairWidth = clampWidth(pairStart - (width - startWidth), pair);
84429
+ width = clampWidth(startWidth + (pairStart - pairWidth), column);
84430
+ }
84431
+ const tracks = buildColumnTracks(this.columnState, this.leadingTracks, this.trailingTracks);
84432
+ tracks[index + offset] = `${width}px`;
84433
+ if (pair)
84434
+ tracks[pairIndex + offset] = `${pairWidth}px`;
84435
+ (_a = this.gridEl) === null || _a === void 0 ? void 0 : _a.style.setProperty('--xv-table-columns', tracks.join(' '));
84436
+ };
84437
+ const stop = () => {
84438
+ handle.removeEventListener('pointermove', move);
84439
+ handle.removeEventListener('pointerup', stop);
84440
+ handle.removeEventListener('pointercancel', stop);
84441
+ this.columnState = this.columnState.map(item => {
84442
+ if (item.id === column.id)
84443
+ return Object.assign(Object.assign({}, item), { width });
84444
+ if (pair && item.id === pair.id)
84445
+ return Object.assign(Object.assign({}, item), { width: pairWidth });
84446
+ return item;
84447
+ });
84448
+ this.commitLayout();
84449
+ };
84450
+ handle.addEventListener('pointermove', move);
84451
+ handle.addEventListener('pointerup', stop);
84452
+ handle.addEventListener('pointercancel', stop);
84453
+ };
84454
+ this.resizeReset = (column) => {
84455
+ var _a;
84456
+ const width = (_a = this.declared.find(item => item.id === column.id)) === null || _a === void 0 ? void 0 : _a.width;
84457
+ this.columnState = this.columnState.map(item => (item.id === column.id ? Object.assign(Object.assign({}, item), { width }) : item));
84458
+ this.commitLayout();
84459
+ };
84460
+ this.headPointerDown = (event) => {
84461
+ const hit = this.headerCellFrom(event);
84462
+ if (!hit)
84463
+ return;
84464
+ const path = event.composedPath();
84465
+ if (!path.some(node => { var _a; return (_a = node === null || node === void 0 ? void 0 : node.classList) === null || _a === void 0 ? void 0 : _a.contains('resize'); }))
84466
+ return;
84467
+ this.resizeStart(event, hit.column, event.composedPath()[0]);
84468
+ };
84469
+ this.headKeyDown = (event) => {
84470
+ if (event.key !== 'Enter' && event.key !== ' ')
84471
+ return;
84472
+ const hit = this.headerCellFrom(event);
84473
+ if (!hit)
84474
+ return;
84475
+ event.preventDefault();
84476
+ this.toggleSort(hit.column);
84477
+ };
84478
+ this.headDblClick = (event) => {
84479
+ const path = event.composedPath();
84480
+ if (!path.some(node => { var _a; return (_a = node === null || node === void 0 ? void 0 : node.classList) === null || _a === void 0 ? void 0 : _a.contains('resize'); }))
84481
+ return;
84482
+ const hit = this.headerCellFrom(event);
84483
+ if (hit)
84484
+ this.resizeReset(hit.column);
84485
+ };
84486
+ this.headDragStart = (event) => {
84487
+ const hit = this.headerCellFrom(event);
84488
+ if (hit)
84489
+ this.dragStart(event, hit.column);
84490
+ };
84491
+ this.headDragOver = (event) => {
84492
+ const hit = this.headerCellFrom(event);
84493
+ if (hit)
84494
+ this.dragOver(event, hit.column, hit.cell);
84495
+ };
84496
+ this.headDrop = (event) => {
84497
+ const hit = this.headerCellFrom(event);
84498
+ if (hit)
84499
+ this.drop(event, hit.column);
84500
+ };
84501
+ this.dragStart = (event, column) => {
84502
+ var _a;
84503
+ this.dragColumnId = column.id;
84504
+ this.columnDragging = true;
84505
+ (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.setData('text/plain', column.id);
84506
+ if (event.dataTransfer)
84507
+ event.dataTransfer.effectAllowed = 'move';
84508
+ };
84509
+ this.dragOver = (event, column, cell) => {
84510
+ if (!this.dragColumnId || column.id === this.dragColumnId)
84511
+ return;
84512
+ if (!columnAllows(column, this.reorderable, 'reorderable'))
84513
+ return;
84514
+ event.preventDefault();
84515
+ if (this.dragOverId === column.id)
84516
+ return;
84517
+ this.dragOverId = column.id;
84518
+ this.headerCells().forEach(item => item.classList.toggle('drag-over', item === cell));
84519
+ };
84520
+ this.drop = (event, column) => {
84521
+ event.preventDefault();
84522
+ this.clearDragOver();
84523
+ if (!this.dragColumnId || column.id === this.dragColumnId)
84524
+ return;
84525
+ if (!columnAllows(column, this.reorderable, 'reorderable'))
84526
+ return;
84527
+ const shown = this.visible;
84528
+ const from = shown.findIndex(item => item.id === this.dragColumnId);
84529
+ const to = shown.findIndex(item => item.id === column.id);
84530
+ if (from < 0 || to < 0)
84531
+ return;
84532
+ this.columnState = mergeVisibleOrder(this.columnState, moveItem(shown, from, to));
84533
+ this.commitLayout();
84534
+ };
84535
+ this.dragEnd = () => {
84536
+ this.dragColumnId = '';
84537
+ this.clearDragOver();
84538
+ // The trailing click lands after dragend, so the sort guard has to outlive the gesture.
84539
+ setTimeout(() => (this.columnDragging = false), 0);
84540
+ };
84541
+ this.toggleSelectAll = () => {
84542
+ // Tri-state: a partial box clears what is picked rather than completing the set.
84543
+ this.setSelection(this.selectedValues.length ? [] : this.rowValues());
84544
+ };
84545
+ this.toggleColumn = (column) => {
84546
+ this.columnState = this.columnState.map(item => item.id === column.id ? Object.assign(Object.assign({}, item), { hidden: !item.hidden }) : item);
84547
+ this.commitLayout();
84548
+ };
84549
+ this.rowDragStart = (event) => {
84550
+ const row = this.rowFrom(event);
84551
+ if (!row || row.group || row.disabled)
84552
+ return;
84553
+ this.dragRowIndex = this.bodyRows().indexOf(row);
84554
+ if (this.dragRowIndex < 0)
84555
+ return;
84556
+ row.classList.add('is-dragging');
84557
+ if (event.dataTransfer)
84558
+ event.dataTransfer.effectAllowed = 'move';
84559
+ };
84560
+ this.rowDragOver = (event) => {
84561
+ if (this.dragRowIndex < 0)
84562
+ return;
84563
+ const row = this.rowFrom(event);
84564
+ if (!row || row.group)
84565
+ return;
84566
+ const index = this.bodyRows().indexOf(row);
84567
+ if (index < 0 || index === this.dragRowIndex)
84568
+ return;
84569
+ event.preventDefault();
84570
+ if (index === this.dropRowIndex)
84571
+ return;
84572
+ this.dropRowIndex = index;
84573
+ // The line marks the edge the row will land against, so its side follows the drag direction.
84574
+ this.bodyRows().forEach((item, i) => {
84575
+ item.classList.toggle('drop-above', i === index && index < this.dragRowIndex);
84576
+ item.classList.toggle('drop-below', i === index && index > this.dragRowIndex);
84577
+ });
84578
+ };
84579
+ this.rowDrop = (event) => {
84580
+ if (this.dragRowIndex < 0)
84581
+ return;
84582
+ event.preventDefault();
84583
+ const to = this.dropRowIndex;
84584
+ const from = this.dragRowIndex;
84585
+ this.rowDragEnd();
84586
+ if (to < 0 || from === to)
84587
+ return;
84588
+ this.rowOrderChange.emit({ from, to });
84589
+ };
84590
+ this.rowDragEnd = () => {
84591
+ this.bodyRows().forEach(row => row.classList.remove('is-dragging', 'drop-above', 'drop-below'));
84592
+ this.dragRowIndex = -1;
84593
+ this.dropRowIndex = -1;
84594
+ };
84595
+ /** One listener for the whole body instead of a child event per row. */
84596
+ this.bodyChange = (event) => {
84597
+ var _a;
84598
+ const path = event.composedPath();
84599
+ const row = path.find(node => { var _a; return ((_a = node === null || node === void 0 ? void 0 : node.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === XV_TABLE_ROW_TAG; });
84600
+ if (!row || row.disabled)
84601
+ return;
84602
+ // A checkbox the consumer put in a cell is its own; only the row's own control selects a row.
84603
+ const control = path.find(node => { var _a; return (_a = node === null || node === void 0 ? void 0 : node.classList) === null || _a === void 0 ? void 0 : _a.contains('control_input'); });
84604
+ if (!control || !((_a = row.shadowRoot) === null || _a === void 0 ? void 0 : _a.contains(control)))
84605
+ return;
84606
+ event.stopPropagation();
84607
+ if (row.hasAttribute('header'))
84608
+ return this.toggleSelectAll();
84609
+ this.toggleRowSelection(row.value);
84610
+ };
84611
+ this.gridClick = (event) => {
84612
+ const path = event.composedPath();
84613
+ if (path.some(node => { var _a; return (_a = node === null || node === void 0 ? void 0 : node.classList) === null || _a === void 0 ? void 0 : _a.contains('resize'); }))
84614
+ return;
84615
+ const header = this.headerCellFrom(event);
84616
+ if (header)
84617
+ return this.toggleSort(header.column);
84618
+ this.bodyClick(event);
84619
+ };
84620
+ this.bodyClick = (event) => {
84621
+ const path = event.composedPath();
84622
+ const row = path.find(node => { var _a; return ((_a = node === null || node === void 0 ? void 0 : node.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === XV_TABLE_ROW_TAG; });
84623
+ if (!row || row.disabled)
84624
+ return;
84625
+ if (path.some(node => { var _a; return ((_a = node === null || node === void 0 ? void 0 : node.getAttribute) === null || _a === void 0 ? void 0 : _a.call(node, 'part')) === 'expand-button'; })) {
84626
+ this.toggleExpanded(row.value);
84627
+ return;
84628
+ }
84629
+ if (!this.rowClickable)
84630
+ return;
84631
+ // event.target is retargeted to the row at this boundary, so the path is the only honest check.
84632
+ if (path.some(node => { var _a; return node !== row && ((_a = node === null || node === void 0 ? void 0 : node.matches) === null || _a === void 0 ? void 0 : _a.call(node, INTERACTIVE)); }))
84633
+ return;
84634
+ this.rowClick.emit({ value: row.value, index: this.renderedRows().indexOf(row) });
84635
+ };
84636
+ this.paginationChanged = (event) => {
84637
+ event.stopPropagation();
84638
+ this.page = event.detail.page || this.page;
84639
+ this.pageSize = event.detail.itemsPerPage || this.pageSize;
84640
+ this.pageChange.emit({ page: this.page, pageSize: this.pageSize });
84641
+ };
84642
+ }
84643
+ componentWillLoad() {
84644
+ this.declared = parseProp(this.columns, []);
84645
+ this.rowData = parseProp(this.rows, []);
84646
+ this.columnState = this.declared.map(column => (Object.assign({}, column)));
84647
+ this.sortState = parseSortBy(this.sortBy);
84648
+ this.selectedValues = parseProp(this.selected, []);
84649
+ this.expandedValues = parseProp(this.expanded, []);
84650
+ this.slottedRowCount = this.slottedRows().length;
84651
+ if (this.storageKey || this.layout)
84652
+ this.restoreLayout();
84653
+ }
84654
+ componentDidLoad() {
84655
+ // Bound imperatively: a custom event has no typed JSX handler on a plain element.
84656
+ this.el.addEventListener(CHECKBOX_EVENT, this.bodyChange);
84657
+ // Absent in mock-doc and in hydrate builds; componentDidRender still keeps the rows in sync.
84658
+ if (typeof MutationObserver !== 'undefined') {
84659
+ this.rowObserver = new MutationObserver(records => {
84660
+ // A framework re-rendering its own markup inside a cell must not trigger a full resync.
84661
+ if (!records.some(record => this.touchesStructure(record)))
84662
+ return;
84663
+ this.syncStructure();
84664
+ this.syncRows();
84665
+ });
84666
+ this.rowObserver.observe(this.el, {
84667
+ childList: true,
84668
+ subtree: true,
84669
+ // A framework can reflect these after the table has already read the header once.
84670
+ attributes: true,
84671
+ attributeFilter: ['column-id', 'width', 'sortable', 'hideable', 'parent'],
84672
+ });
84673
+ }
84674
+ // Fires after layout, so reading the two widths costs no extra reflow.
84675
+ if (typeof ResizeObserver !== 'undefined') {
84676
+ this.sizeObserver = new ResizeObserver(() => this.measureOverflow());
84677
+ if (this.scrollEl)
84678
+ this.sizeObserver.observe(this.scrollEl);
84679
+ if (this.gridEl)
84680
+ this.sizeObserver.observe(this.gridEl);
84681
+ }
84682
+ this.syncStructure();
84683
+ this.syncRows();
84684
+ }
84685
+ componentDidRender() {
84686
+ this.syncRows();
84687
+ }
84688
+ disconnectedCallback() {
84689
+ var _a, _b;
84690
+ this.el.removeEventListener(CHECKBOX_EVENT, this.bodyChange);
84691
+ (_a = this.rowObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
84692
+ this.rowObserver = undefined;
84693
+ (_b = this.sizeObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
84694
+ this.sizeObserver = undefined;
84695
+ }
84696
+ columnsChanged() {
84697
+ this.declared = parseProp(this.columns, []);
84698
+ this.restoreLayout();
83887
84699
  }
83888
- handleCheckedChange({ detail }) {
83889
- if (detail.header || detail.expandable)
84700
+ layoutInputChanged() {
84701
+ this.restoreLayout();
84702
+ }
84703
+ sortByChanged() {
84704
+ this.sortState = parseSortBy(this.sortBy);
84705
+ }
84706
+ selectedChanged() {
84707
+ this.selectedValues = parseProp(this.selected, []);
84708
+ }
84709
+ expandedChanged() {
84710
+ this.expandedValues = parseProp(this.expanded, []);
84711
+ }
84712
+ rowsChanged() {
84713
+ this.rowData = parseProp(this.rows, []);
84714
+ }
84715
+ /** Selects every selectable row. */
84716
+ async selectAll() {
84717
+ this.setSelection(this.rowValues());
84718
+ }
84719
+ /** Clears the selection. */
84720
+ async clearSelection() {
84721
+ this.setSelection([]);
84722
+ }
84723
+ /** Drops the stored layout and returns to the declared columns. */
84724
+ async resetLayout() {
84725
+ this.columnState = this.declared.map(column => (Object.assign({}, column)));
84726
+ await deleteLayout(this.storageOwner, this.storageKey);
84727
+ this.layoutChange.emit(diffLayout(this.columnState, this.declared));
84728
+ }
84729
+ /** The layout as it would be stored: only the deviations from the declared columns. */
84730
+ async getLayout() {
84731
+ return diffLayout(this.columnState, this.declared);
84732
+ }
84733
+ async restoreLayout() {
84734
+ const token = ++this.layoutToken;
84735
+ const controlled = parseProp(this.layout, null);
84736
+ if (controlled) {
84737
+ this.columnState = applyLayout(this.declared, controlled);
83890
84738
  return;
83891
- if (detail.checked) {
83892
- this.selected.set(detail.name, detail);
83893
84739
  }
83894
- else {
83895
- this.selected.delete(detail.name);
84740
+ if (!this.storageKey) {
84741
+ this.columnState = this.declared.map(column => (Object.assign({}, column)));
84742
+ return;
83896
84743
  }
83897
- this.selectedCount = this.selected.size;
84744
+ // Painting declared widths and correcting them afterwards is visible, so the body waits.
84745
+ this.layoutPending = true;
84746
+ const stored = await readLayout(this.storageOwner, this.storageKey);
84747
+ if (token !== this.layoutToken)
84748
+ return;
84749
+ this.columnState = applyLayout(this.declared, stored);
84750
+ this.layoutPending = false;
84751
+ }
84752
+ commitLayout() {
84753
+ const next = diffLayout(this.columnState, this.declared);
84754
+ void writeLayout(this.storageOwner, this.storageKey, next);
84755
+ this.layoutChange.emit(next);
84756
+ }
84757
+ get localeTag() {
84758
+ var _a;
84759
+ return this.locale || ((_a = this.el.closest('[lang]')) === null || _a === void 0 ? void 0 : _a.getAttribute('lang')) || 'de';
84760
+ }
84761
+ get visible() {
84762
+ return visibleColumns(this.columnState);
84763
+ }
84764
+ get hasSelection() {
84765
+ return this.selection !== 'none';
84766
+ }
84767
+ get hasExpand() {
84768
+ return this.expandMode !== 'none';
84769
+ }
84770
+ get template() {
84771
+ if (this.columnState.length) {
84772
+ return buildColumnTemplate(this.columnState, this.leadingTracks, this.trailingTracks);
84773
+ }
84774
+ // No columns declared: a plain table takes its structure from the markup itself.
84775
+ return [...this.leadingTracks.map(w => `${w}px`), ...this.derivedTracks, ...this.trailingTracks.map(w => `${w}px`)].join(' ');
84776
+ }
84777
+ /** Grip, then the expand toggle, then selection — one track each, in render order. */
84778
+ get leadingTracks() {
84779
+ return [
84780
+ ...(this.rowReorderable ? [XV_TABLE_CONTROL_WIDTH] : []),
84781
+ ...(this.hasExpand ? [XV_TABLE_CONTROL_WIDTH] : []),
84782
+ ...(this.hasSelection ? [XV_TABLE_CONTROL_WIDTH] : []),
84783
+ ];
84784
+ }
84785
+ get trailingTracks() {
84786
+ return [];
83898
84787
  }
83899
- setColsSizeTemplate() {
84788
+ get dataRows() {
84789
+ const all = this.rowData;
84790
+ const sorted = this.sortMode === 'client' && this.sortState
84791
+ ? sortRows(all, this.columnBySortName(this.sortState.name), this.sortState.direction, this.localeTag)
84792
+ : all;
84793
+ return this.paginationMode === 'client' ? pageSlice(sorted, this.page, this.pageSize) : sorted;
84794
+ }
84795
+ get rowTotal() {
84796
+ if (this.paginationMode === 'server')
84797
+ return this.total;
84798
+ const slotted = this.topRows(this.slottedRows()).length;
84799
+ return slotted || this.rowData.length;
84800
+ }
84801
+ // Nothing to show is not the same as something to say: a consumer that draws its own empty state
84802
+ // next to the table would otherwise get an empty frame above it.
84803
+ get isEmpty() {
84804
+ return !this.loading && !this.rowTotal && (!!this.emptyLabel || this.hasSlottedEmpty);
84805
+ }
84806
+ columnBySortName(name) {
84807
+ return this.columnState.find(column => sortName(column) === name) || null;
84808
+ }
84809
+ touchesStructure(record) {
84810
+ // The filter already narrows attributes to the ones that shape a column.
84811
+ if (record.type === 'attributes')
84812
+ return true;
84813
+ const structural = (node) => {
84814
+ var _a;
84815
+ const tag = (_a = node.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
84816
+ // Anything that fills a slot shapes the table; markup inside a cell does not.
84817
+ return tag === XV_TABLE_ROW_TAG || tag === XV_TABLE_CELL_TAG || !!node.slot;
84818
+ };
84819
+ return (Array.from(record.addedNodes).some(structural) || Array.from(record.removedNodes).some(structural));
84820
+ }
84821
+ isBodyRow(row) {
84822
+ return !row.hasAttribute('header') && row.getAttribute('slot') !== 'footer';
84823
+ }
84824
+ /** Body rows only — these are the ones selection and expansion count. */
84825
+ slottedRows() {
84826
+ return this.slottedRowsAll().filter(row => this.isBodyRow(row));
84827
+ }
84828
+ /** A page is counted in top-level rows: a group and its children travel together. */
84829
+ topRows(rows) {
84830
+ return rows.filter(row => this.isBodyRow(row) && !this.parentOf(row));
84831
+ }
84832
+ /** Every slotted row, footer included: they all need the column tracks lined up. */
84833
+ slottedRowsAll() {
84834
+ return Array.from(this.el.children).filter(child => child.tagName.toLowerCase() === XV_TABLE_ROW_TAG);
84835
+ }
84836
+ /** Every row on screen, whichever mode produced it. */
84837
+ renderedRows() {
83900
84838
  var _a;
83901
- if (!this.colsSize || !((_a = this.colsSize) === null || _a === void 0 ? void 0 : _a.length))
84839
+ const slotted = this.slottedRows();
84840
+ if (slotted.length)
84841
+ return slotted;
84842
+ return Array.from(((_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll(`${XV_TABLE_ROW_TAG}:not([header])`)) || []);
84843
+ }
84844
+ rowValues() {
84845
+ const slotted = this.slottedRows();
84846
+ if (slotted.length) {
84847
+ const parents = this.parentValues(slotted);
84848
+ return slotted
84849
+ .filter(row => !this.isDisabled(row))
84850
+ .map(row => row.value)
84851
+ .filter(value => !parents.has(String(value)));
84852
+ }
84853
+ return this.dataRows.map(row => row === null || row === void 0 ? void 0 : row[this.rowKey]);
84854
+ }
84855
+ /** A disabled row is not selectable, so it stays out of every selection set. */
84856
+ isDisabled(row) {
84857
+ return !!row.disabled || row.hasAttribute('disabled');
84858
+ }
84859
+ /** `parent` may arrive as an attribute or as a property, depending on the consumer. */
84860
+ parentOf(row) {
84861
+ return String(row.parent || row.getAttribute('parent') || '');
84862
+ }
84863
+ parentValues(rows) {
84864
+ return new Set(rows.map(row => this.parentOf(row)).filter(Boolean));
84865
+ }
84866
+ childValuesOf(value) {
84867
+ return this.buildTree(this.slottedRows()).get(String(value)) || [];
84868
+ }
84869
+ /** One walk of the rows answers every parent/child question asked during a sync. */
84870
+ buildTree(rows) {
84871
+ const children = new Map();
84872
+ rows.forEach(row => {
84873
+ const parent = this.parentOf(row);
84874
+ if (!parent)
84875
+ return;
84876
+ const values = children.get(parent) || [];
84877
+ if (!this.isDisabled(row))
84878
+ values.push(row.value);
84879
+ children.set(parent, values);
84880
+ });
84881
+ return children;
84882
+ }
84883
+ /**
84884
+ * Child rows declare their parent by value. They stay siblings in the grid — that is what keeps
84885
+ * them in the table's columns, rather than a nested table inside a panel.
84886
+ */
84887
+ syncRowTree(rows, children, expanded) {
84888
+ const page = this.pageWindow(rows);
84889
+ const groups = new Map();
84890
+ rows.forEach(row => {
84891
+ var _a;
84892
+ const value = String((_a = row.value) !== null && _a !== void 0 ? _a : '');
84893
+ if (value && !this.parentOf(row))
84894
+ groups.set(value, row);
84895
+ });
84896
+ rows.forEach(row => {
84897
+ var _a;
84898
+ const props = row;
84899
+ const parent = this.parentOf(row);
84900
+ const value = String((_a = props.value) !== null && _a !== void 0 ? _a : '');
84901
+ if (parent) {
84902
+ const group = groups.get(parent);
84903
+ // A child follows its group: it shows when the group is open and on the current page.
84904
+ const show = expanded.has(parent) && (!page || (!!group && page.has(group)));
84905
+ this.showRow(row, show);
84906
+ props.expandable = false;
84907
+ return;
84908
+ }
84909
+ const hasChildren = children.has(value);
84910
+ const panel = !!row.querySelector('[slot="expand"]');
84911
+ // a row is expandable when it has children, or content for the panel
84912
+ props.expandable = hasChildren || panel;
84913
+ props.hasPanel = panel;
84914
+ row.classList.toggle('has-children', hasChildren);
84915
+ this.showRow(row, !page || !this.isBodyRow(row) || page.has(row));
84916
+ });
84917
+ }
84918
+ /** Only rows this table hid are shown again, so a consumer's own `hidden` survives a sync. */
84919
+ showRow(row, show) {
84920
+ if (!show) {
84921
+ this.collapsed.add(row);
84922
+ row.hidden = true;
83902
84923
  return;
83903
- this.el.style.setProperty('--xv-table-cols-template', this.colsSize
83904
- .map((v) => {
83905
- if (!v)
83906
- return 'minmax(0, 1fr)';
83907
- if (v === 'auto')
83908
- return 'minmax(0, auto)';
83909
- return `calc(${v} - ${50 / this.colsSize.length}px)`;
83910
- })
83911
- .join(' ') + ' repeat(auto-fit, minmax(0, 1fr))');
84924
+ }
84925
+ if (this.collapsed.delete(row))
84926
+ row.hidden = false;
83912
84927
  }
83913
- render() {
83914
- return (index$1.h(index$1.Host, { key: '1f954a0f71091fec58ed541ab9b71e07e756acf2', class: { batchVisible: !!this.selectedCount } }, index$1.h("slot", { key: 'cc4af9285051a8ce0eda8df5d306b9834815513c', name: "title" }, !!this.el.title && index$1.h("h2", { key: 'd74ca7c913d6b5239acce4a6e154dae57a325dd4', class: "xv-table-title" }, this.el.title)), index$1.h("slot", { key: '00df66a0aae78ac291ed818f123fa508e7437b91', name: "toolbar" }), index$1.h("div", { key: 'b5d81c782aa533dc591ec77ffe4fc71cffeafc86', class: "xv-table" }, index$1.h("div", { key: 'efa26ad85d880de121d53ecae616f0b0468b8c74', class: "batch-actions" }, index$1.h(index$1.Fragment, { key: '4a808f4de6683dd524057c6199c2e80b11860d8d' }, index$1.h("div", { key: 'ae5cce54e37780f32724e7ff9ef2549e5020b7f7', class: "batch-actions_content" }, index$1.h("slot", { key: 'f5b19fc73ca2e7cb1af08fcf23d42c817d531870', name: "batch" })), index$1.h("p", { key: '2f445105146d1d2ebb080f76c5bb81848e3e2a43', class: "batch-actions_count" }, !!this.selectedCount && `${this.selectedCount} ${this.selectedCount === 1 ? 'Position ausgewählt' : 'Positionen ausgewählt'}`))), index$1.h("div", { key: '6f41e51583e6d2a5dc076999fee3e573b062ad1f', class: "xv-table_wrapper" }, index$1.h("slot", { key: 'acccd9efedf38d59bde44f2f9d6ac2aec0ffa948' }), index$1.h("slot", { key: 'db6b9a957e4bc4e670f5c082c999c1931e36b6c1', name: "footer" })), !!this.loading && (index$1.h("div", { key: '3096c66919118c66992dd13e7b868c588876974c', class: "xv-table_loading" }, index$1.h("xv-loader-v2", { key: 'f469390775597fcfb9787749a915098eb0567d64', size: _vars.SIZE_VAR.LG }))))));
84928
+ /** The rows of the current page, or null while the table is not the one paging. */
84929
+ pageWindow(rows) {
84930
+ if (this.paginationMode !== 'client')
84931
+ return null;
84932
+ const top = this.topRows(rows);
84933
+ if (!top.length)
84934
+ return null;
84935
+ const size = this.pageSize || 10;
84936
+ const start = (clampPage(this.page, totalPages(top.length, size)) - 1) * size;
84937
+ return new Set(top.slice(start, start + size));
83915
84938
  }
83916
- componentWillLoad() {
83917
- this.setColsSizeTemplate();
84939
+ /** Cells are written in declared order; hiding and reordering only move them visually. */
84940
+ syncCells(row, order) {
84941
+ const cells = Array.from(row.children).filter(cell => cell.getAttribute('slot') !== 'expand');
84942
+ cells.forEach((cell, index) => {
84943
+ var _a;
84944
+ const column = this.declared[index];
84945
+ if (!column)
84946
+ return;
84947
+ const current = this.columnState.find(item => item.id === column.id);
84948
+ const props = cell;
84949
+ props.columnId = column.id;
84950
+ if (column.align)
84951
+ props.align = column.align;
84952
+ if (column.overflow)
84953
+ props.overflow = column.overflow;
84954
+ if (column.clampLines)
84955
+ props.clampLines = column.clampLines;
84956
+ cell.style.order = String((_a = order.get(column.id)) !== null && _a !== void 0 ? _a : index);
84957
+ cell.hidden = !!(current === null || current === void 0 ? void 0 : current.hidden);
84958
+ });
83918
84959
  }
83919
- get el() { return index$1.getElement(this); }
83920
- static get watchers() { return {
83921
- "colsSize": [{
83922
- "setColsSizeTemplate": 0
83923
- }]
83924
- }; }
83925
- };
83926
- XvTable.style = xvTableCss();
83927
-
83928
- const xvTableCellCss = () => `@charset "UTF-8";:host{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:var(--xv-table-padding-y) var(--xv-table-padding-x);color:var(--text-primary, #333);font-family:var(--ff-body, Tahoma);font-size:14px;font-style:normal;font-weight:400;line-height:1.2;letter-spacing:0.16px;transition:0.25s ease-in-out background-color}:host([multiline]){display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:initial;padding-bottom:1px;padding-top:0;line-height:1.2}:host([align=left]){text-align:left}:host([align=right]){text-align:right}:host([align=center]){text-align:center}:host([sort]){position:relative;cursor:pointer;user-select:none}:host([sort]):before,:host([sort]):after{font-size:12px;line-height:10px;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;position:absolute;right:8px;pointer-events:none;transition:350ms ease-in-out opacity;opacity:0}:host([sort]):before{content:"▲";top:50%;transform:translateY(calc(-50% - 5px))}:host([sort])::after{content:"▼";top:50%;transform:translateY(calc(-50% + 5px))}:host([sort]:hover){background-color:var(--layer-accent-hover-01, #E3E3E3)}:host([sort]:hover)::before,:host([sort]:hover)::after{opacity:1}:host([sort=asc]){background-color:var(--layer-accent-active-01, #D1D1D1)}:host([sort=asc])::before{opacity:1}:host([sort=asc])::after{display:none}:host([sort=desc]){background-color:var(--layer-accent-active-01, #D1D1D1)}:host([sort=desc])::before{display:none}:host([sort=desc])::after{opacity:1}`;
83929
-
83930
- const XvTableCell = class {
83931
- constructor(hostRef) {
83932
- index$1.registerInstance(this, hostRef);
83933
- this.sortChange = index$1.createEvent(this, "sortChange", 7);
84960
+ /** Structure writes @State, so it runs outside the render cycle: on load and on childList. */
84961
+ syncStructure() {
84962
+ const rows = this.slottedRowsAll();
84963
+ this.slottedRowCount = this.slottedRows().length;
84964
+ // The heading block is not rendered at all unless something fills it, and a slotted title is
84965
+ // just as much a title as the prop.
84966
+ const heading = Array.from(this.el.children).some(child => child.slot === 'label' || child.slot === 'description');
84967
+ if (this.hasSlottedHeading !== heading)
84968
+ this.hasSlottedHeading = heading;
84969
+ const empty = Array.from(this.el.children).some(child => child.slot === 'empty');
84970
+ if (this.hasSlottedEmpty !== empty)
84971
+ this.hasSlottedEmpty = empty;
84972
+ this.seedExpanded(rows);
84973
+ this.syncDerivedTracks(rows);
83934
84974
  }
83935
- handleSort() {
83936
- if (this.sort === undefined)
84975
+ /**
84976
+ * A row may declare itself open in markup. Read once, before the table starts writing the
84977
+ * attribute itself — after that there is no telling a declared value from a toggled one.
84978
+ */
84979
+ seedExpanded(rows) {
84980
+ // Rows that arrive from an HTTP call are not there on the first pass, so seeding waits for them.
84981
+ if (this.seededExpanded || !rows.length)
83937
84982
  return;
83938
- let sort = this.sort;
83939
- if (this.sort === '')
83940
- sort = _vars.XV_SORT_DIR.NONE;
83941
- this.sort = sort === _vars.XV_SORT_DIR.NONE ?
83942
- _vars.XV_SORT_DIR.ASC : sort === _vars.XV_SORT_DIR.ASC ?
83943
- _vars.XV_SORT_DIR.DESC : _vars.XV_SORT_DIR.NONE;
83944
- index$2.forEach(this.el.parentElement.children, (cell) => {
83945
- if (cell !== this.el && cell.hasAttribute('sort')) {
83946
- cell.setAttribute('sort', 'none');
84983
+ this.seededExpanded = true;
84984
+ const open = rows
84985
+ .filter(row => row.hasAttribute('expanded'))
84986
+ .map(row => row.value)
84987
+ .filter(value => value !== '' && value !== undefined);
84988
+ const merged = [...this.expandedValues, ...open.filter(v => !this.expandedValues.includes(v))];
84989
+ if (merged.length !== this.expandedValues.length)
84990
+ this.expandedValues = merged;
84991
+ }
84992
+ /** Pushing props onto children is safe during render; nothing here touches @State. */
84993
+ syncRows() {
84994
+ const rows = this.slottedRowsAll();
84995
+ const tree = this.buildTree(rows);
84996
+ // A value may reach the table as a number and come back from an attribute as a string.
84997
+ const expanded = new Set(this.expandedValues.map(String));
84998
+ const selected = new Set(this.selectedValues.map(String));
84999
+ const order = new Map(this.columnState.map((column, index) => [column.id, index]));
85000
+ this.syncRowTree(rows, tree, expanded);
85001
+ this.syncHeaderCells(rows.find(row => row.hasAttribute('header')));
85002
+ rows.forEach(row => {
85003
+ const value = row.value;
85004
+ const props = row;
85005
+ props.selectionMode = this.selection;
85006
+ props.expandMode = this.expandMode;
85007
+ props.size = this.size;
85008
+ props.hover = this.hover;
85009
+ props.rowReorderable = this.rowReorderable;
85010
+ props.rowReorderHandle = this.rowReorderHandle;
85011
+ props.expandLabel = this.expandLabel;
85012
+ props.reorderLabel = this.reorderLabel;
85013
+ if (row.hasAttribute('header')) {
85014
+ // A slotted header carries select-all too, so it reflects the whole table.
85015
+ const all = this.rowValues();
85016
+ const picked = this.selectedValues.length;
85017
+ props.selected = !!picked && picked === all.length;
85018
+ props.partial = !!picked && picked < all.length;
85019
+ props.selectable = all.length > 0;
85020
+ this.syncCells(row, order);
85021
+ return;
83947
85022
  }
85023
+ const children = tree.get(String(value)) || [];
85024
+ if (children.length) {
85025
+ const picked = children.filter(child => selected.has(String(child)));
85026
+ props.selected = picked.length === children.length;
85027
+ props.partial = !!picked.length && picked.length < children.length;
85028
+ }
85029
+ else {
85030
+ props.selected = selected.has(String(value));
85031
+ props.partial = false;
85032
+ }
85033
+ props.expanded = expanded.has(String(value));
85034
+ this.syncCells(row, order);
83948
85035
  });
83949
- if (!this.name)
83950
- this.name = index$2.uidGenerator();
83951
- this.sortChange.emit({ name: this.name, value: this.sort });
83952
85036
  }
83953
- ;
85037
+ /** Sorting is offered only when a mode asks for it, so `none` and `server` cannot look alike. */
85038
+ isSortable(column) {
85039
+ return !!column.sortable && this.sortMode !== 'none';
85040
+ }
85041
+ /**
85042
+ * A slotted header is the consumer's markup, so the table pushes the column state onto its cells
85043
+ * rather than rendering a second header of its own.
85044
+ */
85045
+ syncHeaderCells(header) {
85046
+ if (!header)
85047
+ return;
85048
+ const cells = Array.from(header.children).filter(child => child.tagName.toLowerCase() === XV_TABLE_CELL_TAG);
85049
+ cells.forEach((cell, index) => {
85050
+ var _a;
85051
+ const declared = cell.columnId || cell.getAttribute('column-id');
85052
+ const column = declared
85053
+ ? this.columnState.find(item => item.id === declared)
85054
+ : this.visible[index];
85055
+ const props = cell;
85056
+ props.header = true;
85057
+ props.reorderLabel = this.reorderLabel;
85058
+ if (!column) {
85059
+ props.resizable = false;
85060
+ props.reorderable = false;
85061
+ return;
85062
+ }
85063
+ const sortable = this.isSortable(column);
85064
+ props.columnId = column.id;
85065
+ // A markup header declares `sortable` itself. Writing the table's own idea of it back would
85066
+ // overwrite what the consumer just bound, and the table would then read its own answer.
85067
+ if (!this.fromMarkup)
85068
+ props.sortable = sortable;
85069
+ props.sortDirection =
85070
+ sortable && ((_a = this.sortState) === null || _a === void 0 ? void 0 : _a.name) === sortName(column) ? this.sortState.direction : '';
85071
+ props.resizable = columnAllows(column, this.resizable, 'resizable');
85072
+ props.reorderable = columnAllows(column, this.reorderable, 'reorderable');
85073
+ if (column.headerAlign)
85074
+ props.align = column.headerAlign;
85075
+ cell.draggable = props.reorderable;
85076
+ });
85077
+ }
85078
+ /** Reads the column shape out of the markup when no `columns` prop was given. */
85079
+ syncDerivedTracks(rows) {
85080
+ const header = rows.find(row => row.hasAttribute('header')) || null;
85081
+ if (this.hasSlottedHeader !== !!header)
85082
+ this.hasSlottedHeader = !!header;
85083
+ // Re-read the header while it is the declaration: a framework sets `sortable`, `hideable` or a
85084
+ // width as properties, and those can land after the first read. `columns` wins when it is given.
85085
+ if (header && (this.fromMarkup || !this.declared.length))
85086
+ this.deriveColumns(header);
85087
+ if (this.columnState.length)
85088
+ return;
85089
+ const source = header || rows[0];
85090
+ if (!source)
85091
+ return;
85092
+ const cells = Array.from(source.children).filter(cell => cell.getAttribute('slot') !== 'expand');
85093
+ const widths = cells.map(cell => String(cell.width || cell.getAttribute('width') || ''));
85094
+ // Every width fixed leaves nothing to absorb the slack, so they share it by weight.
85095
+ const share = widths.length > 0 && widths.every(width => /^[0-9.]+$/.test(width));
85096
+ const tracks = widths.map(width => {
85097
+ if (!width)
85098
+ return `minmax(${XV_TABLE_MIN_COLUMN_WIDTH}px,1fr)`;
85099
+ if (!/^[0-9.]+$/.test(width))
85100
+ return width;
85101
+ return share ? `minmax(${width}px,${width}fr)` : `${width}px`;
85102
+ });
85103
+ if (tracks.join(' ') !== this.derivedTracks.join(' '))
85104
+ this.derivedTracks = tracks;
85105
+ }
85106
+ /**
85107
+ * With no `columns` prop the header cells are the declaration: their attributes carry the id,
85108
+ * width and switches, so a markup-only table still resizes, reorders and remembers its layout.
85109
+ */
85110
+ deriveColumns(header) {
85111
+ const cells = Array.from(header.children).filter(child => child.tagName.toLowerCase() === XV_TABLE_CELL_TAG);
85112
+ if (!cells.length)
85113
+ return;
85114
+ const taken = new Set();
85115
+ const derived = cells.map((cell, index) => {
85116
+ var _a;
85117
+ // The property wins over the attribute: a framework binds properties, and it may have done so
85118
+ // before the cell upgraded. The attribute is the fallback for plain markup.
85119
+ const props = cell;
85120
+ const flag = (name, value) => (value !== null && value !== void 0 ? value : cell.hasAttribute(name));
85121
+ // `240` and `240px` are both pixels; `25%`, `auto` or `12rem` land in the track as written.
85122
+ const width = String(props.width || cell.getAttribute('width') || '');
85123
+ const pixels = /^([0-9.]+)(px)?$/.exec(width);
85124
+ // Two columns may honestly carry the same name — a details and a delete cell both keyed by
85125
+ // `id`. Ids address a column, so a repeat is made unique here rather than silently sharing
85126
+ // a track with the column it collides with.
85127
+ let id = props.columnId || cell.getAttribute('column-id') || `col-${index}`;
85128
+ while (taken.has(id))
85129
+ id = `${id}-${index}`;
85130
+ taken.add(id);
85131
+ return {
85132
+ id,
85133
+ label: ((_a = cell.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '',
85134
+ sortable: flag('sortable', props.sortable),
85135
+ hideable: flag('hideable', props.hideable),
85136
+ width: !width ? undefined : pixels ? Number(pixels[1]) : width,
85137
+ };
85138
+ });
85139
+ // Compared on everything the header declares, not only the ids: a framework sets `sortable` as
85140
+ // a property, and it may land after the table first read the markup. Ids alone would freeze
85141
+ // that first reading and quietly drop the sort affordance the consumer asked for.
85142
+ const signature = derived.map(c => `${c.id}|${c.sortable}|${c.hideable}|${c.width}`).join();
85143
+ if (signature === this.declaredSignature)
85144
+ return;
85145
+ this.declaredSignature = signature;
85146
+ this.fromMarkup = true;
85147
+ this.declared = derived;
85148
+ this.columnState = derived.map(column => (Object.assign({}, column)));
85149
+ if (this.storageKey)
85150
+ this.restoreLayout();
85151
+ }
85152
+ /** Every header cell on screen, whether the table rendered it or the consumer slotted it. */
85153
+ headerCells() {
85154
+ var _a;
85155
+ const row = this.slottedRowsAll().find(item => item.hasAttribute('header')) ||
85156
+ ((_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector(`${XV_TABLE_ROW_TAG}[header]`));
85157
+ if (!row)
85158
+ return [];
85159
+ return Array.from(row.children).filter(
85160
+ // Hidden cells are left out: these are indexed against the visible columns.
85161
+ child => child.tagName.toLowerCase() === XV_TABLE_CELL_TAG && !child.hidden);
85162
+ }
85163
+ /** A header cell knows its column by id, or failing that by its position in the row. */
85164
+ columnOf(cell) {
85165
+ const id = cell.columnId || cell.getAttribute('column-id');
85166
+ if (id)
85167
+ return this.columnState.find(column => column.id === id) || null;
85168
+ const index = this.headerCells().indexOf(cell);
85169
+ return this.visible[index] || null;
85170
+ }
85171
+ headerCellFrom(event) {
85172
+ const path = event.composedPath();
85173
+ const cell = path.find(node => { var _a; return ((_a = node === null || node === void 0 ? void 0 : node.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === XV_TABLE_CELL_TAG && node.hasAttribute('header'); });
85174
+ if (!cell)
85175
+ return null;
85176
+ const column = this.columnOf(cell);
85177
+ return column ? { cell, column } : null;
85178
+ }
85179
+ clearDragOver() {
85180
+ this.dragOverId = '';
85181
+ this.headerCells().forEach(item => item.classList.remove('drag-over'));
85182
+ }
85183
+ setSelection(values) {
85184
+ this.selectedValues = values;
85185
+ const all = !!values.length && values.length === this.rowValues().length;
85186
+ this.selectedChange.emit({ values, all, partial: !!values.length && !all });
85187
+ }
85188
+ toggleRowSelection(value) {
85189
+ const children = this.childValuesOf(value);
85190
+ if (children.length) {
85191
+ const picked = children.some(child => this.selectedValues.includes(child));
85192
+ this.setSelection(picked
85193
+ ? this.selectedValues.filter(item => !children.includes(item))
85194
+ : [...this.selectedValues, ...children]);
85195
+ return;
85196
+ }
85197
+ if (this.selection === 'single') {
85198
+ this.setSelection(this.selectedValues.includes(value) ? [] : [value]);
85199
+ return;
85200
+ }
85201
+ const next = this.selectedValues.includes(value)
85202
+ ? this.selectedValues.filter(item => item !== value)
85203
+ : [...this.selectedValues, value];
85204
+ this.setSelection(next);
85205
+ }
85206
+ toggleExpanded(value) {
85207
+ const open = this.expandedValues.includes(value);
85208
+ const next = open
85209
+ ? this.expandedValues.filter(item => item !== value)
85210
+ : this.expandMode === 'single'
85211
+ ? [value]
85212
+ : [...this.expandedValues, value];
85213
+ this.expandedValues = next;
85214
+ this.expandedChange.emit({ values: next });
85215
+ }
85216
+ bodyRows() {
85217
+ // A collapsed child is not on screen, so it must not take an index in `rowOrderChange`.
85218
+ return this.renderedRows().filter(row => row.getAttribute('slot') !== 'footer' && !row.hidden);
85219
+ }
85220
+ rowFrom(event) {
85221
+ if (!this.rowReorderable)
85222
+ return null;
85223
+ const path = event.composedPath();
85224
+ return path.find(node => { var _a; return ((_a = node === null || node === void 0 ? void 0 : node.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === XV_TABLE_ROW_TAG; }) || null;
85225
+ }
85226
+ /** The same row and cell components the consumer would write by hand. */
85227
+ renderHead() {
85228
+ const values = this.rowValues();
85229
+ const count = this.selectedValues.length;
85230
+ return (index$1.h("xv-table-row", { header: true, part: "head", size: this.size, selectionMode: this.selection, expandMode: this.expandMode, expandable: this.expandMode !== 'none', rowReorderable: this.rowReorderable, rowReorderHandle: this.rowReorderHandle, selected: !!count && count === values.length, partial: !!count && count < values.length, selectable: values.length > 0 }, this.visible.map(column => {
85231
+ var _a;
85232
+ const sortable = this.isSortable(column);
85233
+ const active = sortable && ((_a = this.sortState) === null || _a === void 0 ? void 0 : _a.name) === sortName(column);
85234
+ return (index$1.h("xv-table-cell", { key: column.id, header: true, part: "header-cell", columnId: column.id, align: column.headerAlign || 'start', tooltip: column.headerTooltip || '', sortable: sortable, sortDirection: active ? this.sortState.direction : '', resizable: columnAllows(column, this.resizable, 'resizable'), reorderable: columnAllows(column, this.reorderable, 'reorderable'), reorderLabel: this.reorderLabel, ref: element => element && (element.draggable = columnAllows(column, this.reorderable, 'reorderable')) }, column.label));
85235
+ })));
85236
+ }
85237
+ renderDataRow(row, index) {
85238
+ const value = row === null || row === void 0 ? void 0 : row[this.rowKey];
85239
+ return (index$1.h("xv-table-row", { key: value !== null && value !== void 0 ? value : index, value: value, size: this.size, hover: this.hover, selectionMode: this.selection, expandMode: this.expandMode, expandable: this.expandMode !== 'none', rowReorderable: this.rowReorderable, rowReorderHandle: this.rowReorderHandle, expandLabel: this.expandLabel, reorderLabel: this.reorderLabel, selected: this.selectedValues.includes(value), expanded: this.expandedValues.includes(value) }, this.visible.map(column => (index$1.h("xv-table-cell", { key: column.id, columnId: column.id, align: column.align || 'start', overflow: column.overflow || 'ellipsis', clampLines: column.clampLines || 2 }, formatCell(cellValue(row, column), column, this.localeTag))))));
85240
+ }
85241
+ renderSkeleton() {
85242
+ return Array.from({ length: this.skeletonRows }).map((_, index) => (index$1.h("div", { class: "skeleton_row", key: `skeleton-${index}`, "aria-hidden": "true" }, this.visible.map(column => (index$1.h("div", { class: "skeleton_cell", key: column.id }, index$1.h("span", { class: "skeleton_bar" })))))));
85243
+ }
85244
+ renderColumnPicker() {
85245
+ const hideable = hideableColumns(this.columnState);
85246
+ if (!hideable.length)
85247
+ return null;
85248
+ const changed = isLayoutChanged(diffLayout(this.columnState, this.declared));
85249
+ return (
85250
+ // The picker sits at the right edge, so it opens inward or a container with overflow clips it.
85251
+ index$1.h("xv-overflow-menu-v2", { class: "picker", part: "column-picker", position: "right", tooltip: this.columnsLabel }, index$1.h("span", { slot: "trigger", class: "picker_trigger" }, index$1.h("svg", { viewBox: "0 0 640 512", width: "16", height: "16", role: "img", "aria-hidden": "true" }, index$1.h("path", { fill: "currentColor", d: "M448 80l0 352 128 0c8.8 0 16-7.2 16-16l0-320c0-8.8-7.2-16-16-16L448 80zm-48 0L240 80l0 352 160 0 0-352zM192 432l0-352L64 80c-8.8 0-16 7.2-16 16l0 320c0 8.8 7.2 16 16 16l128 0zM0 96C0 60.7 28.7 32 64 32l512 0c35.3 0 64 28.7 64 64l0 320c0 35.3-28.7 64-64 64L64 480c-35.3 0-64-28.7-64-64L0 96z" })), changed && index$1.h("span", { class: "picker_marker" })), index$1.h("div", { class: "picker_list" }, hideable.map(column => (index$1.h("xv-checkbox-v2", { key: column.id, class: "picker_item", checked: !column.hidden, label: column.label || column.id, size: this.size, onEventChange: () => this.toggleColumn(column) }))), changed && (index$1.h("xv-button-v2", { variant: "tertiary", size: "sm", onClick: () => this.resetLayout() }, this.resetLabel)))));
85252
+ }
83954
85253
  render() {
83955
- return (index$1.h(index$1.Host, { key: 'f1ae644f52064308240bda543eb23999a9a6eb8a' }, index$1.h("slot", { key: '7ce7b7c7f36cdaa8cf5e31ec5ed028af1c0db625' })));
85254
+ const hasHeading = !!this.label || !!this.description || this.hasSlottedHeading;
85255
+ const count = this.selectedValues.length;
85256
+ const composed = !!this.slottedRowCount;
85257
+ const pages = totalPages(this.rowTotal, this.pageSize);
85258
+ return (index$1.h(index$1.Host, { key: 'c2f1eeb31477c009112ea67964859a06f32fb0be', class: { 'is-dragging': this.columnDragging } }, hasHeading && (index$1.h("div", { key: 'b16d5ed6a0ec41e1e93938c136720a9b3f076718', class: "heading", part: "heading" }, index$1.h("slot", { key: 'b5597ee8f3e1b43c8a003bf51f0dd1fdea307584', name: "label" }, this.label && index$1.h("h3", { key: '7b5c70866bbea7f38bd9ed3f12f5f79abdec9b5b', class: "heading_title", part: "title" }, this.label)), index$1.h("slot", { key: 'e3fc65553d7d8afa5617116ef03c0e71c4083092', name: "description" }, this.description && index$1.h("p", { key: 'f3545d3da1697eadb58b081db1f63dbc758446a2', class: "heading_description", part: "description" }, this.description)))), index$1.h("div", { key: 'b2363cd4706ef813a7986a46e634c7a17c2887e7', class: "bar", part: "bar" }, index$1.h("div", { key: 'b4ed99838d302c23e539d3f0aed986d6597cfa97', class: "bar_toolbar", part: "toolbar" }, index$1.h("slot", { key: '7dfe5fe111ac94245b57d9b16db98e86df96e14d', name: "toolbar" }), this.renderColumnPicker()), !!count && (index$1.h("div", { key: '00e6baa9e59099c688f398f98552e96accfcfdbd', class: "bar_batch", part: "batch" }, index$1.h("slot", { key: '719ccca8dc2d5728ceec0fa5953ec45148fbfca7', name: "batch" }), !!this.selectedLabel && (index$1.h("span", { key: 'ae71c3c543d5faef29145a32c0cee9f2d9c5441e', class: "bar_count" }, this.selectedLabel.replace('{count}', String(count))))))), index$1.h("div", { key: '0739869a681a870c611b50b8cec858bf8c60b2fb', class: { scroll: true, 'scroll--overflowing': this.overflowing }, part: "scroll", ref: element => (this.scrollEl = element) }, index$1.h("div", { key: '978390fa1eed594533ac9911eae893cdbcb48f01', class: "grid", part: "grid", role: "table", onPointerDown: this.headPointerDown, onDblClick: this.headDblClick, onKeyDown: this.headKeyDown, onDragStart: this.headDragStart, onDragOver: this.headDragOver, onDrop: this.headDrop, onDragEnd: this.dragEnd, ref: element => (this.gridEl = element), style: {
85259
+ '--xv-table-columns': this.template,
85260
+ // Handed to CSS rather than applied here: a wide table squeezes like a real one, and
85261
+ // only a narrow viewport turns this into the width it scrolls at.
85262
+ '--xv-table-min-width': `${tableMinWidth(this.columnState, this.minWidth, [...this.leadingTracks, ...this.trailingTracks].reduce((a, b) => a + b, 0))}px`,
85263
+ }, onClick: this.gridClick }, !this.hasSlottedHeader && this.renderHead(), index$1.h("div", { key: '22295be916a60272a46fe01cf3399b345e274948', class: "body", part: "body", role: "rowgroup", hidden: this.layoutPending, onDragStart: this.rowReorderable ? this.rowDragStart : undefined, onDragOver: this.rowReorderable ? this.rowDragOver : undefined, onDrop: this.rowReorderable ? this.rowDrop : undefined, onDragEnd: this.rowReorderable ? this.rowDragEnd : undefined }, this.loading && this.skeletonRows > 0
85264
+ ? this.renderSkeleton()
85265
+ : composed
85266
+ ? null
85267
+ : this.dataRows.map((row, index) => this.renderDataRow(row, index)), index$1.h("slot", { key: '05441531d73c716d3846794bea921eafa2b61533' })), index$1.h("slot", { key: 'e9f573271b2a6b19f212b598cd4471ee0070e340', name: "footer" }))), this.isEmpty && (index$1.h("div", { key: '4ceb6586322442b2fe48c3191641ce7857ef8f4b', class: "empty", part: "empty" }, index$1.h("slot", { key: '6213459f9c9657174edbb8b41daa48672b8f0a51', name: "empty" }, this.emptyLabel))), this.loading && !this.skeletonRows && (index$1.h("div", { key: 'edd362ca185dcd335b76b6c1c1369b886a97864c', class: "loading", part: "loading" }, index$1.h("xv-loader-v2", { key: '8d73899654faa6bb8b403f1aad2a426ad595bfa9', size: _vars.SIZE_VAR.LG }))), this.paginationMode !== 'none' && !!this.rowTotal && (index$1.h("xv-pagination", { key: '64f7884cf9dd446c5cad790f5bca97fbe33522b9', class: "pagination", part: "pagination", size: this.size, variant: "full", block: true, total: pages, page: this.page, totalItems: this.rowTotal, itemsPerPage: this.pageSize, itemsPerPageOptions: parsePageSizes(this.pageSizeOptions), responsiveVariant: { compact: [0, 768] }, onPageChange: this.paginationChanged }))));
83956
85268
  }
83957
85269
  get el() { return index$1.getElement(this); }
85270
+ static get watchers() { return {
85271
+ "columns": [{
85272
+ "columnsChanged": 0
85273
+ }],
85274
+ "layout": [{
85275
+ "layoutInputChanged": 0
85276
+ }],
85277
+ "storageKey": [{
85278
+ "layoutInputChanged": 0
85279
+ }],
85280
+ "storageOwner": [{
85281
+ "layoutInputChanged": 0
85282
+ }],
85283
+ "sortBy": [{
85284
+ "sortByChanged": 0
85285
+ }],
85286
+ "selected": [{
85287
+ "selectedChanged": 0
85288
+ }],
85289
+ "expanded": [{
85290
+ "expandedChanged": 0
85291
+ }],
85292
+ "rows": [{
85293
+ "rowsChanged": 0
85294
+ }]
85295
+ }; }
83958
85296
  };
83959
- XvTableCell.style = xvTableCellCss();
83960
-
83961
- const XV_EXPANDABLE_KEY = 'expandable';
83962
- const XV_TABLE_TAG = 'xv-table-v2';
85297
+ XvTable.style = xvTableCss();
83963
85298
 
83964
- const xvTableExpandCss = () => `:host{display:block;position:relative;transition:0.25s ease-in-out background-color}:host .expand-btn{z-index:9;position:absolute;left:max(10px, var(--xv-table-padding-x));top:max(2px, var(--xv-table-padding-y) + 2px);background-color:transparent;cursor:pointer;outline:none;margin:0;padding:0;box-sizing:border-box;display:block;width:8.5px;height:8.5px;border-top:none;border-left:none;border-right:2px solid var(--icon-primary, #333);border-bottom:2px solid var(--icon-primary, #333);transform:rotate(45deg);transform-origin:center center;transition:0.2s ease-in-out transform}:host .expand-btn:disabled{cursor:not-allowed;opacity:0.5}:host .expand-btn.open{transform:rotate(-135deg)}:host .expandableContent{overflow:hidden;margin:0;padding:0;max-height:0;transition:250ms ease max-height}:host .expandableContent.open{max-height:600px}:host ::slotted([slot=expandable]){display:grid;align-items:center}:host ::slotted(xv-table-v2-row),:host ::slotted([slot=expandable]){padding-inline-start:calc(max(10px, var(--xv-table-padding-x)) * 2 + 10px)}:host ::slotted([disabled]){pointer-events:none;opacity:0.4;cursor:not-allowed;user-select:none}`;
85299
+ const xvTableCellCss = () => `:host{--xv-table-cell-padding-x:var(--xv-table-padding-x, var(--spacing-05));--xv-table-cell-padding-y:var(--xv-table-padding-y, var(--spacing-03));--xv-table-cell-clamp:2;display:flex;align-items:center;box-sizing:border-box;min-width:0;padding-block:var(--xv-table-cell-padding-y);padding-inline:min(var(--xv-table-cell-padding-x), 25%);color:var(--text-primary);font-family:var(--ff-body);font-size:var(--fz-md);line-height:18px;letter-spacing:0.16px}:host([align=center]){justify-content:center;text-align:center}:host([align=end]){justify-content:flex-end;text-align:right}.content{min-width:0;max-width:100%}[part=tooltip]{min-width:0;max-width:100%}:host([overflow=ellipsis]) .content{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}:host([overflow=ellipsis]) .content ::slotted(*){min-width:0;max-width:100%}:host([overflow=clamp]) .content{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--xv-table-cell-clamp);overflow:hidden}:host([overflow=clamp]) .content ::slotted(*){display:inline}:host([overflow=wrap]) .content{overflow:visible;white-space:normal}:host([header]){position:relative;gap:var(--spacing-02);font-weight:600}:host([header]) .content{flex:1}:host([header][align=end]) .sort{order:-1}:host([header][sortable]){cursor:pointer}:host([header][sortable]):hover{background:var(--layer-accent-hover-01)}:host([header][sortable]):focus-visible{outline:2px solid var(--focus);outline-offset:0}:host([header][sortable]):focus-visible{outline-offset:-2px}:host([header][sort-direction=asc]),:host([header][sort-direction=desc]){background:var(--layer-accent-active-01)}.sort{flex:none;width:8px;height:8px;border-right:1px solid currentColor;border-bottom:1px solid currentColor;opacity:0;transform:rotate(45deg) translate(-2px, -2px)}:host([header][sortable]:hover) .sort{opacity:0.5}:host([header][sort-direction=asc]) .sort,:host([header][sort-direction=desc]) .sort{opacity:1}:host([header][sort-direction=asc]) .sort{transform:rotate(-135deg) translate(-2px, -2px)}.grip{position:absolute;top:50%;left:4px;transform:translateY(-50%);width:8px;height:14px;opacity:0;cursor:grab;background-image:radial-gradient(currentColor 1px, transparent 1px);background-size:4px 4px}:host([header]:hover) .grip{opacity:0.5}:host(.drag-over){box-shadow:inset 2px 0 0 0 var(--interactive-01)}.resize{position:absolute;top:0;right:0;z-index:1;width:6px;height:100%;cursor:col-resize;touch-action:none}.resize:hover,.resize:active{background:var(--interactive-01)}:host([hidden]){display:none}`;
83965
85300
 
83966
- const XvTableExpand = class {
85301
+ const XvTableCell = class {
83967
85302
  constructor(hostRef) {
83968
85303
  index$1.registerInstance(this, hostRef);
83969
- this.open = false;
83970
- this.disabled = false;
83971
- this.handleExpand = () => {
83972
- this.open = !this.open;
83973
- };
85304
+ /** Column this cell belongs to. Identifies it for sorting, resizing and the stored layout. */
85305
+ this.columnId = '';
85306
+ /** Horizontal alignment of the content. */
85307
+ this.align = 'start';
85308
+ /** How content wider than the column behaves. */
85309
+ this.overflow = 'ellipsis';
85310
+ /** Lines kept before clamping, when `overflow` is `clamp`. */
85311
+ this.clampLines = 2;
85312
+ /** Tooltip shown on hover. Only a cell that sets it pays for the tooltip component. */
85313
+ this.tooltip = '';
85314
+ /** Column width. Read off the header row when the table has no `columns`. Any CSS length. */
85315
+ this.width = '';
85316
+ /** Renders the cell as a column header. Set by the table from the row it sits in. */
85317
+ this.header = false;
85318
+ /** Offers the sort affordance. A header cell only. */
85319
+ this.sortable = false;
85320
+ /** Direction currently sorted by; empty when this column is not the active one. */
85321
+ this.sortDirection = '';
85322
+ /** Lets the column picker hide this column. A header cell only. */
85323
+ this.hideable = false;
85324
+ /** Offers the resize handle. A header cell only. */
85325
+ this.resizable = false;
85326
+ /** Offers the drag grip. A header cell only. */
85327
+ this.reorderable = false;
85328
+ /** Accessible name of the drag grip. */
85329
+ this.reorderLabel = 'Drag to reorder';
83974
85330
  }
83975
- render() {
83976
- return (index$1.h(index$1.Host, { key: '8fe9adf5fd39b640b89bddf303fcc4fb97f03cbd' }, index$1.h("button", { key: '1df684103a777e3a54ac94fa8f3c570d4ecbbe41', class: { 'expand-btn': true, open: this.open }, disabled: this.disabled, onClick: this.handleExpand }), index$1.h("slot", { key: 'e092ff357605223aa974a8f5061c7a0667c3917f', name: XV_EXPANDABLE_KEY }), index$1.h("div", { key: 'e4313af9e98ac24f25c5fc9c8250aff052f7c19b', class: { expandableContent: true, open: this.open } }, index$1.h("slot", { key: 'f5cb16c98a69917b6679eb620b2bfc1856a48501' }))));
85331
+ get ariaSort() {
85332
+ if (!this.header || !this.sortable)
85333
+ return null;
85334
+ if (this.sortDirection === _vars.XV_SORT_DIR.ASC)
85335
+ return 'ascending';
85336
+ if (this.sortDirection === _vars.XV_SORT_DIR.DESC)
85337
+ return 'descending';
85338
+ return 'none';
83977
85339
  }
83978
- componentDidLoad() {
83979
- index$2.setAttr(this.el.parentElement, XV_EXPANDABLE_KEY, true);
85340
+ render() {
85341
+ const content = (index$1.h("div", { key: 'eefd1609b456cdcc9e802c27e524613b64a9ce39', class: "content", part: "content", style: this.overflow === 'clamp' ? { '--xv-table-cell-clamp': `${this.clampLines}` } : undefined }, index$1.h("slot", { key: 'a00460b7e2fbf775c7607af68b078a4fcff70c11' })));
85342
+ return (index$1.h(index$1.Host, { key: '54976b9c9740d576bb4a81a15af65aa79a2f0888', role: this.header ? 'columnheader' : 'cell', part: "cell", "aria-sort": this.ariaSort, tabindex: this.header && this.sortable ? 0 : null }, this.header && this.reorderable && index$1.h("span", { key: 'f443393d1ea62a0c94bfa59b77c377bf5fc04a66', class: "grip", part: "grip", "aria-label": this.reorderLabel }), this.tooltip ? (
85343
+ // Popper puts the panel on document.body, so the scroll container cannot clip it.
85344
+ index$1.h("xv-tooltip-v2", { part: "tooltip", dashed: true, position: "top-start", message: this.tooltip }, content)) : (content), this.header && this.sortable && index$1.h("span", { key: 'c26fa895c0a9a17cbe6c33c68f9e14b05781554e', class: "sort", "aria-hidden": "true" }), this.header && this.resizable && index$1.h("span", { key: '37fa59799c363ed83f2dd0052b3203aa3bf01a6c', class: "resize", part: "resize", "aria-hidden": "true" })));
83980
85345
  }
83981
85346
  get el() { return index$1.getElement(this); }
83982
85347
  };
83983
- XvTableExpand.style = xvTableExpandCss();
85348
+ XvTableCell.style = xvTableCellCss();
83984
85349
 
83985
- const xvTableRowCss = () => `:host{display:grid;grid-template-columns:var(--xv-table-cols-template, repeat(auto-fit, minmax(0, 1fr)));border-bottom:1px solid #E3E3E3;border-right:1px solid #E3E3E3;border-left:1px solid #E3E3E3;min-height:var(--xv-table-min-height);align-items:center;align-content:center;transition:0.25s ease-in-out background-color}:host .cell-control{min-height:20px;display:flex;align-items:center;justify-content:center}:host([variant]){grid-template-columns:minmax(47.97px, min-content) var(--xv-table-cols-template, repeat(auto-fit, minmax(0, 1fr)))}:host([hover]:not([header]):hover){background-color:var(--layer-hover-01, #E9E9E9)}:host([checked]){background-color:var(--layer-selected-01, #E3E3E3)}:host([checked]:hover){background-color:var(--layer-selected-hover-01, #DADADA)}:host([header]){background-color:var(--layer-accent-01, #F7F7F7);box-shadow:0 0 0 1px #E3E3E3 inset;border-bottom:none}`;
85350
+ const xvTableRowCss = () => `:host{--xv-table-row-bg:var(--layer-02);--xv-table-row-height:var(--xv-table-height, 40px);--xv-table-row-disabled-opacity:0.5;grid-column:1/-1;display:grid;grid-template-columns:subgrid;align-items:stretch;min-height:var(--xv-table-row-height);background:var(--xv-table-row-bg);box-shadow:inset 0 -1px 0 0 var(--border-subtle-00)}@supports not (grid-template-columns: subgrid){:host{display:contents}}:host([hover]:not([disabled]):hover){--xv-table-row-bg:var(--layer-hover-01)}:host([selected]){--xv-table-row-bg:var(--layer-selected-01)}:host([selected][hover]:hover){--xv-table-row-bg:var(--layer-selected-hover-01)}:host([row-reorderable][draggable=true]){cursor:grab}:host(.is-dragging){opacity:0.4}:host(.drop-above){box-shadow:inset 0 2px 0 0 var(--interactive-01)}:host(.drop-below){box-shadow:inset 0 -2px 0 0 var(--interactive-01)}:host([group]){--xv-table-row-bg:var(--layer-accent-01);font-weight:600}:host(.has-children){--xv-table-row-bg:var(--layer-accent-01)}:host(.has-children[hover]:hover){--xv-table-row-bg:var(--layer-accent-hover-01)}:host([header]){--xv-table-row-bg:var(--xv-table-header-bg, var(--layer-accent-01));box-shadow:inset 0 -1px 0 0 var(--border-subtle-01);font-weight:600}:host([disabled]:not([header])){cursor:not-allowed;color:var(--text-disabled);pointer-events:none;opacity:var(--xv-table-row-disabled-opacity)}.control{display:flex;align-items:center;justify-content:center;padding:0 var(--spacing-03)}.control--grip{order:-3}.control--expand{order:-2}.control--lead{order:-1}.control_grip{width:8px;height:14px;opacity:0.4;cursor:grab;background-image:radial-gradient(currentColor 1px, transparent 1px);background-size:4px 4px}.control_grip:active{cursor:grabbing}.control_expand{width:24px;height:24px;padding:0;border:0;background:none;color:var(--icon-primary);cursor:pointer}.control_expand::before{content:"";display:block;width:8px;height:8px;margin:0 auto;border-right:1px solid currentColor;border-bottom:1px solid currentColor;transform:rotate(45deg) translate(-2px, -2px);transition:transform 0.15s ease}.control_expand.open::before{transform:rotate(-135deg) translate(-2px, -2px)}.control_expand:disabled{color:var(--icon-disabled);cursor:not-allowed}.control_expand:focus-visible{outline:2px solid var(--focus);outline-offset:0}.control_expand:focus-visible{outline-offset:-2px}.expand{order:10000;grid-column:1/-1;padding:var(--spacing-05);background:var(--layer-01);box-shadow:inset 0 1px 0 0 var(--border-subtle-00)}.expand[hidden]{display:none}:host([hidden]){display:none}`;
83986
85351
 
83987
85352
  const XvTableRow = class {
83988
85353
  constructor(hostRef) {
83989
85354
  index$1.registerInstance(this, hostRef);
83990
- this.checkedChange = index$1.createEvent(this, "checkedChange", 7);
83991
- this.selectRow = index$1.createEvent(this, "selectRow", 7);
83992
- this.checkHandle = ({ detail: checked }) => {
83993
- if (!checked && this.partial)
83994
- this.partial = checked;
83995
- if (!this.name)
83996
- this.name = index$2.uidGenerator();
83997
- this.selectRow.emit({
83998
- name: this.name,
83999
- value: this.value,
84000
- checked: checked,
84001
- partial: this.partial,
84002
- header: this.header,
84003
- expandable: this.el.getAttribute('slot') === XV_EXPANDABLE_KEY,
84004
- });
84005
- };
85355
+ /** Identifies the row in selection and expansion payloads. */
85356
+ this.value = '';
85357
+ /** Selection control rendered in the leading cell. Set by the table. */
85358
+ this.selectionMode = 'none';
85359
+ /** Whether the row can be expanded. Set by the table. */
85360
+ this.expandMode = 'none';
85361
+ /** Whether the row offers its selection control. A header with no rows under it has nothing to pick. */
85362
+ this.selectable = true;
85363
+ /** Row height ladder. Set by the table. */
85364
+ this.size = _vars.SIZE_VAR.MD;
85365
+ /** Whether the row is selected. */
85366
+ this.selected = false;
85367
+ /** Indeterminate state of the header row's select-all checkbox. */
85368
+ this.partial = false;
85369
+ /** Whether the row's expand panel is open. */
85370
+ this.expanded = false;
85371
+ /**
85372
+ * Value of the row this one belongs to. Child rows are siblings in the same grid, so they keep
85373
+ * the table's columns instead of living in a panel of their own.
85374
+ */
85375
+ // Not reflected: an empty default would put parent="" on every row and break [parent] selectors.
85376
+ this.parent = '';
85377
+ /** Whether this row has anything to expand. Set by the table. */
85378
+ this.expandable = false;
85379
+ /** Whether the row carries `slot="expand"` content. Set by the table. */
85380
+ this.hasPanel = false;
85381
+ /** Renders the row as a subtotal or grouping row: no controls, accented background. */
85382
+ this.group = false;
85383
+ /** Marks the row as the table's header. Its cells supply the column labels. */
85384
+ this.header = false;
85385
+ /** Highlights the row on pointer hover. Set by the table. */
85386
+ this.hover = false;
85387
+ /** Blocks selection and expansion. */
85388
+ this.disabled = false;
85389
+ /** Whether this row can be dragged into a new position. Set by the table. */
85390
+ this.rowReorderable = false;
85391
+ /** Whether the whole row drags, or only its grip. Set by the table. */
85392
+ this.rowReorderHandle = 'icon';
85393
+ /** Accessible name of the expand toggle. Set by the table. */
85394
+ this.expandLabel = 'Toggle row';
85395
+ /** Accessible name of the drag grip. Set by the table. */
85396
+ this.reorderLabel = 'Drag to reorder';
84006
85397
  }
84007
- checkedChangeHandle() {
84008
- if (!this.name)
84009
- this.name = index$2.uidGenerator();
84010
- this.checkedChange.emit({
84011
- name: this.name,
84012
- value: this.value,
84013
- checked: this.checked,
84014
- partial: this.partial,
84015
- header: this.header,
84016
- expandable: this.el.getAttribute('slot') === XV_EXPANDABLE_KEY,
84017
- });
85398
+ // `draggable` is an enumerated attribute, not a boolean one: rendered as `draggable=""` it reads
85399
+ // as `auto`, which never drags. The property reflects the string the browser expects.
85400
+ componentDidRender() {
85401
+ this.el.draggable = this.dragsWholeRow;
84018
85402
  }
84019
- setInitialAttrs() {
84020
- if (this.variant || !this.hover) {
84021
- const tableEl = this.el.closest(XV_TABLE_TAG);
84022
- if (!this.hover) {
84023
- this.hover = tableEl.hasAttribute('hover');
84024
- }
84025
- if (this.variant) {
84026
- index$2.setAttr(this.el.closest(XV_TABLE_TAG), `variant-${this.variant}`, !!this.variant);
84027
- }
84028
- }
85403
+ get dragsWholeRow() {
85404
+ return (this.rowReorderable &&
85405
+ this.rowReorderHandle === 'row' &&
85406
+ !this.group &&
85407
+ !this.header &&
85408
+ !this.disabled &&
85409
+ this.el.slot !== 'footer');
84029
85410
  }
84030
85411
  render() {
84031
- return (index$1.h(index$1.Host, { key: '96836583a7db08fbbe974a6ece55d5a909a7e415' }, this.variant !== undefined && (index$1.h("xv-table-v2-cell", { key: '0783aad6e26302d3430333cad806fc1747e26e39', class: "cell-control" }, this.variant === 'checkbox' && (index$1.h("xv-checkbox-v2", { key: 'bd4e052458eeda60f79e22507ac25d5914f39c0c', name: this.name, partial: this.partial, checked: this.checked || this.partial, disabled: this.disabled, required: this.required, readonly: this.readonly, onEventChange: this.checkHandle })), this.variant === 'radio' && (index$1.h("input", { key: '1cda8e32f1e8d6ad47fc93e63ee3c879651faa2a', type: "radio", name: this.name, checked: this.checked || this.partial, disabled: this.disabled, required: this.required, readonly: this.readonly })))), index$1.h("slot", { key: '2a74a7a6ab1c5d997bf71fe99b6cd98b61a70219' })));
84032
- }
84033
- componentWillLoad() {
84034
- this.setInitialAttrs();
85412
+ // Empty spacers, or a group row's cells slide into the control tracks.
85413
+ const hasSelect = this.selectionMode !== 'none';
85414
+ const hasExpand = this.expandMode !== 'none';
85415
+ // A header keeps the control cells as spacers, like a group row: it has nothing to expand or drag.
85416
+ const expandable = hasExpand && !this.group && !this.header && this.expandable;
85417
+ const draggable = this.rowReorderable && !this.group && !this.header && !this.disabled && this.el.slot !== 'footer';
85418
+ // An empty panel would still paint its padding and background, so it is not rendered at all.
85419
+ const panel = expandable && this.hasPanel;
85420
+ return (index$1.h(index$1.Host, { key: 'ff2940779a1781b9a953629e4c8bf9a7431105fb', role: "row", part: "row" }, this.rowReorderable && (index$1.h("div", { key: 'd37b95aa6e56d073f1a9183be0475835b991f9d9', class: "control control--grip", part: "control", role: "cell" }, draggable && this.rowReorderHandle === 'icon' && (index$1.h("span", { key: '806316bd3cfb4340069418b3a43791073800d8fd', class: "control_grip", part: "grip", ref: element => element && (element.draggable = true), "aria-label": this.reorderLabel })))), hasExpand && (index$1.h("div", { key: 'e8455932d6147a965a27fbe2543ceeece4a65be8', class: "control control--expand", part: "control", role: "cell" }, expandable && (index$1.h("button", { key: 'eff064a985e9e6e44f122a42658f36ebd4f8d443', type: "button", class: { control_expand: true, open: this.expanded }, part: "expand-button", disabled: this.disabled, "aria-expanded": String(this.expanded), "aria-label": this.expandLabel })))), hasSelect && (index$1.h("div", { key: '97ffdebfe4ef650aa45020ff54449db83f252f68', class: "control control--lead", part: "control", role: "cell" }, !this.group &&
85421
+ this.selectable &&
85422
+ (this.selectionMode === 'multiple' ? (index$1.h("xv-checkbox-v2", { class: "control_input", checked: this.selected || this.partial, partial: this.partial, disabled: this.disabled, size: this.size })) : (index$1.h("xv-radio-v2", { class: "control_input", checked: this.selected, disabled: this.disabled, size: this.size }))))), index$1.h("slot", { key: '77414059aab52c6b11fe4b3571742eb9f4781fa8' }), panel && (index$1.h("div", { key: 'df45265616deac76f9bdb571def33be0a917bb01', class: "expand", part: "expand-panel", role: "cell", hidden: !this.expanded }, index$1.h("slot", { key: '986cbf15abb19462e98b4650ac707d0c79be54f4', name: "expand" })))));
84035
85423
  }
84036
85424
  get el() { return index$1.getElement(this); }
84037
- static get watchers() { return {
84038
- "checked": [{
84039
- "checkedChangeHandle": 0
84040
- }]
84041
- }; }
84042
85425
  };
84043
85426
  XvTableRow.style = xvTableRowCss();
84044
85427
 
@@ -84395,12 +85778,12 @@ const XvTagCombobox = class {
84395
85778
  const ariaOwns = suggestionsVisible ? `${this.uid}-listbox` : undefined;
84396
85779
  const activedesc = this.highlighted >= 0 ? this.optionId(this.highlighted) : undefined;
84397
85780
  const message = index$2.resolveFieldMessage({ error: this.error, warning: this.warning, helper: this.helper });
84398
- return (index$1.h(index$1.Host, { key: '5b78581d7d76f3f8548a8879831c1774b0f6e3ba', class: "xv-combobox", part: "root", size: this.size }, this.label && index$1.h("label", { key: 'd2d7249c6b2c65018ab203ce71b72df3e19aa2d8', class: "label" }, this.label), index$1.h("div", { key: '5d5782acb42a47e6b61151eeb3a2b20bb440b335', class: {
85781
+ return (index$1.h(index$1.Host, { key: '5351ddba9ec53411d14582d3e4c013000f560540', class: "xv-combobox", part: "root", size: this.size }, this.label && index$1.h("label", { key: '9072c85cbd926b16e08827dacccd4d7f0a86d411', class: "label" }, this.label), index$1.h("div", { key: 'd63f9438b385fc05b53f29be87d5e1cf77a02f88', class: {
84399
85782
  'control': true,
84400
85783
  'control--disabled': this.disabled,
84401
85784
  'control--error': !!this.error,
84402
85785
  'control--readonly': !!this.readonly,
84403
- }, onClick: () => this.blockClick() }, index$1.h("div", { key: 'bcebbb940ffacac018068926ff3f714d60848d31', class: "control-chips", role: "list" }, this.selected.map((s, i) => (index$1.h("xv-tag-v2", { role: "listitem", part: "chip", "data-value": s.value, size: this.COMPARE_TAG_SIZE[this.size], disabled: this.disabled, bg: (s === null || s === void 0 ? void 0 : s.bg) || 'var(--layer-accent-01, #F7F7F7)', color: (s === null || s === void 0 ? void 0 : s.color) || 'var(--text-primary, #333)', closeable: !this.readonly, onCloseClick: ({ detail }) => this.removeTag(i, detail) }, s.label))), index$1.h("input", { key: '231998800b3984fc5d8f98e3b387c856aefe2c3f', ref: (el) => (this.inputEl = el), class: "control-input", readonly: this.readonly, placeholder: this.selected.length ? '' : this.placeholder, value: this.inputValue, onInput: (e) => this.onInput(e), onKeyDown: (e) => this.onKeyDown(e), onFocus: () => { this.onOpen(); this.recomputeFiltered(); }, "aria-autocomplete": "list", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": ariaOwns, "aria-activedescendant": activedesc, disabled: this.disabled })), this.loading && (index$1.h("span", { key: '06553869f491586642f501cb5fcfc14e2ba6f1f4', class: "control-loader", part: "loader", "aria-hidden": "true" }, index$1.h("xv-loader-v2", { key: 'db81d3335f20e26a0049508340da8cb3f59c24d9', size: "sm", variant: "horizontal" })))), message && (index$1.h("p", { key: '912315e151754bf4f8c63fbec64f3433bdbfac9d', class: { message: true, [message.level]: true } }, message.text)), suggestionsVisible && (index$1.h("ul", { key: 'c68bdb4c63e330440a038be034c1edefee84015c', id: `${this.uid}-listbox`, class: "suggestions", role: "listbox", part: "listbox" }, this.filtered.map((opt, idx) => (index$1.h("li", { id: this.optionId(idx), class: { 'suggestions-opt': true, 'suggestions-opt--highlight': idx === this.highlighted }, role: "option", "aria-selected": idx === this.highlighted, onMouseEnter: () => this.onOptionMouseEnter(idx), onMouseDown: (ev) => ev.preventDefault(), onClick: () => this.selectOption(opt) }, index$1.h("div", { class: "suggestions-opt-content" }, opt.bg ? index$1.h("span", { class: "suggestions-opt-content--color", style: { background: opt.bg } }) : null, index$1.h("span", { class: "suggestions-opt-content--label" }, this.highlightLabel(opt.label).map((seg, i) => typeof seg === 'string' ? index$1.h("span", { key: i }, seg) : index$1.h("strong", { key: i }, seg.match)))))))))));
85786
+ }, onClick: () => this.blockClick() }, index$1.h("div", { key: 'e303fef8789d9f1df8a9febe667f8fa0d72f4aaa', class: "control-chips", role: "list" }, this.selected.map((s, i) => (index$1.h("xv-tag-v2", { role: "listitem", part: "chip", "data-value": s.value, size: this.COMPARE_TAG_SIZE[this.size], disabled: this.disabled, bg: (s === null || s === void 0 ? void 0 : s.bg) || 'var(--layer-accent-01, #F7F7F7)', color: (s === null || s === void 0 ? void 0 : s.color) || 'var(--text-primary, #333)', closeable: !this.readonly, onCloseClick: ({ detail }) => this.removeTag(i, detail) }, s.label))), index$1.h("input", { key: '08ec28c65696a36238aa4f2c7f9ba2a89c34e31c', ref: (el) => (this.inputEl = el), class: "control-input", readonly: this.readonly, placeholder: this.selected.length ? '' : this.placeholder, value: this.inputValue, onInput: (e) => this.onInput(e), onKeyDown: (e) => this.onKeyDown(e), onFocus: () => { this.onOpen(); this.recomputeFiltered(); }, "aria-autocomplete": "list", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": ariaOwns, "aria-activedescendant": activedesc, disabled: this.disabled })), this.loading && (index$1.h("span", { key: '434666b2391399635cfe9c18320e4e10c0b67abf', class: "control-loader", part: "loader", "aria-hidden": "true" }, index$1.h("xv-loader-v2", { key: '66ffdb3f446ee255495d05c9a456a868b208c52a', size: "sm", variant: "horizontal" })))), message && (index$1.h("p", { key: '47f10c7a1e7a0eb5f9cfef0a303a667278833673', class: { message: true, [message.level]: true } }, message.text)), suggestionsVisible && (index$1.h("ul", { key: 'cba3064999cd0fa1159bb1a5b0967633de6d2e6f', id: `${this.uid}-listbox`, class: "suggestions", role: "listbox", part: "listbox" }, this.filtered.map((opt, idx) => (index$1.h("li", { id: this.optionId(idx), class: { 'suggestions-opt': true, 'suggestions-opt--highlight': idx === this.highlighted }, role: "option", "aria-selected": idx === this.highlighted, onMouseEnter: () => this.onOptionMouseEnter(idx), onMouseDown: (ev) => ev.preventDefault(), onClick: () => this.selectOption(opt) }, index$1.h("div", { class: "suggestions-opt-content" }, opt.bg ? index$1.h("span", { class: "suggestions-opt-content--color", style: { background: opt.bg } }) : null, index$1.h("span", { class: "suggestions-opt-content--label" }, this.highlightLabel(opt.label).map((seg, i) => typeof seg === 'string' ? index$1.h("span", { key: i }, seg) : index$1.h("strong", { key: i }, seg.match)))))))))));
84404
85787
  }
84405
85788
  get host() { return index$1.getElement(this); }
84406
85789
  static get watchers() { return {
@@ -84432,7 +85815,7 @@ const XvTag = class {
84432
85815
  this.closeClick.emit(e);
84433
85816
  }
84434
85817
  render() {
84435
- return (index$1.h(index$1.Host, { key: 'cd0cab01aba5ad627de9cc282c57032b83280c92', style: { color: this.color, background: this.bg }, class: `xv-tag ${this.disabled ? 'disabled' : ''} ${this.size}` }, index$1.h("div", { key: '094a98000cf24d32d8fc47821f0aa704ab61419e', class: "xv-tag_content", part: "details-content" }, index$1.h("slot", { key: 'c19eeb245989563c381268b0ffdaf6d228c9bc04' })), this.closeable && (index$1.h("button", { key: '38df038e4ec7ebcf387ba1008f7bb3e66fe93cfa', onClick: this.closeHandler.bind(this), class: "xv-tag_close" }))));
85818
+ return (index$1.h(index$1.Host, { key: '138d2cd5c76589ffd98054c7af17905921725aab', style: { color: this.color, background: this.bg }, class: `xv-tag ${this.disabled ? 'disabled' : ''} ${this.size}` }, index$1.h("div", { key: 'd3fe0db007cf464d64a63ed907c60dc0fd61c19c', class: "xv-tag_content", part: "details-content" }, index$1.h("slot", { key: 'caaebab8bce651040ac5c3291ffa2668b04cac56' })), this.closeable && (index$1.h("button", { key: 'ab6790f6b80906dcf28aee7fc739e375ae774df4', onClick: this.closeHandler.bind(this), class: "xv-tag_close" }))));
84436
85819
  }
84437
85820
  };
84438
85821
  XvTag.style = xvTagCss();
@@ -84472,13 +85855,13 @@ const XvTextInput = class {
84472
85855
  }
84473
85856
  render() {
84474
85857
  const message = index$2.resolveFieldMessage({ error: this.error, warning: this.warning, helper: this.helper });
84475
- return (index$1.h(index$1.Host, { key: 'bb73bf066f367a9062cebeb186bce1310929d6ac', class: { disabled: !!this.disabled } }, index$1.h("label", { key: 'c6051d9ecac23444845e61345631aede0c5a14c2', class: "control" }, this.label && index$1.h("span", { key: '921f096a485031eeb34b3385200270a29f1d61d1', class: "control_label" }, this.label), index$1.h("div", { key: '2e8a94946100504e6a5d820f4a2c67c03557fe1f', class: {
85858
+ return (index$1.h(index$1.Host, { key: '9aec75a885d16f416708047095897ac987b9e1ec', class: { disabled: !!this.disabled } }, index$1.h("label", { key: '4d6934a4208df6e858277366e7a74da9ec7c0ed3', class: "control" }, this.label && index$1.h("span", { key: '57c1974e09512b744aecc18dacfe7cae0bac6921', class: "control_label" }, this.label), index$1.h("div", { key: '5b0dd4d878da6e8bfc05a0f704954081e9b8058d', class: {
84476
85859
  'control_input': true,
84477
85860
  readonly: !!this.readonly,
84478
85861
  [this.size]: true,
84479
85862
  error: !!this.error,
84480
85863
  warning: !!this.warning,
84481
- } }, index$1.h("input", { key: '2f458206c2ba1960611e57e14167d2d40b34c433', autocomplete: this.autocomplete, type: (this.type === 'password' && this.isPasswordVisible && 'text') || this.type, placeholder: this.placeholder, disabled: this.disabled, readonly: this.readonly, onInput: this.handleInput, name: this.name, value: this.value }), index$1.h("div", { key: '1028060cff07974a58f87e6ee097e0f7eeaf00ee', class: "control_input__icons" }, this.loading && index$1.h("xv-loader-v2", { key: '478195557f75714c67a98020229c4c1591ab015e', size: _vars.SIZE_VAR.XS }), this.clearable && this.value && !this.loading && !this.disabled && !this.readonly && (index$1.h("button", { key: '4019006c7b199a3f2014d36284d20e1a17d122ae', type: "button", class: "status-icon clear", "aria-label": "Clear", onClick: this.handleClear }, "\u00D7")), !!this.error ? (index$1.h("span", { class: "status-icon error", "aria-hidden": "true" }, "!")) : !!this.warning ? (index$1.h("span", { class: "status-icon warning", "aria-hidden": "true" }, "\u26A0")) : null, this.type === 'password' && (index$1.h("button", { key: 'b3405a4b94e72b0e577c36448cae2afdea3e6b7a', onClick: this.togglePassword, disabled: this.disabled, class: "status-icon" }, index$1.h("svg", { key: '39cbc33366ff94fc0893f3ccff1716b862d232bd', xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 640 512", width: 16, height: 16 }, this.isPasswordVisible ? (index$1.h("path", { fill: "currentColor", d: "M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zm151 118.3C226 97.7 269.5 80 320 80c65.2 0 118.8 29.6 159.9 67.7C518.4 183.5 545 226 558.6 256c-12.6 28-36.6 66.8-70.9 100.9l-53.8-42.2c9.1-17.6 14.2-37.5 14.2-58.7c0-70.7-57.3-128-128-128c-32.2 0-61.7 11.9-84.2 31.5l-46.1-36.1zM394.9 284.2l-81.5-63.9c4.2-8.5 6.6-18.2 6.6-28.3c0-5.5-.7-10.9-2-16c.7 0 1.3 0 2 0c44.2 0 80 35.8 80 80c0 9.9-1.8 19.4-5.1 28.2zm9.4 130.3C378.8 425.4 350.7 432 320 432c-65.2 0-118.8-29.6-159.9-67.7C121.6 328.5 95 286 81.4 256c8.3-18.4 21.5-41.5 39.4-64.8L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5l-41.9-33zM192 256c0 70.7 57.3 128 128 128c13.3 0 26.1-2 38.2-5.8L302 334c-23.5-5.4-43.1-21.2-53.7-42.3l-56.1-44.2c-.2 2.8-.3 5.6-.3 8.5z" })) : (index$1.h("path", { fill: "currentColor", d: "M288 80c-65.2 0-118.8 29.6-159.9 67.7C89.6 183.5 63 226 49.4 256c13.6 30 40.2 72.5 78.6 108.3C169.2 402.4 222.8 432 288 432s118.8-29.6 159.9-67.7C486.4 328.5 513 286 526.6 256c-13.6-30-40.2-72.5-78.6-108.3C406.8 109.6 353.2 80 288 80zM95.4 112.6C142.5 68.8 207.2 32 288 32s145.5 36.8 192.6 80.6c46.8 43.5 78.1 95.4 93 131.1c3.3 7.9 3.3 16.7 0 24.6c-14.9 35.7-46.2 87.7-93 131.1C433.5 443.2 368.8 480 288 480s-145.5-36.8-192.6-80.6C48.6 356 17.3 304 2.5 268.3c-3.3-7.9-3.3-16.7 0-24.6C17.3 208 48.6 156 95.4 112.6zM288 336c44.2 0 80-35.8 80-80s-35.8-80-80-80c-.7 0-1.3 0-2 0c1.3 5.1 2 10.5 2 16c0 35.3-28.7 64-64 64c-5.5 0-10.9-.7-16-2c0 .7 0 1.3 0 2c0 44.2 35.8 80 80 80zm0-208a128 128 0 1 1 0 256 128 128 0 1 1 0-256z" })))))))), message && (index$1.h("p", { key: '13bdeb70bde027cd09a66645298efe8b0d98b9a6', class: { message: true, [message.level]: true } }, message.text))));
85864
+ } }, index$1.h("input", { key: '0a5d8923bbcf54a551618557037a96b2e3c2166f', autocomplete: this.autocomplete, type: (this.type === 'password' && this.isPasswordVisible && 'text') || this.type, placeholder: this.placeholder, disabled: this.disabled, readonly: this.readonly, onInput: this.handleInput, name: this.name, value: this.value }), index$1.h("div", { key: 'a627fa606172a1e8d198b8dc8daadc280d39cfa2', class: "control_input__icons" }, this.loading && index$1.h("xv-loader-v2", { key: 'e2e9bb121daf4aedc173909545b80961db442002', size: _vars.SIZE_VAR.XS }), this.clearable && this.value && !this.loading && !this.disabled && !this.readonly && (index$1.h("button", { key: '45e514e856569d54bb4c98a8ac78a0aedc70ce37', type: "button", class: "status-icon clear", "aria-label": "Clear", onClick: this.handleClear }, "\u00D7")), !!this.error ? (index$1.h("span", { class: "status-icon error", "aria-hidden": "true" }, "!")) : !!this.warning ? (index$1.h("span", { class: "status-icon warning", "aria-hidden": "true" }, "\u26A0")) : null, this.type === 'password' && (index$1.h("button", { key: 'f7ae4b875d4a515e79fa1699d0fe3d4aa8b27586', onClick: this.togglePassword, disabled: this.disabled, class: "status-icon" }, index$1.h("svg", { key: '08bf622486f686fba2309004145c4c340faf8cd0', xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 640 512", width: 16, height: 16 }, this.isPasswordVisible ? (index$1.h("path", { fill: "currentColor", d: "M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zm151 118.3C226 97.7 269.5 80 320 80c65.2 0 118.8 29.6 159.9 67.7C518.4 183.5 545 226 558.6 256c-12.6 28-36.6 66.8-70.9 100.9l-53.8-42.2c9.1-17.6 14.2-37.5 14.2-58.7c0-70.7-57.3-128-128-128c-32.2 0-61.7 11.9-84.2 31.5l-46.1-36.1zM394.9 284.2l-81.5-63.9c4.2-8.5 6.6-18.2 6.6-28.3c0-5.5-.7-10.9-2-16c.7 0 1.3 0 2 0c44.2 0 80 35.8 80 80c0 9.9-1.8 19.4-5.1 28.2zm9.4 130.3C378.8 425.4 350.7 432 320 432c-65.2 0-118.8-29.6-159.9-67.7C121.6 328.5 95 286 81.4 256c8.3-18.4 21.5-41.5 39.4-64.8L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5l-41.9-33zM192 256c0 70.7 57.3 128 128 128c13.3 0 26.1-2 38.2-5.8L302 334c-23.5-5.4-43.1-21.2-53.7-42.3l-56.1-44.2c-.2 2.8-.3 5.6-.3 8.5z" })) : (index$1.h("path", { fill: "currentColor", d: "M288 80c-65.2 0-118.8 29.6-159.9 67.7C89.6 183.5 63 226 49.4 256c13.6 30 40.2 72.5 78.6 108.3C169.2 402.4 222.8 432 288 432s118.8-29.6 159.9-67.7C486.4 328.5 513 286 526.6 256c-13.6-30-40.2-72.5-78.6-108.3C406.8 109.6 353.2 80 288 80zM95.4 112.6C142.5 68.8 207.2 32 288 32s145.5 36.8 192.6 80.6c46.8 43.5 78.1 95.4 93 131.1c3.3 7.9 3.3 16.7 0 24.6c-14.9 35.7-46.2 87.7-93 131.1C433.5 443.2 368.8 480 288 480s-145.5-36.8-192.6-80.6C48.6 356 17.3 304 2.5 268.3c-3.3-7.9-3.3-16.7 0-24.6C17.3 208 48.6 156 95.4 112.6zM288 336c44.2 0 80-35.8 80-80s-35.8-80-80-80c-.7 0-1.3 0-2 0c1.3 5.1 2 10.5 2 16c0 35.3-28.7 64-64 64c-5.5 0-10.9-.7-16-2c0 .7 0 1.3 0 2c0 44.2 35.8 80 80 80zm0-208a128 128 0 1 1 0 256 128 128 0 1 1 0-256z" })))))))), message && (index$1.h("p", { key: '2c1d43925fd56c86e47dfd88c4644b030639f81e', class: { message: true, [message.level]: true } }, message.text))));
84482
85865
  }
84483
85866
  static get formAssociated() { return true; }
84484
85867
  };
@@ -84516,12 +85899,12 @@ const XvTextarea = class {
84516
85899
  }
84517
85900
  render() {
84518
85901
  const message = index$2.resolveFieldMessage({ error: this.error, warning: this.warning, helper: this.helper });
84519
- return (index$1.h(index$1.Host, { key: '658e393a65602e686906bd2ad9eca9efd0d185fc', class: { disabled: !!this.disabled } }, index$1.h("label", { key: '93ad9edea381b99bcb7bcf1f692db00800776bf3', class: "control" }, (this.label || this.max) && (index$1.h("p", { key: 'fa5d19c60d4d528fe1fb7e7d5505d9927e69b1ec', class: "control_label" }, index$1.h("span", { key: '4bf48eb50474b3b74417a5ad3c01d09f6b485034' }, this.label, this.info && index$1.h("xv-tooltip-v2", { key: 'd7f1d420fbb2fa18d598b83e75a5218e4de1bfd4', message: this.info })), this.max !== undefined && !this.counterHide && (index$1.h("span", { key: '5053f5fa4902e4079d6163db7c13ff659bb656e5', class: "control_label__count" }, this.value.length || 0, "/", this.max)))), index$1.h("div", { key: '52762934c658eb768e494963ece43228dfa5926e', class: {
85902
+ return (index$1.h(index$1.Host, { key: '8f8a6e5f1886e21e52ffc3e006c4d43b1de420eb', class: { disabled: !!this.disabled } }, index$1.h("label", { key: '2097cfb9d893772a0aa1e2aa3aeadd5484ebb48e', class: "control" }, (this.label || this.max) && (index$1.h("p", { key: '4a5ce1d5ad1d62ba1ab1249b2f15504eafc727af', class: "control_label" }, index$1.h("span", { key: 'f8344446dcf38978181473292c6a748d394538f6' }, this.label, this.info && index$1.h("xv-tooltip-v2", { key: 'bf23e43f1b7f0ea94ba9cb376c4893ea413ec5df', message: this.info })), this.max !== undefined && !this.counterHide && (index$1.h("span", { key: '7b377f47c6b426428fbaee01746415032b75d0b5', class: "control_label__count" }, this.value.length || 0, "/", this.max)))), index$1.h("div", { key: 'b7e1937e704f7493544443d159e7b3c1783a1e45', class: {
84520
85903
  'control_input': true,
84521
85904
  readonly: !!this.readonly,
84522
85905
  error: !!this.error,
84523
85906
  warning: this.warning !== undefined,
84524
- } }, index$1.h("textarea", { key: '7b2e78e20deaf989e72df9ff44a78d3111b775ac', class: { 'no-resize': !!this.noResize }, name: this.name, rows: this.rows, value: this.value, maxLength: this.max, disabled: this.disabled, readOnly: this.readonly, placeholder: this.placeholder, onInput: this.onInput }), index$1.h("div", { key: '9cea8ecb9db775ce6aaa7573a140d5d308ff0d30', class: "control_input__icons" }, this._renderIcon()))), message && (index$1.h("p", { key: '7ddc85f57fca259024f1060ec85265f5c661e4e8', class: { message: true, [message.level]: true } }, message.text))));
85907
+ } }, index$1.h("textarea", { key: '4c09ca41ec313fca1f2df3e4e941d342d6121b6a', class: { 'no-resize': !!this.noResize }, name: this.name, rows: this.rows, value: this.value, maxLength: this.max, disabled: this.disabled, readOnly: this.readonly, placeholder: this.placeholder, onInput: this.onInput }), index$1.h("div", { key: '68dcba186158bf977193f908cf2a129452ba904e', class: "control_input__icons" }, this._renderIcon()))), message && (index$1.h("p", { key: '150534971f182c93c131fee2b00eae5cc78e7c30', class: { message: true, [message.level]: true } }, message.text))));
84525
85908
  }
84526
85909
  _renderIcon() {
84527
85910
  if (this.loading)
@@ -84572,7 +85955,7 @@ const XvTile = class {
84572
85955
  this.checked = !this.checked;
84573
85956
  }
84574
85957
  render() {
84575
- return (index$1.h(index$1.Host, { key: 'a2c476c09c531b51f71f991e1880b2a47204491a', class: "xv-tile--host" }, index$1.h("label", { key: '3e2a54ab149f6043179bb7d1cc9e37496482cde4', class: {
85958
+ return (index$1.h(index$1.Host, { key: '7a4262c881da376efbba73e6ecdeef845caefa0e', class: "xv-tile--host" }, index$1.h("label", { key: '9e3fcc2f59463c39d61352e84f89c6905b8b6754', class: {
84576
85959
  [this.el.className]: !!this.el.className,
84577
85960
  'xv-tile': true,
84578
85961
  [`xv-tile--variant-${this.variant}`]: !!this.variant,
@@ -84580,7 +85963,7 @@ const XvTile = class {
84580
85963
  'xv-tile--disabled': !!this.disabled,
84581
85964
  'selected': !!this.checked,
84582
85965
  'xv-tile--error': !!this.error,
84583
- } }, index$1.h("div", { key: 'fc25a98acbca605f9dc1184d60303e8114e2e43b', class: "xv-tile_content" }, this.label && index$1.h("p", { key: '0f466d3aa936261cdc54a0b7492b5f5737b2a778', class: "xv-tile_content__title" }, this.label), index$1.h("slot", { key: '8e6c17221070c8c5bde4049b55943155ba2e7c17' })), this.variant === 'selectable' && (index$1.h("div", { key: '98a511f78a1dfbbcc65e971a0dad71510a6830c5', class: "xv-tile_control" }, this.multiple ? (index$1.h("input", { type: "checkbox", disabled: this.disabled || this.readonly, readonly: this.readonly, onChange: this.handleChange, name: this.name, value: this.value, checked: this.checked })) : (index$1.h("input", { type: "radio", disabled: this.disabled || this.readonly, readonly: this.readonly, onChange: this.handleChange, name: this.name, value: this.value, checked: this.checked })))), (this.variant === 'clickable' || this.variant === 'expandable') && (index$1.h("div", { key: '0bcfa73c1f2fb1b2d6d2740258cde9483dbdcd87', class: "xv-tile_footer" }, index$1.h("button", { key: 'e6a2b02d5b4596596ba216c300c954fbb08268ee', class: { 'xv-tile_footer__icon': true, [`icon--${this.variant}`]: true, open: this.checked } }))), index$1.h("div", { key: '700535d5440bb57fd31382a2c0d0803f7cbdf239', class: { 'xv-tile_expandable': true, open: this.checked } }, index$1.h("slot", { key: '3888e0d07a757ef7e9f8d9a16ca04c9cce814b06', name: "expandable" })))));
85966
+ } }, index$1.h("div", { key: 'aacc76f7706cef6b3f7dc642e07f0aa0ed641368', class: "xv-tile_content" }, this.label && index$1.h("p", { key: 'c52856112766b1047581570dadd3ca3daa09e191', class: "xv-tile_content__title" }, this.label), index$1.h("slot", { key: 'c23faffc735f62a7007ad6ab25caad10278543d8' })), this.variant === 'selectable' && (index$1.h("div", { key: 'c9005b66ccb8feea162b43079762f7e2f8a7c5cf', class: "xv-tile_control" }, this.multiple ? (index$1.h("input", { type: "checkbox", disabled: this.disabled || this.readonly, readonly: this.readonly, onChange: this.handleChange, name: this.name, value: this.value, checked: this.checked })) : (index$1.h("input", { type: "radio", disabled: this.disabled || this.readonly, readonly: this.readonly, onChange: this.handleChange, name: this.name, value: this.value, checked: this.checked })))), (this.variant === 'clickable' || this.variant === 'expandable') && (index$1.h("div", { key: '08d6633d4a19ea03c761d18b20f164ae23002479', class: "xv-tile_footer" }, index$1.h("button", { key: 'ff242c00e2dadf564d146a02ac944d1bee7c7ec7', class: { 'xv-tile_footer__icon': true, [`icon--${this.variant}`]: true, open: this.checked } }))), index$1.h("div", { key: '27350c54f82cf8c78e49c04fc2b2b4fb0e4bbb96', class: { 'xv-tile_expandable': true, open: this.checked } }, index$1.h("slot", { key: '85f9a007a422ca5e7c06239d771cc8ede86a4e21', name: "expandable" })))));
84584
85967
  }
84585
85968
  get el() { return index$1.getElement(this); }
84586
85969
  };
@@ -84612,7 +85995,7 @@ const XvToggle = class {
84612
85995
  };
84613
85996
  }
84614
85997
  render() {
84615
- return (index$1.h(index$1.Host, { key: '37a5b9544456493cc34c79b2b7f5b00e23e287c2', class: { 'xv-toggle': true, disabled: this.disabled, readonly: !!this.readonly, block: !!this.block } }, this.label && index$1.h("span", { key: '0a25845f45dafed5e868dc09443c45d566dc9c3f', class: "label" }, this.label), index$1.h("label", { key: '5d1da814a7de2b5965d51fe2eb1f17cfa30f6a0d', class: "control" }, index$1.h("slot", { key: 'c739617e825bf2ed051175cbeb5eb83d1fc298f3', name: "before" }), index$1.h("div", { key: '32bd77c1ca5f8e58892cf41d9004f3f38a63bb10', class: "control_input" }, index$1.h("input", { key: '9447c95ba00b07b288f650ac169f816607d624b9', type: "checkbox", readonly: this.readonly, name: this.name, value: this.value, checked: this.checked, disabled: this.disabled || this.readonly, onChange: this.onChange }), index$1.h("span", { key: 'ce5ae18fa782dda6a28e45e297cc9e04ace9c7cd', class: "toggle" })), index$1.h("slot", { key: 'e4005eee0f127a0a1a59c1930aae06fac534ae77', name: "after" }))));
85998
+ return (index$1.h(index$1.Host, { key: '752b686c9e361b4ca0a0ad48d61072a2c819373c', class: { 'xv-toggle': true, disabled: this.disabled, readonly: !!this.readonly, block: !!this.block } }, this.label && index$1.h("span", { key: 'c99e7d648d7886db04fbfaf16bedf40b982f6b72', class: "label" }, this.label), index$1.h("label", { key: 'ff15e59d5b7ace403030f997d8b1ddf3640f0bf6', class: "control" }, index$1.h("slot", { key: 'bea4d7593d2c7caca6b69e5cc219c1b8dbb55d09', name: "before" }), index$1.h("div", { key: '7ad81dc90a00339c8653605cfeb5468377be366b', class: "control_input" }, index$1.h("input", { key: 'ffbcaac266859de781476ba06e9e56069fd11ad4', type: "checkbox", readonly: this.readonly, name: this.name, value: this.value, checked: this.checked, disabled: this.disabled || this.readonly, onChange: this.onChange }), index$1.h("span", { key: 'd0b1915cd7ab776eb3b573802f5ee73ec417edde', class: "toggle" })), index$1.h("slot", { key: '4de504f5a68a747e097fed0260fe55b4dd93de57', name: "after" }))));
84616
85999
  }
84617
86000
  static get formAssociated() { return true; }
84618
86001
  };
@@ -84689,7 +86072,7 @@ const XvToggleTip = class {
84689
86072
  }
84690
86073
  ;
84691
86074
  render() {
84692
- return (index$1.h(index$1.Host, { key: 'fd081052d0ce9e3c3505e99914eb765e2c708144', class: "xv-toggle-tip" }, index$1.h("div", { key: '7820225106348327e96a5620a64e2c13c15e7129', class: { 'trigger': true, 'trigger--block': this.block }, role: "button", tabindex: "0", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": "popover", onClick: () => this.setPopover(!this.open), ref: (el) => (this.triggerEl = el) }, index$1.h("slot", { key: 'daa48bf90a6b283a361414047b9f5cc194d6969c', name: "trigger" }, index$1.h("svg", { key: '37abc5de519c6b48bff301a48ddc11edffc23008', class: "trigger_icon", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", width: 16, height: 16 }, index$1.h("path", { key: '120b7659351f0dacc52c818803dc735fe4e4dfc8', fill: "currentColor", d: "M256 48a208 208 0 1 1 0 416 208 208 0 1 1 0-416zm0 464A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336c-13.3 0-24 10.7-24 24s10.7 24 24 24l80 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-8 0 0-88c0-13.3-10.7-24-24-24l-48 0c-13.3 0-24 10.7-24 24s10.7 24 24 24l24 0 0 64-24 0zm40-144a32 32 0 1 0 0-64 32 32 0 1 0 0 64z" })))), index$1.h("div", { key: 'edc6f66c90815a764e884bbb3adea6687a9148a8', class: { popover: true, autoSize: !!this.autoSize }, role: "tooltip", tabindex: "-1", ref: (el) => (this.popoverEl = el) }, index$1.h("div", { key: '592926c0f4c6534bfcf5d01b6ca6b4bfe63f1337', class: "popover-tip", part: "tip", "data-popper-arrow": "" }), index$1.h("div", { key: 'e91dc73a6c6acf68173a05a932615fcf3e3dfe27', class: "popover-content" }, index$1.h("slot", { key: 'afaac527e6f4853075417b598795a37322612888', name: "header" }), index$1.h("slot", { key: 'cc047953642b7c4b686c1f7af1a0647cf84e6001', name: "body" }), index$1.h("slot", { key: 'b4b8a501b0fc655fb2151726121ab5b882af0ce7', name: "footer" })))));
86075
+ return (index$1.h(index$1.Host, { key: '355065995790b620e5ed8b5d561b2898f787ac15', class: "xv-toggle-tip" }, index$1.h("div", { key: 'ff20f44061ee280105d53176e5c508e0845df871', class: { 'trigger': true, 'trigger--block': this.block }, role: "button", tabindex: "0", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": "popover", onClick: () => this.setPopover(!this.open), ref: (el) => (this.triggerEl = el) }, index$1.h("slot", { key: 'd407db9a0df2a9f90b628ed79d6c648eed2c2c70', name: "trigger" }, index$1.h("svg", { key: 'f82ed966ca4436d8dde8bf5c2b992466f541224f', class: "trigger_icon", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", width: 16, height: 16 }, index$1.h("path", { key: '6f5187fbf1560ebd7a3f2e529d3fdd15fa80fea0', fill: "currentColor", d: "M256 48a208 208 0 1 1 0 416 208 208 0 1 1 0-416zm0 464A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336c-13.3 0-24 10.7-24 24s10.7 24 24 24l80 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-8 0 0-88c0-13.3-10.7-24-24-24l-48 0c-13.3 0-24 10.7-24 24s10.7 24 24 24l24 0 0 64-24 0zm40-144a32 32 0 1 0 0-64 32 32 0 1 0 0 64z" })))), index$1.h("div", { key: '76fc29909a52ce4701d71e3509c4ebe8d1d32ee2', class: { popover: true, autoSize: !!this.autoSize }, role: "tooltip", tabindex: "-1", ref: (el) => (this.popoverEl = el) }, index$1.h("div", { key: 'afabe0c85104f8c5e204677b53f5815f314a5039', class: "popover-tip", part: "tip", "data-popper-arrow": "" }), index$1.h("div", { key: 'f274e790046bcf6edc8123b2b0bcda895931772c', class: "popover-content" }, index$1.h("slot", { key: '8f28653ab605ae2eee5c7027532b024e914a8c13', name: "header" }), index$1.h("slot", { key: '1c26b3cb17db7fc9256fd42f7dcddb51eb182db5', name: "body" }), index$1.h("slot", { key: '3b537a669336579f2285784f469d4425d0f1cc31', name: "footer" })))));
84693
86076
  }
84694
86077
  disconnectedCallback() {
84695
86078
  this.destroyPopper();
@@ -84744,11 +86127,11 @@ const XvTooltip = class {
84744
86127
  this.destroyTooltip();
84745
86128
  }
84746
86129
  render() {
84747
- return (index$1.h(index$1.Host, { key: 'a435539ec69538a238bd35c6d4867c18da9a7a40', role: "tooltip", class: {
86130
+ return (index$1.h(index$1.Host, { key: 'a6853dc450f6d063a702a1791297963f1530c003', role: "tooltip", class: {
84748
86131
  'xv-tooltip-wrapper': true,
84749
86132
  [`xv-tooltip-wrapper__block`]: !!this.block,
84750
86133
  [`xv-tooltip-wrapper__dashed`]: !!this.dashed,
84751
- } }, index$1.h("slot", { key: 'd766446f98777a9e680867a372ed4df0843b77b0' }, index$1.h("svg", { key: '9b2c7d9ed60fb6b4b82c034feef022468df3bf5c', xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", width: 16, height: 16 }, index$1.h("path", { key: '526be5c67ca24171376da19d7dd1c1f7c09d8edc', fill: "currentColor", d: "M256 48a208 208 0 1 1 0 416 208 208 0 1 1 0-416zm0 464A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336c-13.3 0-24 10.7-24 24s10.7 24 24 24l80 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-8 0 0-88c0-13.3-10.7-24-24-24l-48 0c-13.3 0-24 10.7-24 24s10.7 24 24 24l24 0 0 64-24 0zm40-144a32 32 0 1 0 0-64 32 32 0 1 0 0 64z" })))));
86134
+ } }, index$1.h("slot", { key: 'db5ea6da812b85930e8c74dc2ceaf59f8e6197b1' }, index$1.h("svg", { key: '7ac24beb22b912f77ec3535309019833f28fd375', xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", width: 16, height: 16 }, index$1.h("path", { key: 'b86e5339a9af99e6011fceea6d8b77e89dcd0e19', fill: "currentColor", d: "M256 48a208 208 0 1 1 0 416 208 208 0 1 1 0-416zm0 464A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336c-13.3 0-24 10.7-24 24s10.7 24 24 24l80 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-8 0 0-88c0-13.3-10.7-24-24-24l-48 0c-13.3 0-24 10.7-24 24s10.7 24 24 24l24 0 0 64-24 0zm40-144a32 32 0 1 0 0-64 32 32 0 1 0 0 64z" })))));
84752
86135
  }
84753
86136
  get el() { return index$1.getElement(this); }
84754
86137
  };
@@ -84791,10 +86174,9 @@ exports.xv_progress_indicator_v2_item = XvProgressIndicatorItem;
84791
86174
  exports.xv_radio_v2 = XvRadio;
84792
86175
  exports.xv_slider_v2 = XvSlider;
84793
86176
  exports.xv_tab_v2 = XvTab;
84794
- exports.xv_table_v2 = XvTable;
84795
- exports.xv_table_v2_cell = XvTableCell;
84796
- exports.xv_table_v2_expand = XvTableExpand;
84797
- exports.xv_table_v2_row = XvTableRow;
86177
+ exports.xv_table = XvTable;
86178
+ exports.xv_table_cell = XvTableCell;
86179
+ exports.xv_table_row = XvTableRow;
84798
86180
  exports.xv_tabs_v2 = XvTabs;
84799
86181
  exports.xv_tag_combobox = XvTagCombobox;
84800
86182
  exports.xv_tag_v2 = XvTag;