@nvidia-elements/core 2.23.5 → 2.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/accordion/accordion-group.js.map +1 -1
  3. package/dist/accordion/accordion.js.map +1 -1
  4. package/dist/accordion/accordion2.js +4 -4
  5. package/dist/alert/alert-group2.js +1 -1
  6. package/dist/alert/alert2.js +1 -1
  7. package/dist/avatar/avatar-group2.js +1 -1
  8. package/dist/avatar/avatar2.js +1 -1
  9. package/dist/badge/badge2.js +1 -1
  10. package/dist/breadcrumb/breadcrumb2.js +1 -1
  11. package/dist/bundle.d.ts +2 -0
  12. package/dist/bundles/index.d.ts +323 -56
  13. package/dist/bundles/index.js +9 -9
  14. package/dist/button/button2.js +1 -1
  15. package/dist/button-group/button-group2.js +1 -1
  16. package/dist/card/card2.js +4 -4
  17. package/dist/chat-message/chat-message2.js +1 -1
  18. package/dist/checkbox/checkbox-group2.js +1 -1
  19. package/dist/checkbox/checkbox2.js +1 -1
  20. package/dist/color/color2.js +1 -1
  21. package/dist/combobox/combobox2.js +1 -1
  22. package/dist/copy-button/copy-button2.js +1 -1
  23. package/dist/custom-elements-jsx.d.ts +167 -1
  24. package/dist/custom-elements-vue.d.ts +161 -1
  25. package/dist/custom-elements.json +5017 -268
  26. package/dist/dashboard/controllers/arrangement.controller.d.ts +30 -0
  27. package/dist/dashboard/controllers/arrangement.controller.js +68 -0
  28. package/dist/dashboard/controllers/arrangement.controller.js.map +1 -0
  29. package/dist/dashboard/controllers/command.controller.d.ts +28 -0
  30. package/dist/dashboard/controllers/command.controller.js +69 -0
  31. package/dist/dashboard/controllers/command.controller.js.map +1 -0
  32. package/dist/dashboard/controllers/composition.controller.d.ts +61 -0
  33. package/dist/dashboard/controllers/composition.controller.js +285 -0
  34. package/dist/dashboard/controllers/composition.controller.js.map +1 -0
  35. package/dist/dashboard/controllers/fullscreen.controller.d.ts +23 -0
  36. package/dist/dashboard/controllers/fullscreen.controller.js +46 -0
  37. package/dist/dashboard/controllers/fullscreen.controller.js.map +1 -0
  38. package/dist/dashboard/controllers/interaction.controller.d.ts +53 -0
  39. package/dist/dashboard/controllers/interaction.controller.js +407 -0
  40. package/dist/dashboard/controllers/interaction.controller.js.map +1 -0
  41. package/dist/dashboard/controllers/measurement.controller.d.ts +28 -0
  42. package/dist/dashboard/controllers/measurement.controller.js +77 -0
  43. package/dist/dashboard/controllers/measurement.controller.js.map +1 -0
  44. package/dist/dashboard/dashboard.d.ts +83 -0
  45. package/dist/dashboard/dashboard.examples.js +5 -0
  46. package/dist/dashboard/dashboard.examples.js.map +1 -0
  47. package/dist/dashboard/dashboard.examples.json +138 -0
  48. package/dist/dashboard/dashboard.js +5 -0
  49. package/dist/dashboard/dashboard.js.map +1 -0
  50. package/dist/dashboard/dashboard.types.d.ts +33 -0
  51. package/dist/dashboard/dashboard2.js +352 -0
  52. package/dist/dashboard/dashboard2.js.map +1 -0
  53. package/dist/dashboard/define.d.ts +10 -0
  54. package/dist/dashboard/define.js +9 -0
  55. package/dist/dashboard/define.js.map +1 -0
  56. package/dist/dashboard/index.d.ts +8 -0
  57. package/dist/dashboard/index.js +6 -0
  58. package/dist/dashboard/panel/panel.d.ts +88 -0
  59. package/dist/dashboard/panel/panel.js +5 -0
  60. package/dist/dashboard/panel/panel.js.map +1 -0
  61. package/dist/dashboard/panel/panel2.js +110 -0
  62. package/dist/dashboard/panel/panel2.js.map +1 -0
  63. package/dist/dashboard/panel-content/panel-content.d.ts +20 -0
  64. package/dist/dashboard/panel-content/panel-content.js +5 -0
  65. package/dist/dashboard/panel-content/panel-content.js.map +1 -0
  66. package/dist/dashboard/panel-content/panel-content2.js +22 -0
  67. package/dist/dashboard/panel-content/panel-content2.js.map +1 -0
  68. package/dist/dashboard/panel-footer/panel-footer.d.ts +25 -0
  69. package/dist/dashboard/panel-footer/panel-footer.js +5 -0
  70. package/dist/dashboard/panel-footer/panel-footer.js.map +1 -0
  71. package/dist/dashboard/panel-footer/panel-footer2.js +28 -0
  72. package/dist/dashboard/panel-footer/panel-footer2.js.map +1 -0
  73. package/dist/dashboard/panel-header/panel-header.d.ts +27 -0
  74. package/dist/dashboard/panel-header/panel-header.js +5 -0
  75. package/dist/dashboard/panel-header/panel-header.js.map +1 -0
  76. package/dist/dashboard/panel-header/panel-header2.js +28 -0
  77. package/dist/dashboard/panel-header/panel-header2.js.map +1 -0
  78. package/dist/dashboard/utils/action.utils.d.ts +17 -0
  79. package/dist/dashboard/utils/action.utils.js +144 -0
  80. package/dist/dashboard/utils/action.utils.js.map +1 -0
  81. package/dist/dashboard/utils/geometry.utils.d.ts +110 -0
  82. package/dist/dashboard/utils/geometry.utils.js +208 -0
  83. package/dist/dashboard/utils/geometry.utils.js.map +1 -0
  84. package/dist/dashboard/utils/intent.types.d.ts +67 -0
  85. package/dist/dashboard/utils/layout.utils.d.ts +20 -0
  86. package/dist/dashboard/utils/layout.utils.js +224 -0
  87. package/dist/dashboard/utils/layout.utils.js.map +1 -0
  88. package/dist/dashboard/utils/movement.utils.d.ts +7 -0
  89. package/dist/dashboard/utils/movement.utils.js +15 -0
  90. package/dist/dashboard/utils/movement.utils.js.map +1 -0
  91. package/dist/dashboard/utils/mutation.utils.d.ts +2 -0
  92. package/dist/dashboard/utils/mutation.utils.js +19 -0
  93. package/dist/dashboard/utils/mutation.utils.js.map +1 -0
  94. package/dist/dashboard/utils/packing.utils.d.ts +13 -0
  95. package/dist/dashboard/utils/packing.utils.js +421 -0
  96. package/dist/dashboard/utils/packing.utils.js.map +1 -0
  97. package/dist/data.html.json +141 -1
  98. package/dist/date/date2.js +1 -1
  99. package/dist/datetime/datetime2.js +1 -1
  100. package/dist/dialog/dialog-footer2.js +1 -1
  101. package/dist/dialog/dialog-header2.js +1 -1
  102. package/dist/dialog/dialog2.js +1 -1
  103. package/dist/divider/divider2.js +1 -1
  104. package/dist/dot/dot2.js +1 -1
  105. package/dist/drag-handle/drag-handle2.js +1 -1
  106. package/dist/drawer/drawer-content2.js +1 -1
  107. package/dist/drawer/drawer-footer2.js +1 -1
  108. package/dist/drawer/drawer-header2.js +1 -1
  109. package/dist/drawer/drawer2.js +1 -1
  110. package/dist/dropdown/dropdown-footer2.js +1 -1
  111. package/dist/dropdown/dropdown-header2.js +1 -1
  112. package/dist/dropdown/dropdown.examples.js.map +1 -1
  113. package/dist/dropdown/dropdown2.js +1 -1
  114. package/dist/dropdown-group/dropdown-group.js +1 -1
  115. package/dist/dropzone/dropzone2.js +1 -1
  116. package/dist/file/file2.js +1 -1
  117. package/dist/format-bytes/format-bytes2.js +1 -1
  118. package/dist/format-datetime/format-datetime2.js +1 -1
  119. package/dist/format-number/format-number2.js +1 -1
  120. package/dist/format-relative-time/format-relative-time2.js +1 -1
  121. package/dist/format-truncate/format-truncate2.js +1 -1
  122. package/dist/forms/control/control2.js +1 -1
  123. package/dist/forms/control-group/control-group2.js +1 -1
  124. package/dist/forms/control-message/control-message2.js +1 -1
  125. package/dist/gauge/gauge2.js +1 -1
  126. package/dist/ghost/ghost2.js +1 -1
  127. package/dist/grid/cell/cell2.js +1 -1
  128. package/dist/grid/column/column2.js +1 -1
  129. package/dist/grid/footer/footer2.js +1 -1
  130. package/dist/grid/grid.js.map +1 -1
  131. package/dist/grid/grid2.js +1 -1
  132. package/dist/grid/header/header2.js +1 -1
  133. package/dist/grid/placeholder/placeholder2.js +1 -1
  134. package/dist/grid/row/row2.js +1 -1
  135. package/dist/icon/icon2.js +1 -1
  136. package/dist/icon-button/icon-button2.js +1 -1
  137. package/dist/iframe/iframe2.js +1 -1
  138. package/dist/index.js +1 -1
  139. package/dist/input/input-group2.js +1 -1
  140. package/dist/input/input2.js +1 -1
  141. package/dist/internal/controllers/native-fullscreen.controller.d.ts +13 -0
  142. package/dist/internal/controllers/native-fullscreen.controller.js +73 -0
  143. package/dist/internal/controllers/native-fullscreen.controller.js.map +1 -0
  144. package/dist/internal/index.d.ts +1 -0
  145. package/dist/internal/index.js +59 -57
  146. package/dist/internal/index.js.map +1 -1
  147. package/dist/joystick/joystick2.js +1 -1
  148. package/dist/logo/logo2.js +1 -1
  149. package/dist/menu/menu-group2.js +1 -1
  150. package/dist/menu/menu-item2.js +1 -1
  151. package/dist/menu/menu2.js +1 -1
  152. package/dist/month/month2.js +1 -1
  153. package/dist/notification/notification-group2.js +1 -1
  154. package/dist/notification/notification2.js +1 -1
  155. package/dist/page/page-panel/page-panel-content2.js +1 -1
  156. package/dist/page/page-panel/page-panel-footer2.js +1 -1
  157. package/dist/page/page-panel/page-panel-header2.js +1 -1
  158. package/dist/page/page-panel/page-panel2.js +1 -1
  159. package/dist/page/page2.js +1 -1
  160. package/dist/page-header/page-header2.js +1 -1
  161. package/dist/page-loader/page-loader2.js +1 -1
  162. package/dist/pagination/pagination2.js +1 -1
  163. package/dist/panel/panel2.js +4 -4
  164. package/dist/password/password2.js +1 -1
  165. package/dist/preferences-input/preferences-input2.js +1 -1
  166. package/dist/progress-bar/progress-bar2.js +1 -1
  167. package/dist/progress-dot/progress-dot2.js +1 -1
  168. package/dist/progress-ring/progress-ring2.js +1 -1
  169. package/dist/progressive-filter-chip/progressive-filter-chip2.js +1 -1
  170. package/dist/pulse/pulse2.js +1 -1
  171. package/dist/radio/radio-group2.js +1 -1
  172. package/dist/radio/radio2.js +1 -1
  173. package/dist/range/range2.js +1 -1
  174. package/dist/resize-handle/resize-handle2.js +1 -1
  175. package/dist/search/search2.js +1 -1
  176. package/dist/select/select2.js +1 -1
  177. package/dist/skeleton/skeleton2.js +1 -1
  178. package/dist/sort-button/sort-button2.js +1 -1
  179. package/dist/sparkline/sparkline2.js +1 -1
  180. package/dist/star-rating/star-rating2.js +1 -1
  181. package/dist/steps/steps2.js +2 -2
  182. package/dist/switch/switch-group2.js +1 -1
  183. package/dist/switch/switch2.js +1 -1
  184. package/dist/tabs/tabs-group2.js +1 -1
  185. package/dist/tabs/tabs-item-group2.js +1 -1
  186. package/dist/tabs/tabs2.js +2 -2
  187. package/dist/tag/tag2.js +1 -1
  188. package/dist/textarea/textarea2.js +1 -1
  189. package/dist/time/time2.js +1 -1
  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/toggletip2.js +1 -1
  194. package/dist/toolbar/toolbar2.js +1 -1
  195. package/dist/tooltip/tooltip2.js +1 -1
  196. package/dist/tree/tree-node2.js +1 -1
  197. package/dist/tree/tree2.js +1 -1
  198. package/dist/week/week2.js +1 -1
  199. package/dist/workspace/controllers/workspace-composition.controller.d.ts +4 -1
  200. package/dist/workspace/controllers/workspace-composition.controller.js +69 -39
  201. package/dist/workspace/controllers/workspace-composition.controller.js.map +1 -1
  202. package/dist/workspace/controllers/workspace-fullscreen.controller.d.ts +2 -4
  203. package/dist/workspace/controllers/workspace-fullscreen.controller.js +17 -47
  204. package/dist/workspace/controllers/workspace-fullscreen.controller.js.map +1 -1
  205. package/dist/workspace/controllers/workspace-rearrange.controller.js +27 -27
  206. package/dist/workspace/controllers/workspace-rearrange.controller.js.map +1 -1
  207. package/dist/workspace/controllers/workspace-restoration.controller.js +2 -2
  208. package/dist/workspace/controllers/workspace-restoration.controller.js.map +1 -1
  209. package/dist/workspace/panel/panel2.js +2 -2
  210. package/dist/workspace/panel/panel2.js.map +1 -1
  211. package/dist/workspace/panel-content/panel-content2.js +1 -1
  212. package/dist/workspace/panel-footer/panel-footer2.js +1 -1
  213. package/dist/workspace/panel-header/panel-header2.js +1 -1
  214. package/dist/workspace/utils/comparison.utils.d.ts +3 -0
  215. package/dist/workspace/utils/comparison.utils.js +13 -0
  216. package/dist/workspace/utils/comparison.utils.js.map +1 -0
  217. package/dist/workspace/utils/evaluation.utils.d.ts +65 -6
  218. package/dist/workspace/utils/evaluation.utils.js +334 -99
  219. package/dist/workspace/utils/evaluation.utils.js.map +1 -1
  220. package/dist/workspace/utils/geometry/allocation.utils.js +15 -13
  221. package/dist/workspace/utils/geometry/allocation.utils.js.map +1 -1
  222. package/dist/workspace/utils/geometry/sizing.utils.d.ts +2 -0
  223. package/dist/workspace/utils/geometry/sizing.utils.js +37 -17
  224. package/dist/workspace/utils/geometry/sizing.utils.js.map +1 -1
  225. package/dist/workspace/utils/interaction/boundary.utils.d.ts +2 -2
  226. package/dist/workspace/utils/interaction/boundary.utils.js +2 -2
  227. package/dist/workspace/utils/interaction/boundary.utils.js.map +1 -1
  228. package/dist/workspace/utils/interaction/drag-preview.utils.d.ts +3 -3
  229. package/dist/workspace/utils/interaction/drag-preview.utils.js.map +1 -1
  230. package/dist/workspace/utils/interaction/insertion-offers.utils.d.ts +11 -9
  231. package/dist/workspace/utils/interaction/insertion-offers.utils.js +37 -43
  232. package/dist/workspace/utils/interaction/insertion-offers.utils.js.map +1 -1
  233. package/dist/workspace/utils/interaction/placement-decision.utils.d.ts +6 -1
  234. package/dist/workspace/utils/interaction/placement-decision.utils.js +94 -87
  235. package/dist/workspace/utils/interaction/placement-decision.utils.js.map +1 -1
  236. package/dist/workspace/utils/model/layout.utils.d.ts +2 -1
  237. package/dist/workspace/utils/model/layout.utils.js +12 -10
  238. package/dist/workspace/utils/model/layout.utils.js.map +1 -1
  239. package/dist/workspace/utils/model/membership.utils.d.ts +4 -0
  240. package/dist/workspace/utils/model/membership.utils.js +13 -4
  241. package/dist/workspace/utils/model/membership.utils.js.map +1 -1
  242. package/dist/workspace/utils/model/operations.utils.d.ts +1 -0
  243. package/dist/workspace/utils/model/operations.utils.js +51 -46
  244. package/dist/workspace/utils/model/operations.utils.js.map +1 -1
  245. package/dist/workspace/utils/model/projection.utils.d.ts +4 -2
  246. package/dist/workspace/utils/model/projection.utils.js +49 -40
  247. package/dist/workspace/utils/model/projection.utils.js.map +1 -1
  248. package/dist/workspace/utils/model/value.utils.d.ts +4 -3
  249. package/dist/workspace/utils/model/value.utils.js +15 -50
  250. package/dist/workspace/utils/model/value.utils.js.map +1 -1
  251. package/dist/workspace/utils/placement/acquisition-sizing.utils.d.ts +2 -0
  252. package/dist/workspace/utils/placement/acquisition-sizing.utils.js +30 -22
  253. package/dist/workspace/utils/placement/acquisition-sizing.utils.js.map +1 -1
  254. package/dist/workspace/utils/placement/group-insertion.utils.d.ts +19 -13
  255. package/dist/workspace/utils/placement/group-insertion.utils.js +50 -47
  256. package/dist/workspace/utils/placement/group-insertion.utils.js.map +1 -1
  257. package/dist/workspace/utils/placement/planner.utils.d.ts +13 -2
  258. package/dist/workspace/utils/placement/planner.utils.js +79 -73
  259. package/dist/workspace/utils/placement/planner.utils.js.map +1 -1
  260. package/dist/workspace/utils/placement/preparation.utils.d.ts +5 -2
  261. package/dist/workspace/utils/placement/preparation.utils.js +45 -41
  262. package/dist/workspace/utils/placement/preparation.utils.js.map +1 -1
  263. package/dist/workspace/utils/placement/region.utils.js +32 -32
  264. package/dist/workspace/utils/placement/region.utils.js.map +1 -1
  265. package/dist/workspace/utils/placement/scope.utils.d.ts +34 -0
  266. package/dist/workspace/utils/placement/scope.utils.js +155 -0
  267. package/dist/workspace/utils/placement/scope.utils.js.map +1 -0
  268. package/dist/workspace/utils/placement/session.utils.d.ts +11 -0
  269. package/dist/workspace/utils/placement/session.utils.js +78 -0
  270. package/dist/workspace/utils/placement/session.utils.js.map +1 -0
  271. package/dist/workspace/utils/placement/split-sizing.utils.d.ts +2 -2
  272. package/dist/workspace/utils/placement/split-sizing.utils.js +19 -19
  273. package/dist/workspace/utils/placement/split-sizing.utils.js.map +1 -1
  274. package/dist/workspace/utils/presentation/composition.utils.d.ts +1 -1
  275. package/dist/workspace/utils/presentation/composition.utils.js +4 -2
  276. package/dist/workspace/utils/presentation/composition.utils.js.map +1 -1
  277. package/dist/workspace/utils/presentation/groups.utils.d.ts +3 -3
  278. package/dist/workspace/utils/presentation/groups.utils.js +40 -30
  279. package/dist/workspace/utils/presentation/groups.utils.js.map +1 -1
  280. package/dist/workspace/utils/presentation/measurements.utils.d.ts +1 -0
  281. package/dist/workspace/utils/presentation/measurements.utils.js +6 -14
  282. package/dist/workspace/utils/presentation/measurements.utils.js.map +1 -1
  283. package/dist/workspace/utils/presentation/offers.utils.d.ts +1 -1
  284. package/dist/workspace/utils/presentation/offers.utils.js +3 -3
  285. package/dist/workspace/utils/presentation/offers.utils.js.map +1 -1
  286. package/dist/workspace/utils/presentation/preview.utils.d.ts +6 -0
  287. package/dist/workspace/utils/presentation/preview.utils.js +14 -3
  288. package/dist/workspace/utils/presentation/preview.utils.js.map +1 -1
  289. package/dist/workspace/workspace.examples.js.map +1 -1
  290. package/dist/workspace/workspace.examples.json +4 -4
  291. package/dist/workspace/workspace.js +1 -1
  292. package/dist/workspace/workspace.js.map +1 -1
  293. package/dist/workspace/workspace2.js +206 -212
  294. package/dist/workspace/workspace2.js.map +1 -1
  295. package/package.json +16 -4
  296. package/dist/workspace/utils/placement/context.utils.d.ts +0 -36
  297. package/dist/workspace/utils/placement/context.utils.js +0 -135
  298. package/dist/workspace/utils/placement/context.utils.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packing.utils.js","names":["exhaustive","isDefined","value","extent","settleDashboardItems","settled","item","items","compareItems","row","other","findNormalizedPlacementPlan","source","request","final","getNormalizedItems","selectPlan","options","getMovementAxes","movementAxis","getMovementAxis","aimGeometry","step","delta","getSnappedPlacement","tracks","areGridGeometriesEqual","a","b","getDisplacedItems","candidate","old","createUnchangedCandidate","getUniqueCandidates","result","candidates","key","previous","getLocalCandidates","placement","context","classified","perpendicularAxis","perpendicularSpanKey","direction","findBestCandidate","input","eligible","createAdvanceCandidate","autoSettle","findItemAtPointerPosition","point","query","peer","spacingFraction","findBestOverlappingItem","peers","entry","hasMovementAxisContact","body","geometry","movementSpanKey","createVacantPlacementCandidate","carried","target","plan","doDashboardGridGeometriesOverlap","isPlacementPlanValid","findPointerPlacementPlan","owner","createExchangeCandidate","literal","vacancy","contact","createPointerCandidates","isPointerCandidateAdmissible","getContactPlacements","pose","generateCandidates","resolveMovement","intent","sharedStart","sharedEnd","createVacancyCandidates","exchange","createFrontierCandidates","max","ranges","getClearIntervals","getOccupiedIntervals","interval","lo","hi","propagateDisplacement","queue","protectedIds","cursor","id","blocker","updates","getDisplacementUpdates","next","contains","inner","outer","index","orientDashboardItem","orientDashboardGridGeometry","flow","transposeDashboardGridGeometry","createStartPlan","createResizePlan","others","minimum","shift","proposed","primary","findPrimaryResizePressure","outward","edge","poses","coordinate","occupants","ids","targetItem","ahead","createFrontierCandidate","crossed","frontier","getFrontierRange","remaining","occupied","merged","last","clear","start","span","collisions"],"sources":["../../../src/dashboard/utils/packing.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { doDashboardGridGeometriesOverlap, transposeDashboardGridGeometry } from './geometry.utils.js';\n\nimport type {\n DashboardAxis as Axis,\n DashboardAxisDirection as Direction,\n DashboardGridGeometry,\n DashboardGridPoint,\n DashboardIntent,\n DashboardPointerPlacementQuery\n} from './intent.types.js';\n\nimport type { DashboardItem, DashboardLayout } from '../dashboard.types.js';\n\ntype SpanKey = 'columnSpan' | 'rowSpan';\n\ninterface MovementAxes {\n readonly movementAxis: Axis;\n readonly perpendicularAxis: Axis;\n readonly movementSpanKey: SpanKey;\n readonly perpendicularSpanKey: SpanKey;\n readonly direction: Direction;\n}\n\ninterface ResizePressure {\n readonly movementAxis: Axis;\n readonly direction: Direction;\n readonly amount: number;\n}\n\ninterface PlacementPlan {\n readonly items: readonly DashboardItem[];\n /** Preserve these items without applying another settling pass. */\n readonly skipSettling?: boolean;\n}\n\ninterface PlacementCandidate extends PlacementPlan {\n readonly placedItem: DashboardItem;\n /** Tie-breaking priority for otherwise equal placements. */\n readonly priority: 0 | 1;\n}\n\ninterface RankedCandidate extends PlacementCandidate {\n readonly distance: number;\n readonly rankCoordinate: number;\n}\n\nfunction isDefined<T>(value: T | undefined): value is T {\n return value !== undefined;\n}\n\nconst extent = 1_000_000;\n\n/** Applies top gravity without moving panels through an overhanging predecessor. Coordinates are growth-normalized. */\nexport function settleDashboardItems(items: readonly DashboardItem[]): DashboardItem[] | undefined {\n const settled: DashboardItem[] = [];\n\n for (const item of [...items].sort(compareItems)) {\n let row = 0;\n\n for (const other of settled) {\n if (item.column < other.column + other.columnSpan && item.column + item.columnSpan > other.column) {\n row = Math.max(row, other.row + other.rowSpan);\n }\n }\n\n if (row + item.rowSpan > extent) return undefined;\n\n settled.push({ ...item, row });\n }\n\n return settled;\n}\n\n/** Resolves directional collisions into vacated space, with optional final top-gravity normalization. */\nexport function findNormalizedPlacementPlan(\n items: readonly DashboardItem[],\n request: { readonly id: string; readonly intent: DashboardIntent },\n options: { tracks: number; autoSettle?: boolean }\n): DashboardItem[] | undefined {\n const source = items.find(item => item.id === request.id);\n if (!source) return undefined;\n\n const context = { items, source, ...options };\n const final = getNormalizedItems(selectPlan(context, request.intent), options.autoSettle);\n\n return final && [...final];\n}\n\nfunction getMovementAxes(\n source: DashboardGridGeometry,\n aimGeometry: DashboardGridGeometry,\n step?: DashboardGridPoint\n): MovementAxes {\n const movementAxis = getMovementAxis(source, aimGeometry, step);\n const delta = step ? step[movementAxis] : aimGeometry[movementAxis] - source[movementAxis];\n\n return {\n movementAxis,\n perpendicularAxis: movementAxis === 'column' ? 'row' : 'column',\n movementSpanKey: movementAxis === 'column' ? 'columnSpan' : 'rowSpan',\n perpendicularSpanKey: movementAxis === 'column' ? 'rowSpan' : 'columnSpan',\n direction: delta >= 0 ? 1 : -1\n };\n}\n\nfunction getMovementAxis(\n source: DashboardGridGeometry,\n aimGeometry: DashboardGridGeometry,\n step?: DashboardGridPoint\n): Axis {\n if (step) return step.column ? 'column' : 'row';\n\n const columnDistance = Math.abs(aimGeometry.column - source.column);\n const rowDistance = Math.abs(aimGeometry.row - source.row);\n\n return columnDistance > rowDistance ? 'column' : 'row';\n}\n\nfunction getSnappedPlacement(\n source: DashboardGridGeometry,\n aimGeometry: DashboardGridGeometry,\n tracks: number\n): DashboardGridGeometry {\n return {\n column: Math.max(0, Math.min(tracks - source.columnSpan, Math.round(aimGeometry.column))),\n row: Math.max(0, Math.min(extent - source.rowSpan, Math.round(aimGeometry.row))),\n columnSpan: source.columnSpan,\n rowSpan: source.rowSpan\n };\n}\n\nfunction areGridGeometriesEqual(a: DashboardGridGeometry, b: DashboardGridGeometry): boolean {\n return a.column === b.column && a.row === b.row && a.columnSpan === b.columnSpan && a.rowSpan === b.rowSpan;\n}\n\nfunction getDisplacedItems(\n candidate: PlacementCandidate,\n items: readonly DashboardItem[],\n source: DashboardItem\n): DashboardItem[] {\n return candidate.items.filter(\n item =>\n item.id !== source.id &&\n items.some(\n old =>\n old.id === item.id &&\n (old.column !== item.column ||\n old.row !== item.row ||\n old.columnSpan !== item.columnSpan ||\n old.rowSpan !== item.rowSpan)\n )\n );\n}\n\nfunction createUnchangedCandidate(items: readonly DashboardItem[], source: DashboardItem): PlacementCandidate {\n return {\n items: items.map(item => ({ ...item })),\n placedItem: { ...source },\n priority: 1,\n skipSettling: true\n };\n}\n\nfunction getUniqueCandidates(candidates: readonly PlacementCandidate[]): PlacementCandidate[] {\n const result = new Map<string, PlacementCandidate>();\n\n for (const candidate of candidates) {\n const key = JSON.stringify(\n candidate.items.map(item => [item.id, item.column, item.row, item.columnSpan, item.rowSpan])\n );\n const previous = result.get(key);\n\n if (!previous || candidate.priority < previous.priority) {\n result.set(key, candidate);\n }\n }\n\n return [...result.values()];\n}\n\nfunction getLocalCandidates(\n candidates: readonly PlacementCandidate[],\n placement: PlacementInput,\n context: MovementAxes\n): PlacementCandidate[] {\n const { items, source } = placement;\n const { movementAxis, perpendicularAxis, perpendicularSpanKey, direction } = context;\n\n const classified = candidates.map(candidate => ({\n ...candidate,\n quiet: getDisplacedItems(candidate, items, source).every(\n item =>\n item[perpendicularAxis] >= source[perpendicularAxis] &&\n item[perpendicularAxis] + item[perpendicularSpanKey] <= source[perpendicularAxis] + source[perpendicularSpanKey]\n )\n }));\n\n const restricted = classified.some(\n candidate => candidate.quiet && (candidate.placedItem[movementAxis] - source[movementAxis]) * direction > 0\n );\n\n return restricted ? classified.filter(candidate => candidate.quiet) : classified;\n}\n\nfunction findBestCandidate(\n candidates: readonly PlacementCandidate[],\n input: {\n source: DashboardItem;\n aimGeometry: DashboardGridGeometry;\n context: MovementAxes;\n step?: DashboardGridPoint;\n autoSettle?: boolean;\n }\n): PlacementCandidate | undefined {\n const { source, aimGeometry, context, step, autoSettle } = input;\n const { movementAxis, direction } = context;\n\n const eligible = step\n ? candidates.map(candidate => createAdvanceCandidate(candidate, { source, step, autoSettle })).filter(isDefined)\n : candidates.map(candidate => ({\n ...candidate,\n distance:\n (candidate.placedItem.column - aimGeometry.column) ** 2 + (candidate.placedItem.row - aimGeometry.row) ** 2,\n rankCoordinate: candidate.placedItem[movementAxis]\n }));\n\n eligible.sort(\n (a, b) =>\n a.distance - b.distance ||\n direction * (b.rankCoordinate - a.rankCoordinate) ||\n (areGridGeometriesEqual(a.placedItem, b.placedItem) ? a.priority - b.priority : 0)\n );\n\n return eligible[0];\n}\n\nfunction getNormalizedItems(\n candidate: PlacementPlan | undefined,\n autoSettle?: boolean\n): readonly DashboardItem[] | undefined {\n if (!candidate) return undefined;\n if (candidate.skipSettling || !autoSettle) return candidate.items;\n\n return settleDashboardItems(candidate.items);\n}\n\nfunction findItemAtPointerPosition(\n items: readonly DashboardItem[],\n source: DashboardItem,\n query: Partial<Pick<DashboardPointerPlacementQuery, 'pointerPosition' | 'spacingFraction'>>\n): DashboardItem | undefined {\n const { pointerPosition: point, spacingFraction } = query;\n return (\n point &&\n items.find(\n peer =>\n peer.id !== source.id &&\n point.column >= peer.column &&\n point.column < peer.column + peer.columnSpan - (spacingFraction?.column ?? 0) &&\n point.row >= peer.row &&\n point.row < peer.row + peer.rowSpan - (spacingFraction?.row ?? 0)\n )\n );\n}\n\nfunction findBestOverlappingItem(\n items: readonly DashboardItem[],\n source: DashboardItem,\n aimGeometry: DashboardGridGeometry\n): DashboardItem | undefined {\n const peers = items\n .filter(peer => peer.id !== source.id)\n .map(peer => ({\n peer,\n coverage:\n (Math.max(\n 0,\n Math.min(aimGeometry.column + source.columnSpan, peer.column + peer.columnSpan) -\n Math.max(aimGeometry.column, peer.column)\n ) *\n Math.max(\n 0,\n Math.min(aimGeometry.row + source.rowSpan, peer.row + peer.rowSpan) - Math.max(aimGeometry.row, peer.row)\n )) /\n (Math.min(source.columnSpan, peer.columnSpan) * Math.min(source.rowSpan, peer.rowSpan))\n }))\n .filter(entry => entry.coverage >= 0.5);\n\n peers.sort((a, b) => b.coverage - a.coverage || compareItems(a.peer, b.peer));\n\n return peers[0]?.peer;\n}\n\nfunction hasMovementAxisContact(\n geometry: DashboardGridGeometry,\n body: DashboardGridGeometry | undefined,\n context: MovementAxes\n): boolean {\n const { movementAxis, perpendicularAxis, movementSpanKey, perpendicularSpanKey } = context;\n return (\n !!body &&\n geometry[movementAxis] <= body[movementAxis] + body[movementSpanKey] &&\n geometry[movementAxis] + geometry[movementSpanKey] >= body[movementAxis] &&\n geometry[perpendicularAxis] < body[perpendicularAxis] + body[perpendicularSpanKey] &&\n geometry[perpendicularAxis] + geometry[perpendicularSpanKey] > body[perpendicularAxis]\n );\n}\n\nfunction createVacantPlacementCandidate(\n placement: PlacementInput,\n target: DashboardGridGeometry\n): PlacementCandidate | undefined {\n const { items, source, tracks } = placement;\n const carried = { ...target, id: source.id };\n const plan = items.map(item => (item.id === source.id ? carried : item));\n if (\n items.every(item => item.id === source.id || !doDashboardGridGeometriesOverlap(item, carried)) &&\n isPlacementPlanValid(plan, tracks)\n ) {\n return { items: plan, placedItem: carried, priority: 1 };\n }\n\n return undefined;\n}\n\nfunction findPointerPlacementPlan(\n placement: PlacementInput,\n aimGeometry: DashboardGridGeometry,\n query: Partial<Pick<DashboardPointerPlacementQuery, 'pointerPosition' | 'spacingFraction'>> = {}\n): PlacementCandidate | undefined {\n const { items, source, tracks, autoSettle } = placement;\n if (areGridGeometriesEqual(source, aimGeometry)) return createUnchangedCandidate(items, source);\n\n const owner = findItemAtPointerPosition(items, source, query);\n if (owner && owner.columnSpan === source.columnSpan && owner.rowSpan === source.rowSpan) {\n return createExchangeCandidate(placement, owner) ?? createUnchangedCandidate(items, source);\n }\n\n const context = getMovementAxes(source, aimGeometry);\n const literal = getSnappedPlacement(source, aimGeometry, tracks);\n\n if (!owner) {\n const vacancy = createVacantPlacementCandidate(placement, literal);\n if (vacancy) return vacancy;\n }\n\n const contact = owner ?? findBestOverlappingItem(items, source, aimGeometry);\n const candidates = createPointerCandidates(placement, literal, { contact, context }).filter(candidate =>\n isPointerCandidateAdmissible(candidate, placement, { literal, contact, context })\n );\n candidates.push(createUnchangedCandidate(items, source));\n\n const pool = getLocalCandidates(getUniqueCandidates(candidates), placement, context);\n\n return findBestCandidate(pool, { source, aimGeometry, context, autoSettle });\n}\n\nfunction createPointerCandidates(\n placement: PlacementInput,\n literal: DashboardGridGeometry,\n input: { contact?: DashboardItem; context: MovementAxes }\n): PlacementCandidate[] {\n const { source, tracks } = placement;\n const { context } = input;\n const poses = getContactPlacements(source, literal, input);\n\n return getUniqueCandidates(\n poses\n .filter(\n pose =>\n pose.column >= 0 &&\n pose.row >= 0 &&\n pose.column + pose.columnSpan <= tracks &&\n pose.row + pose.rowSpan <= extent\n )\n .flatMap(pose => generateCandidates(placement, pose, context))\n );\n}\n\nfunction isPointerCandidateAdmissible(\n candidate: PlacementCandidate,\n placement: PlacementInput,\n input: { literal: DashboardGridGeometry; contact?: DashboardItem; context: MovementAxes }\n): boolean {\n const { literal, contact, context } = input;\n if (areGridGeometriesEqual(candidate.placedItem, literal)) return true;\n\n return (\n getDisplacedItems(candidate, placement.items, placement.source).length > 0 &&\n hasMovementAxisContact(candidate.placedItem, contact, context)\n );\n}\n\nfunction resolveMovement(\n placement: PlacementInput,\n intent: Extract<DashboardIntent, { kind: 'coordinate' | 'pointer' | 'advance' }>\n): PlacementCandidate | undefined {\n const { items, source, autoSettle } = placement;\n const aimGeometry = intent.kind === 'pointer' ? intent.position.aimGeometry : intent.geometry;\n if (intent.kind !== 'advance' && areGridGeometriesEqual(source, aimGeometry)) {\n return createUnchangedCandidate(items, source);\n }\n if (intent.kind !== 'advance') {\n return findPointerPlacementPlan(placement, aimGeometry, intent.kind === 'pointer' ? intent.position : undefined);\n }\n\n const { step } = intent;\n const context = getMovementAxes(source, intent.geometry, step);\n const candidates = getUniqueCandidates(generateCandidates(placement, intent.geometry, context));\n const pool = getLocalCandidates(candidates, placement, context);\n\n return findBestCandidate(pool, { source, aimGeometry: intent.geometry, context, step, autoSettle });\n}\n\nfunction generateCandidates(\n placement: PlacementInput,\n target: DashboardGridGeometry,\n context: MovementAxes\n): PlacementCandidate[] {\n const { source } = placement;\n const { movementAxis, perpendicularAxis, perpendicularSpanKey, direction } = context;\n if ((target[movementAxis] - source[movementAxis]) * direction < 0) return [];\n\n const sharedStart = Math.max(source[perpendicularAxis], target[perpendicularAxis]);\n const sharedEnd = Math.min(\n source[perpendicularAxis] + source[perpendicularSpanKey],\n target[perpendicularAxis] + target[perpendicularSpanKey]\n );\n const candidates = createVacancyCandidates(placement, target, context);\n\n if (sharedStart >= sharedEnd) {\n const exchange = createExchangeCandidate(placement, target);\n\n if (exchange) {\n candidates.push(exchange);\n }\n } else {\n candidates.push(...createFrontierCandidates(placement, target, context));\n }\n\n return candidates;\n}\n\nfunction createVacancyCandidates(\n placement: PlacementInput,\n target: DashboardGridGeometry,\n context: MovementAxes\n): PlacementCandidate[] {\n const { items, source, tracks } = placement;\n const { movementAxis, movementSpanKey, direction } = context;\n const max = (movementAxis === 'column' ? tracks : extent) - source[movementSpanKey];\n const ranges = getClearIntervals(\n getOccupiedIntervals(\n items.filter(item => item.id !== source.id),\n target,\n context\n ),\n max,\n source[movementSpanKey]\n );\n const candidates: PlacementCandidate[] = [];\n\n for (const interval of ranges) {\n const lo = Math.max(0, interval[0], direction > 0 ? source[movementAxis] : 0);\n const hi = Math.min(max, interval[1], direction < 0 ? source[movementAxis] : max);\n\n if (lo > hi) continue;\n\n const carried = { ...target, id: source.id, [movementAxis]: Math.max(lo, Math.min(hi, target[movementAxis])) };\n const plan = items.map(item => (item.id === source.id ? carried : item));\n\n if (isPlacementPlanValid(plan, tracks)) {\n candidates.push({ items: plan, placedItem: carried, priority: 1 });\n }\n }\n\n return candidates;\n}\n\nfunction createAdvanceCandidate(\n candidate: PlacementCandidate,\n input: { source: DashboardItem; step: DashboardGridPoint; autoSettle?: boolean }\n): RankedCandidate | undefined {\n const { source, step, autoSettle } = input;\n const items = autoSettle ? settleDashboardItems(candidate.items) : candidate.items;\n const final = items?.find(item => item.id === source.id);\n const movementAxis = step.column ? 'column' : 'row';\n const direction = step[movementAxis];\n if (!items || !final || (final[movementAxis] - source[movementAxis]) * direction <= 0) {\n return undefined;\n }\n\n return {\n ...candidate,\n items,\n skipSettling: true,\n distance: Math.abs(final[movementAxis] - source[movementAxis]),\n rankCoordinate: final[movementAxis]\n };\n}\n\n/** Protected items seed the cascade and cannot move when another collision reaches them. */\nfunction propagateDisplacement(\n items: readonly DashboardItem[],\n protectedIds: ReadonlySet<string>,\n input: { movementAxis: Axis; direction: Direction; tracks: number }\n): DashboardItem[] | undefined {\n const result = new Map(items.map(item => [item.id, { ...item }]));\n const queue = [...protectedIds];\n\n for (let cursor = 0; cursor < queue.length; cursor++) {\n if (cursor >= items.length * items.length + items.length) return undefined;\n\n const id = queue[cursor];\n const blocker = id === undefined ? undefined : result.get(id);\n if (!blocker) return undefined;\n\n const updates = getDisplacementUpdates(blocker, [...result.values()], { ...input, protectedIds });\n if (!updates) return undefined;\n\n for (const next of updates) {\n result.set(next.id, next);\n queue.push(next.id);\n }\n }\n\n return [...result.values()];\n}\n\nfunction contains(outer: DashboardGridGeometry, inner: DashboardGridGeometry): boolean {\n return (\n inner.column >= outer.column &&\n inner.row >= outer.row &&\n inner.column + inner.columnSpan <= outer.column + outer.columnSpan &&\n inner.row + inner.rowSpan <= outer.row + outer.rowSpan\n );\n}\n\nfunction isPlacementPlanValid(items: readonly DashboardItem[], tracks: number): boolean {\n return items.every(\n (item, index) =>\n item.column >= 0 &&\n item.row >= 0 &&\n item.column + item.columnSpan <= tracks &&\n item.row + item.rowSpan <= extent &&\n items.slice(index + 1).every(peer => !doDashboardGridGeometriesOverlap(item, peer))\n );\n}\n\nexport function orientDashboardItem(item: DashboardItem, flow: DashboardLayout['grid']['flow']): DashboardItem {\n return { id: item.id, ...orientDashboardGridGeometry(item, flow) };\n}\n\nfunction orientDashboardGridGeometry(\n geometry: DashboardGridGeometry,\n flow: DashboardLayout['grid']['flow']\n): DashboardGridGeometry {\n return flow === 'vertical'\n ? { column: geometry.column, row: geometry.row, columnSpan: geometry.columnSpan, rowSpan: geometry.rowSpan }\n : transposeDashboardGridGeometry(geometry);\n}\n\nfunction compareItems(a: DashboardItem, b: DashboardItem): number {\n return a.row - b.row || a.column - b.column || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0);\n}\n\ninterface PlacementInput {\n readonly items: readonly DashboardItem[];\n readonly source: DashboardItem;\n readonly tracks: number;\n readonly autoSettle?: boolean;\n}\n\nfunction selectPlan(placement: PlacementInput, intent: DashboardIntent): PlacementPlan | undefined {\n switch (intent.kind) {\n case 'start':\n return createStartPlan(placement, intent.geometry);\n case 'resize':\n return createResizePlan(placement, intent.geometry);\n case 'coordinate':\n case 'pointer':\n case 'advance':\n return resolveMovement(placement, intent);\n default: {\n const exhaustive: never = intent;\n return exhaustive;\n }\n }\n}\n\nfunction createStartPlan(placement: PlacementInput, target: DashboardGridGeometry): PlacementPlan | undefined {\n const { items, source, tracks } = placement;\n const carried = { ...target, id: source.id, columnSpan: source.columnSpan, rowSpan: source.rowSpan, row: 0 };\n const vacancy = createVacantPlacementCandidate(placement, carried);\n if (vacancy) return vacancy;\n\n const others = items.filter(item => item.id !== source.id);\n const minimum = others.length ? Math.min(...others.map(item => item.row)) : source.rowSpan;\n const shift = Math.max(0, source.rowSpan - minimum);\n const plan = items.map(item => (item.id === source.id ? carried : { ...item, row: item.row + shift }));\n\n return isPlacementPlanValid(plan, tracks) ? { items: plan } : undefined;\n}\n\nfunction createResizePlan(placement: PlacementInput, geometry: DashboardGridGeometry): PlacementPlan | undefined {\n const { items, source, tracks } = placement;\n const target = { id: source.id, ...geometry };\n const proposed = items.map(item => (item.id === source.id ? target : item));\n const primary = findPrimaryResizePressure(source, target);\n if (!primary) {\n return isPlacementPlanValid(proposed, tracks) ? { items: proposed } : undefined;\n }\n\n let result = propagateDisplacement(proposed, new Set([source.id]), {\n movementAxis: primary.movementAxis,\n direction: primary.direction,\n tracks\n });\n\n if (result && !isPlacementPlanValid(result, tracks)) {\n result = undefined;\n }\n\n if (!result && (primary.movementAxis !== 'row' || primary.direction !== 1)) {\n result = propagateDisplacement(proposed, new Set([source.id]), { movementAxis: 'row', direction: 1, tracks });\n }\n\n return result && isPlacementPlanValid(result, tracks) ? { items: result } : undefined;\n}\n\nfunction findPrimaryResizePressure(\n source: DashboardGridGeometry,\n target: DashboardGridGeometry\n): ResizePressure | undefined {\n const outward = (\n [\n { movementAxis: 'column', direction: -1, amount: source.column - target.column },\n {\n movementAxis: 'column',\n direction: 1,\n amount: target.column + target.columnSpan - source.column - source.columnSpan\n },\n { movementAxis: 'row', direction: -1, amount: source.row - target.row },\n { movementAxis: 'row', direction: 1, amount: target.row + target.rowSpan - source.row - source.rowSpan }\n ] satisfies ResizePressure[]\n ).filter(edge => edge.amount > 0);\n\n outward.sort(\n (a, b) =>\n b.amount - a.amount ||\n (b.movementAxis === 'row' ? 1 : 0) - (a.movementAxis === 'row' ? 1 : 0) ||\n b.direction - a.direction\n );\n\n return outward[0];\n}\n\nfunction getContactPlacements(\n source: DashboardItem,\n literal: DashboardGridGeometry,\n input: { contact?: DashboardItem; context: MovementAxes }\n): DashboardGridGeometry[] {\n const { contact, context } = input;\n const poses = [literal];\n if (!contact) return poses;\n\n for (const coordinate of [\n contact[context.movementAxis],\n contact[context.movementAxis] + contact[context.movementSpanKey] - source[context.movementSpanKey],\n contact[context.movementAxis] - source[context.movementSpanKey],\n contact[context.movementAxis] + contact[context.movementSpanKey]\n ]) {\n poses.push({ ...literal, [context.movementAxis]: coordinate });\n }\n\n return poses;\n}\n\nfunction createExchangeCandidate(\n placement: PlacementInput,\n target: DashboardGridGeometry\n): PlacementCandidate | undefined {\n const { items, source, tracks } = placement;\n const occupants = items.filter(item => item.id !== source.id && doDashboardGridGeometriesOverlap(item, target));\n if (!occupants.length || !occupants.every(item => contains(target, item))) return undefined;\n\n const ids = new Set(occupants.map(item => item.id));\n const targetItem = { ...target, id: source.id };\n const plan = items.map(item => {\n if (item.id === source.id) return targetItem;\n if (ids.has(item.id)) {\n return { ...item, column: item.column + source.column - target.column, row: item.row + source.row - target.row };\n }\n\n return item;\n });\n\n return isPlacementPlanValid(plan, tracks) ? { items: plan, placedItem: targetItem, priority: 0 } : undefined;\n}\n\nfunction createFrontierCandidates(\n placement: PlacementInput,\n target: DashboardGridGeometry,\n context: MovementAxes\n): PlacementCandidate[] {\n const { items, source } = placement;\n const { movementAxis, perpendicularAxis, movementSpanKey, perpendicularSpanKey, direction } = context;\n const sharedStart = Math.max(source[perpendicularAxis], target[perpendicularAxis]);\n const sharedEnd = Math.min(\n source[perpendicularAxis] + source[perpendicularSpanKey],\n target[perpendicularAxis] + target[perpendicularSpanKey]\n );\n const ahead = items.filter(\n item =>\n item.id !== source.id &&\n item[perpendicularAxis] < sharedEnd &&\n item[perpendicularAxis] + item[perpendicularSpanKey] > sharedStart &&\n (direction > 0\n ? item[movementAxis] >= source[movementAxis] + source[movementSpanKey]\n : item[movementAxis] + item[movementSpanKey] <= source[movementAxis])\n );\n const frontiers = [\n null,\n ...new Set(ahead.map(item => (direction > 0 ? item[movementAxis] + item[movementSpanKey] : item[movementAxis])))\n ];\n\n return frontiers\n .map(frontier => createFrontierCandidate(placement, { target, context, ahead, frontier }))\n .filter(isDefined);\n}\n\nfunction createFrontierCandidate(\n placement: PlacementInput,\n input: {\n target: DashboardGridGeometry;\n context: MovementAxes;\n ahead: readonly DashboardItem[];\n frontier: number | null;\n }\n): PlacementCandidate | undefined {\n const { items, source, tracks } = placement;\n const { target, context, ahead, frontier } = input;\n const { movementAxis, movementSpanKey, direction } = context;\n const crossed =\n frontier === null\n ? []\n : ahead.filter(item =>\n direction > 0 ? item[movementAxis] + item[movementSpanKey] <= frontier : item[movementAxis] >= frontier\n );\n const ids = new Set(crossed.map(item => item.id));\n const remaining = ahead.filter(item => !ids.has(item.id));\n const { lo, hi, shift } = getFrontierRange(placement, { crossed, remaining, context });\n if (lo > hi) return undefined;\n\n const carried = { ...target, id: source.id, [movementAxis]: Math.max(lo, Math.min(hi, target[movementAxis])) };\n const protectedIds = new Set([source.id, ...ids]);\n const proposed = items.map(item => {\n if (item.id === source.id) return carried;\n if (ids.has(item.id)) return { ...item, [movementAxis]: item[movementAxis] + shift };\n\n return item;\n });\n const plan = propagateDisplacement(proposed, protectedIds, {\n movementAxis,\n direction: direction === 1 ? -1 : 1,\n tracks\n });\n\n return plan && isPlacementPlanValid(plan, tracks) ? { items: plan, placedItem: carried, priority: 0 } : undefined;\n}\n\nfunction getFrontierRange(\n placement: PlacementInput,\n input: { crossed: readonly DashboardItem[]; remaining: readonly DashboardItem[]; context: MovementAxes }\n): { lo: number; hi: number; shift: number } {\n const { source, tracks } = placement;\n const { crossed, remaining, context } = input;\n const { movementAxis, movementSpanKey, direction } = context;\n if (direction > 0) {\n return {\n lo: Math.max(\n source[movementAxis],\n crossed.length\n ? Math.max(...crossed.map(item => item[movementAxis] + item[movementSpanKey])) - source[movementSpanKey]\n : source[movementAxis]\n ),\n hi: Math.min(\n movementAxis === 'column' ? tracks - source[movementSpanKey] : extent - source[movementSpanKey],\n remaining.length ? Math.min(...remaining.map(item => item[movementAxis])) - source[movementSpanKey] : Infinity\n ),\n shift: crossed.length ? source[movementAxis] - Math.min(...crossed.map(item => item[movementAxis])) : 0\n };\n }\n\n return {\n lo: Math.max(\n 0,\n remaining.length ? Math.max(...remaining.map(item => item[movementAxis] + item[movementSpanKey])) : 0\n ),\n hi: Math.min(\n source[movementAxis],\n crossed.length ? Math.min(...crossed.map(item => item[movementAxis])) : source[movementAxis]\n ),\n shift: crossed.length\n ? source[movementAxis] +\n source[movementSpanKey] -\n Math.max(...crossed.map(item => item[movementAxis] + item[movementSpanKey]))\n : 0\n };\n}\n\nfunction getOccupiedIntervals(\n items: readonly DashboardItem[],\n target: DashboardGridGeometry,\n context: MovementAxes\n): [number, number][] {\n const { movementAxis, perpendicularAxis, movementSpanKey, perpendicularSpanKey } = context;\n const occupied = items\n .filter(\n item =>\n item[perpendicularAxis] < target[perpendicularAxis] + target[perpendicularSpanKey] &&\n item[perpendicularAxis] + item[perpendicularSpanKey] > target[perpendicularAxis]\n )\n .map((item): [number, number] => [item[movementAxis], item[movementAxis] + item[movementSpanKey]])\n .sort((a, b) => a[0] - b[0] || a[1] - b[1]);\n const merged: [number, number][] = [];\n\n for (const interval of occupied) {\n const last = merged.at(-1);\n\n if (last && interval[0] <= last[1]) {\n last[1] = Math.max(last[1], interval[1]);\n } else {\n merged.push([interval[0], interval[1]]);\n }\n }\n\n return merged;\n}\n\nfunction getClearIntervals(occupied: readonly [number, number][], max: number, span: number): [number, number][] {\n const clear: [number, number][] = [];\n let start = 0;\n\n for (const interval of occupied) {\n if (start <= interval[0] - span) {\n clear.push([start, interval[0] - span]);\n }\n\n start = Math.max(start, interval[1]);\n }\n\n if (start <= max) {\n clear.push([start, max]);\n }\n\n return clear;\n}\n\nfunction getDisplacementUpdates(\n blocker: DashboardItem,\n items: readonly DashboardItem[],\n input: { movementAxis: Axis; direction: Direction; tracks: number; protectedIds: ReadonlySet<string> }\n): DashboardItem[] | undefined {\n const { movementAxis, direction, tracks, protectedIds } = input;\n const movementSpanKey = movementAxis === 'column' ? 'columnSpan' : 'rowSpan';\n const collisions = items\n .filter(item => item.id !== blocker.id && doDashboardGridGeometriesOverlap(item, blocker))\n .sort((a, b) => direction * (a[movementAxis] - b[movementAxis]) || compareItems(a, b));\n const updates: DashboardItem[] = [];\n\n for (const item of collisions) {\n if (protectedIds.has(item.id)) return undefined;\n\n const next = {\n ...item,\n [movementAxis]:\n direction < 0 ? blocker[movementAxis] - item[movementSpanKey] : blocker[movementAxis] + blocker[movementSpanKey]\n };\n if (next.column < 0 || next.row < 0 || next.column + next.columnSpan > tracks || next.row + next.rowSpan > extent) {\n return undefined;\n }\n\n updates.push(next);\n }\n\n return updates;\n}\n"],"mappings":"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"}
@@ -985,6 +985,146 @@
985
985
  }
986
986
  ]
987
987
  },
988
+ {
989
+ "name": "nve-dashboard",
990
+ "description": "A dashboard arranges application panels on a resizable grid with a restorable layout.\n---\n\n\n### **Events:**\n - **change** - Announces one committed arrangement after interaction, commands, or panel membership and span-constraint reconciliation. Read value on the dashboard; authored content events still bubble normally.\n- **commandavailabilitychange** - Arrangement or fullscreen command availability may have changed.\n\n### **Methods:**\n - **place(id: _string_, placement: _DashboardGridPlacement_): _boolean_** - Requests an integer placement without gesture target snapping. Anchored span changes use resizing permission, including left and top edges that change the origin; other position changes require movement. Directional collisions and optional growth-axis settling determine the final arrangement. Returns false for unavailable, invalid, or unchanged normalized placement. Successful placement emits one change.\n- **isCommandAvailable(command: _string_, context: _DashboardCommandContext_): _boolean_** - Queries arrangement and fullscreen commands using a panel ID. A placement supplies the full grid placement for --place, or the desired bounded-axis coordinate for --move-to-start. Availability compares the complete normalized proposal with the current arrangement. Directional movement derives from grid placement and panel permissions without requiring rendered controls. Native fullscreen admission remains subject to browser permission.\n\n### **Slots:**\n - _default_ - Direct dashboard panels with unique durable IDs, required headers, and application dropdown groups. DOM order remains application authored. Native reading order follows committed placement where supported; previews preserve that order.\n\n### **CSS Properties:**\n - **--column-size** - Single-cell outer column length in fixed sizing or horizontal flow. Defaults to 160px. _(default: undefined)_\n- **--row-size** - Single-cell outer row length in fixed sizing or vertical flow. Defaults to 120px. _(default: undefined)_\n- **--gap** - Nonnegative CSS length between cells. Include units, including 0px for no gap. At zero, uniform used border widths overlap; unequal widths keep independent geometry. Shared seams assume square panels with solid opaque borders. [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/gap) _(default: undefined)_\n- **--guide-color** - Color of the circular cell-center guides. Defaults to the muted border color. _(default: undefined)_\n- **--guide-size** - Nonnegative CSS length for the guide circle diameter. Defaults to 8px. Include units, including 0px to hide the circles. _(default: undefined)_\n- **--height** - Default viewport height. Defaults to 400px; horizontal fit needs a definite height. [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/height) _(default: undefined)_\n- **--animation-duration** - Duration of panel geometry, destination ghost geometry, and arrangement control transitions. Defaults to 150ms; reduced motion uses 0ms. Panel geometry follows external container resizing immediately; explicit arrangement and sizing changes use transitions. Animation never delays logical placement commits. [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-duration) _(default: undefined)_\n- **--animation-easing** - Easing of panel and destination ghost geometry transitions. _(default: undefined)_\n\n### **CSS Parts:**\n - **ghost** - Inert placement preview shown during pointer arrangement.",
991
+ "attributes": [
992
+ {
993
+ "name": "rearrangeable",
994
+ "description": "Enables moving and resizing panels through controls and placement commands.",
995
+ "values": []
996
+ },
997
+ {
998
+ "name": "fullscreenable",
999
+ "description": "Enables native fullscreen commands and a header control for each panel. Turning this off preserves an accepted session and its exit control. Fullscreen does not change the saved arrangement.",
1000
+ "values": []
1001
+ },
1002
+ {
1003
+ "name": "container",
1004
+ "description": "Selects panel content framing.",
1005
+ "values": [
1006
+ { "name": "inset" },
1007
+ { "name": "flat" },
1008
+ { "name": "full" }
1009
+ ]
1010
+ },
1011
+ {
1012
+ "name": "sizing",
1013
+ "description": "Cell sizing, defaulting to fit. Fit sizing fits bounded tracks to the viewport and scrolls along the growth axis. Fixed sizing uses the configured --column-size and --row-size dimensions and may scroll on both axes. Does not change value.",
1014
+ "values": [{ "name": "fit" }, { "name": "fixed" }]
1015
+ },
1016
+ {
1017
+ "name": "guides",
1018
+ "description": "Guide visibility: auto shows circular cell-center guides during pointer arrangement, visible always shows them, and hidden hides them while keeping the destination preview. Attribute keywords ignore case; missing, empty, or unrecognized values use auto. Does not change value or interaction permissions.",
1019
+ "values": [
1020
+ { "name": "auto" },
1021
+ { "name": "visible" },
1022
+ { "name": "hidden" }
1023
+ ]
1024
+ },
1025
+ {
1026
+ "name": "autosettle",
1027
+ "description": "Closes growth-axis gaps toward top in vertical flow or inline start in horizontal flow, preserving bounded-axis positions and spans. Defaults to false. Enabling silently canonicalizes the current arrangement; disabling keeps current coordinates. This policy is independent of value.",
1028
+ "values": []
1029
+ },
1030
+ {
1031
+ "name": "value",
1032
+ "description": "Version 1 JSON with grid {flow, tracks} and items {id, column, row, columnSpan, rowSpan}. Positions are zero-based cells from inline start and top; column zero is at the right in RTL. Spans count columns and rows. Defaults to an empty string, which seeds one-cell panels in DOM order. Assignment validates the saved model immediately and normalizes panels once their upgrades and unique nonempty IDs are ready; restoration is silent. Intentional gaps remain when autoSettle is false. After successful reconciliation, only direct default-slot panel children remain in the value, including hidden children. Removed panels lose their placement. Applications own content data, persistence, and any saved placement history.",
1033
+ "values": []
1034
+ },
1035
+ {
1036
+ "name": "flow",
1037
+ "description": "Growth direction, defaulting to vertical with bounded columns. Horizontal flow bounds rows. Changing flow does not transpose panel coordinates or spans. Assignment updates the arrangement silently; changes that conflict with panel constraints throw before changing the arrangement.",
1038
+ "values": [{ "name": "vertical" }, { "name": "horizontal" }]
1039
+ },
1040
+ {
1041
+ "name": "tracks",
1042
+ "description": "Bounded-axis track count, defaulting to 12. Valid integers range from 1 through 1000000. Assignment updates the arrangement silently and rejects changes that conflict with panel constraints.",
1043
+ "values": []
1044
+ }
1045
+ ],
1046
+ "references": [
1047
+ {
1048
+ "name": "Documentation",
1049
+ "url": "https://nvidia.github.io/elements/docs/elements/dashboard/"
1050
+ }
1051
+ ]
1052
+ },
1053
+ {
1054
+ "name": "nve-dashboard-panel-content",
1055
+ "description": "Provides padding for dashboard panel content.\n---\n\n\n### **Slots:**\n - _default_ - Application content.\n\n### **CSS Properties:**\n - **--padding** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) _(default: undefined)_",
1056
+ "attributes": [],
1057
+ "references": [
1058
+ {
1059
+ "name": "Documentation",
1060
+ "url": "https://nvidia.github.io/elements/docs/elements/dashboard/"
1061
+ }
1062
+ ]
1063
+ },
1064
+ {
1065
+ "name": "nve-dashboard-panel-footer",
1066
+ "description": "Provides dashboard panel status and actions outside the scrolling body.\n---\n\n\n### **Slots:**\n - _default_ - Status and supporting content in a bounded scrolling area.\n- **suffix** - Application actions in a bounded scrolling area before the reserved resize control.\n\n### **CSS Properties:**\n - **--padding** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) _(default: undefined)_\n- **--suffix-padding** - Padding around application actions. Defaults to 4px. _(default: undefined)_\n- **--gap** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/gap) _(default: undefined)_",
1067
+ "attributes": [],
1068
+ "references": [
1069
+ {
1070
+ "name": "Documentation",
1071
+ "url": "https://nvidia.github.io/elements/docs/elements/dashboard/"
1072
+ }
1073
+ ]
1074
+ },
1075
+ {
1076
+ "name": "nve-dashboard-panel-header",
1077
+ "description": "Supplies the required dashboard panel title and application controls.\n---\n\n\n### **Slots:**\n - _default_ - Noninteractive title used as the default accessible panel name. Heading semantics remain application owned.\n- **prefix** - Title decoration.\n- **suffix** - Application controls.\n\n### **CSS Properties:**\n - **--padding** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) _(default: undefined)_\n- **--suffix-padding** - Padding around application actions. Defaults to 4px. _(default: undefined)_\n- **--gap** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/gap) _(default: undefined)_\n- **--min-height** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/min-height) _(default: undefined)_",
1078
+ "attributes": [],
1079
+ "references": [
1080
+ {
1081
+ "name": "Documentation",
1082
+ "url": "https://nvidia.github.io/elements/docs/elements/dashboard/"
1083
+ }
1084
+ ]
1085
+ },
1086
+ {
1087
+ "name": "nve-dashboard-panel",
1088
+ "description": "A stable application surface identified by a durable panel ID.\n---\n\n\n### **Slots:**\n - _default_ - Application content in the scrolling body. Content, data, and native hidden state remain application owned.\n- **header** - Required panel header with a title and optional application controls.\n- **footer** - Optional status and actions outside the body.\n\n### **CSS Properties:**\n - **--background** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/background) _(default: undefined)_\n- **--border** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border) _(default: undefined)_\n- **--border-radius** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius) _(default: undefined)_\n- **--control-width** - Width shared by the move and resize controls. Defaults to 36px. [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/width) _(default: undefined)_\n- **--control-height** - Height shared by the move and resize controls. Defaults to 48px. [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/height) _(default: undefined)_\n- **--resize-target-size** - Extra pointer resize reach on each side of the panel edge. Defaults to 3px; outward reach stops halfway across the cell gap. Configure on the panel. Inward reach covers application content at the edge, including on hybrid touch devices. _(default: undefined)_\n- **--box-shadow** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow) _(default: undefined)_\n\n### **CSS Parts:**\n - **drag-handle** - Movement control.\n- **resize-button** - Resize control.\n- **fullscreen-button** - Panel fullscreen control.",
1089
+ "attributes": [
1090
+ {
1091
+ "name": "min-column-span",
1092
+ "description": "Smallest width in columns.",
1093
+ "values": []
1094
+ },
1095
+ {
1096
+ "name": "min-row-span",
1097
+ "description": "Smallest height in rows.",
1098
+ "values": []
1099
+ },
1100
+ {
1101
+ "name": "max-column-span",
1102
+ "description": "Largest width in columns.",
1103
+ "values": []
1104
+ },
1105
+ {
1106
+ "name": "max-row-span",
1107
+ "description": "Largest height in rows.",
1108
+ "values": []
1109
+ },
1110
+ {
1111
+ "name": "move-disabled",
1112
+ "description": "Disables direct movement. Collision displacement remains available.",
1113
+ "values": []
1114
+ },
1115
+ {
1116
+ "name": "resize-disabled",
1117
+ "description": "Disables direct resizing.",
1118
+ "values": []
1119
+ }
1120
+ ],
1121
+ "references": [
1122
+ {
1123
+ "name": "Documentation",
1124
+ "url": "https://nvidia.github.io/elements/docs/elements/dashboard/"
1125
+ }
1126
+ ]
1127
+ },
988
1128
  {
989
1129
  "name": "nve-date",
990
1130
  "description": "A date picker is a control that enables users to choose a date value.\n---\n\n\n### **Events:**\n - **reset**\n\n### **Methods:**\n - **reset()** - Resets control value to initial attribute value and clears any active validation rules.\n\n### **Slots:**\n - _default_ - Control input element\n- **label** - Label element\n\n### **CSS Properties:**\n - **--padding** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) _(default: undefined)_\n- **--font-size** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size) _(default: undefined)_\n- **--height** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/height) _(default: undefined)_\n- **--background** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/background) _(default: undefined)_\n- **--color** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/color) _(default: undefined)_\n- **--border-radius** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius) _(default: undefined)_\n- **--border** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border) _(default: undefined)_\n- **--border-bottom** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom) _(default: undefined)_\n- **--cursor** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) _(default: undefined)_\n- **--font-weight** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight) _(default: undefined)_\n- **--width** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/width) _(default: undefined)_\n- **--max-width** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/max-width) _(default: undefined)_\n- **--min-width** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/min-width) _(default: undefined)_\n- **--accent-color** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/accent-color) _(default: undefined)_\n- **--label-color** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/color) _(default: undefined)_\n- **--label-width** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/width) _(default: undefined)_\n- **--label-font-weight** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight) _(default: undefined)_\n- **--label-font-size** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size) _(default: undefined)_\n- **--control-width** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/width) _(default: undefined)_\n- **--control-height** - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/height) _(default: undefined)_\n\n### **CSS Parts:**\n - **icon-button** - The calendar icon button element",
@@ -6209,7 +6349,7 @@
6209
6349
  },
6210
6350
  {
6211
6351
  "name": "value",
6212
- "description": "Defines the value associated with the element's name when submitting the form data. The server receives this value in params when the form submits through this button. [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#value)",
6352
+ "description": "Versioned JSON arrangement. Assignment restores without emitting change.",
6213
6353
  "values": []
6214
6354
  }
6215
6355
  ],
@@ -22,7 +22,7 @@ var l = { expand: "expand" }, u = class extends n {
22
22
  static {
23
23
  this.metadata = {
24
24
  tag: "nve-date",
25
- version: "2.23.5"
25
+ version: "2.24.0"
26
26
  };
27
27
  }
28
28
  static {
@@ -22,7 +22,7 @@ var l = { expand: "expand" }, u = class extends n {
22
22
  static {
23
23
  this.metadata = {
24
24
  tag: "nve-datetime",
25
- version: "2.23.5"
25
+ version: "2.24.0"
26
26
  };
27
27
  }
28
28
  static {
@@ -9,7 +9,7 @@ var i = class extends t {
9
9
  static {
10
10
  this.metadata = {
11
11
  tag: "nve-dialog-footer",
12
- version: "2.23.5",
12
+ version: "2.24.0",
13
13
  parents: ["nve-dialog"]
14
14
  };
15
15
  }
@@ -9,7 +9,7 @@ var i = class extends t {
9
9
  static {
10
10
  this.metadata = {
11
11
  tag: "nve-dialog-header",
12
- version: "2.23.5",
12
+ version: "2.24.0",
13
13
  parents: ["nve-dialog"]
14
14
  };
15
15
  }
@@ -30,7 +30,7 @@ var h = { close: "close" }, g = class extends l {
30
30
  static {
31
31
  this.metadata = {
32
32
  tag: "nve-dialog",
33
- version: "2.23.5"
33
+ version: "2.24.0"
34
34
  };
35
35
  }
36
36
  static {
@@ -15,7 +15,7 @@ var s = class extends r {
15
15
  static {
16
16
  this.metadata = {
17
17
  tag: "nve-divider",
18
- version: "2.23.5"
18
+ version: "2.24.0"
19
19
  };
20
20
  }
21
21
  render() {
package/dist/dot/dot2.js CHANGED
@@ -17,7 +17,7 @@ var l = class extends a {
17
17
  static {
18
18
  this.metadata = {
19
19
  tag: "nve-dot",
20
- version: "2.23.5"
20
+ version: "2.24.0"
21
21
  };
22
22
  }
23
23
  render() {
@@ -13,7 +13,7 @@ var c = class extends s(r) {
13
13
  static {
14
14
  this.metadata = {
15
15
  tag: "nve-drag-handle",
16
- version: "2.23.5"
16
+ version: "2.24.0"
17
17
  };
18
18
  }
19
19
  static {
@@ -9,7 +9,7 @@ var i = class extends t {
9
9
  static {
10
10
  this.metadata = {
11
11
  tag: "nve-drawer-content",
12
- version: "2.23.5",
12
+ version: "2.24.0",
13
13
  parents: ["nve-drawer"]
14
14
  };
15
15
  }
@@ -9,7 +9,7 @@ var i = class extends t {
9
9
  static {
10
10
  this.metadata = {
11
11
  tag: "nve-drawer-footer",
12
- version: "2.23.5",
12
+ version: "2.24.0",
13
13
  parents: ["nve-drawer"]
14
14
  };
15
15
  }
@@ -9,7 +9,7 @@ var i = class extends t {
9
9
  static {
10
10
  this.metadata = {
11
11
  tag: "nve-drawer-header",
12
- version: "2.23.5",
12
+ version: "2.24.0",
13
13
  parents: ["nve-drawer"]
14
14
  };
15
15
  }
@@ -30,7 +30,7 @@ var p = { close: "close" }, m = class extends s {
30
30
  static {
31
31
  this.metadata = {
32
32
  tag: "nve-drawer",
33
- version: "2.23.5"
33
+ version: "2.24.0"
34
34
  };
35
35
  }
36
36
  static {
@@ -9,7 +9,7 @@ var i = class extends t {
9
9
  static {
10
10
  this.metadata = {
11
11
  tag: "nve-dropdown-footer",
12
- version: "2.23.5",
12
+ version: "2.24.0",
13
13
  parents: ["nve-dropdown"]
14
14
  };
15
15
  }
@@ -9,7 +9,7 @@ var i = class extends t {
9
9
  static {
10
10
  this.metadata = {
11
11
  tag: "nve-dropdown-header",
12
- version: "2.23.5",
12
+ version: "2.24.0",
13
13
  parents: ["nve-dropdown"]
14
14
  };
15
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown.examples.js","names":["dropdown_examples_default"],"sources":["../../src/dropdown/dropdown.examples.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { html } from 'lit';\nimport '@nvidia-elements/core/card/define.js';\nimport '@nvidia-elements/core/button/define.js';\nimport '@nvidia-elements/core/forms/define.js';\nimport '@nvidia-elements/core/dropdown/define.js';\nimport '@nvidia-elements/core/radio/define.js';\nimport '@nvidia-elements/core/checkbox/define.js';\nimport '@nvidia-elements/core/icon/define.js';\nimport '@nvidia-elements/core/menu/define.js';\nimport '@nvidia-elements/core/tooltip/define.js';\n\nexport default {\n title: 'Elements/Dropdown',\n component: 'nve-dropdown'\n};\n\n/* eslint-disable @nvidia-elements/lint/no-missing-popover-trigger */\n\n/**\n * @summary Basic dropdown implementation using popovertarget attribute to connect trigger and dropdown. Useful for simple dropdown menus.\n */\nexport const Default = {\n render: () => html`\n<nve-button popovertarget=\"dropdown\">button</nve-button>\n<nve-dropdown id=\"dropdown\">dropdown content</nve-dropdown>\n `\n};\n\n/**\n * @summary Dropdown with popover-positioned menu for trigger-based actions. Use for context menus, settings, and user actions where content appears on demand relative to a trigger button.\n */\nexport const Menu = {\n render: () => html`\n <nve-button popovertarget=\"dropdown-menu\">dropdown</nve-button>\n <nve-dropdown id=\"dropdown-menu\">\n <nve-menu>\n <nve-menu-item><nve-icon name=\"person\"></nve-icon> profile</nve-menu-item>\n <nve-menu-item><nve-icon name=\"gear\"></nve-icon> settings</nve-menu-item>\n <nve-menu-item><nve-icon name=\"star\"></nve-icon> favorites</nve-menu-item>\n <nve-divider></nve-divider>\n <nve-menu-item><nve-icon name=\"logout\"></nve-icon> logout</nve-menu-item>\n </nve-menu>\n </nve-dropdown>\n `\n};\n\n/**\n * @summary Closed dropdowns anchored to a resizable panel. Measure repeated layout before and after opening and dismissing every menu.\n * @tags test-case performance\n */\nexport const ClosedPopoverLayout = {\n render: () => html`\n<section id=\"closed-popover-layout\" nve-layout=\"column gap:md\">\n <p nve-text=\"body\">Measure 120 resize/layout operations with 64 closed menus, first fresh and then after dismissal. Lower times mean less work.</p>\n <nve-button data-run>Run benchmark</nve-button>\n <p nve-text=\"body\" role=\"status\">Ready. Each run resets the menus; setup time is excluded.</p>\n <div data-panel nve-layout=\"column gap:sm pad:sm\" style=\"resize: horizontal; overflow: auto; width: 640px; min-width: 320px; max-width: 100%; height: 360px;\">\n ${Array.from({ length: 64 }, (_, index) => html`\n <div nve-layout=\"row full:width align:right\">\n <nve-button popovertarget=${`closed-popover-layout-menu-${index}`}>Menu ${index + 1}</nve-button>\n <nve-dropdown id=${`closed-popover-layout-menu-${index}`}>Menu ${index + 1} content</nve-dropdown>\n </div>\n `)}\n </div>\n</section>\n<script type=\"module\">\n const root = document.querySelector('#closed-popover-layout');\n let panel = root.querySelector('[data-panel]');\n const template = panel.cloneNode(true);\n const button = root.querySelector('[data-run]');\n const status = root.querySelector('[role=\"status\"]');\n\n function measure() {\n panel.style.width = '640px';\n panel.getBoundingClientRect();\n const start = performance.now();\n for (let iteration = 0; iteration < 120; iteration++) {\n panel.style.width = (iteration % 2 ? 800 : 480) + 'px';\n // Force each width change to finish layout within the measured interval.\n panel.getBoundingClientRect();\n }\n const elapsed = performance.now() - start;\n return elapsed.toFixed(1) + ' ms (' + (elapsed / 120).toFixed(2) + ' ms/operation)';\n }\n\n button.addEventListener('click', async () => {\n button.disabled = true;\n status.textContent = 'Running both measurements…';\n try {\n const freshPanel = template.cloneNode(true);\n panel.replaceWith(freshPanel);\n panel = freshPanel;\n const menus = Array.from(panel.querySelectorAll('nve-dropdown'));\n await Promise.all(menus.map(menu => menu.updateComplete));\n await new Promise(requestAnimationFrame);\n const fresh = measure();\n for (const menu of menus) {\n menu.showPopover({ source: menu.previousElementSibling });\n // Flush open layout only during preparation so exit transitions can run.\n menu.getBoundingClientRect();\n menu.hidePopover();\n }\n await new Promise(requestAnimationFrame);\n await Promise.allSettled(menus.flatMap(menu => menu.getAnimations().map(animation => animation.finished)));\n const dismissed = measure();\n status.textContent = '120 resize/layout operations each. Never opened: ' + fresh + '. After dismissal: ' + dismissed + '.';\n } finally {\n button.disabled = false;\n }\n });\n</script>\n `\n};\n\n/**\n * @summary Dropdown using anchor attribute to reference trigger element by ID. Alternative approach for connecting dropdowns to their triggers.\n * @tags test-case\n */\nexport const Visual = {\n render: () => html`\n<nve-dropdown anchor=\"btn\">dropdown content</nve-dropdown>\n<nve-button id=\"btn\">button</nve-button>\n `\n};\n\n/**\n * @summary Event handling for dropdown open and close events. Useful for adding custom behavior when dropdown state changes.\n * @tags test-case\n */\nexport const Events = {\n inline: false,\n render: () => html`\n<nve-dropdown id=\"dropdown\">dropdown content</nve-dropdown>\n<nve-button popovertarget=\"dropdown\">button</nve-button>\n<script type=\"module\">\n const dropdown = document.querySelector('nve-dropdown');\n dropdown.addEventListener('beforetoggle', () => console.log('beforetoggle'));\n dropdown.addEventListener('toggle', () => console.log('toggle'));\n dropdown.addEventListener('open', () => console.log('open'));\n dropdown.addEventListener('close', () => console.log('close'));\n</script>\n `\n};\n\n/**\n * @summary Dropdown with closable attribute that allows users to dismiss the dropdown by clicking close button.\n * @tags test-case\n */\nexport const Closable = {\n render: () => html`\n<nve-dropdown anchor=\"btn\" closable>\n <h3 nve-text=\"label\">Title</h3>\n <p nve-text=\"body\">some text content in a closable dropdown</p>\n</nve-dropdown>\n<nve-button id=\"btn\">button</nve-button>\n `\n};\n\n/**\n * @summary Dropdown with structured content using header and footer sections. Perfect for complex dropdown content that needs clear visual hierarchy.\n * @tags test-case\n */\nexport const Layout = {\n render: () => html`\n<nve-dropdown anchor=\"btn\">\n <nve-dropdown-header>\n <h3 nve-text=\"heading semibold sm\">heading</h3>\n </nve-dropdown-header>\n <p nve-text=\"body\">some text content in a closable dropdown</p>\n <nve-dropdown-footer>\n <p nve-text=\"body\">footer</p>\n </nve-dropdown-footer>\n</nve-dropdown>\n<nve-button id=\"btn\">button</nve-button>\n `\n};\n\n/**\n * @summary Dropdown with many triggers, showing how to use the popovertarget attribute to connect many triggers to the same dropdown.\n * @tags test-case\n */\nexport const MultipleTriggers = {\n render: () => html`\n<div nve-layout=\"row gap:sm align:center\">\n <nve-button popovertarget=\"dropdown\">button</nve-button>\n <nve-button popovertarget=\"dropdown\">button</nve-button>\n <nve-button popovertarget=\"dropdown\">button</nve-button>\n <nve-dropdown id=\"dropdown\">hello there</nve-dropdown>\n</div>\n `\n};\n\n/**\n * @summary Dropdown position, with the position attribute controlling placement when the trigger is not visible.\n * @tags test-case\n */\nexport const Position = {\n render: () => html`\n<nve-dropdown anchor=\"card\" position=\"top\" alignment=\"center\">\n <h3 nve-text=\"label\">Top</h3>\n <p nve-text=\"body\">dropdown positioned top</p>\n</nve-dropdown>\n<nve-dropdown anchor=\"card\" position=\"right\" alignment=\"center\">\n <h3 nve-text=\"label\">Right</h3>\n <p nve-text=\"body\">dropdown positioned right</p>\n</nve-dropdown>\n<nve-dropdown anchor=\"card\" position=\"bottom\" alignment=\"center\">\n <h3 nve-text=\"label\">Bottom</h3>\n <p nve-text=\"body\">dropdown positioned bottom</p>\n</nve-dropdown>\n<nve-dropdown anchor=\"card\" position=\"left\" alignment=\"center\">\n <h3 nve-text=\"label\">Left</h3>\n <p nve-text=\"body\">dropdown positioned left</p>\n</nve-dropdown>\n<nve-card id=\"card\" style=\"width: 250px; height: 200px;\"></nve-card>\n `\n};\n\n/**\n * @summary Dropdown alignment, with the alignment attribute controlling horizontal placement relative to the trigger.\n * @tags test-case\n */\nexport const Alignment = {\n render: () => html`\n<div nve-theme nve-layout=\"row align:center\">\n <nve-dropdown open anchor=\"card\" position=\"top\" alignment=\"start\">top start</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"top\" alignment=\"center\">top center</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"top\" alignment=\"end\">top end</nve-dropdown>\n\n <nve-dropdown open anchor=\"card\" position=\"right\" alignment=\"start\">right start</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"right\" alignment=\"center\">right center</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"right\" alignment=\"end\">right end</nve-dropdown>\n\n <nve-dropdown open anchor=\"card\" position=\"bottom\" alignment=\"start\">bottom start</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"bottom\" alignment=\"center\">bottom center</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"bottom\" alignment=\"end\">bottom end</nve-dropdown>\n\n <nve-dropdown open anchor=\"card\" position=\"left\" alignment=\"start\">left start</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"left\" alignment=\"center\">left center</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"left\" alignment=\"end\">left end</nve-dropdown>\n\n <nve-card id=\"card\" style=\"width: 450px; height: 300px; margin-top: 50px;\"></nve-card>\n</div>\n `\n};\n\n/**\n * @summary Dropdown containing a radio group for single-selection options. Perfect for sort controls, filter selections, or preference settings.\n * @tags test-case\n */\nexport const RadioGroup = {\n render: () => html`\n<nve-dropdown anchor=\"btn\">\n <nve-radio-group style=\"width: 250px\">\n <label>Sort By</label>\n <nve-radio>\n <label>Completed</label>\n <input type=\"radio\" checked />\n <nve-control-message>latest completed tasks</nve-control-message>\n </nve-radio>\n <nve-radio>\n <label>Failing</label>\n <input type=\"radio\" />\n <nve-control-message>latest failing tasks</nve-control-message>\n </nve-radio>\n <nve-radio>\n <label>Status</label>\n <input type=\"radio\" />\n <nve-control-message>task status priority</nve-control-message>\n </nve-radio>\n </nve-radio-group>\n</nve-dropdown>\n<nve-button id=\"btn\" nve-control>completed <nve-icon name=\"caret\" direction=\"down\" size=\"sm\"></nve-icon></nve-button>\n `\n};\n\n/**\n * @summary Dropdown containing a checkbox group for multi-selection options. Ideal for filter controls, feature toggles, or bulk action selections.\n * @tags test-case\n */\nexport const CheckboxGroup = {\n render: () => html`\n<nve-dropdown anchor=\"btn\">\n <nve-checkbox-group style=\"width: 250px\">\n <label>Test Suites</label>\n <nve-checkbox>\n <label>Local</label>\n <input type=\"checkbox\" />\n </nve-checkbox>\n <nve-checkbox>\n <label>Nightly</label>\n <input type=\"checkbox\" checked />\n </nve-checkbox>\n <nve-checkbox>\n <label>Remote</label>\n <input type=\"checkbox\" />\n </nve-checkbox>\n </nve-checkbox-group>\n</nve-dropdown>\n<nve-button id=\"btn\" nve-control>test suites <nve-icon name=\"caret\" direction=\"down\" size=\"sm\"></nve-icon></nve-button>\n `\n};\n\n/* eslint-disable @nvidia-elements/lint/no-deprecated-popover-attributes */\n\n/**\n * @deprecated\n * @summary Legacy behavior trigger for dropdown, using the behavior-trigger attribute to open the dropdown on button click.\n * @tags test-case\n */\nexport const LegacyBehaviorTrigger = {\n inline: false,\n render: () => html`\n<nve-button id=\"dropdown-btn\">open</nve-button>\n<nve-dropdown anchor=\"dropdown-btn\" trigger=\"dropdown-btn\" behavior-trigger hidden>\n <p nve-text=\"body\">hello there</p>\n</nve-dropdown>\n `\n};\n\n/**\n * @deprecated\n * @summary Dropdown hint, using the tooltip element to display a hint when the dropdown opens.\n * @tags test-case\n */\nexport const Hint = {\n render: () => html`\n<nve-dropdown id=\"dropdown\">\n dropdown content\n</nve-dropdown>\n\n<nve-tooltip id=\"tooltip\" hidden behavior-trigger trigger=\"btn\">dropdown content</nve-tooltip>\n\n<nve-icon-button id=\"btn\" popovertarget=\"dropdown\" icon-name=\"gear\" aria-label=\"settings\"></nve-icon-button>\n `\n};\n\n/**\n * @summary Dropdown position fallback, using the position and alignment attributes to reposition the dropdown when the trigger is not visible.\n * @tags test-case\n */\nexport const PositionFallback = {\n render: () => html`\n<style>\n body {\n align-items: start !important;\n margin: 0;\n padding: 0 !important;\n }\n</style>\n\n<nve-dropdown anchor=\"btn\" position=\"bottom\" alignment=\"center\">\n dropdown content\n</nve-dropdown>\n\n<nve-dropdown anchor=\"btn\" position=\"right\" alignment=\"center\">\n dropdown content\n</nve-dropdown>\n\n<nve-icon-button id=\"btn\" icon-name=\"gear\" aria-label=\"settings\"></nve-icon-button>\n `\n};\n"],"mappings":";AAGA,IAAAA,IAAS"}
1
+ {"version":3,"file":"dropdown.examples.js","names":["dropdown_examples_default"],"sources":["../../src/dropdown/dropdown.examples.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { html } from 'lit';\nimport '@nvidia-elements/core/card/define.js';\nimport '@nvidia-elements/core/button/define.js';\nimport '@nvidia-elements/core/forms/define.js';\nimport '@nvidia-elements/core/dropdown/define.js';\nimport '@nvidia-elements/core/radio/define.js';\nimport '@nvidia-elements/core/checkbox/define.js';\nimport '@nvidia-elements/core/icon/define.js';\nimport '@nvidia-elements/core/menu/define.js';\nimport '@nvidia-elements/core/tooltip/define.js';\n\nexport default {\n title: 'Elements/Dropdown',\n component: 'nve-dropdown'\n};\n\n/**\n * @summary Basic dropdown implementation using popovertarget attribute to connect trigger and dropdown. Useful for simple dropdown menus.\n */\nexport const Default = {\n render: () => html`\n<nve-button popovertarget=\"dropdown\">button</nve-button>\n<nve-dropdown id=\"dropdown\">dropdown content</nve-dropdown>\n `\n};\n\n/**\n * @summary Dropdown with popover-positioned menu for trigger-based actions. Use for context menus, settings, and user actions where content appears on demand relative to a trigger button.\n */\nexport const Menu = {\n render: () => html`\n <nve-button popovertarget=\"dropdown-menu\">dropdown</nve-button>\n <nve-dropdown id=\"dropdown-menu\">\n <nve-menu>\n <nve-menu-item><nve-icon name=\"person\"></nve-icon> profile</nve-menu-item>\n <nve-menu-item><nve-icon name=\"gear\"></nve-icon> settings</nve-menu-item>\n <nve-menu-item><nve-icon name=\"star\"></nve-icon> favorites</nve-menu-item>\n <nve-divider></nve-divider>\n <nve-menu-item><nve-icon name=\"logout\"></nve-icon> logout</nve-menu-item>\n </nve-menu>\n </nve-dropdown>\n `\n};\n\n/**\n * @summary Closed dropdowns anchored to a resizable panel. Measure repeated layout before and after opening and dismissing every menu.\n * @tags test-case performance\n */\nexport const ClosedPopoverLayout = {\n render: () => html`\n<section id=\"closed-popover-layout\" nve-layout=\"column gap:md\">\n <p nve-text=\"body\">Measure 120 resize/layout operations with 64 closed menus, first fresh and then after dismissal. Lower times mean less work.</p>\n <nve-button data-run>Run benchmark</nve-button>\n <p nve-text=\"body\" role=\"status\">Ready. Each run resets the menus; setup time is excluded.</p>\n <div data-panel nve-layout=\"column gap:sm pad:sm\" style=\"resize: horizontal; overflow: auto; width: 640px; min-width: 320px; max-width: 100%; height: 360px;\">\n ${Array.from({ length: 64 }, (_, index) => html`\n <div nve-layout=\"row full:width align:right\">\n <nve-button popovertarget=${`closed-popover-layout-menu-${index}`}>Menu ${index + 1}</nve-button>\n <nve-dropdown id=${`closed-popover-layout-menu-${index}`}>Menu ${index + 1} content</nve-dropdown>\n </div>\n `)}\n </div>\n</section>\n<script type=\"module\">\n const root = document.querySelector('#closed-popover-layout');\n let panel = root.querySelector('[data-panel]');\n const template = panel.cloneNode(true);\n const button = root.querySelector('[data-run]');\n const status = root.querySelector('[role=\"status\"]');\n\n function measure() {\n panel.style.width = '640px';\n panel.getBoundingClientRect();\n const start = performance.now();\n for (let iteration = 0; iteration < 120; iteration++) {\n panel.style.width = (iteration % 2 ? 800 : 480) + 'px';\n // Force each width change to finish layout within the measured interval.\n panel.getBoundingClientRect();\n }\n const elapsed = performance.now() - start;\n return elapsed.toFixed(1) + ' ms (' + (elapsed / 120).toFixed(2) + ' ms/operation)';\n }\n\n button.addEventListener('click', async () => {\n button.disabled = true;\n status.textContent = 'Running both measurements…';\n try {\n const freshPanel = template.cloneNode(true);\n panel.replaceWith(freshPanel);\n panel = freshPanel;\n const menus = Array.from(panel.querySelectorAll('nve-dropdown'));\n await Promise.all(menus.map(menu => menu.updateComplete));\n await new Promise(requestAnimationFrame);\n const fresh = measure();\n for (const menu of menus) {\n menu.showPopover({ source: menu.previousElementSibling });\n // Flush open layout only during preparation so exit transitions can run.\n menu.getBoundingClientRect();\n menu.hidePopover();\n }\n await new Promise(requestAnimationFrame);\n await Promise.allSettled(menus.flatMap(menu => menu.getAnimations().map(animation => animation.finished)));\n const dismissed = measure();\n status.textContent = '120 resize/layout operations each. Never opened: ' + fresh + '. After dismissal: ' + dismissed + '.';\n } finally {\n button.disabled = false;\n }\n });\n</script>\n `\n};\n\n/**\n * @summary Dropdown using anchor attribute to reference trigger element by ID. Alternative approach for connecting dropdowns to their triggers.\n * @tags test-case\n */\nexport const Visual = {\n render: () => html`\n<nve-dropdown anchor=\"btn\">dropdown content</nve-dropdown>\n<nve-button id=\"btn\">button</nve-button>\n `\n};\n\n/**\n * @summary Event handling for dropdown open and close events. Useful for adding custom behavior when dropdown state changes.\n * @tags test-case\n */\nexport const Events = {\n inline: false,\n render: () => html`\n<nve-dropdown id=\"dropdown\">dropdown content</nve-dropdown>\n<nve-button popovertarget=\"dropdown\">button</nve-button>\n<script type=\"module\">\n const dropdown = document.querySelector('nve-dropdown');\n dropdown.addEventListener('beforetoggle', () => console.log('beforetoggle'));\n dropdown.addEventListener('toggle', () => console.log('toggle'));\n dropdown.addEventListener('open', () => console.log('open'));\n dropdown.addEventListener('close', () => console.log('close'));\n</script>\n `\n};\n\n/**\n * @summary Dropdown with closable attribute that allows users to dismiss the dropdown by clicking close button.\n * @tags test-case\n */\nexport const Closable = {\n render: () => html`\n<nve-dropdown anchor=\"btn\" closable>\n <h3 nve-text=\"label\">Title</h3>\n <p nve-text=\"body\">some text content in a closable dropdown</p>\n</nve-dropdown>\n<nve-button id=\"btn\">button</nve-button>\n `\n};\n\n/**\n * @summary Dropdown with structured content using header and footer sections. Perfect for complex dropdown content that needs clear visual hierarchy.\n * @tags test-case\n */\nexport const Layout = {\n render: () => html`\n<nve-dropdown anchor=\"btn\">\n <nve-dropdown-header>\n <h3 nve-text=\"heading semibold sm\">heading</h3>\n </nve-dropdown-header>\n <p nve-text=\"body\">some text content in a closable dropdown</p>\n <nve-dropdown-footer>\n <p nve-text=\"body\">footer</p>\n </nve-dropdown-footer>\n</nve-dropdown>\n<nve-button id=\"btn\">button</nve-button>\n `\n};\n\n/**\n * @summary Dropdown with many triggers, showing how to use the popovertarget attribute to connect many triggers to the same dropdown.\n * @tags test-case\n */\nexport const MultipleTriggers = {\n render: () => html`\n<div nve-layout=\"row gap:sm align:center\">\n <nve-button popovertarget=\"dropdown\">button</nve-button>\n <nve-button popovertarget=\"dropdown\">button</nve-button>\n <nve-button popovertarget=\"dropdown\">button</nve-button>\n <nve-dropdown id=\"dropdown\">hello there</nve-dropdown>\n</div>\n `\n};\n\n/**\n * @summary Dropdown position, with the position attribute controlling placement when the trigger is not visible.\n * @tags test-case\n */\nexport const Position = {\n render: () => html`\n<nve-dropdown anchor=\"card\" position=\"top\" alignment=\"center\">\n <h3 nve-text=\"label\">Top</h3>\n <p nve-text=\"body\">dropdown positioned top</p>\n</nve-dropdown>\n<nve-dropdown anchor=\"card\" position=\"right\" alignment=\"center\">\n <h3 nve-text=\"label\">Right</h3>\n <p nve-text=\"body\">dropdown positioned right</p>\n</nve-dropdown>\n<nve-dropdown anchor=\"card\" position=\"bottom\" alignment=\"center\">\n <h3 nve-text=\"label\">Bottom</h3>\n <p nve-text=\"body\">dropdown positioned bottom</p>\n</nve-dropdown>\n<nve-dropdown anchor=\"card\" position=\"left\" alignment=\"center\">\n <h3 nve-text=\"label\">Left</h3>\n <p nve-text=\"body\">dropdown positioned left</p>\n</nve-dropdown>\n<nve-card id=\"card\" style=\"width: 250px; height: 200px;\"></nve-card>\n `\n};\n\n/**\n * @summary Dropdown alignment, with the alignment attribute controlling horizontal placement relative to the trigger.\n * @tags test-case\n */\nexport const Alignment = {\n render: () => html`\n<div nve-theme nve-layout=\"row align:center\">\n <nve-dropdown open anchor=\"card\" position=\"top\" alignment=\"start\">top start</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"top\" alignment=\"center\">top center</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"top\" alignment=\"end\">top end</nve-dropdown>\n\n <nve-dropdown open anchor=\"card\" position=\"right\" alignment=\"start\">right start</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"right\" alignment=\"center\">right center</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"right\" alignment=\"end\">right end</nve-dropdown>\n\n <nve-dropdown open anchor=\"card\" position=\"bottom\" alignment=\"start\">bottom start</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"bottom\" alignment=\"center\">bottom center</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"bottom\" alignment=\"end\">bottom end</nve-dropdown>\n\n <nve-dropdown open anchor=\"card\" position=\"left\" alignment=\"start\">left start</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"left\" alignment=\"center\">left center</nve-dropdown>\n <nve-dropdown open anchor=\"card\" position=\"left\" alignment=\"end\">left end</nve-dropdown>\n\n <nve-card id=\"card\" style=\"width: 450px; height: 300px; margin-top: 50px;\"></nve-card>\n</div>\n `\n};\n\n/**\n * @summary Dropdown containing a radio group for single-selection options. Perfect for sort controls, filter selections, or preference settings.\n * @tags test-case\n */\nexport const RadioGroup = {\n render: () => html`\n<nve-dropdown anchor=\"btn\">\n <nve-radio-group style=\"width: 250px\">\n <label>Sort By</label>\n <nve-radio>\n <label>Completed</label>\n <input type=\"radio\" checked />\n <nve-control-message>latest completed tasks</nve-control-message>\n </nve-radio>\n <nve-radio>\n <label>Failing</label>\n <input type=\"radio\" />\n <nve-control-message>latest failing tasks</nve-control-message>\n </nve-radio>\n <nve-radio>\n <label>Status</label>\n <input type=\"radio\" />\n <nve-control-message>task status priority</nve-control-message>\n </nve-radio>\n </nve-radio-group>\n</nve-dropdown>\n<nve-button id=\"btn\" nve-control>completed <nve-icon name=\"caret\" direction=\"down\" size=\"sm\"></nve-icon></nve-button>\n `\n};\n\n/**\n * @summary Dropdown containing a checkbox group for multi-selection options. Ideal for filter controls, feature toggles, or bulk action selections.\n * @tags test-case\n */\nexport const CheckboxGroup = {\n render: () => html`\n<nve-dropdown anchor=\"btn\">\n <nve-checkbox-group style=\"width: 250px\">\n <label>Test Suites</label>\n <nve-checkbox>\n <label>Local</label>\n <input type=\"checkbox\" />\n </nve-checkbox>\n <nve-checkbox>\n <label>Nightly</label>\n <input type=\"checkbox\" checked />\n </nve-checkbox>\n <nve-checkbox>\n <label>Remote</label>\n <input type=\"checkbox\" />\n </nve-checkbox>\n </nve-checkbox-group>\n</nve-dropdown>\n<nve-button id=\"btn\" nve-control>test suites <nve-icon name=\"caret\" direction=\"down\" size=\"sm\"></nve-icon></nve-button>\n `\n};\n\n/* eslint-disable @nvidia-elements/lint/no-deprecated-popover-attributes */\n\n/**\n * @deprecated\n * @summary Legacy behavior trigger for dropdown, using the behavior-trigger attribute to open the dropdown on button click.\n * @tags test-case\n */\nexport const LegacyBehaviorTrigger = {\n inline: false,\n render: () => html`\n<nve-button id=\"dropdown-btn\">open</nve-button>\n<nve-dropdown anchor=\"dropdown-btn\" trigger=\"dropdown-btn\" behavior-trigger hidden>\n <p nve-text=\"body\">hello there</p>\n</nve-dropdown>\n `\n};\n\n/**\n * @deprecated\n * @summary Dropdown hint, using the tooltip element to display a hint when the dropdown opens.\n * @tags test-case\n */\nexport const Hint = {\n render: () => html`\n<nve-dropdown id=\"dropdown\">\n dropdown content\n</nve-dropdown>\n\n<nve-tooltip id=\"tooltip\" hidden behavior-trigger trigger=\"btn\">dropdown content</nve-tooltip>\n\n<nve-icon-button id=\"btn\" popovertarget=\"dropdown\" icon-name=\"gear\" aria-label=\"settings\"></nve-icon-button>\n `\n};\n\n/**\n * @summary Dropdown position fallback, using the position and alignment attributes to reposition the dropdown when the trigger is not visible.\n * @tags test-case\n */\nexport const PositionFallback = {\n render: () => html`\n<style>\n body {\n align-items: start !important;\n margin: 0;\n padding: 0 !important;\n }\n</style>\n\n<nve-dropdown anchor=\"btn\" position=\"bottom\" alignment=\"center\">\n dropdown content\n</nve-dropdown>\n\n<nve-dropdown anchor=\"btn\" position=\"right\" alignment=\"center\">\n dropdown content\n</nve-dropdown>\n\n<nve-icon-button id=\"btn\" icon-name=\"gear\" aria-label=\"settings\"></nve-icon-button>\n `\n};\n"],"mappings":";AAGA,IAAAA,IAAS"}
@@ -21,7 +21,7 @@ var p = { close: "close" }, m = class extends o {
21
21
  static {
22
22
  this.metadata = {
23
23
  tag: "nve-dropdown",
24
- version: "2.23.5"
24
+ version: "2.24.0"
25
25
  };
26
26
  }
27
27
  static {
@@ -14,7 +14,7 @@ var d = class extends s {
14
14
  static {
15
15
  this.metadata = {
16
16
  tag: "nve-dropdown-group",
17
- version: "2.23.5",
17
+ version: "2.24.0",
18
18
  children: ["nve-dropdown"]
19
19
  };
20
20
  }
@@ -26,7 +26,7 @@ var g = {
26
26
  static {
27
27
  this.metadata = {
28
28
  tag: "nve-dropzone",
29
- version: "2.23.5",
29
+ version: "2.24.0",
30
30
  validators: [o, a],
31
31
  valueSchema: {
32
32
  type: "array",
@@ -11,7 +11,7 @@ var a = class extends t {
11
11
  static {
12
12
  this.metadata = {
13
13
  tag: "nve-file",
14
- version: "2.23.5"
14
+ version: "2.24.0"
15
15
  };
16
16
  }
17
17
  connectedCallback() {
@@ -94,7 +94,7 @@ var h = class extends r {
94
94
  static {
95
95
  this.metadata = {
96
96
  tag: "nve-format-bytes",
97
- version: "2.23.5"
97
+ version: "2.24.0"
98
98
  };
99
99
  }
100
100
  get #e() {
@@ -12,7 +12,7 @@ var s = class extends r {
12
12
  static {
13
13
  this.metadata = {
14
14
  tag: "nve-format-datetime",
15
- version: "2.23.5"
15
+ version: "2.24.0"
16
16
  };
17
17
  }
18
18
  get #e() {
@@ -28,7 +28,7 @@ var s = [
28
28
  static {
29
29
  this.metadata = {
30
30
  tag: "nve-format-number",
31
- version: "2.23.5"
31
+ version: "2.24.0"
32
32
  };
33
33
  }
34
34
  get #e() {
@@ -52,7 +52,7 @@ var s = {
52
52
  static {
53
53
  this.metadata = {
54
54
  tag: "nve-format-relative-time",
55
- version: "2.23.5"
55
+ version: "2.24.0"
56
56
  };
57
57
  }
58
58
  #e;
@@ -19,7 +19,7 @@ var d = class extends s {
19
19
  static {
20
20
  this.metadata = {
21
21
  tag: "nve-format-truncate",
22
- version: "2.23.5"
22
+ version: "2.24.0"
23
23
  };
24
24
  }
25
25
  #e;