@nvidia-elements/core 0.0.9 → 0.0.11

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 (204) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/accordion/accordion.examples.json +11 -11
  3. package/dist/accordion/accordion2.js +4 -4
  4. package/dist/alert/alert-group2.js +1 -1
  5. package/dist/alert/alert.examples.json +12 -12
  6. package/dist/alert/alert2.js +1 -1
  7. package/dist/avatar/avatar-group2.js +1 -1
  8. package/dist/avatar/avatar.examples.json +6 -6
  9. package/dist/avatar/avatar2.js +1 -1
  10. package/dist/badge/badge.examples.json +12 -12
  11. package/dist/badge/badge2.js +1 -1
  12. package/dist/breadcrumb/breadcrumb.examples.json +3 -3
  13. package/dist/breadcrumb/breadcrumb2.js +1 -1
  14. package/dist/bundles/index.d.ts +1 -0
  15. package/dist/bundles/index.js +3 -3
  16. package/dist/button/button.examples.json +24 -24
  17. package/dist/button/button2.js +1 -1
  18. package/dist/button-group/button-group.examples.json +11 -11
  19. package/dist/button-group/button-group2.js +1 -1
  20. package/dist/card/card.examples.json +10 -10
  21. package/dist/card/card2.js +4 -4
  22. package/dist/chat-message/chat-message.examples.json +7 -7
  23. package/dist/chat-message/chat-message2.js +1 -1
  24. package/dist/checkbox/checkbox-group2.js +1 -1
  25. package/dist/checkbox/checkbox.examples.json +7 -7
  26. package/dist/checkbox/checkbox2.js +1 -1
  27. package/dist/color/color.examples.json +4 -4
  28. package/dist/color/color2.js +1 -1
  29. package/dist/combobox/combobox.examples.json +24 -24
  30. package/dist/combobox/combobox2.js +1 -1
  31. package/dist/copy-button/copy-button.examples.json +9 -9
  32. package/dist/copy-button/copy-button2.js +1 -1
  33. package/dist/custom-elements-jsx.d.ts +2 -0
  34. package/dist/custom-elements-vue.d.ts +2 -0
  35. package/dist/custom-elements.json +35 -77
  36. package/dist/data.html.json +3 -1
  37. package/dist/date/date.examples.json +7 -7
  38. package/dist/date/date2.js +1 -1
  39. package/dist/datetime/datetime.examples.json +4 -4
  40. package/dist/datetime/datetime2.js +1 -1
  41. package/dist/dialog/dialog-footer2.js +1 -1
  42. package/dist/dialog/dialog-header2.js +1 -1
  43. package/dist/dialog/dialog.examples.json +21 -21
  44. package/dist/dialog/dialog2.js +1 -1
  45. package/dist/divider/divider.examples.json +5 -5
  46. package/dist/divider/divider2.js +1 -1
  47. package/dist/dot/dot.examples.json +5 -5
  48. package/dist/dot/dot2.js +1 -1
  49. package/dist/drawer/drawer-content2.js +1 -1
  50. package/dist/drawer/drawer-footer2.js +1 -1
  51. package/dist/drawer/drawer-header2.js +1 -1
  52. package/dist/drawer/drawer.examples.json +13 -13
  53. package/dist/drawer/drawer2.js +1 -1
  54. package/dist/dropdown/dropdown-footer2.js +1 -1
  55. package/dist/dropdown/dropdown-header2.js +1 -1
  56. package/dist/dropdown/dropdown.examples.json +14 -14
  57. package/dist/dropdown/dropdown2.js +1 -1
  58. package/dist/dropdown-group/dropdown-group.examples.json +4 -4
  59. package/dist/dropdown-group/dropdown-group.js +1 -1
  60. package/dist/dropzone/dropzone.examples.json +3 -3
  61. package/dist/dropzone/dropzone2.js +1 -1
  62. package/dist/file/file.examples.json +3 -3
  63. package/dist/file/file2.js +1 -1
  64. package/dist/format-datetime/format-datetime.examples.json +9 -9
  65. package/dist/format-datetime/format-datetime2.js +1 -1
  66. package/dist/format-relative-time/format-relative-time.examples.json +7 -7
  67. package/dist/format-relative-time/format-relative-time2.js +1 -1
  68. package/dist/forms/actions.examples.json +3 -3
  69. package/dist/forms/control/control.examples.json +11 -11
  70. package/dist/forms/control/control2.js +1 -1
  71. package/dist/forms/control-group/control-group2.js +1 -1
  72. package/dist/forms/control-message/control-message2.js +1 -1
  73. package/dist/forms/forms.examples.json +8 -8
  74. package/dist/forms/validation.examples.json +5 -5
  75. package/dist/grid/cell/cell2.js +1 -1
  76. package/dist/grid/column/column2.js +1 -1
  77. package/dist/grid/footer/footer2.js +1 -1
  78. package/dist/grid/grid.examples.js.map +1 -1
  79. package/dist/grid/grid.examples.json +45 -45
  80. package/dist/grid/grid2.js +1 -1
  81. package/dist/grid/header/header2.js +2 -2
  82. package/dist/grid/header/header2.js.map +1 -1
  83. package/dist/grid/placeholder/placeholder2.js +1 -1
  84. package/dist/grid/row/row2.js +1 -1
  85. package/dist/icon/icon.examples.json +8 -8
  86. package/dist/icon/icon2.js +2 -2
  87. package/dist/icon/icons/stop.js +6 -0
  88. package/dist/icon/icons/stop.js.map +1 -0
  89. package/dist/icon/icons.d.ts +1 -0
  90. package/dist/icon/icons.js +1 -0
  91. package/dist/icon/icons.js.map +1 -1
  92. package/dist/icon/server.js +1 -0
  93. package/dist/icon/server.js.map +1 -1
  94. package/dist/icon-button/icon-button.examples.json +13 -13
  95. package/dist/icon-button/icon-button2.js +1 -1
  96. package/dist/index.js +1 -1
  97. package/dist/input/input-group.examples.json +2 -2
  98. package/dist/input/input-group2.js +1 -1
  99. package/dist/input/input.examples.json +8 -8
  100. package/dist/input/input2.js +1 -1
  101. package/dist/internal/controllers/i18n.controller.examples.json +1 -1
  102. package/dist/internal/controllers/keynav-grid.controller.examples.json +2 -2
  103. package/dist/internal/controllers/keynav-grid.controller.js +15 -7
  104. package/dist/internal/controllers/keynav-grid.controller.js.map +1 -1
  105. package/dist/internal/controllers/keynav-list.controller.examples.json +4 -4
  106. package/dist/internal/controllers/keynav-list.controller.js +11 -5
  107. package/dist/internal/controllers/keynav-list.controller.js.map +1 -1
  108. package/dist/internal/controllers/popover.examples.json +8 -8
  109. package/dist/internal/controllers/type-button.controller.examples.json +1 -1
  110. package/dist/internal/controllers/type-popover.controller.examples.json +2 -2
  111. package/dist/internal/controllers/type-touch.controller.examples.json +1 -1
  112. package/dist/internal/services/global.service.js +1 -1
  113. package/dist/logo/logo.examples.json +6 -6
  114. package/dist/logo/logo2.js +1 -1
  115. package/dist/menu/menu-item2.js +1 -1
  116. package/dist/menu/menu.examples.json +15 -15
  117. package/dist/menu/menu2.js +1 -1
  118. package/dist/month/month.examples.json +4 -4
  119. package/dist/month/month2.js +1 -1
  120. package/dist/notification/notification-group2.js +1 -1
  121. package/dist/notification/notification.examples.json +15 -15
  122. package/dist/notification/notification2.js +1 -1
  123. package/dist/page/page-panel/page-panel-content2.js +1 -1
  124. package/dist/page/page-panel/page-panel-footer2.js +1 -1
  125. package/dist/page/page-panel/page-panel-header2.js +1 -1
  126. package/dist/page/page-panel/page-panel2.js +1 -1
  127. package/dist/page/page.examples.js.map +1 -1
  128. package/dist/page/page.examples.json +36 -34
  129. package/dist/page/page2.js +1 -1
  130. package/dist/page-header/page-header.examples.json +9 -9
  131. package/dist/page-header/page-header2.js +1 -1
  132. package/dist/page-loader/page-loader.examples.json +2 -2
  133. package/dist/page-loader/page-loader2.js +1 -1
  134. package/dist/pagination/pagination.examples.json +16 -16
  135. package/dist/pagination/pagination2.js +1 -1
  136. package/dist/panel/panel.examples.json +7 -7
  137. package/dist/panel/panel2.js +4 -4
  138. package/dist/password/password.examples.json +3 -3
  139. package/dist/password/password2.js +1 -1
  140. package/dist/preferences-input/preferences-input.examples.json +3 -3
  141. package/dist/preferences-input/preferences-input2.js +1 -1
  142. package/dist/progress-bar/progress-bar.examples.js.map +1 -1
  143. package/dist/progress-bar/progress-bar.examples.json +9 -9
  144. package/dist/progress-bar/progress-bar2.js +1 -1
  145. package/dist/progress-ring/progress-ring.examples.json +8 -8
  146. package/dist/progress-ring/progress-ring2.js +1 -1
  147. package/dist/progressive-filter-chip/progressive-filter-chip.examples.json +7 -7
  148. package/dist/progressive-filter-chip/progressive-filter-chip2.js +1 -1
  149. package/dist/pulse/pulse.examples.json +4 -4
  150. package/dist/pulse/pulse2.js +1 -1
  151. package/dist/radio/radio-group2.js +1 -1
  152. package/dist/radio/radio.examples.json +5 -5
  153. package/dist/radio/radio2.js +1 -1
  154. package/dist/range/range.examples.json +9 -9
  155. package/dist/range/range2.js +1 -1
  156. package/dist/resize-handle/resize-handle.examples.json +7 -7
  157. package/dist/resize-handle/resize-handle2.js +1 -1
  158. package/dist/search/search.examples.json +5 -5
  159. package/dist/search/search2.js +1 -1
  160. package/dist/select/select.examples.json +18 -18
  161. package/dist/select/select2.js +1 -1
  162. package/dist/skeleton/skeleton.examples.json +4 -4
  163. package/dist/skeleton/skeleton2.js +1 -1
  164. package/dist/sort-button/sort-button.examples.json +3 -3
  165. package/dist/sort-button/sort-button2.js +1 -1
  166. package/dist/sparkline/sparkline.examples.json +13 -13
  167. package/dist/sparkline/sparkline.utils.d.ts +26 -5
  168. package/dist/sparkline/sparkline.utils.js +30 -30
  169. package/dist/sparkline/sparkline.utils.js.map +1 -1
  170. package/dist/sparkline/sparkline2.js +21 -6
  171. package/dist/sparkline/sparkline2.js.map +1 -1
  172. package/dist/star-rating/star-rating.examples.json +4 -4
  173. package/dist/star-rating/star-rating2.js +1 -1
  174. package/dist/steps/steps.examples.json +5 -5
  175. package/dist/steps/steps2.js +2 -2
  176. package/dist/switch/switch-group2.js +1 -1
  177. package/dist/switch/switch.examples.json +7 -7
  178. package/dist/switch/switch2.js +1 -1
  179. package/dist/tabs/tabs-group2.js +9 -6
  180. package/dist/tabs/tabs-group2.js.map +1 -1
  181. package/dist/tabs/tabs.examples.json +14 -14
  182. package/dist/tabs/tabs2.js +2 -2
  183. package/dist/tag/tag.examples.json +8 -8
  184. package/dist/tag/tag2.js +1 -1
  185. package/dist/textarea/textarea.examples.json +5 -5
  186. package/dist/textarea/textarea2.js +1 -1
  187. package/dist/time/time.examples.json +4 -4
  188. package/dist/time/time2.js +1 -1
  189. package/dist/toast/toast.examples.json +11 -11
  190. package/dist/toast/toast2.js +1 -1
  191. package/dist/toggletip/toggletip-footer2.js +1 -1
  192. package/dist/toggletip/toggletip-header2.js +1 -1
  193. package/dist/toggletip/toggletip.examples.json +12 -12
  194. package/dist/toggletip/toggletip2.js +1 -1
  195. package/dist/toolbar/toolbar.examples.json +8 -8
  196. package/dist/toolbar/toolbar2.js +1 -1
  197. package/dist/tooltip/tooltip.examples.json +22 -22
  198. package/dist/tooltip/tooltip2.js +1 -1
  199. package/dist/tree/tree-node2.js +1 -1
  200. package/dist/tree/tree.examples.json +13 -13
  201. package/dist/tree/tree2.js +1 -1
  202. package/dist/week/week.examples.json +5 -5
  203. package/dist/week/week2.js +1 -1
  204. package/package.json +3 -3
@@ -3,7 +3,7 @@
3
3
  "entrypoint": "@nvidia-elements/core/icon-button/icon-button.examples.json",
4
4
  "items": [
5
5
  {
6
- "id": "core-icon-button_default",
6
+ "id": "icon-button",
7
7
  "name": "Default",
8
8
  "template": "<nve-icon-button icon-name=\"menu\"></nve-icon-button>\n",
9
9
  "summary": "Basic icon button for compact actions and toolbar controls with minimal visual footprint.",
@@ -12,7 +12,7 @@
12
12
  "tags": []
13
13
  },
14
14
  {
15
- "id": "core-icon-button_interactions",
15
+ "id": "icon-button-interactions",
16
16
  "name": "Interactions",
17
17
  "template": "<nve-icon-button icon-name=\"menu\"></nve-icon-button>\n<nve-icon-button interaction=\"emphasis\" icon-name=\"menu\"></nve-icon-button>\n<nve-icon-button interaction=\"destructive\" icon-name=\"menu\"></nve-icon-button>\n<nve-icon-button disabled icon-name=\"menu\"></nve-icon-button>\n",
18
18
  "summary": "Icon buttons with different interaction styles including default, emphasis, destructive, and disabled states.",
@@ -21,7 +21,7 @@
21
21
  "tags": []
22
22
  },
23
23
  {
24
- "id": "core-icon-button_size",
24
+ "id": "icon-button-size",
25
25
  "name": "Size",
26
26
  "template": "<nve-icon-button size=\"sm\" icon-name=\"menu\"></nve-icon-button>\n<nve-icon-button icon-name=\"menu\"></nve-icon-button>\n<nve-icon-button size=\"lg\" icon-name=\"menu\"></nve-icon-button>\n",
27
27
  "summary": "Icon buttons in different sizes (small, medium, large) for varying contexts and visual hierarchy.",
@@ -32,7 +32,7 @@
32
32
  ]
33
33
  },
34
34
  {
35
- "id": "core-icon-button_flat-interactions",
35
+ "id": "icon-button-flat-interactions",
36
36
  "name": "FlatInteractions",
37
37
  "template": "<nve-icon-button container=\"flat\" icon-name=\"menu\"></nve-icon-button>\n<nve-icon-button container=\"flat\" interaction=\"emphasis\" icon-name=\"menu\"></nve-icon-button>\n<nve-icon-button container=\"flat\" interaction=\"destructive\" icon-name=\"menu\"></nve-icon-button>\n<nve-icon-button container=\"flat\" icon-name=\"menu\" disabled></nve-icon-button>\n",
38
38
  "summary": "Flat container icon buttons with interaction styles for minimal visual weight in dense toolbars.",
@@ -43,7 +43,7 @@
43
43
  ]
44
44
  },
45
45
  {
46
- "id": "core-icon-button_pressed",
46
+ "id": "icon-button-pressed",
47
47
  "name": "Pressed",
48
48
  "template": "<nve-icon-button pressed icon-name=\"filter-stroke\"></nve-icon-button>\n<nve-icon-button icon-name=\"filter\"></nve-icon-button>\n",
49
49
  "summary": "Icon buttons with pressed state for toggle functionality like filters or visibility controls.",
@@ -52,7 +52,7 @@
52
52
  "tags": []
53
53
  },
54
54
  {
55
- "id": "core-icon-button_pressed-flat",
55
+ "id": "icon-button-pressed-flat",
56
56
  "name": "PressedFlat",
57
57
  "template": "<nve-icon-button pressed container=\"flat\" icon-name=\"eye-hidden\" aria-label=\"show\"></nve-icon-button>\n<nve-icon-button container=\"flat\" icon-name=\"eye\" aria-label=\"hide\"></nve-icon-button>\n",
58
58
  "summary": "Flat icon buttons with pressed state for low-emphasis toggles and compact toggle controls.",
@@ -63,7 +63,7 @@
63
63
  ]
64
64
  },
65
65
  {
66
- "id": "core-icon-button_pressed-inline",
66
+ "id": "icon-button-pressed-inline",
67
67
  "name": "PressedInline",
68
68
  "template": "<nve-icon-button pressed container=\"inline\" icon-name=\"eye-hidden\" aria-label=\"show\"></nve-icon-button>\n<nve-icon-button container=\"inline\" icon-name=\"eye\" aria-label=\"hide\"></nve-icon-button>\n",
69
69
  "summary": "Inline icon buttons with pressed state for minimal toggle controls within text or content flows.",
@@ -74,7 +74,7 @@
74
74
  ]
75
75
  },
76
76
  {
77
- "id": "core-icon-button_selected",
77
+ "id": "icon-button-selected",
78
78
  "name": "Selected",
79
79
  "template": "<nve-icon-button selected icon-name=\"split-vertical\" aria-label=\"split vertical\"></nve-icon-button>\n<nve-icon-button icon-name=\"split-horizontal\" aria-label=\"split horizontal\"></nve-icon-button>\n<nve-icon-button icon-name=\"split-none\" aria-label=\"preview\"></nve-icon-button>\n",
80
80
  "summary": "Icon buttons with selected state for mutually exclusive options like view modes or layout choices.",
@@ -83,7 +83,7 @@
83
83
  "tags": []
84
84
  },
85
85
  {
86
- "id": "core-icon-button_selected-flat",
86
+ "id": "icon-button-selected-flat",
87
87
  "name": "SelectedFlat",
88
88
  "template": "<nve-icon-button selected container=\"flat\" icon-name=\"split-vertical\" aria-label=\"split vertical\"></nve-icon-button>\n<nve-icon-button container=\"flat\" icon-name=\"split-horizontal\" aria-label=\"split horizontal\"></nve-icon-button>\n<nve-icon-button container=\"flat\" icon-name=\"split-none\" aria-label=\"preview\"></nve-icon-button>\n",
89
89
  "summary": "Flat icon buttons with selected state for low-emphasis mode selection in compact toolbars.",
@@ -94,7 +94,7 @@
94
94
  ]
95
95
  },
96
96
  {
97
- "id": "core-icon-button_selected-inline",
97
+ "id": "icon-button-selected-inline",
98
98
  "name": "SelectedInline",
99
99
  "template": "<nve-icon-button selected container=\"inline\" icon-name=\"split-vertical\" aria-label=\"split vertical\"></nve-icon-button>\n<nve-icon-button container=\"inline\" icon-name=\"split-horizontal\" aria-label=\"split horizontal\"></nve-icon-button>\n<nve-icon-button container=\"inline\" icon-name=\"split-none\" aria-label=\"preview\"></nve-icon-button>\n",
100
100
  "summary": "Inline icon buttons with selected state for minimal mode selection within content flows.",
@@ -105,7 +105,7 @@
105
105
  ]
106
106
  },
107
107
  {
108
- "id": "core-icon-button_custom-icon",
108
+ "id": "icon-button-custom-icon",
109
109
  "name": "CustomIcon",
110
110
  "template": "<nve-icon-button interaction=\"emphasis\">ML</nve-icon-button>\n<nve-icon-button>🎉</nve-icon-button>\n<nve-icon-button> 🔗 <a href=\"#\" aria-label=\"custom icon button\"></a> </nve-icon-button>\n",
111
111
  "summary": "Icon buttons with custom content like text initials, emojis, or symbols for personalized actions.",
@@ -116,7 +116,7 @@
116
116
  ]
117
117
  },
118
118
  {
119
- "id": "core-icon-button_link",
119
+ "id": "icon-button-link",
120
120
  "name": "Link",
121
121
  "template": "<nve-icon-button icon-name=\"menu\">\n <a href=\"#\" aria-label=\"link to page\"></a>\n</nve-icon-button>\n",
122
122
  "summary": "Proper implementation of icon buttons with links, showing correct and incorrect anchor placement patterns.",
@@ -125,7 +125,7 @@
125
125
  "tags": []
126
126
  },
127
127
  {
128
- "id": "core-icon-button_themes",
128
+ "id": "icon-button-themes",
129
129
  "name": "Themes",
130
130
  "template": "<div nve-theme=\"root light\">\n <nve-icon-button icon-name=\"menu\"></nve-icon-button>\n <nve-icon-button interaction=\"emphasis\" icon-name=\"menu\"></nve-icon-button>\n <nve-icon-button interaction=\"destructive\" icon-name=\"menu\"></nve-icon-button>\n <nve-icon-button container=\"flat\" icon-name=\"menu\"></nve-icon-button>\n <nve-icon-button disabled icon-name=\"menu\"></nve-icon-button>\n</div>\n<div nve-theme=\"root dark\">\n <nve-icon-button icon-name=\"menu\"></nve-icon-button>\n <nve-icon-button interaction=\"emphasis\" icon-name=\"menu\"></nve-icon-button>\n <nve-icon-button interaction=\"destructive\" icon-name=\"menu\"></nve-icon-button>\n <nve-icon-button container=\"flat\" icon-name=\"menu\"></nve-icon-button>\n <nve-icon-button disabled icon-name=\"menu\"></nve-icon-button>\n</div>\n",
131
131
  "summary": "Icon buttons styled for light and dark themes with all interaction states for theme consistency.",
@@ -15,7 +15,7 @@ var l = class extends a {
15
15
  static {
16
16
  this.metadata = {
17
17
  tag: "nve-icon-button",
18
- version: "0.0.9"
18
+ version: "0.0.11"
19
19
  };
20
20
  }
21
21
  static {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { getThemeTokens as e } from "./internal/utils/dom.js";
2
2
  import { I18nService as t } from "./internal/services/i18n.service.js";
3
3
  import { statusIcons as n } from "./internal/types/index.js";
4
4
  //#region src/index.ts
5
- var r = "0.0.9", i = "@nvidia-elements";
5
+ var r = "0.0.11", i = "@nvidia-elements";
6
6
  //#endregion
7
7
  export { t as I18nService, i as SCOPE, r as VERSION, e as getThemeTokens, n as statusIcons };
8
8
 
@@ -3,7 +3,7 @@
3
3
  "entrypoint": "@nvidia-elements/core/input/input-group.examples.json",
4
4
  "items": [
5
5
  {
6
- "id": "core-input-input-group_default",
6
+ "id": "input-input-group",
7
7
  "name": "Default",
8
8
  "template": "<nve-input-group>\n <label>domain</label>\n <nve-select style=\"width: 130px\">\n <select aria-label=\"protocol\">\n <option>https://</option>\n <option>http://</option>\n </select>\n </nve-select>\n <nve-input>\n <input placeholder=\"example\" type=\"url\" aria-label=\"host\" />\n <nve-button container=\"flat\" readonly>.com</nve-button>\n </nve-input>\n <nve-control-message>host: 123456</nve-control-message>\n</nve-input-group>\n",
9
9
  "summary": "Input group combining select, input, and button for composite controls like domain URL entry.",
@@ -12,7 +12,7 @@
12
12
  "tags": []
13
13
  },
14
14
  {
15
- "id": "core-input-input-group_filter-group-range",
15
+ "id": "input-input-group-filter-group-range",
16
16
  "name": "FilterGroupRange",
17
17
  "template": "<div nve-layout=\"row align:vertical-center\">\n <nve-input-group>\n <nve-select style=\"width: 150px\">\n <select aria-label=\"date type\">\n <option value=\"1\">recording date</option>\n <option value=\"2\">process date</option>\n </select>\n </nve-select>\n <nve-date style=\"width: 220px\">\n <nve-button container=\"flat\" readonly>start</nve-button>\n <input type=\"date\" value=\"2022-05-11\" aria-label=\"start date\" />\n </nve-date>\n <nve-date style=\"width: 220px\">\n <nve-button container=\"flat\" readonly>end</nve-button>\n <input type=\"date\" value=\"2022-12-07\" aria-label=\"end date\" />\n </nve-date>\n <nve-icon-button aria-label=\"remove filter\" icon-name=\"cancel\"></nve-icon-button>\n </nve-input-group>\n</div>\n",
18
18
  "summary": "Input group with date range filters combining select and date inputs for filtering data by time periods.",
@@ -11,7 +11,7 @@ var a = class extends n {
11
11
  static {
12
12
  this.metadata = {
13
13
  tag: "nve-input-group",
14
- version: "0.0.9"
14
+ version: "0.0.11"
15
15
  };
16
16
  }
17
17
  async connectedCallback() {
@@ -3,7 +3,7 @@
3
3
  "entrypoint": "@nvidia-elements/core/input/input.examples.json",
4
4
  "items": [
5
5
  {
6
- "id": "core-input_default",
6
+ "id": "input",
7
7
  "name": "Default",
8
8
  "template": "<nve-input>\n <label>label</label>\n <input type=\"text\" />\n <nve-control-message>message</nve-control-message>\n</nve-input>\n",
9
9
  "summary": "Basic text input field with label and message for general text entry and form data collection.",
@@ -12,7 +12,7 @@
12
12
  "tags": []
13
13
  },
14
14
  {
15
- "id": "core-input_standard",
15
+ "id": "input-standard",
16
16
  "name": "Standard",
17
17
  "template": "<nve-input>\n <label>label</label>\n <input type=\"text\" />\n <nve-control-message>message</nve-control-message>\n</nve-input>\n",
18
18
  "summary": "Text input with the standard input structure, label, and control message.",
@@ -21,7 +21,7 @@
21
21
  "tags": []
22
22
  },
23
23
  {
24
- "id": "core-input_vertical",
24
+ "id": "input-vertical",
25
25
  "name": "Vertical",
26
26
  "template": "<div nve-layout=\"column gap:lg full\">\n <nve-input>\n <label>label</label>\n <input />\n <nve-control-message>message</nve-control-message>\n </nve-input>\n <nve-input>\n <label>disabled</label>\n <input disabled />\n <nve-control-message>message</nve-control-message>\n </nve-input>\n <nve-input>\n <label>success</label>\n <input />\n <nve-control-message status=\"success\">message</nve-control-message>\n </nve-input>\n <nve-input>\n <label>error</label>\n <input />\n <nve-control-message status=\"error\">message</nve-control-message>\n </nve-input>\n</div>\n",
27
27
  "summary": "Text inputs with vertical layout including validation states for disabled, success, and error.",
@@ -32,7 +32,7 @@
32
32
  ]
33
33
  },
34
34
  {
35
- "id": "core-input_horizontal",
35
+ "id": "input-horizontal",
36
36
  "name": "Horizontal",
37
37
  "template": "<div nve-layout=\"column gap:lg full\">\n <nve-input layout=\"horizontal\">\n <label>label</label>\n <input />\n <nve-control-message>message</nve-control-message>\n </nve-input>\n <nve-input layout=\"horizontal\">\n <label>disabled</label>\n <input disabled />\n <nve-control-message>message</nve-control-message>\n </nve-input>\n <nve-input layout=\"horizontal\">\n <label>success</label>\n <input />\n <nve-control-message status=\"success\">message</nve-control-message>\n </nve-input>\n <nve-input layout=\"horizontal\">\n <label>error</label>\n <input />\n <nve-control-message status=\"error\">message</nve-control-message>\n </nve-input>\n</div>\n",
38
38
  "summary": "Text inputs with horizontal layout showing validation states for inline forms and compact layouts.",
@@ -43,7 +43,7 @@
43
43
  ]
44
44
  },
45
45
  {
46
- "id": "core-input_rounded",
46
+ "id": "input-rounded",
47
47
  "name": "Rounded",
48
48
  "template": "<nve-input rounded>\n <label>label</label>\n <input />\n <nve-control-message>message</nve-control-message>\n</nve-input>\n",
49
49
  "summary": "Text input with rounded corners for a softer visual appearance and modern aesthetic.",
@@ -52,7 +52,7 @@
52
52
  "tags": []
53
53
  },
54
54
  {
55
- "id": "core-input_fit-text",
55
+ "id": "input-fit-text",
56
56
  "name": "FitText",
57
57
  "template": "<nve-input fit-text>\n <label>label</label>\n <input value=\"123456789012345678901234567890\" />\n <nve-control-message>message</nve-control-message>\n</nve-input>\n",
58
58
  "summary": "Text input with fit-text styling that adjusts width to match the input value for compact displays.",
@@ -63,7 +63,7 @@
63
63
  ]
64
64
  },
65
65
  {
66
- "id": "core-input_fit-content",
66
+ "id": "input-fit-content",
67
67
  "name": "FitContent",
68
68
  "template": "<nve-input fit-content>\n <label>label</label>\n <input />\n <nve-control-message>message</nve-control-message>\n</nve-input>\n",
69
69
  "summary": "Text input with fit-content sizing that automatically adjusts width based on available space.",
@@ -74,7 +74,7 @@
74
74
  ]
75
75
  },
76
76
  {
77
- "id": "core-input_flat",
77
+ "id": "input-flat",
78
78
  "name": "Flat",
79
79
  "template": "<nve-input container=\"flat\">\n <label>label</label>\n <input />\n <nve-control-message>message</nve-control-message>\n</nve-input>\n",
80
80
  "summary": "Text input with flat container styling for minimal visual appearance and borderless design.",
@@ -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: "0.0.9"
17
+ version: "0.0.11"
18
18
  };
19
19
  }
20
20
  };
@@ -2,7 +2,7 @@
2
2
  "entrypoint": "@nvidia-elements/core/internal/controllers/i18n.controller.examples.json",
3
3
  "items": [
4
4
  {
5
- "id": "core-internal-controllers-i18n.controller_i18n-controller-demo",
5
+ "id": "internal-controllers-i18n.controller-i18n-controller-demo",
6
6
  "name": "I18nControllerDemo",
7
7
  "template": "<i18n-demo></i18n-demo>\n",
8
8
  "summary": "Internationalization controller with dynamic language switching between English and French.",
@@ -2,7 +2,7 @@
2
2
  "entrypoint": "@nvidia-elements/core/internal/controllers/keynav-grid.controller.examples.json",
3
3
  "items": [
4
4
  {
5
- "id": "core-internal-controllers-keynav-grid.controller_styles",
5
+ "id": "internal-controllers-keynav-grid.controller-styles",
6
6
  "name": "styles",
7
7
  "template": "section { display: grid; gap: 4px; grid-template-columns: repeat(10, 50px); } .vertical { grid-template-rows: repeat(10,\n1fr); grid-template-columns: 50px; } .row { display: contents; } button { width: 100%; height: 30px; min-width: 30px;\ndisplay: block; } button[selected] { background: green; color: white; }\n",
8
8
  "summary": "",
@@ -11,7 +11,7 @@
11
11
  "tags": []
12
12
  },
13
13
  {
14
- "id": "core-internal-controllers-keynav-grid.controller_grid-demo",
14
+ "id": "internal-controllers-keynav-grid.controller-grid-demo",
15
15
  "name": "GridDemo",
16
16
  "template": "<demo-key-navigation-grid></demo-key-navigation-grid>\n",
17
17
  "summary": "Grid-based keyboard navigation controller with arrow key support across rows and columns.",
@@ -94,21 +94,29 @@ function _(e, t) {
94
94
  dy: 4
95
95
  } : null;
96
96
  }
97
- function v(e, t, n, r, i, a) {
97
+ function v(e, t, n) {
98
+ let { x: r, y: i } = t, { columnCount: a, rowCount: s, ctrlKey: c } = n;
98
99
  return e === o.End ? {
99
- x: r,
100
- y: a ? i : n
100
+ x: a,
101
+ y: c ? s : i
101
102
  } : e === o.Home ? {
102
103
  x: 0,
103
- y: a ? 0 : n
104
+ y: c ? 0 : i
104
105
  } : {
105
- x: t,
106
- y: n
106
+ x: r,
107
+ y: i
107
108
  };
108
109
  }
109
110
  function y(e, t, n) {
110
111
  let r = e.find((e) => e.tabIndex === 0), i = t.find((e) => s(e).find((e) => e === r)), a = Array.from(s(i)).filter((t) => !!e.find((e) => e === t)), o = t.length - 1, c = a.length - 1, l = a.indexOf(r), u = t.indexOf(i), d = _(n.code, n.dir);
111
- return d ? (l = Math.max(0, Math.min(c, l + d.dx)), u = Math.max(0, Math.min(o, u + d.dy))) : {x: l, y: u} = v(n.code, l, u, c, o, n.ctrlKey), {
112
+ return d ? (l = Math.max(0, Math.min(c, l + d.dx)), u = Math.max(0, Math.min(o, u + d.dy))) : {x: l, y: u} = v(n.code, {
113
+ x: l,
114
+ y: u
115
+ }, {
116
+ columnCount: c,
117
+ rowCount: o,
118
+ ctrlKey: n.ctrlKey
119
+ }), {
112
120
  x: l,
113
121
  y: u
114
122
  };
@@ -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 x: number,\n y: number,\n columnCount: number,\n rowCount: number,\n ctrlKey: boolean\n) {\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, 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","#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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"}
@@ -2,7 +2,7 @@
2
2
  "entrypoint": "@nvidia-elements/core/internal/controllers/keynav-list.controller.examples.json",
3
3
  "items": [
4
4
  {
5
- "id": "core-internal-controllers-keynav-list.controller_styles",
5
+ "id": "internal-controllers-keynav-list.controller-styles",
6
6
  "name": "styles",
7
7
  "template": "section { display: grid; gap: 4px; grid-template-columns: repeat(10, 50px); } .vertical { grid-template-rows: repeat(10,\n1fr); grid-template-columns: 50px; } .row { display: contents; } button { width: 100%; height: 30px; min-width: 30px;\ndisplay: block; } button[selected] { background: green; color: white; }\n",
8
8
  "summary": "",
@@ -11,7 +11,7 @@
11
11
  "tags": []
12
12
  },
13
13
  {
14
- "id": "core-internal-controllers-keynav-list.controller_list-demo",
14
+ "id": "internal-controllers-keynav-list.controller-list-demo",
15
15
  "name": "ListDemo",
16
16
  "template": "<demo-key-navigation-list></demo-key-navigation-list>\n",
17
17
  "summary": "Horizontal list keyboard navigation controller with arrow key support.",
@@ -22,7 +22,7 @@
22
22
  ]
23
23
  },
24
24
  {
25
- "id": "core-internal-controllers-keynav-list.controller_vertical-demo",
25
+ "id": "internal-controllers-keynav-list.controller-vertical-demo",
26
26
  "name": "VerticalDemo",
27
27
  "template": "<demo-key-navigation-list-vertical></demo-key-navigation-list-vertical>\n",
28
28
  "summary": "Vertical list keyboard navigation controller with up and down arrow key support.",
@@ -33,7 +33,7 @@
33
33
  ]
34
34
  },
35
35
  {
36
- "id": "core-internal-controllers-keynav-list.controller_loop-demo",
36
+ "id": "internal-controllers-keynav-list.controller-loop-demo",
37
37
  "name": "LoopDemo",
38
38
  "template": "<demo-key-navigation-list-loop></demo-key-navigation-list-loop>\n",
39
39
  "summary": "Vertical list keyboard navigation with looping enabled to wrap from last item to first.",
@@ -83,18 +83,24 @@ function s(e) {
83
83
  function c(e) {
84
84
  return e === r.End ? "end" : e === r.Home ? "home" : e === r.PageUp ? "pageup" : e === r.PageDown ? "pagedown" : null;
85
85
  }
86
- function l(e, t, n, r) {
87
- let i = e + n;
88
- return i >= 0 && i <= t ? i : r ? n < 0 ? t : 0 : e;
86
+ function l(e, t, n) {
87
+ let { limit: r, loop: i } = n, a = e + t;
88
+ return a >= 0 && a <= r ? a : i ? t < 0 ? r : 0 : e;
89
89
  }
90
90
  function u(e, t, n) {
91
91
  let r = t.indexOf(e), i = r, a = t.length - 1;
92
92
  switch (s(n) ?? c(n.code)) {
93
93
  case "backward":
94
- r = l(r, a, -1, n.loop);
94
+ r = l(r, -1, {
95
+ limit: a,
96
+ loop: n.loop
97
+ });
95
98
  break;
96
99
  case "forward":
97
- r = l(r, a, 1, n.loop);
100
+ r = l(r, 1, {
101
+ limit: a,
102
+ loop: n.loop
103
+ });
98
104
  break;
99
105
  case "end":
100
106
  r = a;
@@ -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, limit: number, step: number, loop: boolean | undefined) {\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, itemCount, -1, config.loop);\n break;\n case 'forward':\n next = navigateWithLoop(next, itemCount, 1, 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","#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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"}
@@ -2,7 +2,7 @@
2
2
  "entrypoint": "@nvidia-elements/core/internal/controllers/popover.examples.json",
3
3
  "items": [
4
4
  {
5
- "id": "core-internal-controllers-popover_anchor",
5
+ "id": "internal-controllers-popover-anchor",
6
6
  "name": "Anchor",
7
7
  "template": "<nve-tooltip id=\"popover-1\" anchor=\"btn-2\">tooltip 1</nve-tooltip>\n<nve-tooltip id=\"popover-2\" anchor=\"btn-1\">tooltip 2</nve-tooltip>\n<div nve-layout=\"row gap:xs align:center\">\n <nve-button id=\"btn-1\" popovertarget=\"popover-1\">button 1</nve-button>\n <nve-button id=\"btn-2\" popovertarget=\"popover-2\">button 2</nve-button>\n</div>\n",
8
8
  "summary": "Anchor-based positioning where popovers anchor to specific elements rather than their triggers.",
@@ -13,7 +13,7 @@
13
13
  ]
14
14
  },
15
15
  {
16
- "id": "core-internal-controllers-popover_nested",
16
+ "id": "internal-controllers-popover-nested",
17
17
  "name": "Nested",
18
18
  "template": "<style>\n #root-inner {\n height: 2000px;\n }\n</style>\n<nve-dialog closable modal>\n <h3 nve-text=\"heading\">Dialog</h3>\n <p nve-text=\"body\" style=\"margin-bottom: 48px\">hello there</p>\n <nve-button id=\"dropdown-btn\">search</nve-button>\n <nve-dropdown anchor=\"dropdown-btn\" closable position=\"bottom\" alignment=\"start\">\n <nve-search rounded>\n <label>search dataset</label>\n <nve-icon-button\n id=\"tooltip-btn\"\n icon-name=\"information-circle-stroke\"\n container=\"flat\"\n aria-label=\"more details\"\n slot=\"label\"\n ></nve-icon-button>\n <input type=\"search\" placeholder=\"search\" />\n </nve-search>\n <nve-tooltip anchor=\"tooltip-btn\" position=\"top\">hello there</nve-tooltip>\n </nve-dropdown>\n</nve-dialog>\n<nve-notification closable position=\"bottom\" alignment=\"end\">\n <h3 nve-text=\"label\">notification</h3>\n <p nve-text=\"body\">some text content in a notification</p>\n</nve-notification>\n",
19
19
  "summary": "Nested popovers within dialogs and notifications, with proper layering and stacking order.",
@@ -24,7 +24,7 @@
24
24
  ]
25
25
  },
26
26
  {
27
- "id": "core-internal-controllers-popover_programmatic-trigger",
27
+ "id": "internal-controllers-popover-programmatic-trigger",
28
28
  "name": "ProgrammaticTrigger",
29
29
  "template": "<nve-toast hidden close-timeout=\"3000\">hello there</nve-toast>\n<nve-button>open after 2s</nve-button>\n<script type=\"module\">\n const toast = document.querySelector(\"nve-toast\");\n const button = document.querySelector(\"nve-button\");\n button.addEventListener(\"click\", async () => {\n await new Promise((r) => setTimeout(r, 2000)); // do an async task then open the popover\n toast.showPopover();\n });\n</script>\n",
30
30
  "summary": "Programmatic popover control with async operations before showing the popover.",
@@ -35,7 +35,7 @@
35
35
  ]
36
36
  },
37
37
  {
38
- "id": "core-internal-controllers-popover_interactive",
38
+ "id": "internal-controllers-popover-interactive",
39
39
  "name": "Interactive",
40
40
  "template": "<div nve-layout=\"row align:center gap:xl\" style=\"height: 300px\">\n <nve-tooltip id=\"tooltip\">hello there</nve-tooltip>\n <nve-button popovertarget=\"tooltip\">tooltip</nve-button>\n <nve-toast id=\"toast\" close-timeout=\"1500\">copied!</nve-toast>\n <nve-button popovertarget=\"toast\">toast</nve-button>\n <nve-drawer id=\"drawer\" closable modal>\n <nve-drawer-header>\n <h3 nve-text=\"heading semibold sm\">Title</h3>\n </nve-drawer-header>\n <p nve-text=\"body\">some text content in a drawer</p>\n </nve-drawer>\n <nve-button popovertarget=\"drawer\">drawer</nve-button>\n <nve-dropdown id=\"dropdown\" closable>\n <h3 nve-text=\"heading\">Title</h3>\n <p nve-text=\"body\">some text content in a dropdown</p>\n </nve-dropdown>\n <nve-button popovertarget=\"dropdown\">dropdown</nve-button>\n <nve-dialog id=\"dialog\" closable modal>\n <h3 nve-text=\"heading\">Title</h3>\n <p nve-text=\"body\">some text content in a closable dialog</p>\n </nve-dialog>\n <nve-button popovertarget=\"dialog\">dialog</nve-button>\n <nve-notification id=\"notification\" closable position=\"bottom\" alignment=\"end\" close-timeout=\"2000\">\n <h3 nve-text=\"label\">notification</h3>\n <p nve-text=\"body\">some text content in a notification</p>\n </nve-notification>\n <nve-button popovertarget=\"notification\">notification snackbar</nve-button>\n</div>\n",
41
41
  "summary": "Interactive showcase of all popover types (tooltip, toast, drawer, dropdown, dialog, notification) using modern popovertarget API.",
@@ -44,7 +44,7 @@
44
44
  "tags": []
45
45
  },
46
46
  {
47
- "id": "core-internal-controllers-popover_legacy-interactive",
47
+ "id": "internal-controllers-popover-legacy-interactive",
48
48
  "name": "LegacyInteractive",
49
49
  "template": "<div nve-layout=\"row align:center gap:xl\" style=\"height: 300px\">\n <nve-tooltip trigger=\"tooltip-btn\" behavior-trigger position=\"top\" hidden>hello there</nve-tooltip>\n <nve-button id=\"tooltip-btn\">tooltip</nve-button>\n <nve-button id=\"toast-btn\">toast</nve-button>\n <nve-toast trigger=\"toast-btn\" behavior-trigger position=\"top\" close-timeout=\"1500\" hidden>copied!</nve-toast>\n <nve-button id=\"drawer-btn\" size=\"sm\">drawer</nve-button>\n <nve-drawer trigger=\"drawer-btn\" behavior-trigger hidden closable modal>\n <nve-drawer-header>\n <h3 nve-text=\"heading semibold sm\">Title</h3>\n </nve-drawer-header>\n <p nve-text=\"body\">some text content in a drawer</p>\n </nve-drawer>\n <nve-button id=\"dropdown-btn\">dropdown</nve-button>\n <nve-dropdown trigger=\"dropdown-btn\" behavior-trigger closable hidden>\n <h3 nve-text=\"heading\">Title</h3>\n <p nve-text=\"body\">some text content in a dropdown</p>\n </nve-dropdown>\n <nve-button id=\"dialog-btn\">dialog</nve-button>\n <nve-dialog trigger=\"dialog-btn\" behavior-trigger closable modal hidden>\n <h3 nve-text=\"heading\">Title</h3>\n <p nve-text=\"body\">some text content in a closable dialog</p>\n </nve-dialog>\n <nve-button id=\"notification-btn\">notification snackbar</nve-button>\n <nve-notification\n trigger=\"notification-btn\"\n behavior-trigger\n hidden\n closable\n position=\"bottom\"\n alignment=\"end\"\n close-timeout=\"2000\"\n >\n <h3 nve-text=\"label\">notification</h3>\n <p nve-text=\"body\">some text content in a notification</p>\n </nve-notification>\n</div>\n",
50
50
  "summary": "Legacy implementation showing all popover types using the older trigger/behavior-trigger API for backward compatibility.",
@@ -56,7 +56,7 @@
56
56
  ]
57
57
  },
58
58
  {
59
- "id": "core-internal-controllers-popover_closable",
59
+ "id": "internal-controllers-popover-closable",
60
60
  "name": "Closable",
61
61
  "template": "<nve-button popovertarget=\"popover\">open dialog</nve-button>\n<nve-dialog id=\"popover\" modal>\n <p nve-text=\"body\">Press \"escape\" key to close.</p>\n</nve-dialog>\n",
62
62
  "summary": "Simple modal dialog with keyboard accessibility, including escape key to close functionality.",
@@ -67,7 +67,7 @@
67
67
  ]
68
68
  },
69
69
  {
70
- "id": "core-internal-controllers-popover_invoker-command",
70
+ "id": "internal-controllers-popover-invoker-command",
71
71
  "name": "InvokerCommand",
72
72
  "template": "<nve-button commandfor=\"popover\" command=\"toggle-popover\">toggle-popover</nve-button>\n<nve-button commandfor=\"popover\" command=\"show-popover\">show-popover</nve-button>\n<nve-toggletip id=\"popover\">\n toggletip\n <nve-button commandfor=\"popover\" command=\"hide-popover\">hide-popover</nve-button>\n</nve-toggletip>\n",
73
73
  "summary": "example of declarative popovers using the Invoker Commands API",
@@ -76,7 +76,7 @@
76
76
  "tags": []
77
77
  },
78
78
  {
79
- "id": "core-internal-controllers-popover_event-bubbling",
79
+ "id": "internal-controllers-popover-event-bubbling",
80
80
  "name": "EventBubbling",
81
81
  "template": "<div style=\"width: 100vw; height: 100vh\">\n <p nve-text=\"body\" id=\"event-example\">event:</p>\n <nve-button popovertarget=\"event-example-dialog\">open</nve-button>\n <nve-dialog id=\"event-example-dialog\" closable modal (close)=\"close($event)\" (open)=\"open($event)\">\n <nve-dialog-header>Header</nve-dialog-header>\n <div>\n <nve-button popovertarget=\"event-example-dropdown\">show dropdown</nve-button>\n </div>\n <nve-dropdown id=\"event-example-dropdown\"> dropdown content </nve-dropdown>\n </nve-dialog>\n</div>\n<script type=\"module\">\n const dialog = document.querySelector(\"#event-example-dialog\");\n const eventLabel = document.querySelector(\"#event-example\");\n // Custom events like many standard DOM events bubble. By listening to\n // larger DOM trees check which element dispatched the source event\n dialog.addEventListener(\"open\", (e) => {\n eventLabel.innerText = \"open: \" + e.target.localName;\n });\n dialog.addEventListener(\"close\", (e) => {\n eventLabel.innerText = \"close: \" + e.target.localName;\n });\n</script>\n",
82
82
  "summary": "Custom events like many standard DOM events bubble. When listening to larger DOM trees, check which element dispatched the source event.",
@@ -2,7 +2,7 @@
2
2
  "entrypoint": "@nvidia-elements/core/internal/controllers/type-button.controller.examples.json",
3
3
  "items": [
4
4
  {
5
- "id": "core-internal-controllers-type-button.controller_type-button-demo",
5
+ "id": "internal-controllers-type-button.controller-type-button-demo",
6
6
  "name": "TypeButtonDemo",
7
7
  "template": "<ui-button>button</ui-button>\n<ui-button pressed>pressed</ui-button>\n<ui-button expanded>expanded</ui-button>\n<ui-button selected>selected</ui-button>\n<ui-button disabled>disabled</ui-button>\n<ui-button><a href=\"#\">link</a></ui-button>\n<form id=\"type-button-demo-form\" style=\"display: inline-flex\">\n <ui-button type=\"submit\">submit</ui-button>\n</form>\n<script type=\"module\">\n const form = document.querySelector(\"#type-button-demo-form\");\n form.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n alert(\"submit!\");\n });\n</script>\n",
8
8
  "summary": "Custom button element using BaseButton with pressed, expanded, disabled, and link states.",
@@ -2,7 +2,7 @@
2
2
  "entrypoint": "@nvidia-elements/core/internal/controllers/type-popover.controller.examples.json",
3
3
  "items": [
4
4
  {
5
- "id": "core-internal-controllers-type-popover.controller_default",
5
+ "id": "internal-controllers-type-popover.controller",
6
6
  "name": "Default",
7
7
  "template": "<style>\n #root-inner {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n width: 100%;\n height: 100vh;\n }\n</style>\n<ui-popover id=\"type-popover\">popover</ui-popover>\n<nve-button popovertarget=\"type-popover\">toggle</nve-button>\n",
8
8
  "summary": "Basic popover toggled by a button using the native popovertarget API.",
@@ -13,7 +13,7 @@
13
13
  ]
14
14
  },
15
15
  {
16
- "id": "core-internal-controllers-type-popover.controller_alignment",
16
+ "id": "internal-controllers-type-popover.controller-alignment",
17
17
  "name": "Alignment",
18
18
  "template": "<nve-card id=\"card\" style=\"width: 450px; height: 300px\"></nve-card>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"top\" alignment=\"start\">top start</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"top\">top center</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"top\" alignment=\"end\">top end</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"right\" alignment=\"start\">right start</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"right\">right center</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"right\" alignment=\"end\">right end</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"bottom\" alignment=\"start\">bottom start</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"bottom\">bottom center</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"bottom\" alignment=\"end\">bottom end</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"left\" alignment=\"start\">left start</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"left\">left center</ui-popover>\n<ui-popover anchor=\"card\" popover-type=\"manual\" position=\"left\" alignment=\"end\">left end</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"center\">center</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"top\" alignment=\"start\">top start</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"top\">top center</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"top\" alignment=\"end\">top end</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"right\" alignment=\"start\">right start</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"right\">right center</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"right\" alignment=\"end\">right end</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"bottom\" alignment=\"start\">bottom start</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"bottom\">bottom center</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"bottom\" alignment=\"end\">bottom end</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"left\" alignment=\"start\">left start</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"left\">left center</ui-popover>\n<ui-popover popover-type=\"manual\" position=\"left\" alignment=\"end\">left end</ui-popover>\n",
19
19
  "summary": "Popover positioning and alignment options across all anchor and viewport placements.",