@nvidia-elements/core 2.0.1 → 2.0.3

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 (195) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +1 -1
  3. package/dist/_virtual/{_@oxc-project_runtime@0.132.0/helpers → _@oxc-project_runtime@0.133.0/helpers/esm}/decorate.js +1 -1
  4. package/dist/accordion/accordion2.js +5 -5
  5. package/dist/alert/alert-group2.js +2 -2
  6. package/dist/alert/alert2.js +2 -2
  7. package/dist/avatar/avatar-group2.js +1 -1
  8. package/dist/avatar/avatar.examples.js.map +1 -1
  9. package/dist/avatar/avatar.examples.json +1 -1
  10. package/dist/avatar/avatar2.js +2 -2
  11. package/dist/badge/badge2.js +2 -2
  12. package/dist/breadcrumb/breadcrumb2.js +2 -2
  13. package/dist/bundles/index.d.ts +6 -17
  14. package/dist/bundles/index.js +6 -6
  15. package/dist/button/button2.js +2 -2
  16. package/dist/button-group/button-group2.js +2 -2
  17. package/dist/card/card.examples.js.map +1 -1
  18. package/dist/card/card.examples.json +1 -1
  19. package/dist/card/card2.js +5 -5
  20. package/dist/chat-message/chat-message.d.ts +0 -2
  21. package/dist/chat-message/chat-message2.js +2 -2
  22. package/dist/chat-message/chat-message2.js.map +1 -1
  23. package/dist/checkbox/checkbox-group2.js +2 -2
  24. package/dist/checkbox/checkbox2.js +2 -2
  25. package/dist/color/color2.js +2 -2
  26. package/dist/combobox/combobox2.js +8 -8
  27. package/dist/copy-button/copy-button2.js +2 -2
  28. package/dist/custom-elements.json +155 -720
  29. package/dist/data.html.json +26 -3
  30. package/dist/data.snippets.json +27 -27
  31. package/dist/date/date2.js +2 -2
  32. package/dist/datetime/datetime2.js +2 -2
  33. package/dist/dialog/dialog-footer2.js +2 -2
  34. package/dist/dialog/dialog-header2.js +2 -2
  35. package/dist/dialog/dialog2.js +2 -2
  36. package/dist/divider/divider2.js +2 -2
  37. package/dist/dot/dot2.js +2 -2
  38. package/dist/drawer/drawer-content2.js +2 -2
  39. package/dist/drawer/drawer-footer2.js +2 -2
  40. package/dist/drawer/drawer-header2.js +2 -2
  41. package/dist/drawer/drawer2.js +2 -2
  42. package/dist/dropdown/dropdown-footer2.js +2 -2
  43. package/dist/dropdown/dropdown-header2.js +2 -2
  44. package/dist/dropdown/dropdown2.js +2 -2
  45. package/dist/dropdown-group/dropdown-group.d.ts +0 -1
  46. package/dist/dropdown-group/dropdown-group.js +2 -2
  47. package/dist/dropdown-group/dropdown-group.js.map +1 -1
  48. package/dist/dropzone/dropzone.d.ts +0 -1
  49. package/dist/dropzone/dropzone2.js +2 -2
  50. package/dist/dropzone/dropzone2.js.map +1 -1
  51. package/dist/file/file2.js +1 -1
  52. package/dist/format-datetime/format-datetime.d.ts +1 -0
  53. package/dist/format-datetime/format-datetime2.js +2 -2
  54. package/dist/format-datetime/format-datetime2.js.map +1 -1
  55. package/dist/format-number/format-number.d.ts +1 -0
  56. package/dist/format-number/format-number2.js +2 -2
  57. package/dist/format-number/format-number2.js.map +1 -1
  58. package/dist/format-relative-time/format-relative-time.d.ts +1 -0
  59. package/dist/format-relative-time/format-relative-time2.js +6 -3
  60. package/dist/format-relative-time/format-relative-time2.js.map +1 -1
  61. package/dist/forms/control/control.js +1 -1
  62. package/dist/forms/control/control.js.map +1 -1
  63. package/dist/forms/control/control2.js +39 -21
  64. package/dist/forms/control/control2.js.map +1 -1
  65. package/dist/forms/control-group/control-group.js +1 -1
  66. package/dist/forms/control-group/control-group.js.map +1 -1
  67. package/dist/forms/control-group/control-group2.js +2 -2
  68. package/dist/forms/control-group/control-group2.js.map +1 -1
  69. package/dist/forms/control-message/control-message2.js +2 -2
  70. package/dist/forms/utils/states.d.ts +6 -3
  71. package/dist/forms/utils/states.js +40 -32
  72. package/dist/forms/utils/states.js.map +1 -1
  73. package/dist/grid/cell/cell2.js +1 -1
  74. package/dist/grid/column/column2.js +2 -2
  75. package/dist/grid/footer/footer2.js +2 -2
  76. package/dist/grid/grid2.js +2 -2
  77. package/dist/grid/header/header2.js +2 -2
  78. package/dist/grid/placeholder/placeholder2.js +1 -1
  79. package/dist/grid/row/row2.js +2 -2
  80. package/dist/icon/icon2.js +3 -3
  81. package/dist/icon-button/icon-button2.js +2 -2
  82. package/dist/index.js +1 -1
  83. package/dist/input/input-group2.js +1 -1
  84. package/dist/input/input2.js +2 -2
  85. package/dist/internal/controllers/keynav-grid.controller.js +22 -18
  86. package/dist/internal/controllers/keynav-grid.controller.js.map +1 -1
  87. package/dist/internal/controllers/keynav-list.controller.d.ts +1 -0
  88. package/dist/internal/controllers/keynav-list.controller.js +6 -1
  89. package/dist/internal/controllers/keynav-list.controller.js.map +1 -1
  90. package/dist/internal/controllers/type-native-popover.controller.js +70 -40
  91. package/dist/internal/controllers/type-native-popover.controller.js.map +1 -1
  92. package/dist/internal/index.d.ts +0 -9
  93. package/dist/internal/index.js +20 -29
  94. package/dist/internal/services/global.service.js +1 -1
  95. package/dist/internal/services/log.service.js +1 -1
  96. package/dist/internal/services/log.service.js.map +1 -1
  97. package/dist/internal/types/index.d.ts +3 -0
  98. package/dist/internal/types/index.js.map +1 -1
  99. package/dist/internal/utils/dom.d.ts +1 -1
  100. package/dist/internal/utils/dom.js +71 -54
  101. package/dist/internal/utils/dom.js.map +1 -1
  102. package/dist/logo/logo2.js +2 -2
  103. package/dist/menu/menu-item2.js +2 -2
  104. package/dist/menu/menu2.js +2 -2
  105. package/dist/month/month2.js +2 -2
  106. package/dist/notification/notification-group2.js +2 -2
  107. package/dist/notification/notification2.js +2 -2
  108. package/dist/page/page-panel/page-panel-content2.js +1 -1
  109. package/dist/page/page-panel/page-panel-footer2.js +2 -2
  110. package/dist/page/page-panel/page-panel-header2.js +2 -2
  111. package/dist/page/page-panel/page-panel2.js +2 -2
  112. package/dist/page/page.examples.js.map +1 -1
  113. package/dist/page/page.examples.json +1 -1
  114. package/dist/page/page2.js +2 -2
  115. package/dist/page-header/page-header2.js +1 -1
  116. package/dist/page-loader/page-loader2.js +2 -2
  117. package/dist/pagination/pagination2.js +2 -2
  118. package/dist/panel/panel2.js +5 -5
  119. package/dist/password/password2.js +2 -2
  120. package/dist/preferences-input/preferences-input.js +1 -1
  121. package/dist/preferences-input/preferences-input.js.map +1 -1
  122. package/dist/preferences-input/preferences-input2.js +2 -2
  123. package/dist/progress-bar/progress-bar2.js +2 -2
  124. package/dist/progress-ring/progress-ring2.js +2 -2
  125. package/dist/progressive-filter-chip/progressive-filter-chip.examples.js.map +1 -1
  126. package/dist/progressive-filter-chip/progressive-filter-chip.examples.json +1 -1
  127. package/dist/progressive-filter-chip/progressive-filter-chip2.js +2 -2
  128. package/dist/pulse/pulse2.js +2 -2
  129. package/dist/radio/radio-group2.js +2 -2
  130. package/dist/radio/radio2.js +2 -2
  131. package/dist/range/range2.js +2 -2
  132. package/dist/resize-handle/resize-handle2.js +2 -2
  133. package/dist/search/search2.js +2 -2
  134. package/dist/select/select2.js +35 -21
  135. package/dist/select/select2.js.map +1 -1
  136. package/dist/skeleton/skeleton2.js +2 -2
  137. package/dist/sort-button/sort-button2.js +2 -2
  138. package/dist/sparkline/sparkline.utils.js +4 -2
  139. package/dist/sparkline/sparkline.utils.js.map +1 -1
  140. package/dist/sparkline/sparkline2.js +2 -2
  141. package/dist/star-rating/star-rating2.js +2 -2
  142. package/dist/steps/steps2.js +3 -3
  143. package/dist/switch/switch-group2.js +2 -2
  144. package/dist/switch/switch2.js +2 -2
  145. package/dist/tabs/tabs-group2.js +2 -2
  146. package/dist/tabs/tabs.examples.js.map +1 -1
  147. package/dist/tabs/tabs.examples.json +1 -1
  148. package/dist/tabs/tabs2.js +3 -3
  149. package/dist/tag/tag2.js +2 -2
  150. package/dist/textarea/textarea2.js +1 -1
  151. package/dist/time/time2.js +2 -2
  152. package/dist/toast/toast2.js +2 -2
  153. package/dist/toggletip/toggletip-footer.d.ts +1 -1
  154. package/dist/toggletip/toggletip-footer2.js +2 -2
  155. package/dist/toggletip/toggletip-footer2.js.map +1 -1
  156. package/dist/toggletip/toggletip-header.d.ts +1 -1
  157. package/dist/toggletip/toggletip-header2.js +2 -2
  158. package/dist/toggletip/toggletip-header2.js.map +1 -1
  159. package/dist/toggletip/toggletip2.js +2 -2
  160. package/dist/toolbar/toolbar2.js +2 -2
  161. package/dist/tooltip/tooltip2.js +2 -2
  162. package/dist/tree/tree-node2.js +2 -2
  163. package/dist/tree/tree2.js +2 -2
  164. package/dist/week/week2.js +2 -2
  165. package/package.json +8 -8
  166. package/dist/internal/controllers/state-active.controller.d.ts +0 -18
  167. package/dist/internal/controllers/state-active.controller.js +0 -29
  168. package/dist/internal/controllers/state-active.controller.js.map +0 -1
  169. package/dist/internal/controllers/state-current.controller.d.ts +0 -18
  170. package/dist/internal/controllers/state-current.controller.js +0 -28
  171. package/dist/internal/controllers/state-current.controller.js.map +0 -1
  172. package/dist/internal/controllers/state-disabled.controller.d.ts +0 -18
  173. package/dist/internal/controllers/state-disabled.controller.js +0 -20
  174. package/dist/internal/controllers/state-disabled.controller.js.map +0 -1
  175. package/dist/internal/controllers/state-pressed.controller.d.ts +0 -18
  176. package/dist/internal/controllers/state-pressed.controller.js +0 -20
  177. package/dist/internal/controllers/state-pressed.controller.js.map +0 -1
  178. package/dist/internal/controllers/type-button.controller.d.ts +0 -18
  179. package/dist/internal/controllers/type-button.controller.examples.js +0 -6
  180. package/dist/internal/controllers/type-button.controller.examples.js.map +0 -1
  181. package/dist/internal/controllers/type-button.controller.examples.json +0 -16
  182. package/dist/internal/controllers/type-button.controller.js +0 -21
  183. package/dist/internal/controllers/type-button.controller.js.map +0 -1
  184. package/dist/internal/controllers/type-command.controller.d.ts +0 -25
  185. package/dist/internal/controllers/type-command.controller.js +0 -38
  186. package/dist/internal/controllers/type-command.controller.js.map +0 -1
  187. package/dist/internal/controllers/type-interest.controller.d.ts +0 -23
  188. package/dist/internal/controllers/type-interest.controller.js +0 -51
  189. package/dist/internal/controllers/type-interest.controller.js.map +0 -1
  190. package/dist/internal/controllers/type-native-popover-trigger.controller.d.ts +0 -16
  191. package/dist/internal/controllers/type-native-popover-trigger.controller.js +0 -25
  192. package/dist/internal/controllers/type-native-popover-trigger.controller.js.map +0 -1
  193. package/dist/internal/controllers/type-submit.controller.d.ts +0 -22
  194. package/dist/internal/controllers/type-submit.controller.js +0 -49
  195. package/dist/internal/controllers/type-submit.controller.js.map +0 -1
@@ -3,66 +3,74 @@ import { ControlMessage as i } from "../control-message/control-message2.js";
3
3
  //#region src/forms/utils/states.ts
4
4
  var a = "input, select, selectmenu, textarea, [nve-control]";
5
5
  function o(e, t) {
6
+ let n = [];
6
7
  if (!e.input.form?.noValidate && !e.input.formNoValidate && !e.input.hasAttribute("formnovalidate")) {
7
- f(t);
8
- let n = () => {
9
- e.input.validity?.valid && (e._internals.states.delete("invalid"), e._internals.states.add("valid"), e.status = null), m(e, t);
10
- }, r = () => {
11
- e.status = null, e._internals.states.delete("valid"), e._internals.states.delete("invalid"), f(t);
8
+ m(t);
9
+ let r = () => {
10
+ e.input.validity?.valid && (e._internals.states.delete("invalid"), e._internals.states.add("valid"), e.status = null), g(e, t);
11
+ }, i = () => {
12
+ e.status = null, e._internals.states.delete("valid"), e._internals.states.delete("invalid"), m(t);
12
13
  };
13
- e.input.addEventListener("blur", () => {
14
- e.input.checkValidity(), n();
15
- }), e.input.addEventListener("input", () => {
16
- n();
17
- }), e.input.addEventListener("invalid", () => {
18
- t.find((e) => e.error) && (f(t), p(e, t)), e.status = "error", e._internals.states.delete("valid"), e._internals.states.add("invalid");
19
- }), e.addEventListener("reset", () => r()), e.input.form?.addEventListener("reset", () => r());
14
+ n.push(f(e.input, "blur", () => {
15
+ e.input.checkValidity(), r();
16
+ }), f(e.input, "input", () => {
17
+ r();
18
+ }), f(e.input, "invalid", () => {
19
+ t.find((e) => e.error) && (m(t), h(e, t)), e.status = "error", e._internals.states.delete("valid"), e._internals.states.add("invalid");
20
+ }), f(e, "reset", i)), e.input.form && n.push(f(e.input.form, "reset", i));
20
21
  }
21
- e.shadowRoot.addEventListener("slotchange", () => {
22
+ return n.push(f(e.shadowRoot, "slotchange", () => {
22
23
  let t = Array.from(e.querySelectorAll(i.metadata.tag));
23
24
  e._internals.states.delete("valid"), e._internals.states.delete("invalid"), t.find((e) => !e.hidden && (e.status === "error" || e.error)) ? e._internals.states.add("invalid") : e._internals.states.add("valid");
24
- });
25
+ })), n;
25
26
  }
26
27
  function s(e) {
27
28
  let t = [], r = e._internals.states;
28
- return e.input.checked ? r.add("checked") : r.delete("checked"), e.input.indeterminate ? r.add("indeterminate") : r.delete("indeterminate"), e.input.addEventListener("focus", () => e._internals.states.add("focus")), e.input.addEventListener("input", () => e._internals.states.add("dirty")), e.input.addEventListener("blur", () => {
29
+ return e.input.checked ? r.add("checked") : r.delete("checked"), e.input.indeterminate ? r.add("indeterminate") : r.delete("indeterminate"), t.push(...c(e)), t.push(n(e.input, "readonly", (e) => e === "" || e ? r.add("readonly") : r.delete("readonly")), n(e.input, "checked", () => e.input.checked ? r.add("checked") : r.delete("checked")), n(e.input, "disabled", (e) => e === "" || e ? r.add("disabled") : r.delete("disabled")), n(e.input, "indeterminate", () => e.input.indeterminate ? r.add("indeterminate") : r.delete("indeterminate"))), t;
30
+ }
31
+ function c(e) {
32
+ let t = [], n = e._internals.states;
33
+ return t.push(f(e.input, "focus", () => e._internals.states.add("focus")), f(e.input, "input", () => e._internals.states.add("dirty")), f(e.input, "blur", () => {
29
34
  e._internals.states.add("touched"), e._internals.states.delete("focus");
30
- }), e.input.getRootNode().addEventListener("change", (t) => {
31
- t.target.name === e.input?.name && (e.input.checked ? r.add("checked") : r.delete("checked"));
32
- }), e.input.form?.addEventListener("reset", () => {
35
+ }), f(e.input.getRootNode(), "change", (t) => {
36
+ t.target.name === e.input?.name && (e.input.checked ? n.add("checked") : n.delete("checked"));
37
+ })), e.input.form && t.push(f(e.input.form, "reset", () => {
33
38
  e._internals.states.delete("touched"), e._internals.states.delete("dirty"), e._internals.states.delete("error"), e._internals.states.delete("success"), e.requestUpdate();
34
- }), t.push(n(e.input, "readonly", (e) => e === "" || e ? r.add("readonly") : r.delete("readonly")), n(e.input, "checked", () => e.input.checked ? r.add("checked") : r.delete("checked")), n(e.input, "disabled", (e) => e === "" || e ? r.add("disabled") : r.delete("disabled")), n(e.input, "indeterminate", () => e.input.indeterminate ? r.add("indeterminate") : r.delete("indeterminate"))), t;
39
+ })), t;
35
40
  }
36
- function c(t) {
37
- return l(t), e(t, "disabled", () => l(t));
41
+ function l(t) {
42
+ return u(t), e(t, "disabled", () => u(t));
38
43
  }
39
- function l(e) {
44
+ function u(e) {
40
45
  Array.from(e.inputs).find((e) => e.disabled) ? e._internals.states.add("disabled") : e._internals.states.delete("disabled");
41
46
  }
42
- function u(e, n) {
43
- d(e, n.find((e) => !e.hidden));
47
+ function d(e, n) {
48
+ p(e, n.find((e) => !e.hidden));
44
49
  let a = [];
45
50
  return a.push(t(e, ["hidden", "status"], (t) => {
46
51
  let n = t.target;
47
- r(n, i) && d(e, n);
48
- })), e.shadowRoot.addEventListener("slotchange", () => {
52
+ r(n, i) && p(e, n);
53
+ })), a.push(f(e.shadowRoot, "slotchange", () => {
49
54
  let t = Array.from(e.querySelectorAll(i.metadata.tag)).find((e) => e.status && !e.hidden);
50
55
  e._internals.states.delete("error"), e._internals.states.delete("success"), t && e._internals.states.add(t.status);
51
- }), a;
56
+ })), a;
57
+ }
58
+ function f(e, t, n) {
59
+ return e.addEventListener(t, n), { disconnect: () => e.removeEventListener(t, n) };
52
60
  }
53
- function d(e, t) {
61
+ function p(e, t) {
54
62
  e._internals.states.delete("error"), e._internals.states.delete("success"), t?.status?.length && !t?.hidden && e._internals.states.add(t.status);
55
63
  }
56
- function f(e) {
64
+ function m(e) {
57
65
  e.filter((e) => e.hasAttribute("error")).forEach((e) => e.setAttribute("hidden", ""));
58
66
  }
59
- function p(e, t) {
67
+ function h(e, t) {
60
68
  t.find((t) => t.error && e.input.validity[t.error])?.removeAttribute("hidden");
61
69
  }
62
- function m(e, t) {
70
+ function g(e, t) {
63
71
  t.find((e) => e.error) && e.input.validity.valid && t.filter((t) => t.error && !e.input.validity[t.error]).forEach((e) => e.setAttribute("hidden", ""));
64
72
  }
65
73
  //#endregion
66
- export { a as inputQuery, c as setupControlGroupStates, s as setupControlStates, u as setupControlStatusStates, o as setupControlValidationStates };
74
+ export { a as inputQuery, l as setupControlGroupStates, s as setupControlStates, d as setupControlStatusStates, o as setupControlValidationStates };
67
75
 
68
76
  //# sourceMappingURL=states.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"states.js","names":[],"sources":["../../../src/forms/utils/states.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n getAttributeChanges,\n getAttributeListChanges,\n getElementUpdate,\n matchesElementName\n} from '@nvidia-elements/core/internal';\nimport type { ControlGroup } from '../control-group/control-group.js';\nimport { ControlMessage } from '../control-message/control-message.js';\nimport type { Control } from '../control/control.js';\n\nexport const inputQuery = 'input, select, selectmenu, textarea, [nve-control]';\n\n/**\n * Adds validation states to custom element\n * :state(valid) form control is in a valid state\n * :state(invalid) form control is in a invalid state\n */\n// eslint-disable-next-line max-lines-per-function\nexport function setupControlValidationStates(control: Control, messages: ControlMessage[]) {\n if (\n !control.input.form?.noValidate &&\n !control.input.formNoValidate &&\n !control.input.hasAttribute('formnovalidate')\n ) {\n hideAllValidationMessages(messages);\n\n /**\n * updateValidityState() logic triggered by input blur() or input() change events\n */\n const updateValidityState = () => {\n if (control.input.validity?.valid) {\n control._internals.states.delete('invalid');\n control._internals.states.add('valid');\n control.status = null!;\n }\n\n hideInactiveValidationMessages(control, messages);\n };\n\n const resetValidityState = () => {\n control.status = null!;\n control._internals.states.delete('valid');\n control._internals.states.delete('invalid');\n hideAllValidationMessages(messages);\n };\n\n control.input.addEventListener('blur', () => {\n control.input.checkValidity();\n updateValidityState();\n });\n\n control.input.addEventListener('input', () => {\n updateValidityState();\n });\n\n control.input.addEventListener('invalid', () => {\n if (messages.find(m => m.error)) {\n hideAllValidationMessages(messages);\n showActiveValidationMessages(control, messages);\n }\n\n control.status = 'error';\n control._internals.states.delete('valid');\n control._internals.states.add('invalid');\n });\n\n control.addEventListener('reset', () => resetValidityState());\n control.input.form?.addEventListener('reset', () => resetValidityState());\n }\n\n control.shadowRoot!.addEventListener('slotchange', () => {\n const current = Array.from(control.querySelectorAll<ControlMessage>(ControlMessage.metadata.tag));\n control._internals.states.delete('valid');\n control._internals.states.delete('invalid');\n if (current.find(m => !m.hidden && (m.status === 'error' || m.error))) {\n control._internals.states.add('invalid');\n } else {\n control._internals.states.add('valid');\n }\n });\n}\n\n/**\n * Adds control interaction states to custom element\n * :state(checked) form control is in a checked state\n * :state(disabled) form control is in a disabled state\n * :state(readonly) form control is in a readonly state\n * :state(touched) form control received focus and then blurred\n * :state(dirty) user modified the form control\n */\nexport function setupControlStates(control: Control) {\n const observers: MutationObserver[] = [];\n const states = control._internals.states;\n control.input.checked ? states.add('checked') : states.delete('checked');\n control.input.indeterminate ? states.add('indeterminate') : states.delete('indeterminate');\n control.input.addEventListener('focus', () => control._internals.states.add('focus'));\n control.input.addEventListener('input', () => control._internals.states.add('dirty'));\n control.input.addEventListener('blur', () => {\n control._internals.states.add('touched');\n control._internals.states.delete('focus');\n });\n\n control.input.getRootNode().addEventListener('change', (e: Event) => {\n if ((e.target as HTMLInputElement).name === control.input?.name) {\n control.input.checked ? states.add('checked') : states.delete('checked');\n }\n });\n\n control.input.form?.addEventListener('reset', () => {\n control._internals.states.delete('touched');\n control._internals.states.delete('dirty');\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n control.requestUpdate();\n });\n\n observers.push(\n getElementUpdate(control.input, 'readonly', value =>\n (value === '' ? true : value) ? states.add('readonly') : states.delete('readonly')\n ),\n getElementUpdate(control.input, 'checked', () =>\n control.input.checked ? states.add('checked') : states.delete('checked')\n ),\n getElementUpdate(control.input, 'disabled', value =>\n (value === '' ? true : value) ? states.add('disabled') : states.delete('disabled')\n ),\n getElementUpdate(control.input, 'indeterminate', () =>\n control.input.indeterminate ? states.add('indeterminate') : states.delete('indeterminate')\n )\n );\n return observers;\n}\n\n/**\n * Adds control group interaction states to custom element\n * :state(disabled) any form control within group is in a disabled state\n */\nexport function setupControlGroupStates(controlGroup: ControlGroup) {\n toggleControlGroupDisabledState(controlGroup);\n return getAttributeChanges(controlGroup, 'disabled', () => toggleControlGroupDisabledState(controlGroup));\n}\n\nfunction toggleControlGroupDisabledState(controlGroup: ControlGroup) {\n if (Array.from(controlGroup.inputs).find(i => i.disabled)) {\n controlGroup._internals.states.add('disabled');\n } else {\n controlGroup._internals.states.delete('disabled');\n }\n}\n\n/**\n * Adds control status states to custom element\n * :state(error) form control is in a error state\n * :state(success) form control is in a success state\n */\nexport function setupControlStatusStates(control: Control | ControlGroup, messages: ControlMessage[]) {\n updateControlStatusState(control, messages.find(m => !m.hidden)!);\n const observers: MutationObserver[] = [];\n observers.push(\n getAttributeListChanges(control, ['hidden', 'status'], mutation => {\n const target = mutation.target as ControlMessage;\n if (matchesElementName(target, ControlMessage)) {\n updateControlStatusState(control, target);\n }\n })\n );\n\n control.shadowRoot!.addEventListener('slotchange', () => {\n const current = Array.from(control.querySelectorAll<ControlMessage>(ControlMessage.metadata.tag));\n const message = current.find(m => m.status && !m.hidden);\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n if (message) {\n control._internals.states.add(message.status!);\n }\n });\n\n return observers;\n}\n\nexport function updateControlStatusState(control: Control | ControlGroup, message: ControlMessage) {\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n\n if (message?.status?.length && !message?.hidden) {\n control._internals.states.add(message.status);\n }\n}\n\nexport function showNonValidationMessages(messages: ControlMessage[]) {\n messages.filter(m => !m.hasAttribute('error')).forEach(m => m.removeAttribute('hidden'));\n}\n\nexport function hideAllValidationMessages(messages: ControlMessage[]) {\n messages.filter(m => m.hasAttribute('error')).forEach(m => m.setAttribute('hidden', ''));\n}\n\nexport function showActiveValidationMessages(control: Control, messages: ControlMessage[]) {\n messages.find(m => m.error && control.input.validity[m.error])?.removeAttribute('hidden');\n}\n\nexport function hideInactiveValidationMessages(control: Control, messages: ControlMessage[]) {\n if (messages.find(m => m.error) && control.input.validity.valid) {\n messages.filter(m => m.error && !control.input.validity[m.error!]).forEach(m => m.setAttribute('hidden', ''));\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"states.js","names":[],"sources":["../../../src/forms/utils/states.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n getAttributeChanges,\n getAttributeListChanges,\n getElementUpdate,\n matchesElementName\n} from '@nvidia-elements/core/internal';\nimport type { ControlGroup } from '../control-group/control-group.js';\nimport { ControlMessage } from '../control-message/control-message.js';\nimport type { Control } from '../control/control.js';\n\nexport const inputQuery = 'input, select, selectmenu, textarea, [nve-control]';\nexport interface ControlStateCleanup {\n disconnect: () => void;\n}\n\n/**\n * Adds validation states to custom element\n * :state(valid) form control is in a valid state\n * :state(invalid) form control is in a invalid state\n */\n// eslint-disable-next-line max-lines-per-function\nexport function setupControlValidationStates(control: Control, messages: ControlMessage[]) {\n const cleanups: ControlStateCleanup[] = [];\n\n if (\n !control.input.form?.noValidate &&\n !control.input.formNoValidate &&\n !control.input.hasAttribute('formnovalidate')\n ) {\n hideAllValidationMessages(messages);\n\n /**\n * updateValidityState() logic triggered by input blur() or input() change events\n */\n const updateValidityState = () => {\n if (control.input.validity?.valid) {\n control._internals.states.delete('invalid');\n control._internals.states.add('valid');\n control.status = null!;\n }\n\n hideInactiveValidationMessages(control, messages);\n };\n\n const resetValidityState = () => {\n control.status = null!;\n control._internals.states.delete('valid');\n control._internals.states.delete('invalid');\n hideAllValidationMessages(messages);\n };\n\n const onBlur = () => {\n control.input.checkValidity();\n updateValidityState();\n };\n\n const onInput = () => {\n updateValidityState();\n };\n\n const onInvalid = () => {\n if (messages.find(m => m.error)) {\n hideAllValidationMessages(messages);\n showActiveValidationMessages(control, messages);\n }\n\n control.status = 'error';\n control._internals.states.delete('valid');\n control._internals.states.add('invalid');\n };\n\n cleanups.push(\n addCleanupListener(control.input, 'blur', onBlur),\n addCleanupListener(control.input, 'input', onInput),\n addCleanupListener(control.input, 'invalid', onInvalid),\n addCleanupListener(control, 'reset', resetValidityState)\n );\n\n if (control.input.form) {\n cleanups.push(addCleanupListener(control.input.form, 'reset', resetValidityState));\n }\n }\n\n const onSlotChange = () => {\n const current = Array.from(control.querySelectorAll<ControlMessage>(ControlMessage.metadata.tag));\n control._internals.states.delete('valid');\n control._internals.states.delete('invalid');\n if (current.find(m => !m.hidden && (m.status === 'error' || m.error))) {\n control._internals.states.add('invalid');\n } else {\n control._internals.states.add('valid');\n }\n };\n cleanups.push(addCleanupListener(control.shadowRoot!, 'slotchange', onSlotChange));\n\n return cleanups;\n}\n\n/**\n * Adds control interaction states to custom element\n * :state(checked) form control is in a checked state\n * :state(disabled) form control is in a disabled state\n * :state(readonly) form control is in a readonly state\n * :state(touched) form control received focus and then blurred\n * :state(dirty) user modified the form control\n */\nexport function setupControlStates(control: Control) {\n const observers: ControlStateCleanup[] = [];\n const states = control._internals.states;\n control.input.checked ? states.add('checked') : states.delete('checked');\n control.input.indeterminate ? states.add('indeterminate') : states.delete('indeterminate');\n\n observers.push(...addControlInteractionListeners(control));\n observers.push(\n getElementUpdate(control.input, 'readonly', value =>\n (value === '' ? true : value) ? states.add('readonly') : states.delete('readonly')\n ),\n getElementUpdate(control.input, 'checked', () =>\n control.input.checked ? states.add('checked') : states.delete('checked')\n ),\n getElementUpdate(control.input, 'disabled', value =>\n (value === '' ? true : value) ? states.add('disabled') : states.delete('disabled')\n ),\n getElementUpdate(control.input, 'indeterminate', () =>\n control.input.indeterminate ? states.add('indeterminate') : states.delete('indeterminate')\n )\n );\n return observers;\n}\n\nfunction addControlInteractionListeners(control: Control): ControlStateCleanup[] {\n const cleanups: ControlStateCleanup[] = [];\n const states = control._internals.states;\n const onFocus = () => control._internals.states.add('focus');\n const onInput = () => control._internals.states.add('dirty');\n const onBlur = () => {\n control._internals.states.add('touched');\n control._internals.states.delete('focus');\n };\n\n const onRootChange = (e: Event) => {\n if ((e.target as HTMLInputElement).name === control.input?.name) {\n control.input.checked ? states.add('checked') : states.delete('checked');\n }\n };\n\n const onFormReset = () => {\n control._internals.states.delete('touched');\n control._internals.states.delete('dirty');\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n control.requestUpdate();\n };\n\n cleanups.push(\n addCleanupListener(control.input, 'focus', onFocus),\n addCleanupListener(control.input, 'input', onInput),\n addCleanupListener(control.input, 'blur', onBlur),\n addCleanupListener(control.input.getRootNode(), 'change', onRootChange)\n );\n\n if (control.input.form) {\n cleanups.push(addCleanupListener(control.input.form, 'reset', onFormReset));\n }\n\n return cleanups;\n}\n\n/**\n * Adds control group interaction states to custom element\n * :state(disabled) any form control within group is in a disabled state\n */\nexport function setupControlGroupStates(controlGroup: ControlGroup) {\n toggleControlGroupDisabledState(controlGroup);\n return getAttributeChanges(controlGroup, 'disabled', () => toggleControlGroupDisabledState(controlGroup));\n}\n\nfunction toggleControlGroupDisabledState(controlGroup: ControlGroup) {\n if (Array.from(controlGroup.inputs).find(i => i.disabled)) {\n controlGroup._internals.states.add('disabled');\n } else {\n controlGroup._internals.states.delete('disabled');\n }\n}\n\n/**\n * Adds control status states to custom element\n * :state(error) form control is in a error state\n * :state(success) form control is in a success state\n */\nexport function setupControlStatusStates(control: Control | ControlGroup, messages: ControlMessage[]) {\n updateControlStatusState(control, messages.find(m => !m.hidden)!);\n const observers: ControlStateCleanup[] = [];\n observers.push(\n getAttributeListChanges(control, ['hidden', 'status'], mutation => {\n const target = mutation.target as ControlMessage;\n if (matchesElementName(target, ControlMessage)) {\n updateControlStatusState(control, target);\n }\n })\n );\n\n const onSlotChange = () => {\n const current = Array.from(control.querySelectorAll<ControlMessage>(ControlMessage.metadata.tag));\n const message = current.find(m => m.status && !m.hidden);\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n if (message) {\n control._internals.states.add(message.status!);\n }\n };\n observers.push(addCleanupListener(control.shadowRoot!, 'slotchange', onSlotChange));\n\n return observers;\n}\n\nfunction addCleanupListener(target: EventTarget, type: string, listener: EventListener): ControlStateCleanup {\n target.addEventListener(type, listener);\n return {\n disconnect: () => target.removeEventListener(type, listener)\n };\n}\n\nexport function updateControlStatusState(control: Control | ControlGroup, message: ControlMessage) {\n control._internals.states.delete('error');\n control._internals.states.delete('success');\n\n if (message?.status?.length && !message?.hidden) {\n control._internals.states.add(message.status);\n }\n}\n\nexport function showNonValidationMessages(messages: ControlMessage[]) {\n messages.filter(m => !m.hasAttribute('error')).forEach(m => m.removeAttribute('hidden'));\n}\n\nexport function hideAllValidationMessages(messages: ControlMessage[]) {\n messages.filter(m => m.hasAttribute('error')).forEach(m => m.setAttribute('hidden', ''));\n}\n\nexport function showActiveValidationMessages(control: Control, messages: ControlMessage[]) {\n messages.find(m => m.error && control.input.validity[m.error])?.removeAttribute('hidden');\n}\n\nexport function hideInactiveValidationMessages(control: Control, messages: ControlMessage[]) {\n if (messages.find(m => m.error) && control.input.validity.valid) {\n messages.filter(m => m.error && !control.input.validity[m.error!]).forEach(m => m.setAttribute('hidden', ''));\n }\n}\n"],"mappings":"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"}
@@ -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.0.1"
13
+ version: "2.0.3"
14
14
  };
15
15
  }
16
16
  render() {
@@ -1,7 +1,7 @@
1
1
  import { appendRootNodeStyle as e } from "../../internal/utils/dom.js";
2
2
  import { attachInternals as t } from "../../internal/utils/a11y.js";
3
3
  import { useStyles as n } from "../../internal/styles/index.js";
4
- import { __decorate as r } from "../../_virtual/_@oxc-project_runtime@0.132.0/helpers/decorate.js";
4
+ import { __decorate as r } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
5
5
  import i from "./column.js";
6
6
  import { LitElement as a, html as o } from "lit";
7
7
  import { property as s } from "lit/decorators/property.js";
@@ -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.0.1"
16
+ version: "2.0.3"
17
17
  };
18
18
  }
19
19
  get #e() {
@@ -1,7 +1,7 @@
1
1
  import { attachInternals as e } from "../../internal/utils/a11y.js";
2
2
  import { hostAttr as t } from "../../internal/decorators/host-attr.js";
3
3
  import { useStyles as n } from "../../internal/styles/index.js";
4
- import { __decorate as r } from "../../_virtual/_@oxc-project_runtime@0.132.0/helpers/decorate.js";
4
+ import { __decorate as r } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
5
5
  import i from "./footer.js";
6
6
  import { LitElement as a, html as o } from "lit";
7
7
  //#region src/grid/footer/footer.ts
@@ -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.0.1"
18
+ version: "2.0.3"
19
19
  };
20
20
  }
21
21
  static {
@@ -4,7 +4,7 @@ import { keyNavigationGrid as r } from "../internal/controllers/keynav-grid.cont
4
4
  import { attachInternals as i } from "../internal/utils/a11y.js";
5
5
  import { stateScroll as a } from "../internal/controllers/state-scroll.controller.js";
6
6
  import { useStyles as o } from "../internal/styles/index.js";
7
- import { __decorate as s } from "../_virtual/_@oxc-project_runtime@0.132.0/helpers/decorate.js";
7
+ import { __decorate as s } from "../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
8
8
  import { GridPlaceholder as c } from "./placeholder/placeholder2.js";
9
9
  import { GridColumn as l } from "./column/column2.js";
10
10
  import { GridCell as u } from "./cell/cell2.js";
@@ -23,7 +23,7 @@ var y = class extends g {
23
23
  static {
24
24
  this.metadata = {
25
25
  tag: "nve-grid",
26
- version: "2.0.1",
26
+ version: "2.0.3",
27
27
  children: [
28
28
  d.metadata.tag,
29
29
  f.metadata.tag,
@@ -4,7 +4,7 @@ import { debounce as n } from "../../internal/utils/events.js";
4
4
  import { LogService as r } from "../../internal/services/log.service.js";
5
5
  import { attachInternals as i } from "../../internal/utils/a11y.js";
6
6
  import { useStyles as a } from "../../internal/styles/index.js";
7
- import { __decorate as o } from "../../_virtual/_@oxc-project_runtime@0.132.0/helpers/decorate.js";
7
+ import { __decorate as o } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
8
8
  import s from "./header.js";
9
9
  import { GridColumn as c } from "../column/column2.js";
10
10
  import { GridCell as l } from "../cell/cell2.js";
@@ -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.0.1",
22
+ version: "2.0.3",
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.0.1"
13
+ version: "2.0.3"
14
14
  };
15
15
  }
16
16
  render() {
@@ -2,7 +2,7 @@ import { audit as e } from "../../internal/controllers/audit.controller.js";
2
2
  import { attachInternals as t } from "../../internal/utils/a11y.js";
3
3
  import { stateSelected as n } from "../../internal/controllers/state-selected.controller.js";
4
4
  import { useStyles as r } from "../../internal/styles/index.js";
5
- import { __decorate as i } from "../../_virtual/_@oxc-project_runtime@0.132.0/helpers/decorate.js";
5
+ import { __decorate as i } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
6
6
  import { GridCell as a } from "../cell/cell2.js";
7
7
  import o from "./row.js";
8
8
  import { LitElement as s, html as c } from "lit";
@@ -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.0.1",
18
+ version: "2.0.3",
19
19
  children: [a.metadata.tag]
20
20
  };
21
21
  }
@@ -3,7 +3,7 @@ import { attachInternals as t } from "../internal/utils/a11y.js";
3
3
  import { useStyles as n } from "../internal/styles/index.js";
4
4
  import { ICON_IMPORTS as r } from "./icons.js";
5
5
  import i from "./icon.js";
6
- import { __decorate as a } from "../_virtual/_@oxc-project_runtime@0.132.0/helpers/decorate.js";
6
+ import { __decorate as a } from "../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
7
7
  import { LitElement as o, html as s, isServer as c } from "lit";
8
8
  import { property as l } from "lit/decorators/property.js";
9
9
  import { unsafeSVG as u } from "lit/directives/unsafe-svg.js";
@@ -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.0.1"
19
+ version: "2.0.3"
20
20
  };
21
21
  }
22
22
  static {
@@ -94,7 +94,7 @@ a([l({
94
94
  })], f.prototype, "name", void 0), a([d()], f.prototype, "svg", void 0);
95
95
  function p(t) {
96
96
  if (typeof globalThis.customElements?.get == "function") {
97
- let n = e(t.metadata.version), i = e("2.0.1");
97
+ let n = e(t.metadata.version), i = e("2.0.3");
98
98
  n.minor <= i.minor && n.major <= i.major && (t._icons = {
99
99
  ...t._icons,
100
100
  ...r
@@ -1,7 +1,7 @@
1
1
  import { removeEmptySlotWhitespace as e } from "../internal/utils/dom.js";
2
2
  import { scopedRegistry as t } from "../internal/decorators/scoped-registry.js";
3
3
  import { useStyles as n } from "../internal/styles/index.js";
4
- import { __decorate as r } from "../_virtual/_@oxc-project_runtime@0.132.0/helpers/decorate.js";
4
+ import { __decorate as r } from "../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
5
5
  import { Icon as i } from "../icon/icon2.js";
6
6
  import { Button as a } from "../button/button2.js";
7
7
  import o from "./icon-button.js";
@@ -15,7 +15,7 @@ var l = class extends a {
15
15
  static {
16
16
  this.metadata = {
17
17
  tag: "nve-icon-button",
18
- version: "2.0.1"
18
+ version: "2.0.3"
19
19
  };
20
20
  }
21
21
  static {
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.0.1", i = "@nvidia-elements";
5
+ var r = "2.0.3", 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.0.1"
14
+ version: "2.0.3"
15
15
  };
16
16
  }
17
17
  async connectedCallback() {
@@ -1,5 +1,5 @@
1
1
  import { useStyles as e } from "../internal/styles/index.js";
2
- import { __decorate as t } from "../_virtual/_@oxc-project_runtime@0.132.0/helpers/decorate.js";
2
+ import { __decorate as t } from "../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorate.js";
3
3
  import { Control as n } from "../forms/control/control2.js";
4
4
  import r from "./input.js";
5
5
  import { property as i } from "lit/decorators/property.js";
@@ -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.0.1"
17
+ version: "2.0.3"
18
18
  };
19
19
  }
20
20
  };
@@ -9,36 +9,37 @@ function h() {
9
9
  }
10
10
  var g = class {
11
11
  #e = [];
12
- get #t() {
12
+ #t;
13
+ get #n() {
13
14
  return {
14
15
  grid: this.host,
15
16
  ...this.host.keynavGridConfig
16
17
  };
17
18
  }
18
- get #n() {
19
- let e = Array.from(this.#t.rows);
20
- return this.#t.columnRow && e.unshift(this.#t.columnRow), e;
21
- }
22
19
  get #r() {
23
- return [...Array.from(this.#t.columns ?? []), ...Array.from(this.#t.cells)];
20
+ let e = Array.from(this.#n.rows);
21
+ return this.#n.columnRow && e.unshift(this.#n.columnRow), e;
22
+ }
23
+ get #i() {
24
+ return [...Array.from(this.#n.columns ?? []), ...Array.from(this.#n.cells)];
24
25
  }
25
26
  constructor(e) {
26
27
  this.host = e, this.host.addController(this);
27
28
  }
28
29
  async hostConnected() {
29
- await this.host.updateComplete, o(this.#r), this.#t.grid.addEventListener("keyup", (e) => this.#s(e)), this.#t.grid.addEventListener("keydown", (e) => this.#a(e)), this.#t.grid.addEventListener("mouseup", (e) => this.#i(e)), this.#e.push(t(this.host, n(() => o(this.#r), 500)));
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))));
30
31
  }
31
32
  hostDisconnected() {
32
- this.#e.forEach((e) => e?.disconnect());
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;
33
34
  }
34
- #i(e) {
35
+ #a(e) {
35
36
  if (!p(e)) {
36
- let t = e.composedPath()[0], n = this.#r.find((e) => e === t) ? t : null;
37
- n && this.#o(e, n);
37
+ let t = e.composedPath()[0], n = this.#i.find((e) => e === t) ? t : null;
38
+ n && this.#s(e, n);
38
39
  }
39
40
  }
40
- #a(t) {
41
- let n = Array.from(this.#n), i = Array.from(this.#r);
41
+ #o(t) {
42
+ let n = Array.from(this.#r), i = Array.from(this.#i);
42
43
  if (e.state.env !== "production" && f(n)) {
43
44
  r.warn("Invalid grid structure, all rows must have the same number of cells");
44
45
  return;
@@ -49,11 +50,11 @@ var g = class {
49
50
  ctrlKey: t.ctrlKey,
50
51
  dir: this.host.dir
51
52
  }), a = Array.from(u(n[r])).filter((e) => !!i.find((t) => t === e))[e];
52
- this.#o(t, a), t.preventDefault();
53
+ this.#s(t, a), t.preventDefault();
53
54
  }
54
55
  }
55
- #o(e, t) {
56
- c(this.#r, t);
56
+ #s(e, t) {
57
+ c(this.#i, t);
57
58
  let n = d(t), r = n.filter((e) => s(e));
58
59
  r.length === 1 && n.length === 1 ? i(r[0]) : i(t);
59
60
  let a = {
@@ -67,10 +68,13 @@ var g = class {
67
68
  detail: a
68
69
  }));
69
70
  }
70
- #s(e) {
71
- let t = Array.from(this.#r).find((e) => e.tabIndex === 0);
71
+ #c(e) {
72
+ let t = Array.from(this.#i).find((e) => e.tabIndex === 0);
72
73
  e.code === "Escape" && t?.focus(), e.code === "Enter" && t === e.composedPath()[0] && d(t)[0]?.focus();
73
74
  }
75
+ #l = (e) => this.#c(e);
76
+ #u = (e) => this.#o(e);
77
+ #d = (e) => this.#a(e);
74
78
  };
75
79
  function _(e, t) {
76
80
  let n = t === "rtl" ? l.ArrowRight : l.ArrowLeft, r = t === "rtl" ? l.ArrowLeft : l.ArrowRight;
@@ -1 +1 @@
1
- {"version":3,"file":"keynav-grid.controller.js","names":["#config","#hostRows","#hostCells","#updateCellActivation","#keynavCell","#clickCell","#observers","#setActiveCell"],"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\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 initializeKeyListItems(this.#hostCells);\n this.#config.grid.addEventListener('keyup', (e: KeyboardEvent) => this.#updateCellActivation(e));\n this.#config.grid.addEventListener('keydown', (e: KeyboardEvent) => this.#keynavCell(e));\n this.#config.grid.addEventListener('mouseup', (e: MouseEvent) => this.#clickCell(e));\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 }\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\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":["#config","#hostRows","#hostCells","#grid","#onKeyUp","#onKeyDown","#onMouseUp","#observers","#setActiveCell","#updateCellActivation","#keynavCell","#clickCell"],"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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"}
@@ -18,6 +18,7 @@ export declare class KeyNavigationListController<T extends ReactiveElement & Key
18
18
  private host;
19
19
  constructor(host: T);
20
20
  hostConnected(): Promise<void>;
21
+ hostDisconnected(): void;
21
22
  }
22
23
  interface KeyListConfig {
23
24
  code: KeynavCode;
@@ -23,7 +23,10 @@ var o = class {
23
23
  return this.host.hasAttribute("nve-keynav-disabled");
24
24
  }
25
25
  async hostConnected() {
26
- await this.host.updateComplete, this.#n(), this.host.addEventListener("pointerup", (e) => this.#r(e)), this.host.addEventListener("keydown", (e) => this.#i(e));
26
+ await this.host.updateComplete, this.host.isConnected && (this.#n(), this.host.addEventListener("pointerup", this.#s), this.host.addEventListener("keydown", this.#c));
27
+ }
28
+ hostDisconnected() {
29
+ this.host.removeEventListener("pointerup", this.#s), this.host.removeEventListener("keydown", this.#c);
27
30
  }
28
31
  #n() {
29
32
  let { manageFocus: e, manageTabindex: n, items: r } = this.#e;
@@ -67,6 +70,8 @@ var o = class {
67
70
  detail: c
68
71
  }));
69
72
  }
73
+ #s = (e) => this.#r(e);
74
+ #c = (e) => this.#i(e);
70
75
  };
71
76
  function s(e) {
72
77
  let { code: t, layout: n, dir: i } = e, a = i === "rtl" ? r.ArrowRight : r.ArrowLeft, o = i === "rtl" ? r.ArrowLeft : r.ArrowRight;
@@ -1 +1 @@
1
- {"version":3,"file":"keynav-list.controller.js","names":["#config","#keynavDisabled","#initializeTabIndex","#clickItem","#focusItem","#getActiveItem","#setActiveItem"],"sources":["../../../src/internal/controllers/keynav-list.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 { focusElement, initializeKeyListItems, setActiveKeyListItem } from '../utils/focus.js';\nimport { KeynavCode, validKeyNavigationCode } from '../utils/dom.js';\n\nexport interface KeynavListConfig {\n items: NodeListOf<HTMLElement> | HTMLElement[];\n layout?: 'both' | 'horizontal' | 'vertical';\n manageFocus?: boolean;\n manageTabindex?: boolean;\n loop?: boolean;\n dir?: string | null;\n}\n\nexport interface KeynavListElement {\n keynavListConfig: KeynavListConfig;\n}\n\n/** https://webaim.org/techniques/keyboard/ */\nexport function keyNavigationList<T extends ReactiveElement & KeynavListElement>(): ClassDecorator {\n return (target: LegacyDecoratorTarget) =>\n target.addInitializer!((instance: T) => new KeyNavigationListController(instance));\n}\n\nexport class KeyNavigationListController<T extends ReactiveElement & KeynavListElement> implements ReactiveController {\n get #config(): KeynavListConfig & { items: HTMLElement[] } {\n return {\n layout: 'horizontal',\n manageFocus: true,\n manageTabindex: true,\n loop: false,\n dir: this.host.getAttribute('rtl'),\n ...this.host.keynavListConfig,\n items: Array.from(this.host.keynavListConfig.items).filter(\n (i: HTMLElement & { disabled?: boolean }) => !i.disabled\n )\n };\n }\n\n constructor(private host: T) {\n this.host.addController(this);\n }\n\n /** @private attr nve-keynav-disabled is an internal API for advanced use cases only */\n get #keynavDisabled() {\n return this.host.hasAttribute('nve-keynav-disabled');\n }\n\n async hostConnected() {\n await this.host.updateComplete;\n this.#initializeTabIndex();\n this.host.addEventListener('pointerup', (e: PointerEvent) => this.#clickItem(e));\n this.host.addEventListener('keydown', (e: KeyboardEvent) => this.#focusItem(e));\n }\n\n #initializeTabIndex() {\n const { manageFocus, manageTabindex, items } = this.#config;\n if (manageFocus && manageTabindex && !this.#keynavDisabled) {\n initializeKeyListItems(items);\n }\n }\n\n #clickItem(e: PointerEvent) {\n const item = this.#getActiveItem(e, this.#config.items);\n if (item) {\n this.#setActiveItem(e, item);\n }\n }\n\n #focusItem(e: KeyboardEvent) {\n if (validKeyNavigationCode(e) && !this.#keynavDisabled) {\n const { loop, layout, dir, items } = this.#config;\n const activeItem = this.#getActiveItem(e, items);\n if (activeItem) {\n const { next, previous } = getNextKeyListItem(activeItem, Array.from(items), {\n loop,\n layout,\n dir,\n code: e.code as KeynavCode\n });\n\n if (next !== previous) {\n this.#setActiveItem(e, items[next]!, items[previous]);\n }\n }\n }\n }\n\n #getActiveItem(e: Event, items: HTMLElement[]) {\n const focusedElement = e.composedPath()[0] as HTMLElement;\n return items.find(i => i === focusedElement) ? focusedElement : null;\n }\n\n #setActiveItem(e: KeyboardEvent | PointerEvent, activeItem: HTMLElement, previousItem?: HTMLElement) {\n const { manageFocus, manageTabindex, items } = this.#config;\n if (manageFocus) {\n if (manageTabindex) {\n setActiveKeyListItem(items, activeItem);\n }\n\n focusElement(activeItem);\n e.preventDefault();\n }\n\n const detail = {\n activeItem,\n previousItem,\n code: e instanceof KeyboardEvent ? e.code : null,\n metaKey: e.ctrlKey || e.metaKey,\n items\n };\n activeItem.dispatchEvent(new CustomEvent('nve-key-change', { bubbles: true, composed: true, detail }));\n }\n}\n\ninterface KeyListConfig {\n code: KeynavCode;\n loop?: boolean;\n layout?: 'horizontal' | 'vertical' | 'both';\n dir: string | null | undefined;\n}\n\nfunction resolveArrowDirection(config: KeyListConfig): 'backward' | 'forward' | null {\n const { code, layout, dir } = config;\n const start = dir === 'rtl' ? KeynavCode.ArrowRight : KeynavCode.ArrowLeft;\n const end = dir === 'rtl' ? KeynavCode.ArrowLeft : KeynavCode.ArrowRight;\n\n if (layout !== 'horizontal') {\n if (code === KeynavCode.ArrowUp) return 'backward';\n if (code === KeynavCode.ArrowDown) return 'forward';\n }\n\n if (layout !== 'vertical') {\n if (code === start) return 'backward';\n if (code === end) return 'forward';\n }\n\n return null;\n}\n\nfunction resolveSpecialKey(code: KeynavCode): 'home' | 'end' | 'pageup' | 'pagedown' | null {\n if (code === KeynavCode.End) return 'end';\n if (code === KeynavCode.Home) return 'home';\n if (code === KeynavCode.PageUp) return 'pageup';\n if (code === KeynavCode.PageDown) return 'pagedown';\n return null;\n}\n\nfunction navigateWithLoop(current: number, step: number, options: { limit: number; loop: boolean | undefined }) {\n const { limit, loop } = options;\n const next = current + step;\n if (next >= 0 && next <= limit) return next;\n return loop ? (step < 0 ? limit : 0) : current;\n}\n\nexport function getNextKeyListItem(item: HTMLElement, items: HTMLElement[], config: KeyListConfig) {\n let next = items.indexOf(item);\n const previous = next;\n const itemCount = items.length - 1;\n const direction = resolveArrowDirection(config);\n\n switch (direction ?? resolveSpecialKey(config.code)) {\n case 'backward':\n next = navigateWithLoop(next, -1, { limit: itemCount, loop: config.loop });\n break;\n case 'forward':\n next = navigateWithLoop(next, 1, { limit: itemCount, loop: config.loop });\n break;\n case 'end':\n next = itemCount;\n break;\n case 'home':\n next = 0;\n break;\n case 'pageup':\n next = Math.max(0, next - 4);\n break;\n case 'pagedown':\n next = Math.min(itemCount, next + 4);\n break;\n case null:\n break;\n }\n\n return { next, previous };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"keynav-list.controller.js","names":["#config","#keynavDisabled","#initializeTabIndex","#onPointerUp","#onKeyDown","#getActiveItem","#setActiveItem","#clickItem","#focusItem"],"sources":["../../../src/internal/controllers/keynav-list.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 { focusElement, initializeKeyListItems, setActiveKeyListItem } from '../utils/focus.js';\nimport { KeynavCode, validKeyNavigationCode } from '../utils/dom.js';\n\nexport interface KeynavListConfig {\n items: NodeListOf<HTMLElement> | HTMLElement[];\n layout?: 'both' | 'horizontal' | 'vertical';\n manageFocus?: boolean;\n manageTabindex?: boolean;\n loop?: boolean;\n dir?: string | null;\n}\n\nexport interface KeynavListElement {\n keynavListConfig: KeynavListConfig;\n}\n\n/** https://webaim.org/techniques/keyboard/ */\nexport function keyNavigationList<T extends ReactiveElement & KeynavListElement>(): ClassDecorator {\n return (target: LegacyDecoratorTarget) =>\n target.addInitializer!((instance: T) => new KeyNavigationListController(instance));\n}\n\nexport class KeyNavigationListController<T extends ReactiveElement & KeynavListElement> implements ReactiveController {\n get #config(): KeynavListConfig & { items: HTMLElement[] } {\n return {\n layout: 'horizontal',\n manageFocus: true,\n manageTabindex: true,\n loop: false,\n dir: this.host.getAttribute('rtl'),\n ...this.host.keynavListConfig,\n items: Array.from(this.host.keynavListConfig.items).filter(\n (i: HTMLElement & { disabled?: boolean }) => !i.disabled\n )\n };\n }\n\n constructor(private host: T) {\n this.host.addController(this);\n }\n\n /** @private attr nve-keynav-disabled is an internal API for advanced use cases only */\n get #keynavDisabled() {\n return this.host.hasAttribute('nve-keynav-disabled');\n }\n\n async hostConnected() {\n await this.host.updateComplete;\n if (!this.host.isConnected) return;\n this.#initializeTabIndex();\n this.host.addEventListener('pointerup', this.#onPointerUp);\n this.host.addEventListener('keydown', this.#onKeyDown);\n }\n\n hostDisconnected() {\n this.host.removeEventListener('pointerup', this.#onPointerUp);\n this.host.removeEventListener('keydown', this.#onKeyDown);\n }\n\n #initializeTabIndex() {\n const { manageFocus, manageTabindex, items } = this.#config;\n if (manageFocus && manageTabindex && !this.#keynavDisabled) {\n initializeKeyListItems(items);\n }\n }\n\n #clickItem(e: PointerEvent) {\n const item = this.#getActiveItem(e, this.#config.items);\n if (item) {\n this.#setActiveItem(e, item);\n }\n }\n\n #focusItem(e: KeyboardEvent) {\n if (validKeyNavigationCode(e) && !this.#keynavDisabled) {\n const { loop, layout, dir, items } = this.#config;\n const activeItem = this.#getActiveItem(e, items);\n if (activeItem) {\n const { next, previous } = getNextKeyListItem(activeItem, Array.from(items), {\n loop,\n layout,\n dir,\n code: e.code as KeynavCode\n });\n\n if (next !== previous) {\n this.#setActiveItem(e, items[next]!, items[previous]);\n }\n }\n }\n }\n\n #getActiveItem(e: Event, items: HTMLElement[]) {\n const focusedElement = e.composedPath()[0] as HTMLElement;\n return items.find(i => i === focusedElement) ? focusedElement : null;\n }\n\n #setActiveItem(e: KeyboardEvent | PointerEvent, activeItem: HTMLElement, previousItem?: HTMLElement) {\n const { manageFocus, manageTabindex, items } = this.#config;\n if (manageFocus) {\n if (manageTabindex) {\n setActiveKeyListItem(items, activeItem);\n }\n\n focusElement(activeItem);\n e.preventDefault();\n }\n\n const detail = {\n activeItem,\n previousItem,\n code: e instanceof KeyboardEvent ? e.code : null,\n metaKey: e.ctrlKey || e.metaKey,\n items\n };\n activeItem.dispatchEvent(new CustomEvent('nve-key-change', { bubbles: true, composed: true, detail }));\n }\n\n #onPointerUp = (e: PointerEvent) => this.#clickItem(e);\n\n #onKeyDown = (e: KeyboardEvent) => this.#focusItem(e);\n}\n\ninterface KeyListConfig {\n code: KeynavCode;\n loop?: boolean;\n layout?: 'horizontal' | 'vertical' | 'both';\n dir: string | null | undefined;\n}\n\nfunction resolveArrowDirection(config: KeyListConfig): 'backward' | 'forward' | null {\n const { code, layout, dir } = config;\n const start = dir === 'rtl' ? KeynavCode.ArrowRight : KeynavCode.ArrowLeft;\n const end = dir === 'rtl' ? KeynavCode.ArrowLeft : KeynavCode.ArrowRight;\n\n if (layout !== 'horizontal') {\n if (code === KeynavCode.ArrowUp) return 'backward';\n if (code === KeynavCode.ArrowDown) return 'forward';\n }\n\n if (layout !== 'vertical') {\n if (code === start) return 'backward';\n if (code === end) return 'forward';\n }\n\n return null;\n}\n\nfunction resolveSpecialKey(code: KeynavCode): 'home' | 'end' | 'pageup' | 'pagedown' | null {\n if (code === KeynavCode.End) return 'end';\n if (code === KeynavCode.Home) return 'home';\n if (code === KeynavCode.PageUp) return 'pageup';\n if (code === KeynavCode.PageDown) return 'pagedown';\n return null;\n}\n\nfunction navigateWithLoop(current: number, step: number, options: { limit: number; loop: boolean | undefined }) {\n const { limit, loop } = options;\n const next = current + step;\n if (next >= 0 && next <= limit) return next;\n return loop ? (step < 0 ? limit : 0) : current;\n}\n\nexport function getNextKeyListItem(item: HTMLElement, items: HTMLElement[], config: KeyListConfig) {\n let next = items.indexOf(item);\n const previous = next;\n const itemCount = items.length - 1;\n const direction = resolveArrowDirection(config);\n\n switch (direction ?? resolveSpecialKey(config.code)) {\n case 'backward':\n next = navigateWithLoop(next, -1, { limit: itemCount, loop: config.loop });\n break;\n case 'forward':\n next = navigateWithLoop(next, 1, { limit: itemCount, loop: config.loop });\n break;\n case 'end':\n next = itemCount;\n break;\n case 'home':\n next = 0;\n break;\n case 'pageup':\n next = Math.max(0, next - 4);\n break;\n case 'pagedown':\n next = Math.min(itemCount, next + 4);\n break;\n case null:\n break;\n }\n\n return { next, previous };\n}\n"],"mappings":"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"}