@nova-design-system/nova-webcomponents 3.16.0 → 3.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/cjs/index-93d3b2f8.js +4 -0
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/native.cjs.js +1 -1
  4. package/dist/cjs/nv-button.cjs.entry.js +1 -7
  5. package/dist/cjs/nv-button.cjs.entry.js.map +1 -1
  6. package/dist/cjs/nv-split.cjs.entry.js +339 -0
  7. package/dist/cjs/nv-split.cjs.entry.js.map +1 -0
  8. package/dist/cjs/nv-stack.cjs.entry.js +1 -1
  9. package/dist/cjs/nv-table.cjs.entry.js +1 -1
  10. package/dist/cjs/nv-toggle.cjs.entry.js +2 -2
  11. package/dist/cjs/nv-togglebutton.cjs.entry.js +1 -1
  12. package/dist/cjs/nv-togglebuttongroup.cjs.entry.js +1 -1
  13. package/dist/cjs/nv-tooltip.cjs.entry.js +1 -1
  14. package/dist/collection/collection-manifest.json +1 -0
  15. package/dist/collection/components/nv-button/nv-button.js +1 -13
  16. package/dist/collection/components/nv-button/nv-button.js.map +1 -1
  17. package/dist/collection/components/nv-split/nv-split.docs.js +41 -0
  18. package/dist/collection/components/nv-split/nv-split.docs.js.map +1 -0
  19. package/dist/collection/components/nv-split/nv-split.js +549 -0
  20. package/dist/collection/components/nv-split/nv-split.js.map +1 -0
  21. package/dist/collection/components/nv-split/styles/nv-split.css +96 -0
  22. package/dist/collection/components/nv-stack/nv-stack.js +1 -1
  23. package/dist/collection/components/nv-table/nv-table.js +1 -1
  24. package/dist/collection/components/nv-toggle/nv-toggle.js +2 -2
  25. package/dist/collection/components/nv-togglebutton/nv-togglebutton.js +1 -1
  26. package/dist/collection/components/nv-togglebuttongroup/nv-togglebuttongroup.js +1 -1
  27. package/dist/collection/components/nv-tooltip/nv-tooltip.js +1 -1
  28. package/dist/components/nv-breadcrumb.js +1 -1
  29. package/dist/components/nv-button.js +1 -1
  30. package/dist/components/nv-dialog.js +2 -2
  31. package/dist/components/nv-dialogfooter.js +1 -1
  32. package/dist/components/nv-split.d.ts +11 -0
  33. package/dist/components/nv-split.js +366 -0
  34. package/dist/components/nv-split.js.map +1 -0
  35. package/dist/components/nv-stack.js +1 -1
  36. package/dist/components/nv-table.js +1 -1
  37. package/dist/components/nv-toggle.js +2 -2
  38. package/dist/components/nv-togglebutton.js +1 -1
  39. package/dist/components/nv-togglebuttongroup.js +1 -1
  40. package/dist/components/nv-tooltip.js +1 -1
  41. package/dist/components/{p-9707528d.js → p-6f2b257e.js} +2 -2
  42. package/dist/components/{p-9707528d.js.map → p-6f2b257e.js.map} +1 -1
  43. package/dist/components/{p-a1ef5e37.js → p-7b5102c8.js} +2 -2
  44. package/dist/components/{p-a1ef5e37.js.map → p-7b5102c8.js.map} +1 -1
  45. package/dist/components/{p-2d64749f.js → p-9e7468e3.js} +3 -9
  46. package/dist/components/p-9e7468e3.js.map +1 -0
  47. package/dist/esm/index-dc2723f3.js +4 -0
  48. package/dist/esm/loader.js +1 -1
  49. package/dist/esm/native.js +1 -1
  50. package/dist/esm/nv-button.entry.js +1 -7
  51. package/dist/esm/nv-button.entry.js.map +1 -1
  52. package/dist/esm/nv-split.entry.js +335 -0
  53. package/dist/esm/nv-split.entry.js.map +1 -0
  54. package/dist/esm/nv-stack.entry.js +1 -1
  55. package/dist/esm/nv-table.entry.js +1 -1
  56. package/dist/esm/nv-toggle.entry.js +2 -2
  57. package/dist/esm/nv-togglebutton.entry.js +1 -1
  58. package/dist/esm/nv-togglebuttongroup.entry.js +1 -1
  59. package/dist/esm/nv-tooltip.entry.js +1 -1
  60. package/dist/native/native.css +1 -1
  61. package/dist/native/native.esm.js +1 -1
  62. package/dist/native/native.esm.js.map +1 -1
  63. package/dist/native/{p-445221dc.entry.js → p-14e622e1.entry.js} +2 -2
  64. package/dist/native/p-2364aefa.entry.js +2 -0
  65. package/dist/native/p-2364aefa.entry.js.map +1 -0
  66. package/dist/native/{p-44a78545.entry.js → p-52d2c0ae.entry.js} +2 -2
  67. package/dist/native/{p-a2f58133.entry.js → p-638967bf.entry.js} +2 -2
  68. package/dist/native/{p-075d231e.entry.js → p-91fab6c2.entry.js} +2 -2
  69. package/dist/native/{p-d45ee8e5.entry.js → p-a6fc987a.entry.js} +2 -2
  70. package/dist/native/p-a6fc987a.entry.js.map +1 -0
  71. package/dist/native/{p-dfb6b65e.entry.js → p-cb0293ec.entry.js} +2 -2
  72. package/dist/native/{p-b02c896a.entry.js → p-d94bf052.entry.js} +2 -2
  73. package/dist/types/components/nv-button/nv-button.d.ts +0 -1
  74. package/dist/types/components/nv-split/nv-split.d.ts +128 -0
  75. package/dist/types/components/nv-split/nv-split.docs.d.ts +4 -0
  76. package/dist/types/components.d.ts +107 -0
  77. package/dist/vscode-data.json +25 -0
  78. package/hydrate/index.js +363 -15
  79. package/hydrate/index.mjs +363 -15
  80. package/package.json +5 -1
  81. package/dist/components/p-2d64749f.js.map +0 -1
  82. package/dist/native/p-d45ee8e5.entry.js.map +0 -1
  83. /package/dist/native/{p-445221dc.entry.js.map → p-14e622e1.entry.js.map} +0 -0
  84. /package/dist/native/{p-44a78545.entry.js.map → p-52d2c0ae.entry.js.map} +0 -0
  85. /package/dist/native/{p-a2f58133.entry.js.map → p-638967bf.entry.js.map} +0 -0
  86. /package/dist/native/{p-075d231e.entry.js.map → p-91fab6c2.entry.js.map} +0 -0
  87. /package/dist/native/{p-dfb6b65e.entry.js.map → p-cb0293ec.entry.js.map} +0 -0
  88. /package/dist/native/{p-b02c896a.entry.js.map → p-d94bf052.entry.js.map} +0 -0
package/hydrate/index.mjs CHANGED
@@ -6341,12 +6341,6 @@ class NvButton {
6341
6341
  this.el.click();
6342
6342
  }
6343
6343
  }
6344
- handleTouchStart(event) {
6345
- if (event.touches.length > 1)
6346
- return;
6347
- event.preventDefault();
6348
- this.el.click();
6349
- }
6350
6344
  //#endregion EVENTS
6351
6345
  /****************************************************************************/
6352
6346
  //#region WATCHERS
@@ -6374,7 +6368,7 @@ class NvButton {
6374
6368
  /****************************************************************************/
6375
6369
  //#region RENDER
6376
6370
  render() {
6377
- return (hAsync(Host, { key: '54c0b3351f4d8a180058a03e61a562882fb98498', role: "button", tabindex: "0", onClick: this.handleButtonClick }, this.loading && (hAsync("nv-loader", { key: '21315e4af4111bcf47c67e65a9a58a1d7121a43e', size: this.size === ButtonSize.Large ? 'sm' : 'xs' })), hAsync("slot", { key: 'f37683ddaa2c11c5b7accfc99429c930f5a3dcf6', name: "leading-icon" }), hAsync("slot", { key: 'd17ebe7505d9027c6c58f930a8ea9b097561cead' }), hAsync("slot", { key: '2cd6c9756cc7540417041adf5830b734291b2ab5', name: "trailing-icon" })));
6371
+ return (hAsync(Host, { key: '42488f71ad33233c839cd70b3ea57aee50b143b3', role: "button", tabindex: "0", onClick: this.handleButtonClick }, this.loading && (hAsync("nv-loader", { key: 'a30c71eebb8f0476bcca5acbc8e7ac7f6377740c', size: this.size === ButtonSize.Large ? 'sm' : 'xs' })), hAsync("slot", { key: '4bbcee81ef7236ae35471c649971c122e4b468f3', name: "leading-icon" }), hAsync("slot", { key: '82203f6aed911e61aef2438bba3b3e664ffb9f76' }), hAsync("slot", { key: 'c97a5ce78c15556b8c1a91a4d06eb6bc9a9cd255', name: "trailing-icon" })));
6378
6372
  }
6379
6373
  static get formAssociated() { return true; }
6380
6374
  get el() { return getElement(this); }
@@ -6397,7 +6391,7 @@ class NvButton {
6397
6391
  "type": [513],
6398
6392
  "form": [513]
6399
6393
  },
6400
- "$listeners$": [[0, "keydown", "handleKeyDown"], [0, "touchstart", "handleTouchStart"]],
6394
+ "$listeners$": [[0, "keydown", "handleKeyDown"]],
6401
6395
  "$lazyBundleId$": "-",
6402
6396
  "$attrsToReflect$": [["size", "size"], ["emphasis", "emphasis"], ["active", "active"], ["danger", "danger"], ["loading", "loading"], ["disabled", "disabled"], ["fluid", "fluid"], ["type", "type"], ["form", "form"]]
6403
6397
  }; }
@@ -26941,6 +26935,359 @@ class NvRow {
26941
26935
  }; }
26942
26936
  }
26943
26937
 
26938
+ const nvSplitCss = "nv-split{display:flex;width:100%;height:100%;position:relative}nv-split[direction=horizontal]{flex-direction:row}nv-split[direction=vertical]{flex-direction:column}nv-split .nv-split-gutter{position:absolute;z-index:10;background:transparent;display:flex;align-items:center;justify-content:center;flex:0 0 auto;transition:background-color 0.2s ease}nv-split .nv-split-gutter::after{content:\"\";position:absolute;background:var(--nv-color-neutral-400, #ccc);border-radius:2px;transition:background-color 0.2s ease}nv-split .nv-split-gutter:hover::after{background:var(--nv-color-brand-primary, #0066cc)}nv-split .nv-split-gutter::before{content:\"\";position:absolute;background-repeat:no-repeat;background-position:center;opacity:0.4;transition:opacity 0.2s ease;pointer-events:none}nv-split .nv-split-gutter:hover::before{opacity:0.7}nv-split[direction=horizontal]>.nv-split-gutter{width:var(--nv-split-gutter-size, 24px);top:0;bottom:0;transform:translateX(-50%);cursor:col-resize}nv-split[direction=horizontal]>.nv-split-gutter::after{width:2px;height:60%;left:50%;top:20%;transform:translateX(-50%)}nv-split[direction=horizontal]>.nv-split-gutter::before{width:16px;height:16px}nv-split[direction=vertical]>.nv-split-gutter{height:var(--nv-split-gutter-size, 24px);left:0;right:0;transform:translateY(-50%);cursor:row-resize}nv-split[direction=vertical]>.nv-split-gutter::after{height:2px;width:60%;top:50%;left:20%;transform:translateY(-50%)}nv-split[direction=vertical]>.nv-split-gutter::before{width:16px;height:16px}nv-split[data-dragging=true]>.nv-split-gutter::after{background:var(--nv-color-neutral-500, #9ca3af)}nv-split>[slot=pane]{flex:1 1 auto;overflow:hidden;min-width:0;min-height:0;display:flex;flex-direction:column}nv-split>[slot=pane]>nv-split{flex:1 1 auto;width:100%;height:100%}";
26939
+ var NvSplitStyle0 = nvSplitCss;
26940
+
26941
+ /**
26942
+ * The `nv-split` component is an advanced layout container that enables the creation of interactively resizable panels. It provides a flexible solution for dividing available space between multiple interface sections, with precise control over dimensions and constraints for each panel.
26943
+ * @slot pane - Content of each split pane. Use multiple `<div slot="pane">` elements.
26944
+ * @slot gutter - Optional custom content inside every gutter handle.
26945
+ */
26946
+ class NvSplit {
26947
+ constructor(hostRef) {
26948
+ registerInstance(this, hostRef);
26949
+ this.sizesChanged = createEvent(this, "sizesChanged", 7);
26950
+ /****************************************************************************/
26951
+ //#region PROPERTIES
26952
+ /**
26953
+ * Direction of the split layout.
26954
+ * - `horizontal`: panes side by side
26955
+ * - `vertical`: panes stacked
26956
+ */
26957
+ this.direction = 'horizontal';
26958
+ /**
26959
+ * Initial sizes of the panes in percentages.
26960
+ * Example: `[50, 50]` means two equal panes.
26961
+ * Explicitly `reflect: false` (array) for framework compatibility.
26962
+ */
26963
+ this.sizes = [];
26964
+ /**
26965
+ * Width or height of the gutter (in px) depending on the split direction.
26966
+ * Default is 24px to meet WCAG 2.2 target size requirements for touch accessibility.
26967
+ */
26968
+ this.gutterSize = 24;
26969
+ //#endregion
26970
+ /****************************************************************************/
26971
+ //#region STATE
26972
+ this.isDragging = false;
26973
+ this.dragIndex = -1;
26974
+ this.startPos = 0;
26975
+ this.startSizes = [];
26976
+ // Handlers stored to be able to detach them
26977
+ this.onDocMove = (ev) => this.handleMouseMove(ev);
26978
+ this.onDocUp = () => this.stopDragging();
26979
+ }
26980
+ //#endregion
26981
+ /****************************************************************************/
26982
+ //#region WATCHERS
26983
+ onSizesChanged() {
26984
+ // Re-apply sizes if modified from the outside
26985
+ this.applySizes();
26986
+ }
26987
+ onDirectionChanged() {
26988
+ // Update the orientation and the cursors of the gutters
26989
+ this.ensureGutters();
26990
+ this.applySizes();
26991
+ }
26992
+ //#endregion
26993
+ /****************************************************************************/
26994
+ //#region LIFECYCLE
26995
+ componentDidLoad() {
26996
+ // Initialization (once)
26997
+ this.ensureGutters();
26998
+ this.applySizes();
26999
+ this.positionGutters();
27000
+ // Observer: reposition gutters when resized (nested or parent split changes)
27001
+ this.ro = new ResizeObserver(() => this.positionGutters());
27002
+ this.ro.observe(this.el);
27003
+ window.addEventListener('resize', () => this.positionGutters());
27004
+ }
27005
+ disconnectedCallback() {
27006
+ var _a;
27007
+ // Security cleanup (in case a drag was in progress)
27008
+ this.detachDocumentListeners();
27009
+ (_a = this.ro) === null || _a === void 0 ? void 0 : _a.disconnect();
27010
+ this.ro = undefined;
27011
+ }
27012
+ //#endregion
27013
+ /****************************************************************************/
27014
+ //#region PUBLIC METHODS
27015
+ /**
27016
+ * Programmatically set pane sizes.
27017
+ * @param {Array<number>} sizes Array of pane sizes in percentages.
27018
+ * @returns {Promise<void>}
27019
+ */
27020
+ async setSizes(sizes) {
27021
+ this.sizes = [...sizes];
27022
+ this.applySizes();
27023
+ this.sizesChanged.emit([...this.sizes]);
27024
+ this.positionGutters();
27025
+ }
27026
+ /**
27027
+ * Returns the current pane sizes.
27028
+ * @returns {Promise<number[]>} Array of pane sizes in percentages.
27029
+ */
27030
+ async getSizes() {
27031
+ return [...this.sizes];
27032
+ }
27033
+ /**
27034
+ * Collapse a specific pane to 0 size.
27035
+ * @param {number} index Index of the pane to collapse.
27036
+ * @returns {Promise<void>}
27037
+ */
27038
+ async collapse(index) {
27039
+ const panes = this.getPanes();
27040
+ if (index < 0 || index >= panes.length)
27041
+ return;
27042
+ // Simple strategy: 0% for the index, the rest (100%) for its nearest neighbor
27043
+ const next = new Array(panes.length).fill(0);
27044
+ const target = index < panes.length - 1 ? index + 1 : index - 1;
27045
+ if (target >= 0)
27046
+ next[target] = 100;
27047
+ this.sizes = next;
27048
+ this.applySizes();
27049
+ this.sizesChanged.emit([...this.sizes]);
27050
+ this.positionGutters();
27051
+ }
27052
+ /**
27053
+ * Destroy the split instance: removes gutters and resets layout state.
27054
+ * @returns {Promise<void>}
27055
+ */
27056
+ async destroy() {
27057
+ var _a;
27058
+ this.sizes = [];
27059
+ this.isDragging = false;
27060
+ this.dragIndex = -1;
27061
+ this.removeOwnGutters();
27062
+ this.detachDocumentListeners();
27063
+ (_a = this.ro) === null || _a === void 0 ? void 0 : _a.disconnect();
27064
+ }
27065
+ //#endregion
27066
+ /****************************************************************************/
27067
+ //#region INTERNAL HELPERS
27068
+ /**
27069
+ * Returns the panes of the split.
27070
+ * @returns {HTMLElement[]} The panes of the split.
27071
+ */
27072
+ getPanes() {
27073
+ // Only the direct children slot="pane"
27074
+ return Array.from(this.el.querySelectorAll(':scope > [slot="pane"]'));
27075
+ }
27076
+ /**
27077
+ * Returns the own gutters of the split.
27078
+ * @returns {HTMLElement[]} The own gutters of the split.
27079
+ */
27080
+ getOwnGutters() {
27081
+ // Only the direct gutters of THIS instance
27082
+ return Array.from(this.el.querySelectorAll(':scope > .nv-split-gutter[data-auto="true"]'));
27083
+ }
27084
+ /**
27085
+ * Removes the own gutters of the split.
27086
+ */
27087
+ removeOwnGutters() {
27088
+ this.getOwnGutters().forEach(g => g.remove());
27089
+ }
27090
+ /**
27091
+ * Ensures the gutters of the split.
27092
+ */
27093
+ ensureGutters() {
27094
+ const panes = this.getPanes();
27095
+ // 1) Clean ONLY the old direct gutters of THIS instance
27096
+ this.removeOwnGutters();
27097
+ if (panes.length <= 1)
27098
+ return;
27099
+ // 2) Add the gutters (directs) between the panes
27100
+ panes.forEach((pane, i) => {
27101
+ if (i >= panes.length - 1)
27102
+ return;
27103
+ const g = document.createElement('div');
27104
+ g.className = 'nv-split-gutter';
27105
+ g.setAttribute('data-auto', 'true');
27106
+ if (this.direction === 'horizontal') {
27107
+ g.style.width = `${this.gutterSize}px`;
27108
+ g.style.cursor = 'col-resize';
27109
+ }
27110
+ else {
27111
+ g.style.height = `${this.gutterSize}px`;
27112
+ g.style.cursor = 'row-resize';
27113
+ }
27114
+ // Customizable internal slot
27115
+ const slotEl = document.createElement('slot');
27116
+ slotEl.name = 'gutter';
27117
+ g.appendChild(slotEl);
27118
+ // Listener drag (index = gutter between pane i and i+1)
27119
+ g.addEventListener('mousedown', (ev) => this.startDragging(ev, i));
27120
+ // Insert just after the pane
27121
+ pane.insertAdjacentElement('afterend', g);
27122
+ });
27123
+ this.positionGutters();
27124
+ }
27125
+ /**
27126
+ * Applies the sizes to the panes.
27127
+ */
27128
+ applySizes() {
27129
+ const panes = this.getPanes();
27130
+ const n = panes.length;
27131
+ if (n === 0)
27132
+ return;
27133
+ // Default values if inconsistent
27134
+ if (!this.sizes || this.sizes.length !== n) {
27135
+ this.sizes = Array(n).fill(100 / n);
27136
+ }
27137
+ panes.forEach((pane, i) => {
27138
+ var _a;
27139
+ const size = Math.max(0, (_a = this.sizes[i]) !== null && _a !== void 0 ? _a : 100 / n);
27140
+ // Flex-basis via flex shorthand (https://developer.mozilla.org/en-US/docs/Web/CSS/flex)
27141
+ pane.style.flex = `0 0 ${size}%`;
27142
+ pane.style.minWidth = '0';
27143
+ pane.style.minHeight = '0';
27144
+ pane.style.overflow = 'hidden'; // let a nv-split child extend
27145
+ pane.style.display = 'flex';
27146
+ pane.style.flexDirection = 'column';
27147
+ });
27148
+ this.positionGutters();
27149
+ }
27150
+ /**
27151
+ * Attaches the document listeners.
27152
+ */
27153
+ attachDocumentListeners() {
27154
+ document.addEventListener('mousemove', this.onDocMove);
27155
+ document.addEventListener('mouseup', this.onDocUp);
27156
+ }
27157
+ /**
27158
+ * Detaches the document listeners.
27159
+ */
27160
+ detachDocumentListeners() {
27161
+ document.removeEventListener('mousemove', this.onDocMove);
27162
+ document.removeEventListener('mouseup', this.onDocUp);
27163
+ }
27164
+ /**
27165
+ * Positions the gutters based on the current sizes of the panes.
27166
+ */
27167
+ positionGutters() {
27168
+ var _a, _b;
27169
+ const panes = this.getPanes();
27170
+ const gutters = this.getOwnGutters();
27171
+ if (panes.length <= 1 || gutters.length === 0)
27172
+ return;
27173
+ const horizontal = this.direction === 'horizontal';
27174
+ let cumPct = 0;
27175
+ for (let i = 0; i < gutters.length; i++) {
27176
+ const sizePct = (_b = (_a = this.sizes) === null || _a === void 0 ? void 0 : _a[i]) !== null && _b !== void 0 ? _b : 100 / panes.length;
27177
+ cumPct += sizePct;
27178
+ const g = gutters[i];
27179
+ g.style.position = 'absolute';
27180
+ if (horizontal) {
27181
+ g.style.left = `${cumPct}%`;
27182
+ g.style.top = '0';
27183
+ g.style.bottom = '0';
27184
+ g.style.height = '100%';
27185
+ }
27186
+ else {
27187
+ g.style.top = `${cumPct}%`;
27188
+ g.style.left = '0';
27189
+ g.style.right = '0';
27190
+ g.style.width = '100%';
27191
+ }
27192
+ }
27193
+ }
27194
+ /**
27195
+ * Starts the dragging process.
27196
+ * @param {MouseEvent} ev - The mouse event.
27197
+ * @param {number} index - The index of the gutter.
27198
+ */
27199
+ startDragging(ev, index) {
27200
+ this.isDragging = true;
27201
+ this.dragIndex = index;
27202
+ this.startPos = this.direction === 'horizontal' ? ev.clientX : ev.clientY;
27203
+ this.startSizes = [...this.sizes];
27204
+ this.attachDocumentListeners();
27205
+ }
27206
+ /**
27207
+ * Handles the mouse movement during dragging.
27208
+ * @param {MouseEvent} ev - The mouse event.
27209
+ */
27210
+ handleMouseMove(ev) {
27211
+ var _a, _b, _c, _d;
27212
+ if (!this.isDragging || this.dragIndex < 0)
27213
+ return;
27214
+ const panes = this.getPanes();
27215
+ if (panes.length < 2)
27216
+ return;
27217
+ const rect = this.el.getBoundingClientRect();
27218
+ // Ensure we never divide by zero if the element has zero width/height
27219
+ const rawSize = this.direction === 'horizontal' ? rect.width : rect.height;
27220
+ const totalPx = Math.max(rawSize, 1);
27221
+ const deltaPx = (this.direction === 'horizontal' ? ev.clientX : ev.clientY) -
27222
+ this.startPos;
27223
+ const deltaPct = (deltaPx / totalPx) * 100;
27224
+ const i = this.dragIndex;
27225
+ const j = i + 1;
27226
+ let left = this.startSizes[i] + deltaPct;
27227
+ let right = this.startSizes[j] - deltaPct;
27228
+ // minSizes (px) -> %
27229
+ const minLeftPct = (((_b = (_a = this.minSizes) === null || _a === void 0 ? void 0 : _a[i]) !== null && _b !== void 0 ? _b : 0) / totalPx) * 100;
27230
+ const minRightPct = (((_d = (_c = this.minSizes) === null || _c === void 0 ? void 0 : _c[j]) !== null && _d !== void 0 ? _d : 0) / totalPx) * 100;
27231
+ left = Math.max(left, minLeftPct);
27232
+ right = Math.max(right, minRightPct);
27233
+ // Keep the sum of the pair i/j constant
27234
+ const pairSum = left + right;
27235
+ const targetSum = this.startSizes[i] + this.startSizes[j];
27236
+ if (Math.abs(pairSum - targetSum) > 0.0001) {
27237
+ const k = targetSum / (pairSum || 1);
27238
+ left *= k;
27239
+ right *= k;
27240
+ }
27241
+ const next = [...this.startSizes];
27242
+ next[i] = left;
27243
+ next[j] = right;
27244
+ this.sizes = next;
27245
+ this.applySizes();
27246
+ this.sizesChanged.emit([...this.sizes]);
27247
+ this.positionGutters();
27248
+ }
27249
+ /**
27250
+ * Stops the dragging process.
27251
+ */
27252
+ stopDragging() {
27253
+ if (!this.isDragging)
27254
+ return;
27255
+ this.isDragging = false;
27256
+ this.dragIndex = -1;
27257
+ this.detachDocumentListeners();
27258
+ }
27259
+ //#endregion
27260
+ /****************************************************************************/
27261
+ //#region RENDER
27262
+ render() {
27263
+ return (hAsync(Host, { key: 'e3b158ff1b4f665862079d245c219102d8b8ccda', "data-dragging": this.isDragging.toString() }, hAsync("slot", { key: 'baa8105a05bf8446d7a31a23cd5276edb320ea2f', name: "pane" }), hAsync("slot", { key: '44afe4f4a220aff45f802218f2618e9305141a9f', name: "gutter" })));
27264
+ }
27265
+ get el() { return getElement(this); }
27266
+ static get watchers() { return {
27267
+ "sizes": ["onSizesChanged"],
27268
+ "direction": ["onDirectionChanged"]
27269
+ }; }
27270
+ static get style() { return NvSplitStyle0; }
27271
+ static get cmpMeta() { return {
27272
+ "$flags$": 4,
27273
+ "$tagName$": "nv-split",
27274
+ "$members$": {
27275
+ "direction": [513],
27276
+ "sizes": [1040],
27277
+ "minSizes": [16],
27278
+ "gutterSize": [514, "gutter-size"],
27279
+ "isDragging": [32],
27280
+ "setSizes": [64],
27281
+ "getSizes": [64],
27282
+ "collapse": [64],
27283
+ "destroy": [64]
27284
+ },
27285
+ "$listeners$": undefined,
27286
+ "$lazyBundleId$": "-",
27287
+ "$attrsToReflect$": [["direction", "direction"], ["gutterSize", "gutter-size"]]
27288
+ }; }
27289
+ }
27290
+
26944
27291
  const nvStackCss = "nv-stack{display:flex;align-items:center;justify-content:flex-start;flex-direction:row}nv-stack nv-col{display:flex}nv-stack:not(nv-row){flex-wrap:nowrap}nv-stack>.nv-stack-item-flex{flex-shrink:1;flex-grow:1}nv-stack>.nv-stack-item-lead{margin-right:auto}nv-stack>.nv-stack-item-lead+*{margin-left:0}nv-stack>.nv-stack-item-center{margin-right:auto;margin-left:auto}nv-stack>.nv-stack-item-tail{margin-left:auto}nv-stack>.nv-stack-nowrap{white-space:nowrap}nv-stack.nv-stack-vertical{align-items:stretch;flex-direction:column}nv-stack.nv-stack-vertical>.nv-stack-item-lead{margin-right:0;margin-bottom:auto}nv-stack.nv-stack-vertical>.nv-stack-item-lead+*{margin-top:0}nv-stack.nv-stack-vertical>.nv-stack-item-tail{margin-left:0;margin-top:auto}nv-stack.nv-stack-vertical>.nv-stack-item-center{margin:auto 0}nv-stack.nv-stack-flex>*{flex-shrink:1;flex-grow:1}nv-stack.nv-stack-fill>*{height:100%}nv-stack.nv-stack-fill.nv-stack-vertical>*{height:auto;width:100%}";
26945
27292
  var NvStackStyle0 = nvStackCss;
26946
27293
 
@@ -26963,7 +27310,7 @@ class NvStack {
26963
27310
  /****************************************************************************/
26964
27311
  //#region RENDER
26965
27312
  render() {
26966
- return (hAsync(Host, { key: '8f771805224c769b5a87f5c550ddbcb8f888d002', class: clsx(this.fill && 'nv-stack-fill', this.flex && 'nv-stack-flex', this.full && 'w-full', this.gutter && !this.vertical && `gap-x-${this.gutter}`, this.gutter && this.vertical && `gap-y-${this.gutter}`, this.vertical && 'nv-stack-vertical') }, hAsync("slot", { key: '6fcd46cfd74415d2f07c762b065e3aa0f0194764' })));
27313
+ return (hAsync(Host, { key: '5922efd8652a14d73e812e85dd6770101e22fe46', class: clsx(this.fill && 'nv-stack-fill', this.flex && 'nv-stack-flex', this.full && 'w-full', this.gutter && !this.vertical && `gap-x-${this.gutter}`, this.gutter && this.vertical && `gap-y-${this.gutter}`, this.vertical && 'nv-stack-vertical') }, hAsync("slot", { key: '71daf4ee34bd57d785203f98799b6ea7c66ffa3b' })));
26967
27314
  }
26968
27315
  static get style() { return NvStackStyle0; }
26969
27316
  static get cmpMeta() { return {
@@ -27217,7 +27564,7 @@ class NvTable {
27217
27564
  /****************************************************************************/
27218
27565
  //#region RENDER
27219
27566
  render() {
27220
- return (hAsync(Host, { key: 'b63510e2da93a1b98eb3813ba7ac9bed97b81c1f' }, hAsync("slot", { key: '14fb76c397db4da5dfba94bce599d1e4d8992a6b' })));
27567
+ return (hAsync(Host, { key: '16b564cc29e8987d8b3fda3a84c0b19882a733bd' }, hAsync("slot", { key: '1305cbc6d29caa60df55bfa01a39a3417a27ec01' })));
27221
27568
  }
27222
27569
  get host() { return getElement(this); }
27223
27570
  static get style() { return NvTableStyle0; }
@@ -27295,8 +27642,8 @@ class NvToggle {
27295
27642
  /****************************************************************************/
27296
27643
  //#region RENDER
27297
27644
  render() {
27298
- return (hAsync(Host, { key: '65222149af4edb9f8fd2da7efe9a01e15dec4722', class: clsx(this.labelPlacement === 'before' && 'label-placement-before') }, hAsync("div", { key: '7edd5587281b5610269f1ac09826ce379abfae24', class: "input-container" }, hAsync("input", { key: '30d3db3cbdc263259a5ba1bf8e637225c4db3b4a', type: "checkbox", id: this.inputId, name: this.name, autocomplete: "off", value: this.value, checked: Boolean(this.checked), disabled: this.disabled || this.readonly, readonly: this.readonly })), hAsync("div", { key: 'a8a6d3c2774560b7d43cda75882d90cc564f4c54', class: "text-container" }, (this.label || this.el.querySelector('[slot="label"]')) && (hAsync("label", { key: 'fe980a07df4901081fda42df758236da0b8a11d0', htmlFor: this.inputId, class: clsx(this.hideLabel && 'visually-hidden') }, hAsync("slot", { key: '723cec5914c6c0bed7e14e61e2f64e83c8e8b7b8', name: "label" }, this.label))), (this.description ||
27299
- this.el.querySelector('[slot="description"]')) && (hAsync("div", { key: 'f811065ed06f0816d8f0f1f65d4c659cbde3f683', class: "description" }, hAsync("slot", { key: '541946e3f33a315bf667999c30a44fd93fc5f07f', name: "description" }, this.description))))));
27645
+ return (hAsync(Host, { key: '0f440b59ac0c32d9abe9577668d7045081819b49', class: clsx(this.labelPlacement === 'before' && 'label-placement-before') }, hAsync("div", { key: '4289435e34eb31a8e59e00cefcba2e17e98bd03a', class: "input-container" }, hAsync("input", { key: '1b7d05f77fd32cece9eed2e6cf79c7e2e707f64c', type: "checkbox", id: this.inputId, name: this.name, autocomplete: "off", value: this.value, checked: Boolean(this.checked), disabled: this.disabled || this.readonly, readonly: this.readonly })), hAsync("div", { key: '6d78d7e80eb790bbead21bba6108329f9ded3746', class: "text-container" }, (this.label || this.el.querySelector('[slot="label"]')) && (hAsync("label", { key: '524a2c2542a45945bddb688c5dff6c9426d58570', htmlFor: this.inputId, class: clsx(this.hideLabel && 'visually-hidden') }, hAsync("slot", { key: '59eda4b826602062620e7167acf3c8de0f77ebef', name: "label" }, this.label))), (this.description ||
27646
+ this.el.querySelector('[slot="description"]')) && (hAsync("div", { key: '6e8412879ed60fc6806464432348bd52483e3567', class: "description" }, hAsync("slot", { key: '85a876130569a5a4051e271eaf1cf49593a014a6', name: "description" }, this.description))))));
27300
27647
  }
27301
27648
  static get formAssociated() { return true; }
27302
27649
  get el() { return getElement(this); }
@@ -27372,7 +27719,7 @@ class NvTogglebutton {
27372
27719
  /****************************************************************************/
27373
27720
  //#region RENDER
27374
27721
  render() {
27375
- return (hAsync(Host, { key: 'c4b698b1fb80f0dcca5d7a77bc20d22db1cbf538', role: "button", tabindex: "0", "aria-pressed": String(this.active), onClick: this.handleClick }, hAsync("slot", { key: '605385f07f32b989685983cfd1a082525741fba4' })));
27722
+ return (hAsync(Host, { key: 'b9e37fc1cb34272bca476c7b61db173ab2a9d238', role: "button", tabindex: "0", "aria-pressed": String(this.active), onClick: this.handleClick }, hAsync("slot", { key: 'cf9cf3445fd93873def1f9fa9cbec46c35600025' })));
27376
27723
  }
27377
27724
  static get style() { return NvTogglebuttonStyle0; }
27378
27725
  static get cmpMeta() { return {
@@ -27546,7 +27893,7 @@ class NvTogglebuttongroup {
27546
27893
  /****************************************************************************/
27547
27894
  //#region RENDER
27548
27895
  render() {
27549
- return (hAsync(Host, { key: 'ab91ff1817e3388508ed1da7a9ed57a79cf8c4bc' }, hAsync("slot", { key: '4a3280db78c1f0cd120a0cb32d95eabaf69995a6' })));
27896
+ return (hAsync(Host, { key: '7aad0160ae8e093765ba42649293e27d7b93ab75' }, hAsync("slot", { key: '39364122a5e65b1a454bd782a5daacc7edfee8b0' })));
27550
27897
  }
27551
27898
  get el() { return getElement(this); }
27552
27899
  static get watchers() { return {
@@ -27617,7 +27964,7 @@ class NvTooltip {
27617
27964
  /****************************************************************************/
27618
27965
  //#region RENDER
27619
27966
  render() {
27620
- return (hAsync(Host, { key: 'c2fdcd47be909554e31a3a7d77cd94dcb07c0d6e' }, hAsync("slot", { key: '2305f6b7175d0ba84819351f60f2a4d76d117df9' }), hAsync("nv-popover", { key: 'e388730b5858671d08981c6bbf72588a5084edbf', triggerMode: "hover", hasArrow: true, placement: this.placement, strategy: this.strategy, triggerElement: this.triggerElement, groupName: 'tooltip', enterDelay: this.enterDelay }, hAsync("p", { key: '73f548a1c822f7c6d5a97bb4ef8da0d335cf049e', slot: "content" }, this.message), hAsync("slot", { key: 'abb7a2dfa6a327122732802a867c5d4057fd1616', name: "content" }))));
27967
+ return (hAsync(Host, { key: '5d5facbf2a0487bda4fbae49913a2cb4f69dcf5a' }, hAsync("slot", { key: '91080d347f3473879109f7b0b59b159f5bb5979b' }), hAsync("nv-popover", { key: '876e5e2487d1b2b5182e42909a6edeab5b3e9db2', triggerMode: "hover", hasArrow: true, placement: this.placement, strategy: this.strategy, triggerElement: this.triggerElement, groupName: 'tooltip', enterDelay: this.enterDelay }, hAsync("p", { key: 'e30ce16ed27e41dee7359fb44ccba7a780e72d37', slot: "content" }, this.message), hAsync("slot", { key: '395c75d7f45bab9aaebf979bd75087058b979350', name: "content" }))));
27621
27968
  }
27622
27969
  get el() { return getElement(this); }
27623
27970
  static get style() { return NvTooltipStyle0; }
@@ -27678,6 +28025,7 @@ registerComponents([
27678
28025
  NvNotificationContainer,
27679
28026
  NvPopover,
27680
28027
  NvRow,
28028
+ NvSplit,
27681
28029
  NvStack,
27682
28030
  NvTable,
27683
28031
  NvToggle,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nova-design-system/nova-webcomponents",
3
- "version": "3.16.0",
3
+ "version": "3.17.0",
4
4
  "description": "Nova is a design system created by Elia Group to empower creators to efficiently build solutions that people love to use.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -70,6 +70,10 @@
70
70
  "extract-comments": "1.1.0"
71
71
  },
72
72
  "exports": {
73
+ "./nv-split": {
74
+ "import": "./dist/components/nv-split.js",
75
+ "types": "./dist/components/nv-split.d.ts"
76
+ },
73
77
  "./nv-table": {
74
78
  "import": "./dist/components/nv-table.js",
75
79
  "types": "./dist/components/nv-table.d.ts"
@@ -1 +0,0 @@
1
- {"file":"p-2d64749f.js","mappings":"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","names":[],"sources":["src/components/nv-button/styles/nv-button.scss?tag=nv-button","src/components/nv-button/nv-button.tsx"],"sourcesContent":["@use \"./mixins\" as *;\n\n// Make sure to update nv-button class in the tailwind-components.scss file when\n// you add new styles or change the structure here.\nnv-button {\n @include root-styles();\n\n @each $size in $sizes {\n &[size=\"#{$size}\"] {\n @include size-styles($size);\n }\n }\n\n @each $emphasis in $emphases {\n &[emphasis=\"#{$emphasis}\"] {\n @include emphasis-styles($emphasis);\n\n &[active]:not([active=\"false\"]) {\n @include active-styles($emphasis);\n }\n\n &[danger]:not([danger=\"false\"]) {\n @include danger-styles($emphasis);\n }\n }\n }\n\n &[fluid]:not([fluid=\"false\"]) {\n @include fluid-styles();\n }\n\n &[loading]:not([loading=\"false\"]) {\n [slot=\"leading-icon\"] {\n display: none;\n }\n }\n}\n","import {\n Component,\n Listen,\n Host,\n h,\n Prop,\n AttachInternals,\n Element,\n Watch,\n} from '@stencil/core';\n\nimport { ButtonSize, ButtonEmphasis, ButtonType } from '../../utils/constants';\n\n/**\n * @slot default - Content of the button.\n * @slot leading-icon - Icon before the label.\n * @slot trailing-icon - Icon after the label.\n */\n@Component({\n tag: 'nv-button',\n shadow: false,\n formAssociated: true,\n styleUrl: 'styles/nv-button.scss',\n})\nexport class NvButton {\n @AttachInternals() internals: ElementInternals;\n @Element() el: HTMLNvButtonElement;\n\n /****************************************************************************/\n //#region PROPERTIES\n\n /**\n * Determines how large or small the button appears, allowing for\n * customization of the button's dimensions to fit different design\n * specifications and user needs.\n */\n @Prop({ reflect: true })\n readonly size: `${ButtonSize}` = 'md';\n\n /**\n * Adjusts the button's emphasis to make it more or less visually prominent\n * to users. Use this to draw attention to important actions or reduce focus\n * on less critical ones\n */\n @Prop({ reflect: true })\n readonly emphasis: `${ButtonEmphasis}` = 'high';\n\n /**\n * Use this prop to highlight the button when it represents the current page\n * or active selection. This helps users understand their navigation context.\n */\n @Prop({ reflect: true })\n readonly active: boolean = false;\n\n /**\n * Applies styling that visually indicates the button represents a dangerous\n * action.\n */\n @Prop({ reflect: true })\n readonly danger: boolean = false;\n\n /**\n * Set this to true to show a spinner on the button, letting users know that\n * their action is being processed. It helps improve user experience by\n * indicating ongoing activities.\n */\n @Prop({ reflect: true, mutable: true })\n loading: boolean = false;\n\n /**\n * Disables the button, preventing user interaction.\n */\n @Prop({ reflect: true, mutable: true })\n disabled: boolean = false;\n\n /**\n * Allows the button to stretch and fill the entire width of its container.\n */\n @Prop({ reflect: true })\n readonly fluid: boolean = false;\n\n /**\n * Sets the button type to control its function in forms. Use 'submit' to send\n * form data, 'reset' to clear the form, or 'button' for a standard button\n * that doesn't interact with form submission by default.\n */\n @Prop({ reflect: true })\n readonly type: `${ButtonType}` = 'button';\n\n /**\n * Sets the form associated with the button in case the (submit) button is not a child of a form.\n * Matches the native HTML button 'form' attribute behavior.\n */\n @Prop({ reflect: true })\n readonly form: string;\n\n //#endregion PROPERTIES\n /****************************************************************************/\n //#region METHODS\n\n /**\n * Handles button click events, managing form actions and disabled states.\n * Prevents default behavior when button is disabled or loading, and\n * processes form submissions/resets when appropriate.\n * @param {Event} event - The click event.\n */\n private handleButtonClick = (event: Event): void => {\n if (this.loading || this.disabled) {\n event.preventDefault();\n return;\n }\n\n if (\n this.type !== ButtonType.Button &&\n (this.form || this.internals?.form)\n ) {\n this.processFormAction();\n } else if (this.form && this.type === ButtonType.Button) {\n console.warn(\n 'Button has a form id but is not of type submit or reset so no form action will be processed.',\n `Button:`,\n this.el,\n );\n }\n };\n\n /**\n * Processes form-related actions by finding the associated form element\n * and triggering the appropriate action (submit/reset) based on button type.\n * Falls back to ElementInternals form if no explicit form ID is provided.\n */\n private processFormAction = (): void => {\n const formElement = this.form\n ? (document.getElementById(this.form) as HTMLFormElement)\n : this.internals?.form;\n\n if (!formElement) {\n console.warn(\n 'No form element found.',\n `Form ID: ${this.form || 'Not provided'}`,\n `Internals form:`,\n this.internals?.form,\n );\n return;\n }\n\n switch (this.type) {\n case ButtonType.Submit:\n formElement.requestSubmit();\n break;\n case ButtonType.Reset:\n formElement.reset();\n break;\n }\n };\n\n //#endregion METHODS\n /****************************************************************************/\n //#region EVENTS\n\n @Listen('keydown', { passive: false })\n handleKeyDown(event: KeyboardEvent) {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.el.click();\n }\n }\n\n @Listen('touchstart', { passive: false })\n handleTouchStart(event: TouchEvent) {\n if (event.touches.length > 1) return;\n event.preventDefault();\n this.el.click();\n }\n\n //#endregion EVENTS\n /****************************************************************************/\n //#region WATCHERS\n\n @Watch('loading')\n handleLoadingChange(loading: boolean) {\n this.loading = loading;\n this.disabled = loading;\n }\n\n @Watch('disabled')\n handleDisabledChange(disabled: boolean) {\n if (this.loading) {\n this.disabled = this.loading;\n } else {\n this.disabled = disabled;\n }\n }\n\n //#endregion WATCHERS\n /****************************************************************************/\n //#region LIFECYCLE\n\n componentWillLoad() {\n if (this.loading) {\n this.disabled = this.loading;\n }\n }\n\n //#endregion LIFECYCLE\n /****************************************************************************/\n //#region RENDER\n\n render() {\n return (\n <Host role=\"button\" tabindex=\"0\" onClick={this.handleButtonClick}>\n {this.loading && (\n <nv-loader\n size={this.size === ButtonSize.Large ? 'sm' : 'xs'}\n ></nv-loader>\n )}\n\n <slot name=\"leading-icon\"></slot>\n <slot></slot>\n <slot name=\"trailing-icon\"></slot>\n </Host>\n );\n }\n\n //#endregion RENDER\n}\n"],"version":3}
@@ -1 +0,0 @@
1
- {"version":3,"names":["nvButtonCss","NvButtonStyle0","NvButton","constructor","hostRef","this","size","emphasis","active","danger","loading","disabled","fluid","type","handleButtonClick","event","preventDefault","ButtonType","Button","form","_a","internals","processFormAction","console","warn","el","formElement","document","getElementById","_b","Submit","requestSubmit","Reset","reset","handleKeyDown","key","click","handleTouchStart","touches","length","handleLoadingChange","handleDisabledChange","componentWillLoad","render","h","Host","role","tabindex","onClick","ButtonSize","Large","name"],"sources":["src/components/nv-button/styles/nv-button.scss?tag=nv-button","src/components/nv-button/nv-button.tsx"],"sourcesContent":["@use \"./mixins\" as *;\n\n// Make sure to update nv-button class in the tailwind-components.scss file when\n// you add new styles or change the structure here.\nnv-button {\n @include root-styles();\n\n @each $size in $sizes {\n &[size=\"#{$size}\"] {\n @include size-styles($size);\n }\n }\n\n @each $emphasis in $emphases {\n &[emphasis=\"#{$emphasis}\"] {\n @include emphasis-styles($emphasis);\n\n &[active]:not([active=\"false\"]) {\n @include active-styles($emphasis);\n }\n\n &[danger]:not([danger=\"false\"]) {\n @include danger-styles($emphasis);\n }\n }\n }\n\n &[fluid]:not([fluid=\"false\"]) {\n @include fluid-styles();\n }\n\n &[loading]:not([loading=\"false\"]) {\n [slot=\"leading-icon\"] {\n display: none;\n }\n }\n}\n","import {\n Component,\n Listen,\n Host,\n h,\n Prop,\n AttachInternals,\n Element,\n Watch,\n} from '@stencil/core';\n\nimport { ButtonSize, ButtonEmphasis, ButtonType } from '../../utils/constants';\n\n/**\n * @slot default - Content of the button.\n * @slot leading-icon - Icon before the label.\n * @slot trailing-icon - Icon after the label.\n */\n@Component({\n tag: 'nv-button',\n shadow: false,\n formAssociated: true,\n styleUrl: 'styles/nv-button.scss',\n})\nexport class NvButton {\n @AttachInternals() internals: ElementInternals;\n @Element() el: HTMLNvButtonElement;\n\n /****************************************************************************/\n //#region PROPERTIES\n\n /**\n * Determines how large or small the button appears, allowing for\n * customization of the button's dimensions to fit different design\n * specifications and user needs.\n */\n @Prop({ reflect: true })\n readonly size: `${ButtonSize}` = 'md';\n\n /**\n * Adjusts the button's emphasis to make it more or less visually prominent\n * to users. Use this to draw attention to important actions or reduce focus\n * on less critical ones\n */\n @Prop({ reflect: true })\n readonly emphasis: `${ButtonEmphasis}` = 'high';\n\n /**\n * Use this prop to highlight the button when it represents the current page\n * or active selection. This helps users understand their navigation context.\n */\n @Prop({ reflect: true })\n readonly active: boolean = false;\n\n /**\n * Applies styling that visually indicates the button represents a dangerous\n * action.\n */\n @Prop({ reflect: true })\n readonly danger: boolean = false;\n\n /**\n * Set this to true to show a spinner on the button, letting users know that\n * their action is being processed. It helps improve user experience by\n * indicating ongoing activities.\n */\n @Prop({ reflect: true, mutable: true })\n loading: boolean = false;\n\n /**\n * Disables the button, preventing user interaction.\n */\n @Prop({ reflect: true, mutable: true })\n disabled: boolean = false;\n\n /**\n * Allows the button to stretch and fill the entire width of its container.\n */\n @Prop({ reflect: true })\n readonly fluid: boolean = false;\n\n /**\n * Sets the button type to control its function in forms. Use 'submit' to send\n * form data, 'reset' to clear the form, or 'button' for a standard button\n * that doesn't interact with form submission by default.\n */\n @Prop({ reflect: true })\n readonly type: `${ButtonType}` = 'button';\n\n /**\n * Sets the form associated with the button in case the (submit) button is not a child of a form.\n * Matches the native HTML button 'form' attribute behavior.\n */\n @Prop({ reflect: true })\n readonly form: string;\n\n //#endregion PROPERTIES\n /****************************************************************************/\n //#region METHODS\n\n /**\n * Handles button click events, managing form actions and disabled states.\n * Prevents default behavior when button is disabled or loading, and\n * processes form submissions/resets when appropriate.\n * @param {Event} event - The click event.\n */\n private handleButtonClick = (event: Event): void => {\n if (this.loading || this.disabled) {\n event.preventDefault();\n return;\n }\n\n if (\n this.type !== ButtonType.Button &&\n (this.form || this.internals?.form)\n ) {\n this.processFormAction();\n } else if (this.form && this.type === ButtonType.Button) {\n console.warn(\n 'Button has a form id but is not of type submit or reset so no form action will be processed.',\n `Button:`,\n this.el,\n );\n }\n };\n\n /**\n * Processes form-related actions by finding the associated form element\n * and triggering the appropriate action (submit/reset) based on button type.\n * Falls back to ElementInternals form if no explicit form ID is provided.\n */\n private processFormAction = (): void => {\n const formElement = this.form\n ? (document.getElementById(this.form) as HTMLFormElement)\n : this.internals?.form;\n\n if (!formElement) {\n console.warn(\n 'No form element found.',\n `Form ID: ${this.form || 'Not provided'}`,\n `Internals form:`,\n this.internals?.form,\n );\n return;\n }\n\n switch (this.type) {\n case ButtonType.Submit:\n formElement.requestSubmit();\n break;\n case ButtonType.Reset:\n formElement.reset();\n break;\n }\n };\n\n //#endregion METHODS\n /****************************************************************************/\n //#region EVENTS\n\n @Listen('keydown', { passive: false })\n handleKeyDown(event: KeyboardEvent) {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.el.click();\n }\n }\n\n @Listen('touchstart', { passive: false })\n handleTouchStart(event: TouchEvent) {\n if (event.touches.length > 1) return;\n event.preventDefault();\n this.el.click();\n }\n\n //#endregion EVENTS\n /****************************************************************************/\n //#region WATCHERS\n\n @Watch('loading')\n handleLoadingChange(loading: boolean) {\n this.loading = loading;\n this.disabled = loading;\n }\n\n @Watch('disabled')\n handleDisabledChange(disabled: boolean) {\n if (this.loading) {\n this.disabled = this.loading;\n } else {\n this.disabled = disabled;\n }\n }\n\n //#endregion WATCHERS\n /****************************************************************************/\n //#region LIFECYCLE\n\n componentWillLoad() {\n if (this.loading) {\n this.disabled = this.loading;\n }\n }\n\n //#endregion LIFECYCLE\n /****************************************************************************/\n //#region RENDER\n\n render() {\n return (\n <Host role=\"button\" tabindex=\"0\" onClick={this.handleButtonClick}>\n {this.loading && (\n <nv-loader\n size={this.size === ButtonSize.Large ? 'sm' : 'xs'}\n ></nv-loader>\n )}\n\n <slot name=\"leading-icon\"></slot>\n <slot></slot>\n <slot name=\"trailing-icon\"></slot>\n </Host>\n );\n }\n\n //#endregion RENDER\n}\n"],"mappings":"oGAAA,MAAMA,EAAc,i4TACpB,MAAAC,EAAeD,E,MCuBFE,EAAQ,MANrB,WAAAC,CAAAC,G,0KAmBWC,KAAAC,KAAwB,KAQxBD,KAAAE,SAAgC,OAOhCF,KAAAG,OAAkB,MAOlBH,KAAAI,OAAkB,MAQ3BJ,KAAAK,QAAmB,MAMnBL,KAAAM,SAAoB,MAMXN,KAAAO,MAAiB,MAQjBP,KAAAQ,KAAwB,SAmBzBR,KAAAS,kBAAqBC,I,MAC3B,GAAIV,KAAKK,SAAWL,KAAKM,SAAU,CACjCI,EAAMC,iBACN,M,CAGF,GACEX,KAAKQ,OAASI,EAAWC,SACxBb,KAAKc,QAAQC,EAAAf,KAAKgB,aAAS,MAAAD,SAAA,SAAAA,EAAED,OAC9B,CACAd,KAAKiB,mB,MACA,GAAIjB,KAAKc,MAAQd,KAAKQ,OAASI,EAAWC,OAAQ,CACvDK,QAAQC,KACN,+FACA,UACAnB,KAAKoB,G,GAUHpB,KAAAiB,kBAAoB,K,QAC1B,MAAMI,EAAcrB,KAAKc,KACpBQ,SAASC,eAAevB,KAAKc,OAC9BC,EAAAf,KAAKgB,aAAS,MAAAD,SAAA,SAAAA,EAAED,KAEpB,IAAKO,EAAa,CAChBH,QAAQC,KACN,yBACA,YAAYnB,KAAKc,MAAQ,iBACzB,mBACAU,EAAAxB,KAAKgB,aAAS,MAAAQ,SAAA,SAAAA,EAAEV,MAElB,M,CAGF,OAAQd,KAAKQ,MACX,KAAKI,EAAWa,OACdJ,EAAYK,gBACZ,MACF,KAAKd,EAAWe,MACdN,EAAYO,QACZ,M,EASN,aAAAC,CAAcnB,GACZ,GAAIA,EAAMoB,MAAQ,SAAWpB,EAAMoB,MAAQ,IAAK,CAC9CpB,EAAMC,iBACNX,KAAKoB,GAAGW,O,EAKZ,gBAAAC,CAAiBtB,GACf,GAAIA,EAAMuB,QAAQC,OAAS,EAAG,OAC9BxB,EAAMC,iBACNX,KAAKoB,GAAGW,O,CAQV,mBAAAI,CAAoB9B,GAClBL,KAAKK,QAAUA,EACfL,KAAKM,SAAWD,C,CAIlB,oBAAA+B,CAAqB9B,GACnB,GAAIN,KAAKK,QAAS,CAChBL,KAAKM,SAAWN,KAAKK,O,KAChB,CACLL,KAAKM,SAAWA,C,EAQpB,iBAAA+B,GACE,GAAIrC,KAAKK,QAAS,CAChBL,KAAKM,SAAWN,KAAKK,O,EAQzB,MAAAiC,GACE,OACEC,EAACC,EAAI,CAAAV,IAAA,2CAACW,KAAK,SAASC,SAAS,IAAIC,QAAS3C,KAAKS,mBAC5CT,KAAKK,SACJkC,EAAA,aAAAT,IAAA,2CACE7B,KAAMD,KAAKC,OAAS2C,EAAWC,MAAQ,KAAO,OAIlDN,EAAA,QAAAT,IAAA,2CAAMgB,KAAK,iBACXP,EAAA,QAAAT,IAAA,6CACAS,EAAA,QAAAT,IAAA,2CAAMgB,KAAK,kB","ignoreList":[]}