@vielzeug/refine 26.10.0 → 26.10.5

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 (468) hide show
  1. package/README.md +1 -1
  2. package/dist/accordion-item.cjs.map +1 -1
  3. package/dist/accordion-item.js.map +1 -1
  4. package/dist/accordion.cjs.map +1 -1
  5. package/dist/accordion.js.map +1 -1
  6. package/dist/async.cjs.map +1 -1
  7. package/dist/async.js.map +1 -1
  8. package/dist/badge.cjs.map +1 -1
  9. package/dist/badge.js.map +1 -1
  10. package/dist/box.cjs.map +1 -1
  11. package/dist/box.js.map +1 -1
  12. package/dist/button.cjs +3 -3
  13. package/dist/button.cjs.map +1 -1
  14. package/dist/button.js +3 -3
  15. package/dist/button.js.map +1 -1
  16. package/dist/calendar.cjs.map +1 -1
  17. package/dist/calendar.js.map +1 -1
  18. package/dist/carousel.cjs.map +1 -1
  19. package/dist/carousel.js.map +1 -1
  20. package/dist/chat-message.cjs.map +1 -1
  21. package/dist/chat-message.js.map +1 -1
  22. package/dist/chat-panel.cjs.map +1 -1
  23. package/dist/chat-panel.js.map +1 -1
  24. package/dist/checkbox-group.cjs.map +1 -1
  25. package/dist/checkbox-group.js.map +1 -1
  26. package/dist/chip.cjs.map +1 -1
  27. package/dist/chip.js.map +1 -1
  28. package/dist/code-window.cjs.map +1 -1
  29. package/dist/code-window.js.map +1 -1
  30. package/dist/combobox.cjs.map +1 -1
  31. package/dist/combobox.js.map +1 -1
  32. package/dist/command-palette.cjs +9 -1
  33. package/dist/command-palette.cjs.map +1 -1
  34. package/dist/command-palette.js +9 -1
  35. package/dist/command-palette.js.map +1 -1
  36. package/dist/content/card/card.css.cjs.map +1 -1
  37. package/dist/content/card/card.css.js.map +1 -1
  38. package/dist/content/carousel/carousel-slide.css.cjs.map +1 -1
  39. package/dist/content/carousel/carousel-slide.css.js.map +1 -1
  40. package/dist/content/carousel/carousel.css.cjs.map +1 -1
  41. package/dist/content/carousel/carousel.css.js.map +1 -1
  42. package/dist/content/carousel/carousel.d.ts +5 -5
  43. package/dist/content/chat-message/chat-message.css.cjs +1 -1
  44. package/dist/content/chat-message/chat-message.css.cjs.map +1 -1
  45. package/dist/content/chat-message/chat-message.css.js +1 -1
  46. package/dist/content/chat-message/chat-message.css.js.map +1 -1
  47. package/dist/content/chat-message/chat-message.d.ts +4 -4
  48. package/dist/content/chat-message/chat-message.d.ts.map +1 -1
  49. package/dist/content/chat-panel/chat-panel.d.ts +1 -1
  50. package/dist/content/code-window/code-window.css.cjs.map +1 -1
  51. package/dist/content/code-window/code-window.css.js.map +1 -1
  52. package/dist/content/code-window/code-window.d.ts +4 -4
  53. package/dist/content/index.d.ts +4 -0
  54. package/dist/content/index.d.ts.map +1 -1
  55. package/dist/content/list/_list-item-reveal.cjs.map +1 -1
  56. package/dist/content/list/_list-item-reveal.d.ts +4 -4
  57. package/dist/content/list/_list-item-reveal.d.ts.map +1 -1
  58. package/dist/content/list/_list-item-reveal.js.map +1 -1
  59. package/dist/content/list/list-item.css.cjs.map +1 -1
  60. package/dist/content/list/list-item.css.js.map +1 -1
  61. package/dist/content/list/list-item.d.ts +8 -8
  62. package/dist/content/list/list-item.d.ts.map +1 -1
  63. package/dist/content/list/list.d.ts +8 -8
  64. package/dist/content/list/list.d.ts.map +1 -1
  65. package/dist/content/qr-code/qr-code.d.ts +1 -1
  66. package/dist/content/rank-list/rank-item.css.cjs +2 -0
  67. package/dist/content/rank-list/rank-item.css.cjs.map +1 -0
  68. package/dist/content/rank-list/rank-item.css.js +2 -0
  69. package/dist/content/rank-list/rank-item.css.js.map +1 -0
  70. package/dist/content/rank-list/rank-item.d.ts +68 -0
  71. package/dist/content/rank-list/rank-item.d.ts.map +1 -0
  72. package/dist/content/rank-list/rank-list.css.cjs +2 -0
  73. package/dist/content/rank-list/rank-list.css.cjs.map +1 -0
  74. package/dist/content/rank-list/rank-list.css.js +2 -0
  75. package/dist/content/rank-list/rank-list.css.js.map +1 -0
  76. package/dist/content/rank-list/rank-list.d.ts +44 -0
  77. package/dist/content/rank-list/rank-list.d.ts.map +1 -0
  78. package/dist/content/separator/separator.d.ts +1 -1
  79. package/dist/content/separator/separator.d.ts.map +1 -1
  80. package/dist/content/speech-player/speech-player.css.cjs.map +1 -1
  81. package/dist/content/speech-player/speech-player.css.js.map +1 -1
  82. package/dist/content/speech-player/speech-player.d.ts +12 -12
  83. package/dist/content/speech-player/speech-player.d.ts.map +1 -1
  84. package/dist/content/stepper/step.css.cjs.map +1 -1
  85. package/dist/content/stepper/step.css.js.map +1 -1
  86. package/dist/content/stepper/step.d.ts +3 -3
  87. package/dist/content/stepper/step.d.ts.map +1 -1
  88. package/dist/content/stepper/stepper.css.cjs.map +1 -1
  89. package/dist/content/stepper/stepper.css.js.map +1 -1
  90. package/dist/content/stepper/stepper.d.ts +3 -3
  91. package/dist/content/stepper/stepper.d.ts.map +1 -1
  92. package/dist/content/table/table.css.cjs.map +1 -1
  93. package/dist/content/table/table.css.js.map +1 -1
  94. package/dist/content/table/table.d.ts +3 -3
  95. package/dist/content/table/table.d.ts.map +1 -1
  96. package/dist/content/text/text.css.cjs.map +1 -1
  97. package/dist/content/text/text.css.js.map +1 -1
  98. package/dist/content/text/text.d.ts +2 -2
  99. package/dist/content/text/text.d.ts.map +1 -1
  100. package/dist/cookie-banner.cjs.map +1 -1
  101. package/dist/cookie-banner.js.map +1 -1
  102. package/dist/copy-command.cjs +1 -1
  103. package/dist/copy-command.cjs.map +1 -1
  104. package/dist/copy-command.js +1 -1
  105. package/dist/copy-command.js.map +1 -1
  106. package/dist/core/announcer.cjs.map +1 -1
  107. package/dist/core/announcer.d.ts +2 -2
  108. package/dist/core/announcer.js.map +1 -1
  109. package/dist/core/aria-reflection.cjs.map +1 -1
  110. package/dist/core/aria-reflection.d.ts +3 -3
  111. package/dist/core/aria-reflection.js.map +1 -1
  112. package/dist/core/auto-resize.cjs.map +1 -1
  113. package/dist/core/auto-resize.d.ts +1 -1
  114. package/dist/core/auto-resize.js.map +1 -1
  115. package/dist/core/checkable.cjs.map +1 -1
  116. package/dist/core/checkable.d.ts +2 -2
  117. package/dist/core/checkable.d.ts.map +1 -1
  118. package/dist/core/checkable.js.map +1 -1
  119. package/dist/core/choice-field.cjs.map +1 -1
  120. package/dist/core/choice-field.d.ts +3 -3
  121. package/dist/core/choice-field.d.ts.map +1 -1
  122. package/dist/core/choice-field.js.map +1 -1
  123. package/dist/core/composer.cjs.map +1 -1
  124. package/dist/core/composer.d.ts +4 -4
  125. package/dist/core/composer.d.ts.map +1 -1
  126. package/dist/core/composer.js.map +1 -1
  127. package/dist/core/date-picker.cjs.map +1 -1
  128. package/dist/core/date-picker.d.ts +5 -5
  129. package/dist/core/date-picker.d.ts.map +1 -1
  130. package/dist/core/date-picker.js.map +1 -1
  131. package/dist/core/direction.cjs.map +1 -1
  132. package/dist/core/direction.d.ts +1 -1
  133. package/dist/core/direction.js.map +1 -1
  134. package/dist/core/field-base.cjs.map +1 -1
  135. package/dist/core/field-base.d.ts +9 -9
  136. package/dist/core/field-base.d.ts.map +1 -1
  137. package/dist/core/field-base.js.map +1 -1
  138. package/dist/core/focus.cjs.map +1 -1
  139. package/dist/core/focus.d.ts +1 -1
  140. package/dist/core/focus.js.map +1 -1
  141. package/dist/core/icon-registry.cjs.map +1 -1
  142. package/dist/core/icon-registry.d.ts +1 -1
  143. package/dist/core/icon-registry.js.map +1 -1
  144. package/dist/core/icons.cjs.map +1 -1
  145. package/dist/core/icons.js.map +1 -1
  146. package/dist/core/keyboard.cjs.map +1 -1
  147. package/dist/core/keyboard.d.ts +1 -1
  148. package/dist/core/keyboard.js.map +1 -1
  149. package/dist/core/numbers.cjs.map +1 -1
  150. package/dist/core/numbers.d.ts +1 -1
  151. package/dist/core/numbers.js.map +1 -1
  152. package/dist/core/overlay.cjs.map +1 -1
  153. package/dist/core/overlay.d.ts +6 -6
  154. package/dist/core/overlay.js.map +1 -1
  155. package/dist/core/parse.cjs.map +1 -1
  156. package/dist/core/parse.d.ts +1 -1
  157. package/dist/core/parse.js.map +1 -1
  158. package/dist/core/positioner.cjs.map +1 -1
  159. package/dist/core/positioner.d.ts +3 -3
  160. package/dist/core/positioner.js.map +1 -1
  161. package/dist/core/ref-callback.cjs.map +1 -1
  162. package/dist/core/ref-callback.d.ts +2 -2
  163. package/dist/core/ref-callback.d.ts.map +1 -1
  164. package/dist/core/ref-callback.js.map +1 -1
  165. package/dist/core/text-field.cjs.map +1 -1
  166. package/dist/core/text-field.d.ts +6 -6
  167. package/dist/core/text-field.d.ts.map +1 -1
  168. package/dist/core/text-field.js.map +1 -1
  169. package/dist/counter.cjs +1 -0
  170. package/dist/counter.cjs.map +1 -1
  171. package/dist/counter.js +1 -0
  172. package/dist/counter.js.map +1 -1
  173. package/dist/custom-elements.json +334 -87
  174. package/dist/datagrid.cjs.map +1 -1
  175. package/dist/datagrid.js.map +1 -1
  176. package/dist/date-picker.cjs +1 -1
  177. package/dist/date-picker.cjs.map +1 -1
  178. package/dist/date-picker.js +1 -1
  179. package/dist/date-picker.js.map +1 -1
  180. package/dist/dialog.cjs.map +1 -1
  181. package/dist/dialog.js.map +1 -1
  182. package/dist/disclosure/accordion-item/accordion-item.css.cjs +1 -1
  183. package/dist/disclosure/accordion-item/accordion-item.css.cjs.map +1 -1
  184. package/dist/disclosure/accordion-item/accordion-item.css.js +1 -1
  185. package/dist/disclosure/accordion-item/accordion-item.css.js.map +1 -1
  186. package/dist/disclosure/tab-item/tab-item.d.ts +1 -1
  187. package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -1
  188. package/dist/drawer.cjs.map +1 -1
  189. package/dist/drawer.js.map +1 -1
  190. package/dist/feedback/alert/alert.css.cjs.map +1 -1
  191. package/dist/feedback/alert/alert.css.js.map +1 -1
  192. package/dist/feedback/badge/badge.css.cjs.map +1 -1
  193. package/dist/feedback/badge/badge.css.js.map +1 -1
  194. package/dist/feedback/badge/badge.d.ts +1 -1
  195. package/dist/feedback/badge/badge.d.ts.map +1 -1
  196. package/dist/feedback/chip/chip.css.cjs.map +1 -1
  197. package/dist/feedback/chip/chip.css.js.map +1 -1
  198. package/dist/feedback/chip/chip.d.ts +3 -3
  199. package/dist/feedback/chip/chip.d.ts.map +1 -1
  200. package/dist/feedback/cookie-banner/cookie-banner.css.cjs.map +1 -1
  201. package/dist/feedback/cookie-banner/cookie-banner.css.js.map +1 -1
  202. package/dist/feedback/cookie-banner/cookie-banner.d.ts +8 -8
  203. package/dist/feedback/cookie-banner/cookie-banner.d.ts.map +1 -1
  204. package/dist/feedback/progress/progress.css.cjs.map +1 -1
  205. package/dist/feedback/progress/progress.css.js.map +1 -1
  206. package/dist/feedback/progress/progress.d.ts +1 -1
  207. package/dist/feedback/progress/progress.d.ts.map +1 -1
  208. package/dist/feedback/skeleton/skeleton.css.cjs.map +1 -1
  209. package/dist/feedback/skeleton/skeleton.css.js.map +1 -1
  210. package/dist/feedback/skeleton/skeleton.d.ts +1 -1
  211. package/dist/feedback/skeleton/skeleton.d.ts.map +1 -1
  212. package/dist/feedback/toast/toast.css.cjs +1 -1
  213. package/dist/feedback/toast/toast.css.cjs.map +1 -1
  214. package/dist/feedback/toast/toast.css.js +1 -1
  215. package/dist/feedback/toast/toast.css.js.map +1 -1
  216. package/dist/feedback/toast/toast.d.ts +1 -1
  217. package/dist/feedback/toast/toast.d.ts.map +1 -1
  218. package/dist/feedback/typing-indicator/typing-indicator.d.ts +2 -2
  219. package/dist/file-input.cjs +1 -1
  220. package/dist/file-input.cjs.map +1 -1
  221. package/dist/file-input.js +1 -1
  222. package/dist/file-input.js.map +1 -1
  223. package/dist/frameworks/elements.d.ts +1 -1
  224. package/dist/grid-item.cjs.map +1 -1
  225. package/dist/grid-item.js.map +1 -1
  226. package/dist/grid.cjs.map +1 -1
  227. package/dist/grid.js.map +1 -1
  228. package/dist/icon.cjs.map +1 -1
  229. package/dist/icon.js.map +1 -1
  230. package/dist/input.cjs.map +1 -1
  231. package/dist/input.js.map +1 -1
  232. package/dist/inputs/button/button.css.cjs.map +1 -1
  233. package/dist/inputs/button/button.css.js.map +1 -1
  234. package/dist/inputs/button/button.d.ts +3 -3
  235. package/dist/inputs/button/button.d.ts.map +1 -1
  236. package/dist/inputs/calendar/calendar.css.cjs.map +1 -1
  237. package/dist/inputs/calendar/calendar.css.js.map +1 -1
  238. package/dist/inputs/calendar/calendar.d.ts +2 -2
  239. package/dist/inputs/checkbox-group/checkbox-group.d.ts +2 -2
  240. package/dist/inputs/checkbox-group/checkbox-group.d.ts.map +1 -1
  241. package/dist/inputs/combobox/combobox.css.cjs.map +1 -1
  242. package/dist/inputs/combobox/combobox.css.js.map +1 -1
  243. package/dist/inputs/counter/counter.css.cjs +1 -1
  244. package/dist/inputs/counter/counter.css.cjs.map +1 -1
  245. package/dist/inputs/counter/counter.css.js +1 -1
  246. package/dist/inputs/counter/counter.css.js.map +1 -1
  247. package/dist/inputs/counter/counter.d.ts +2 -1
  248. package/dist/inputs/counter/counter.d.ts.map +1 -1
  249. package/dist/inputs/datagrid/datagrid.css.cjs.map +1 -1
  250. package/dist/inputs/datagrid/datagrid.css.js.map +1 -1
  251. package/dist/inputs/datagrid/datagrid.d.ts +5 -5
  252. package/dist/inputs/date-picker/date-picker.css.cjs.map +1 -1
  253. package/dist/inputs/date-picker/date-picker.css.js.map +1 -1
  254. package/dist/inputs/date-picker/date-picker.d.ts +1 -1
  255. package/dist/inputs/file-input/file-input-upload.cjs.map +1 -1
  256. package/dist/inputs/file-input/file-input-upload.d.ts +6 -6
  257. package/dist/inputs/file-input/file-input-upload.js.map +1 -1
  258. package/dist/inputs/file-input/file-input.css.cjs.map +1 -1
  259. package/dist/inputs/file-input/file-input.css.js.map +1 -1
  260. package/dist/inputs/file-input/file-input.d.ts +6 -6
  261. package/dist/inputs/input/input.css.cjs +1 -1
  262. package/dist/inputs/input/input.css.cjs.map +1 -1
  263. package/dist/inputs/input/input.css.js +1 -1
  264. package/dist/inputs/input/input.css.js.map +1 -1
  265. package/dist/inputs/input/input.d.ts +6 -6
  266. package/dist/inputs/input/input.d.ts.map +1 -1
  267. package/dist/inputs/message-composer/message-composer.css.cjs.map +1 -1
  268. package/dist/inputs/message-composer/message-composer.css.js.map +1 -1
  269. package/dist/inputs/message-composer/message-composer.d.ts +7 -7
  270. package/dist/inputs/message-composer/message-composer.d.ts.map +1 -1
  271. package/dist/inputs/number-input/number-input.css.cjs.map +1 -1
  272. package/dist/inputs/number-input/number-input.css.js.map +1 -1
  273. package/dist/inputs/number-input/number-input.d.ts +2 -2
  274. package/dist/inputs/otp-input/otp-input.css.cjs.map +1 -1
  275. package/dist/inputs/otp-input/otp-input.css.js.map +1 -1
  276. package/dist/inputs/qr-scanner/qr-scanner.d.ts +1 -1
  277. package/dist/inputs/qr-scanner/qr-scanner.d.ts.map +1 -1
  278. package/dist/inputs/rating/rating.d.ts +1 -1
  279. package/dist/inputs/rating/rating.d.ts.map +1 -1
  280. package/dist/inputs/select/select.css.cjs +1 -1
  281. package/dist/inputs/select/select.css.cjs.map +1 -1
  282. package/dist/inputs/select/select.css.js +1 -1
  283. package/dist/inputs/select/select.css.js.map +1 -1
  284. package/dist/inputs/select/select.d.ts +1 -1
  285. package/dist/inputs/select/select.d.ts.map +1 -1
  286. package/dist/inputs/shared/field-binding.cjs.map +1 -1
  287. package/dist/inputs/shared/field-binding.d.ts +2 -2
  288. package/dist/inputs/shared/field-binding.d.ts.map +1 -1
  289. package/dist/inputs/shared/field-binding.js.map +1 -1
  290. package/dist/inputs/shared/native-field-event.cjs.map +1 -1
  291. package/dist/inputs/shared/native-field-event.d.ts +1 -1
  292. package/dist/inputs/shared/native-field-event.js.map +1 -1
  293. package/dist/inputs/shared/templates.cjs.map +1 -1
  294. package/dist/inputs/shared/templates.d.ts +3 -3
  295. package/dist/inputs/shared/templates.js.map +1 -1
  296. package/dist/inputs/slider/slider.css.cjs.map +1 -1
  297. package/dist/inputs/slider/slider.css.js.map +1 -1
  298. package/dist/inputs/slider/slider.d.ts +1 -1
  299. package/dist/inputs/slider/slider.d.ts.map +1 -1
  300. package/dist/inputs/textarea/textarea.css.cjs.map +1 -1
  301. package/dist/inputs/textarea/textarea.css.js.map +1 -1
  302. package/dist/inputs/textarea/textarea.d.ts +1 -1
  303. package/dist/inputs/time-picker/time-picker.css.cjs.map +1 -1
  304. package/dist/inputs/time-picker/time-picker.css.js.map +1 -1
  305. package/dist/inputs/time-picker/time-picker.d.ts +1 -1
  306. package/dist/layout/box/box.css.cjs.map +1 -1
  307. package/dist/layout/box/box.css.js.map +1 -1
  308. package/dist/layout/box/box.d.ts +1 -1
  309. package/dist/layout/grid/grid.d.ts +1 -1
  310. package/dist/layout/grid-item/grid-item.d.ts +3 -3
  311. package/dist/layout/grid-item/grid-item.d.ts.map +1 -1
  312. package/dist/layout/navbar/navbar.css.cjs +1 -1
  313. package/dist/layout/navbar/navbar.css.cjs.map +1 -1
  314. package/dist/layout/navbar/navbar.css.js +1 -1
  315. package/dist/layout/navbar/navbar.css.js.map +1 -1
  316. package/dist/layout/navbar/navbar.d.ts +3 -3
  317. package/dist/layout/sidebar/sidebar-item.css.cjs.map +1 -1
  318. package/dist/layout/sidebar/sidebar-item.css.js.map +1 -1
  319. package/dist/layout/sidebar/sidebar.d.ts +5 -5
  320. package/dist/layout/sidebar/sidebar.d.ts.map +1 -1
  321. package/dist/list-item.cjs.map +1 -1
  322. package/dist/list-item.js.map +1 -1
  323. package/dist/list.cjs.map +1 -1
  324. package/dist/list.js.map +1 -1
  325. package/dist/menu.cjs +6 -5
  326. package/dist/menu.cjs.map +1 -1
  327. package/dist/menu.js +6 -5
  328. package/dist/menu.js.map +1 -1
  329. package/dist/message-composer.cjs.map +1 -1
  330. package/dist/message-composer.js.map +1 -1
  331. package/dist/navbar.cjs.map +1 -1
  332. package/dist/navbar.js.map +1 -1
  333. package/dist/number-input.cjs.map +1 -1
  334. package/dist/number-input.js.map +1 -1
  335. package/dist/otp-input.cjs.map +1 -1
  336. package/dist/otp-input.js.map +1 -1
  337. package/dist/overlay/command-palette/command-palette-items.cjs.map +1 -1
  338. package/dist/overlay/command-palette/command-palette-items.d.ts +1 -1
  339. package/dist/overlay/command-palette/command-palette-items.js.map +1 -1
  340. package/dist/overlay/command-palette/command-palette.css.cjs +1 -1
  341. package/dist/overlay/command-palette/command-palette.css.cjs.map +1 -1
  342. package/dist/overlay/command-palette/command-palette.css.js +1 -1
  343. package/dist/overlay/command-palette/command-palette.css.js.map +1 -1
  344. package/dist/overlay/command-palette/command-palette.d.ts +7 -3
  345. package/dist/overlay/command-palette/command-palette.d.ts.map +1 -1
  346. package/dist/overlay/command-palette/command-palette.types.d.ts +16 -6
  347. package/dist/overlay/command-palette/command-palette.types.d.ts.map +1 -1
  348. package/dist/overlay/dialog/dialog.css.cjs +1 -1
  349. package/dist/overlay/dialog/dialog.css.cjs.map +1 -1
  350. package/dist/overlay/dialog/dialog.css.js +1 -1
  351. package/dist/overlay/dialog/dialog.css.js.map +1 -1
  352. package/dist/overlay/dialog/dialog.d.ts +2 -2
  353. package/dist/overlay/dialog/dialog.d.ts.map +1 -1
  354. package/dist/overlay/drawer/drawer.css.cjs.map +1 -1
  355. package/dist/overlay/drawer/drawer.css.js.map +1 -1
  356. package/dist/overlay/drawer/drawer.d.ts +1 -1
  357. package/dist/overlay/drawer/drawer.d.ts.map +1 -1
  358. package/dist/overlay/menu/menu-item.css.cjs.map +1 -1
  359. package/dist/overlay/menu/menu-item.css.js.map +1 -1
  360. package/dist/overlay/menu/menu.d.ts.map +1 -1
  361. package/dist/overlay/shared/use-dialog.cjs.map +1 -1
  362. package/dist/overlay/shared/use-dialog.d.ts +6 -6
  363. package/dist/overlay/shared/use-dialog.d.ts.map +1 -1
  364. package/dist/overlay/shared/use-dialog.js.map +1 -1
  365. package/dist/overlay/shared/use-floating-trigger.cjs.map +1 -1
  366. package/dist/overlay/shared/use-floating-trigger.d.ts +1 -1
  367. package/dist/overlay/shared/use-floating-trigger.d.ts.map +1 -1
  368. package/dist/overlay/shared/use-floating-trigger.js.map +1 -1
  369. package/dist/overlay/tooltip/tooltip.css.cjs.map +1 -1
  370. package/dist/overlay/tooltip/tooltip.css.js.map +1 -1
  371. package/dist/progress.cjs.map +1 -1
  372. package/dist/progress.js.map +1 -1
  373. package/dist/qr-code.cjs.map +1 -1
  374. package/dist/qr-code.js.map +1 -1
  375. package/dist/qr-scanner.cjs.map +1 -1
  376. package/dist/qr-scanner.js.map +1 -1
  377. package/dist/radio-group.cjs.map +1 -1
  378. package/dist/radio-group.js.map +1 -1
  379. package/dist/radio.cjs.map +1 -1
  380. package/dist/radio.js.map +1 -1
  381. package/dist/rank-item.cjs +21 -0
  382. package/dist/rank-item.cjs.map +1 -0
  383. package/dist/rank-item.js +21 -0
  384. package/dist/rank-item.js.map +1 -0
  385. package/dist/rank-list.cjs +4 -0
  386. package/dist/rank-list.cjs.map +1 -0
  387. package/dist/rank-list.js +4 -0
  388. package/dist/rank-list.js.map +1 -0
  389. package/dist/rating.cjs.map +1 -1
  390. package/dist/rating.js.map +1 -1
  391. package/dist/refine.cjs +111 -80
  392. package/dist/refine.cjs.map +1 -1
  393. package/dist/refine.iife.js +111 -80
  394. package/dist/refine.iife.js.map +1 -1
  395. package/dist/refine.js +112 -81
  396. package/dist/refine.js.map +1 -1
  397. package/dist/select.cjs.map +1 -1
  398. package/dist/select.js.map +1 -1
  399. package/dist/separator.cjs.map +1 -1
  400. package/dist/separator.js.map +1 -1
  401. package/dist/shared/index.d.ts +3 -3
  402. package/dist/shared/size-presets.cjs.map +1 -1
  403. package/dist/shared/size-presets.d.ts +4 -4
  404. package/dist/shared/size-presets.js.map +1 -1
  405. package/dist/shared/types.d.ts +1 -1
  406. package/dist/sidebar.cjs.map +1 -1
  407. package/dist/sidebar.js.map +1 -1
  408. package/dist/skeleton.cjs.map +1 -1
  409. package/dist/skeleton.js.map +1 -1
  410. package/dist/slider.cjs.map +1 -1
  411. package/dist/slider.js.map +1 -1
  412. package/dist/speech-player.cjs.map +1 -1
  413. package/dist/speech-player.js.map +1 -1
  414. package/dist/step.cjs.map +1 -1
  415. package/dist/step.js.map +1 -1
  416. package/dist/stepper.cjs.map +1 -1
  417. package/dist/stepper.js.map +1 -1
  418. package/dist/styles/fouc.css +2 -2
  419. package/dist/styles/mixins/accessibility.css.cjs.map +1 -1
  420. package/dist/styles/mixins/accessibility.css.d.ts +4 -4
  421. package/dist/styles/mixins/accessibility.css.js.map +1 -1
  422. package/dist/styles/mixins/animation.css.cjs +2 -2
  423. package/dist/styles/mixins/animation.css.cjs.map +1 -1
  424. package/dist/styles/mixins/animation.css.d.ts +4 -4
  425. package/dist/styles/mixins/animation.css.js +2 -2
  426. package/dist/styles/mixins/animation.css.js.map +1 -1
  427. package/dist/styles/mixins/field-variants.css.cjs +2 -2
  428. package/dist/styles/mixins/field-variants.css.cjs.map +1 -1
  429. package/dist/styles/mixins/field-variants.css.d.ts +6 -6
  430. package/dist/styles/mixins/field-variants.css.d.ts.map +1 -1
  431. package/dist/styles/mixins/field-variants.css.js +2 -2
  432. package/dist/styles/mixins/field-variants.css.js.map +1 -1
  433. package/dist/styles/mixins/shape.css.cjs.map +1 -1
  434. package/dist/styles/mixins/shape.css.d.ts +9 -9
  435. package/dist/styles/mixins/shape.css.d.ts.map +1 -1
  436. package/dist/styles/mixins/shape.css.js.map +1 -1
  437. package/dist/styles/mixins/variants.css.cjs.map +1 -1
  438. package/dist/styles/mixins/variants.css.d.ts +1 -1
  439. package/dist/styles/mixins/variants.css.js.map +1 -1
  440. package/dist/styles/theme.css +36 -28
  441. package/dist/tab-item.cjs.map +1 -1
  442. package/dist/tab-item.js.map +1 -1
  443. package/dist/tab-panel.cjs.map +1 -1
  444. package/dist/tab-panel.js.map +1 -1
  445. package/dist/table.cjs.map +1 -1
  446. package/dist/table.js.map +1 -1
  447. package/dist/text.cjs.map +1 -1
  448. package/dist/text.js.map +1 -1
  449. package/dist/textarea.cjs.map +1 -1
  450. package/dist/textarea.js.map +1 -1
  451. package/dist/theme.cjs.map +1 -1
  452. package/dist/theme.d.ts +2 -2
  453. package/dist/theme.js.map +1 -1
  454. package/dist/time-picker.cjs +1 -1
  455. package/dist/time-picker.cjs.map +1 -1
  456. package/dist/time-picker.js +1 -1
  457. package/dist/time-picker.js.map +1 -1
  458. package/dist/toast.cjs.map +1 -1
  459. package/dist/toast.js.map +1 -1
  460. package/dist/types/elements.d.ts +6 -2
  461. package/dist/typing-indicator.cjs.map +1 -1
  462. package/dist/typing-indicator.js.map +1 -1
  463. package/dist/utils/css.cjs.map +1 -1
  464. package/dist/utils/css.js.map +1 -1
  465. package/dist/utils/link.cjs.map +1 -1
  466. package/dist/utils/link.d.ts +2 -2
  467. package/dist/utils/link.js.map +1 -1
  468. package/package.json +31 -14
package/dist/step.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"step.cjs","names":[],"sources":["../src/content/stepper/step.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, prop, useSlots, watchEffect } from '@vielzeug/ore';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport stepStyles from './step.css?inline';\nimport { STEPPER_CTX } from './stepper';\n\nexport { ICON_TAG } from '../icon/icon';\nexport type OreStepProps = {\n /**\n * Theme color. Inherited from the parent `ore-stepper` when nested inside one (overrides\n * this value); only takes effect on its own when `ore-step` is rendered standalone.\n */\n color?: ThemeColor;\n /** Disables this step — it cannot be navigated to and is skipped by keyboard navigation. */\n disabled?: boolean;\n /** Marks this step as failed/invalid. Overrides the completed/current indicator visuals. */\n error?: boolean;\n /**\n * Marks this step as optional. Renders a small \"(optional)\" hint next to the label.\n * Purely presentational — has no effect on navigation.\n */\n optional?: boolean;\n /** Orientation. Inherited from the parent `ore-stepper` when nested inside one. */\n orientation?: 'horizontal' | 'vertical';\n /** Component size. Inherited from the parent `ore-stepper` when nested inside one. */\n size?: ComponentSize;\n /** Unique identifier, matches `ore-stepper`'s `value` attribute. */\n value: string;\n};\n\n/**\n * A single step trigger. Must be placed as a direct child of `ore-stepper`, which provides\n * this step's current/completed/navigable/index/total state via context — those are derived,\n * read-only attributes on this element, not settable props.\n *\n * @element ore-step\n *\n * @attr {string} value - Unique identifier, matches the parent ore-stepper's `value` attribute\n * @attr {boolean} disabled - Prevents navigation to this step\n * @attr {boolean} error - Marks the step as failed/invalid\n * @attr {boolean} optional - Renders an \"(optional)\" hint next to the label\n * @attr {boolean} current - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} completed - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} navigable - Read-only. Derived from the parent ore-stepper's `clickable`/`linear`/`disabled`.\n * @attr {number} index - Read-only. This step's 1-based position among its siblings.\n * @attr {number} total - Read-only. Total sibling step count.\n * @attr {string} color - Inherited from ore-stepper: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Inherited from ore-stepper: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Inherited from ore-stepper: 'horizontal' | 'vertical'\n *\n * @slot - Step label\n * @slot description - Optional supporting text shown below the label\n * @slot icon - Custom icon replacing the step number/check/error indicator\n *\n * @part control - Clickable (or static) root element for the step\n * @part indicator - Circular indicator holding the number/icon\n * @part content - Wrapper around the label and description\n * @part label - Step label element\n * @part description - Step description element\n * @part connector - Connector line segments (leading and trailing halves) either side of this step's indicator\n *\n * @example\n * ```html\n * <ore-step value=\"details\">Account details</ore-step>\n * <ore-step value=\"review\" disabled>Review</ore-step>\n * ```\n */\nexport const STEP_TAG = 'ore-step' as const;\ndefine<OreStepProps>(STEP_TAG, {\n props: {\n ...disablableBundle,\n color: prop.string<ThemeColor>(),\n error: prop.bool(false),\n optional: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n size: prop.string<ComponentSize>(),\n value: prop.string(''),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n const stepperCtx = inject(STEPPER_CTX);\n\n // ────────────────────────────────────────────────────────────────\n // State derived from the parent ore-stepper's context — see stepper.ts's\n // module doc comment for why this replaced parent-side attribute fan-out.\n // ────────────────────────────────────────────────────────────────\n\n // Plain functions, not `computed()` — every one of these ultimately reads\n // `stepperCtx.stepValues`/`stepperCtx.currentValue`, which are themselves `computed()`s\n // owned by the parent `ore-stepper`. Wrapping a *child* `computed()` around a *parent*\n // `computed()` (a computed-to-computed dependency crossing a `provide()`/`inject()`\n // boundary) is exactly the shape that surfaced two related bugs: a step's `completed`/\n // `current` attributes going permanently stale after a few rapid selections, and — worse —\n // a step's entire clickable/static control silently failing to render at all when its\n // `ore-step` tag upgrades before its siblings exist in the light DOM yet (true whenever\n // `ore-step`/`ore-stepper` are already `customElements.define()`d before this markup is\n // parsed, e.g. every sandboxed live-preview iframe). Reading straight through to the\n // parent's computeds on every call — no intermediate computed layer of our own to go\n // stale — made both disappear. Cheap enough to not need memoizing (a couple of `indexOf`/\n // comparisons over an already-memoized parent computed).\n const stepIndex = (): number => (stepperCtx ? stepperCtx.stepValues.value.indexOf(props.value.value) : -1);\n const totalSteps = (): number => stepperCtx?.stepValues.value.length ?? 0;\n const currentIndex = (): number =>\n stepperCtx ? stepperCtx.stepValues.value.indexOf(stepperCtx.currentValue.value ?? '') : -1;\n // 1-based, always-sane values for on-screen text (the step number badge, the sr-only\n // \"Step X of Y\" label) — falls back to \"1 of 1\" when rendered standalone with no parent\n // `ore-stepper` to derive a real position from. Kept separate from the `index`/`total`\n // *attributes* below, which correctly reflect nothing at all in that same standalone case.\n const displayIndex = (): number => {\n const index = stepIndex();\n\n return index >= 0 ? index + 1 : 1;\n };\n const displayTotal = (): number => totalSteps() || 1;\n\n const isCurrent = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && index === current;\n };\n // Purely positional — intentionally NOT gated on `props.error.value`. This also drives the\n // `completed` *attribute* below, which `step.css` uses to color both connector segments\n // either side of the indicator (`:host([completed]) .connector`); every *consumer* of this\n // (the icon choice, the sr-only state label) already checks `error` first and short-circuits\n // before it matters, so folding `!error` in here too would only end up suppressing\n // `[completed]` on an error step that's before the current one — breaking the connector\n // color chain right at that step instead of just swapping its icon.\n const isCompleted = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && current >= 0 && index < current;\n };\n const isNavigable = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return (\n !!stepperCtx &&\n isStepNavigable({\n disabled: props.disabled.value === true,\n index,\n linear: stepperCtx.linear.value,\n stepperClickable: stepperCtx.clickable.value,\n stepperCurrentIndex: current,\n })\n );\n };\n const isDisabled = () => Boolean(props.disabled.value);\n\n // Purely derived, read-only state — no matching `prop.*` declaration, so `bind()` is the\n // sole writer and can safely reflect `undefined` (removes the attribute) when this step\n // isn't nested inside an `ore-stepper` at all.\n bind({\n attr: {\n completed: () => (isCompleted() ? true : undefined),\n current: () => (isCurrent() ? true : undefined),\n index: () => {\n const index = stepIndex();\n\n return index >= 0 ? String(index + 1) : undefined;\n },\n navigable: () => (isNavigable() ? true : undefined),\n total: () => (stepperCtx ? String(totalSteps()) : undefined),\n },\n });\n\n // `color`/`size`/`orientation` double as regular, independently-settable props (for a step\n // rendered standalone) *and* stepper-inherited values — mirrors ore-tab-item's handling of\n // its own `color`/`size`/`variant` inheritance from `ore-tabs`. Only forcibly overwrite the\n // attribute when a parent context actually exists, so the plain prop reflection is left\n // alone otherwise.\n if (stepperCtx) {\n watchEffect(() => {\n const color = stepperCtx.color.value;\n const size = stepperCtx.size.value;\n const orientation = stepperCtx.orientation.value;\n\n if (color !== undefined) el.setAttribute('color', color);\n\n if (size !== undefined) el.setAttribute('size', size);\n\n el.setAttribute('orientation', orientation);\n });\n }\n\n const stateLabel = (): string | undefined => {\n if (props.error.value) return 'error';\n\n if (isCompleted()) return 'completed';\n\n if (isCurrent()) return 'current step';\n\n return undefined;\n };\n\n const positionLabel = () => `Step ${displayIndex()} of ${displayTotal()}`;\n const srLabel = () => {\n const state = stateLabel();\n\n return state ? `${positionLabel()}, ${state}` : positionLabel();\n };\n\n const handleClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (!isNavigable()) {\n event.preventDefault();\n\n return;\n }\n\n el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n };\n\n const indicatorTemplate = () => html`\n <span class=\"indicator\" part=\"indicator\" aria-hidden=\"true\">\n <span class=\"icon-slot\" ?hidden=\"${() => !slots.has('icon').value}\"><slot name=\"icon\"></slot></span>\n ${() =>\n slots.has('icon').value\n ? ''\n : props.error.value\n ? html`\n <ore-icon name=\"x\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : isCompleted()\n ? html`\n <ore-icon name=\"check\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : html`\n <span class=\"number\">${displayIndex}</span>\n `}\n </span>\n `;\n\n const contentTemplate = () => html`\n <span class=\"content\" part=\"content\">\n <span class=\"sr-only\">${srLabel}</span>\n <span class=\"label\" part=\"label\">\n <span class=\"label-text\"><slot></slot></span>\n ${() =>\n props.optional.value\n ? html`\n <span class=\"optional-hint\">(optional)</span>\n `\n : ''}\n </span>\n <span class=\"description\" part=\"description\" ?hidden=\"${() => !slots.has('description').value}\">\n <slot name=\"description\"></slot>\n </span>\n </span>\n `;\n\n return html`\n <li class=\"step\" role=\"listitem\">\n <span class=\"connector connector-leading\" part=\"connector\" aria-hidden=\"true\"></span>\n <span class=\"connector connector-trailing\" part=\"connector\" aria-hidden=\"true\"></span>\n ${() =>\n isNavigable()\n ? html`\n <button\n type=\"button\"\n class=\"control\"\n part=\"control\"\n aria-current=\"${() => (isCurrent() ? 'step' : null)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"${() => (isCurrent() ? '0' : '-1')}\"\n @click=\"${handleClick}\">\n ${indicatorTemplate()}${contentTemplate()}\n </button>\n `\n : html`\n <div class=\"control\" part=\"control\" aria-current=\"${() => (isCurrent() ? 'step' : null)}\">\n ${indicatorTemplate()}${contentTemplate()}\n </div>\n `}\n </li>\n `;\n },\n styles: [colorThemeMixin, coarsePointerMixin, forcedColorsFocusMixin('button.control'), stepStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"step.cjs","names":[],"sources":["../src/content/stepper/step.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, prop, useSlots, watchEffect } from '@vielzeug/ore';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport stepStyles from './step.css?inline';\nimport { STEPPER_CTX } from './stepper';\n\nexport { ICON_TAG } from '../icon/icon';\nexport type OreStepProps = {\n /**\n * Theme color. Inherited from the parent `ore-stepper` when nested inside one (overrides\n * this value); only takes effect on its own when `ore-step` is rendered standalone.\n */\n color?: ThemeColor;\n /** Disables this step: it cannot be navigated to and is skipped by keyboard navigation. */\n disabled?: boolean;\n /** Marks this step as failed/invalid. Overrides the completed/current indicator visuals. */\n error?: boolean;\n /**\n * Marks this step as optional. Renders a small \"(optional)\" hint next to the label.\n * Purely presentational: has no effect on navigation.\n */\n optional?: boolean;\n /** Orientation. Inherited from the parent `ore-stepper` when nested inside one. */\n orientation?: 'horizontal' | 'vertical';\n /** Component size. Inherited from the parent `ore-stepper` when nested inside one. */\n size?: ComponentSize;\n /** Unique identifier, matches `ore-stepper`'s `value` attribute. */\n value: string;\n};\n\n/**\n * A single step trigger. Must be placed as a direct child of `ore-stepper`, which provides\n * this step's current/completed/navigable/index/total state via context: those are derived,\n * read-only attributes on this element, not settable props.\n *\n * @element ore-step\n *\n * @attr {string} value - Unique identifier, matches the parent ore-stepper's `value` attribute\n * @attr {boolean} disabled - Prevents navigation to this step\n * @attr {boolean} error - Marks the step as failed/invalid\n * @attr {boolean} optional - Renders an \"(optional)\" hint next to the label\n * @attr {boolean} current - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} completed - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} navigable - Read-only. Derived from the parent ore-stepper's `clickable`/`linear`/`disabled`.\n * @attr {number} index - Read-only. This step's 1-based position among its siblings.\n * @attr {number} total - Read-only. Total sibling step count.\n * @attr {string} color - Inherited from ore-stepper: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Inherited from ore-stepper: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Inherited from ore-stepper: 'horizontal' | 'vertical'\n *\n * @slot - Step label\n * @slot description - Optional supporting text shown below the label\n * @slot icon - Custom icon replacing the step number/check/error indicator\n *\n * @part control - Clickable (or static) root element for the step\n * @part indicator - Circular indicator holding the number/icon\n * @part content - Wrapper around the label and description\n * @part label - Step label element\n * @part description - Step description element\n * @part connector - Connector line segments (leading and trailing halves) either side of this step's indicator\n *\n * @example\n * ```html\n * <ore-step value=\"details\">Account details</ore-step>\n * <ore-step value=\"review\" disabled>Review</ore-step>\n * ```\n */\nexport const STEP_TAG = 'ore-step' as const;\ndefine<OreStepProps>(STEP_TAG, {\n props: {\n ...disablableBundle,\n color: prop.string<ThemeColor>(),\n error: prop.bool(false),\n optional: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n size: prop.string<ComponentSize>(),\n value: prop.string(''),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n const stepperCtx = inject(STEPPER_CTX);\n\n // ────────────────────────────────────────────────────────────────\n // State derived from the parent ore-stepper's context: see stepper.ts's\n // module doc comment for why this replaced parent-side attribute fan-out.\n // ────────────────────────────────────────────────────────────────\n\n // Plain functions, not `computed()`: every one of these ultimately reads\n // `stepperCtx.stepValues`/`stepperCtx.currentValue`, which are themselves `computed()`s\n // owned by the parent `ore-stepper`. Wrapping a *child* `computed()` around a *parent*\n // `computed()` (a computed-to-computed dependency crossing a `provide()`/`inject()`\n // boundary) is exactly the shape that surfaced two related bugs: a step's `completed`/\n // `current` attributes going permanently stale after a few rapid selections, and: worse :\n // a step's entire clickable/static control silently failing to render at all when its\n // `ore-step` tag upgrades before its siblings exist in the light DOM yet (true whenever\n // `ore-step`/`ore-stepper` are already `customElements.define()`d before this markup is\n // parsed, e.g. every sandboxed live-preview iframe). Reading straight through to the\n // parent's computeds on every call: no intermediate computed layer of our own to go\n // stale: made both disappear. Cheap enough to not need memoizing (a couple of `indexOf`/\n // comparisons over an already-memoized parent computed).\n const stepIndex = (): number => (stepperCtx ? stepperCtx.stepValues.value.indexOf(props.value.value) : -1);\n const totalSteps = (): number => stepperCtx?.stepValues.value.length ?? 0;\n const currentIndex = (): number =>\n stepperCtx ? stepperCtx.stepValues.value.indexOf(stepperCtx.currentValue.value ?? '') : -1;\n // 1-based, always-sane values for on-screen text (the step number badge, the sr-only\n // \"Step X of Y\" label): falls back to \"1 of 1\" when rendered standalone with no parent\n // `ore-stepper` to derive a real position from. Kept separate from the `index`/`total`\n // *attributes* below, which correctly reflect nothing at all in that same standalone case.\n const displayIndex = (): number => {\n const index = stepIndex();\n\n return index >= 0 ? index + 1 : 1;\n };\n const displayTotal = (): number => totalSteps() || 1;\n\n const isCurrent = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && index === current;\n };\n // Purely positional: intentionally NOT gated on `props.error.value`. This also drives the\n // `completed` *attribute* below, which `step.css` uses to color both connector segments\n // either side of the indicator (`:host([completed]) .connector`); every *consumer* of this\n // (the icon choice, the sr-only state label) already checks `error` first and short-circuits\n // before it matters, so folding `!error` in here too would only end up suppressing\n // `[completed]` on an error step that's before the current one: breaking the connector\n // color chain right at that step instead of just swapping its icon.\n const isCompleted = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && current >= 0 && index < current;\n };\n const isNavigable = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return (\n !!stepperCtx &&\n isStepNavigable({\n disabled: props.disabled.value === true,\n index,\n linear: stepperCtx.linear.value,\n stepperClickable: stepperCtx.clickable.value,\n stepperCurrentIndex: current,\n })\n );\n };\n const isDisabled = () => Boolean(props.disabled.value);\n\n // Purely derived, read-only state: no matching `prop.*` declaration, so `bind()` is the\n // sole writer and can safely reflect `undefined` (removes the attribute) when this step\n // isn't nested inside an `ore-stepper` at all.\n bind({\n attr: {\n completed: () => (isCompleted() ? true : undefined),\n current: () => (isCurrent() ? true : undefined),\n index: () => {\n const index = stepIndex();\n\n return index >= 0 ? String(index + 1) : undefined;\n },\n navigable: () => (isNavigable() ? true : undefined),\n total: () => (stepperCtx ? String(totalSteps()) : undefined),\n },\n });\n\n // `color`/`size`/`orientation` double as regular, independently-settable props (for a step\n // rendered standalone) *and* stepper-inherited values: mirrors ore-tab-item's handling of\n // its own `color`/`size`/`variant` inheritance from `ore-tabs`. Only forcibly overwrite the\n // attribute when a parent context actually exists, so the plain prop reflection is left\n // alone otherwise.\n if (stepperCtx) {\n watchEffect(() => {\n const color = stepperCtx.color.value;\n const size = stepperCtx.size.value;\n const orientation = stepperCtx.orientation.value;\n\n if (color !== undefined) el.setAttribute('color', color);\n\n if (size !== undefined) el.setAttribute('size', size);\n\n el.setAttribute('orientation', orientation);\n });\n }\n\n const stateLabel = (): string | undefined => {\n if (props.error.value) return 'error';\n\n if (isCompleted()) return 'completed';\n\n if (isCurrent()) return 'current step';\n\n return undefined;\n };\n\n const positionLabel = () => `Step ${displayIndex()} of ${displayTotal()}`;\n const srLabel = () => {\n const state = stateLabel();\n\n return state ? `${positionLabel()}, ${state}` : positionLabel();\n };\n\n const handleClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (!isNavigable()) {\n event.preventDefault();\n\n return;\n }\n\n el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n };\n\n const indicatorTemplate = () => html`\n <span class=\"indicator\" part=\"indicator\" aria-hidden=\"true\">\n <span class=\"icon-slot\" ?hidden=\"${() => !slots.has('icon').value}\"><slot name=\"icon\"></slot></span>\n ${() =>\n slots.has('icon').value\n ? ''\n : props.error.value\n ? html`\n <ore-icon name=\"x\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : isCompleted()\n ? html`\n <ore-icon name=\"check\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : html`\n <span class=\"number\">${displayIndex}</span>\n `}\n </span>\n `;\n\n const contentTemplate = () => html`\n <span class=\"content\" part=\"content\">\n <span class=\"sr-only\">${srLabel}</span>\n <span class=\"label\" part=\"label\">\n <span class=\"label-text\"><slot></slot></span>\n ${() =>\n props.optional.value\n ? html`\n <span class=\"optional-hint\">(optional)</span>\n `\n : ''}\n </span>\n <span class=\"description\" part=\"description\" ?hidden=\"${() => !slots.has('description').value}\">\n <slot name=\"description\"></slot>\n </span>\n </span>\n `;\n\n return html`\n <li class=\"step\" role=\"listitem\">\n <span class=\"connector connector-leading\" part=\"connector\" aria-hidden=\"true\"></span>\n <span class=\"connector connector-trailing\" part=\"connector\" aria-hidden=\"true\"></span>\n ${() =>\n isNavigable()\n ? html`\n <button\n type=\"button\"\n class=\"control\"\n part=\"control\"\n aria-current=\"${() => (isCurrent() ? 'step' : null)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"${() => (isCurrent() ? '0' : '-1')}\"\n @click=\"${handleClick}\">\n ${indicatorTemplate()}${contentTemplate()}\n </button>\n `\n : html`\n <div class=\"control\" part=\"control\" aria-current=\"${() => (isCurrent() ? 'step' : null)}\">\n ${indicatorTemplate()}${contentTemplate()}\n </div>\n `}\n </li>\n `;\n },\n styles: [colorThemeMixin, coarsePointerMixin, forcedColorsFocusMixin('button.control'), stepStyles],\n});\n"],"mappings":"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"}
package/dist/step.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"step.js","names":[],"sources":["../src/content/stepper/step.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, prop, useSlots, watchEffect } from '@vielzeug/ore';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport stepStyles from './step.css?inline';\nimport { STEPPER_CTX } from './stepper';\n\nexport { ICON_TAG } from '../icon/icon';\nexport type OreStepProps = {\n /**\n * Theme color. Inherited from the parent `ore-stepper` when nested inside one (overrides\n * this value); only takes effect on its own when `ore-step` is rendered standalone.\n */\n color?: ThemeColor;\n /** Disables this step — it cannot be navigated to and is skipped by keyboard navigation. */\n disabled?: boolean;\n /** Marks this step as failed/invalid. Overrides the completed/current indicator visuals. */\n error?: boolean;\n /**\n * Marks this step as optional. Renders a small \"(optional)\" hint next to the label.\n * Purely presentational — has no effect on navigation.\n */\n optional?: boolean;\n /** Orientation. Inherited from the parent `ore-stepper` when nested inside one. */\n orientation?: 'horizontal' | 'vertical';\n /** Component size. Inherited from the parent `ore-stepper` when nested inside one. */\n size?: ComponentSize;\n /** Unique identifier, matches `ore-stepper`'s `value` attribute. */\n value: string;\n};\n\n/**\n * A single step trigger. Must be placed as a direct child of `ore-stepper`, which provides\n * this step's current/completed/navigable/index/total state via context — those are derived,\n * read-only attributes on this element, not settable props.\n *\n * @element ore-step\n *\n * @attr {string} value - Unique identifier, matches the parent ore-stepper's `value` attribute\n * @attr {boolean} disabled - Prevents navigation to this step\n * @attr {boolean} error - Marks the step as failed/invalid\n * @attr {boolean} optional - Renders an \"(optional)\" hint next to the label\n * @attr {boolean} current - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} completed - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} navigable - Read-only. Derived from the parent ore-stepper's `clickable`/`linear`/`disabled`.\n * @attr {number} index - Read-only. This step's 1-based position among its siblings.\n * @attr {number} total - Read-only. Total sibling step count.\n * @attr {string} color - Inherited from ore-stepper: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Inherited from ore-stepper: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Inherited from ore-stepper: 'horizontal' | 'vertical'\n *\n * @slot - Step label\n * @slot description - Optional supporting text shown below the label\n * @slot icon - Custom icon replacing the step number/check/error indicator\n *\n * @part control - Clickable (or static) root element for the step\n * @part indicator - Circular indicator holding the number/icon\n * @part content - Wrapper around the label and description\n * @part label - Step label element\n * @part description - Step description element\n * @part connector - Connector line segments (leading and trailing halves) either side of this step's indicator\n *\n * @example\n * ```html\n * <ore-step value=\"details\">Account details</ore-step>\n * <ore-step value=\"review\" disabled>Review</ore-step>\n * ```\n */\nexport const STEP_TAG = 'ore-step' as const;\ndefine<OreStepProps>(STEP_TAG, {\n props: {\n ...disablableBundle,\n color: prop.string<ThemeColor>(),\n error: prop.bool(false),\n optional: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n size: prop.string<ComponentSize>(),\n value: prop.string(''),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n const stepperCtx = inject(STEPPER_CTX);\n\n // ────────────────────────────────────────────────────────────────\n // State derived from the parent ore-stepper's context — see stepper.ts's\n // module doc comment for why this replaced parent-side attribute fan-out.\n // ────────────────────────────────────────────────────────────────\n\n // Plain functions, not `computed()` — every one of these ultimately reads\n // `stepperCtx.stepValues`/`stepperCtx.currentValue`, which are themselves `computed()`s\n // owned by the parent `ore-stepper`. Wrapping a *child* `computed()` around a *parent*\n // `computed()` (a computed-to-computed dependency crossing a `provide()`/`inject()`\n // boundary) is exactly the shape that surfaced two related bugs: a step's `completed`/\n // `current` attributes going permanently stale after a few rapid selections, and — worse —\n // a step's entire clickable/static control silently failing to render at all when its\n // `ore-step` tag upgrades before its siblings exist in the light DOM yet (true whenever\n // `ore-step`/`ore-stepper` are already `customElements.define()`d before this markup is\n // parsed, e.g. every sandboxed live-preview iframe). Reading straight through to the\n // parent's computeds on every call — no intermediate computed layer of our own to go\n // stale — made both disappear. Cheap enough to not need memoizing (a couple of `indexOf`/\n // comparisons over an already-memoized parent computed).\n const stepIndex = (): number => (stepperCtx ? stepperCtx.stepValues.value.indexOf(props.value.value) : -1);\n const totalSteps = (): number => stepperCtx?.stepValues.value.length ?? 0;\n const currentIndex = (): number =>\n stepperCtx ? stepperCtx.stepValues.value.indexOf(stepperCtx.currentValue.value ?? '') : -1;\n // 1-based, always-sane values for on-screen text (the step number badge, the sr-only\n // \"Step X of Y\" label) — falls back to \"1 of 1\" when rendered standalone with no parent\n // `ore-stepper` to derive a real position from. Kept separate from the `index`/`total`\n // *attributes* below, which correctly reflect nothing at all in that same standalone case.\n const displayIndex = (): number => {\n const index = stepIndex();\n\n return index >= 0 ? index + 1 : 1;\n };\n const displayTotal = (): number => totalSteps() || 1;\n\n const isCurrent = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && index === current;\n };\n // Purely positional — intentionally NOT gated on `props.error.value`. This also drives the\n // `completed` *attribute* below, which `step.css` uses to color both connector segments\n // either side of the indicator (`:host([completed]) .connector`); every *consumer* of this\n // (the icon choice, the sr-only state label) already checks `error` first and short-circuits\n // before it matters, so folding `!error` in here too would only end up suppressing\n // `[completed]` on an error step that's before the current one — breaking the connector\n // color chain right at that step instead of just swapping its icon.\n const isCompleted = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && current >= 0 && index < current;\n };\n const isNavigable = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return (\n !!stepperCtx &&\n isStepNavigable({\n disabled: props.disabled.value === true,\n index,\n linear: stepperCtx.linear.value,\n stepperClickable: stepperCtx.clickable.value,\n stepperCurrentIndex: current,\n })\n );\n };\n const isDisabled = () => Boolean(props.disabled.value);\n\n // Purely derived, read-only state — no matching `prop.*` declaration, so `bind()` is the\n // sole writer and can safely reflect `undefined` (removes the attribute) when this step\n // isn't nested inside an `ore-stepper` at all.\n bind({\n attr: {\n completed: () => (isCompleted() ? true : undefined),\n current: () => (isCurrent() ? true : undefined),\n index: () => {\n const index = stepIndex();\n\n return index >= 0 ? String(index + 1) : undefined;\n },\n navigable: () => (isNavigable() ? true : undefined),\n total: () => (stepperCtx ? String(totalSteps()) : undefined),\n },\n });\n\n // `color`/`size`/`orientation` double as regular, independently-settable props (for a step\n // rendered standalone) *and* stepper-inherited values — mirrors ore-tab-item's handling of\n // its own `color`/`size`/`variant` inheritance from `ore-tabs`. Only forcibly overwrite the\n // attribute when a parent context actually exists, so the plain prop reflection is left\n // alone otherwise.\n if (stepperCtx) {\n watchEffect(() => {\n const color = stepperCtx.color.value;\n const size = stepperCtx.size.value;\n const orientation = stepperCtx.orientation.value;\n\n if (color !== undefined) el.setAttribute('color', color);\n\n if (size !== undefined) el.setAttribute('size', size);\n\n el.setAttribute('orientation', orientation);\n });\n }\n\n const stateLabel = (): string | undefined => {\n if (props.error.value) return 'error';\n\n if (isCompleted()) return 'completed';\n\n if (isCurrent()) return 'current step';\n\n return undefined;\n };\n\n const positionLabel = () => `Step ${displayIndex()} of ${displayTotal()}`;\n const srLabel = () => {\n const state = stateLabel();\n\n return state ? `${positionLabel()}, ${state}` : positionLabel();\n };\n\n const handleClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (!isNavigable()) {\n event.preventDefault();\n\n return;\n }\n\n el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n };\n\n const indicatorTemplate = () => html`\n <span class=\"indicator\" part=\"indicator\" aria-hidden=\"true\">\n <span class=\"icon-slot\" ?hidden=\"${() => !slots.has('icon').value}\"><slot name=\"icon\"></slot></span>\n ${() =>\n slots.has('icon').value\n ? ''\n : props.error.value\n ? html`\n <ore-icon name=\"x\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : isCompleted()\n ? html`\n <ore-icon name=\"check\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : html`\n <span class=\"number\">${displayIndex}</span>\n `}\n </span>\n `;\n\n const contentTemplate = () => html`\n <span class=\"content\" part=\"content\">\n <span class=\"sr-only\">${srLabel}</span>\n <span class=\"label\" part=\"label\">\n <span class=\"label-text\"><slot></slot></span>\n ${() =>\n props.optional.value\n ? html`\n <span class=\"optional-hint\">(optional)</span>\n `\n : ''}\n </span>\n <span class=\"description\" part=\"description\" ?hidden=\"${() => !slots.has('description').value}\">\n <slot name=\"description\"></slot>\n </span>\n </span>\n `;\n\n return html`\n <li class=\"step\" role=\"listitem\">\n <span class=\"connector connector-leading\" part=\"connector\" aria-hidden=\"true\"></span>\n <span class=\"connector connector-trailing\" part=\"connector\" aria-hidden=\"true\"></span>\n ${() =>\n isNavigable()\n ? html`\n <button\n type=\"button\"\n class=\"control\"\n part=\"control\"\n aria-current=\"${() => (isCurrent() ? 'step' : null)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"${() => (isCurrent() ? '0' : '-1')}\"\n @click=\"${handleClick}\">\n ${indicatorTemplate()}${contentTemplate()}\n </button>\n `\n : html`\n <div class=\"control\" part=\"control\" aria-current=\"${() => (isCurrent() ? 'step' : null)}\">\n ${indicatorTemplate()}${contentTemplate()}\n </div>\n `}\n </li>\n `;\n },\n styles: [colorThemeMixin, coarsePointerMixin, forcedColorsFocusMixin('button.control'), stepStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"step.js","names":[],"sources":["../src/content/stepper/step.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, prop, useSlots, watchEffect } from '@vielzeug/ore';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport stepStyles from './step.css?inline';\nimport { STEPPER_CTX } from './stepper';\n\nexport { ICON_TAG } from '../icon/icon';\nexport type OreStepProps = {\n /**\n * Theme color. Inherited from the parent `ore-stepper` when nested inside one (overrides\n * this value); only takes effect on its own when `ore-step` is rendered standalone.\n */\n color?: ThemeColor;\n /** Disables this step: it cannot be navigated to and is skipped by keyboard navigation. */\n disabled?: boolean;\n /** Marks this step as failed/invalid. Overrides the completed/current indicator visuals. */\n error?: boolean;\n /**\n * Marks this step as optional. Renders a small \"(optional)\" hint next to the label.\n * Purely presentational: has no effect on navigation.\n */\n optional?: boolean;\n /** Orientation. Inherited from the parent `ore-stepper` when nested inside one. */\n orientation?: 'horizontal' | 'vertical';\n /** Component size. Inherited from the parent `ore-stepper` when nested inside one. */\n size?: ComponentSize;\n /** Unique identifier, matches `ore-stepper`'s `value` attribute. */\n value: string;\n};\n\n/**\n * A single step trigger. Must be placed as a direct child of `ore-stepper`, which provides\n * this step's current/completed/navigable/index/total state via context: those are derived,\n * read-only attributes on this element, not settable props.\n *\n * @element ore-step\n *\n * @attr {string} value - Unique identifier, matches the parent ore-stepper's `value` attribute\n * @attr {boolean} disabled - Prevents navigation to this step\n * @attr {boolean} error - Marks the step as failed/invalid\n * @attr {boolean} optional - Renders an \"(optional)\" hint next to the label\n * @attr {boolean} current - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} completed - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} navigable - Read-only. Derived from the parent ore-stepper's `clickable`/`linear`/`disabled`.\n * @attr {number} index - Read-only. This step's 1-based position among its siblings.\n * @attr {number} total - Read-only. Total sibling step count.\n * @attr {string} color - Inherited from ore-stepper: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Inherited from ore-stepper: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Inherited from ore-stepper: 'horizontal' | 'vertical'\n *\n * @slot - Step label\n * @slot description - Optional supporting text shown below the label\n * @slot icon - Custom icon replacing the step number/check/error indicator\n *\n * @part control - Clickable (or static) root element for the step\n * @part indicator - Circular indicator holding the number/icon\n * @part content - Wrapper around the label and description\n * @part label - Step label element\n * @part description - Step description element\n * @part connector - Connector line segments (leading and trailing halves) either side of this step's indicator\n *\n * @example\n * ```html\n * <ore-step value=\"details\">Account details</ore-step>\n * <ore-step value=\"review\" disabled>Review</ore-step>\n * ```\n */\nexport const STEP_TAG = 'ore-step' as const;\ndefine<OreStepProps>(STEP_TAG, {\n props: {\n ...disablableBundle,\n color: prop.string<ThemeColor>(),\n error: prop.bool(false),\n optional: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n size: prop.string<ComponentSize>(),\n value: prop.string(''),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n const stepperCtx = inject(STEPPER_CTX);\n\n // ────────────────────────────────────────────────────────────────\n // State derived from the parent ore-stepper's context: see stepper.ts's\n // module doc comment for why this replaced parent-side attribute fan-out.\n // ────────────────────────────────────────────────────────────────\n\n // Plain functions, not `computed()`: every one of these ultimately reads\n // `stepperCtx.stepValues`/`stepperCtx.currentValue`, which are themselves `computed()`s\n // owned by the parent `ore-stepper`. Wrapping a *child* `computed()` around a *parent*\n // `computed()` (a computed-to-computed dependency crossing a `provide()`/`inject()`\n // boundary) is exactly the shape that surfaced two related bugs: a step's `completed`/\n // `current` attributes going permanently stale after a few rapid selections, and: worse :\n // a step's entire clickable/static control silently failing to render at all when its\n // `ore-step` tag upgrades before its siblings exist in the light DOM yet (true whenever\n // `ore-step`/`ore-stepper` are already `customElements.define()`d before this markup is\n // parsed, e.g. every sandboxed live-preview iframe). Reading straight through to the\n // parent's computeds on every call: no intermediate computed layer of our own to go\n // stale: made both disappear. Cheap enough to not need memoizing (a couple of `indexOf`/\n // comparisons over an already-memoized parent computed).\n const stepIndex = (): number => (stepperCtx ? stepperCtx.stepValues.value.indexOf(props.value.value) : -1);\n const totalSteps = (): number => stepperCtx?.stepValues.value.length ?? 0;\n const currentIndex = (): number =>\n stepperCtx ? stepperCtx.stepValues.value.indexOf(stepperCtx.currentValue.value ?? '') : -1;\n // 1-based, always-sane values for on-screen text (the step number badge, the sr-only\n // \"Step X of Y\" label): falls back to \"1 of 1\" when rendered standalone with no parent\n // `ore-stepper` to derive a real position from. Kept separate from the `index`/`total`\n // *attributes* below, which correctly reflect nothing at all in that same standalone case.\n const displayIndex = (): number => {\n const index = stepIndex();\n\n return index >= 0 ? index + 1 : 1;\n };\n const displayTotal = (): number => totalSteps() || 1;\n\n const isCurrent = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && index === current;\n };\n // Purely positional: intentionally NOT gated on `props.error.value`. This also drives the\n // `completed` *attribute* below, which `step.css` uses to color both connector segments\n // either side of the indicator (`:host([completed]) .connector`); every *consumer* of this\n // (the icon choice, the sr-only state label) already checks `error` first and short-circuits\n // before it matters, so folding `!error` in here too would only end up suppressing\n // `[completed]` on an error step that's before the current one: breaking the connector\n // color chain right at that step instead of just swapping its icon.\n const isCompleted = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && current >= 0 && index < current;\n };\n const isNavigable = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return (\n !!stepperCtx &&\n isStepNavigable({\n disabled: props.disabled.value === true,\n index,\n linear: stepperCtx.linear.value,\n stepperClickable: stepperCtx.clickable.value,\n stepperCurrentIndex: current,\n })\n );\n };\n const isDisabled = () => Boolean(props.disabled.value);\n\n // Purely derived, read-only state: no matching `prop.*` declaration, so `bind()` is the\n // sole writer and can safely reflect `undefined` (removes the attribute) when this step\n // isn't nested inside an `ore-stepper` at all.\n bind({\n attr: {\n completed: () => (isCompleted() ? true : undefined),\n current: () => (isCurrent() ? true : undefined),\n index: () => {\n const index = stepIndex();\n\n return index >= 0 ? String(index + 1) : undefined;\n },\n navigable: () => (isNavigable() ? true : undefined),\n total: () => (stepperCtx ? String(totalSteps()) : undefined),\n },\n });\n\n // `color`/`size`/`orientation` double as regular, independently-settable props (for a step\n // rendered standalone) *and* stepper-inherited values: mirrors ore-tab-item's handling of\n // its own `color`/`size`/`variant` inheritance from `ore-tabs`. Only forcibly overwrite the\n // attribute when a parent context actually exists, so the plain prop reflection is left\n // alone otherwise.\n if (stepperCtx) {\n watchEffect(() => {\n const color = stepperCtx.color.value;\n const size = stepperCtx.size.value;\n const orientation = stepperCtx.orientation.value;\n\n if (color !== undefined) el.setAttribute('color', color);\n\n if (size !== undefined) el.setAttribute('size', size);\n\n el.setAttribute('orientation', orientation);\n });\n }\n\n const stateLabel = (): string | undefined => {\n if (props.error.value) return 'error';\n\n if (isCompleted()) return 'completed';\n\n if (isCurrent()) return 'current step';\n\n return undefined;\n };\n\n const positionLabel = () => `Step ${displayIndex()} of ${displayTotal()}`;\n const srLabel = () => {\n const state = stateLabel();\n\n return state ? `${positionLabel()}, ${state}` : positionLabel();\n };\n\n const handleClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (!isNavigable()) {\n event.preventDefault();\n\n return;\n }\n\n el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n };\n\n const indicatorTemplate = () => html`\n <span class=\"indicator\" part=\"indicator\" aria-hidden=\"true\">\n <span class=\"icon-slot\" ?hidden=\"${() => !slots.has('icon').value}\"><slot name=\"icon\"></slot></span>\n ${() =>\n slots.has('icon').value\n ? ''\n : props.error.value\n ? html`\n <ore-icon name=\"x\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : isCompleted()\n ? html`\n <ore-icon name=\"check\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : html`\n <span class=\"number\">${displayIndex}</span>\n `}\n </span>\n `;\n\n const contentTemplate = () => html`\n <span class=\"content\" part=\"content\">\n <span class=\"sr-only\">${srLabel}</span>\n <span class=\"label\" part=\"label\">\n <span class=\"label-text\"><slot></slot></span>\n ${() =>\n props.optional.value\n ? html`\n <span class=\"optional-hint\">(optional)</span>\n `\n : ''}\n </span>\n <span class=\"description\" part=\"description\" ?hidden=\"${() => !slots.has('description').value}\">\n <slot name=\"description\"></slot>\n </span>\n </span>\n `;\n\n return html`\n <li class=\"step\" role=\"listitem\">\n <span class=\"connector connector-leading\" part=\"connector\" aria-hidden=\"true\"></span>\n <span class=\"connector connector-trailing\" part=\"connector\" aria-hidden=\"true\"></span>\n ${() =>\n isNavigable()\n ? html`\n <button\n type=\"button\"\n class=\"control\"\n part=\"control\"\n aria-current=\"${() => (isCurrent() ? 'step' : null)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"${() => (isCurrent() ? '0' : '-1')}\"\n @click=\"${handleClick}\">\n ${indicatorTemplate()}${contentTemplate()}\n </button>\n `\n : html`\n <div class=\"control\" part=\"control\" aria-current=\"${() => (isCurrent() ? 'step' : null)}\">\n ${indicatorTemplate()}${contentTemplate()}\n </div>\n `}\n </li>\n `;\n },\n styles: [colorThemeMixin, coarsePointerMixin, forcedColorsFocusMixin('button.control'), stepStyles],\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"stepper.cjs","names":[],"sources":["../src/content/stepper/stepper.ts"],"sourcesContent":["import {\n bind,\n createContext,\n define,\n getHost,\n html,\n onCleanup,\n onMounted,\n prop,\n provide,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal, watch } from '@vielzeug/ripple';\nimport { createInteraction, createListControl, elementDirection, lifecycleSignal } from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport componentStyles from './stepper.css?inline';\n\n// ── Context ─────────────────────────────────────────────────────────────────\n//\n// ore-step derives all of its parent-relative state (current/completed/navigable/\n// index/total/color/size/orientation) from this context instead of ore-stepper\n// pushing 8 attributes onto every child on every change. Matches the\n// provide()/inject() coordination already used by ore-tabs/ore-tab-item,\n// ore-radio-group/ore-radio, and ore-list/ore-list-item — ore-stepper was\n// previously the one outlier doing manual `querySelectorAll` + `setAttribute`\n// fan-out, which meant every reactive change re-walked and re-wrote every step\n// regardless of whether that step's own state actually changed.\n\n/** Context provided by ore-stepper to its ore-step children. */\nexport type StepperContext = {\n clickable: Readable<boolean>;\n color: Readable<ThemeColor | undefined>;\n currentValue: Readable<string | undefined>;\n linear: Readable<boolean>;\n orientation: Readable<'horizontal' | 'vertical'>;\n size: Readable<ComponentSize | undefined>;\n /** Ordered `value`s of every sibling `ore-step`, used to derive index/total/completed. */\n stepValues: Readable<string[]>;\n};\n/** Injection key for the stepper context. */\nexport const STEPPER_CTX = createContext<StepperContext>('StepperContext');\n\nexport type OreStepperEvents = {\n change: { value: string };\n};\n\nexport type OreStepperProps = {\n /** When true, steps are clickable/keyboard-focusable for navigation. Default: display-only progress. */\n clickable?: boolean;\n /** Theme color for the current/completed step indicators */\n color?: ThemeColor;\n /** Disables the whole stepper — no step is navigable regardless of `clickable` */\n disabled?: boolean;\n /** Accessible label for the nav landmark */\n label?: string;\n /**\n * Restricts navigation to completed steps and the current step — steps ahead of the\n * current one cannot be clicked or focused, even when `clickable` is set.\n */\n linear?: boolean;\n /** Layout orientation — 'horizontal' (default, desktop) or 'vertical' (compact/mobile-friendly) */\n orientation?: 'horizontal' | 'vertical';\n /** Component size */\n size?: ComponentSize;\n /** The `value` of the currently active `ore-step` */\n value?: string;\n};\n\n/**\n * Displays progress through a sequence of numbered steps. Manages step selection and provides\n * shared state (current value, clickability, theming) to its `ore-step` children via context.\n * Can be purely informational (progress display) or interactive navigation.\n *\n * @element ore-stepper\n * @element ore-step - Child element for each step (auto-discovered)\n *\n * @attr {string} value - The value of the currently active step\n * @attr {boolean} clickable - Allow clicking/focusing steps to navigate\n * @attr {boolean} linear - Restrict navigation to completed + current steps only\n * @attr {boolean} disabled - Disables the whole stepper\n * @attr {string} orientation - 'horizontal' (default) | 'vertical'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav landmark label (default: 'Progress')\n *\n * @fires change - Emitted when the active step changes via click/keyboard. detail: { value: string }\n *\n * @slot - `ore-step` elements\n *\n * @cssprop --stepper-connector-color - Color of the connector line between steps\n * @cssprop --stepper-connector-size - Thickness of the connector line\n * @cssprop --stepper-gap - Gap between steps\n *\n * @part nav - Navigation landmark element\n * @part list - Ordered list container holding the slotted steps\n *\n * @example\n * ```html\n * <!-- Display-only progress -->\n * <ore-stepper value=\"shipping\" color=\"primary\">\n * <ore-step value=\"cart\">Cart</ore-step>\n * <ore-step value=\"shipping\">Shipping</ore-step>\n * <ore-step value=\"payment\">Payment</ore-step>\n * </ore-stepper>\n *\n * <!-- Clickable navigation, mobile-friendly vertical layout -->\n * <ore-stepper value=\"shipping\" clickable linear orientation=\"vertical\">\n * <ore-step value=\"cart\">Cart</ore-step>\n * <ore-step value=\"shipping\">Shipping</ore-step>\n * <ore-step value=\"payment\" disabled>Payment</ore-step>\n * </ore-stepper>\n * ```\n */\nexport const STEPPER_TAG = 'ore-stepper' as const;\ndefine<OreStepperProps>(STEPPER_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n clickable: prop.bool(false),\n label: prop.string('Progress'),\n linear: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n value: prop.string(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreStepperEvents>();\n const slots = useSlots();\n\n const getSteps = (): HTMLElement[] => Array.from(el.querySelectorAll(':scope > ore-step')) as HTMLElement[];\n\n const focusStep = (step: HTMLElement | undefined) => {\n step?.shadowRoot?.querySelector<HTMLElement>('button.control')?.focus();\n };\n\n // ────────────────────────────────────────────────────────────────\n // Selection State — mirrors ore-tabs' `selectedValue` signal + `ensureSelection()` pattern\n // ────────────────────────────────────────────────────────────────\n\n const currentValue = signal<string | undefined>(props.value.value);\n\n bind({ attr: { value: () => currentValue.value ?? null } });\n\n const setSelection = (value: string | undefined, shouldEmit = false) => {\n if (!value || value === currentValue.value) return;\n\n currentValue.value = value;\n\n if (shouldEmit) emit('change', { value });\n };\n\n const ensureSelection = () => {\n const steps = getSteps();\n\n if (steps.length === 0) return;\n\n const current = currentValue.value;\n const hasCurrent = current ? steps.some((s) => s.getAttribute('value') === current) : false;\n\n if (hasCurrent) return;\n\n const firstEnabled = steps.find((s) => !s.hasAttribute('disabled'))?.getAttribute('value') ?? undefined;\n\n if (firstEnabled) setSelection(firstEnabled);\n };\n\n watch(props.value, (value) => {\n currentValue.value = value;\n ensureSelection();\n });\n\n // ────────────────────────────────────────────────────────────────\n // Context provided to ore-step children\n // ────────────────────────────────────────────────────────────────\n\n const stepValues = computed(() => {\n void slots.elements().value;\n\n return getSteps().map((s) => s.getAttribute('value') ?? '');\n });\n\n provide(STEPPER_CTX, {\n clickable: computed(() => Boolean(props.clickable.value) && !props.disabled.value),\n color: props.color,\n currentValue,\n linear: computed(() => Boolean(props.linear.value)),\n orientation: computed(() => props.orientation.value ?? 'horizontal'),\n size: props.size,\n stepValues,\n });\n\n // Deferred to `onMounted()` (mirrors ore-tabs' `ensureSelection()` timing) rather than an\n // immediate `watch(stepValues, ...)` — `getSteps()` walks the *live* light DOM, and while the\n // browser is still parsing this element's `ore-step` children (synchronously upgrading each\n // one as its own tag is reached, which happens whenever `customElements.define()` already\n // ran before this markup was parsed — exactly what a sandboxed live-preview iframe does by\n // design), `stepValues` observes that child list mid-populate. Reading it eagerly here used\n // to call `ensureSelection()` — and therefore write `currentValue` — once per step as each\n // one was discovered, interleaved with that *same* step's own first render effect further\n // down the reactive graph. That reentrant write during a child's not-yet-finished initial\n // render corrupted its rendered output (the step's clickable/static control silently failed\n // to mount at all). Onmounted's callback runs on a microtask, strictly after the whole\n // synchronous parse (and thus every child) has completed, so `getSteps()` sees the final list.\n onMounted(() => {\n ensureSelection();\n return undefined;\n });\n\n // ────────────────────────────────────────────────────────────────\n // Keyboard Navigation (roving tabindex over navigable steps)\n // ────────────────────────────────────────────────────────────────\n\n const getNavigableSteps = (): HTMLElement[] => {\n const steps = getSteps();\n const values = steps.map((s) => s.getAttribute('value') ?? '');\n const currentIndex = values.indexOf(currentValue.value ?? '');\n const clickable = Boolean(props.clickable.value) && !props.disabled.value;\n const linear = Boolean(props.linear.value);\n\n return steps.filter((step, index) =>\n isStepNavigable({\n disabled: step.hasAttribute('disabled'),\n index,\n linear,\n stepperClickable: clickable,\n stepperCurrentIndex: currentIndex,\n }),\n );\n };\n\n const listControl = createListControl({\n direction: () => elementDirection(el),\n getItems: getNavigableSteps,\n loop: false,\n onNavigate: ({ item }) => {\n // Select BEFORE focusing: changing `currentValue` re-renders each step's\n // control (the step's navigable/button node-slot depends on the current\n // index), which destroys the previously focused button. Ripple flushes\n // effects synchronously, so by the time focusStep() runs the replacement\n // button exists.\n const value = item.getAttribute('value');\n\n if (value) setSelection(value, true);\n\n focusStep(item);\n },\n orientation: () => (props.orientation.value === 'vertical' ? 'vertical' : 'horizontal'),\n signal: lifecycleSignal(onCleanup),\n });\n\n const handleStepClick = (e: Event) => {\n const step = e\n .composedPath()\n .find((node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-step');\n\n if (!step || step.closest(STEPPER_TAG) !== el || !getNavigableSteps().includes(step)) return;\n\n const value = step.getAttribute('value');\n\n setSelection(value ?? undefined, true);\n // The click focused the step's old control; the selection re-render replaced\n // it — restore focus onto the new one (see onNavigate's ordering note).\n focusStep(step);\n };\n\n const activateFocusedStep = (): void => {\n const steps = getNavigableSteps();\n const focusedStep = steps.find(\n (step) => step === document.activeElement || step.shadowRoot?.activeElement === document.activeElement,\n );\n const value = focusedStep?.getAttribute('value');\n\n if (value) {\n setSelection(value, true);\n focusStep(focusedStep);\n }\n };\n\n const activationPress = createInteraction({ onPress: activateFocusedStep });\n\n const handleKeydown = (e: KeyboardEvent) => {\n const steps = getNavigableSteps();\n\n if (steps.length === 0) return;\n\n const path = e.composedPath();\n const stepFromEvent = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-step',\n );\n const focused = stepFromEvent ? steps.indexOf(stepFromEvent) : -1;\n\n if (focused >= 0) listControl.set(focused);\n\n if (listControl.handleKeydown(e)) return;\n\n activationPress.handleKeydown(e);\n };\n\n bind({\n on: {\n click: handleStepClick,\n keydown: handleKeydown,\n },\n });\n\n return html`\n <nav part=\"nav\" aria-label=\"${props.label}\">\n <ol class=\"steps\" role=\"list\" part=\"list\">\n <slot></slot>\n </ol>\n </nav>\n `;\n },\n styles: [componentStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"stepper.cjs","names":[],"sources":["../src/content/stepper/stepper.ts"],"sourcesContent":["import {\n bind,\n createContext,\n define,\n getHost,\n html,\n onCleanup,\n onMounted,\n prop,\n provide,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal, watch } from '@vielzeug/ripple';\nimport { createInteraction, createListControl, elementDirection, lifecycleSignal } from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport componentStyles from './stepper.css?inline';\n\n// ── Context ─────────────────────────────────────────────────────────────────\n//\n// ore-step derives all of its parent-relative state (current/completed/navigable/\n// index/total/color/size/orientation) from this context instead of ore-stepper\n// pushing 8 attributes onto every child on every change. Matches the\n// provide()/inject() coordination already used by ore-tabs/ore-tab-item,\n// ore-radio-group/ore-radio, and ore-list/ore-list-item: ore-stepper was\n// previously the one outlier doing manual `querySelectorAll` + `setAttribute`\n// fan-out, which meant every reactive change re-walked and re-wrote every step\n// regardless of whether that step's own state actually changed.\n\n/** Context provided by ore-stepper to its ore-step children. */\nexport type StepperContext = {\n clickable: Readable<boolean>;\n color: Readable<ThemeColor | undefined>;\n currentValue: Readable<string | undefined>;\n linear: Readable<boolean>;\n orientation: Readable<'horizontal' | 'vertical'>;\n size: Readable<ComponentSize | undefined>;\n /** Ordered `value`s of every sibling `ore-step`, used to derive index/total/completed. */\n stepValues: Readable<string[]>;\n};\n/** Injection key for the stepper context. */\nexport const STEPPER_CTX = createContext<StepperContext>('StepperContext');\n\nexport type OreStepperEvents = {\n change: { value: string };\n};\n\nexport type OreStepperProps = {\n /** When true, steps are clickable/keyboard-focusable for navigation. Default: display-only progress. */\n clickable?: boolean;\n /** Theme color for the current/completed step indicators */\n color?: ThemeColor;\n /** Disables the whole stepper: no step is navigable regardless of `clickable` */\n disabled?: boolean;\n /** Accessible label for the nav landmark */\n label?: string;\n /**\n * Restricts navigation to completed steps and the current step: steps ahead of the\n * current one cannot be clicked or focused, even when `clickable` is set.\n */\n linear?: boolean;\n /** Layout orientation: 'horizontal' (default, desktop) or 'vertical' (compact/mobile-friendly) */\n orientation?: 'horizontal' | 'vertical';\n /** Component size */\n size?: ComponentSize;\n /** The `value` of the currently active `ore-step` */\n value?: string;\n};\n\n/**\n * Displays progress through a sequence of numbered steps. Manages step selection and provides\n * shared state (current value, clickability, theming) to its `ore-step` children via context.\n * Can be purely informational (progress display) or interactive navigation.\n *\n * @element ore-stepper\n * @element ore-step - Child element for each step (auto-discovered)\n *\n * @attr {string} value - The value of the currently active step\n * @attr {boolean} clickable - Allow clicking/focusing steps to navigate\n * @attr {boolean} linear - Restrict navigation to completed + current steps only\n * @attr {boolean} disabled - Disables the whole stepper\n * @attr {string} orientation - 'horizontal' (default) | 'vertical'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav landmark label (default: 'Progress')\n *\n * @fires change - Emitted when the active step changes via click/keyboard. detail: { value: string }\n *\n * @slot - `ore-step` elements\n *\n * @cssprop --stepper-connector-color - Color of the connector line between steps\n * @cssprop --stepper-connector-size - Thickness of the connector line\n * @cssprop --stepper-gap - Gap between steps\n *\n * @part nav - Navigation landmark element\n * @part list - Ordered list container holding the slotted steps\n *\n * @example\n * ```html\n * <!-- Display-only progress -->\n * <ore-stepper value=\"shipping\" color=\"primary\">\n * <ore-step value=\"cart\">Cart</ore-step>\n * <ore-step value=\"shipping\">Shipping</ore-step>\n * <ore-step value=\"payment\">Payment</ore-step>\n * </ore-stepper>\n *\n * <!-- Clickable navigation, mobile-friendly vertical layout -->\n * <ore-stepper value=\"shipping\" clickable linear orientation=\"vertical\">\n * <ore-step value=\"cart\">Cart</ore-step>\n * <ore-step value=\"shipping\">Shipping</ore-step>\n * <ore-step value=\"payment\" disabled>Payment</ore-step>\n * </ore-stepper>\n * ```\n */\nexport const STEPPER_TAG = 'ore-stepper' as const;\ndefine<OreStepperProps>(STEPPER_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n clickable: prop.bool(false),\n label: prop.string('Progress'),\n linear: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n value: prop.string(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreStepperEvents>();\n const slots = useSlots();\n\n const getSteps = (): HTMLElement[] => Array.from(el.querySelectorAll(':scope > ore-step')) as HTMLElement[];\n\n const focusStep = (step: HTMLElement | undefined) => {\n step?.shadowRoot?.querySelector<HTMLElement>('button.control')?.focus();\n };\n\n // ────────────────────────────────────────────────────────────────\n // Selection State: mirrors ore-tabs' `selectedValue` signal + `ensureSelection()` pattern\n // ────────────────────────────────────────────────────────────────\n\n const currentValue = signal<string | undefined>(props.value.value);\n\n bind({ attr: { value: () => currentValue.value ?? null } });\n\n const setSelection = (value: string | undefined, shouldEmit = false) => {\n if (!value || value === currentValue.value) return;\n\n currentValue.value = value;\n\n if (shouldEmit) emit('change', { value });\n };\n\n const ensureSelection = () => {\n const steps = getSteps();\n\n if (steps.length === 0) return;\n\n const current = currentValue.value;\n const hasCurrent = current ? steps.some((s) => s.getAttribute('value') === current) : false;\n\n if (hasCurrent) return;\n\n const firstEnabled = steps.find((s) => !s.hasAttribute('disabled'))?.getAttribute('value') ?? undefined;\n\n if (firstEnabled) setSelection(firstEnabled);\n };\n\n watch(props.value, (value) => {\n currentValue.value = value;\n ensureSelection();\n });\n\n // ────────────────────────────────────────────────────────────────\n // Context provided to ore-step children\n // ────────────────────────────────────────────────────────────────\n\n const stepValues = computed(() => {\n void slots.elements().value;\n\n return getSteps().map((s) => s.getAttribute('value') ?? '');\n });\n\n provide(STEPPER_CTX, {\n clickable: computed(() => Boolean(props.clickable.value) && !props.disabled.value),\n color: props.color,\n currentValue,\n linear: computed(() => Boolean(props.linear.value)),\n orientation: computed(() => props.orientation.value ?? 'horizontal'),\n size: props.size,\n stepValues,\n });\n\n // Deferred to `onMounted()` (mirrors ore-tabs' `ensureSelection()` timing) rather than an\n // immediate `watch(stepValues, ...)`: `getSteps()` walks the *live* light DOM, and while the\n // browser is still parsing this element's `ore-step` children (synchronously upgrading each\n // one as its own tag is reached, which happens whenever `customElements.define()` already\n // ran before this markup was parsed: exactly what a sandboxed live-preview iframe does by\n // design), `stepValues` observes that child list mid-populate. Reading it eagerly here used\n // to call `ensureSelection()`, and therefore write `currentValue`: once per step as each\n // one was discovered, interleaved with that *same* step's own first render effect further\n // down the reactive graph. That reentrant write during a child's not-yet-finished initial\n // render corrupted its rendered output (the step's clickable/static control silently failed\n // to mount at all). Onmounted's callback runs on a microtask, strictly after the whole\n // synchronous parse (and thus every child) has completed, so `getSteps()` sees the final list.\n onMounted(() => {\n ensureSelection();\n return undefined;\n });\n\n // ────────────────────────────────────────────────────────────────\n // Keyboard Navigation (roving tabindex over navigable steps)\n // ────────────────────────────────────────────────────────────────\n\n const getNavigableSteps = (): HTMLElement[] => {\n const steps = getSteps();\n const values = steps.map((s) => s.getAttribute('value') ?? '');\n const currentIndex = values.indexOf(currentValue.value ?? '');\n const clickable = Boolean(props.clickable.value) && !props.disabled.value;\n const linear = Boolean(props.linear.value);\n\n return steps.filter((step, index) =>\n isStepNavigable({\n disabled: step.hasAttribute('disabled'),\n index,\n linear,\n stepperClickable: clickable,\n stepperCurrentIndex: currentIndex,\n }),\n );\n };\n\n const listControl = createListControl({\n direction: () => elementDirection(el),\n getItems: getNavigableSteps,\n loop: false,\n onNavigate: ({ item }) => {\n // Select BEFORE focusing: changing `currentValue` re-renders each step's\n // control (the step's navigable/button node-slot depends on the current\n // index), which destroys the previously focused button. Ripple flushes\n // effects synchronously, so by the time focusStep() runs the replacement\n // button exists.\n const value = item.getAttribute('value');\n\n if (value) setSelection(value, true);\n\n focusStep(item);\n },\n orientation: () => (props.orientation.value === 'vertical' ? 'vertical' : 'horizontal'),\n signal: lifecycleSignal(onCleanup),\n });\n\n const handleStepClick = (e: Event) => {\n const step = e\n .composedPath()\n .find((node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-step');\n\n if (!step || step.closest(STEPPER_TAG) !== el || !getNavigableSteps().includes(step)) return;\n\n const value = step.getAttribute('value');\n\n setSelection(value ?? undefined, true);\n // The click focused the step's old control; the selection re-render replaced\n // it: restore focus onto the new one (see onNavigate's ordering note).\n focusStep(step);\n };\n\n const activateFocusedStep = (): void => {\n const steps = getNavigableSteps();\n const focusedStep = steps.find(\n (step) => step === document.activeElement || step.shadowRoot?.activeElement === document.activeElement,\n );\n const value = focusedStep?.getAttribute('value');\n\n if (value) {\n setSelection(value, true);\n focusStep(focusedStep);\n }\n };\n\n const activationPress = createInteraction({ onPress: activateFocusedStep });\n\n const handleKeydown = (e: KeyboardEvent) => {\n const steps = getNavigableSteps();\n\n if (steps.length === 0) return;\n\n const path = e.composedPath();\n const stepFromEvent = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-step',\n );\n const focused = stepFromEvent ? steps.indexOf(stepFromEvent) : -1;\n\n if (focused >= 0) listControl.set(focused);\n\n if (listControl.handleKeydown(e)) return;\n\n activationPress.handleKeydown(e);\n };\n\n bind({\n on: {\n click: handleStepClick,\n keydown: handleKeydown,\n },\n });\n\n return html`\n <nav part=\"nav\" aria-label=\"${props.label}\">\n <ol class=\"steps\" role=\"list\" part=\"list\">\n <slot></slot>\n </ol>\n </nav>\n `;\n },\n styles: [componentStyles],\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"stepper.js","names":[],"sources":["../src/content/stepper/stepper.ts"],"sourcesContent":["import {\n bind,\n createContext,\n define,\n getHost,\n html,\n onCleanup,\n onMounted,\n prop,\n provide,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal, watch } from '@vielzeug/ripple';\nimport { createInteraction, createListControl, elementDirection, lifecycleSignal } from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport componentStyles from './stepper.css?inline';\n\n// ── Context ─────────────────────────────────────────────────────────────────\n//\n// ore-step derives all of its parent-relative state (current/completed/navigable/\n// index/total/color/size/orientation) from this context instead of ore-stepper\n// pushing 8 attributes onto every child on every change. Matches the\n// provide()/inject() coordination already used by ore-tabs/ore-tab-item,\n// ore-radio-group/ore-radio, and ore-list/ore-list-item — ore-stepper was\n// previously the one outlier doing manual `querySelectorAll` + `setAttribute`\n// fan-out, which meant every reactive change re-walked and re-wrote every step\n// regardless of whether that step's own state actually changed.\n\n/** Context provided by ore-stepper to its ore-step children. */\nexport type StepperContext = {\n clickable: Readable<boolean>;\n color: Readable<ThemeColor | undefined>;\n currentValue: Readable<string | undefined>;\n linear: Readable<boolean>;\n orientation: Readable<'horizontal' | 'vertical'>;\n size: Readable<ComponentSize | undefined>;\n /** Ordered `value`s of every sibling `ore-step`, used to derive index/total/completed. */\n stepValues: Readable<string[]>;\n};\n/** Injection key for the stepper context. */\nexport const STEPPER_CTX = createContext<StepperContext>('StepperContext');\n\nexport type OreStepperEvents = {\n change: { value: string };\n};\n\nexport type OreStepperProps = {\n /** When true, steps are clickable/keyboard-focusable for navigation. Default: display-only progress. */\n clickable?: boolean;\n /** Theme color for the current/completed step indicators */\n color?: ThemeColor;\n /** Disables the whole stepper — no step is navigable regardless of `clickable` */\n disabled?: boolean;\n /** Accessible label for the nav landmark */\n label?: string;\n /**\n * Restricts navigation to completed steps and the current step — steps ahead of the\n * current one cannot be clicked or focused, even when `clickable` is set.\n */\n linear?: boolean;\n /** Layout orientation — 'horizontal' (default, desktop) or 'vertical' (compact/mobile-friendly) */\n orientation?: 'horizontal' | 'vertical';\n /** Component size */\n size?: ComponentSize;\n /** The `value` of the currently active `ore-step` */\n value?: string;\n};\n\n/**\n * Displays progress through a sequence of numbered steps. Manages step selection and provides\n * shared state (current value, clickability, theming) to its `ore-step` children via context.\n * Can be purely informational (progress display) or interactive navigation.\n *\n * @element ore-stepper\n * @element ore-step - Child element for each step (auto-discovered)\n *\n * @attr {string} value - The value of the currently active step\n * @attr {boolean} clickable - Allow clicking/focusing steps to navigate\n * @attr {boolean} linear - Restrict navigation to completed + current steps only\n * @attr {boolean} disabled - Disables the whole stepper\n * @attr {string} orientation - 'horizontal' (default) | 'vertical'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav landmark label (default: 'Progress')\n *\n * @fires change - Emitted when the active step changes via click/keyboard. detail: { value: string }\n *\n * @slot - `ore-step` elements\n *\n * @cssprop --stepper-connector-color - Color of the connector line between steps\n * @cssprop --stepper-connector-size - Thickness of the connector line\n * @cssprop --stepper-gap - Gap between steps\n *\n * @part nav - Navigation landmark element\n * @part list - Ordered list container holding the slotted steps\n *\n * @example\n * ```html\n * <!-- Display-only progress -->\n * <ore-stepper value=\"shipping\" color=\"primary\">\n * <ore-step value=\"cart\">Cart</ore-step>\n * <ore-step value=\"shipping\">Shipping</ore-step>\n * <ore-step value=\"payment\">Payment</ore-step>\n * </ore-stepper>\n *\n * <!-- Clickable navigation, mobile-friendly vertical layout -->\n * <ore-stepper value=\"shipping\" clickable linear orientation=\"vertical\">\n * <ore-step value=\"cart\">Cart</ore-step>\n * <ore-step value=\"shipping\">Shipping</ore-step>\n * <ore-step value=\"payment\" disabled>Payment</ore-step>\n * </ore-stepper>\n * ```\n */\nexport const STEPPER_TAG = 'ore-stepper' as const;\ndefine<OreStepperProps>(STEPPER_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n clickable: prop.bool(false),\n label: prop.string('Progress'),\n linear: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n value: prop.string(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreStepperEvents>();\n const slots = useSlots();\n\n const getSteps = (): HTMLElement[] => Array.from(el.querySelectorAll(':scope > ore-step')) as HTMLElement[];\n\n const focusStep = (step: HTMLElement | undefined) => {\n step?.shadowRoot?.querySelector<HTMLElement>('button.control')?.focus();\n };\n\n // ────────────────────────────────────────────────────────────────\n // Selection State — mirrors ore-tabs' `selectedValue` signal + `ensureSelection()` pattern\n // ────────────────────────────────────────────────────────────────\n\n const currentValue = signal<string | undefined>(props.value.value);\n\n bind({ attr: { value: () => currentValue.value ?? null } });\n\n const setSelection = (value: string | undefined, shouldEmit = false) => {\n if (!value || value === currentValue.value) return;\n\n currentValue.value = value;\n\n if (shouldEmit) emit('change', { value });\n };\n\n const ensureSelection = () => {\n const steps = getSteps();\n\n if (steps.length === 0) return;\n\n const current = currentValue.value;\n const hasCurrent = current ? steps.some((s) => s.getAttribute('value') === current) : false;\n\n if (hasCurrent) return;\n\n const firstEnabled = steps.find((s) => !s.hasAttribute('disabled'))?.getAttribute('value') ?? undefined;\n\n if (firstEnabled) setSelection(firstEnabled);\n };\n\n watch(props.value, (value) => {\n currentValue.value = value;\n ensureSelection();\n });\n\n // ────────────────────────────────────────────────────────────────\n // Context provided to ore-step children\n // ────────────────────────────────────────────────────────────────\n\n const stepValues = computed(() => {\n void slots.elements().value;\n\n return getSteps().map((s) => s.getAttribute('value') ?? '');\n });\n\n provide(STEPPER_CTX, {\n clickable: computed(() => Boolean(props.clickable.value) && !props.disabled.value),\n color: props.color,\n currentValue,\n linear: computed(() => Boolean(props.linear.value)),\n orientation: computed(() => props.orientation.value ?? 'horizontal'),\n size: props.size,\n stepValues,\n });\n\n // Deferred to `onMounted()` (mirrors ore-tabs' `ensureSelection()` timing) rather than an\n // immediate `watch(stepValues, ...)` — `getSteps()` walks the *live* light DOM, and while the\n // browser is still parsing this element's `ore-step` children (synchronously upgrading each\n // one as its own tag is reached, which happens whenever `customElements.define()` already\n // ran before this markup was parsed — exactly what a sandboxed live-preview iframe does by\n // design), `stepValues` observes that child list mid-populate. Reading it eagerly here used\n // to call `ensureSelection()` — and therefore write `currentValue` — once per step as each\n // one was discovered, interleaved with that *same* step's own first render effect further\n // down the reactive graph. That reentrant write during a child's not-yet-finished initial\n // render corrupted its rendered output (the step's clickable/static control silently failed\n // to mount at all). Onmounted's callback runs on a microtask, strictly after the whole\n // synchronous parse (and thus every child) has completed, so `getSteps()` sees the final list.\n onMounted(() => {\n ensureSelection();\n return undefined;\n });\n\n // ────────────────────────────────────────────────────────────────\n // Keyboard Navigation (roving tabindex over navigable steps)\n // ────────────────────────────────────────────────────────────────\n\n const getNavigableSteps = (): HTMLElement[] => {\n const steps = getSteps();\n const values = steps.map((s) => s.getAttribute('value') ?? '');\n const currentIndex = values.indexOf(currentValue.value ?? '');\n const clickable = Boolean(props.clickable.value) && !props.disabled.value;\n const linear = Boolean(props.linear.value);\n\n return steps.filter((step, index) =>\n isStepNavigable({\n disabled: step.hasAttribute('disabled'),\n index,\n linear,\n stepperClickable: clickable,\n stepperCurrentIndex: currentIndex,\n }),\n );\n };\n\n const listControl = createListControl({\n direction: () => elementDirection(el),\n getItems: getNavigableSteps,\n loop: false,\n onNavigate: ({ item }) => {\n // Select BEFORE focusing: changing `currentValue` re-renders each step's\n // control (the step's navigable/button node-slot depends on the current\n // index), which destroys the previously focused button. Ripple flushes\n // effects synchronously, so by the time focusStep() runs the replacement\n // button exists.\n const value = item.getAttribute('value');\n\n if (value) setSelection(value, true);\n\n focusStep(item);\n },\n orientation: () => (props.orientation.value === 'vertical' ? 'vertical' : 'horizontal'),\n signal: lifecycleSignal(onCleanup),\n });\n\n const handleStepClick = (e: Event) => {\n const step = e\n .composedPath()\n .find((node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-step');\n\n if (!step || step.closest(STEPPER_TAG) !== el || !getNavigableSteps().includes(step)) return;\n\n const value = step.getAttribute('value');\n\n setSelection(value ?? undefined, true);\n // The click focused the step's old control; the selection re-render replaced\n // it — restore focus onto the new one (see onNavigate's ordering note).\n focusStep(step);\n };\n\n const activateFocusedStep = (): void => {\n const steps = getNavigableSteps();\n const focusedStep = steps.find(\n (step) => step === document.activeElement || step.shadowRoot?.activeElement === document.activeElement,\n );\n const value = focusedStep?.getAttribute('value');\n\n if (value) {\n setSelection(value, true);\n focusStep(focusedStep);\n }\n };\n\n const activationPress = createInteraction({ onPress: activateFocusedStep });\n\n const handleKeydown = (e: KeyboardEvent) => {\n const steps = getNavigableSteps();\n\n if (steps.length === 0) return;\n\n const path = e.composedPath();\n const stepFromEvent = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-step',\n );\n const focused = stepFromEvent ? steps.indexOf(stepFromEvent) : -1;\n\n if (focused >= 0) listControl.set(focused);\n\n if (listControl.handleKeydown(e)) return;\n\n activationPress.handleKeydown(e);\n };\n\n bind({\n on: {\n click: handleStepClick,\n keydown: handleKeydown,\n },\n });\n\n return html`\n <nav part=\"nav\" aria-label=\"${props.label}\">\n <ol class=\"steps\" role=\"list\" part=\"list\">\n <slot></slot>\n </ol>\n </nav>\n `;\n },\n styles: [componentStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"stepper.js","names":[],"sources":["../src/content/stepper/stepper.ts"],"sourcesContent":["import {\n bind,\n createContext,\n define,\n getHost,\n html,\n onCleanup,\n onMounted,\n prop,\n provide,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal, watch } from '@vielzeug/ripple';\nimport { createInteraction, createListControl, elementDirection, lifecycleSignal } from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport componentStyles from './stepper.css?inline';\n\n// ── Context ─────────────────────────────────────────────────────────────────\n//\n// ore-step derives all of its parent-relative state (current/completed/navigable/\n// index/total/color/size/orientation) from this context instead of ore-stepper\n// pushing 8 attributes onto every child on every change. Matches the\n// provide()/inject() coordination already used by ore-tabs/ore-tab-item,\n// ore-radio-group/ore-radio, and ore-list/ore-list-item: ore-stepper was\n// previously the one outlier doing manual `querySelectorAll` + `setAttribute`\n// fan-out, which meant every reactive change re-walked and re-wrote every step\n// regardless of whether that step's own state actually changed.\n\n/** Context provided by ore-stepper to its ore-step children. */\nexport type StepperContext = {\n clickable: Readable<boolean>;\n color: Readable<ThemeColor | undefined>;\n currentValue: Readable<string | undefined>;\n linear: Readable<boolean>;\n orientation: Readable<'horizontal' | 'vertical'>;\n size: Readable<ComponentSize | undefined>;\n /** Ordered `value`s of every sibling `ore-step`, used to derive index/total/completed. */\n stepValues: Readable<string[]>;\n};\n/** Injection key for the stepper context. */\nexport const STEPPER_CTX = createContext<StepperContext>('StepperContext');\n\nexport type OreStepperEvents = {\n change: { value: string };\n};\n\nexport type OreStepperProps = {\n /** When true, steps are clickable/keyboard-focusable for navigation. Default: display-only progress. */\n clickable?: boolean;\n /** Theme color for the current/completed step indicators */\n color?: ThemeColor;\n /** Disables the whole stepper: no step is navigable regardless of `clickable` */\n disabled?: boolean;\n /** Accessible label for the nav landmark */\n label?: string;\n /**\n * Restricts navigation to completed steps and the current step: steps ahead of the\n * current one cannot be clicked or focused, even when `clickable` is set.\n */\n linear?: boolean;\n /** Layout orientation: 'horizontal' (default, desktop) or 'vertical' (compact/mobile-friendly) */\n orientation?: 'horizontal' | 'vertical';\n /** Component size */\n size?: ComponentSize;\n /** The `value` of the currently active `ore-step` */\n value?: string;\n};\n\n/**\n * Displays progress through a sequence of numbered steps. Manages step selection and provides\n * shared state (current value, clickability, theming) to its `ore-step` children via context.\n * Can be purely informational (progress display) or interactive navigation.\n *\n * @element ore-stepper\n * @element ore-step - Child element for each step (auto-discovered)\n *\n * @attr {string} value - The value of the currently active step\n * @attr {boolean} clickable - Allow clicking/focusing steps to navigate\n * @attr {boolean} linear - Restrict navigation to completed + current steps only\n * @attr {boolean} disabled - Disables the whole stepper\n * @attr {string} orientation - 'horizontal' (default) | 'vertical'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav landmark label (default: 'Progress')\n *\n * @fires change - Emitted when the active step changes via click/keyboard. detail: { value: string }\n *\n * @slot - `ore-step` elements\n *\n * @cssprop --stepper-connector-color - Color of the connector line between steps\n * @cssprop --stepper-connector-size - Thickness of the connector line\n * @cssprop --stepper-gap - Gap between steps\n *\n * @part nav - Navigation landmark element\n * @part list - Ordered list container holding the slotted steps\n *\n * @example\n * ```html\n * <!-- Display-only progress -->\n * <ore-stepper value=\"shipping\" color=\"primary\">\n * <ore-step value=\"cart\">Cart</ore-step>\n * <ore-step value=\"shipping\">Shipping</ore-step>\n * <ore-step value=\"payment\">Payment</ore-step>\n * </ore-stepper>\n *\n * <!-- Clickable navigation, mobile-friendly vertical layout -->\n * <ore-stepper value=\"shipping\" clickable linear orientation=\"vertical\">\n * <ore-step value=\"cart\">Cart</ore-step>\n * <ore-step value=\"shipping\">Shipping</ore-step>\n * <ore-step value=\"payment\" disabled>Payment</ore-step>\n * </ore-stepper>\n * ```\n */\nexport const STEPPER_TAG = 'ore-stepper' as const;\ndefine<OreStepperProps>(STEPPER_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n clickable: prop.bool(false),\n label: prop.string('Progress'),\n linear: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n value: prop.string(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreStepperEvents>();\n const slots = useSlots();\n\n const getSteps = (): HTMLElement[] => Array.from(el.querySelectorAll(':scope > ore-step')) as HTMLElement[];\n\n const focusStep = (step: HTMLElement | undefined) => {\n step?.shadowRoot?.querySelector<HTMLElement>('button.control')?.focus();\n };\n\n // ────────────────────────────────────────────────────────────────\n // Selection State: mirrors ore-tabs' `selectedValue` signal + `ensureSelection()` pattern\n // ────────────────────────────────────────────────────────────────\n\n const currentValue = signal<string | undefined>(props.value.value);\n\n bind({ attr: { value: () => currentValue.value ?? null } });\n\n const setSelection = (value: string | undefined, shouldEmit = false) => {\n if (!value || value === currentValue.value) return;\n\n currentValue.value = value;\n\n if (shouldEmit) emit('change', { value });\n };\n\n const ensureSelection = () => {\n const steps = getSteps();\n\n if (steps.length === 0) return;\n\n const current = currentValue.value;\n const hasCurrent = current ? steps.some((s) => s.getAttribute('value') === current) : false;\n\n if (hasCurrent) return;\n\n const firstEnabled = steps.find((s) => !s.hasAttribute('disabled'))?.getAttribute('value') ?? undefined;\n\n if (firstEnabled) setSelection(firstEnabled);\n };\n\n watch(props.value, (value) => {\n currentValue.value = value;\n ensureSelection();\n });\n\n // ────────────────────────────────────────────────────────────────\n // Context provided to ore-step children\n // ────────────────────────────────────────────────────────────────\n\n const stepValues = computed(() => {\n void slots.elements().value;\n\n return getSteps().map((s) => s.getAttribute('value') ?? '');\n });\n\n provide(STEPPER_CTX, {\n clickable: computed(() => Boolean(props.clickable.value) && !props.disabled.value),\n color: props.color,\n currentValue,\n linear: computed(() => Boolean(props.linear.value)),\n orientation: computed(() => props.orientation.value ?? 'horizontal'),\n size: props.size,\n stepValues,\n });\n\n // Deferred to `onMounted()` (mirrors ore-tabs' `ensureSelection()` timing) rather than an\n // immediate `watch(stepValues, ...)`: `getSteps()` walks the *live* light DOM, and while the\n // browser is still parsing this element's `ore-step` children (synchronously upgrading each\n // one as its own tag is reached, which happens whenever `customElements.define()` already\n // ran before this markup was parsed: exactly what a sandboxed live-preview iframe does by\n // design), `stepValues` observes that child list mid-populate. Reading it eagerly here used\n // to call `ensureSelection()`, and therefore write `currentValue`: once per step as each\n // one was discovered, interleaved with that *same* step's own first render effect further\n // down the reactive graph. That reentrant write during a child's not-yet-finished initial\n // render corrupted its rendered output (the step's clickable/static control silently failed\n // to mount at all). Onmounted's callback runs on a microtask, strictly after the whole\n // synchronous parse (and thus every child) has completed, so `getSteps()` sees the final list.\n onMounted(() => {\n ensureSelection();\n return undefined;\n });\n\n // ────────────────────────────────────────────────────────────────\n // Keyboard Navigation (roving tabindex over navigable steps)\n // ────────────────────────────────────────────────────────────────\n\n const getNavigableSteps = (): HTMLElement[] => {\n const steps = getSteps();\n const values = steps.map((s) => s.getAttribute('value') ?? '');\n const currentIndex = values.indexOf(currentValue.value ?? '');\n const clickable = Boolean(props.clickable.value) && !props.disabled.value;\n const linear = Boolean(props.linear.value);\n\n return steps.filter((step, index) =>\n isStepNavigable({\n disabled: step.hasAttribute('disabled'),\n index,\n linear,\n stepperClickable: clickable,\n stepperCurrentIndex: currentIndex,\n }),\n );\n };\n\n const listControl = createListControl({\n direction: () => elementDirection(el),\n getItems: getNavigableSteps,\n loop: false,\n onNavigate: ({ item }) => {\n // Select BEFORE focusing: changing `currentValue` re-renders each step's\n // control (the step's navigable/button node-slot depends on the current\n // index), which destroys the previously focused button. Ripple flushes\n // effects synchronously, so by the time focusStep() runs the replacement\n // button exists.\n const value = item.getAttribute('value');\n\n if (value) setSelection(value, true);\n\n focusStep(item);\n },\n orientation: () => (props.orientation.value === 'vertical' ? 'vertical' : 'horizontal'),\n signal: lifecycleSignal(onCleanup),\n });\n\n const handleStepClick = (e: Event) => {\n const step = e\n .composedPath()\n .find((node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-step');\n\n if (!step || step.closest(STEPPER_TAG) !== el || !getNavigableSteps().includes(step)) return;\n\n const value = step.getAttribute('value');\n\n setSelection(value ?? undefined, true);\n // The click focused the step's old control; the selection re-render replaced\n // it: restore focus onto the new one (see onNavigate's ordering note).\n focusStep(step);\n };\n\n const activateFocusedStep = (): void => {\n const steps = getNavigableSteps();\n const focusedStep = steps.find(\n (step) => step === document.activeElement || step.shadowRoot?.activeElement === document.activeElement,\n );\n const value = focusedStep?.getAttribute('value');\n\n if (value) {\n setSelection(value, true);\n focusStep(focusedStep);\n }\n };\n\n const activationPress = createInteraction({ onPress: activateFocusedStep });\n\n const handleKeydown = (e: KeyboardEvent) => {\n const steps = getNavigableSteps();\n\n if (steps.length === 0) return;\n\n const path = e.composedPath();\n const stepFromEvent = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-step',\n );\n const focused = stepFromEvent ? steps.indexOf(stepFromEvent) : -1;\n\n if (focused >= 0) listControl.set(focused);\n\n if (listControl.handleKeydown(e)) return;\n\n activationPress.handleKeydown(e);\n };\n\n bind({\n on: {\n click: handleStepClick,\n keydown: handleKeydown,\n },\n });\n\n return html`\n <nav part=\"nav\" aria-label=\"${props.label}\">\n <ol class=\"steps\" role=\"list\" part=\"list\">\n <slot></slot>\n </ol>\n </nav>\n `;\n },\n styles: [componentStyles],\n});\n"],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  * Suppress flash of unstyled content (FOUC) for custom elements.
4
4
  *
5
5
  * :not(:defined) only matches custom elements that have not yet been
6
- * upgraded — standard HTML elements are always :defined, so this rule is
6
+ * upgraded: standard HTML elements are always :defined, so this rule is
7
7
  * safe globally. Once customElements.define() runs and the element
8
8
  * upgrades, :defined matches and this rule no longer applies.
9
9
  *
@@ -13,7 +13,7 @@
13
13
  * import '@vielzeug/refine/fouc.css';
14
14
  *
15
15
  * `visibility: hidden` is used instead of `display: none` to preserve
16
- * layout space — the element occupies its inline size while invisible,
16
+ * layout space: the element occupies its inline size while invisible,
17
17
  * reducing layout shift when the shadow DOM attaches.
18
18
  */
19
19
  :not(:defined) {
@@ -1 +1 @@
1
- {"version":3,"file":"accessibility.css.cjs","names":[],"sources":["../../../src/styles/mixins/accessibility.css.ts"],"sourcesContent":["import { css } from '@vielzeug/ore';\n\n/**\n * Visually-Hidden (\"sr-only\") Style\n *\n * Single source of truth for the standard visually-hidden-but-accessible\n * clipping technique — hides content visually while keeping it in the\n * accessibility tree (screen readers, `aria-live` regions).\n *\n * Two forms are exported from the same declarations so component stylesheets\n * and JS-created DOM elements never drift out of sync:\n * - `srOnlyMixin` — a `.sr-only` class for component `styles: [...]` arrays.\n * - `SR_ONLY_INLINE_STYLE` — the equivalent `cssText` string for elements\n * created outside any component's shadow root (e.g. a live region appended\n * directly to `document.body`).\n *\n * @example\n * ```ts\n * // Component stylesheet\n * import { srOnlyMixin } from '../../styles';\n * return { styles: [srOnlyMixin, componentStyles], template: html`<span class=\"sr-only\">...</span>` };\n *\n * // JS-created element outside a shadow root\n * import { SR_ONLY_INLINE_STYLE } from '../../styles';\n * el.style.cssText = SR_ONLY_INLINE_STYLE;\n * ```\n */\nexport const SR_ONLY_INLINE_STYLE =\n 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;' +\n 'white-space:nowrap;border-width:0;clip-path:inset(50%);';\n\nexport const srOnlyMixin = css`\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n white-space: nowrap;\n border-width: 0;\n clip-path: inset(50%);\n }\n`;\n\n/**\n * Coarse Pointer Mixin\n *\n * Under `@media (pointer: coarse)`, promotes the full component one size tier\n * so padding, gap, font-size, height, and icon-size all grow proportionally\n * with the WCAG 44 px touch target — not just the minimum height in isolation:\n *\n * - default / `size=\"md\"` → lg-scale tokens + `--_touch-target: var(--size-11)`\n * - `size=\"sm\"` → md-scale tokens + `--_touch-target: var(--size-11)`\n * - `size=\"lg\"` → touch target only (already at max scale)\n *\n * Interactive elements inside the component that need a guaranteed tap target\n * should still reference `--_touch-target`:\n *\n * ```css\n * .close { min-height: var(--_touch-target); min-width: var(--_touch-target); }\n * ```\n *\n * @example\n * ```ts\n * import { coarsePointerMixin } from '../../styles';\n *\n * return {\n * styles: [coarsePointerMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const coarsePointerMixin = css`\n @media (pointer: coarse) {\n /* Default / md size: promote all scale tokens one tier up (md → lg) */\n :host,\n :host([size='md']) {\n --_touch-target: var(--size-11);\n --_font-size: var(--text-base);\n --_gap: var(--size-2-5);\n --_height: var(--size-12);\n --_size: var(--size-6);\n --_icon-size: var(--size-6);\n --_padding: var(--size-2-5) var(--size-5);\n }\n\n /* sm size: promote to md scale */\n :host([size='sm']) {\n --_touch-target: var(--size-11);\n --_font-size: var(--text-sm);\n --_gap: var(--size-2);\n --_height: var(--size-10);\n --_size: var(--size-5);\n --_icon-size: var(--size-5);\n --_padding: var(--size-2) var(--size-4);\n }\n\n /* lg size: already max, just enforce touch target */\n :host([size='lg']) {\n --_touch-target: var(--size-11);\n }\n }\n`;\n\n/**\n * Reduced Motion Mixin\n *\n * Defines `--_motion-transition: none` and `--_motion-animation: none` on\n * `:host` under `@media (prefers-reduced-motion: reduce)`.\n * Component CSS opts in via CSS variable fallbacks:\n *\n * ```css\n * .panel { transition: var(--_motion-transition, opacity 300ms ease); }\n * .loader { animation: var(--_motion-animation, spin 0.6s linear infinite); }\n * ```\n *\n * @example\n * ```ts\n * import { reducedMotionMixin } from '../../styles';\n *\n * return {\n * styles: [reducedMotionMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const reducedMotionMixin = css`\n @media (prefers-reduced-motion: reduce) {\n :host {\n --_motion-transition: none;\n --_motion-animation: none;\n }\n }\n`;\n"],"mappings":"+BA2BA,IAAa,EACX,uIAGW,EAAc,EAAA,GAAG;;;;;;;;;;;;EA0CjB,EAAqB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDxB,EAAqB,EAAA,GAAG"}
1
+ {"version":3,"file":"accessibility.css.cjs","names":[],"sources":["../../../src/styles/mixins/accessibility.css.ts"],"sourcesContent":["import { css } from '@vielzeug/ore';\n\n/**\n * Visually-Hidden (\"sr-only\") Style\n *\n * Single source of truth for the standard visually-hidden-but-accessible\n * clipping technique: hides content visually while keeping it in the\n * accessibility tree (screen readers, `aria-live` regions).\n *\n * Two forms are exported from the same declarations so component stylesheets\n * and JS-created DOM elements never drift out of sync:\n * - `srOnlyMixin`: a `.sr-only` class for component `styles: [...]` arrays.\n * - `SR_ONLY_INLINE_STYLE`: the equivalent `cssText` string for elements\n * created outside any component's shadow root (e.g. a live region appended\n * directly to `document.body`).\n *\n * @example\n * ```ts\n * // Component stylesheet\n * import { srOnlyMixin } from '../../styles';\n * return { styles: [srOnlyMixin, componentStyles], template: html`<span class=\"sr-only\">...</span>` };\n *\n * // JS-created element outside a shadow root\n * import { SR_ONLY_INLINE_STYLE } from '../../styles';\n * el.style.cssText = SR_ONLY_INLINE_STYLE;\n * ```\n */\nexport const SR_ONLY_INLINE_STYLE =\n 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;' +\n 'white-space:nowrap;border-width:0;clip-path:inset(50%);';\n\nexport const srOnlyMixin = css`\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n white-space: nowrap;\n border-width: 0;\n clip-path: inset(50%);\n }\n`;\n\n/**\n * Coarse Pointer Mixin\n *\n * Under `@media (pointer: coarse)`, promotes the full component one size tier\n * so padding, gap, font-size, height, and icon-size all grow proportionally\n * with the WCAG 44 px touch target: not just the minimum height in isolation:\n *\n * - default / `size=\"md\"` → lg-scale tokens + `--_touch-target: var(--size-11)`\n * - `size=\"sm\"` → md-scale tokens + `--_touch-target: var(--size-11)`\n * - `size=\"lg\"` → touch target only (already at max scale)\n *\n * Interactive elements inside the component that need a guaranteed tap target\n * should still reference `--_touch-target`:\n *\n * ```css\n * .close { min-height: var(--_touch-target); min-width: var(--_touch-target); }\n * ```\n *\n * @example\n * ```ts\n * import { coarsePointerMixin } from '../../styles';\n *\n * return {\n * styles: [coarsePointerMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const coarsePointerMixin = css`\n @media (pointer: coarse) {\n /* Default / md size: promote all scale tokens one tier up (md → lg) */\n :host,\n :host([size='md']) {\n --_touch-target: var(--size-11);\n --_font-size: var(--text-base);\n --_gap: var(--size-2-5);\n --_height: var(--size-12);\n --_size: var(--size-6);\n --_icon-size: var(--size-6);\n --_padding: var(--size-2-5) var(--size-5);\n }\n\n /* sm size: promote to md scale */\n :host([size='sm']) {\n --_touch-target: var(--size-11);\n --_font-size: var(--text-sm);\n --_gap: var(--size-2);\n --_height: var(--size-10);\n --_size: var(--size-5);\n --_icon-size: var(--size-5);\n --_padding: var(--size-2) var(--size-4);\n }\n\n /* lg size: already max, just enforce touch target */\n :host([size='lg']) {\n --_touch-target: var(--size-11);\n }\n }\n`;\n\n/**\n * Reduced Motion Mixin\n *\n * Defines `--_motion-transition: none` and `--_motion-animation: none` on\n * `:host` under `@media (prefers-reduced-motion: reduce)`.\n * Component CSS opts in via CSS variable fallbacks:\n *\n * ```css\n * .panel { transition: var(--_motion-transition, opacity 300ms ease); }\n * .loader { animation: var(--_motion-animation, spin 0.6s linear infinite); }\n * ```\n *\n * @example\n * ```ts\n * import { reducedMotionMixin } from '../../styles';\n *\n * return {\n * styles: [reducedMotionMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const reducedMotionMixin = css`\n @media (prefers-reduced-motion: reduce) {\n :host {\n --_motion-transition: none;\n --_motion-animation: none;\n }\n }\n`;\n"],"mappings":"+BA2BA,IAAa,EACX,uIAGW,EAAc,EAAA,GAAG;;;;;;;;;;;;EA0CjB,EAAqB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDxB,EAAqB,EAAA,GAAG"}
@@ -2,13 +2,13 @@
2
2
  * Visually-Hidden ("sr-only") Style
3
3
  *
4
4
  * Single source of truth for the standard visually-hidden-but-accessible
5
- * clipping technique — hides content visually while keeping it in the
5
+ * clipping technique: hides content visually while keeping it in the
6
6
  * accessibility tree (screen readers, `aria-live` regions).
7
7
  *
8
8
  * Two forms are exported from the same declarations so component stylesheets
9
9
  * and JS-created DOM elements never drift out of sync:
10
- * - `srOnlyMixin` — a `.sr-only` class for component `styles: [...]` arrays.
11
- * - `SR_ONLY_INLINE_STYLE` — the equivalent `cssText` string for elements
10
+ * - `srOnlyMixin`: a `.sr-only` class for component `styles: [...]` arrays.
11
+ * - `SR_ONLY_INLINE_STYLE`: the equivalent `cssText` string for elements
12
12
  * created outside any component's shadow root (e.g. a live region appended
13
13
  * directly to `document.body`).
14
14
  *
@@ -30,7 +30,7 @@ export declare const srOnlyMixin: import("@vielzeug/ore").CSSResult;
30
30
  *
31
31
  * Under `@media (pointer: coarse)`, promotes the full component one size tier
32
32
  * so padding, gap, font-size, height, and icon-size all grow proportionally
33
- * with the WCAG 44 px touch target — not just the minimum height in isolation:
33
+ * with the WCAG 44 px touch target: not just the minimum height in isolation:
34
34
  *
35
35
  * - default / `size="md"` → lg-scale tokens + `--_touch-target: var(--size-11)`
36
36
  * - `size="sm"` → md-scale tokens + `--_touch-target: var(--size-11)`
@@ -1 +1 @@
1
- {"version":3,"file":"accessibility.css.js","names":[],"sources":["../../../src/styles/mixins/accessibility.css.ts"],"sourcesContent":["import { css } from '@vielzeug/ore';\n\n/**\n * Visually-Hidden (\"sr-only\") Style\n *\n * Single source of truth for the standard visually-hidden-but-accessible\n * clipping technique — hides content visually while keeping it in the\n * accessibility tree (screen readers, `aria-live` regions).\n *\n * Two forms are exported from the same declarations so component stylesheets\n * and JS-created DOM elements never drift out of sync:\n * - `srOnlyMixin` — a `.sr-only` class for component `styles: [...]` arrays.\n * - `SR_ONLY_INLINE_STYLE` — the equivalent `cssText` string for elements\n * created outside any component's shadow root (e.g. a live region appended\n * directly to `document.body`).\n *\n * @example\n * ```ts\n * // Component stylesheet\n * import { srOnlyMixin } from '../../styles';\n * return { styles: [srOnlyMixin, componentStyles], template: html`<span class=\"sr-only\">...</span>` };\n *\n * // JS-created element outside a shadow root\n * import { SR_ONLY_INLINE_STYLE } from '../../styles';\n * el.style.cssText = SR_ONLY_INLINE_STYLE;\n * ```\n */\nexport const SR_ONLY_INLINE_STYLE =\n 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;' +\n 'white-space:nowrap;border-width:0;clip-path:inset(50%);';\n\nexport const srOnlyMixin = css`\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n white-space: nowrap;\n border-width: 0;\n clip-path: inset(50%);\n }\n`;\n\n/**\n * Coarse Pointer Mixin\n *\n * Under `@media (pointer: coarse)`, promotes the full component one size tier\n * so padding, gap, font-size, height, and icon-size all grow proportionally\n * with the WCAG 44 px touch target — not just the minimum height in isolation:\n *\n * - default / `size=\"md\"` → lg-scale tokens + `--_touch-target: var(--size-11)`\n * - `size=\"sm\"` → md-scale tokens + `--_touch-target: var(--size-11)`\n * - `size=\"lg\"` → touch target only (already at max scale)\n *\n * Interactive elements inside the component that need a guaranteed tap target\n * should still reference `--_touch-target`:\n *\n * ```css\n * .close { min-height: var(--_touch-target); min-width: var(--_touch-target); }\n * ```\n *\n * @example\n * ```ts\n * import { coarsePointerMixin } from '../../styles';\n *\n * return {\n * styles: [coarsePointerMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const coarsePointerMixin = css`\n @media (pointer: coarse) {\n /* Default / md size: promote all scale tokens one tier up (md → lg) */\n :host,\n :host([size='md']) {\n --_touch-target: var(--size-11);\n --_font-size: var(--text-base);\n --_gap: var(--size-2-5);\n --_height: var(--size-12);\n --_size: var(--size-6);\n --_icon-size: var(--size-6);\n --_padding: var(--size-2-5) var(--size-5);\n }\n\n /* sm size: promote to md scale */\n :host([size='sm']) {\n --_touch-target: var(--size-11);\n --_font-size: var(--text-sm);\n --_gap: var(--size-2);\n --_height: var(--size-10);\n --_size: var(--size-5);\n --_icon-size: var(--size-5);\n --_padding: var(--size-2) var(--size-4);\n }\n\n /* lg size: already max, just enforce touch target */\n :host([size='lg']) {\n --_touch-target: var(--size-11);\n }\n }\n`;\n\n/**\n * Reduced Motion Mixin\n *\n * Defines `--_motion-transition: none` and `--_motion-animation: none` on\n * `:host` under `@media (prefers-reduced-motion: reduce)`.\n * Component CSS opts in via CSS variable fallbacks:\n *\n * ```css\n * .panel { transition: var(--_motion-transition, opacity 300ms ease); }\n * .loader { animation: var(--_motion-animation, spin 0.6s linear infinite); }\n * ```\n *\n * @example\n * ```ts\n * import { reducedMotionMixin } from '../../styles';\n *\n * return {\n * styles: [reducedMotionMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const reducedMotionMixin = css`\n @media (prefers-reduced-motion: reduce) {\n :host {\n --_motion-transition: none;\n --_motion-animation: none;\n }\n }\n`;\n"],"mappings":"oCA2BA,IAAa,EACX,uIAGW,EAAc,CAAG;;;;;;;;;;;;EA0CjB,EAAqB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDxB,EAAqB,CAAG"}
1
+ {"version":3,"file":"accessibility.css.js","names":[],"sources":["../../../src/styles/mixins/accessibility.css.ts"],"sourcesContent":["import { css } from '@vielzeug/ore';\n\n/**\n * Visually-Hidden (\"sr-only\") Style\n *\n * Single source of truth for the standard visually-hidden-but-accessible\n * clipping technique: hides content visually while keeping it in the\n * accessibility tree (screen readers, `aria-live` regions).\n *\n * Two forms are exported from the same declarations so component stylesheets\n * and JS-created DOM elements never drift out of sync:\n * - `srOnlyMixin`: a `.sr-only` class for component `styles: [...]` arrays.\n * - `SR_ONLY_INLINE_STYLE`: the equivalent `cssText` string for elements\n * created outside any component's shadow root (e.g. a live region appended\n * directly to `document.body`).\n *\n * @example\n * ```ts\n * // Component stylesheet\n * import { srOnlyMixin } from '../../styles';\n * return { styles: [srOnlyMixin, componentStyles], template: html`<span class=\"sr-only\">...</span>` };\n *\n * // JS-created element outside a shadow root\n * import { SR_ONLY_INLINE_STYLE } from '../../styles';\n * el.style.cssText = SR_ONLY_INLINE_STYLE;\n * ```\n */\nexport const SR_ONLY_INLINE_STYLE =\n 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;' +\n 'white-space:nowrap;border-width:0;clip-path:inset(50%);';\n\nexport const srOnlyMixin = css`\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n white-space: nowrap;\n border-width: 0;\n clip-path: inset(50%);\n }\n`;\n\n/**\n * Coarse Pointer Mixin\n *\n * Under `@media (pointer: coarse)`, promotes the full component one size tier\n * so padding, gap, font-size, height, and icon-size all grow proportionally\n * with the WCAG 44 px touch target: not just the minimum height in isolation:\n *\n * - default / `size=\"md\"` → lg-scale tokens + `--_touch-target: var(--size-11)`\n * - `size=\"sm\"` → md-scale tokens + `--_touch-target: var(--size-11)`\n * - `size=\"lg\"` → touch target only (already at max scale)\n *\n * Interactive elements inside the component that need a guaranteed tap target\n * should still reference `--_touch-target`:\n *\n * ```css\n * .close { min-height: var(--_touch-target); min-width: var(--_touch-target); }\n * ```\n *\n * @example\n * ```ts\n * import { coarsePointerMixin } from '../../styles';\n *\n * return {\n * styles: [coarsePointerMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const coarsePointerMixin = css`\n @media (pointer: coarse) {\n /* Default / md size: promote all scale tokens one tier up (md → lg) */\n :host,\n :host([size='md']) {\n --_touch-target: var(--size-11);\n --_font-size: var(--text-base);\n --_gap: var(--size-2-5);\n --_height: var(--size-12);\n --_size: var(--size-6);\n --_icon-size: var(--size-6);\n --_padding: var(--size-2-5) var(--size-5);\n }\n\n /* sm size: promote to md scale */\n :host([size='sm']) {\n --_touch-target: var(--size-11);\n --_font-size: var(--text-sm);\n --_gap: var(--size-2);\n --_height: var(--size-10);\n --_size: var(--size-5);\n --_icon-size: var(--size-5);\n --_padding: var(--size-2) var(--size-4);\n }\n\n /* lg size: already max, just enforce touch target */\n :host([size='lg']) {\n --_touch-target: var(--size-11);\n }\n }\n`;\n\n/**\n * Reduced Motion Mixin\n *\n * Defines `--_motion-transition: none` and `--_motion-animation: none` on\n * `:host` under `@media (prefers-reduced-motion: reduce)`.\n * Component CSS opts in via CSS variable fallbacks:\n *\n * ```css\n * .panel { transition: var(--_motion-transition, opacity 300ms ease); }\n * .loader { animation: var(--_motion-animation, spin 0.6s linear infinite); }\n * ```\n *\n * @example\n * ```ts\n * import { reducedMotionMixin } from '../../styles';\n *\n * return {\n * styles: [reducedMotionMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const reducedMotionMixin = css`\n @media (prefers-reduced-motion: reduce) {\n :host {\n --_motion-transition: none;\n --_motion-animation: none;\n }\n }\n`;\n"],"mappings":"oCA2BA,IAAa,EACX,uIAGW,EAAc,CAAG;;;;;;;;;;;;EA0CjB,EAAqB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDxB,EAAqB,CAAG"}
@@ -20,7 +20,7 @@ let e=require("@vielzeug/ore");var t=!1;function registerRainbowProperty(){if(!t
20
20
  /* Reserve no-clip space for glow */
21
21
  box-shadow: 0 0 calc(3 * var(--blur-xl)) rgba(0 0 0 / 0.001);
22
22
 
23
- /* Rainbow gradient — Okabe-Ito colorblind-safe palette */
23
+ /* Rainbow gradient: Okabe-Ito colorblind-safe palette */
24
24
  background: conic-gradient(
25
25
  from var(--rainbow-angle),
26
26
  #56b4e9,
@@ -83,7 +83,7 @@ let e=require("@vielzeug/ore");var t=!1;function registerRainbowProperty(){if(!t
83
83
  );
84
84
  }
85
85
 
86
- /* Shine border — single pseudo, glow via box-shadow (follows border-radius, no artifacts) */
86
+ /* Shine border: single pseudo, glow via box-shadow (follows border-radius, no artifacts) */
87
87
  :host([effect='shine']) ${t}::before {
88
88
  content: '';
89
89
  position: absolute;
@@ -1 +1 @@
1
- {"version":3,"file":"animation.css.cjs","names":[],"sources":["../../../src/styles/mixins/animation.css.ts"],"sourcesContent":["import { css } from '@vielzeug/ore';\n\n/**\n * Register the --rainbow-angle CSS custom property so browsers can\n * interpolate it inside conic-gradient().\n * Called automatically by rainbowEffectMixin on first use.\n */\nlet rainbowRegistered = false;\n\nexport function registerRainbowProperty() {\n if (rainbowRegistered) return;\n\n if (typeof CSS !== 'undefined' && CSS.registerProperty) {\n try {\n CSS.registerProperty({\n inherits: false,\n initialValue: '0deg',\n name: '--rainbow-angle',\n syntax: '<angle>',\n });\n } catch {\n // Already registered — safe to ignore\n }\n }\n\n rainbowRegistered = true;\n}\n\n/**\n * Register the --shine-angle CSS custom property so browsers can\n * interpolate it inside conic-gradient().\n * Called automatically by shineEffectMixin on first use.\n */\nlet shineRegistered = false;\n\nexport function registerShineProperty() {\n if (shineRegistered) return;\n\n if (typeof CSS !== 'undefined' && CSS.registerProperty) {\n try {\n CSS.registerProperty({\n inherits: false,\n initialValue: '0deg',\n name: '--shine-angle',\n syntax: '<angle>',\n });\n } catch {\n // Already registered — safe to ignore\n }\n }\n\n shineRegistered = true;\n}\n\n/**\n * Rainbow Border Effect Mixin\n *\n * Animated rainbow border with glow effect.\n * Perfect for highlighting call-to-action elements or special features.\n *\n * @param selector - CSS selector for the element carrying the border, matched\n * against the component's actual shadow DOM markup — a bare word like\n * 'button' is a TYPE selector (matches a literal `<button>` tag), not a\n * part/class selector. Use the selector that actually matches your root\n * element, e.g. `'.box'` for a `<div class=\"box\">`, or `'[part=\"button\"]'`\n * for a `<span part=\"button\">`/`<a part=\"button\">` (ore-button's actual\n * markup — it never renders a `<button>` tag).\n * @returns CSSResult with rainbow border animation\n *\n * @example\n * ```ts\n * import { rainbowEffectMixin } from '../../styles/effects/rainbow.css';\n *\n * return {\n * styles: [rainbowEffectMixin('[part=\"button\"]'), componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const rainbowEffectMixin = (selector: string) => {\n registerRainbowProperty();\n\n return css`\n /* ========================================\n Rainbow Border Effect\n ======================================== */\n\n :host([effect='rainbow']) ${selector} {\n position: relative;\n border: var(--border-2) solid transparent !important;\n overflow: visible;\n }\n\n /* Rainbow border and glow layers */\n :host([effect='rainbow']) ${selector}::before, :host([effect='rainbow']) ${selector}::after {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--border-2));\n border: inherit;\n border-radius: inherit;\n\n /* Reserve no-clip space for glow */\n box-shadow: 0 0 calc(3 * var(--blur-xl)) rgba(0 0 0 / 0.001);\n\n /* Rainbow gradient — Okabe-Ito colorblind-safe palette */\n background: conic-gradient(\n from var(--rainbow-angle),\n #56b4e9,\n /* Sky Blue */ #0072b2,\n /* Deep Blue */ #009e73,\n /* Bluish Green */ #f0e442,\n /* Yellow */ #e69f00,\n /* Orange */ #d55e00,\n /* Vermillion */ #cc79a7,\n /* Reddish Purple */ #56b4e9 /* Back to Sky Blue */\n )\n border-box;\n\n /* Make everything inside padding-box transparent\n by subtracting padding-box from no-clip box */\n -webkit-mask:\n conic-gradient(red 0 0) no-clip subtract,\n conic-gradient(red 0 0) padding-box;\n mask:\n conic-gradient(red 0 0) no-clip subtract,\n conic-gradient(red 0 0) padding-box;\n\n opacity: var(--rainbow-border-opacity, 0.7);\n pointer-events: none;\n animation: rainbow-rotate 4s linear infinite;\n }\n\n /* Turn one pseudo layer into glow halo */\n :host([effect='rainbow']) ${selector}::after {\n opacity: var(--rainbow-glow-opacity, 0.18);\n filter: blur(var(--blur-xl));\n }\n\n /* ========================================\n Animation\n ======================================== */\n\n @keyframes rainbow-rotate {\n to {\n --rainbow-angle: 1turn;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host([effect='rainbow']) ${selector}::before, :host([effect='rainbow']) ${selector}::after {\n animation: none;\n }\n }\n `;\n};\n\n/**\n * Shine Border Effect Mixin\n *\n * Animated color-aware border shine. A tight arc of the component's own\n * theme color rotates around the border, producing the glossy \"shimmer\"\n * look seen in modern card and button designs.\n *\n * Respects the `color` attribute via `--_theme-*` tokens — no extra\n * configuration needed. Falls back to the neutral theme when no color\n * is set.\n *\n * @param selector - CSS selector for the inner element, matched against the\n * component's actual shadow DOM markup — see rainbowEffectMixin's\n * `selector` doc above for why a bare word like 'button' is usually wrong.\n * @returns CSSResult with shine border animation\n *\n * @example\n * ```ts\n * styles: [shineEffectMixin('[part=\"button\"]'), componentStyles]\n * ```\n */\nexport const shineEffectMixin = (selector: string) => {\n registerShineProperty();\n\n return css`\n /* ========================================\n Shine Border Effect\n ======================================== */\n\n :host([effect='shine']) ${selector} {\n position: relative;\n overflow: visible;\n --_shine-color: light-dark(\n oklch(from var(--_theme-focus) 0.6 calc(c * 1.2) h),\n oklch(from var(--_theme-focus) 0.85 calc(c * 1.2) h)\n );\n }\n\n /* Shine border — single pseudo, glow via box-shadow (follows border-radius, no artifacts) */\n :host([effect='shine']) ${selector}::before {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--border-2));\n border: var(--border-2) solid transparent;\n border-radius: calc(var(--_radius, 0px) + var(--border-2));\n\n /* Two comet tails 180deg apart, same shape rotating together */\n background:\n conic-gradient(from var(--shine-angle), transparent 0%, transparent 75%, var(--_shine-color) 100%) border-box,\n conic-gradient(\n from calc(var(--shine-angle) + 180deg),\n transparent 0%,\n transparent 75%,\n var(--_shine-color) 100%\n )\n border-box;\n\n -webkit-mask:\n conic-gradient(red 0 0) no-clip subtract,\n conic-gradient(red 0 0) padding-box;\n mask:\n conic-gradient(red 0 0) no-clip subtract,\n conic-gradient(red 0 0) padding-box;\n\n pointer-events: none;\n animation: shine-rotate 2.5s linear infinite;\n }\n\n /* ========================================\n Animation\n ======================================== */\n\n @keyframes shine-rotate {\n to {\n --shine-angle: 1turn;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host([effect='shine']) ${selector}::before {\n animation: none;\n }\n }\n `;\n};\n"],"mappings":"+BAOA,IAAI,EAAoB,GAExB,SAAgB,yBAA0B,CACpC,MAEJ,IAAI,OAAO,IAAQ,KAAe,IAAI,iBACpC,GAAI,CACF,IAAI,iBAAiB,CACnB,SAAU,GACV,aAAc,OACd,KAAM,kBACN,OAAQ,SACV,CAAC,CACH,MAAQ,CAER,CAGF,EAAoB,EAHlB,CAIJ,CAOA,IAAI,EAAkB,GAEtB,SAAgB,uBAAwB,CAClC,MAEJ,IAAI,OAAO,IAAQ,KAAe,IAAI,iBACpC,GAAI,CACF,IAAI,iBAAiB,CACnB,SAAU,GACV,aAAc,OACd,KAAM,gBACN,OAAQ,SACV,CAAC,CACH,MAAQ,CAER,CAGF,EAAkB,EAHhB,CAIJ,CA2BA,IAAa,mBAAsB,IACjC,wBAAwB,EAEjB,EAAA,GAAG;;;;;gCAKoB,EAAS;;;;;;;gCAOT,EAAS,sCAAsC,EAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAuCxD,EAAS;;;;;;;;;;;;;;;;kCAgBP,EAAS,sCAAsC,EAAS;;;;KA4B7E,iBAAoB,IAC/B,sBAAsB,EAEf,EAAA,GAAG;;;;;8BAKkB,EAAS;;;;;;;;;;8BAUT,EAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAwCP,EAAS"}
1
+ {"version":3,"file":"animation.css.cjs","names":[],"sources":["../../../src/styles/mixins/animation.css.ts"],"sourcesContent":["import { css } from '@vielzeug/ore';\n\n/**\n * Register the --rainbow-angle CSS custom property so browsers can\n * interpolate it inside conic-gradient().\n * Called automatically by rainbowEffectMixin on first use.\n */\nlet rainbowRegistered = false;\n\nexport function registerRainbowProperty() {\n if (rainbowRegistered) return;\n\n if (typeof CSS !== 'undefined' && CSS.registerProperty) {\n try {\n CSS.registerProperty({\n inherits: false,\n initialValue: '0deg',\n name: '--rainbow-angle',\n syntax: '<angle>',\n });\n } catch {\n // Already registered: safe to ignore\n }\n }\n\n rainbowRegistered = true;\n}\n\n/**\n * Register the --shine-angle CSS custom property so browsers can\n * interpolate it inside conic-gradient().\n * Called automatically by shineEffectMixin on first use.\n */\nlet shineRegistered = false;\n\nexport function registerShineProperty() {\n if (shineRegistered) return;\n\n if (typeof CSS !== 'undefined' && CSS.registerProperty) {\n try {\n CSS.registerProperty({\n inherits: false,\n initialValue: '0deg',\n name: '--shine-angle',\n syntax: '<angle>',\n });\n } catch {\n // Already registered: safe to ignore\n }\n }\n\n shineRegistered = true;\n}\n\n/**\n * Rainbow Border Effect Mixin\n *\n * Animated rainbow border with glow effect.\n * Perfect for highlighting call-to-action elements or special features.\n *\n * @param selector - CSS selector for the element carrying the border, matched\n * against the component's actual shadow DOM markup: a bare word like\n * 'button' is a TYPE selector (matches a literal `<button>` tag), not a\n * part/class selector. Use the selector that actually matches your root\n * element, e.g. `'.box'` for a `<div class=\"box\">`, or `'[part=\"button\"]'`\n * for a `<span part=\"button\">`/`<a part=\"button\">` (ore-button's actual\n * markup: it never renders a `<button>` tag).\n * @returns CSSResult with rainbow border animation\n *\n * @example\n * ```ts\n * import { rainbowEffectMixin } from '../../styles/effects/rainbow.css';\n *\n * return {\n * styles: [rainbowEffectMixin('[part=\"button\"]'), componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const rainbowEffectMixin = (selector: string) => {\n registerRainbowProperty();\n\n return css`\n /* ========================================\n Rainbow Border Effect\n ======================================== */\n\n :host([effect='rainbow']) ${selector} {\n position: relative;\n border: var(--border-2) solid transparent !important;\n overflow: visible;\n }\n\n /* Rainbow border and glow layers */\n :host([effect='rainbow']) ${selector}::before, :host([effect='rainbow']) ${selector}::after {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--border-2));\n border: inherit;\n border-radius: inherit;\n\n /* Reserve no-clip space for glow */\n box-shadow: 0 0 calc(3 * var(--blur-xl)) rgba(0 0 0 / 0.001);\n\n /* Rainbow gradient: Okabe-Ito colorblind-safe palette */\n background: conic-gradient(\n from var(--rainbow-angle),\n #56b4e9,\n /* Sky Blue */ #0072b2,\n /* Deep Blue */ #009e73,\n /* Bluish Green */ #f0e442,\n /* Yellow */ #e69f00,\n /* Orange */ #d55e00,\n /* Vermillion */ #cc79a7,\n /* Reddish Purple */ #56b4e9 /* Back to Sky Blue */\n )\n border-box;\n\n /* Make everything inside padding-box transparent\n by subtracting padding-box from no-clip box */\n -webkit-mask:\n conic-gradient(red 0 0) no-clip subtract,\n conic-gradient(red 0 0) padding-box;\n mask:\n conic-gradient(red 0 0) no-clip subtract,\n conic-gradient(red 0 0) padding-box;\n\n opacity: var(--rainbow-border-opacity, 0.7);\n pointer-events: none;\n animation: rainbow-rotate 4s linear infinite;\n }\n\n /* Turn one pseudo layer into glow halo */\n :host([effect='rainbow']) ${selector}::after {\n opacity: var(--rainbow-glow-opacity, 0.18);\n filter: blur(var(--blur-xl));\n }\n\n /* ========================================\n Animation\n ======================================== */\n\n @keyframes rainbow-rotate {\n to {\n --rainbow-angle: 1turn;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host([effect='rainbow']) ${selector}::before, :host([effect='rainbow']) ${selector}::after {\n animation: none;\n }\n }\n `;\n};\n\n/**\n * Shine Border Effect Mixin\n *\n * Animated color-aware border shine. A tight arc of the component's own\n * theme color rotates around the border, producing the glossy \"shimmer\"\n * look seen in modern card and button designs.\n *\n * Respects the `color` attribute via `--_theme-*` tokens: no extra\n * configuration needed. Falls back to the neutral theme when no color\n * is set.\n *\n * @param selector - CSS selector for the inner element, matched against the\n * component's actual shadow DOM markup: see rainbowEffectMixin's\n * `selector` doc above for why a bare word like 'button' is usually wrong.\n * @returns CSSResult with shine border animation\n *\n * @example\n * ```ts\n * styles: [shineEffectMixin('[part=\"button\"]'), componentStyles]\n * ```\n */\nexport const shineEffectMixin = (selector: string) => {\n registerShineProperty();\n\n return css`\n /* ========================================\n Shine Border Effect\n ======================================== */\n\n :host([effect='shine']) ${selector} {\n position: relative;\n overflow: visible;\n --_shine-color: light-dark(\n oklch(from var(--_theme-focus) 0.6 calc(c * 1.2) h),\n oklch(from var(--_theme-focus) 0.85 calc(c * 1.2) h)\n );\n }\n\n /* Shine border: single pseudo, glow via box-shadow (follows border-radius, no artifacts) */\n :host([effect='shine']) ${selector}::before {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--border-2));\n border: var(--border-2) solid transparent;\n border-radius: calc(var(--_radius, 0px) + var(--border-2));\n\n /* Two comet tails 180deg apart, same shape rotating together */\n background:\n conic-gradient(from var(--shine-angle), transparent 0%, transparent 75%, var(--_shine-color) 100%) border-box,\n conic-gradient(\n from calc(var(--shine-angle) + 180deg),\n transparent 0%,\n transparent 75%,\n var(--_shine-color) 100%\n )\n border-box;\n\n -webkit-mask:\n conic-gradient(red 0 0) no-clip subtract,\n conic-gradient(red 0 0) padding-box;\n mask:\n conic-gradient(red 0 0) no-clip subtract,\n conic-gradient(red 0 0) padding-box;\n\n pointer-events: none;\n animation: shine-rotate 2.5s linear infinite;\n }\n\n /* ========================================\n Animation\n ======================================== */\n\n @keyframes shine-rotate {\n to {\n --shine-angle: 1turn;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host([effect='shine']) ${selector}::before {\n animation: none;\n }\n }\n `;\n};\n"],"mappings":"+BAOA,IAAI,EAAoB,GAExB,SAAgB,yBAA0B,CACpC,MAEJ,IAAI,OAAO,IAAQ,KAAe,IAAI,iBACpC,GAAI,CACF,IAAI,iBAAiB,CACnB,SAAU,GACV,aAAc,OACd,KAAM,kBACN,OAAQ,SACV,CAAC,CACH,MAAQ,CAER,CAGF,EAAoB,EAHlB,CAIJ,CAOA,IAAI,EAAkB,GAEtB,SAAgB,uBAAwB,CAClC,MAEJ,IAAI,OAAO,IAAQ,KAAe,IAAI,iBACpC,GAAI,CACF,IAAI,iBAAiB,CACnB,SAAU,GACV,aAAc,OACd,KAAM,gBACN,OAAQ,SACV,CAAC,CACH,MAAQ,CAER,CAGF,EAAkB,EAHhB,CAIJ,CA2BA,IAAa,mBAAsB,IACjC,wBAAwB,EAEjB,EAAA,GAAG;;;;;gCAKoB,EAAS;;;;;;;gCAOT,EAAS,sCAAsC,EAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAuCxD,EAAS;;;;;;;;;;;;;;;;kCAgBP,EAAS,sCAAsC,EAAS;;;;KA4B7E,iBAAoB,IAC/B,sBAAsB,EAEf,EAAA,GAAG;;;;;8BAKkB,EAAS;;;;;;;;;;8BAUT,EAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAwCP,EAAS"}
@@ -7,12 +7,12 @@ export declare function registerShineProperty(): void;
7
7
  * Perfect for highlighting call-to-action elements or special features.
8
8
  *
9
9
  * @param selector - CSS selector for the element carrying the border, matched
10
- * against the component's actual shadow DOM markup — a bare word like
10
+ * against the component's actual shadow DOM markup: a bare word like
11
11
  * 'button' is a TYPE selector (matches a literal `<button>` tag), not a
12
12
  * part/class selector. Use the selector that actually matches your root
13
13
  * element, e.g. `'.box'` for a `<div class="box">`, or `'[part="button"]'`
14
14
  * for a `<span part="button">`/`<a part="button">` (ore-button's actual
15
- * markup — it never renders a `<button>` tag).
15
+ * markup: it never renders a `<button>` tag).
16
16
  * @returns CSSResult with rainbow border animation
17
17
  *
18
18
  * @example
@@ -33,12 +33,12 @@ export declare const rainbowEffectMixin: (selector: string) => import("@vielzeug
33
33
  * theme color rotates around the border, producing the glossy "shimmer"
34
34
  * look seen in modern card and button designs.
35
35
  *
36
- * Respects the `color` attribute via `--_theme-*` tokens — no extra
36
+ * Respects the `color` attribute via `--_theme-*` tokens: no extra
37
37
  * configuration needed. Falls back to the neutral theme when no color
38
38
  * is set.
39
39
  *
40
40
  * @param selector - CSS selector for the inner element, matched against the
41
- * component's actual shadow DOM markup — see rainbowEffectMixin's
41
+ * component's actual shadow DOM markup: see rainbowEffectMixin's
42
42
  * `selector` doc above for why a bare word like 'button' is usually wrong.
43
43
  * @returns CSSResult with shine border animation
44
44
  *
@@ -20,7 +20,7 @@ import{css as e}from"@vielzeug/ore";var t=!1;function registerRainbowProperty(){
20
20
  /* Reserve no-clip space for glow */
21
21
  box-shadow: 0 0 calc(3 * var(--blur-xl)) rgba(0 0 0 / 0.001);
22
22
 
23
- /* Rainbow gradient — Okabe-Ito colorblind-safe palette */
23
+ /* Rainbow gradient: Okabe-Ito colorblind-safe palette */
24
24
  background: conic-gradient(
25
25
  from var(--rainbow-angle),
26
26
  #56b4e9,
@@ -83,7 +83,7 @@ import{css as e}from"@vielzeug/ore";var t=!1;function registerRainbowProperty(){
83
83
  );
84
84
  }
85
85
 
86
- /* Shine border — single pseudo, glow via box-shadow (follows border-radius, no artifacts) */
86
+ /* Shine border: single pseudo, glow via box-shadow (follows border-radius, no artifacts) */
87
87
  :host([effect='shine']) ${t}::before {
88
88
  content: '';
89
89
  position: absolute;