@nvidia-elements/core 2.16.0 → 2.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 (126) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/accordion/accordion2.js +4 -4
  3. package/dist/alert/alert-group2.js +1 -1
  4. package/dist/alert/alert2.js +1 -1
  5. package/dist/avatar/avatar-group2.js +1 -1
  6. package/dist/avatar/avatar2.js +1 -1
  7. package/dist/badge/badge2.js +1 -1
  8. package/dist/breadcrumb/breadcrumb2.js +1 -1
  9. package/dist/bundles/index.d.ts +5 -0
  10. package/dist/bundles/index.js +7 -7
  11. package/dist/button/button2.js +1 -1
  12. package/dist/button-group/button-group2.js +1 -1
  13. package/dist/card/card2.js +4 -4
  14. package/dist/chat-message/chat-message2.js +1 -1
  15. package/dist/checkbox/checkbox-group2.js +1 -1
  16. package/dist/checkbox/checkbox2.js +1 -1
  17. package/dist/color/color2.js +1 -1
  18. package/dist/combobox/combobox2.js +1 -1
  19. package/dist/copy-button/copy-button2.js +1 -1
  20. package/dist/custom-elements-jsx.d.ts +3 -0
  21. package/dist/custom-elements-vue.d.ts +3 -0
  22. package/dist/custom-elements.json +99 -55
  23. package/dist/data.html.json +5 -0
  24. package/dist/date/date2.js +1 -1
  25. package/dist/datetime/datetime2.js +1 -1
  26. package/dist/dialog/dialog-footer2.js +1 -1
  27. package/dist/dialog/dialog-header2.js +1 -1
  28. package/dist/dialog/dialog2.js +1 -1
  29. package/dist/divider/divider2.js +1 -1
  30. package/dist/dot/dot2.js +1 -1
  31. package/dist/drag-handle/drag-handle2.js +1 -1
  32. package/dist/drawer/drawer-content2.js +1 -1
  33. package/dist/drawer/drawer-footer2.js +1 -1
  34. package/dist/drawer/drawer-header2.js +1 -1
  35. package/dist/drawer/drawer2.js +1 -1
  36. package/dist/dropdown/dropdown-footer2.js +1 -1
  37. package/dist/dropdown/dropdown-header2.js +1 -1
  38. package/dist/dropdown/dropdown2.js +1 -1
  39. package/dist/dropdown-group/dropdown-group.js +1 -1
  40. package/dist/dropzone/dropzone2.js +1 -1
  41. package/dist/file/file2.js +1 -1
  42. package/dist/format-bytes/format-bytes2.js +1 -1
  43. package/dist/format-datetime/format-datetime2.js +1 -1
  44. package/dist/format-number/format-number2.js +1 -1
  45. package/dist/format-relative-time/format-relative-time2.js +1 -1
  46. package/dist/format-truncate/format-truncate2.js +1 -1
  47. package/dist/forms/control/control2.js +1 -1
  48. package/dist/forms/control-group/control-group2.js +1 -1
  49. package/dist/forms/control-message/control-message2.js +1 -1
  50. package/dist/gauge/gauge2.js +1 -1
  51. package/dist/grid/cell/cell2.js +1 -1
  52. package/dist/grid/column/column2.js +1 -1
  53. package/dist/grid/footer/footer2.js +1 -1
  54. package/dist/grid/grid2.js +1 -1
  55. package/dist/grid/header/header2.js +1 -1
  56. package/dist/grid/placeholder/placeholder2.js +1 -1
  57. package/dist/grid/row/row2.js +1 -1
  58. package/dist/icon/icon2.js +2 -2
  59. package/dist/icon-button/icon-button.d.ts +5 -0
  60. package/dist/icon-button/icon-button2.js +3 -3
  61. package/dist/icon-button/icon-button2.js.map +1 -1
  62. package/dist/iframe/iframe2.js +1 -1
  63. package/dist/index.js +1 -1
  64. package/dist/input/input-group2.js +1 -1
  65. package/dist/input/input2.js +1 -1
  66. package/dist/internal/controllers/keynav-grid.controller.js +93 -62
  67. package/dist/internal/controllers/keynav-grid.controller.js.map +1 -1
  68. package/dist/internal/services/global.service.js +1 -1
  69. package/dist/internal/utils/events.d.ts +6 -1
  70. package/dist/internal/utils/events.js +22 -4
  71. package/dist/internal/utils/events.js.map +1 -1
  72. package/dist/logo/logo2.js +1 -1
  73. package/dist/menu/menu-group2.js +1 -1
  74. package/dist/menu/menu-item2.js +1 -1
  75. package/dist/menu/menu2.js +1 -1
  76. package/dist/month/month2.js +1 -1
  77. package/dist/notification/notification-group2.js +1 -1
  78. package/dist/notification/notification2.js +1 -1
  79. package/dist/page/page-panel/page-panel-content2.js +1 -1
  80. package/dist/page/page-panel/page-panel-footer2.js +1 -1
  81. package/dist/page/page-panel/page-panel-header2.js +1 -1
  82. package/dist/page/page-panel/page-panel2.js +1 -1
  83. package/dist/page/page2.js +1 -1
  84. package/dist/page-header/page-header2.js +1 -1
  85. package/dist/page-loader/page-loader2.js +1 -1
  86. package/dist/pagination/pagination2.js +1 -1
  87. package/dist/panel/panel2.js +4 -4
  88. package/dist/password/password2.js +1 -1
  89. package/dist/preferences-input/preferences-input2.js +1 -1
  90. package/dist/progress-bar/progress-bar2.js +1 -1
  91. package/dist/progress-dot/progress-dot2.js +1 -1
  92. package/dist/progress-ring/progress-ring2.js +1 -1
  93. package/dist/progressive-filter-chip/progressive-filter-chip2.js +1 -1
  94. package/dist/pulse/pulse2.js +1 -1
  95. package/dist/radio/radio-group2.js +1 -1
  96. package/dist/radio/radio2.js +1 -1
  97. package/dist/range/range2.js +1 -1
  98. package/dist/resize-handle/resize-handle2.js +1 -1
  99. package/dist/search/search2.js +1 -1
  100. package/dist/select/select2.js +1 -1
  101. package/dist/skeleton/skeleton2.js +1 -1
  102. package/dist/sort-button/sort-button2.js +1 -1
  103. package/dist/sparkline/sparkline2.js +1 -1
  104. package/dist/star-rating/star-rating2.js +1 -1
  105. package/dist/steps/steps2.js +2 -2
  106. package/dist/switch/switch-group2.js +1 -1
  107. package/dist/switch/switch2.js +1 -1
  108. package/dist/tabs/tabs-group2.js +1 -1
  109. package/dist/tabs/tabs2.js +2 -2
  110. package/dist/tag/tag2.js +1 -1
  111. package/dist/textarea/textarea2.js +1 -1
  112. package/dist/time/time2.js +1 -1
  113. package/dist/toast/toast2.js +1 -1
  114. package/dist/toggletip/toggletip-footer2.js +1 -1
  115. package/dist/toggletip/toggletip-header.js +1 -1
  116. package/dist/toggletip/toggletip-header.js.map +1 -1
  117. package/dist/toggletip/toggletip-header2.js +1 -1
  118. package/dist/toggletip/toggletip.examples.js.map +1 -1
  119. package/dist/toggletip/toggletip.examples.json +1 -1
  120. package/dist/toggletip/toggletip2.js +1 -1
  121. package/dist/toolbar/toolbar2.js +1 -1
  122. package/dist/tooltip/tooltip2.js +1 -1
  123. package/dist/tree/tree-node2.js +1 -1
  124. package/dist/tree/tree2.js +1 -1
  125. package/dist/week/week2.js +1 -1
  126. package/package.json +1 -1
@@ -29,7 +29,7 @@ var c = [
29
29
  static {
30
30
  this.metadata = {
31
31
  tag: "nve-format-number",
32
- version: "2.16.0"
32
+ version: "2.17.0"
33
33
  };
34
34
  }
35
35
  get #e() {
@@ -53,7 +53,7 @@ var c = {
53
53
  static {
54
54
  this.metadata = {
55
55
  tag: "nve-format-relative-time",
56
- version: "2.16.0"
56
+ version: "2.17.0"
57
57
  };
58
58
  }
59
59
  #e;
@@ -19,7 +19,7 @@ var d = class extends c {
19
19
  static {
20
20
  this.metadata = {
21
21
  tag: "nve-format-truncate",
22
- version: "2.16.0"
22
+ version: "2.17.0"
23
23
  };
24
24
  }
25
25
  #e;
@@ -48,7 +48,7 @@ var C = class extends v {
48
48
  static {
49
49
  this.metadata = {
50
50
  tag: "nve-control",
51
- version: "2.16.0"
51
+ version: "2.17.0"
52
52
  };
53
53
  }
54
54
  render() {
@@ -24,7 +24,7 @@ var m = class extends d {
24
24
  static {
25
25
  this.metadata = {
26
26
  tag: "nve-control-group",
27
- version: "2.16.0"
27
+ version: "2.17.0"
28
28
  };
29
29
  }
30
30
  render() {
@@ -23,7 +23,7 @@ var l = {
23
23
  static {
24
24
  this.metadata = {
25
25
  tag: "nve-control-message",
26
- version: "2.16.0"
26
+ version: "2.17.0"
27
27
  };
28
28
  }
29
29
  static {
@@ -40,7 +40,7 @@ var l = {
40
40
  static {
41
41
  this.metadata = {
42
42
  tag: "nve-gauge",
43
- version: "2.16.0"
43
+ version: "2.17.0"
44
44
  };
45
45
  }
46
46
  #e;
@@ -10,7 +10,7 @@ var a = class extends r {
10
10
  static {
11
11
  this.metadata = {
12
12
  tag: "nve-grid-cell",
13
- version: "2.16.0"
13
+ version: "2.17.0"
14
14
  };
15
15
  }
16
16
  render() {
@@ -13,7 +13,7 @@ var c = class r extends a {
13
13
  static {
14
14
  this.metadata = {
15
15
  tag: "nve-grid-column",
16
- version: "2.16.0"
16
+ version: "2.17.0"
17
17
  };
18
18
  }
19
19
  get #e() {
@@ -15,7 +15,7 @@ var s = class extends a {
15
15
  static {
16
16
  this.metadata = {
17
17
  tag: "nve-grid-footer",
18
- version: "2.16.0"
18
+ version: "2.17.0"
19
19
  };
20
20
  }
21
21
  static {
@@ -23,7 +23,7 @@ var y = class extends g {
23
23
  static {
24
24
  this.metadata = {
25
25
  tag: "nve-grid",
26
- version: "2.16.0",
26
+ version: "2.17.0",
27
27
  children: [
28
28
  d.metadata.tag,
29
29
  f.metadata.tag,
@@ -19,7 +19,7 @@ var m = class extends d {
19
19
  static {
20
20
  this.metadata = {
21
21
  tag: "nve-grid-header",
22
- version: "2.16.0",
22
+ version: "2.17.0",
23
23
  children: [c.metadata.tag]
24
24
  };
25
25
  }
@@ -10,7 +10,7 @@ var a = class extends r {
10
10
  static {
11
11
  this.metadata = {
12
12
  tag: "nve-grid-placeholder",
13
- version: "2.16.0"
13
+ version: "2.17.0"
14
14
  };
15
15
  }
16
16
  render() {
@@ -15,7 +15,7 @@ var u = class extends s {
15
15
  static {
16
16
  this.metadata = {
17
17
  tag: "nve-grid-row",
18
- version: "2.16.0",
18
+ version: "2.17.0",
19
19
  children: [a.metadata.tag]
20
20
  };
21
21
  }
@@ -16,7 +16,7 @@ var f = class e extends o {
16
16
  static {
17
17
  this.metadata = {
18
18
  tag: "nve-icon",
19
- version: "2.16.0"
19
+ version: "2.17.0"
20
20
  };
21
21
  }
22
22
  static {
@@ -103,7 +103,7 @@ a([l({
103
103
  })], f.prototype, "name", void 0), a([d()], f.prototype, "svg", void 0);
104
104
  function p(t) {
105
105
  if (typeof globalThis.customElements?.get == "function") {
106
- let n = e(t.metadata.version), i = e("2.16.0");
106
+ let n = e(t.metadata.version), i = e("2.17.0");
107
107
  n.minor <= i.minor && n.major <= i.major && (t._icons = {
108
108
  ...t._icons,
109
109
  ...r
@@ -35,6 +35,11 @@ export declare class IconButton extends Button {
35
35
  * Sets size of the icon button.
36
36
  */
37
37
  size?: Size;
38
+ /**
39
+ * Selects the outline or solid form of the named icon. Solid icons use an optional `-solid` asset and fall back to
40
+ * the outline form when that asset is unavailable.
41
+ */
42
+ appearance?: 'outline' | 'solid';
38
43
  static styles: import("lit").CSSResult[];
39
44
  static readonly metadata: {
40
45
  tag: string;
@@ -15,14 +15,14 @@ var l = class extends a {
15
15
  static {
16
16
  this.metadata = {
17
17
  tag: "nve-icon-button",
18
- version: "2.16.0"
18
+ version: "2.17.0"
19
19
  };
20
20
  }
21
21
  static {
22
22
  this.elementDefinitions = { [i.metadata.tag]: i };
23
23
  }
24
24
  render() {
25
- return s`<div internal-host interaction-state focus-within aria-hidden="true"><slot @slotchange="${(t) => e(t.target)}"><nve-icon .name="${this.iconName}" .direction="${this.direction}" .size="${this.size}" aria-hidden="true" part="icon"></nve-icon></slot></div><slot name="anchor"></slot>`;
25
+ return s`<div internal-host interaction-state focus-within aria-hidden="true"><slot @slotchange="${(t) => e(t.target)}"><nve-icon .name="${this.iconName}" .appearance="${this.appearance}" .direction="${this.direction}" .size="${this.size}" aria-hidden="true" part="icon"></nve-icon></slot></div><slot name="anchor"></slot>`;
26
26
  }
27
27
  };
28
28
  r([c({
@@ -34,7 +34,7 @@ r([c({
34
34
  })], l.prototype, "direction", void 0), r([c({
35
35
  type: String,
36
36
  reflect: !0
37
- })], l.prototype, "size", void 0), l = r([t()], l);
37
+ })], l.prototype, "size", void 0), r([c({ type: String })], l.prototype, "appearance", void 0), l = r([t()], l);
38
38
  //#endregion
39
39
  export { l as IconButton };
40
40
 
@@ -1 +1 @@
1
- {"version":3,"file":"icon-button2.js","names":[],"sources":["../../src/icon-button/icon-button.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { html } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport type { Size } from '@nvidia-elements/core/internal';\nimport { removeEmptySlotWhitespace, scopedRegistry, useStyles } from '@nvidia-elements/core/internal';\nimport { Button } from '@nvidia-elements/core/button';\nimport type { IconName } from '@nvidia-elements/core/icon';\nimport { Icon } from '@nvidia-elements/core/icon';\nimport styles from './icon-button.css?inline';\n\n/**\n * @element nve-icon-button\n * @description An icon button is a button that displays only an icon without a visual label.\n * @documentation https://nvidia.github.io/elements/docs/elements/icon-button/\n * @since 0.2.1\n * @entrypoint \\@nvidia-elements/core/icon-button\n * @slot - default slot for custom icons\n * @cssprop --border-radius\n * @cssprop --padding\n * @cssprop --line-height\n * @cssprop --gap\n * @cssprop --height\n * @cssprop --width\n * @cssprop --font-size\n * @cssprop --color\n * @cssprop --background\n * @csspart icon - The icon element\n * @aria https://www.w3.org/WAI/ARIA/apg/patterns/button/\n */\n@scopedRegistry()\nexport class IconButton extends Button {\n /**\n * Sets the icon name, which determines which icon to display.\n */\n @property({ type: String, attribute: 'icon-name' }) iconName: IconName;\n\n /**\n * Sets the direction of the icon.\n * Only supported by expand-panel/collapse-panel (horizontal axis) and arrow/caret/chevron icons (4-directions)\n */\n @property({ type: String, reflect: true }) direction: 'up' | 'down' | 'left' | 'right';\n\n /**\n * Sets size of the icon button.\n */\n @property({ type: String, reflect: true }) size?: Size;\n\n static styles = useStyles([...Button.styles, styles]);\n\n static readonly metadata = {\n tag: 'nve-icon-button',\n version: '0.0.0'\n };\n\n static elementDefinitions = {\n [Icon.metadata.tag]: Icon\n };\n\n render() {\n return html`\n <div internal-host interaction-state focus-within aria-hidden=\"true\">\n <slot @slotchange=${(e: Event) => removeEmptySlotWhitespace(e.target as HTMLSlotElement)}>\n <nve-icon .name=${this.iconName} .direction=${this.direction} .size=${this.size} aria-hidden=\"true\" part=\"icon\"></nve-icon>\n </slot>\n </div>\n <slot name=\"anchor\"></slot>\n `;\n }\n}\n"],"mappings":";;;;;;;;;;AAgCO,IAAM,IAAN,cAAyB,EAAO;;EAiBrB,KAAA,SAAA,EAAU,CAAC,GAAG,EAAO,QAAQ,CAAM,CAAC;;;EAEzB,KAAA,WAAA;GACzB,KAAK;GACL,SAAS;EACX;;;EAE4B,KAAA,qBAAA,GACzB,EAAK,SAAS,MAAM,EACvB;;CAEA,SAAS;EACP,OAAO,CAAI,4FAEc,MAAa,EAA0B,EAAE,MAAyB,EAAE,qBACrE,KAAK,SAAS,gBAAc,KAAK,UAAU,WAAS,KAAK,KAAK;CAKxF;AACF;AAlCG,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,WAAW;AAAY,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GAMjD,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,aAAA,KAAA,CAAA,GAKxC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,GAhB1C,IAAA,EAAA,CAAA,EAAe,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"icon-button2.js","names":[],"sources":["../../src/icon-button/icon-button.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { html } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport type { Size } from '@nvidia-elements/core/internal';\nimport { removeEmptySlotWhitespace, scopedRegistry, useStyles } from '@nvidia-elements/core/internal';\nimport { Button } from '@nvidia-elements/core/button';\nimport type { IconName } from '@nvidia-elements/core/icon';\nimport { Icon } from '@nvidia-elements/core/icon';\nimport styles from './icon-button.css?inline';\n\n/**\n * @element nve-icon-button\n * @description An icon button is a button that displays only an icon without a visual label.\n * @documentation https://nvidia.github.io/elements/docs/elements/icon-button/\n * @since 0.2.1\n * @entrypoint \\@nvidia-elements/core/icon-button\n * @slot - default slot for custom icons\n * @cssprop --border-radius\n * @cssprop --padding\n * @cssprop --line-height\n * @cssprop --gap\n * @cssprop --height\n * @cssprop --width\n * @cssprop --font-size\n * @cssprop --color\n * @cssprop --background\n * @csspart icon - The icon element\n * @aria https://www.w3.org/WAI/ARIA/apg/patterns/button/\n */\n@scopedRegistry()\nexport class IconButton extends Button {\n /**\n * Sets the icon name, which determines which icon to display.\n */\n @property({ type: String, attribute: 'icon-name' }) iconName: IconName;\n\n /**\n * Sets the direction of the icon.\n * Only supported by expand-panel/collapse-panel (horizontal axis) and arrow/caret/chevron icons (4-directions)\n */\n @property({ type: String, reflect: true }) direction: 'up' | 'down' | 'left' | 'right';\n\n /**\n * Sets size of the icon button.\n */\n @property({ type: String, reflect: true }) size?: Size;\n\n /**\n * Selects the outline or solid form of the named icon. Solid icons use an optional `-solid` asset and fall back to\n * the outline form when that asset is unavailable.\n */\n @property({ type: String }) appearance?: 'outline' | 'solid';\n\n static styles = useStyles([...Button.styles, styles]);\n\n static readonly metadata = {\n tag: 'nve-icon-button',\n version: '0.0.0'\n };\n\n static elementDefinitions = {\n [Icon.metadata.tag]: Icon\n };\n\n render() {\n return html`\n <div internal-host interaction-state focus-within aria-hidden=\"true\">\n <slot @slotchange=${(e: Event) => removeEmptySlotWhitespace(e.target as HTMLSlotElement)}>\n <nve-icon .name=${this.iconName} .appearance=${this.appearance} .direction=${this.direction} .size=${this.size} aria-hidden=\"true\" part=\"icon\"></nve-icon>\n </slot>\n </div>\n <slot name=\"anchor\"></slot>\n `;\n }\n}\n"],"mappings":";;;;;;;;;;AAgCO,IAAM,IAAN,cAAyB,EAAO;;EAuBrB,KAAA,SAAA,EAAU,CAAC,GAAG,EAAO,QAAQ,CAAM,CAAC;;;EAEzB,KAAA,WAAA;GACzB,KAAK;GACL,SAAS;EACX;;;EAE4B,KAAA,qBAAA,GACzB,EAAK,SAAS,MAAM,EACvB;;CAEA,SAAS;EACP,OAAO,CAAI,4FAEc,MAAa,EAA0B,EAAE,MAAyB,EAAE,qBACrE,KAAK,SAAS,iBAAe,KAAK,WAAW,gBAAc,KAAK,UAAU,WAAS,KAAK,KAAK;CAKvH;AACF;AAxCG,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,WAAW;AAAY,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GAMjD,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,aAAA,KAAA,CAAA,GAKxC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,GAMxC,EAAA,CAAA,EAAS,EAAE,MAAM,OAAO,CAAC,CAAA,GAAA,EAAA,WAAA,cAAA,KAAA,CAAA,GAtB3B,IAAA,EAAA,CAAA,EAAe,CAAA,GAAA,CAAA"}
@@ -61,7 +61,7 @@ var a = (e) => `
61
61
  static {
62
62
  this.metadata = {
63
63
  tag: "nve-iframe",
64
- version: "2.16.0"
64
+ version: "2.17.0"
65
65
  };
66
66
  }
67
67
  static get observedAttributes() {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { I18nService as e } from "./internal/services/i18n.service.js";
2
2
  import { getThemeTokens as t } from "./internal/utils/dom.js";
3
3
  import { statusIcons as n } from "./internal/types/index.js";
4
4
  //#region src/index.ts
5
- var r = "2.16.0", i = "@nvidia-elements";
5
+ var r = "2.17.0", i = "@nvidia-elements";
6
6
  //#endregion
7
7
  export { e as I18nService, i as SCOPE, r as VERSION, t as getThemeTokens, n as statusIcons };
8
8
 
@@ -11,7 +11,7 @@ var a = class extends n {
11
11
  static {
12
12
  this.metadata = {
13
13
  tag: "nve-input-group",
14
- version: "2.16.0"
14
+ version: "2.17.0"
15
15
  };
16
16
  }
17
17
  async connectedCallback() {
@@ -14,7 +14,7 @@ var a = r, o = class extends n {
14
14
  static {
15
15
  this.metadata = {
16
16
  tag: "nve-input",
17
- version: "2.16.0"
17
+ version: "2.17.0"
18
18
  };
19
19
  }
20
20
  };
@@ -1,63 +1,95 @@
1
1
  import { GlobalStateService as e } from "../services/global.service.js";
2
- import { onChildListMutation as t, throttle as n } from "../utils/events.js";
3
- import { LogService as r } from "../services/log.service.js";
4
- import { focusElement as i, getActiveElement as a, initializeKeyListItems as o, isSimpleFocusable as s, setActiveKeyListItem as c } from "../utils/focus.js";
5
- import { KeynavCode as l, getFlattenedDOMTree as u, getFlattenedFocusableItems as d, hasInvalidDOMGrid as f, isContextMenuClick as p, validKeyNavigationCode as m } from "../utils/dom.js";
2
+ import { throttle as t } from "../utils/events.js";
3
+ import { LogService as n } from "../services/log.service.js";
4
+ import { focusElement as r, getActiveElement as i, isSimpleFocusable as a, setActiveKeyListItem as o } from "../utils/focus.js";
5
+ import { KeynavCode as s, getFlattenedDOMTree as c, getFlattenedFocusableItems as l, hasInvalidDOMGrid as u, isContextMenuClick as d, validKeyNavigationCode as f } from "../utils/dom.js";
6
6
  //#region src/internal/controllers/keynav-grid.controller.ts
7
- function h() {
8
- return (e) => e.addInitializer((e) => new g(e));
7
+ function p() {
8
+ return (e) => e.addInitializer((e) => new m(e));
9
9
  }
10
- var g = class {
11
- #e = [];
10
+ var m = class {
11
+ #e;
12
12
  #t;
13
- get #n() {
13
+ #n;
14
+ #r = /* @__PURE__ */ new WeakSet();
15
+ #i = t(() => this.#c(), 500, { trailing: !0 });
16
+ get #a() {
14
17
  return {
15
18
  grid: this.host,
16
19
  ...this.host.keynavGridConfig
17
20
  };
18
21
  }
19
- get #r() {
20
- let e = Array.from(this.#n.rows);
21
- return this.#n.columnRow && e.unshift(this.#n.columnRow), e;
22
+ get #o() {
23
+ let e = Array.from(this.#a.rows);
24
+ return this.#a.columnRow && e.unshift(this.#a.columnRow), e;
22
25
  }
23
- get #i() {
24
- return [...Array.from(this.#n.columns ?? []), ...Array.from(this.#n.cells)];
26
+ get #s() {
27
+ let { columns: e, cells: t } = this.#a;
28
+ return [...Array.from(e ?? []), ...Array.from(t)];
25
29
  }
26
30
  constructor(e) {
27
31
  this.host = e, this.host.addController(this);
28
32
  }
29
33
  async hostConnected() {
30
- await this.host.updateComplete, this.host.isConnected && (this.#t = this.#n.grid, o(this.#i), this.#t.addEventListener("keyup", this.#l), this.#t.addEventListener("keydown", this.#u), this.#t.addEventListener("mouseup", this.#d), this.#e.push(t(this.host, n(() => o(this.#i), 500))));
34
+ await this.host.updateComplete, this.host.isConnected && (this.#t = this.#a.grid, this.#c(), this.#t.addEventListener("keyup", this.#m), this.#t.addEventListener("keydown", this.#f), this.#t.addEventListener("mouseup", this.#d), this.#e?.disconnect(), this.#e = new MutationObserver(this.#l), this.#e.observe(this.#t, {
35
+ childList: !0,
36
+ subtree: !0,
37
+ attributes: !0,
38
+ attributeFilter: ["tabindex"]
39
+ }));
31
40
  }
32
41
  hostDisconnected() {
33
- this.#e.forEach((e) => e?.disconnect()), this.#e.length = 0, this.#t?.removeEventListener("keyup", this.#l), this.#t?.removeEventListener("keydown", this.#u), this.#t?.removeEventListener("mouseup", this.#d), this.#t = void 0;
42
+ this.#e?.disconnect(), this.#e = void 0, this.#i.cancel(), this.#t?.removeEventListener("keyup", this.#m), this.#t?.removeEventListener("keydown", this.#f), this.#t?.removeEventListener("mouseup", this.#d), this.#t = void 0, this.#n = void 0;
34
43
  }
35
- #a(e) {
36
- if (!p(e)) {
37
- let t = e.composedPath()[0], n = this.#i.find((e) => e === t) ? t : null;
38
- n && this.#s(e, n);
44
+ #c() {
45
+ let e = this.#s, t = e.find((e) => e.tabIndex === 0) ?? (this.#n && e.includes(this.#n) ? this.#n : e[0]);
46
+ this.#n = t, this.#r = new WeakSet(e);
47
+ for (let n of e) {
48
+ let e = n === t ? "0" : "-1";
49
+ n.getAttribute("tabindex") !== e && n.setAttribute("tabindex", e);
39
50
  }
40
51
  }
41
- #o(t) {
42
- let n = Array.from(this.#r), i = Array.from(this.#i);
43
- if (e.state.env !== "production" && f(n)) {
44
- r.warn("Invalid grid structure, all rows must have the same number of cells");
52
+ #l = (e) => {
53
+ e.some((e) => {
54
+ if (e.type === "attributes") {
55
+ let t = e.target;
56
+ return t instanceof HTMLElement && this.#r.has(t) && t.getAttribute("tabindex") !== (t === this.#n ? "0" : "-1");
57
+ }
58
+ return [...e.addedNodes, ...e.removedNodes].some((e) => e.nodeType === Node.ELEMENT_NODE);
59
+ }) && this.#i();
60
+ };
61
+ #u() {
62
+ this.#l(this.#e?.takeRecords() ?? []), this.#i.flush();
63
+ }
64
+ #d = (e) => {
65
+ if (!d(e)) {
66
+ this.#u();
67
+ let t = e.composedPath()[0], n = this.#s.find((e) => e === t) ? t : null;
68
+ n && this.#p(e, n);
69
+ }
70
+ };
71
+ #f = (t) => {
72
+ if (!f(t)) return;
73
+ this.#u();
74
+ let r = Array.from(this.#o), o = Array.from(this.#s);
75
+ if (e.state.env !== "production" && u(r)) {
76
+ n.warn("Invalid grid structure, all rows must have the same number of cells");
45
77
  return;
46
78
  }
47
- if (m(t) && s(a())) {
48
- let { x: e, y: r } = y(i, n, {
79
+ if (a(i())) {
80
+ let { x: e, y: n } = _(o, r, {
49
81
  code: t.code,
50
82
  ctrlKey: t.ctrlKey,
51
83
  dir: this.host.dir
52
- }), a = Array.from(u(n[r])).filter((e) => !!i.find((t) => t === e))[e];
53
- this.#s(t, a), t.preventDefault();
84
+ }), i = Array.from(c(r[n])).filter((e) => !!o.find((t) => t === e))[e];
85
+ this.#p(t, i), t.preventDefault();
54
86
  }
55
- }
56
- #s(e, t) {
57
- c(this.#i, t);
58
- let n = d(t), r = n.filter((e) => s(e));
59
- r.length === 1 && n.length === 1 ? i(r[0]) : i(t);
60
- let a = {
87
+ };
88
+ #p(e, t) {
89
+ this.#n = t, o(this.#s, t);
90
+ let n = l(t), i = n.filter((e) => a(e));
91
+ i.length === 1 && n.length === 1 ? r(i[0]) : r(t);
92
+ let s = {
61
93
  code: e instanceof KeyboardEvent ? e.code : null,
62
94
  shiftKey: e.shiftKey,
63
95
  activeItem: t
@@ -65,23 +97,22 @@ var g = class {
65
97
  t.dispatchEvent(new CustomEvent("nve-key-change", {
66
98
  bubbles: !0,
67
99
  composed: !0,
68
- detail: a
100
+ detail: s
69
101
  }));
70
102
  }
71
- #c(e) {
72
- let t = Array.from(this.#i).find((e) => e.tabIndex === 0);
73
- e.code === "Escape" && t?.focus(), e.code === "Enter" && t === e.composedPath()[0] && d(t)[0]?.focus();
74
- }
75
- #l = (e) => this.#c(e);
76
- #u = (e) => this.#o(e);
77
- #d = (e) => this.#a(e);
103
+ #m = (e) => {
104
+ if (e.code !== "Enter" && e.code !== "Escape") return;
105
+ this.#u();
106
+ let t = Array.from(this.#s).find((e) => e.tabIndex === 0);
107
+ e.code === "Escape" && t?.focus(), e.code === "Enter" && t === e.composedPath()[0] && l(t)[0]?.focus();
108
+ };
78
109
  };
79
- function _(e, t) {
80
- let n = t === "rtl" ? l.ArrowRight : l.ArrowLeft, r = t === "rtl" ? l.ArrowLeft : l.ArrowRight;
81
- return e === l.ArrowUp ? {
110
+ function h(e, t) {
111
+ let n = t === "rtl" ? s.ArrowRight : s.ArrowLeft, r = t === "rtl" ? s.ArrowLeft : s.ArrowRight;
112
+ return e === s.ArrowUp ? {
82
113
  dx: 0,
83
114
  dy: -1
84
- } : e === l.ArrowDown ? {
115
+ } : e === s.ArrowDown ? {
85
116
  dx: 0,
86
117
  dy: 1
87
118
  } : e === n ? {
@@ -90,42 +121,42 @@ function _(e, t) {
90
121
  } : e === r ? {
91
122
  dx: 1,
92
123
  dy: 0
93
- } : e === l.PageUp ? {
124
+ } : e === s.PageUp ? {
94
125
  dx: 0,
95
126
  dy: -4
96
- } : e === l.PageDown ? {
127
+ } : e === s.PageDown ? {
97
128
  dx: 0,
98
129
  dy: 4
99
130
  } : null;
100
131
  }
101
- function v(e, t, n) {
102
- let { x: r, y: i } = t, { columnCount: a, rowCount: o, ctrlKey: s } = n;
103
- return e === l.End ? {
132
+ function g(e, t, n) {
133
+ let { x: r, y: i } = t, { columnCount: a, rowCount: o, ctrlKey: c } = n;
134
+ return e === s.End ? {
104
135
  x: a,
105
- y: s ? o : i
106
- } : e === l.Home ? {
136
+ y: c ? o : i
137
+ } : e === s.Home ? {
107
138
  x: 0,
108
- y: s ? 0 : i
139
+ y: c ? 0 : i
109
140
  } : {
110
141
  x: r,
111
142
  y: i
112
143
  };
113
144
  }
114
- function y(e, t, n) {
115
- let r = e.find((e) => e.tabIndex === 0), i = t.find((e) => u(e).find((e) => e === r)), a = Array.from(u(i)).filter((t) => !!e.find((e) => e === t)), o = t.length - 1, s = a.length - 1, c = a.indexOf(r), l = t.indexOf(i), d = _(n.code, n.dir);
116
- return d ? (c = Math.max(0, Math.min(s, c + d.dx)), l = Math.max(0, Math.min(o, l + d.dy))) : {x: c, y: l} = v(n.code, {
117
- x: c,
118
- y: l
145
+ function _(e, t, n) {
146
+ let r = e.find((e) => e.tabIndex === 0), i = t.find((e) => c(e).find((e) => e === r)), a = Array.from(c(i)).filter((t) => !!e.find((e) => e === t)), o = t.length - 1, s = a.length - 1, l = a.indexOf(r), u = t.indexOf(i), d = h(n.code, n.dir);
147
+ return d ? (l = Math.max(0, Math.min(s, l + d.dx)), u = Math.max(0, Math.min(o, u + d.dy))) : {x: l, y: u} = g(n.code, {
148
+ x: l,
149
+ y: u
119
150
  }, {
120
151
  columnCount: s,
121
152
  rowCount: o,
122
153
  ctrlKey: n.ctrlKey
123
154
  }), {
124
- x: c,
125
- y: l
155
+ x: l,
156
+ y: u
126
157
  };
127
158
  }
128
159
  //#endregion
129
- export { g as KeyNavigationGridController, y as getNextKeyGridItem, h as keyNavigationGrid };
160
+ export { m as KeyNavigationGridController, _ as getNextKeyGridItem, p as keyNavigationGrid };
130
161
 
131
162
  //# sourceMappingURL=keynav-grid.controller.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"keynav-grid.controller.js","names":[],"sources":["../../../src/internal/controllers/keynav-grid.controller.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ReactiveController, ReactiveElement } from 'lit';\nimport type { LegacyDecoratorTarget } from '../types/index.js';\nimport { onChildListMutation, throttle } from '../utils/events.js';\nimport { GlobalStateService } from '../services/global.service.js';\nimport { LogService } from '../services/log.service.js';\nimport {\n validKeyNavigationCode,\n isContextMenuClick,\n getFlattenedDOMTree,\n getFlattenedFocusableItems,\n KeynavCode,\n hasInvalidDOMGrid\n} from '../utils/dom.js';\nimport {\n focusElement,\n getActiveElement,\n initializeKeyListItems,\n setActiveKeyListItem,\n isSimpleFocusable\n} from '../utils/focus.js';\n\nexport interface KeynavGridConfig {\n grid?: HTMLElement;\n columnRow?: HTMLElement;\n columns?: NodeListOf<HTMLElement> | HTMLElement[];\n rows: NodeListOf<HTMLElement> | HTMLElement[];\n cells: NodeListOf<HTMLElement> | HTMLElement[];\n}\n\nexport interface KeynavGridElement {\n keynavGridConfig: KeynavGridConfig;\n}\n\n/**\n * https://w3c.github.io/aria-practices/#gridNav_focus\n */\nexport function keyNavigationGrid<T extends ReactiveElement & KeynavGridElement>(): ClassDecorator {\n return (target: LegacyDecoratorTarget) =>\n target.addInitializer!((instance: T) => new KeyNavigationGridController(instance));\n}\n\nexport class KeyNavigationGridController<T extends ReactiveElement & KeynavGridElement> implements ReactiveController {\n #observers: MutationObserver[] = [];\n #grid?: HTMLElement;\n\n get #config() {\n return {\n grid: this.host,\n ...this.host.keynavGridConfig\n };\n }\n\n get #hostRows() {\n const rows = Array.from(this.#config.rows);\n\n if (this.#config.columnRow) {\n rows.unshift(this.#config.columnRow);\n }\n\n return rows;\n }\n\n get #hostCells() {\n return [...Array.from(this.#config.columns ?? []), ...Array.from(this.#config.cells)];\n }\n\n constructor(private host: T) {\n this.host.addController(this);\n }\n\n async hostConnected() {\n await this.host.updateComplete;\n if (!this.host.isConnected) return;\n\n this.#grid = this.#config.grid;\n initializeKeyListItems(this.#hostCells);\n this.#grid.addEventListener('keyup', this.#onKeyUp);\n this.#grid.addEventListener('keydown', this.#onKeyDown);\n this.#grid.addEventListener('mouseup', this.#onMouseUp);\n this.#observers.push(\n onChildListMutation(\n this.host,\n throttle(() => initializeKeyListItems(this.#hostCells), 500)\n )\n );\n }\n\n hostDisconnected() {\n this.#observers.forEach(o => o?.disconnect());\n this.#observers.length = 0;\n this.#grid?.removeEventListener('keyup', this.#onKeyUp);\n this.#grid?.removeEventListener('keydown', this.#onKeyDown);\n this.#grid?.removeEventListener('mouseup', this.#onMouseUp);\n this.#grid = undefined;\n }\n\n #clickCell(e: MouseEvent) {\n if (!isContextMenuClick(e)) {\n const focusedElement = e.composedPath()[0] as HTMLElement;\n const activeCell = this.#hostCells.find(i => i === focusedElement) ? focusedElement : null;\n if (activeCell) {\n this.#setActiveCell(e, activeCell as HTMLElement);\n }\n }\n }\n\n #keynavCell(e: KeyboardEvent) {\n const rows = Array.from(this.#hostRows);\n const cells = Array.from(this.#hostCells);\n\n if (GlobalStateService.state.env !== 'production' && hasInvalidDOMGrid(rows)) {\n LogService.warn('Invalid grid structure, all rows must have the same number of cells');\n return;\n }\n\n if (validKeyNavigationCode(e) && isSimpleFocusable(getActiveElement() as Element)) {\n const { x, y } = getNextKeyGridItem(cells, rows, {\n code: e.code,\n ctrlKey: e.ctrlKey,\n dir: this.host.dir\n });\n\n const nextCell = Array.from(getFlattenedDOMTree(rows[y]!)).filter(c => !!cells.find(i => i === c))[\n x\n ] as HTMLElement;\n this.#setActiveCell(e, nextCell);\n e.preventDefault();\n }\n }\n\n #setActiveCell(e: KeyboardEvent | MouseEvent, activeCell: HTMLElement) {\n setActiveKeyListItem(this.#hostCells, activeCell);\n\n const items = getFlattenedFocusableItems(activeCell);\n const simpleItems = items.filter(i => isSimpleFocusable(i));\n\n if (simpleItems.length === 1 && items.length === 1) {\n focusElement(simpleItems[0]!);\n } else {\n focusElement(activeCell);\n }\n\n const detail = { code: e instanceof KeyboardEvent ? e.code : null, shiftKey: e.shiftKey, activeItem: activeCell };\n activeCell.dispatchEvent(new CustomEvent('nve-key-change', { bubbles: true, composed: true, detail }));\n }\n\n #updateCellActivation(e: KeyboardEvent) {\n const activeCell = Array.from(this.#hostCells).find(i => i.tabIndex === 0) as HTMLElement;\n if (e.code === 'Escape') {\n activeCell?.focus();\n }\n\n if (e.code === 'Enter' && activeCell === e.composedPath()[0]) {\n getFlattenedFocusableItems(activeCell as HTMLElement)[0]?.focus();\n }\n }\n\n #onKeyUp = (e: KeyboardEvent) => this.#updateCellActivation(e);\n\n #onKeyDown = (e: KeyboardEvent) => this.#keynavCell(e);\n\n #onMouseUp = (e: MouseEvent) => this.#clickCell(e);\n}\n\nfunction getGridDelta(code: KeynavCode | string, dir: string): { dx: number; dy: number } | null {\n const start = dir === 'rtl' ? KeynavCode.ArrowRight : KeynavCode.ArrowLeft;\n const end = dir === 'rtl' ? KeynavCode.ArrowLeft : KeynavCode.ArrowRight;\n\n if (code === KeynavCode.ArrowUp) return { dx: 0, dy: -1 };\n if (code === KeynavCode.ArrowDown) return { dx: 0, dy: 1 };\n if (code === start) return { dx: -1, dy: 0 };\n if (code === end) return { dx: 1, dy: 0 };\n if (code === KeynavCode.PageUp) return { dx: 0, dy: -4 };\n if (code === KeynavCode.PageDown) return { dx: 0, dy: 4 };\n return null;\n}\n\nfunction applyGridHomeEnd(\n code: KeynavCode | string,\n position: { x: number; y: number },\n bounds: { columnCount: number; rowCount: number; ctrlKey: boolean }\n) {\n const { x, y } = position;\n const { columnCount, rowCount, ctrlKey } = bounds;\n if (code === KeynavCode.End) {\n return { x: columnCount, y: ctrlKey ? rowCount : y };\n }\n\n if (code === KeynavCode.Home) {\n return { x: 0, y: ctrlKey ? 0 : y };\n }\n\n return { x, y };\n}\n\nexport function getNextKeyGridItem(\n cells: HTMLElement[],\n rows: HTMLElement[],\n config: { code: KeynavCode | string; ctrlKey: boolean; dir: string }\n) {\n const currentCell = cells.find(i => i.tabIndex === 0) as HTMLElement;\n const currentRow = rows.find(r => getFlattenedDOMTree(r).find(c => c === currentCell)) as HTMLElement;\n const currentRowCells = Array.from(getFlattenedDOMTree(currentRow)).filter(c => !!cells.find(i => i === c));\n const rowCount = rows.length - 1;\n const columnCount = currentRowCells.length - 1;\n\n let x = currentRowCells.indexOf(currentCell);\n let y = rows.indexOf(currentRow);\n\n const delta = getGridDelta(config.code, config.dir);\n if (delta) {\n x = Math.max(0, Math.min(columnCount, x + delta.dx));\n y = Math.max(0, Math.min(rowCount, y + delta.dy));\n } else {\n ({ x, y } = applyGridHomeEnd(config.code, { x, y }, { columnCount, rowCount, ctrlKey: config.ctrlKey }));\n }\n\n return { x, y };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"keynav-grid.controller.js","names":[],"sources":["../../../src/internal/controllers/keynav-grid.controller.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ReactiveController, ReactiveElement } from 'lit';\nimport type { LegacyDecoratorTarget } from '../types/index.js';\nimport { throttle } from '../utils/events.js';\nimport { GlobalStateService } from '../services/global.service.js';\nimport { LogService } from '../services/log.service.js';\nimport {\n validKeyNavigationCode,\n isContextMenuClick,\n getFlattenedDOMTree,\n getFlattenedFocusableItems,\n KeynavCode,\n hasInvalidDOMGrid\n} from '../utils/dom.js';\nimport { focusElement, getActiveElement, setActiveKeyListItem, isSimpleFocusable } from '../utils/focus.js';\n\nexport interface KeynavGridConfig {\n grid?: HTMLElement;\n columnRow?: HTMLElement;\n columns?: NodeListOf<HTMLElement> | HTMLElement[];\n rows: NodeListOf<HTMLElement> | HTMLElement[];\n cells: NodeListOf<HTMLElement> | HTMLElement[];\n}\n\nexport interface KeynavGridElement {\n keynavGridConfig: KeynavGridConfig;\n}\n\n/**\n * https://w3c.github.io/aria-practices/#gridNav_focus\n */\nexport function keyNavigationGrid<T extends ReactiveElement & KeynavGridElement>(): ClassDecorator {\n return (target: LegacyDecoratorTarget) =>\n target.addInitializer!((instance: T) => new KeyNavigationGridController(instance));\n}\n\nexport class KeyNavigationGridController<T extends ReactiveElement & KeynavGridElement> implements ReactiveController {\n #observer?: MutationObserver;\n #grid?: HTMLElement;\n #activeCell?: HTMLElement;\n #cells = new WeakSet<HTMLElement>();\n #updateCells = throttle(() => this.#initializeCells(), 500, { trailing: true });\n\n get #config() {\n return {\n grid: this.host,\n ...this.host.keynavGridConfig\n };\n }\n\n get #hostRows() {\n const rows = Array.from(this.#config.rows);\n\n if (this.#config.columnRow) {\n rows.unshift(this.#config.columnRow);\n }\n\n return rows;\n }\n\n get #hostCells() {\n const { columns, cells } = this.#config;\n return [...Array.from(columns ?? []), ...Array.from(cells)];\n }\n\n constructor(private host: T) {\n this.host.addController(this);\n }\n\n async hostConnected() {\n await this.host.updateComplete;\n if (!this.host.isConnected) return;\n\n this.#grid = this.#config.grid;\n this.#initializeCells();\n this.#grid.addEventListener('keyup', this.#onKeyUp);\n this.#grid.addEventListener('keydown', this.#onKeyDown);\n this.#grid.addEventListener('mouseup', this.#onMouseUp);\n this.#observer?.disconnect();\n this.#observer = new MutationObserver(this.#onMutations);\n this.#observer.observe(this.#grid, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['tabindex']\n });\n }\n\n hostDisconnected() {\n this.#observer?.disconnect();\n this.#observer = undefined;\n this.#updateCells.cancel();\n this.#grid?.removeEventListener('keyup', this.#onKeyUp);\n this.#grid?.removeEventListener('keydown', this.#onKeyDown);\n this.#grid?.removeEventListener('mouseup', this.#onMouseUp);\n this.#grid = undefined;\n this.#activeCell = undefined;\n }\n\n #initializeCells() {\n const cells = this.#hostCells;\n const activeCell =\n cells.find(cell => cell.tabIndex === 0) ??\n (this.#activeCell && cells.includes(this.#activeCell) ? this.#activeCell : cells[0]);\n this.#activeCell = activeCell;\n this.#cells = new WeakSet(cells);\n for (const cell of cells) {\n const tabIndex = cell === activeCell ? '0' : '-1';\n // Avoid observing our own unchanged writes after a DOM morph or key change.\n if (cell.getAttribute('tabindex') !== tabIndex) {\n cell.setAttribute('tabindex', tabIndex);\n }\n }\n }\n\n #onMutations = (mutations: MutationRecord[]) => {\n const changed = mutations.some(mutation => {\n if (mutation.type === 'attributes') {\n const cell = mutation.target;\n // Ignore nested controls and our own tabindex writes.\n return (\n cell instanceof HTMLElement &&\n this.#cells.has(cell) &&\n cell.getAttribute('tabindex') !== (cell === this.#activeCell ? '0' : '-1')\n );\n }\n return [...mutation.addedNodes, ...mutation.removedNodes].some(node => node.nodeType === Node.ELEMENT_NODE);\n });\n if (changed) this.#updateCells();\n };\n\n #flushCellUpdates() {\n // A key event can arrive before the observer delivers a synchronous DOM update.\n this.#onMutations(this.#observer?.takeRecords() ?? []);\n this.#updateCells.flush();\n }\n\n #onMouseUp = (e: MouseEvent) => {\n if (!isContextMenuClick(e)) {\n this.#flushCellUpdates();\n const focusedElement = e.composedPath()[0] as HTMLElement;\n const activeCell = this.#hostCells.find(i => i === focusedElement) ? focusedElement : null;\n if (activeCell) {\n this.#setActiveCell(e, activeCell);\n }\n }\n };\n\n #onKeyDown = (e: KeyboardEvent) => {\n if (!validKeyNavigationCode(e)) return;\n this.#flushCellUpdates();\n const rows = Array.from(this.#hostRows);\n const cells = Array.from(this.#hostCells);\n\n if (GlobalStateService.state.env !== 'production' && hasInvalidDOMGrid(rows)) {\n LogService.warn('Invalid grid structure, all rows must have the same number of cells');\n return;\n }\n\n if (isSimpleFocusable(getActiveElement() as Element)) {\n const { x, y } = getNextKeyGridItem(cells, rows, {\n code: e.code,\n ctrlKey: e.ctrlKey,\n dir: this.host.dir\n });\n\n const nextCell = Array.from(getFlattenedDOMTree(rows[y]!)).filter(c => !!cells.find(i => i === c))[\n x\n ] as HTMLElement;\n this.#setActiveCell(e, nextCell);\n e.preventDefault();\n }\n };\n\n #setActiveCell(e: KeyboardEvent | MouseEvent, activeCell: HTMLElement) {\n this.#activeCell = activeCell;\n setActiveKeyListItem(this.#hostCells, activeCell);\n\n const items = getFlattenedFocusableItems(activeCell);\n const simpleItems = items.filter(i => isSimpleFocusable(i));\n\n if (simpleItems.length === 1 && items.length === 1) {\n focusElement(simpleItems[0]!);\n } else {\n focusElement(activeCell);\n }\n\n const detail = { code: e instanceof KeyboardEvent ? e.code : null, shiftKey: e.shiftKey, activeItem: activeCell };\n activeCell.dispatchEvent(new CustomEvent('nve-key-change', { bubbles: true, composed: true, detail }));\n }\n\n #onKeyUp = (e: KeyboardEvent) => {\n if (e.code !== 'Enter' && e.code !== 'Escape') return;\n this.#flushCellUpdates();\n const activeCell = Array.from(this.#hostCells).find(i => i.tabIndex === 0) as HTMLElement;\n if (e.code === 'Escape') {\n activeCell?.focus();\n }\n\n if (e.code === 'Enter' && activeCell === e.composedPath()[0]) {\n getFlattenedFocusableItems(activeCell)[0]?.focus();\n }\n };\n}\n\nfunction getGridDelta(code: KeynavCode | string, dir: string): { dx: number; dy: number } | null {\n const start = dir === 'rtl' ? KeynavCode.ArrowRight : KeynavCode.ArrowLeft;\n const end = dir === 'rtl' ? KeynavCode.ArrowLeft : KeynavCode.ArrowRight;\n\n if (code === KeynavCode.ArrowUp) return { dx: 0, dy: -1 };\n if (code === KeynavCode.ArrowDown) return { dx: 0, dy: 1 };\n if (code === start) return { dx: -1, dy: 0 };\n if (code === end) return { dx: 1, dy: 0 };\n if (code === KeynavCode.PageUp) return { dx: 0, dy: -4 };\n if (code === KeynavCode.PageDown) return { dx: 0, dy: 4 };\n return null;\n}\n\nfunction applyGridHomeEnd(\n code: KeynavCode | string,\n position: { x: number; y: number },\n bounds: { columnCount: number; rowCount: number; ctrlKey: boolean }\n) {\n const { x, y } = position;\n const { columnCount, rowCount, ctrlKey } = bounds;\n if (code === KeynavCode.End) {\n return { x: columnCount, y: ctrlKey ? rowCount : y };\n }\n\n if (code === KeynavCode.Home) {\n return { x: 0, y: ctrlKey ? 0 : y };\n }\n\n return { x, y };\n}\n\nexport function getNextKeyGridItem(\n cells: HTMLElement[],\n rows: HTMLElement[],\n config: { code: KeynavCode | string; ctrlKey: boolean; dir: string }\n) {\n const currentCell = cells.find(i => i.tabIndex === 0) as HTMLElement;\n const currentRow = rows.find(r => getFlattenedDOMTree(r).find(c => c === currentCell)) as HTMLElement;\n const currentRowCells = Array.from(getFlattenedDOMTree(currentRow)).filter(c => !!cells.find(i => i === c));\n const rowCount = rows.length - 1;\n const columnCount = currentRowCells.length - 1;\n\n let x = currentRowCells.indexOf(currentCell);\n let y = rows.indexOf(currentRow);\n\n const delta = getGridDelta(config.code, config.dir);\n if (delta) {\n x = Math.max(0, Math.min(columnCount, x + delta.dx));\n y = Math.max(0, Math.min(rowCount, y + delta.dy));\n } else {\n ({ x, y } = applyGridHomeEnd(config.code, { x, y }, { columnCount, rowCount, ctrlKey: config.ctrlKey }));\n }\n\n return { x, y };\n}\n"],"mappings":"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"}
@@ -19,7 +19,7 @@ var a = class {
19
19
  i18nRegistry: {},
20
20
  audit: {}
21
21
  }
22
- }, globalThis.NVE_ELEMENTS.state.versions = Array.from(/* @__PURE__ */ new Set([...globalThis.NVE_ELEMENTS.state.versions, "2.16.0"])), globalThis.NVE_ELEMENTS.state.scopedRegistry ??= {}, globalThis.NVE_ELEMENTS.state.scopedRegistry["2.16.0"] = i(), globalThis.NVE_ELEMENTS.state.versions.length > 1 && globalThis.NVE_ELEMENTS.state.env !== "production" && console.warn(e(), `\n\n${JSON.stringify(globalThis.NVE_ELEMENTS.state.versions, null, 2)}`);
22
+ }, globalThis.NVE_ELEMENTS.state.versions = Array.from(/* @__PURE__ */ new Set([...globalThis.NVE_ELEMENTS.state.versions, "2.17.0"])), globalThis.NVE_ELEMENTS.state.scopedRegistry ??= {}, globalThis.NVE_ELEMENTS.state.scopedRegistry["2.17.0"] = i(), globalThis.NVE_ELEMENTS.state.versions.length > 1 && globalThis.NVE_ELEMENTS.state.env !== "production" && console.warn(e(), `\n\n${JSON.stringify(globalThis.NVE_ELEMENTS.state.versions, null, 2)}`);
23
23
  }
24
24
  get state() {
25
25
  return globalThis.NVE_ELEMENTS.state;
@@ -1,4 +1,9 @@
1
1
  export declare function stopEvent(event: Event): void;
2
2
  export declare function onChildListMutation(element: HTMLElement, fn: (mutation?: MutationRecord) => void, options?: MutationObserverInit): MutationObserver;
3
- export declare function throttle(func: (...args: unknown[]) => void, limit: number): (...args: unknown[]) => void;
3
+ export declare function throttle<Args extends unknown[]>(func: (...args: Args) => void, limit: number, { trailing }?: {
4
+ trailing?: boolean;
5
+ }): ((...args: Args) => void) & {
6
+ flush(): void;
7
+ cancel(): void;
8
+ };
4
9
  export declare function debounce(func: (...args: unknown[]) => void, timeout?: number): (...args: unknown[]) => void;
@@ -11,11 +11,29 @@ function t(e, t, n = {}) {
11
11
  ...n
12
12
  }), r;
13
13
  }
14
- function n(e, t) {
15
- let n = !0;
16
- return (...r) => {
17
- n && (e(...r), n = !1, setTimeout(() => n = !0, t));
14
+ function n(e, t, { trailing: n = !1 } = {}) {
15
+ let r, i, a = (...o) => {
16
+ if (r !== void 0) {
17
+ n && (i = o);
18
+ return;
19
+ }
20
+ e(...o), r = setTimeout(() => {
21
+ if (r = void 0, i) {
22
+ let e = i;
23
+ i = void 0, a(...e);
24
+ }
25
+ }, t);
18
26
  };
27
+ return Object.assign(a, {
28
+ flush() {
29
+ if (!i) return;
30
+ let t = i;
31
+ i = void 0, e(...t);
32
+ },
33
+ cancel() {
34
+ clearTimeout(r), r = void 0, i = void 0;
35
+ }
36
+ });
19
37
  }
20
38
  function r(e, t = 0) {
21
39
  let n;
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","names":[],"sources":["../../../src/internal/utils/events.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport function stopEvent(event: Event) {\n event?.preventDefault();\n event?.stopPropagation();\n}\n\nexport function onChildListMutation(\n element: HTMLElement,\n fn: (mutation?: MutationRecord) => void,\n options: MutationObserverInit = {}\n) {\n const observer = new MutationObserver(mutations => {\n for (const mutation of mutations) {\n if (mutation.type === 'childList') {\n fn(mutation);\n }\n\n if (options.attributes && mutation.type === 'attributes') {\n fn(mutation);\n }\n }\n });\n observer.observe(element, { childList: true, ...options });\n return observer;\n}\n\nexport function throttle(func: (...args: unknown[]) => void, limit: number) {\n let wait = true;\n return (...args: unknown[]) => {\n if (wait) {\n func(...args);\n wait = false;\n /* istanbul ignore next */\n setTimeout(() => (wait = true), limit);\n }\n };\n}\n\nexport function debounce(func: (...args: unknown[]) => void, timeout = 0) {\n let timer: ReturnType<typeof setTimeout> | undefined;\n return (...args: unknown[]) => {\n clearTimeout(timer);\n /* istanbul ignore next */\n timer = setTimeout(() => {\n func(...args);\n }, timeout);\n };\n}\n"],"mappings":";AAGA,SAAgB,EAAU,GAAc;CAEtC,AADA,GAAO,eAAe,GACtB,GAAO,gBAAgB;AACzB;AAEA,SAAgB,EACd,GACA,GACA,IAAgC,CAAC,GACjC;CACA,IAAM,IAAW,IAAI,kBAAiB,MAAa;EACjD,KAAK,IAAM,KAAY,GAKrB,AAJI,EAAS,SAAS,eACpB,EAAG,CAAQ,GAGT,EAAQ,cAAc,EAAS,SAAS,gBAC1C,EAAG,CAAQ;CAGjB,CAAC;CAED,OADA,EAAS,QAAQ,GAAS;EAAE,WAAW;EAAM,GAAG;CAAQ,CAAC,GAClD;AACT;AAEA,SAAgB,EAAS,GAAoC,GAAe;CAC1E,IAAI,IAAO;CACX,QAAQ,GAAG,MAAoB;EAC7B,AAAI,MACF,EAAK,GAAG,CAAI,GACZ,IAAO,IAEP,iBAAkB,IAAO,IAAO,CAAK;CAEzC;AACF;AAEA,SAAgB,EAAS,GAAoC,IAAU,GAAG;CACxE,IAAI;CACJ,QAAQ,GAAG,MAAoB;;EAG7B,AAFA,aAAa,CAAK,GAElB,IAAQ,iBAAiB;GACvB,EAAK,GAAG,CAAI;EACd,GAAG,CAAO;CACZ;AACF"}
1
+ {"version":3,"file":"events.js","names":[],"sources":["../../../src/internal/utils/events.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport function stopEvent(event: Event) {\n event?.preventDefault();\n event?.stopPropagation();\n}\n\nexport function onChildListMutation(\n element: HTMLElement,\n fn: (mutation?: MutationRecord) => void,\n options: MutationObserverInit = {}\n) {\n const observer = new MutationObserver(mutations => {\n for (const mutation of mutations) {\n if (mutation.type === 'childList') {\n fn(mutation);\n }\n\n if (options.attributes && mutation.type === 'attributes') {\n fn(mutation);\n }\n }\n });\n observer.observe(element, { childList: true, ...options });\n return observer;\n}\n\nexport function throttle<Args extends unknown[]>(\n func: (...args: Args) => void,\n limit: number,\n { trailing = false }: { trailing?: boolean } = {}\n) {\n let timer: ReturnType<typeof setTimeout> | undefined;\n let pending: Args | undefined;\n\n const throttled = (...args: Args): void => {\n if (timer !== undefined) {\n if (trailing) pending = args;\n return;\n }\n\n func(...args);\n timer = setTimeout(() => {\n timer = undefined;\n if (pending) {\n const nextArgs = pending;\n pending = undefined;\n throttled(...nextArgs);\n }\n }, limit);\n };\n\n return Object.assign(throttled, {\n flush() {\n if (!pending) return;\n const args = pending;\n pending = undefined;\n func(...args);\n },\n cancel() {\n clearTimeout(timer);\n timer = undefined;\n pending = undefined;\n }\n });\n}\n\nexport function debounce(func: (...args: unknown[]) => void, timeout = 0) {\n let timer: ReturnType<typeof setTimeout> | undefined;\n return (...args: unknown[]) => {\n clearTimeout(timer);\n /* istanbul ignore next */\n timer = setTimeout(() => {\n func(...args);\n }, timeout);\n };\n}\n"],"mappings":";AAGA,SAAgB,EAAU,GAAc;CAEtC,AADA,GAAO,eAAe,GACtB,GAAO,gBAAgB;AACzB;AAEA,SAAgB,EACd,GACA,GACA,IAAgC,CAAC,GACjC;CACA,IAAM,IAAW,IAAI,kBAAiB,MAAa;EACjD,KAAK,IAAM,KAAY,GAKrB,AAJI,EAAS,SAAS,eACpB,EAAG,CAAQ,GAGT,EAAQ,cAAc,EAAS,SAAS,gBAC1C,EAAG,CAAQ;CAGjB,CAAC;CAED,OADA,EAAS,QAAQ,GAAS;EAAE,WAAW;EAAM,GAAG;CAAQ,CAAC,GAClD;AACT;AAEA,SAAgB,EACd,GACA,GACA,EAAE,cAAW,OAAkC,CAAC,GAChD;CACA,IAAI,GACA,GAEE,KAAa,GAAG,MAAqB;EACzC,IAAI,MAAU,KAAA,GAAW;GACvB,AAAI,MAAU,IAAU;GACxB;EACF;EAGA,AADA,EAAK,GAAG,CAAI,GACZ,IAAQ,iBAAiB;GAEvB,IADA,IAAQ,KAAA,GACJ,GAAS;IACX,IAAM,IAAW;IAEjB,AADA,IAAU,KAAA,GACV,EAAU,GAAG,CAAQ;GACvB;EACF,GAAG,CAAK;CACV;CAEA,OAAO,OAAO,OAAO,GAAW;EAC9B,QAAQ;GACN,IAAI,CAAC,GAAS;GACd,IAAM,IAAO;GAEb,AADA,IAAU,KAAA,GACV,EAAK,GAAG,CAAI;EACd;EACA,SAAS;GAGP,AAFA,aAAa,CAAK,GAClB,IAAQ,KAAA,GACR,IAAU,KAAA;EACZ;CACF,CAAC;AACH;AAEA,SAAgB,EAAS,GAAoC,IAAU,GAAG;CACxE,IAAI;CACJ,QAAQ,GAAG,MAAoB;;EAG7B,AAFA,aAAa,CAAK,GAElB,IAAQ,iBAAiB;GACvB,EAAK,GAAG,CAAI;EACd,GAAG,CAAO;CACZ;AACF"}
@@ -12,7 +12,7 @@ var c = class extends a {
12
12
  static {
13
13
  this.metadata = {
14
14
  tag: "nve-logo",
15
- version: "2.16.0"
15
+ version: "2.17.0"
16
16
  };
17
17
  }
18
18
  render() {