@vielzeug/refine 1.5.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/dist/accordion.cjs +1 -1
  2. package/dist/accordion.cjs.map +1 -1
  3. package/dist/accordion.js +30 -28
  4. package/dist/accordion.js.map +1 -1
  5. package/dist/async.cjs +11 -11
  6. package/dist/async.cjs.map +1 -1
  7. package/dist/async.js +1 -2
  8. package/dist/async.js.map +1 -1
  9. package/dist/button-group.cjs.map +1 -1
  10. package/dist/button-group.js.map +1 -1
  11. package/dist/button.cjs +1 -1
  12. package/dist/button.cjs.map +1 -1
  13. package/dist/button.js +1 -0
  14. package/dist/button.js.map +1 -1
  15. package/dist/calendar.cjs +26 -26
  16. package/dist/calendar.cjs.map +1 -1
  17. package/dist/calendar.js +4 -5
  18. package/dist/calendar.js.map +1 -1
  19. package/dist/checkbox-group.cjs +9 -9
  20. package/dist/checkbox-group.cjs.map +1 -1
  21. package/dist/checkbox-group.js +50 -58
  22. package/dist/checkbox-group.js.map +1 -1
  23. package/dist/code-window.cjs +4 -4
  24. package/dist/code-window.cjs.map +1 -1
  25. package/dist/code-window.js +1 -2
  26. package/dist/code-window.js.map +1 -1
  27. package/dist/combobox.cjs +29 -28
  28. package/dist/combobox.cjs.map +1 -1
  29. package/dist/combobox.js +201 -195
  30. package/dist/combobox.js.map +1 -1
  31. package/dist/command-palette.cjs +6 -6
  32. package/dist/command-palette.cjs.map +1 -1
  33. package/dist/command-palette.js +46 -47
  34. package/dist/command-palette.js.map +1 -1
  35. package/dist/content/card/card.css.cjs +1 -1
  36. package/dist/content/card/card.css.cjs.map +1 -1
  37. package/dist/content/card/card.css.js +1 -1
  38. package/dist/content/card/card.css.js.map +1 -1
  39. package/dist/content/chat-message/chat-message.css.cjs +1 -1
  40. package/dist/content/chat-message/chat-message.css.cjs.map +1 -1
  41. package/dist/content/chat-message/chat-message.css.js +1 -1
  42. package/dist/content/chat-message/chat-message.css.js.map +1 -1
  43. package/dist/content/code-window/code-window.d.ts.map +1 -1
  44. package/dist/content/icon/icon.d.ts.map +1 -1
  45. package/dist/content/index.d.ts +4 -0
  46. package/dist/content/index.d.ts.map +1 -1
  47. package/dist/content/list/_list-item-reveal.cjs +2 -0
  48. package/dist/content/list/_list-item-reveal.cjs.map +1 -0
  49. package/dist/content/list/_list-item-reveal.d.ts +25 -0
  50. package/dist/content/list/_list-item-reveal.d.ts.map +1 -0
  51. package/dist/content/list/_list-item-reveal.js +33 -0
  52. package/dist/content/list/_list-item-reveal.js.map +1 -0
  53. package/dist/content/list/list-item.css.cjs +2 -0
  54. package/dist/content/list/list-item.css.cjs.map +1 -0
  55. package/dist/content/list/list-item.css.js +6 -0
  56. package/dist/content/list/list-item.css.js.map +1 -0
  57. package/dist/content/list/list-item.d.ts +111 -0
  58. package/dist/content/list/list-item.d.ts.map +1 -0
  59. package/dist/content/list/list.css.cjs +2 -0
  60. package/dist/content/list/list.css.cjs.map +1 -0
  61. package/dist/content/list/list.css.js +6 -0
  62. package/dist/content/list/list.css.js.map +1 -0
  63. package/dist/content/list/list.d.ts +93 -0
  64. package/dist/content/list/list.d.ts.map +1 -0
  65. package/dist/custom-elements.json +5693 -5090
  66. package/dist/datagrid.cjs +2 -2
  67. package/dist/datagrid.js +206 -206
  68. package/dist/datagrid.js.map +1 -1
  69. package/dist/date-picker.cjs +2 -1
  70. package/dist/date-picker.cjs.map +1 -1
  71. package/dist/date-picker.js +2 -0
  72. package/dist/date-picker.js.map +1 -1
  73. package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -1
  74. package/dist/disclosure/tabs/tabs.d.ts.map +1 -1
  75. package/dist/drawer.cjs +1 -1
  76. package/dist/drawer.cjs.map +1 -1
  77. package/dist/drawer.js +47 -48
  78. package/dist/drawer.js.map +1 -1
  79. package/dist/feedback/async/async.d.ts.map +1 -1
  80. package/dist/feedback/progress/progress.d.ts.map +1 -1
  81. package/dist/file-input.cjs +108 -42
  82. package/dist/file-input.cjs.map +1 -1
  83. package/dist/file-input.js +215 -156
  84. package/dist/file-input.js.map +1 -1
  85. package/dist/headless/aria-reflection.cjs +2 -0
  86. package/dist/headless/aria-reflection.cjs.map +1 -0
  87. package/dist/headless/aria-reflection.d.ts +27 -0
  88. package/dist/headless/aria-reflection.d.ts.map +1 -0
  89. package/dist/headless/aria-reflection.js +18 -0
  90. package/dist/headless/aria-reflection.js.map +1 -0
  91. package/dist/headless/checkable.cjs +1 -1
  92. package/dist/headless/checkable.cjs.map +1 -1
  93. package/dist/headless/checkable.d.ts +2 -10
  94. package/dist/headless/checkable.d.ts.map +1 -1
  95. package/dist/headless/checkable.js +29 -29
  96. package/dist/headless/checkable.js.map +1 -1
  97. package/dist/headless/choice-field.cjs +1 -1
  98. package/dist/headless/choice-field.cjs.map +1 -1
  99. package/dist/headless/choice-field.d.ts +2 -7
  100. package/dist/headless/choice-field.d.ts.map +1 -1
  101. package/dist/headless/choice-field.js +37 -37
  102. package/dist/headless/choice-field.js.map +1 -1
  103. package/dist/headless/field-base.cjs +1 -1
  104. package/dist/headless/field-base.cjs.map +1 -1
  105. package/dist/headless/field-base.d.ts +17 -0
  106. package/dist/headless/field-base.d.ts.map +1 -1
  107. package/dist/headless/field-base.js +21 -6
  108. package/dist/headless/field-base.js.map +1 -1
  109. package/dist/headless/focus.cjs +1 -1
  110. package/dist/headless/focus.cjs.map +1 -1
  111. package/dist/headless/focus.d.ts +7 -0
  112. package/dist/headless/focus.d.ts.map +1 -1
  113. package/dist/headless/focus.js +6 -6
  114. package/dist/headless/focus.js.map +1 -1
  115. package/dist/headless/index.d.ts +4 -2
  116. package/dist/headless/index.d.ts.map +1 -1
  117. package/dist/headless/nav.cjs +1 -1
  118. package/dist/headless/nav.cjs.map +1 -1
  119. package/dist/headless/nav.d.ts +12 -0
  120. package/dist/headless/nav.d.ts.map +1 -1
  121. package/dist/headless/nav.js +68 -50
  122. package/dist/headless/nav.js.map +1 -1
  123. package/dist/headless/overlay.cjs +1 -1
  124. package/dist/headless/overlay.cjs.map +1 -1
  125. package/dist/headless/overlay.d.ts +2 -0
  126. package/dist/headless/overlay.d.ts.map +1 -1
  127. package/dist/headless/overlay.js +8 -5
  128. package/dist/headless/overlay.js.map +1 -1
  129. package/dist/headless/ref-callback.cjs +2 -0
  130. package/dist/headless/ref-callback.cjs.map +1 -0
  131. package/dist/headless/ref-callback.d.ts +26 -0
  132. package/dist/headless/ref-callback.d.ts.map +1 -0
  133. package/dist/headless/ref-callback.js +13 -0
  134. package/dist/headless/ref-callback.js.map +1 -0
  135. package/dist/headless/swipe.cjs +1 -1
  136. package/dist/headless/swipe.cjs.map +1 -1
  137. package/dist/headless/swipe.d.ts +2 -0
  138. package/dist/headless/swipe.d.ts.map +1 -1
  139. package/dist/headless/swipe.js +26 -21
  140. package/dist/headless/swipe.js.map +1 -1
  141. package/dist/headless.cjs +1 -1
  142. package/dist/headless.js +28 -26
  143. package/dist/icon.cjs +1 -1
  144. package/dist/icon.cjs.map +1 -1
  145. package/dist/icon.js +35 -38
  146. package/dist/icon.js.map +1 -1
  147. package/dist/index.cjs +1 -1
  148. package/dist/index.js +63 -61
  149. package/dist/input.cjs +29 -26
  150. package/dist/input.cjs.map +1 -1
  151. package/dist/input.js +91 -79
  152. package/dist/input.js.map +1 -1
  153. package/dist/inputs/button/button.css.cjs +1 -1
  154. package/dist/inputs/button/button.css.cjs.map +1 -1
  155. package/dist/inputs/button/button.css.js +1 -1
  156. package/dist/inputs/button/button.css.js.map +1 -1
  157. package/dist/inputs/button/button.d.ts +8 -0
  158. package/dist/inputs/button/button.d.ts.map +1 -1
  159. package/dist/inputs/calendar/calendar.d.ts.map +1 -1
  160. package/dist/inputs/checkbox/checkbox.css.cjs +1 -1
  161. package/dist/inputs/checkbox/checkbox.css.cjs.map +1 -1
  162. package/dist/inputs/checkbox/checkbox.css.js +1 -1
  163. package/dist/inputs/checkbox/checkbox.css.js.map +1 -1
  164. package/dist/inputs/combobox/combobox.d.ts +1 -0
  165. package/dist/inputs/combobox/combobox.d.ts.map +1 -1
  166. package/dist/inputs/date-picker/date-picker.css.cjs +1 -1
  167. package/dist/inputs/date-picker/date-picker.css.cjs.map +1 -1
  168. package/dist/inputs/date-picker/date-picker.css.js +1 -1
  169. package/dist/inputs/date-picker/date-picker.css.js.map +1 -1
  170. package/dist/inputs/date-picker/date-picker.d.ts +6 -0
  171. package/dist/inputs/date-picker/date-picker.d.ts.map +1 -1
  172. package/dist/inputs/file-input/file-input-upload.cjs +2 -0
  173. package/dist/inputs/file-input/file-input-upload.cjs.map +1 -0
  174. package/dist/inputs/file-input/file-input-upload.d.ts +76 -0
  175. package/dist/inputs/file-input/file-input-upload.d.ts.map +1 -0
  176. package/dist/inputs/file-input/file-input-upload.js +145 -0
  177. package/dist/inputs/file-input/file-input-upload.js.map +1 -0
  178. package/dist/inputs/file-input/file-input.css.cjs +1 -1
  179. package/dist/inputs/file-input/file-input.css.cjs.map +1 -1
  180. package/dist/inputs/file-input/file-input.css.js +1 -1
  181. package/dist/inputs/file-input/file-input.css.js.map +1 -1
  182. package/dist/inputs/file-input/file-input.d.ts +54 -1
  183. package/dist/inputs/file-input/file-input.d.ts.map +1 -1
  184. package/dist/inputs/input/input.css.cjs +1 -1
  185. package/dist/inputs/input/input.css.cjs.map +1 -1
  186. package/dist/inputs/input/input.css.js +1 -1
  187. package/dist/inputs/input/input.css.js.map +1 -1
  188. package/dist/inputs/input/input.d.ts +13 -0
  189. package/dist/inputs/input/input.d.ts.map +1 -1
  190. package/dist/inputs/message-composer/message-composer.css.cjs +1 -1
  191. package/dist/inputs/message-composer/message-composer.css.cjs.map +1 -1
  192. package/dist/inputs/message-composer/message-composer.css.js +1 -1
  193. package/dist/inputs/message-composer/message-composer.css.js.map +1 -1
  194. package/dist/inputs/message-composer/message-composer.d.ts +7 -0
  195. package/dist/inputs/message-composer/message-composer.d.ts.map +1 -1
  196. package/dist/inputs/number-input/number-input.css.cjs +1 -1
  197. package/dist/inputs/number-input/number-input.css.cjs.map +1 -1
  198. package/dist/inputs/number-input/number-input.css.js +1 -1
  199. package/dist/inputs/number-input/number-input.css.js.map +1 -1
  200. package/dist/inputs/number-input/number-input.d.ts +15 -0
  201. package/dist/inputs/number-input/number-input.d.ts.map +1 -1
  202. package/dist/inputs/otp-input/otp-input.css.cjs +1 -1
  203. package/dist/inputs/otp-input/otp-input.css.cjs.map +1 -1
  204. package/dist/inputs/otp-input/otp-input.css.js +1 -1
  205. package/dist/inputs/otp-input/otp-input.css.js.map +1 -1
  206. package/dist/inputs/radio/radio.d.ts.map +1 -1
  207. package/dist/inputs/select/select.d.ts +1 -0
  208. package/dist/inputs/select/select.d.ts.map +1 -1
  209. package/dist/inputs/shared/index.d.ts +1 -1
  210. package/dist/inputs/shared/index.d.ts.map +1 -1
  211. package/dist/inputs/shared/templates.cjs +26 -3
  212. package/dist/inputs/shared/templates.cjs.map +1 -1
  213. package/dist/inputs/shared/templates.d.ts +20 -0
  214. package/dist/inputs/shared/templates.d.ts.map +1 -1
  215. package/dist/inputs/shared/templates.js +29 -5
  216. package/dist/inputs/shared/templates.js.map +1 -1
  217. package/dist/inputs/switch/switch.css.cjs +1 -1
  218. package/dist/inputs/switch/switch.css.cjs.map +1 -1
  219. package/dist/inputs/switch/switch.css.js +1 -1
  220. package/dist/inputs/switch/switch.css.js.map +1 -1
  221. package/dist/inputs/switch/switch.d.ts.map +1 -1
  222. package/dist/inputs/textarea/textarea.css.cjs +1 -1
  223. package/dist/inputs/textarea/textarea.css.cjs.map +1 -1
  224. package/dist/inputs/textarea/textarea.css.js +1 -1
  225. package/dist/inputs/textarea/textarea.css.js.map +1 -1
  226. package/dist/inputs/textarea/textarea.d.ts +14 -0
  227. package/dist/inputs/textarea/textarea.d.ts.map +1 -1
  228. package/dist/inputs/time-picker/time-picker.css.cjs +1 -1
  229. package/dist/inputs/time-picker/time-picker.css.cjs.map +1 -1
  230. package/dist/inputs/time-picker/time-picker.css.js +1 -1
  231. package/dist/inputs/time-picker/time-picker.css.js.map +1 -1
  232. package/dist/inputs/time-picker/time-picker.d.ts +6 -0
  233. package/dist/inputs/time-picker/time-picker.d.ts.map +1 -1
  234. package/dist/list-item.cjs +22 -0
  235. package/dist/list-item.cjs.map +1 -0
  236. package/dist/list-item.js +91 -0
  237. package/dist/list-item.js.map +1 -0
  238. package/dist/list.cjs +2 -0
  239. package/dist/list.cjs.map +1 -0
  240. package/dist/list.js +64 -0
  241. package/dist/list.js.map +1 -0
  242. package/dist/menu.cjs +4 -4
  243. package/dist/menu.cjs.map +1 -1
  244. package/dist/menu.js +60 -59
  245. package/dist/menu.js.map +1 -1
  246. package/dist/message-composer.cjs +14 -20
  247. package/dist/message-composer.cjs.map +1 -1
  248. package/dist/message-composer.js +63 -64
  249. package/dist/message-composer.js.map +1 -1
  250. package/dist/number-input.cjs +5 -3
  251. package/dist/number-input.cjs.map +1 -1
  252. package/dist/number-input.js +8 -4
  253. package/dist/number-input.js.map +1 -1
  254. package/dist/otp-input.cjs +9 -9
  255. package/dist/otp-input.cjs.map +1 -1
  256. package/dist/otp-input.js +70 -62
  257. package/dist/otp-input.js.map +1 -1
  258. package/dist/overlay/menu/menu-item.css.cjs +1 -1
  259. package/dist/overlay/menu/menu-item.css.cjs.map +1 -1
  260. package/dist/overlay/menu/menu-item.css.js +1 -1
  261. package/dist/overlay/menu/menu-item.css.js.map +1 -1
  262. package/dist/overlay/menu/menu-separator.css.cjs +1 -1
  263. package/dist/overlay/menu/menu-separator.css.cjs.map +1 -1
  264. package/dist/overlay/menu/menu-separator.css.js +1 -1
  265. package/dist/overlay/menu/menu-separator.css.js.map +1 -1
  266. package/dist/overlay/menu/menu.css.cjs +1 -1
  267. package/dist/overlay/menu/menu.css.cjs.map +1 -1
  268. package/dist/overlay/menu/menu.css.js +1 -1
  269. package/dist/overlay/menu/menu.css.js.map +1 -1
  270. package/dist/overlay/shared/use-dialog.cjs +1 -1
  271. package/dist/overlay/shared/use-dialog.cjs.map +1 -1
  272. package/dist/overlay/shared/use-dialog.d.ts.map +1 -1
  273. package/dist/overlay/shared/use-dialog.js +7 -6
  274. package/dist/overlay/shared/use-dialog.js.map +1 -1
  275. package/dist/progress.cjs +13 -13
  276. package/dist/progress.cjs.map +1 -1
  277. package/dist/progress.js +3 -4
  278. package/dist/progress.js.map +1 -1
  279. package/dist/radio-group.cjs +11 -11
  280. package/dist/radio-group.cjs.map +1 -1
  281. package/dist/radio-group.js +63 -70
  282. package/dist/radio-group.js.map +1 -1
  283. package/dist/radio.cjs +4 -4
  284. package/dist/radio.cjs.map +1 -1
  285. package/dist/radio.js +58 -58
  286. package/dist/radio.js.map +1 -1
  287. package/dist/rating.cjs.map +1 -1
  288. package/dist/rating.js.map +1 -1
  289. package/dist/refine.cjs +502 -309
  290. package/dist/refine.cjs.map +1 -1
  291. package/dist/refine.iife.js +562 -369
  292. package/dist/refine.iife.js.map +1 -1
  293. package/dist/refine.js +558 -365
  294. package/dist/refine.js.map +1 -1
  295. package/dist/select.cjs +21 -21
  296. package/dist/select.cjs.map +1 -1
  297. package/dist/select.js +135 -127
  298. package/dist/select.js.map +1 -1
  299. package/dist/shared/size-presets.cjs +1 -1
  300. package/dist/shared/size-presets.cjs.map +1 -1
  301. package/dist/shared/size-presets.d.ts +74 -0
  302. package/dist/shared/size-presets.d.ts.map +1 -1
  303. package/dist/shared/size-presets.js +48 -1
  304. package/dist/shared/size-presets.js.map +1 -1
  305. package/dist/shared/types.d.ts +5 -0
  306. package/dist/shared/types.d.ts.map +1 -1
  307. package/dist/styles/index.cjs +1 -1
  308. package/dist/styles/index.cjs.map +1 -1
  309. package/dist/styles/index.d.ts +1 -0
  310. package/dist/styles/index.d.ts.map +1 -1
  311. package/dist/styles/index.js +5 -4
  312. package/dist/styles/index.js.map +1 -1
  313. package/dist/styles/mixins/field-variants.css.cjs +85 -0
  314. package/dist/styles/mixins/field-variants.css.cjs.map +1 -0
  315. package/dist/styles/mixins/field-variants.css.d.ts +66 -0
  316. package/dist/styles/mixins/field-variants.css.d.ts.map +1 -0
  317. package/dist/styles/mixins/field-variants.css.js +90 -0
  318. package/dist/styles/mixins/field-variants.css.js.map +1 -0
  319. package/dist/switch.cjs +3 -3
  320. package/dist/switch.cjs.map +1 -1
  321. package/dist/switch.js +38 -36
  322. package/dist/switch.js.map +1 -1
  323. package/dist/tab-item.cjs +8 -8
  324. package/dist/tab-item.cjs.map +1 -1
  325. package/dist/tab-item.js +38 -28
  326. package/dist/tab-item.js.map +1 -1
  327. package/dist/tab-panel.cjs +7 -7
  328. package/dist/tab-panel.cjs.map +1 -1
  329. package/dist/tab-panel.js +33 -26
  330. package/dist/tab-panel.js.map +1 -1
  331. package/dist/tabs.cjs +4 -4
  332. package/dist/tabs.cjs.map +1 -1
  333. package/dist/tabs.js +64 -60
  334. package/dist/tabs.js.map +1 -1
  335. package/dist/testing/index.d.ts +15 -60
  336. package/dist/testing/index.d.ts.map +1 -1
  337. package/dist/testing.cjs +1 -1
  338. package/dist/testing.cjs.map +1 -1
  339. package/dist/testing.js +7 -24
  340. package/dist/testing.js.map +1 -1
  341. package/dist/textarea.cjs +15 -18
  342. package/dist/textarea.cjs.map +1 -1
  343. package/dist/textarea.js +83 -74
  344. package/dist/textarea.js.map +1 -1
  345. package/dist/time-picker.cjs +34 -31
  346. package/dist/time-picker.cjs.map +1 -1
  347. package/dist/time-picker.js +121 -109
  348. package/dist/time-picker.js.map +1 -1
  349. package/package.json +22 -9
  350. package/dist/headless/dialog-focus.cjs +0 -2
  351. package/dist/headless/dialog-focus.cjs.map +0 -1
  352. package/dist/headless/dialog-focus.d.ts +0 -40
  353. package/dist/headless/dialog-focus.d.ts.map +0 -1
  354. package/dist/headless/dialog-focus.js +0 -22
  355. package/dist/headless/dialog-focus.js.map +0 -1
  356. package/dist/headless/focus-trap.cjs +0 -2
  357. package/dist/headless/focus-trap.cjs.map +0 -1
  358. package/dist/headless/focus-trap.d.ts +0 -45
  359. package/dist/headless/focus-trap.d.ts.map +0 -1
  360. package/dist/headless/focus-trap.js +0 -51
  361. package/dist/headless/focus-trap.js.map +0 -1
  362. package/dist/keymap/dist/_dev.cjs +0 -2
  363. package/dist/keymap/dist/_dev.cjs.map +0 -1
  364. package/dist/keymap/dist/_dev.js +0 -4
  365. package/dist/keymap/dist/_dev.js.map +0 -1
  366. package/dist/keymap/dist/format.cjs +0 -1
  367. package/dist/keymap/dist/format.js +0 -1
  368. package/dist/keymap/dist/index.cjs +0 -1
  369. package/dist/keymap/dist/index.js +0 -4
  370. package/dist/keymap/dist/keymap.cjs +0 -2
  371. package/dist/keymap/dist/keymap.cjs.map +0 -1
  372. package/dist/keymap/dist/keymap.js +0 -221
  373. package/dist/keymap/dist/keymap.js.map +0 -1
  374. package/dist/keymap/dist/layer.cjs +0 -1
  375. package/dist/keymap/dist/layer.js +0 -1
package/dist/radio.js CHANGED
@@ -7,128 +7,128 @@ import { CONTROL_SIZE_PRESET as c } from "./shared/size-presets.js";
7
7
  import { lifecycleSignal as l } from "./headless/ore.js";
8
8
  import { createCheckable as u } from "./headless/checkable.js";
9
9
  import { createListControl as d } from "./headless/nav.js";
10
- import { FORM_CTX as f, useFormContext as p } from "./inputs/shared/form-context.js";
11
- import { renderHelperRegion as m } from "./inputs/shared/templates.js";
12
- import { RADIO_GROUP_CTX as h } from "./radio-group.js";
13
- import g from "./inputs/radio/radio.css.js";
14
- import { bind as _, define as v, getHost as y, html as b, inject as x, onCleanup as S, prop as C, useEmit as w } from "@vielzeug/ore";
15
- import { computed as T } from "@vielzeug/ripple";
16
- import { useField as E } from "@vielzeug/ore/forms";
10
+ import { elementDirection as f } from "./headless/direction.js";
11
+ import { FORM_CTX as p, useFormContext as m } from "./inputs/shared/form-context.js";
12
+ import { renderHelperRegion as h } from "./inputs/shared/templates.js";
13
+ import { RADIO_GROUP_CTX as g } from "./radio-group.js";
14
+ import _ from "./inputs/radio/radio.css.js";
15
+ import { bind as v, define as y, getHost as b, html as x, inject as S, onCleanup as C, prop as w, useEmit as T } from "@vielzeug/ore";
16
+ import { computed as E } from "@vielzeug/ripple";
17
+ import { useField as D } from "@vielzeug/ore/forms";
17
18
  //#region src/inputs/radio/radio.ts
18
- var D = "ore-radio";
19
- v(D, {
19
+ var O = "ore-radio";
20
+ y(O, {
20
21
  formAssociated: !0,
21
22
  props: {
22
23
  ...s,
23
24
  ...o,
24
25
  ...a,
25
- checked: C.bool(!1),
26
- error: C.string(),
27
- helper: C.string(),
28
- name: C.string(),
29
- value: C.string()
26
+ checked: w.bool(!1),
27
+ error: w.string(),
28
+ helper: w.string(),
29
+ name: w.string(),
30
+ value: w.string()
30
31
  },
31
32
  setup(e) {
32
- let t = y(), n = w(), r = x(h), i = x(f), a = p(e, i), o = T(() => r?.name.value || e.name.value || ""), s = T(() => r?.size.value ?? a.size.value), c = T(() => r?.color.value ?? e.color.value), g = T(() => r ? r.value.value === e.value.value : !!e.checked.value), v = () => {
33
+ let t = b(), n = T(), r = S(g), i = S(p), a = m(e, i), o = E(() => r?.name.value || e.name.value || ""), s = E(() => r?.size.value ?? a.size.value), c = E(() => r?.color.value ?? e.color.value), _ = E(() => r ? r.value.value === e.value.value : !!e.checked.value), y = () => {
33
34
  let e = o.value;
34
35
  return e ? Array.from(document.querySelectorAll(`ore-radio[name="${e}"]`)).filter((e) => !e.hasAttribute("disabled")) : [];
35
- }, C = (e, t) => {
36
+ }, w = (e, t) => {
36
37
  if (r) {
37
38
  r.select(e.getAttribute("value") ?? "", t);
38
39
  return;
39
40
  }
40
41
  e.click();
41
- }, D = d({
42
- getItems: () => v(),
43
- keys: {
44
- next: ["ArrowDown", "ArrowRight"],
45
- prev: ["ArrowUp", "ArrowLeft"]
46
- },
42
+ }, O = d({
43
+ direction: () => f(t),
44
+ getItems: () => y(),
47
45
  loop: !0,
48
46
  onNavigate: (e, t, n) => {
49
- let r = v()[t];
50
- r && (r.focus(), C(r, n));
51
- }
52
- }), O = (t) => {
53
- if (!k.checked.value) {
47
+ let r = y()[t];
48
+ r && (r.focus(), w(r, n));
49
+ },
50
+ orientation: "both",
51
+ signal: l(C)
52
+ }), k = (t) => {
53
+ if (!A.checked.value) {
54
54
  if (r) {
55
55
  r.select(e.value.value ?? "", t);
56
56
  return;
57
57
  }
58
- k.toggle(t ?? new Event("change"));
58
+ A.toggle(t ?? new Event("change"));
59
59
  }
60
- }, k = u({
61
- checked: g,
62
- disabled: T(() => a.disabled.value || !!r?.disabled.value),
60
+ }, A = u({
61
+ checked: _,
62
+ disabled: E(() => a.disabled.value || !!r?.disabled.value),
63
63
  error: e.error,
64
64
  helper: e.helper,
65
65
  onToggle: (e) => {
66
66
  n("change", e);
67
67
  },
68
68
  prefix: "radio",
69
- signal: l(S),
69
+ signal: l(C),
70
70
  validateOn: i?.validateOn,
71
71
  value: e.value
72
72
  });
73
- k.attachFormField(E({
74
- disabled: k.disabled,
73
+ A.attachFormField(D({
74
+ disabled: A.disabled,
75
75
  toFormValue: (e) => e,
76
- value: k.checkableFormValue
76
+ value: A.checkableFormValue
77
77
  }));
78
- let { assistiveId: A, checked: j, disabled: M, errorText: N, helperText: P, labelId: F, toggle: I } = k;
79
- return _({
78
+ let { assistiveId: j, checked: M, disabled: N, errorText: P, helperText: F, labelId: I, toggle: L } = A;
79
+ return v({
80
80
  attr: {
81
- ariaChecked: () => j.value ? "true" : "false",
82
- ariaDescribedby: () => N.value || P.value ? A : null,
83
- ariaDisabled: () => M.value ? "true" : null,
84
- ariaInvalid: () => N.value ? "true" : null,
85
- ariaLabelledby: F,
86
- checked: j,
81
+ ariaChecked: () => M.value ? "true" : "false",
82
+ ariaDescribedby: () => P.value || F.value ? j : null,
83
+ ariaDisabled: () => N.value ? "true" : null,
84
+ ariaInvalid: () => P.value ? "true" : null,
85
+ ariaLabelledby: I,
86
+ checked: M,
87
87
  color: c,
88
- disabled: () => M.value ? !0 : void 0,
88
+ disabled: () => N.value ? !0 : void 0,
89
89
  name: () => o.value || void 0,
90
90
  role: "radio",
91
91
  size: s,
92
92
  tabindex: () => {
93
- if (!M.value) return j.value ? 0 : -1;
93
+ if (!N.value) return M.value ? 0 : -1;
94
94
  }
95
95
  },
96
96
  class: () => ({
97
- "is-checked": j.value,
98
- "is-disabled": M.value
97
+ "is-checked": M.value,
98
+ "is-disabled": N.value
99
99
  }),
100
100
  on: {
101
101
  click: (n) => {
102
- if (!M.value) if (r) r.select(e.value.value ?? "", n);
102
+ if (!N.value) if (r) r.select(e.value.value ?? "", n);
103
103
  else {
104
104
  if (!o.value) return;
105
- if (!j.value) {
105
+ if (!M.value) {
106
106
  let r = e.name.value;
107
107
  document.querySelectorAll(`ore-radio[name="${r}"]`).forEach((e) => {
108
108
  e !== t && e.removeAttribute("checked");
109
- }), I(n);
109
+ }), L(n);
110
110
  }
111
111
  }
112
112
  },
113
113
  keydown: (e) => {
114
114
  if (e.key === " " || e.key === "Enter") {
115
- e.preventDefault(), O(e);
115
+ e.preventDefault(), k(e);
116
116
  return;
117
117
  }
118
- let n = v();
118
+ let n = y();
119
119
  if (n.length === 0) return;
120
120
  let r = n.indexOf(t);
121
- r !== -1 && (D.set(r), D.handleKeydown(e));
121
+ r !== -1 && (O.set(r), O.handleKeydown(e));
122
122
  }
123
123
  }
124
- }), b`
124
+ }), x`
125
125
  <div class="radio-wrapper" part="radio">
126
126
  <div class="circle" part="circle">
127
127
  <div class="dot" part="dot"></div>
128
128
  </div>
129
129
  </div>
130
- <span class="label" part="label" id="${F}"><slot></slot></span>
131
- ${m(A, N, P)}
130
+ <span class="label" part="label" id="${I}"><slot></slot></span>
131
+ ${h(j, P, F)}
132
132
  `;
133
133
  },
134
134
  styles: [
@@ -137,10 +137,10 @@ v(D, {
137
137
  n,
138
138
  e,
139
139
  t(c),
140
- g
140
+ _
141
141
  ]
142
142
  });
143
143
  //#endregion
144
- export { D as RADIO_TAG };
144
+ export { O as RADIO_TAG };
145
145
 
146
146
  //# sourceMappingURL=radio.js.map
package/dist/radio.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"radio.js","names":[],"sources":["../src/inputs/radio/radio.ts"],"sourcesContent":["import { define, html, inject, prop, bind, getHost, onCleanup, useEmit } from '@vielzeug/ore';\nimport { useField } from '@vielzeug/ore/forms';\nimport { computed } from '@vielzeug/ripple';\n\nimport type { CheckableProps, ComponentSize, ThemeColor } from '../../types';\n\nimport { type CheckableChangePayload, lifecycleSignal, createCheckable, createListControl } from '../../headless';\nimport { CONTROL_SIZE_PRESET, disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport {\n coarsePointerMixin,\n colorThemeMixin,\n disabledStateMixin,\n forcedColorsFormControlMixin,\n sizeVariantMixin,\n} from '../../styles';\nimport { RADIO_GROUP_CTX } from '../radio-group/radio-group';\nimport { FORM_CTX, useFormContext } from '../shared/form-context';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './radio.css?inline';\n\n/** Radio component properties */\n\nexport type OreRadioEvents = {\n change: CheckableChangePayload;\n};\n\nexport type OreRadioProps = CheckableProps & {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message (marks field as invalid) */\n error?: string;\n /** Helper text displayed below the radio */\n helper?: string;\n /** Component size */\n size?: ComponentSize;\n};\n\n/**\n * A customizable radio button component for mutually exclusive selections.\n *\n * @element ore-radio\n *\n * @attr {boolean} checked - Checked state\n * @attr {boolean} disabled - Disable radio interaction\n * @attr {string} value - Field value (required for radio groups)\n * @attr {string} name - Form field name (required for radio groups)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Radio size: 'sm' | 'md' | 'lg'\n * @attr {string} error - Error message (marks field as invalid)\n * @attr {string} helper - Helper text displayed below the radio\n *\n * @fires change - Emitted when radio is selected. detail: { checked: boolean, value: string, originalEvent?: Event }\n *\n * @slot - Radio button label text\n *\n * @cssprop --radio-size - Control size (width and height)\n * @cssprop --radio-bg - Unchecked background color\n * @cssprop --radio-border-color - Unchecked border color\n * @cssprop --radio-checked-bg - Selected indicator background color\n * @cssprop --radio-color - Selected indicator dot color\n * @cssprop --radio-font-size - Label font size\n * @part radio - The radio wrapper element\n * @part circle - The visual radio circle\n * @part label - The label element\n * @part helper-text - The helper/error text element\n *\n * @example\n * ```html\n * <ore-radio name=\"plan\" value=\"free\">Free</ore-radio>\n * <ore-radio name=\"plan\" value=\"pro\" checked color=\"primary\">Pro</ore-radio>\n * <ore-radio name=\"plan\" value=\"enterprise\" disabled>Enterprise</ore-radio>\n * ```\n */\nexport const RADIO_TAG = 'ore-radio' as const;\ndefine<OreRadioProps>(RADIO_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n checked: prop.bool(false),\n error: prop.string(),\n helper: prop.string(),\n name: prop.string(),\n value: prop.string(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreRadioEvents>();\n\n const groupCtx = inject(RADIO_GROUP_CTX);\n const formCtx = inject(FORM_CTX);\n const fCtxProps = useFormContext(props, formCtx);\n\n const effectiveName = computed(() => groupCtx?.name.value || props.name.value || '');\n const effectiveSize = computed(() => groupCtx?.size.value ?? fCtxProps.size.value);\n const effectiveColor = computed(() => groupCtx?.color.value ?? props.color.value);\n const checkedFromState = computed(() => {\n if (groupCtx) return groupCtx.value.value === props.value.value;\n\n return Boolean(props.checked.value);\n });\n\n const getRadioGroup = (): HTMLElement[] => {\n const radioName = effectiveName.value;\n\n if (!radioName) return [];\n\n return Array.from(document.querySelectorAll<HTMLElement>(`ore-radio[name=\"${radioName}\"]`)).filter(\n (r) => !r.hasAttribute('disabled'),\n );\n };\n\n const selectRadio = (radio: HTMLElement, originalEvent?: Event): void => {\n if (groupCtx) {\n groupCtx.select(radio.getAttribute('value') ?? '', originalEvent);\n\n return;\n }\n\n radio.click();\n };\n\n const listControl = createListControl({\n getItems: () => getRadioGroup(),\n keys: { next: ['ArrowDown', 'ArrowRight'], prev: ['ArrowUp', 'ArrowLeft'] },\n loop: true,\n onNavigate: (_action, index, event) => {\n const nextRadio = getRadioGroup()[index];\n\n if (!nextRadio) return;\n\n nextRadio.focus();\n selectRadio(nextRadio, event);\n },\n });\n\n const activateSelf = (originalEvent?: Event): void => {\n if (checkable.checked.value) return;\n\n if (groupCtx) {\n groupCtx.select(props.value.value ?? '', originalEvent);\n\n return;\n }\n\n checkable.toggle(originalEvent ?? new Event('change'));\n };\n\n const checkable = createCheckable({\n checked: checkedFromState,\n disabled: computed(() => fCtxProps.disabled.value || Boolean(groupCtx?.disabled.value)),\n error: props.error,\n helper: props.helper,\n onToggle: (payload) => {\n emit('change', payload);\n },\n prefix: 'radio',\n signal: lifecycleSignal(onCleanup),\n validateOn: formCtx?.validateOn,\n value: props.value,\n });\n\n checkable.attachFormField(\n useField<string | null>({\n disabled: checkable.disabled,\n toFormValue: (v) => v,\n value: checkable.checkableFormValue,\n }),\n );\n\n const { assistiveId, checked, disabled, errorText, helperText, labelId, toggle } = checkable;\n\n bind({\n attr: {\n ariaChecked: () => (checked.value ? 'true' : 'false'),\n ariaDescribedby: () => (errorText.value || helperText.value ? assistiveId : null),\n ariaDisabled: () => (disabled.value ? 'true' : null),\n ariaInvalid: () => (errorText.value ? 'true' : null),\n ariaLabelledby: labelId,\n checked,\n color: effectiveColor,\n disabled: () => (disabled.value ? true : undefined),\n name: () => effectiveName.value || undefined,\n role: 'radio',\n size: effectiveSize,\n tabindex: () => {\n if (disabled.value) return undefined;\n\n return checked.value ? 0 : -1;\n },\n },\n class: () => ({\n 'is-checked': checked.value,\n 'is-disabled': disabled.value,\n }),\n on: {\n click: (e: MouseEvent) => {\n if (disabled.value) return;\n\n if (groupCtx) {\n groupCtx.select(props.value.value ?? '', e);\n } else {\n if (!effectiveName.value) return;\n\n if (!checked.value) {\n const radioName = props.name.value;\n const allRadios = document.querySelectorAll<HTMLElement>(`ore-radio[name=\"${radioName}\"]`);\n\n allRadios.forEach((radio) => {\n if (radio !== el) radio.removeAttribute('checked');\n });\n\n toggle(e);\n }\n }\n },\n keydown: (e: KeyboardEvent) => {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n activateSelf(e);\n\n return;\n }\n\n const radios = getRadioGroup();\n\n if (radios.length === 0) return;\n\n const selfIndex = radios.indexOf(el);\n\n if (selfIndex === -1) return;\n\n listControl.set(selfIndex);\n listControl.handleKeydown(e);\n },\n },\n });\n\n return html`\n <div class=\"radio-wrapper\" part=\"radio\">\n <div class=\"circle\" part=\"circle\">\n <div class=\"dot\" part=\"dot\"></div>\n </div>\n </div>\n <span class=\"label\" part=\"label\" id=\"${labelId}\"><slot></slot></span>\n ${renderHelperRegion(assistiveId, errorText, helperText)}\n `;\n },\n styles: [\n colorThemeMixin,\n forcedColorsFormControlMixin,\n disabledStateMixin,\n coarsePointerMixin,\n sizeVariantMixin(CONTROL_SIZE_PRESET),\n componentStyles,\n ],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"radio.js","names":[],"sources":["../src/inputs/radio/radio.ts"],"sourcesContent":["import { define, html, inject, prop, bind, getHost, onCleanup, useEmit } from '@vielzeug/ore';\nimport { useField } from '@vielzeug/ore/forms';\nimport { computed } from '@vielzeug/ripple';\n\nimport type { CheckableProps, ComponentSize, ThemeColor } from '../../types';\n\nimport {\n type CheckableChangePayload,\n elementDirection,\n lifecycleSignal,\n createCheckable,\n createListControl,\n} from '../../headless';\nimport { CONTROL_SIZE_PRESET, disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport {\n coarsePointerMixin,\n colorThemeMixin,\n disabledStateMixin,\n forcedColorsFormControlMixin,\n sizeVariantMixin,\n} from '../../styles';\nimport { RADIO_GROUP_CTX } from '../radio-group/radio-group';\nimport { FORM_CTX, useFormContext } from '../shared/form-context';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './radio.css?inline';\n\n/** Radio component properties */\n\nexport type OreRadioEvents = {\n change: CheckableChangePayload;\n};\n\nexport type OreRadioProps = CheckableProps & {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message (marks field as invalid) */\n error?: string;\n /** Helper text displayed below the radio */\n helper?: string;\n /** Component size */\n size?: ComponentSize;\n};\n\n/**\n * A customizable radio button component for mutually exclusive selections.\n *\n * @element ore-radio\n *\n * @attr {boolean} checked - Checked state\n * @attr {boolean} disabled - Disable radio interaction\n * @attr {string} value - Field value (required for radio groups)\n * @attr {string} name - Form field name (required for radio groups)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Radio size: 'sm' | 'md' | 'lg'\n * @attr {string} error - Error message (marks field as invalid)\n * @attr {string} helper - Helper text displayed below the radio\n *\n * @fires change - Emitted when radio is selected. detail: { checked: boolean, value: string, originalEvent?: Event }\n *\n * @slot - Radio button label text\n *\n * @cssprop --radio-size - Control size (width and height)\n * @cssprop --radio-bg - Unchecked background color\n * @cssprop --radio-border-color - Unchecked border color\n * @cssprop --radio-checked-bg - Selected indicator background color\n * @cssprop --radio-color - Selected indicator dot color\n * @cssprop --radio-font-size - Label font size\n * @part radio - The radio wrapper element\n * @part circle - The visual radio circle\n * @part label - The label element\n * @part helper-text - The helper/error text element\n *\n * @example\n * ```html\n * <ore-radio name=\"plan\" value=\"free\">Free</ore-radio>\n * <ore-radio name=\"plan\" value=\"pro\" checked color=\"primary\">Pro</ore-radio>\n * <ore-radio name=\"plan\" value=\"enterprise\" disabled>Enterprise</ore-radio>\n * ```\n */\nexport const RADIO_TAG = 'ore-radio' as const;\ndefine<OreRadioProps>(RADIO_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n checked: prop.bool(false),\n error: prop.string(),\n helper: prop.string(),\n name: prop.string(),\n value: prop.string(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreRadioEvents>();\n\n const groupCtx = inject(RADIO_GROUP_CTX);\n const formCtx = inject(FORM_CTX);\n const fCtxProps = useFormContext(props, formCtx);\n\n const effectiveName = computed(() => groupCtx?.name.value || props.name.value || '');\n const effectiveSize = computed(() => groupCtx?.size.value ?? fCtxProps.size.value);\n const effectiveColor = computed(() => groupCtx?.color.value ?? props.color.value);\n const checkedFromState = computed(() => {\n if (groupCtx) return groupCtx.value.value === props.value.value;\n\n return Boolean(props.checked.value);\n });\n\n const getRadioGroup = (): HTMLElement[] => {\n const radioName = effectiveName.value;\n\n if (!radioName) return [];\n\n return Array.from(document.querySelectorAll<HTMLElement>(`ore-radio[name=\"${radioName}\"]`)).filter(\n (r) => !r.hasAttribute('disabled'),\n );\n };\n\n const selectRadio = (radio: HTMLElement, originalEvent?: Event): void => {\n if (groupCtx) {\n groupCtx.select(radio.getAttribute('value') ?? '', originalEvent);\n\n return;\n }\n\n radio.click();\n };\n\n const listControl = createListControl({\n direction: () => elementDirection(el),\n getItems: () => getRadioGroup(),\n // 'both' accepts every arrow key regardless of the group's visual layout (radio groups\n // may render horizontally or vertically via CSS) — RTL mirroring of Left/Right still\n // applies via `direction` since nav.ts's default keymap covers 'both' too.\n loop: true,\n onNavigate: (_action, index, event) => {\n const nextRadio = getRadioGroup()[index];\n\n if (!nextRadio) return;\n\n nextRadio.focus();\n selectRadio(nextRadio, event);\n },\n orientation: 'both',\n signal: lifecycleSignal(onCleanup),\n });\n\n const activateSelf = (originalEvent?: Event): void => {\n if (checkable.checked.value) return;\n\n if (groupCtx) {\n groupCtx.select(props.value.value ?? '', originalEvent);\n\n return;\n }\n\n checkable.toggle(originalEvent ?? new Event('change'));\n };\n\n const checkable = createCheckable({\n checked: checkedFromState,\n disabled: computed(() => fCtxProps.disabled.value || Boolean(groupCtx?.disabled.value)),\n error: props.error,\n helper: props.helper,\n onToggle: (payload) => {\n emit('change', payload);\n },\n prefix: 'radio',\n signal: lifecycleSignal(onCleanup),\n validateOn: formCtx?.validateOn,\n value: props.value,\n });\n\n checkable.attachFormField(\n useField<string | null>({\n disabled: checkable.disabled,\n toFormValue: (v) => v,\n value: checkable.checkableFormValue,\n }),\n );\n\n const { assistiveId, checked, disabled, errorText, helperText, labelId, toggle } = checkable;\n\n bind({\n attr: {\n ariaChecked: () => (checked.value ? 'true' : 'false'),\n ariaDescribedby: () => (errorText.value || helperText.value ? assistiveId : null),\n ariaDisabled: () => (disabled.value ? 'true' : null),\n ariaInvalid: () => (errorText.value ? 'true' : null),\n ariaLabelledby: labelId,\n checked,\n color: effectiveColor,\n disabled: () => (disabled.value ? true : undefined),\n name: () => effectiveName.value || undefined,\n role: 'radio',\n size: effectiveSize,\n tabindex: () => {\n if (disabled.value) return undefined;\n\n return checked.value ? 0 : -1;\n },\n },\n class: () => ({\n 'is-checked': checked.value,\n 'is-disabled': disabled.value,\n }),\n on: {\n click: (e: MouseEvent) => {\n if (disabled.value) return;\n\n if (groupCtx) {\n groupCtx.select(props.value.value ?? '', e);\n } else {\n if (!effectiveName.value) return;\n\n if (!checked.value) {\n const radioName = props.name.value;\n const allRadios = document.querySelectorAll<HTMLElement>(`ore-radio[name=\"${radioName}\"]`);\n\n allRadios.forEach((radio) => {\n if (radio !== el) radio.removeAttribute('checked');\n });\n\n toggle(e);\n }\n }\n },\n keydown: (e: KeyboardEvent) => {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n activateSelf(e);\n\n return;\n }\n\n const radios = getRadioGroup();\n\n if (radios.length === 0) return;\n\n const selfIndex = radios.indexOf(el);\n\n if (selfIndex === -1) return;\n\n listControl.set(selfIndex);\n listControl.handleKeydown(e);\n },\n },\n });\n\n return html`\n <div class=\"radio-wrapper\" part=\"radio\">\n <div class=\"circle\" part=\"circle\">\n <div class=\"dot\" part=\"dot\"></div>\n </div>\n </div>\n <span class=\"label\" part=\"label\" id=\"${labelId}\"><slot></slot></span>\n ${renderHelperRegion(assistiveId, errorText, helperText)}\n `;\n },\n styles: [\n colorThemeMixin,\n forcedColorsFormControlMixin,\n disabledStateMixin,\n coarsePointerMixin,\n sizeVariantMixin(CONTROL_SIZE_PRESET),\n componentStyles,\n ],\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"rating.cjs","names":[],"sources":["../src/inputs/rating/rating.ts"],"sourcesContent":["import { createStableId, define, html, inject, prop, bind, getHost, useEmit } from '@vielzeug/ore';\nimport { useField } from '@vielzeug/ore/forms';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { createErrorHelperState, createSliderControl } from '../../headless';\nimport '../../content/icon/icon';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport { FORM_CTX, useFormContext } from '../shared/form-context';\nimport { renderHelperRegion } from '../shared/templates';\nimport styles from './rating.css?inline';\n\nexport type OreRatingEvents = {\n change: { originalEvent?: Event; value: number };\n};\n\n/** Rating props */\nexport type OreRatingProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message — marks the field as invalid (fallback when the `error` slot is empty) */\n error?: string;\n /** Helper text displayed below the stars (fallback when the `helper` slot is empty) */\n helper?: string;\n /** Accessible group label */\n label?: string;\n /** Maximum rating (number of stars) */\n max?: number;\n /** Form field name */\n name?: string;\n /** Make rating read-only */\n readonly?: boolean;\n /** Component size */\n size?: ComponentSize;\n /** Render selected stars as solid-filled instead of outline-only */\n solid?: boolean;\n /** Current rating value */\n value?: number;\n};\n\n/**\n * A star rating input.\n *\n * @element ore-rating\n *\n * @attr {number} value - Current rating value (default: 0)\n * @attr {number} max - Maximum number of stars (default: 5)\n * @attr {boolean} readonly - Read-only display mode\n * @attr {boolean} disabled - Disabled state\n * @attr {string} label - aria-label for the group (default: 'Rating')\n * @attr {string} color - Theme color for filled stars: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} name - Form field name\n * @attr {boolean} solid - Fill selected stars (outline remains default when omitted)\n * @attr {string} helper - Helper text below the stars\n * @attr {string} error - Error message below the stars\n *\n * @fires change - Emitted when value changes. detail: { value: number, originalEvent?: Event }\n *\n * @cssprop --rating-star-size - Star diameter\n * @cssprop --rating-color-empty - Empty star color\n * @cssprop --rating-color-filled - Filled star color\n * @cssprop --rating-gap - Gap between stars\n *\n * @part stars - Stars container.\n * @part star - Star item element.\n * @part helper-text - The helper/error text element.\n * @example\n * ```html\n * <ore-rating value=\"3\" max=\"5\" color=\"warning\"></ore-rating>\n * <ore-rating value=\"4\" solid></ore-rating>\n * ```\n */\nexport const RATING_TAG = 'ore-rating' as const;\ndefine<OreRatingProps>(RATING_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string('Rating'),\n max: prop.number(5),\n name: prop.string(),\n readonly: prop.bool(false),\n solid: prop.bool(false),\n value: prop.number(0),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreRatingEvents>();\n\n const formCtx = inject(FORM_CTX);\n const fCtxProps = useFormContext(props, formCtx);\n\n const normalizedValue = computed(() => {\n const max = Math.max(1, Number(props.max!.value) || 5);\n const raw = Number(props.value!.value);\n const safe = Number.isFinite(raw) ? raw : 0;\n\n return Math.min(max, Math.max(0, safe));\n });\n\n const fd = useField({\n disabled: fCtxProps.disabled,\n value: computed(() => String(normalizedValue.value || 0)),\n });\n\n const triggerValidation = (on: 'blur' | 'change') => {\n if (formCtx?.validateOn?.value === on) {\n fd.reportValidity();\n }\n };\n\n const assistiveId = createStableId('helper');\n const assistive = createErrorHelperState({ error: props.error, helper: props.helper });\n const errorText = computed(() => assistive.value.errorText);\n const helperText = computed(() => assistive.value.helperText);\n const ariaDescribedBy = computed(() => (errorText.value || helperText.value ? assistiveId : null));\n\n const isInteractive = computed(() => !props.readonly!.value && !fCtxProps.disabled.value);\n const hovered = signal<number | null>(null);\n const displayValue = computed(() => hovered.value ?? normalizedValue.value);\n const getStarButtons = () => {\n return [...(el.shadowRoot?.querySelectorAll<HTMLButtonElement>('[data-star]') ?? [])];\n };\n const ratingControl = createSliderControl({\n max: computed(() => Number(props.max!.value) || 5),\n min: signal(1),\n step: signal(1),\n });\n\n function spawnSparkles(star: number) {\n const layer = el.shadowRoot?.querySelector<HTMLElement>('.sparkle-layer');\n const btn = el.shadowRoot?.querySelector<HTMLElement>(`[data-star=\"${star}\"]`);\n\n if (!layer || !btn) return;\n\n const cx = btn.offsetLeft + btn.offsetWidth / 2;\n const cy = btn.offsetTop + btn.offsetHeight / 2;\n const count = 10;\n\n for (let i = 0; i < count; i++) {\n const p = document.createElement('span');\n const angle = (360 / count) * i + (Math.random() * 30 - 15);\n const dist = 18 + Math.random() * 20;\n const size = 3 + Math.random() * 4;\n const dur = 380 + Math.random() * 220;\n\n p.className = 'sparkle';\n p.style.cssText = [\n `left:${cx}px`,\n `top:${cy}px`,\n `--_angle:${angle}deg`,\n `--_dist:${dist}px`,\n `width:${size}px`,\n `height:${size}px`,\n `--_dur:${dur}ms`,\n `animation-delay:${Math.random() * 60}ms`,\n ].join(';');\n layer.appendChild(p);\n p.addEventListener('animationend', () => p.remove(), { once: true });\n }\n }\n function select(star: number, originalEvent?: Event) {\n if (!isInteractive.value) return;\n\n const max = Math.max(1, Number(props.max!.value) || 5);\n const nextValue = Math.min(max, Math.max(0, star));\n\n if (nextValue === normalizedValue.value) return;\n\n // Write through the host attribute; ore handles host reflection.\n el.setAttribute('value', String(nextValue));\n emit('change', { originalEvent, value: nextValue });\n triggerValidation('change');\n spawnSparkles(nextValue);\n }\n function handleKeydown(e: KeyboardEvent, star: number) {\n const next = ratingControl.nextFromKey(e.key, star);\n\n if (next == null) return;\n\n e.preventDefault();\n select(next, e);\n\n const buttons = getStarButtons();\n\n buttons[next - 1]?.focus();\n }\n\n const stars = computed(() => {\n const max = Number(props.max!.value) || 5;\n\n return Array.from({ length: max }, (_, i) => i + 1);\n });\n\n bind({ attr: { size: fCtxProps.size } });\n\n return html`\n <div\n class=\"stars\"\n part=\"stars\"\n role=\"radiogroup\"\n :aria-label=\"${props.label}\"\n :aria-describedby=\"${ariaDescribedBy}\">\n ${() =>\n stars.value.map(\n (star) =>\n html`<button\n class=\"star-btn\"\n part=\"star\"\n type=\"button\"\n role=\"radio\"\n :aria-label=\"${() => `${star} ${star === 1 ? 'star' : 'stars'}`}\"\n :aria-checked=\"${() => String(star === normalizedValue.value)}\"\n :data-star=\"${star}\"\n ?data-filled=\"${() => star <= displayValue.value}\"\n :disabled=\"${() => (!isInteractive.value ? true : null)}\"\n @click=\"${(e: Event) => select(star, e)}\"\n @pointerenter=\"${() => {\n if (isInteractive.value) hovered.value = star;\n }}\"\n @pointerleave=\"${() => {\n hovered.value = null;\n }}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, star)}\">\n <ore-icon name=\"star\" size=\"var(--_star-size)\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n </button>`,\n )}\n <div class=\"sparkle-layer\"></div>\n </div>\n ${renderHelperRegion(assistiveId, errorText, helperText)}\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, reducedMotionMixin, styles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"rating.cjs","names":[],"sources":["../src/inputs/rating/rating.ts"],"sourcesContent":["import { createStableId, define, html, inject, prop, bind, getHost, useEmit } from '@vielzeug/ore';\nimport { useField } from '@vielzeug/ore/forms';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { createErrorHelperState, createSliderControl } from '../../headless';\nimport '../../content/icon/icon';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport { FORM_CTX, useFormContext } from '../shared/form-context';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './rating.css?inline';\n\nexport type OreRatingEvents = {\n change: { originalEvent?: Event; value: number };\n};\n\n/** Rating props */\nexport type OreRatingProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message — marks the field as invalid (fallback when the `error` slot is empty) */\n error?: string;\n /** Helper text displayed below the stars (fallback when the `helper` slot is empty) */\n helper?: string;\n /** Accessible group label */\n label?: string;\n /** Maximum rating (number of stars) */\n max?: number;\n /** Form field name */\n name?: string;\n /** Make rating read-only */\n readonly?: boolean;\n /** Component size */\n size?: ComponentSize;\n /** Render selected stars as solid-filled instead of outline-only */\n solid?: boolean;\n /** Current rating value */\n value?: number;\n};\n\n/**\n * A star rating input.\n *\n * @element ore-rating\n *\n * @attr {number} value - Current rating value (default: 0)\n * @attr {number} max - Maximum number of stars (default: 5)\n * @attr {boolean} readonly - Read-only display mode\n * @attr {boolean} disabled - Disabled state\n * @attr {string} label - aria-label for the group (default: 'Rating')\n * @attr {string} color - Theme color for filled stars: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} name - Form field name\n * @attr {boolean} solid - Fill selected stars (outline remains default when omitted)\n * @attr {string} helper - Helper text below the stars\n * @attr {string} error - Error message below the stars\n *\n * @fires change - Emitted when value changes. detail: { value: number, originalEvent?: Event }\n *\n * @cssprop --rating-star-size - Star diameter\n * @cssprop --rating-color-empty - Empty star color\n * @cssprop --rating-color-filled - Filled star color\n * @cssprop --rating-gap - Gap between stars\n *\n * @part stars - Stars container.\n * @part star - Star item element.\n * @part helper-text - The helper/error text element.\n * @example\n * ```html\n * <ore-rating value=\"3\" max=\"5\" color=\"warning\"></ore-rating>\n * <ore-rating value=\"4\" solid></ore-rating>\n * ```\n */\nexport const RATING_TAG = 'ore-rating' as const;\ndefine<OreRatingProps>(RATING_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string('Rating'),\n max: prop.number(5),\n name: prop.string(),\n readonly: prop.bool(false),\n solid: prop.bool(false),\n value: prop.number(0),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreRatingEvents>();\n\n const formCtx = inject(FORM_CTX);\n const fCtxProps = useFormContext(props, formCtx);\n\n const normalizedValue = computed(() => {\n const max = Math.max(1, Number(props.max!.value) || 5);\n const raw = Number(props.value!.value);\n const safe = Number.isFinite(raw) ? raw : 0;\n\n return Math.min(max, Math.max(0, safe));\n });\n\n const fd = useField({\n disabled: fCtxProps.disabled,\n value: computed(() => String(normalizedValue.value || 0)),\n });\n\n const triggerValidation = (on: 'blur' | 'change') => {\n if (formCtx?.validateOn?.value === on) {\n fd.reportValidity();\n }\n };\n\n const assistiveId = createStableId('helper');\n const assistive = createErrorHelperState({ error: props.error, helper: props.helper });\n const errorText = computed(() => assistive.value.errorText);\n const helperText = computed(() => assistive.value.helperText);\n const ariaDescribedBy = computed(() => (errorText.value || helperText.value ? assistiveId : null));\n\n const isInteractive = computed(() => !props.readonly!.value && !fCtxProps.disabled.value);\n const hovered = signal<number | null>(null);\n const displayValue = computed(() => hovered.value ?? normalizedValue.value);\n const getStarButtons = () => {\n return [...(el.shadowRoot?.querySelectorAll<HTMLButtonElement>('[data-star]') ?? [])];\n };\n const ratingControl = createSliderControl({\n max: computed(() => Number(props.max!.value) || 5),\n min: signal(1),\n step: signal(1),\n });\n\n function spawnSparkles(star: number) {\n const layer = el.shadowRoot?.querySelector<HTMLElement>('.sparkle-layer');\n const btn = el.shadowRoot?.querySelector<HTMLElement>(`[data-star=\"${star}\"]`);\n\n if (!layer || !btn) return;\n\n const cx = btn.offsetLeft + btn.offsetWidth / 2;\n const cy = btn.offsetTop + btn.offsetHeight / 2;\n const count = 10;\n\n for (let i = 0; i < count; i++) {\n const p = document.createElement('span');\n const angle = (360 / count) * i + (Math.random() * 30 - 15);\n const dist = 18 + Math.random() * 20;\n const size = 3 + Math.random() * 4;\n const dur = 380 + Math.random() * 220;\n\n p.className = 'sparkle';\n p.style.cssText = [\n `left:${cx}px`,\n `top:${cy}px`,\n `--_angle:${angle}deg`,\n `--_dist:${dist}px`,\n `width:${size}px`,\n `height:${size}px`,\n `--_dur:${dur}ms`,\n `animation-delay:${Math.random() * 60}ms`,\n ].join(';');\n layer.appendChild(p);\n p.addEventListener('animationend', () => p.remove(), { once: true });\n }\n }\n function select(star: number, originalEvent?: Event) {\n if (!isInteractive.value) return;\n\n const max = Math.max(1, Number(props.max!.value) || 5);\n const nextValue = Math.min(max, Math.max(0, star));\n\n if (nextValue === normalizedValue.value) return;\n\n // Write through the host attribute; ore handles host reflection.\n el.setAttribute('value', String(nextValue));\n emit('change', { originalEvent, value: nextValue });\n triggerValidation('change');\n spawnSparkles(nextValue);\n }\n function handleKeydown(e: KeyboardEvent, star: number) {\n const next = ratingControl.nextFromKey(e.key, star);\n\n if (next == null) return;\n\n e.preventDefault();\n select(next, e);\n\n const buttons = getStarButtons();\n\n buttons[next - 1]?.focus();\n }\n\n const stars = computed(() => {\n const max = Number(props.max!.value) || 5;\n\n return Array.from({ length: max }, (_, i) => i + 1);\n });\n\n bind({ attr: { size: fCtxProps.size } });\n\n return html`\n <div\n class=\"stars\"\n part=\"stars\"\n role=\"radiogroup\"\n :aria-label=\"${props.label}\"\n :aria-describedby=\"${ariaDescribedBy}\">\n ${() =>\n stars.value.map(\n (star) =>\n html`<button\n class=\"star-btn\"\n part=\"star\"\n type=\"button\"\n role=\"radio\"\n :aria-label=\"${() => `${star} ${star === 1 ? 'star' : 'stars'}`}\"\n :aria-checked=\"${() => String(star === normalizedValue.value)}\"\n :data-star=\"${star}\"\n ?data-filled=\"${() => star <= displayValue.value}\"\n :disabled=\"${() => (!isInteractive.value ? true : null)}\"\n @click=\"${(e: Event) => select(star, e)}\"\n @pointerenter=\"${() => {\n if (isInteractive.value) hovered.value = star;\n }}\"\n @pointerleave=\"${() => {\n hovered.value = null;\n }}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, star)}\">\n <ore-icon name=\"star\" size=\"var(--_star-size)\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n </button>`,\n )}\n <div class=\"sparkle-layer\"></div>\n </div>\n ${renderHelperRegion(assistiveId, errorText, helperText)}\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"rating.js","names":[],"sources":["../src/inputs/rating/rating.ts"],"sourcesContent":["import { createStableId, define, html, inject, prop, bind, getHost, useEmit } from '@vielzeug/ore';\nimport { useField } from '@vielzeug/ore/forms';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { createErrorHelperState, createSliderControl } from '../../headless';\nimport '../../content/icon/icon';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport { FORM_CTX, useFormContext } from '../shared/form-context';\nimport { renderHelperRegion } from '../shared/templates';\nimport styles from './rating.css?inline';\n\nexport type OreRatingEvents = {\n change: { originalEvent?: Event; value: number };\n};\n\n/** Rating props */\nexport type OreRatingProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message — marks the field as invalid (fallback when the `error` slot is empty) */\n error?: string;\n /** Helper text displayed below the stars (fallback when the `helper` slot is empty) */\n helper?: string;\n /** Accessible group label */\n label?: string;\n /** Maximum rating (number of stars) */\n max?: number;\n /** Form field name */\n name?: string;\n /** Make rating read-only */\n readonly?: boolean;\n /** Component size */\n size?: ComponentSize;\n /** Render selected stars as solid-filled instead of outline-only */\n solid?: boolean;\n /** Current rating value */\n value?: number;\n};\n\n/**\n * A star rating input.\n *\n * @element ore-rating\n *\n * @attr {number} value - Current rating value (default: 0)\n * @attr {number} max - Maximum number of stars (default: 5)\n * @attr {boolean} readonly - Read-only display mode\n * @attr {boolean} disabled - Disabled state\n * @attr {string} label - aria-label for the group (default: 'Rating')\n * @attr {string} color - Theme color for filled stars: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} name - Form field name\n * @attr {boolean} solid - Fill selected stars (outline remains default when omitted)\n * @attr {string} helper - Helper text below the stars\n * @attr {string} error - Error message below the stars\n *\n * @fires change - Emitted when value changes. detail: { value: number, originalEvent?: Event }\n *\n * @cssprop --rating-star-size - Star diameter\n * @cssprop --rating-color-empty - Empty star color\n * @cssprop --rating-color-filled - Filled star color\n * @cssprop --rating-gap - Gap between stars\n *\n * @part stars - Stars container.\n * @part star - Star item element.\n * @part helper-text - The helper/error text element.\n * @example\n * ```html\n * <ore-rating value=\"3\" max=\"5\" color=\"warning\"></ore-rating>\n * <ore-rating value=\"4\" solid></ore-rating>\n * ```\n */\nexport const RATING_TAG = 'ore-rating' as const;\ndefine<OreRatingProps>(RATING_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string('Rating'),\n max: prop.number(5),\n name: prop.string(),\n readonly: prop.bool(false),\n solid: prop.bool(false),\n value: prop.number(0),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreRatingEvents>();\n\n const formCtx = inject(FORM_CTX);\n const fCtxProps = useFormContext(props, formCtx);\n\n const normalizedValue = computed(() => {\n const max = Math.max(1, Number(props.max!.value) || 5);\n const raw = Number(props.value!.value);\n const safe = Number.isFinite(raw) ? raw : 0;\n\n return Math.min(max, Math.max(0, safe));\n });\n\n const fd = useField({\n disabled: fCtxProps.disabled,\n value: computed(() => String(normalizedValue.value || 0)),\n });\n\n const triggerValidation = (on: 'blur' | 'change') => {\n if (formCtx?.validateOn?.value === on) {\n fd.reportValidity();\n }\n };\n\n const assistiveId = createStableId('helper');\n const assistive = createErrorHelperState({ error: props.error, helper: props.helper });\n const errorText = computed(() => assistive.value.errorText);\n const helperText = computed(() => assistive.value.helperText);\n const ariaDescribedBy = computed(() => (errorText.value || helperText.value ? assistiveId : null));\n\n const isInteractive = computed(() => !props.readonly!.value && !fCtxProps.disabled.value);\n const hovered = signal<number | null>(null);\n const displayValue = computed(() => hovered.value ?? normalizedValue.value);\n const getStarButtons = () => {\n return [...(el.shadowRoot?.querySelectorAll<HTMLButtonElement>('[data-star]') ?? [])];\n };\n const ratingControl = createSliderControl({\n max: computed(() => Number(props.max!.value) || 5),\n min: signal(1),\n step: signal(1),\n });\n\n function spawnSparkles(star: number) {\n const layer = el.shadowRoot?.querySelector<HTMLElement>('.sparkle-layer');\n const btn = el.shadowRoot?.querySelector<HTMLElement>(`[data-star=\"${star}\"]`);\n\n if (!layer || !btn) return;\n\n const cx = btn.offsetLeft + btn.offsetWidth / 2;\n const cy = btn.offsetTop + btn.offsetHeight / 2;\n const count = 10;\n\n for (let i = 0; i < count; i++) {\n const p = document.createElement('span');\n const angle = (360 / count) * i + (Math.random() * 30 - 15);\n const dist = 18 + Math.random() * 20;\n const size = 3 + Math.random() * 4;\n const dur = 380 + Math.random() * 220;\n\n p.className = 'sparkle';\n p.style.cssText = [\n `left:${cx}px`,\n `top:${cy}px`,\n `--_angle:${angle}deg`,\n `--_dist:${dist}px`,\n `width:${size}px`,\n `height:${size}px`,\n `--_dur:${dur}ms`,\n `animation-delay:${Math.random() * 60}ms`,\n ].join(';');\n layer.appendChild(p);\n p.addEventListener('animationend', () => p.remove(), { once: true });\n }\n }\n function select(star: number, originalEvent?: Event) {\n if (!isInteractive.value) return;\n\n const max = Math.max(1, Number(props.max!.value) || 5);\n const nextValue = Math.min(max, Math.max(0, star));\n\n if (nextValue === normalizedValue.value) return;\n\n // Write through the host attribute; ore handles host reflection.\n el.setAttribute('value', String(nextValue));\n emit('change', { originalEvent, value: nextValue });\n triggerValidation('change');\n spawnSparkles(nextValue);\n }\n function handleKeydown(e: KeyboardEvent, star: number) {\n const next = ratingControl.nextFromKey(e.key, star);\n\n if (next == null) return;\n\n e.preventDefault();\n select(next, e);\n\n const buttons = getStarButtons();\n\n buttons[next - 1]?.focus();\n }\n\n const stars = computed(() => {\n const max = Number(props.max!.value) || 5;\n\n return Array.from({ length: max }, (_, i) => i + 1);\n });\n\n bind({ attr: { size: fCtxProps.size } });\n\n return html`\n <div\n class=\"stars\"\n part=\"stars\"\n role=\"radiogroup\"\n :aria-label=\"${props.label}\"\n :aria-describedby=\"${ariaDescribedBy}\">\n ${() =>\n stars.value.map(\n (star) =>\n html`<button\n class=\"star-btn\"\n part=\"star\"\n type=\"button\"\n role=\"radio\"\n :aria-label=\"${() => `${star} ${star === 1 ? 'star' : 'stars'}`}\"\n :aria-checked=\"${() => String(star === normalizedValue.value)}\"\n :data-star=\"${star}\"\n ?data-filled=\"${() => star <= displayValue.value}\"\n :disabled=\"${() => (!isInteractive.value ? true : null)}\"\n @click=\"${(e: Event) => select(star, e)}\"\n @pointerenter=\"${() => {\n if (isInteractive.value) hovered.value = star;\n }}\"\n @pointerleave=\"${() => {\n hovered.value = null;\n }}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, star)}\">\n <ore-icon name=\"star\" size=\"var(--_star-size)\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n </button>`,\n )}\n <div class=\"sparkle-layer\"></div>\n </div>\n ${renderHelperRegion(assistiveId, errorText, helperText)}\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, reducedMotionMixin, styles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"rating.js","names":[],"sources":["../src/inputs/rating/rating.ts"],"sourcesContent":["import { createStableId, define, html, inject, prop, bind, getHost, useEmit } from '@vielzeug/ore';\nimport { useField } from '@vielzeug/ore/forms';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { createErrorHelperState, createSliderControl } from '../../headless';\nimport '../../content/icon/icon';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport { FORM_CTX, useFormContext } from '../shared/form-context';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './rating.css?inline';\n\nexport type OreRatingEvents = {\n change: { originalEvent?: Event; value: number };\n};\n\n/** Rating props */\nexport type OreRatingProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message — marks the field as invalid (fallback when the `error` slot is empty) */\n error?: string;\n /** Helper text displayed below the stars (fallback when the `helper` slot is empty) */\n helper?: string;\n /** Accessible group label */\n label?: string;\n /** Maximum rating (number of stars) */\n max?: number;\n /** Form field name */\n name?: string;\n /** Make rating read-only */\n readonly?: boolean;\n /** Component size */\n size?: ComponentSize;\n /** Render selected stars as solid-filled instead of outline-only */\n solid?: boolean;\n /** Current rating value */\n value?: number;\n};\n\n/**\n * A star rating input.\n *\n * @element ore-rating\n *\n * @attr {number} value - Current rating value (default: 0)\n * @attr {number} max - Maximum number of stars (default: 5)\n * @attr {boolean} readonly - Read-only display mode\n * @attr {boolean} disabled - Disabled state\n * @attr {string} label - aria-label for the group (default: 'Rating')\n * @attr {string} color - Theme color for filled stars: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} name - Form field name\n * @attr {boolean} solid - Fill selected stars (outline remains default when omitted)\n * @attr {string} helper - Helper text below the stars\n * @attr {string} error - Error message below the stars\n *\n * @fires change - Emitted when value changes. detail: { value: number, originalEvent?: Event }\n *\n * @cssprop --rating-star-size - Star diameter\n * @cssprop --rating-color-empty - Empty star color\n * @cssprop --rating-color-filled - Filled star color\n * @cssprop --rating-gap - Gap between stars\n *\n * @part stars - Stars container.\n * @part star - Star item element.\n * @part helper-text - The helper/error text element.\n * @example\n * ```html\n * <ore-rating value=\"3\" max=\"5\" color=\"warning\"></ore-rating>\n * <ore-rating value=\"4\" solid></ore-rating>\n * ```\n */\nexport const RATING_TAG = 'ore-rating' as const;\ndefine<OreRatingProps>(RATING_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string('Rating'),\n max: prop.number(5),\n name: prop.string(),\n readonly: prop.bool(false),\n solid: prop.bool(false),\n value: prop.number(0),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreRatingEvents>();\n\n const formCtx = inject(FORM_CTX);\n const fCtxProps = useFormContext(props, formCtx);\n\n const normalizedValue = computed(() => {\n const max = Math.max(1, Number(props.max!.value) || 5);\n const raw = Number(props.value!.value);\n const safe = Number.isFinite(raw) ? raw : 0;\n\n return Math.min(max, Math.max(0, safe));\n });\n\n const fd = useField({\n disabled: fCtxProps.disabled,\n value: computed(() => String(normalizedValue.value || 0)),\n });\n\n const triggerValidation = (on: 'blur' | 'change') => {\n if (formCtx?.validateOn?.value === on) {\n fd.reportValidity();\n }\n };\n\n const assistiveId = createStableId('helper');\n const assistive = createErrorHelperState({ error: props.error, helper: props.helper });\n const errorText = computed(() => assistive.value.errorText);\n const helperText = computed(() => assistive.value.helperText);\n const ariaDescribedBy = computed(() => (errorText.value || helperText.value ? assistiveId : null));\n\n const isInteractive = computed(() => !props.readonly!.value && !fCtxProps.disabled.value);\n const hovered = signal<number | null>(null);\n const displayValue = computed(() => hovered.value ?? normalizedValue.value);\n const getStarButtons = () => {\n return [...(el.shadowRoot?.querySelectorAll<HTMLButtonElement>('[data-star]') ?? [])];\n };\n const ratingControl = createSliderControl({\n max: computed(() => Number(props.max!.value) || 5),\n min: signal(1),\n step: signal(1),\n });\n\n function spawnSparkles(star: number) {\n const layer = el.shadowRoot?.querySelector<HTMLElement>('.sparkle-layer');\n const btn = el.shadowRoot?.querySelector<HTMLElement>(`[data-star=\"${star}\"]`);\n\n if (!layer || !btn) return;\n\n const cx = btn.offsetLeft + btn.offsetWidth / 2;\n const cy = btn.offsetTop + btn.offsetHeight / 2;\n const count = 10;\n\n for (let i = 0; i < count; i++) {\n const p = document.createElement('span');\n const angle = (360 / count) * i + (Math.random() * 30 - 15);\n const dist = 18 + Math.random() * 20;\n const size = 3 + Math.random() * 4;\n const dur = 380 + Math.random() * 220;\n\n p.className = 'sparkle';\n p.style.cssText = [\n `left:${cx}px`,\n `top:${cy}px`,\n `--_angle:${angle}deg`,\n `--_dist:${dist}px`,\n `width:${size}px`,\n `height:${size}px`,\n `--_dur:${dur}ms`,\n `animation-delay:${Math.random() * 60}ms`,\n ].join(';');\n layer.appendChild(p);\n p.addEventListener('animationend', () => p.remove(), { once: true });\n }\n }\n function select(star: number, originalEvent?: Event) {\n if (!isInteractive.value) return;\n\n const max = Math.max(1, Number(props.max!.value) || 5);\n const nextValue = Math.min(max, Math.max(0, star));\n\n if (nextValue === normalizedValue.value) return;\n\n // Write through the host attribute; ore handles host reflection.\n el.setAttribute('value', String(nextValue));\n emit('change', { originalEvent, value: nextValue });\n triggerValidation('change');\n spawnSparkles(nextValue);\n }\n function handleKeydown(e: KeyboardEvent, star: number) {\n const next = ratingControl.nextFromKey(e.key, star);\n\n if (next == null) return;\n\n e.preventDefault();\n select(next, e);\n\n const buttons = getStarButtons();\n\n buttons[next - 1]?.focus();\n }\n\n const stars = computed(() => {\n const max = Number(props.max!.value) || 5;\n\n return Array.from({ length: max }, (_, i) => i + 1);\n });\n\n bind({ attr: { size: fCtxProps.size } });\n\n return html`\n <div\n class=\"stars\"\n part=\"stars\"\n role=\"radiogroup\"\n :aria-label=\"${props.label}\"\n :aria-describedby=\"${ariaDescribedBy}\">\n ${() =>\n stars.value.map(\n (star) =>\n html`<button\n class=\"star-btn\"\n part=\"star\"\n type=\"button\"\n role=\"radio\"\n :aria-label=\"${() => `${star} ${star === 1 ? 'star' : 'stars'}`}\"\n :aria-checked=\"${() => String(star === normalizedValue.value)}\"\n :data-star=\"${star}\"\n ?data-filled=\"${() => star <= displayValue.value}\"\n :disabled=\"${() => (!isInteractive.value ? true : null)}\"\n @click=\"${(e: Event) => select(star, e)}\"\n @pointerenter=\"${() => {\n if (isInteractive.value) hovered.value = star;\n }}\"\n @pointerleave=\"${() => {\n hovered.value = null;\n }}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, star)}\">\n <ore-icon name=\"star\" size=\"var(--_star-size)\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n </button>`,\n )}\n <div class=\"sparkle-layer\"></div>\n </div>\n ${renderHelperRegion(assistiveId, errorText, helperText)}\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"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"}