@vielzeug/refine 2.1.0 → 2.1.2

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 (487) hide show
  1. package/dist/accordion-item.cjs +1 -1
  2. package/dist/accordion-item.cjs.map +1 -1
  3. package/dist/accordion-item.js +1 -1
  4. package/dist/accordion-item.js.map +1 -1
  5. package/dist/accordion.cjs +1 -1
  6. package/dist/accordion.cjs.map +1 -1
  7. package/dist/accordion.js +1 -1
  8. package/dist/accordion.js.map +1 -1
  9. package/dist/alert.cjs.map +1 -1
  10. package/dist/alert.js.map +1 -1
  11. package/dist/async.cjs.map +1 -1
  12. package/dist/async.js.map +1 -1
  13. package/dist/avatar-group.cjs.map +1 -1
  14. package/dist/avatar-group.js.map +1 -1
  15. package/dist/avatar.cjs +6 -6
  16. package/dist/avatar.cjs.map +1 -1
  17. package/dist/avatar.js +1 -2
  18. package/dist/avatar.js.map +1 -1
  19. package/dist/badge.cjs.map +1 -1
  20. package/dist/badge.js.map +1 -1
  21. package/dist/box.cjs.map +1 -1
  22. package/dist/box.js.map +1 -1
  23. package/dist/breadcrumb.cjs +3 -3
  24. package/dist/breadcrumb.cjs.map +1 -1
  25. package/dist/breadcrumb.js +4 -4
  26. package/dist/breadcrumb.js.map +1 -1
  27. package/dist/button-group.cjs +1 -1
  28. package/dist/button-group.cjs.map +1 -1
  29. package/dist/button-group.js +0 -1
  30. package/dist/button-group.js.map +1 -1
  31. package/dist/button.cjs.map +1 -1
  32. package/dist/button.js.map +1 -1
  33. package/dist/calendar.cjs.map +1 -1
  34. package/dist/calendar.js.map +1 -1
  35. package/dist/card.cjs +7 -7
  36. package/dist/card.cjs.map +1 -1
  37. package/dist/card.js +27 -27
  38. package/dist/card.js.map +1 -1
  39. package/dist/carousel.cjs +20 -20
  40. package/dist/carousel.cjs.map +1 -1
  41. package/dist/carousel.js +7 -8
  42. package/dist/carousel.js.map +1 -1
  43. package/dist/chat-message.cjs +10 -10
  44. package/dist/chat-message.cjs.map +1 -1
  45. package/dist/chat-message.js +1 -2
  46. package/dist/chat-message.js.map +1 -1
  47. package/dist/checkbox-group.cjs +7 -7
  48. package/dist/checkbox-group.cjs.map +1 -1
  49. package/dist/checkbox-group.js +26 -26
  50. package/dist/checkbox-group.js.map +1 -1
  51. package/dist/checkbox.cjs +2 -2
  52. package/dist/checkbox.cjs.map +1 -1
  53. package/dist/checkbox.js +33 -33
  54. package/dist/checkbox.js.map +1 -1
  55. package/dist/chip.cjs +16 -16
  56. package/dist/chip.cjs.map +1 -1
  57. package/dist/chip.js +1 -2
  58. package/dist/chip.js.map +1 -1
  59. package/dist/combobox.cjs +28 -28
  60. package/dist/combobox.cjs.map +1 -1
  61. package/dist/combobox.js +211 -211
  62. package/dist/combobox.js.map +1 -1
  63. package/dist/command-palette.cjs +21 -21
  64. package/dist/command-palette.cjs.map +1 -1
  65. package/dist/command-palette.js +27 -28
  66. package/dist/command-palette.js.map +1 -1
  67. package/dist/content/avatar/avatar.css.cjs +1 -1
  68. package/dist/content/avatar/avatar.css.js +1 -1
  69. package/dist/content/avatar/avatar.d.ts.map +1 -1
  70. package/dist/content/breadcrumb/breadcrumb.d.ts.map +1 -1
  71. package/dist/content/card/card.css.cjs +1 -1
  72. package/dist/content/card/card.css.cjs.map +1 -1
  73. package/dist/content/card/card.css.js +1 -1
  74. package/dist/content/card/card.css.js.map +1 -1
  75. package/dist/content/card/card.d.ts.map +1 -1
  76. package/dist/content/carousel/carousel-slide.cjs.map +1 -1
  77. package/dist/content/carousel/carousel-slide.js.map +1 -1
  78. package/dist/content/carousel/carousel.css.cjs +1 -1
  79. package/dist/content/carousel/carousel.css.cjs.map +1 -1
  80. package/dist/content/carousel/carousel.css.js +1 -1
  81. package/dist/content/carousel/carousel.css.js.map +1 -1
  82. package/dist/content/carousel/carousel.d.ts.map +1 -1
  83. package/dist/content/carousel/index.d.ts +1 -1
  84. package/dist/content/carousel/index.d.ts.map +1 -1
  85. package/dist/content/chat-message/chat-message.css.cjs +1 -1
  86. package/dist/content/chat-message/chat-message.css.js +1 -1
  87. package/dist/content/chat-message/chat-message.d.ts.map +1 -1
  88. package/dist/content/code-window/code-window.css.cjs +1 -1
  89. package/dist/content/code-window/code-window.css.js +1 -1
  90. package/dist/content/copy-command/copy-command.css.cjs +1 -1
  91. package/dist/content/copy-command/copy-command.css.js +1 -1
  92. package/dist/content/copy-command/copy-command.d.ts.map +1 -1
  93. package/dist/content/index.d.ts +22 -22
  94. package/dist/content/index.d.ts.map +1 -1
  95. package/dist/content/list/_list-item-reveal.cjs.map +1 -1
  96. package/dist/content/list/_list-item-reveal.d.ts +1 -1
  97. package/dist/content/list/_list-item-reveal.d.ts.map +1 -1
  98. package/dist/content/list/_list-item-reveal.js.map +1 -1
  99. package/dist/content/list/list-item.css.cjs +1 -1
  100. package/dist/content/list/list-item.css.cjs.map +1 -1
  101. package/dist/content/list/list-item.css.js +1 -1
  102. package/dist/content/list/list-item.css.js.map +1 -1
  103. package/dist/content/list/list.d.ts.map +1 -1
  104. package/dist/content/marquee/marquee.css.cjs +1 -1
  105. package/dist/content/marquee/marquee.css.js +1 -1
  106. package/dist/content/pagination/pagination.css.cjs +1 -1
  107. package/dist/content/pagination/pagination.css.js +1 -1
  108. package/dist/content/pagination/pagination.d.ts.map +1 -1
  109. package/dist/content/separator/separator.css.cjs +1 -1
  110. package/dist/content/separator/separator.css.js +1 -1
  111. package/dist/content/separator/separator.d.ts.map +1 -1
  112. package/dist/content/stepper/step.css.cjs.map +1 -1
  113. package/dist/content/stepper/step.css.js.map +1 -1
  114. package/dist/content/stepper/stepper.d.ts.map +1 -1
  115. package/dist/content/table/table.css.cjs +1 -1
  116. package/dist/content/table/table.css.js +1 -1
  117. package/dist/content/text/text.css.cjs +1 -1
  118. package/dist/content/text/text.css.js +1 -1
  119. package/dist/copy-command.cjs.map +1 -1
  120. package/dist/copy-command.js.map +1 -1
  121. package/dist/core/checkable.cjs +1 -1
  122. package/dist/core/checkable.cjs.map +1 -1
  123. package/dist/core/checkable.d.ts.map +1 -1
  124. package/dist/core/checkable.js +4 -4
  125. package/dist/core/checkable.js.map +1 -1
  126. package/dist/core/choice-field.cjs +1 -1
  127. package/dist/core/choice-field.cjs.map +1 -1
  128. package/dist/core/choice-field.d.ts.map +1 -1
  129. package/dist/core/choice-field.js +1 -2
  130. package/dist/core/choice-field.js.map +1 -1
  131. package/dist/core/date-picker.cjs +1 -1
  132. package/dist/core/date-picker.cjs.map +1 -1
  133. package/dist/core/date-picker.d.ts.map +1 -1
  134. package/dist/core/date-picker.js +3 -3
  135. package/dist/core/date-picker.js.map +1 -1
  136. package/dist/core/index.d.ts +17 -17
  137. package/dist/core/index.d.ts.map +1 -1
  138. package/dist/core/option-list.cjs +1 -1
  139. package/dist/core/option-list.cjs.map +1 -1
  140. package/dist/core/option-list.d.ts.map +1 -1
  141. package/dist/core/option-list.js +4 -4
  142. package/dist/core/option-list.js.map +1 -1
  143. package/dist/core/ref-callback.cjs +1 -1
  144. package/dist/core/ref-callback.cjs.map +1 -1
  145. package/dist/core/ref-callback.d.ts.map +1 -1
  146. package/dist/core/ref-callback.js +1 -1
  147. package/dist/core/ref-callback.js.map +1 -1
  148. package/dist/core/signals.cjs +1 -1
  149. package/dist/core/signals.cjs.map +1 -1
  150. package/dist/core/signals.d.ts.map +1 -1
  151. package/dist/core/signals.js +1 -2
  152. package/dist/core/signals.js.map +1 -1
  153. package/dist/core/slider.cjs.map +1 -1
  154. package/dist/core/slider.d.ts.map +1 -1
  155. package/dist/core/slider.js.map +1 -1
  156. package/dist/core/spinner.cjs.map +1 -1
  157. package/dist/core/spinner.d.ts.map +1 -1
  158. package/dist/core/spinner.js.map +1 -1
  159. package/dist/core/text-field.cjs +1 -1
  160. package/dist/core/text-field.cjs.map +1 -1
  161. package/dist/core/text-field.js +1 -1
  162. package/dist/core/text-field.js.map +1 -1
  163. package/dist/custom-elements.json +6036 -6036
  164. package/dist/datagrid.cjs +114 -114
  165. package/dist/datagrid.cjs.map +1 -1
  166. package/dist/datagrid.js +42 -43
  167. package/dist/datagrid.js.map +1 -1
  168. package/dist/date-picker.cjs.map +1 -1
  169. package/dist/date-picker.js.map +1 -1
  170. package/dist/dialog.cjs.map +1 -1
  171. package/dist/dialog.js.map +1 -1
  172. package/dist/disclosure/accordion/accordion.d.ts.map +1 -1
  173. package/dist/disclosure/accordion-item/accordion-item.css.cjs +1 -1
  174. package/dist/disclosure/accordion-item/accordion-item.css.cjs.map +1 -1
  175. package/dist/disclosure/accordion-item/accordion-item.css.js +1 -1
  176. package/dist/disclosure/accordion-item/accordion-item.css.js.map +1 -1
  177. package/dist/disclosure/index.d.ts +6 -6
  178. package/dist/disclosure/index.d.ts.map +1 -1
  179. package/dist/disclosure/tab-item/tab-item.css.cjs.map +1 -1
  180. package/dist/disclosure/tab-item/tab-item.css.js.map +1 -1
  181. package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -1
  182. package/dist/disclosure/tabs/tabs.css.cjs +1 -1
  183. package/dist/disclosure/tabs/tabs.css.cjs.map +1 -1
  184. package/dist/disclosure/tabs/tabs.css.js +1 -1
  185. package/dist/disclosure/tabs/tabs.css.js.map +1 -1
  186. package/dist/disclosure/tabs/tabs.d.ts.map +1 -1
  187. package/dist/drawer.cjs +5 -5
  188. package/dist/drawer.cjs.map +1 -1
  189. package/dist/drawer.js +26 -26
  190. package/dist/drawer.js.map +1 -1
  191. package/dist/feedback/alert/alert.css.cjs +1 -1
  192. package/dist/feedback/alert/alert.css.js +1 -1
  193. package/dist/feedback/async/async.d.ts +1 -1
  194. package/dist/feedback/async/async.d.ts.map +1 -1
  195. package/dist/feedback/badge/badge.css.cjs +1 -1
  196. package/dist/feedback/badge/badge.css.js +1 -1
  197. package/dist/feedback/badge/badge.d.ts.map +1 -1
  198. package/dist/feedback/chip/chip.css.cjs.map +1 -1
  199. package/dist/feedback/chip/chip.css.js.map +1 -1
  200. package/dist/feedback/chip/chip.d.ts.map +1 -1
  201. package/dist/feedback/index.d.ts +12 -12
  202. package/dist/feedback/index.d.ts.map +1 -1
  203. package/dist/feedback/progress/progress.d.ts.map +1 -1
  204. package/dist/feedback/skeleton/skeleton.d.ts.map +1 -1
  205. package/dist/feedback/toast/index.d.ts +1 -1
  206. package/dist/feedback/toast/index.d.ts.map +1 -1
  207. package/dist/feedback/toast/toast.css.cjs +1 -1
  208. package/dist/feedback/toast/toast.css.cjs.map +1 -1
  209. package/dist/feedback/toast/toast.css.js +1 -1
  210. package/dist/feedback/toast/toast.css.js.map +1 -1
  211. package/dist/feedback/toast/toast.d.ts +1 -1
  212. package/dist/feedback/toast/toast.d.ts.map +1 -1
  213. package/dist/feedback/typing-indicator/typing-indicator.d.ts.map +1 -1
  214. package/dist/file-input.cjs +67 -67
  215. package/dist/file-input.cjs.map +1 -1
  216. package/dist/file-input.js +129 -130
  217. package/dist/file-input.js.map +1 -1
  218. package/dist/grid.cjs.map +1 -1
  219. package/dist/grid.js.map +1 -1
  220. package/dist/icon.cjs.map +1 -1
  221. package/dist/icon.js.map +1 -1
  222. package/dist/input.cjs +21 -21
  223. package/dist/input.cjs.map +1 -1
  224. package/dist/input.js +58 -58
  225. package/dist/input.js.map +1 -1
  226. package/dist/inputs/button/button.css.cjs +1 -1
  227. package/dist/inputs/button/button.css.js +1 -1
  228. package/dist/inputs/button/button.d.ts.map +1 -1
  229. package/dist/inputs/button-group/button-group.css.cjs.map +1 -1
  230. package/dist/inputs/button-group/button-group.css.js.map +1 -1
  231. package/dist/inputs/button-group/button-group.d.ts +1 -1
  232. package/dist/inputs/button-group/button-group.d.ts.map +1 -1
  233. package/dist/inputs/calendar/calendar.css.cjs +1 -1
  234. package/dist/inputs/calendar/calendar.css.cjs.map +1 -1
  235. package/dist/inputs/calendar/calendar.css.js +1 -1
  236. package/dist/inputs/calendar/calendar.css.js.map +1 -1
  237. package/dist/inputs/calendar/calendar.d.ts.map +1 -1
  238. package/dist/inputs/checkbox/checkbox.css.cjs +1 -1
  239. package/dist/inputs/checkbox/checkbox.css.js +1 -1
  240. package/dist/inputs/checkbox/checkbox.d.ts.map +1 -1
  241. package/dist/inputs/checkbox-group/checkbox-group.d.ts +1 -1
  242. package/dist/inputs/checkbox-group/checkbox-group.d.ts.map +1 -1
  243. package/dist/inputs/combobox/combobox.css.cjs +1 -1
  244. package/dist/inputs/combobox/combobox.css.js +1 -1
  245. package/dist/inputs/combobox/combobox.d.ts.map +1 -1
  246. package/dist/inputs/datagrid/datagrid-column.cjs.map +1 -1
  247. package/dist/inputs/datagrid/datagrid-column.d.ts.map +1 -1
  248. package/dist/inputs/datagrid/datagrid-column.js.map +1 -1
  249. package/dist/inputs/datagrid/datagrid-model.cjs +1 -1
  250. package/dist/inputs/datagrid/datagrid-model.cjs.map +1 -1
  251. package/dist/inputs/datagrid/datagrid-model.d.ts.map +1 -1
  252. package/dist/inputs/datagrid/datagrid-model.js +1 -2
  253. package/dist/inputs/datagrid/datagrid-model.js.map +1 -1
  254. package/dist/inputs/datagrid/datagrid.css.cjs +1 -1
  255. package/dist/inputs/datagrid/datagrid.css.cjs.map +1 -1
  256. package/dist/inputs/datagrid/datagrid.css.js +1 -1
  257. package/dist/inputs/datagrid/datagrid.css.js.map +1 -1
  258. package/dist/inputs/datagrid/datagrid.d.ts +1 -1
  259. package/dist/inputs/datagrid/datagrid.d.ts.map +1 -1
  260. package/dist/inputs/date-picker/date-picker.css.cjs +1 -1
  261. package/dist/inputs/date-picker/date-picker.css.cjs.map +1 -1
  262. package/dist/inputs/date-picker/date-picker.css.js +1 -1
  263. package/dist/inputs/date-picker/date-picker.css.js.map +1 -1
  264. package/dist/inputs/date-picker/date-picker.d.ts.map +1 -1
  265. package/dist/inputs/file-input/file-input-upload.cjs +1 -1
  266. package/dist/inputs/file-input/file-input-upload.cjs.map +1 -1
  267. package/dist/inputs/file-input/file-input-upload.d.ts.map +1 -1
  268. package/dist/inputs/file-input/file-input-upload.js +2 -3
  269. package/dist/inputs/file-input/file-input-upload.js.map +1 -1
  270. package/dist/inputs/file-input/file-input.css.cjs +1 -1
  271. package/dist/inputs/file-input/file-input.css.js +1 -1
  272. package/dist/inputs/file-input/file-input.d.ts.map +1 -1
  273. package/dist/inputs/index.d.ts +28 -28
  274. package/dist/inputs/index.d.ts.map +1 -1
  275. package/dist/inputs/input/input.css.cjs +1 -1
  276. package/dist/inputs/input/input.css.js +1 -1
  277. package/dist/inputs/input/input.d.ts.map +1 -1
  278. package/dist/inputs/message-composer/message-composer.css.cjs +1 -1
  279. package/dist/inputs/message-composer/message-composer.css.js +1 -1
  280. package/dist/inputs/message-composer/message-composer.d.ts +1 -1
  281. package/dist/inputs/message-composer/message-composer.d.ts.map +1 -1
  282. package/dist/inputs/number-input/number-input.d.ts.map +1 -1
  283. package/dist/inputs/otp-input/otp-input.d.ts.map +1 -1
  284. package/dist/inputs/radio/radio.css.cjs +1 -1
  285. package/dist/inputs/radio/radio.css.js +1 -1
  286. package/dist/inputs/radio/radio.d.ts.map +1 -1
  287. package/dist/inputs/radio-group/radio-group.d.ts +2 -2
  288. package/dist/inputs/radio-group/radio-group.d.ts.map +1 -1
  289. package/dist/inputs/rating/rating.d.ts.map +1 -1
  290. package/dist/inputs/select/select.css.cjs +1 -1
  291. package/dist/inputs/select/select.css.js +1 -1
  292. package/dist/inputs/select/select.d.ts.map +1 -1
  293. package/dist/inputs/shared/field-binding.cjs.map +1 -1
  294. package/dist/inputs/shared/field-binding.d.ts.map +1 -1
  295. package/dist/inputs/shared/field-binding.js.map +1 -1
  296. package/dist/inputs/shared/templates.cjs.map +1 -1
  297. package/dist/inputs/shared/templates.d.ts.map +1 -1
  298. package/dist/inputs/shared/templates.js.map +1 -1
  299. package/dist/inputs/slider/slider.d.ts.map +1 -1
  300. package/dist/inputs/switch/switch.css.cjs +1 -1
  301. package/dist/inputs/switch/switch.css.js +1 -1
  302. package/dist/inputs/switch/switch.d.ts.map +1 -1
  303. package/dist/inputs/textarea/textarea.css.cjs +1 -1
  304. package/dist/inputs/textarea/textarea.css.js +1 -1
  305. package/dist/inputs/textarea/textarea.d.ts.map +1 -1
  306. package/dist/inputs/time-picker/time-picker.css.cjs +1 -1
  307. package/dist/inputs/time-picker/time-picker.css.cjs.map +1 -1
  308. package/dist/inputs/time-picker/time-picker.css.js +1 -1
  309. package/dist/inputs/time-picker/time-picker.css.js.map +1 -1
  310. package/dist/inputs/time-picker/time-picker.d.ts.map +1 -1
  311. package/dist/layout/box/box.d.ts.map +1 -1
  312. package/dist/layout/grid/grid.d.ts.map +1 -1
  313. package/dist/layout/index.d.ts +6 -6
  314. package/dist/layout/index.d.ts.map +1 -1
  315. package/dist/layout/navbar/navbar.css.cjs +1 -1
  316. package/dist/layout/navbar/navbar.css.js +1 -1
  317. package/dist/layout/navbar/navbar.d.ts.map +1 -1
  318. package/dist/layout/sidebar/sidebar-group.css.cjs +1 -1
  319. package/dist/layout/sidebar/sidebar-group.css.cjs.map +1 -1
  320. package/dist/layout/sidebar/sidebar-group.css.js +1 -1
  321. package/dist/layout/sidebar/sidebar-group.css.js.map +1 -1
  322. package/dist/layout/sidebar/sidebar.css.cjs +1 -1
  323. package/dist/layout/sidebar/sidebar.css.cjs.map +1 -1
  324. package/dist/layout/sidebar/sidebar.css.js +1 -1
  325. package/dist/layout/sidebar/sidebar.css.js.map +1 -1
  326. package/dist/layout/sidebar/sidebar.d.ts.map +1 -1
  327. package/dist/list-item.cjs.map +1 -1
  328. package/dist/list-item.js.map +1 -1
  329. package/dist/list.cjs +2 -2
  330. package/dist/list.cjs.map +1 -1
  331. package/dist/list.js +15 -16
  332. package/dist/list.js.map +1 -1
  333. package/dist/marquee.cjs +1 -1
  334. package/dist/marquee.cjs.map +1 -1
  335. package/dist/marquee.js +1 -1
  336. package/dist/marquee.js.map +1 -1
  337. package/dist/menu.cjs +5 -5
  338. package/dist/menu.cjs.map +1 -1
  339. package/dist/menu.js +38 -39
  340. package/dist/menu.js.map +1 -1
  341. package/dist/message-composer.cjs +16 -16
  342. package/dist/message-composer.cjs.map +1 -1
  343. package/dist/message-composer.js +61 -61
  344. package/dist/message-composer.js.map +1 -1
  345. package/dist/navbar.cjs +9 -9
  346. package/dist/navbar.cjs.map +1 -1
  347. package/dist/navbar.js +1 -2
  348. package/dist/navbar.js.map +1 -1
  349. package/dist/navigation-menu.cjs +5 -5
  350. package/dist/navigation-menu.cjs.map +1 -1
  351. package/dist/navigation-menu.js +33 -34
  352. package/dist/navigation-menu.js.map +1 -1
  353. package/dist/number-input.cjs +24 -24
  354. package/dist/number-input.cjs.map +1 -1
  355. package/dist/number-input.js +41 -42
  356. package/dist/number-input.js.map +1 -1
  357. package/dist/otp-input.cjs +13 -13
  358. package/dist/otp-input.cjs.map +1 -1
  359. package/dist/otp-input.js +32 -33
  360. package/dist/otp-input.js.map +1 -1
  361. package/dist/overlay/command-palette/command-palette-items.cjs.map +1 -1
  362. package/dist/overlay/command-palette/command-palette-items.d.ts.map +1 -1
  363. package/dist/overlay/command-palette/command-palette-items.js.map +1 -1
  364. package/dist/overlay/command-palette/command-palette.css.cjs +1 -1
  365. package/dist/overlay/command-palette/command-palette.css.cjs.map +1 -1
  366. package/dist/overlay/command-palette/command-palette.css.js +1 -1
  367. package/dist/overlay/command-palette/command-palette.css.js.map +1 -1
  368. package/dist/overlay/command-palette/command-palette.d.ts.map +1 -1
  369. package/dist/overlay/dialog/dialog.css.cjs +1 -1
  370. package/dist/overlay/dialog/dialog.css.js +1 -1
  371. package/dist/overlay/dialog/dialog.d.ts.map +1 -1
  372. package/dist/overlay/drawer/drawer.css.cjs +1 -1
  373. package/dist/overlay/drawer/drawer.css.js +1 -1
  374. package/dist/overlay/drawer/drawer.d.ts +2 -2
  375. package/dist/overlay/drawer/drawer.d.ts.map +1 -1
  376. package/dist/overlay/index.d.ts +6 -6
  377. package/dist/overlay/index.d.ts.map +1 -1
  378. package/dist/overlay/menu/menu.css.cjs +1 -1
  379. package/dist/overlay/menu/menu.css.js +1 -1
  380. package/dist/overlay/menu/menu.d.ts +2 -2
  381. package/dist/overlay/menu/menu.d.ts.map +1 -1
  382. package/dist/overlay/navigation-menu/navigation-menu.d.ts.map +1 -1
  383. package/dist/overlay/popover/popover.d.ts +1 -1
  384. package/dist/overlay/popover/popover.d.ts.map +1 -1
  385. package/dist/overlay/shared/use-dialog.cjs +1 -1
  386. package/dist/overlay/shared/use-dialog.cjs.map +1 -1
  387. package/dist/overlay/shared/use-dialog.d.ts.map +1 -1
  388. package/dist/overlay/shared/use-dialog.js +4 -5
  389. package/dist/overlay/shared/use-dialog.js.map +1 -1
  390. package/dist/overlay/shared/use-floating-trigger.cjs +1 -1
  391. package/dist/overlay/shared/use-floating-trigger.cjs.map +1 -1
  392. package/dist/overlay/shared/use-floating-trigger.d.ts.map +1 -1
  393. package/dist/overlay/shared/use-floating-trigger.js +1 -2
  394. package/dist/overlay/shared/use-floating-trigger.js.map +1 -1
  395. package/dist/overlay/tooltip/tooltip.d.ts +1 -1
  396. package/dist/overlay/tooltip/tooltip.d.ts.map +1 -1
  397. package/dist/pagination.cjs.map +1 -1
  398. package/dist/pagination.js.map +1 -1
  399. package/dist/popover.cjs +1 -1
  400. package/dist/popover.cjs.map +1 -1
  401. package/dist/popover.js +0 -1
  402. package/dist/popover.js.map +1 -1
  403. package/dist/progress.cjs.map +1 -1
  404. package/dist/progress.js.map +1 -1
  405. package/dist/radio-group.cjs +5 -5
  406. package/dist/radio-group.cjs.map +1 -1
  407. package/dist/radio-group.js +26 -27
  408. package/dist/radio-group.js.map +1 -1
  409. package/dist/radio.cjs +2 -2
  410. package/dist/radio.cjs.map +1 -1
  411. package/dist/radio.js +41 -41
  412. package/dist/radio.js.map +1 -1
  413. package/dist/rating.cjs +4 -4
  414. package/dist/rating.cjs.map +1 -1
  415. package/dist/rating.js +36 -36
  416. package/dist/rating.js.map +1 -1
  417. package/dist/refine.cjs +686 -686
  418. package/dist/refine.cjs.map +1 -1
  419. package/dist/refine.iife.js +686 -686
  420. package/dist/refine.iife.js.map +1 -1
  421. package/dist/refine.js +737 -737
  422. package/dist/refine.js.map +1 -1
  423. package/dist/select.cjs +42 -42
  424. package/dist/select.cjs.map +1 -1
  425. package/dist/select.js +146 -147
  426. package/dist/select.js.map +1 -1
  427. package/dist/separator.cjs.map +1 -1
  428. package/dist/separator.js.map +1 -1
  429. package/dist/sidebar.cjs +17 -17
  430. package/dist/sidebar.cjs.map +1 -1
  431. package/dist/sidebar.js +7 -8
  432. package/dist/sidebar.js.map +1 -1
  433. package/dist/skeleton.cjs +3 -3
  434. package/dist/skeleton.cjs.map +1 -1
  435. package/dist/skeleton.js +1 -2
  436. package/dist/skeleton.js.map +1 -1
  437. package/dist/slider.cjs +12 -12
  438. package/dist/slider.cjs.map +1 -1
  439. package/dist/slider.js +54 -55
  440. package/dist/slider.js.map +1 -1
  441. package/dist/step.cjs.map +1 -1
  442. package/dist/step.js.map +1 -1
  443. package/dist/stepper.cjs +2 -2
  444. package/dist/stepper.cjs.map +1 -1
  445. package/dist/stepper.js +8 -7
  446. package/dist/stepper.js.map +1 -1
  447. package/dist/styles/index.d.ts +2 -2
  448. package/dist/styles/index.d.ts.map +1 -1
  449. package/dist/styles/preflight.css +1 -1
  450. package/dist/styles/theme.css +15 -30
  451. package/dist/switch.cjs +3 -3
  452. package/dist/switch.cjs.map +1 -1
  453. package/dist/switch.js +28 -28
  454. package/dist/switch.js.map +1 -1
  455. package/dist/tab-item.cjs +2 -2
  456. package/dist/tab-item.cjs.map +1 -1
  457. package/dist/tab-item.js +21 -21
  458. package/dist/tab-item.js.map +1 -1
  459. package/dist/tab-panel.cjs +2 -2
  460. package/dist/tab-panel.cjs.map +1 -1
  461. package/dist/tab-panel.js +9 -9
  462. package/dist/tab-panel.js.map +1 -1
  463. package/dist/table.cjs +1 -1
  464. package/dist/table.cjs.map +1 -1
  465. package/dist/table.js +1 -1
  466. package/dist/table.js.map +1 -1
  467. package/dist/tabs.cjs +6 -6
  468. package/dist/tabs.cjs.map +1 -1
  469. package/dist/tabs.js +14 -15
  470. package/dist/tabs.js.map +1 -1
  471. package/dist/textarea.cjs +11 -11
  472. package/dist/textarea.cjs.map +1 -1
  473. package/dist/textarea.js +59 -59
  474. package/dist/textarea.js.map +1 -1
  475. package/dist/time-picker.cjs.map +1 -1
  476. package/dist/time-picker.js.map +1 -1
  477. package/dist/toast.cjs +16 -16
  478. package/dist/toast.cjs.map +1 -1
  479. package/dist/toast.js +20 -21
  480. package/dist/toast.js.map +1 -1
  481. package/dist/tooltip.cjs.map +1 -1
  482. package/dist/tooltip.js.map +1 -1
  483. package/dist/typing-indicator.cjs +1 -1
  484. package/dist/typing-indicator.cjs.map +1 -1
  485. package/dist/typing-indicator.js +1 -1
  486. package/dist/typing-indicator.js.map +1 -1
  487. package/package.json +96 -97
@@ -1 +1 @@
1
- {"version":3,"file":"use-floating-trigger.js","names":[],"sources":["../../../src/overlay/shared/use-floating-trigger.ts"],"sourcesContent":["import type { Placement } from '@vielzeug/orbit';\n\nimport { computePosition, flip, offset, shift } from '@vielzeug/orbit';\nimport { type Readable, type Signal, signal } from '@vielzeug/ripple';\nimport { watch } from '@vielzeug/ripple/watch';\n\nimport {\n createOutsidePointerDismissal,\n lifecycleSignal,\n type DialogCloseReason,\n type OverlayOpenReason,\n} from '../../core';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type FloatingTriggerType = 'click' | 'focus' | 'hover';\n\nexport type AriaBindFn = (triggerEl: HTMLElement) => () => void;\n\nexport type FloatingTriggerOptions = {\n /** ARIA binding factory: called with the trigger element, returns a cleanup. */\n bindTriggerAria: AriaBindFn;\n /** Initial uncontrolled visibility. Ignored when `openProp` is defined. */\n defaultOpen: Readable<boolean | undefined>;\n /** If true, disable all trigger interactions and close if open. */\n disabled: Readable<boolean>;\n /** Returns the host element (e.g. ore-popover) so slotted content clicks aren't treated as outside clicks. */\n getHost?: () => Element | null;\n /** Returns the panel element, if mounted. */\n getPanel: () => HTMLElement | null;\n /** Gap from reference to floating panel in px. Default: 8. Accepts a signal for runtime reactivity. */\n offset?: Readable<number | undefined> | number;\n /** Cleanup registrar from the component setup ctx. Automatically called on disconnect. */\n onCleanup: (fn: () => void) => void;\n /** Called when the popover closes. */\n onClose?: (reason: DialogCloseReason) => void;\n /** Called when the popover opens. */\n onOpen?: (reason: OverlayOpenReason) => void;\n /** Callback when resolved placement changes (useful for CSS attribute). */\n onPlacementChange?: (placement: Placement) => void;\n /** Controlled open prop. When defined, disables uncontrolled logic. */\n openProp: Readable<boolean | undefined>;\n /** Preferred placement. Default: 'bottom'. */\n placement: Readable<Placement>;\n /** Slot element or a factory to lazily find it. Resolved each time bindEvents runs. */\n slot: HTMLSlotElement | null | (() => HTMLSlotElement | null);\n /** Slot elements signal — used to rebind when slotted elements change. */\n slotElements: Readable<Element[]>;\n /** Which triggers are active. Set to empty array or omit if handling events manually. */\n triggers: Readable<FloatingTriggerType[]>;\n};\n\nexport type FloatingTriggerHandle = {\n /** Closes the panel. No-op if controlled. */\n close: (reason?: DialogCloseReason) => void;\n /**\n * Call inside `onMounted`. Sets up slot + trigger event watchers\n * and returns a cleanup function to pass back to the framework.\n */\n mount: () => () => void;\n /** Opens the panel. No-op if controlled. */\n open: (reason?: OverlayOpenReason) => void;\n /** Toggles the panel. No-op if controlled. */\n toggle: () => void;\n /** Manually trigger a position recalculation. */\n updatePosition: () => void;\n /** Whether the panel is currently visible. */\n visible: Signal<boolean>;\n};\n\n// ── Implementation ─────────────────────────────────────────────────────────────\n\n/**\n * Shared logic for floating-panel triggers (tooltip, popover).\n *\n * Handles:\n * - Slot-based trigger element detection and rebinding\n * - Event binding per trigger type (hover / focus / click)\n * - Floating-element positioning via `@vielzeug/orbit`\n * - Controlled mode via `openProp` watcher\n * - Keyboard escape dismissal\n *\n * ARIA binding is intentionally delegated to the caller via `bindTriggerAria`\n * so that tooltip (`describedby`) and popover (`expanded`/`controls`/…) can diverge.\n */\nexport const useFloatingTrigger = (options: FloatingTriggerOptions): FloatingTriggerHandle => {\n const {\n bindTriggerAria,\n defaultOpen,\n disabled,\n getPanel,\n onClose,\n onOpen,\n onPlacementChange,\n openProp,\n placement,\n slot,\n slotElements,\n triggers,\n } = options;\n\n const resolveSlot = (): HTMLSlotElement | null => (typeof slot === 'function' ? slot() : slot);\n const getOffset = (): number => {\n const o = options.offset;\n\n if (o == null) return 8;\n\n const val = typeof o === 'object' ? (o as Readable<number | undefined>).value : o;\n\n return val ?? 8;\n };\n const abortSignal = lifecycleSignal(options.onCleanup);\n const visible = signal(false);\n const isControlled = () => openProp.value !== undefined;\n let currentTrigger: HTMLElement | null = null;\n let triggerBinding: (() => void) | null = null;\n\n function updatePosition(): void {\n const panel = getPanel();\n const trigger =\n currentTrigger ?? (resolveSlot()?.assignedElements({ flatten: true })[0] as HTMLElement | undefined);\n\n if (!panel || !trigger) return;\n\n const previousTransition = panel.style.transition;\n const previousTransform = panel.style.transform;\n\n panel.style.transition = 'none';\n panel.style.transform = 'none';\n\n const result = computePosition(trigger, panel, {\n middleware: [offset(getOffset()), flip(), shift({ padding: 8 })],\n placement: placement.value,\n });\n\n panel.style.left = `${result.x}px`;\n panel.style.top = `${result.y}px`;\n panel.style.transition = previousTransition;\n panel.style.transform = previousTransform;\n panel.dataset.placement = result.placement;\n\n onPlacementChange?.(result.placement as Placement);\n }\n\n function showFloat(): void {\n visible.value = true;\n\n const panel = getPanel();\n\n if (panel) {\n panel.dataset.open = '';\n\n if ('showPopover' in panel) {\n try {\n if (!panel.matches(':popover-open')) panel.showPopover();\n } catch {\n // Popover API restricted (e.g. sandboxed iframe); data-open CSS fallback handles visibility.\n }\n }\n }\n\n updatePosition();\n }\n\n function hideFloat(): void {\n visible.value = false;\n\n const panel = getPanel();\n\n if (panel) {\n delete panel.dataset.open;\n\n if ('hidePopover' in panel) {\n try {\n if (panel.matches(':popover-open')) panel.hidePopover();\n } catch {\n // Popover API restricted; data-open removal handles visibility.\n }\n }\n }\n }\n\n function open(reason: OverlayOpenReason = 'programmatic'): void {\n if (isControlled() || disabled.value || visible.value) return;\n\n showFloat();\n onOpen?.(reason);\n }\n\n function close(reason: DialogCloseReason = 'trigger'): void {\n if (isControlled() || !visible.value) return;\n\n hideFloat();\n onClose?.(reason);\n }\n\n function toggle(): void {\n if (isControlled()) return;\n\n if (visible.value) close();\n else open('click');\n }\n\n function handleKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape') close('escape');\n }\n\n function handleFocusOut(e: FocusEvent): void {\n const next = e.relatedTarget as Element | null;\n const panel = getPanel();\n\n if (next && panel?.contains(next)) return;\n\n if (next && currentTrigger?.contains(next)) return;\n\n close('trigger');\n }\n\n const bindEvents = (): void => {\n triggerBinding?.();\n triggerBinding = null;\n\n const triggerEl = resolveSlot()?.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n if (!triggerEl) {\n currentTrigger = null;\n\n return;\n }\n\n currentTrigger = triggerEl;\n\n const removeAria = bindTriggerAria(triggerEl);\n const cleanups: Array<() => void> = [];\n\n const add = (\n target: EventTarget,\n event: string,\n listener: EventListener,\n eventOptions?: AddEventListenerOptions,\n ): void => {\n target.addEventListener(event, listener, eventOptions);\n cleanups.push(() => target.removeEventListener(event, listener, eventOptions));\n };\n\n const t = triggers.value;\n\n if (t.includes('click')) {\n add(triggerEl, 'click', toggle as EventListener);\n }\n\n if (t.includes('hover')) {\n add(triggerEl, 'pointerenter', () => open('hover'));\n add(triggerEl, 'pointerleave', () => close('trigger'));\n\n const panelEl = getPanel();\n\n if (panelEl) {\n add(panelEl, 'pointerenter', () => open('hover'));\n add(panelEl, 'pointerleave', () => close('trigger'));\n }\n }\n\n if (t.includes('focus')) {\n add(triggerEl, 'focusin', () => open('focus'));\n add(triggerEl, 'focusout', handleFocusOut as EventListener);\n\n const panelEl = getPanel();\n\n if (panelEl) add(panelEl, 'focusout', handleFocusOut as EventListener);\n }\n\n add(document, 'keydown', handleKeydown as EventListener);\n\n triggerBinding = () => {\n removeAria();\n\n for (const cleanup of cleanups) cleanup();\n\n currentTrigger = null;\n };\n };\n\n const stopOutsidePointerDismissal = createOutsidePointerDismissal({\n getTargets: () => [currentTrigger, getPanel(), options.getHost?.()],\n isActive: () => visible.value && triggers.value.includes('click'),\n onDismiss: () => close('outsideClick'),\n signal: abortSignal,\n });\n\n const mount = (): (() => void) => {\n let initializedOpenProp = false;\n const triggerSlot = resolveSlot();\n const rebind = (): void => {\n queueMicrotask(() => {\n if (!abortSignal.aborted) bindEvents();\n });\n };\n\n triggerSlot?.addEventListener('slotchange', rebind);\n rebind();\n watch(slotElements, bindEvents, { immediate: true });\n\n watch(\n openProp,\n (openVal) => {\n if (openVal === undefined || openVal === null) {\n if (initializedOpenProp && visible.value) {\n hideFloat();\n onClose?.('programmatic');\n }\n\n initializedOpenProp = true;\n\n return;\n }\n\n initializedOpenProp = true;\n\n if (openVal) {\n showFloat();\n onOpen?.('programmatic');\n } else if (visible.value) {\n hideFloat();\n onClose?.('programmatic');\n }\n },\n { immediate: true },\n );\n\n if (openProp.value === undefined && defaultOpen.value) {\n showFloat();\n onOpen?.('programmatic');\n }\n\n watch(disabled, (isNowDisabled) => {\n if (isNowDisabled) close('programmatic');\n });\n\n return () => {\n triggerSlot?.removeEventListener('slotchange', rebind);\n triggerBinding?.();\n triggerBinding = null;\n\n const panel = getPanel();\n\n if (panel) {\n delete panel.dataset.open;\n\n if ('hidePopover' in panel) {\n try {\n if (panel.matches(':popover-open')) panel.hidePopover();\n } catch {\n // Popover API restricted; data-open removal handles visibility.\n }\n }\n }\n\n stopOutsidePointerDismissal();\n };\n };\n\n return { close, mount, open, toggle, updatePosition, visible };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-floating-trigger.js","names":[],"sources":["../../../src/overlay/shared/use-floating-trigger.ts"],"sourcesContent":["import type { Placement } from '@vielzeug/orbit';\n\nimport { computePosition, flip, offset, shift } from '@vielzeug/orbit';\nimport { type Readable, type Signal, signal, watch } from '@vielzeug/ripple';\n\nimport {\n createOutsidePointerDismissal,\n type DialogCloseReason,\n lifecycleSignal,\n type OverlayOpenReason,\n} from '../../core';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type FloatingTriggerType = 'click' | 'focus' | 'hover';\n\nexport type AriaBindFn = (triggerEl: HTMLElement) => () => void;\n\nexport type FloatingTriggerOptions = {\n /** ARIA binding factory: called with the trigger element, returns a cleanup. */\n bindTriggerAria: AriaBindFn;\n /** Initial uncontrolled visibility. Ignored when `openProp` is defined. */\n defaultOpen: Readable<boolean | undefined>;\n /** If true, disable all trigger interactions and close if open. */\n disabled: Readable<boolean>;\n /** Returns the host element (e.g. ore-popover) so slotted content clicks aren't treated as outside clicks. */\n getHost?: () => Element | null;\n /** Returns the panel element, if mounted. */\n getPanel: () => HTMLElement | null;\n /** Gap from reference to floating panel in px. Default: 8. Accepts a signal for runtime reactivity. */\n offset?: Readable<number | undefined> | number;\n /** Cleanup registrar from the component setup ctx. Automatically called on disconnect. */\n onCleanup: (fn: () => void) => void;\n /** Called when the popover closes. */\n onClose?: (reason: DialogCloseReason) => void;\n /** Called when the popover opens. */\n onOpen?: (reason: OverlayOpenReason) => void;\n /** Callback when resolved placement changes (useful for CSS attribute). */\n onPlacementChange?: (placement: Placement) => void;\n /** Controlled open prop. When defined, disables uncontrolled logic. */\n openProp: Readable<boolean | undefined>;\n /** Preferred placement. Default: 'bottom'. */\n placement: Readable<Placement>;\n /** Slot element or a factory to lazily find it. Resolved each time bindEvents runs. */\n slot: HTMLSlotElement | null | (() => HTMLSlotElement | null);\n /** Slot elements signal — used to rebind when slotted elements change. */\n slotElements: Readable<Element[]>;\n /** Which triggers are active. Set to empty array or omit if handling events manually. */\n triggers: Readable<FloatingTriggerType[]>;\n};\n\nexport type FloatingTriggerHandle = {\n /** Closes the panel. No-op if controlled. */\n close: (reason?: DialogCloseReason) => void;\n /**\n * Call inside `onMounted`. Sets up slot + trigger event watchers\n * and returns a cleanup function to pass back to the framework.\n */\n mount: () => () => void;\n /** Opens the panel. No-op if controlled. */\n open: (reason?: OverlayOpenReason) => void;\n /** Toggles the panel. No-op if controlled. */\n toggle: () => void;\n /** Manually trigger a position recalculation. */\n updatePosition: () => void;\n /** Whether the panel is currently visible. */\n visible: Signal<boolean>;\n};\n\n// ── Implementation ─────────────────────────────────────────────────────────────\n\n/**\n * Shared logic for floating-panel triggers (tooltip, popover).\n *\n * Handles:\n * - Slot-based trigger element detection and rebinding\n * - Event binding per trigger type (hover / focus / click)\n * - Floating-element positioning via `@vielzeug/orbit`\n * - Controlled mode via `openProp` watcher\n * - Keyboard escape dismissal\n *\n * ARIA binding is intentionally delegated to the caller via `bindTriggerAria`\n * so that tooltip (`describedby`) and popover (`expanded`/`controls`/…) can diverge.\n */\nexport const useFloatingTrigger = (options: FloatingTriggerOptions): FloatingTriggerHandle => {\n const {\n bindTriggerAria,\n defaultOpen,\n disabled,\n getPanel,\n onClose,\n onOpen,\n onPlacementChange,\n openProp,\n placement,\n slot,\n slotElements,\n triggers,\n } = options;\n\n const resolveSlot = (): HTMLSlotElement | null => (typeof slot === 'function' ? slot() : slot);\n const getOffset = (): number => {\n const o = options.offset;\n\n if (o == null) return 8;\n\n const val = typeof o === 'object' ? (o as Readable<number | undefined>).value : o;\n\n return val ?? 8;\n };\n const abortSignal = lifecycleSignal(options.onCleanup);\n const visible = signal(false);\n const isControlled = () => openProp.value !== undefined;\n let currentTrigger: HTMLElement | null = null;\n let triggerBinding: (() => void) | null = null;\n\n function updatePosition(): void {\n const panel = getPanel();\n const trigger =\n currentTrigger ?? (resolveSlot()?.assignedElements({ flatten: true })[0] as HTMLElement | undefined);\n\n if (!panel || !trigger) return;\n\n const previousTransition = panel.style.transition;\n const previousTransform = panel.style.transform;\n\n panel.style.transition = 'none';\n panel.style.transform = 'none';\n\n const result = computePosition(trigger, panel, {\n middleware: [offset(getOffset()), flip(), shift({ padding: 8 })],\n placement: placement.value,\n });\n\n panel.style.left = `${result.x}px`;\n panel.style.top = `${result.y}px`;\n panel.style.transition = previousTransition;\n panel.style.transform = previousTransform;\n panel.dataset.placement = result.placement;\n\n onPlacementChange?.(result.placement as Placement);\n }\n\n function showFloat(): void {\n visible.value = true;\n\n const panel = getPanel();\n\n if (panel) {\n panel.dataset.open = '';\n\n if ('showPopover' in panel) {\n try {\n if (!panel.matches(':popover-open')) panel.showPopover();\n } catch {\n // Popover API restricted (e.g. sandboxed iframe); data-open CSS fallback handles visibility.\n }\n }\n }\n\n updatePosition();\n }\n\n function hideFloat(): void {\n visible.value = false;\n\n const panel = getPanel();\n\n if (panel) {\n delete panel.dataset.open;\n\n if ('hidePopover' in panel) {\n try {\n if (panel.matches(':popover-open')) panel.hidePopover();\n } catch {\n // Popover API restricted; data-open removal handles visibility.\n }\n }\n }\n }\n\n function open(reason: OverlayOpenReason = 'programmatic'): void {\n if (isControlled() || disabled.value || visible.value) return;\n\n showFloat();\n onOpen?.(reason);\n }\n\n function close(reason: DialogCloseReason = 'trigger'): void {\n if (isControlled() || !visible.value) return;\n\n hideFloat();\n onClose?.(reason);\n }\n\n function toggle(): void {\n if (isControlled()) return;\n\n if (visible.value) close();\n else open('click');\n }\n\n function handleKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape') close('escape');\n }\n\n function handleFocusOut(e: FocusEvent): void {\n const next = e.relatedTarget as Element | null;\n const panel = getPanel();\n\n if (next && panel?.contains(next)) return;\n\n if (next && currentTrigger?.contains(next)) return;\n\n close('trigger');\n }\n\n const bindEvents = (): void => {\n triggerBinding?.();\n triggerBinding = null;\n\n const triggerEl = resolveSlot()?.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n if (!triggerEl) {\n currentTrigger = null;\n\n return;\n }\n\n currentTrigger = triggerEl;\n\n const removeAria = bindTriggerAria(triggerEl);\n const cleanups: Array<() => void> = [];\n\n const add = (\n target: EventTarget,\n event: string,\n listener: EventListener,\n eventOptions?: AddEventListenerOptions,\n ): void => {\n target.addEventListener(event, listener, eventOptions);\n cleanups.push(() => target.removeEventListener(event, listener, eventOptions));\n };\n\n const t = triggers.value;\n\n if (t.includes('click')) {\n add(triggerEl, 'click', toggle as EventListener);\n }\n\n if (t.includes('hover')) {\n add(triggerEl, 'pointerenter', () => open('hover'));\n add(triggerEl, 'pointerleave', () => close('trigger'));\n\n const panelEl = getPanel();\n\n if (panelEl) {\n add(panelEl, 'pointerenter', () => open('hover'));\n add(panelEl, 'pointerleave', () => close('trigger'));\n }\n }\n\n if (t.includes('focus')) {\n add(triggerEl, 'focusin', () => open('focus'));\n add(triggerEl, 'focusout', handleFocusOut as EventListener);\n\n const panelEl = getPanel();\n\n if (panelEl) add(panelEl, 'focusout', handleFocusOut as EventListener);\n }\n\n add(document, 'keydown', handleKeydown as EventListener);\n\n triggerBinding = () => {\n removeAria();\n\n for (const cleanup of cleanups) cleanup();\n\n currentTrigger = null;\n };\n };\n\n const stopOutsidePointerDismissal = createOutsidePointerDismissal({\n getTargets: () => [currentTrigger, getPanel(), options.getHost?.()],\n isActive: () => visible.value && triggers.value.includes('click'),\n onDismiss: () => close('outsideClick'),\n signal: abortSignal,\n });\n\n const mount = (): (() => void) => {\n let initializedOpenProp = false;\n const triggerSlot = resolveSlot();\n const rebind = (): void => {\n queueMicrotask(() => {\n if (!abortSignal.aborted) bindEvents();\n });\n };\n\n triggerSlot?.addEventListener('slotchange', rebind);\n rebind();\n watch(slotElements, bindEvents, { immediate: true });\n\n watch(\n openProp,\n (openVal) => {\n if (openVal === undefined || openVal === null) {\n if (initializedOpenProp && visible.value) {\n hideFloat();\n onClose?.('programmatic');\n }\n\n initializedOpenProp = true;\n\n return;\n }\n\n initializedOpenProp = true;\n\n if (openVal) {\n showFloat();\n onOpen?.('programmatic');\n } else if (visible.value) {\n hideFloat();\n onClose?.('programmatic');\n }\n },\n { immediate: true },\n );\n\n if (openProp.value === undefined && defaultOpen.value) {\n showFloat();\n onOpen?.('programmatic');\n }\n\n watch(disabled, (isNowDisabled) => {\n if (isNowDisabled) close('programmatic');\n });\n\n return () => {\n triggerSlot?.removeEventListener('slotchange', rebind);\n triggerBinding?.();\n triggerBinding = null;\n\n const panel = getPanel();\n\n if (panel) {\n delete panel.dataset.open;\n\n if ('hidePopover' in panel) {\n try {\n if (panel.matches(':popover-open')) panel.hidePopover();\n } catch {\n // Popover API restricted; data-open removal handles visibility.\n }\n }\n }\n\n stopOutsidePointerDismissal();\n };\n };\n\n return { close, mount, open, toggle, updatePosition, visible };\n};\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import type { ComponentSize } from '../../types';
2
1
  import { type OverlayOpenChangeDetail } from '../../core';
2
+ import type { ComponentSize } from '../../types';
3
3
  type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
4
4
  /** Tooltip component properties */
5
5
  export type OreTooltipEvents = {
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../../src/overlay/tooltip/tooltip.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,KAAK,uBAAuB,EAA+C,MAAM,YAAY,CAAC;AAMvG,KAAK,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAqB5D,mCAAmC;AACnC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,uBAAuB,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8CAA8C;IAC9C,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,mBAAmB;IACnB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,WAAW,EAAG,aAAsB,CAAC"}
1
+ {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../../src/overlay/tooltip/tooltip.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,KAAK,uBAAuB,EAA+C,MAAM,YAAY,CAAC;AAGvG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,KAAK,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAqB5D,mCAAmC;AACnC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,uBAAuB,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8CAA8C;IAC9C,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,mBAAmB;IACnB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,WAAW,EAAG,aAAsB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.cjs","names":[],"sources":["../src/content/pagination/pagination.ts"],"sourcesContent":["import { define, html, prop, getHost, useEmit } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport '../icon/icon';\nimport '../../inputs/button/button';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, sizeVariantMixin } from '../../styles';\nimport componentStyles from './pagination.css?inline';\n\nexport type OrePaginationEvents = {\n change: { page: number };\n};\n\nexport type OrePaginationProps = {\n color?: ThemeColor;\n label?: string;\n page?: number;\n 'show-first-last'?: boolean;\n 'show-prev-next'?: boolean;\n siblings?: number;\n size?: ComponentSize;\n 'total-pages'?: number;\n variant?: VisualVariant;\n};\n\nfunction buildPageRange(\n currentPage: number,\n totalPages: number,\n siblings: number,\n): Array<number | 'ellipsis-start' | 'ellipsis-end'> {\n const BOUNDARY = 1; // always show first and last page\n const total = totalPages;\n const pages: Array<number | 'ellipsis-start' | 'ellipsis-end'> = [];\n\n // If total is small enough, show all pages\n if (total <= 2 * BOUNDARY + 2 * siblings + 3) {\n return Array.from({ length: total }, (_, i) => i + 1);\n }\n\n const leftSibling = Math.max(currentPage - siblings, BOUNDARY + 1);\n const rightSibling = Math.min(currentPage + siblings, total - BOUNDARY);\n\n pages.push(1);\n\n if (leftSibling > BOUNDARY + 2) pages.push('ellipsis-start');\n else if (leftSibling === BOUNDARY + 2) pages.push(BOUNDARY + 1);\n\n for (let i = leftSibling; i <= rightSibling; i++) pages.push(i);\n\n if (rightSibling < total - BOUNDARY - 1) pages.push('ellipsis-end');\n else if (rightSibling === total - BOUNDARY - 1) pages.push(total - BOUNDARY);\n\n pages.push(total);\n\n return pages;\n}\n\n/**\n * Page-based navigation control.\n *\n * @element ore-pagination\n *\n * @attr {number} page - Current page (1-indexed, default: 1)\n * @attr {number} total-pages - Total number of pages (required)\n * @attr {number} siblings - Sibling pages around current (default: 1)\n * @attr {boolean} show-first-last - Show first/last page buttons (default: false)\n * @attr {boolean} show-prev-next - Show prev/next buttons (default: false)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant for nav buttons: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text' | 'frost' (default: 'ghost')\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav label (default: 'Pagination')\n *\n * @fires change - Emitted when the page changes, with { page: number }\n *\n * @cssprop --pagination-item-size - Width/height of each item\n * @cssprop --pagination-gap - Gap between items\n * @cssprop --pagination-radius - Border radius of items\n *\n * @part page-btn - Page button.\n * @part nav - Navigation container.\n * @part list - List container.\n * @part first-btn - First page button.\n * @part prev-btn - Previous page button.\n * @part next-btn - Next page button.\n * @part last-btn - Last page button.\n * @example\n * ```html\n * <!-- Basic -->\n * <ore-pagination page=\"3\" total-pages=\"10\" color=\"primary\"></ore-pagination>\n *\n * <!-- With prev/next and first/last buttons -->\n * <ore-pagination page=\"5\" total-pages=\"20\" show-prev-next show-first-last siblings=\"2\"></ore-pagination>\n *\n * <!-- Compact size -->\n * <ore-pagination page=\"1\" total-pages=\"5\" size=\"sm\" variant=\"ghost\"></ore-pagination>\n * ```\n */\nexport const PAGINATION_TAG = 'ore-pagination' as const;\ndefine<OrePaginationProps>(PAGINATION_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n label: prop.string('Pagination'),\n page: prop.number(1),\n 'show-first-last': prop.bool(false),\n 'show-prev-next': prop.bool(false),\n siblings: prop.number(1),\n 'total-pages': prop.number(1),\n variant: prop.string<VisualVariant>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OrePaginationEvents>();\n\n function goTo(page: number) {\n const total = props['total-pages'].value || 1;\n const next = Math.min(Math.max(1, page), total);\n\n if (next === props.page.value) return;\n\n el.setAttribute('page', String(next));\n emit('change', { page: next });\n }\n\n const pageItems = computed(() =>\n buildPageRange(props.page.value || 1, props['total-pages'].value || 1, props.siblings.value ?? 1),\n );\n\n const isFirst = computed(() => (props.page.value || 1) <= 1);\n const isLast = computed(() => (props.page.value || 1) >= (props['total-pages'].value || 1));\n\n return html`\n <nav aria-label=\"${props.label}\" part=\"nav\">\n <ol class=\"pagination\" part=\"list\">\n ${() =>\n props['show-first-last'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"first-btn\"\n aria-label=\"First page\"\n ?disabled=${isFirst}\n @click=${() => goTo(1)}>\n <ore-icon name=\"chevrons-left\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n ${() =>\n props['show-prev-next'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"prev-btn\"\n aria-label=\"Previous page\"\n ?disabled=${isFirst}\n @click=${() => goTo((props.page.value || 1) - 1)}>\n <ore-icon name=\"chevron-left\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n <li style=\"display: contents;\">\n ${() =>\n pageItems.value.map((item) => {\n if (item === 'ellipsis-start' || item === 'ellipsis-end') {\n return html`\n <span class=\"ellipsis\" aria-hidden=\"true\">&hellip;</span>\n `;\n }\n\n const pg = item as number;\n const isCurrent = pg === (props.page.value || 1);\n const pgLabel = `Page ${pg}`;\n\n return isCurrent\n ? html`\n <button\n type=\"button\"\n part=\"page-btn\"\n aria-label=\"${pgLabel}\"\n aria-current=\"page\"\n @click=${() => goTo(pg)}>\n ${pg}\n </button>\n `\n : html`\n <button type=\"button\" part=\"page-btn\" aria-label=\"${pgLabel}\" @click=${() => goTo(pg)}>\n ${pg}\n </button>\n `;\n })}\n </li>\n ${() =>\n props['show-prev-next'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"next-btn\"\n aria-label=\"Next page\"\n ?disabled=${isLast}\n @click=${() => goTo((props.page.value || 1) + 1)}>\n <ore-icon name=\"chevron-right\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n ${() =>\n props['show-first-last'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"last-btn\"\n aria-label=\"Last page\"\n ?disabled=${isLast}\n @click=${() => goTo(props['total-pages'].value || 1)}>\n <ore-icon name=\"chevrons-right\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n </ol>\n </nav>\n `;\n },\n\n styles: [coarsePointerMixin, colorThemeMixin, sizeVariantMixin(), componentStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"pagination.cjs","names":[],"sources":["../src/content/pagination/pagination.ts"],"sourcesContent":["import { define, getHost, html, prop, useEmit } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport '../icon/icon';\nimport '../../inputs/button/button';\n\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\nimport componentStyles from './pagination.css?inline';\n\nexport type OrePaginationEvents = {\n change: { page: number };\n};\n\nexport type OrePaginationProps = {\n color?: ThemeColor;\n label?: string;\n page?: number;\n 'show-first-last'?: boolean;\n 'show-prev-next'?: boolean;\n siblings?: number;\n size?: ComponentSize;\n 'total-pages'?: number;\n variant?: VisualVariant;\n};\n\nfunction buildPageRange(\n currentPage: number,\n totalPages: number,\n siblings: number,\n): Array<number | 'ellipsis-start' | 'ellipsis-end'> {\n const BOUNDARY = 1; // always show first and last page\n const total = totalPages;\n const pages: Array<number | 'ellipsis-start' | 'ellipsis-end'> = [];\n\n // If total is small enough, show all pages\n if (total <= 2 * BOUNDARY + 2 * siblings + 3) {\n return Array.from({ length: total }, (_, i) => i + 1);\n }\n\n const leftSibling = Math.max(currentPage - siblings, BOUNDARY + 1);\n const rightSibling = Math.min(currentPage + siblings, total - BOUNDARY);\n\n pages.push(1);\n\n if (leftSibling > BOUNDARY + 2) pages.push('ellipsis-start');\n else if (leftSibling === BOUNDARY + 2) pages.push(BOUNDARY + 1);\n\n for (let i = leftSibling; i <= rightSibling; i++) pages.push(i);\n\n if (rightSibling < total - BOUNDARY - 1) pages.push('ellipsis-end');\n else if (rightSibling === total - BOUNDARY - 1) pages.push(total - BOUNDARY);\n\n pages.push(total);\n\n return pages;\n}\n\n/**\n * Page-based navigation control.\n *\n * @element ore-pagination\n *\n * @attr {number} page - Current page (1-indexed, default: 1)\n * @attr {number} total-pages - Total number of pages (required)\n * @attr {number} siblings - Sibling pages around current (default: 1)\n * @attr {boolean} show-first-last - Show first/last page buttons (default: false)\n * @attr {boolean} show-prev-next - Show prev/next buttons (default: false)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant for nav buttons: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text' | 'frost' (default: 'ghost')\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav label (default: 'Pagination')\n *\n * @fires change - Emitted when the page changes, with { page: number }\n *\n * @cssprop --pagination-item-size - Width/height of each item\n * @cssprop --pagination-gap - Gap between items\n * @cssprop --pagination-radius - Border radius of items\n *\n * @part page-btn - Page button.\n * @part nav - Navigation container.\n * @part list - List container.\n * @part first-btn - First page button.\n * @part prev-btn - Previous page button.\n * @part next-btn - Next page button.\n * @part last-btn - Last page button.\n * @example\n * ```html\n * <!-- Basic -->\n * <ore-pagination page=\"3\" total-pages=\"10\" color=\"primary\"></ore-pagination>\n *\n * <!-- With prev/next and first/last buttons -->\n * <ore-pagination page=\"5\" total-pages=\"20\" show-prev-next show-first-last siblings=\"2\"></ore-pagination>\n *\n * <!-- Compact size -->\n * <ore-pagination page=\"1\" total-pages=\"5\" size=\"sm\" variant=\"ghost\"></ore-pagination>\n * ```\n */\nexport const PAGINATION_TAG = 'ore-pagination' as const;\ndefine<OrePaginationProps>(PAGINATION_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n label: prop.string('Pagination'),\n page: prop.number(1),\n 'show-first-last': prop.bool(false),\n 'show-prev-next': prop.bool(false),\n siblings: prop.number(1),\n 'total-pages': prop.number(1),\n variant: prop.string<VisualVariant>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OrePaginationEvents>();\n\n function goTo(page: number) {\n const total = props['total-pages'].value || 1;\n const next = Math.min(Math.max(1, page), total);\n\n if (next === props.page.value) return;\n\n el.setAttribute('page', String(next));\n emit('change', { page: next });\n }\n\n const pageItems = computed(() =>\n buildPageRange(props.page.value || 1, props['total-pages'].value || 1, props.siblings.value ?? 1),\n );\n\n const isFirst = computed(() => (props.page.value || 1) <= 1);\n const isLast = computed(() => (props.page.value || 1) >= (props['total-pages'].value || 1));\n\n return html`\n <nav aria-label=\"${props.label}\" part=\"nav\">\n <ol class=\"pagination\" part=\"list\">\n ${() =>\n props['show-first-last'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"first-btn\"\n aria-label=\"First page\"\n ?disabled=${isFirst}\n @click=${() => goTo(1)}>\n <ore-icon name=\"chevrons-left\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n ${() =>\n props['show-prev-next'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"prev-btn\"\n aria-label=\"Previous page\"\n ?disabled=${isFirst}\n @click=${() => goTo((props.page.value || 1) - 1)}>\n <ore-icon name=\"chevron-left\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n <li style=\"display: contents;\">\n ${() =>\n pageItems.value.map((item) => {\n if (item === 'ellipsis-start' || item === 'ellipsis-end') {\n return html`\n <span class=\"ellipsis\" aria-hidden=\"true\">&hellip;</span>\n `;\n }\n\n const pg = item as number;\n const isCurrent = pg === (props.page.value || 1);\n const pgLabel = `Page ${pg}`;\n\n return isCurrent\n ? html`\n <button\n type=\"button\"\n part=\"page-btn\"\n aria-label=\"${pgLabel}\"\n aria-current=\"page\"\n @click=${() => goTo(pg)}>\n ${pg}\n </button>\n `\n : html`\n <button type=\"button\" part=\"page-btn\" aria-label=\"${pgLabel}\" @click=${() => goTo(pg)}>\n ${pg}\n </button>\n `;\n })}\n </li>\n ${() =>\n props['show-prev-next'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"next-btn\"\n aria-label=\"Next page\"\n ?disabled=${isLast}\n @click=${() => goTo((props.page.value || 1) + 1)}>\n <ore-icon name=\"chevron-right\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n ${() =>\n props['show-first-last'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"last-btn\"\n aria-label=\"Last page\"\n ?disabled=${isLast}\n @click=${() => goTo(props['total-pages'].value || 1)}>\n <ore-icon name=\"chevrons-right\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n </ol>\n </nav>\n `;\n },\n\n styles: [coarsePointerMixin, colorThemeMixin, sizeVariantMixin(), componentStyles],\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","names":[],"sources":["../src/content/pagination/pagination.ts"],"sourcesContent":["import { define, html, prop, getHost, useEmit } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport '../icon/icon';\nimport '../../inputs/button/button';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, sizeVariantMixin } from '../../styles';\nimport componentStyles from './pagination.css?inline';\n\nexport type OrePaginationEvents = {\n change: { page: number };\n};\n\nexport type OrePaginationProps = {\n color?: ThemeColor;\n label?: string;\n page?: number;\n 'show-first-last'?: boolean;\n 'show-prev-next'?: boolean;\n siblings?: number;\n size?: ComponentSize;\n 'total-pages'?: number;\n variant?: VisualVariant;\n};\n\nfunction buildPageRange(\n currentPage: number,\n totalPages: number,\n siblings: number,\n): Array<number | 'ellipsis-start' | 'ellipsis-end'> {\n const BOUNDARY = 1; // always show first and last page\n const total = totalPages;\n const pages: Array<number | 'ellipsis-start' | 'ellipsis-end'> = [];\n\n // If total is small enough, show all pages\n if (total <= 2 * BOUNDARY + 2 * siblings + 3) {\n return Array.from({ length: total }, (_, i) => i + 1);\n }\n\n const leftSibling = Math.max(currentPage - siblings, BOUNDARY + 1);\n const rightSibling = Math.min(currentPage + siblings, total - BOUNDARY);\n\n pages.push(1);\n\n if (leftSibling > BOUNDARY + 2) pages.push('ellipsis-start');\n else if (leftSibling === BOUNDARY + 2) pages.push(BOUNDARY + 1);\n\n for (let i = leftSibling; i <= rightSibling; i++) pages.push(i);\n\n if (rightSibling < total - BOUNDARY - 1) pages.push('ellipsis-end');\n else if (rightSibling === total - BOUNDARY - 1) pages.push(total - BOUNDARY);\n\n pages.push(total);\n\n return pages;\n}\n\n/**\n * Page-based navigation control.\n *\n * @element ore-pagination\n *\n * @attr {number} page - Current page (1-indexed, default: 1)\n * @attr {number} total-pages - Total number of pages (required)\n * @attr {number} siblings - Sibling pages around current (default: 1)\n * @attr {boolean} show-first-last - Show first/last page buttons (default: false)\n * @attr {boolean} show-prev-next - Show prev/next buttons (default: false)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant for nav buttons: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text' | 'frost' (default: 'ghost')\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav label (default: 'Pagination')\n *\n * @fires change - Emitted when the page changes, with { page: number }\n *\n * @cssprop --pagination-item-size - Width/height of each item\n * @cssprop --pagination-gap - Gap between items\n * @cssprop --pagination-radius - Border radius of items\n *\n * @part page-btn - Page button.\n * @part nav - Navigation container.\n * @part list - List container.\n * @part first-btn - First page button.\n * @part prev-btn - Previous page button.\n * @part next-btn - Next page button.\n * @part last-btn - Last page button.\n * @example\n * ```html\n * <!-- Basic -->\n * <ore-pagination page=\"3\" total-pages=\"10\" color=\"primary\"></ore-pagination>\n *\n * <!-- With prev/next and first/last buttons -->\n * <ore-pagination page=\"5\" total-pages=\"20\" show-prev-next show-first-last siblings=\"2\"></ore-pagination>\n *\n * <!-- Compact size -->\n * <ore-pagination page=\"1\" total-pages=\"5\" size=\"sm\" variant=\"ghost\"></ore-pagination>\n * ```\n */\nexport const PAGINATION_TAG = 'ore-pagination' as const;\ndefine<OrePaginationProps>(PAGINATION_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n label: prop.string('Pagination'),\n page: prop.number(1),\n 'show-first-last': prop.bool(false),\n 'show-prev-next': prop.bool(false),\n siblings: prop.number(1),\n 'total-pages': prop.number(1),\n variant: prop.string<VisualVariant>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OrePaginationEvents>();\n\n function goTo(page: number) {\n const total = props['total-pages'].value || 1;\n const next = Math.min(Math.max(1, page), total);\n\n if (next === props.page.value) return;\n\n el.setAttribute('page', String(next));\n emit('change', { page: next });\n }\n\n const pageItems = computed(() =>\n buildPageRange(props.page.value || 1, props['total-pages'].value || 1, props.siblings.value ?? 1),\n );\n\n const isFirst = computed(() => (props.page.value || 1) <= 1);\n const isLast = computed(() => (props.page.value || 1) >= (props['total-pages'].value || 1));\n\n return html`\n <nav aria-label=\"${props.label}\" part=\"nav\">\n <ol class=\"pagination\" part=\"list\">\n ${() =>\n props['show-first-last'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"first-btn\"\n aria-label=\"First page\"\n ?disabled=${isFirst}\n @click=${() => goTo(1)}>\n <ore-icon name=\"chevrons-left\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n ${() =>\n props['show-prev-next'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"prev-btn\"\n aria-label=\"Previous page\"\n ?disabled=${isFirst}\n @click=${() => goTo((props.page.value || 1) - 1)}>\n <ore-icon name=\"chevron-left\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n <li style=\"display: contents;\">\n ${() =>\n pageItems.value.map((item) => {\n if (item === 'ellipsis-start' || item === 'ellipsis-end') {\n return html`\n <span class=\"ellipsis\" aria-hidden=\"true\">&hellip;</span>\n `;\n }\n\n const pg = item as number;\n const isCurrent = pg === (props.page.value || 1);\n const pgLabel = `Page ${pg}`;\n\n return isCurrent\n ? html`\n <button\n type=\"button\"\n part=\"page-btn\"\n aria-label=\"${pgLabel}\"\n aria-current=\"page\"\n @click=${() => goTo(pg)}>\n ${pg}\n </button>\n `\n : html`\n <button type=\"button\" part=\"page-btn\" aria-label=\"${pgLabel}\" @click=${() => goTo(pg)}>\n ${pg}\n </button>\n `;\n })}\n </li>\n ${() =>\n props['show-prev-next'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"next-btn\"\n aria-label=\"Next page\"\n ?disabled=${isLast}\n @click=${() => goTo((props.page.value || 1) + 1)}>\n <ore-icon name=\"chevron-right\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n ${() =>\n props['show-first-last'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"last-btn\"\n aria-label=\"Last page\"\n ?disabled=${isLast}\n @click=${() => goTo(props['total-pages'].value || 1)}>\n <ore-icon name=\"chevrons-right\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n </ol>\n </nav>\n `;\n },\n\n styles: [coarsePointerMixin, colorThemeMixin, sizeVariantMixin(), componentStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"pagination.js","names":[],"sources":["../src/content/pagination/pagination.ts"],"sourcesContent":["import { define, getHost, html, prop, useEmit } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport '../icon/icon';\nimport '../../inputs/button/button';\n\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\nimport componentStyles from './pagination.css?inline';\n\nexport type OrePaginationEvents = {\n change: { page: number };\n};\n\nexport type OrePaginationProps = {\n color?: ThemeColor;\n label?: string;\n page?: number;\n 'show-first-last'?: boolean;\n 'show-prev-next'?: boolean;\n siblings?: number;\n size?: ComponentSize;\n 'total-pages'?: number;\n variant?: VisualVariant;\n};\n\nfunction buildPageRange(\n currentPage: number,\n totalPages: number,\n siblings: number,\n): Array<number | 'ellipsis-start' | 'ellipsis-end'> {\n const BOUNDARY = 1; // always show first and last page\n const total = totalPages;\n const pages: Array<number | 'ellipsis-start' | 'ellipsis-end'> = [];\n\n // If total is small enough, show all pages\n if (total <= 2 * BOUNDARY + 2 * siblings + 3) {\n return Array.from({ length: total }, (_, i) => i + 1);\n }\n\n const leftSibling = Math.max(currentPage - siblings, BOUNDARY + 1);\n const rightSibling = Math.min(currentPage + siblings, total - BOUNDARY);\n\n pages.push(1);\n\n if (leftSibling > BOUNDARY + 2) pages.push('ellipsis-start');\n else if (leftSibling === BOUNDARY + 2) pages.push(BOUNDARY + 1);\n\n for (let i = leftSibling; i <= rightSibling; i++) pages.push(i);\n\n if (rightSibling < total - BOUNDARY - 1) pages.push('ellipsis-end');\n else if (rightSibling === total - BOUNDARY - 1) pages.push(total - BOUNDARY);\n\n pages.push(total);\n\n return pages;\n}\n\n/**\n * Page-based navigation control.\n *\n * @element ore-pagination\n *\n * @attr {number} page - Current page (1-indexed, default: 1)\n * @attr {number} total-pages - Total number of pages (required)\n * @attr {number} siblings - Sibling pages around current (default: 1)\n * @attr {boolean} show-first-last - Show first/last page buttons (default: false)\n * @attr {boolean} show-prev-next - Show prev/next buttons (default: false)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant for nav buttons: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text' | 'frost' (default: 'ghost')\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav label (default: 'Pagination')\n *\n * @fires change - Emitted when the page changes, with { page: number }\n *\n * @cssprop --pagination-item-size - Width/height of each item\n * @cssprop --pagination-gap - Gap between items\n * @cssprop --pagination-radius - Border radius of items\n *\n * @part page-btn - Page button.\n * @part nav - Navigation container.\n * @part list - List container.\n * @part first-btn - First page button.\n * @part prev-btn - Previous page button.\n * @part next-btn - Next page button.\n * @part last-btn - Last page button.\n * @example\n * ```html\n * <!-- Basic -->\n * <ore-pagination page=\"3\" total-pages=\"10\" color=\"primary\"></ore-pagination>\n *\n * <!-- With prev/next and first/last buttons -->\n * <ore-pagination page=\"5\" total-pages=\"20\" show-prev-next show-first-last siblings=\"2\"></ore-pagination>\n *\n * <!-- Compact size -->\n * <ore-pagination page=\"1\" total-pages=\"5\" size=\"sm\" variant=\"ghost\"></ore-pagination>\n * ```\n */\nexport const PAGINATION_TAG = 'ore-pagination' as const;\ndefine<OrePaginationProps>(PAGINATION_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n label: prop.string('Pagination'),\n page: prop.number(1),\n 'show-first-last': prop.bool(false),\n 'show-prev-next': prop.bool(false),\n siblings: prop.number(1),\n 'total-pages': prop.number(1),\n variant: prop.string<VisualVariant>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OrePaginationEvents>();\n\n function goTo(page: number) {\n const total = props['total-pages'].value || 1;\n const next = Math.min(Math.max(1, page), total);\n\n if (next === props.page.value) return;\n\n el.setAttribute('page', String(next));\n emit('change', { page: next });\n }\n\n const pageItems = computed(() =>\n buildPageRange(props.page.value || 1, props['total-pages'].value || 1, props.siblings.value ?? 1),\n );\n\n const isFirst = computed(() => (props.page.value || 1) <= 1);\n const isLast = computed(() => (props.page.value || 1) >= (props['total-pages'].value || 1));\n\n return html`\n <nav aria-label=\"${props.label}\" part=\"nav\">\n <ol class=\"pagination\" part=\"list\">\n ${() =>\n props['show-first-last'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"first-btn\"\n aria-label=\"First page\"\n ?disabled=${isFirst}\n @click=${() => goTo(1)}>\n <ore-icon name=\"chevrons-left\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n ${() =>\n props['show-prev-next'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"prev-btn\"\n aria-label=\"Previous page\"\n ?disabled=${isFirst}\n @click=${() => goTo((props.page.value || 1) - 1)}>\n <ore-icon name=\"chevron-left\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n <li style=\"display: contents;\">\n ${() =>\n pageItems.value.map((item) => {\n if (item === 'ellipsis-start' || item === 'ellipsis-end') {\n return html`\n <span class=\"ellipsis\" aria-hidden=\"true\">&hellip;</span>\n `;\n }\n\n const pg = item as number;\n const isCurrent = pg === (props.page.value || 1);\n const pgLabel = `Page ${pg}`;\n\n return isCurrent\n ? html`\n <button\n type=\"button\"\n part=\"page-btn\"\n aria-label=\"${pgLabel}\"\n aria-current=\"page\"\n @click=${() => goTo(pg)}>\n ${pg}\n </button>\n `\n : html`\n <button type=\"button\" part=\"page-btn\" aria-label=\"${pgLabel}\" @click=${() => goTo(pg)}>\n ${pg}\n </button>\n `;\n })}\n </li>\n ${() =>\n props['show-prev-next'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"next-btn\"\n aria-label=\"Next page\"\n ?disabled=${isLast}\n @click=${() => goTo((props.page.value || 1) + 1)}>\n <ore-icon name=\"chevron-right\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n ${() =>\n props['show-first-last'].value\n ? html`\n <li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"last-btn\"\n aria-label=\"Last page\"\n ?disabled=${isLast}\n @click=${() => goTo(props['total-pages'].value || 1)}>\n <ore-icon name=\"chevrons-right\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n </button>\n </li>\n `\n : ''}\n </ol>\n </nav>\n `;\n },\n\n styles: [coarsePointerMixin, colorThemeMixin, sizeVariantMixin(), componentStyles],\n});\n"],"mappings":";;;;;;;;AA2BA,SAAS,EACP,GACA,GACA,GACmD;CACnD,IACM,IAAQ,GACR,IAA2D,CAAC;CAGlE,IAAI,KAAS,IAAe,IAAI,IAAW,GACzC,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAGtD,IAAM,IAAc,KAAK,IAAI,IAAc,GAAU,CAAY,GAC3D,IAAe,KAAK,IAAI,IAAc,GAAU,IAAQ,CAAQ;CAItE,AAFA,EAAM,KAAK,CAAC,GAER,IAAc,IAAc,EAAM,KAAK,gBAAgB,IAClD,MAAgB,KAAc,EAAM,KAAK,CAAY;CAE9D,KAAK,IAAI,IAAI,GAAa,KAAK,GAAc,KAAK,EAAM,KAAK,CAAC;CAO9D,OALI,IAAe,IAAQ,IAAW,IAAG,EAAM,KAAK,cAAc,IACzD,MAAiB,IAAQ,IAAW,KAAG,EAAM,KAAK,IAAQ,CAAQ,GAE3E,EAAM,KAAK,CAAK,GAET;AACT;AA0CA,IAAa,IAAiB;AAC9B,EAA2B,GAAgB;CACzC,OAAO;EACL,GAAG;EACH,GAAG;EACH,OAAO,EAAK,OAAO,YAAY;EAC/B,MAAM,EAAK,OAAO,CAAC;EACnB,mBAAmB,EAAK,KAAK,EAAK;EAClC,kBAAkB,EAAK,KAAK,EAAK;EACjC,UAAU,EAAK,OAAO,CAAC;EACvB,eAAe,EAAK,OAAO,CAAC;EAC5B,SAAS,EAAK,OAAsB;CACtC;CACA,MAAM,GAAO;EACX,IAAM,IAAK,EAAQ,GACb,IAAO,EAA6B;EAE1C,SAAS,EAAK,GAAc;GAC1B,IAAM,IAAQ,EAAM,cAAc,CAAC,SAAS,GACtC,IAAO,KAAK,IAAI,KAAK,IAAI,GAAG,CAAI,GAAG,CAAK;GAE1C,MAAS,EAAM,KAAK,UAExB,EAAG,aAAa,QAAQ,OAAO,CAAI,CAAC,GACpC,EAAK,UAAU,EAAE,MAAM,EAAK,CAAC;EAC/B;EAEA,IAAM,IAAY,QAChB,EAAe,EAAM,KAAK,SAAS,GAAG,EAAM,cAAc,CAAC,SAAS,GAAG,EAAM,SAAS,SAAS,CAAC,CAClG,GAEM,IAAU,SAAgB,EAAM,KAAK,SAAS,MAAM,CAAC,GACrD,IAAS,SAAgB,EAAM,KAAK,SAAS,OAAO,EAAM,cAAc,CAAC,SAAS,EAAE;EAE1F,OAAO,CAAI;yBACU,EAAM,MAAM;;kBAGzB,EAAM,kBAAkB,CAAC,QACrB,CAAI;;;;;;;kCAOc,EAAQ;qCACL,EAAK,CAAC,EAAE;;;;oBAK7B,GAAG;kBAEP,EAAM,iBAAiB,CAAC,QACpB,CAAI;;;;;;;kCAOc,EAAQ;qCACL,GAAM,EAAM,KAAK,SAAS,KAAK,CAAC,EAAE;;;;oBAKvD,GAAG;;oBAGL,EAAU,MAAM,KAAK,MAAS;GAC5B,IAAI,MAAS,oBAAoB,MAAS,gBACxC,OAAO,CAAI;;;GAKb,IAAM,IAAK,GACL,IAAY,OAAQ,EAAM,KAAK,SAAS,IACxC,IAAU,QAAQ;GAExB,OAAO,IACH,CAAI;;;;sCAIc,EAAQ;;uCAEP,EAAK,CAAE,EAAE;0BACtB,EAAG;;wBAGT,CAAI;0EACkD,EAAQ,iBAAiB,EAAK,CAAE,EAAE;0BAClF,EAAG;;;EAGf,CAAC,EAAE;;kBAGL,EAAM,iBAAiB,CAAC,QACpB,CAAI;;;;;;;kCAOc,EAAO;qCACJ,GAAM,EAAM,KAAK,SAAS,KAAK,CAAC,EAAE;;;;oBAKvD,GAAG;kBAEP,EAAM,kBAAkB,CAAC,QACrB,CAAI;;;;;;;kCAOc,EAAO;qCACJ,EAAK,EAAM,cAAc,CAAC,SAAS,CAAC,EAAE;;;;oBAK3D,GAAG;;;;CAIjB;CAEA,QAAQ;EAAC;EAAoB;EAAiB,EAAiB;EAAG;CAAe;AACnF,CAAC"}
package/dist/popover.cjs CHANGED
@@ -1,4 +1,4 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./core/parse.cjs"),n=require("./shared/prop-bundles.cjs"),r=require("./overlay/shared/use-floating-trigger.cjs"),i=require("./overlay/popover/popover.css.cjs");let a=require("@vielzeug/ore"),o=require("@vielzeug/ripple");require("@vielzeug/orbit");var s=8,c=new Set([`click`,`focus`,`hover`]),l=[`click`],u=e=>e==null?void 0:e===``||e===`true`,d=e=>t.parseStringTriggers(String(e??``),c,l),f=`ore-popover`;(0,a.define)(f,{props:{...n.disablableBundle,"default-open":a.prop.bool(!1),label:a.prop.string(),offset:a.prop.number(s),open:{default:void 0,parse:u},placement:a.prop.oneOf([`bottom`,`bottom-end`,`bottom-start`,`left`,`left-end`,`left-start`,`right`,`right-end`,`right-start`,`top`,`top-end`,`top-start`],`bottom`),trigger:a.prop.string(`click`)},setup(e){let t=(0,a.getHost)(),n=(0,a.useEmit)(),i=(0,a.useSlots)(),s=t.shadowRoot,c=(0,o.computed)(()=>!!e.disabled.value),l=(0,a.createStableId)(`popover`),u=(0,o.computed)(()=>d(e.trigger.value)),f=null,p=r.useFloatingTrigger({bindTriggerAria:e=>(0,a.bind)({aria:{controls:()=>l,disabled:()=>String(c.value),expanded:()=>String(p.visible.value),haspopup:`dialog`}},{target:e}),defaultOpen:e[`default-open`],disabled:c,getHost:()=>t,getPanel:()=>f,offset:e.offset,onCleanup:a.onCleanup,onClose:e=>n(`open-change`,{open:!1,reason:e}),onOpen:e=>n(`open-change`,{open:!0,reason:e}),openProp:e.open,placement:(0,o.computed)(()=>e.placement.value),slot:()=>s?.querySelector(`slot:not([name])`)??null,slotElements:i.elements(),triggers:u});return(0,a.onMounted)(()=>p.mount()),a.html`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./core/parse.cjs"),n=require("./shared/prop-bundles.cjs"),r=require("./overlay/shared/use-floating-trigger.cjs"),i=require("./overlay/popover/popover.css.cjs");let a=require("@vielzeug/ore"),o=require("@vielzeug/ripple");var s=8,c=new Set([`click`,`focus`,`hover`]),l=[`click`],u=e=>e==null?void 0:e===``||e===`true`,d=e=>t.parseStringTriggers(String(e??``),c,l),f=`ore-popover`;(0,a.define)(f,{props:{...n.disablableBundle,"default-open":a.prop.bool(!1),label:a.prop.string(),offset:a.prop.number(s),open:{default:void 0,parse:u},placement:a.prop.oneOf([`bottom`,`bottom-end`,`bottom-start`,`left`,`left-end`,`left-start`,`right`,`right-end`,`right-start`,`top`,`top-end`,`top-start`],`bottom`),trigger:a.prop.string(`click`)},setup(e){let t=(0,a.getHost)(),n=(0,a.useEmit)(),i=(0,a.useSlots)(),s=t.shadowRoot,c=(0,o.computed)(()=>!!e.disabled.value),l=(0,a.createStableId)(`popover`),u=(0,o.computed)(()=>d(e.trigger.value)),f=null,p=r.useFloatingTrigger({bindTriggerAria:e=>(0,a.bind)({aria:{controls:()=>l,disabled:()=>String(c.value),expanded:()=>String(p.visible.value),haspopup:`dialog`}},{target:e}),defaultOpen:e[`default-open`],disabled:c,getHost:()=>t,getPanel:()=>f,offset:e.offset,onCleanup:a.onCleanup,onClose:e=>n(`open-change`,{open:!1,reason:e}),onOpen:e=>n(`open-change`,{open:!0,reason:e}),openProp:e.open,placement:(0,o.computed)(()=>e.placement.value),slot:()=>s?.querySelector(`slot:not([name])`)??null,slotElements:i.elements(),triggers:u});return(0,a.onMounted)(()=>p.mount()),a.html`
2
2
  <slot></slot>
3
3
  <div
4
4
  class="panel"
@@ -1 +1 @@
1
- {"version":3,"file":"popover.cjs","names":[],"sources":["../src/overlay/popover/popover.ts"],"sourcesContent":["import { type Placement } from '@vielzeug/orbit';\nimport {\n createStableId,\n define,\n html,\n prop,\n bind,\n getHost,\n onCleanup,\n onMounted,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport { type OverlayOpenChangeDetail, parseStringTriggers } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport { useFloatingTrigger } from '../shared/use-floating-trigger';\nimport styles from './popover.css?inline';\n\nexport type PopoverTrigger = 'click' | 'focus' | 'hover';\n\nconst PANEL_OFFSET = 8;\nconst VALID_TRIGGERS = new Set<PopoverTrigger>(['click', 'focus', 'hover']);\nconst DEFAULT_POPOVER_TRIGGERS: PopoverTrigger[] = ['click'];\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\nconst normalizeTriggers = (value: unknown): PopoverTrigger[] =>\n parseStringTriggers(String(value ?? ''), VALID_TRIGGERS, DEFAULT_POPOVER_TRIGGERS);\n\nexport type OrePopoverEvents = {\n 'open-change': OverlayOpenChangeDetail;\n};\n\n/** Popover component properties */\nexport type OrePopoverProps = {\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n /** Disable the popover */\n disabled?: boolean;\n /** Accessible label for the panel */\n label?: string;\n /** Gap between trigger and panel in px */\n offset?: number;\n /** Controlled open state */\n open?: boolean;\n /** Preferred placement relative to the trigger */\n placement?: Placement;\n /** Which trigger(s) open/close the popover */\n trigger?: string;\n};\n\n/**\n * A floating panel anchored to a trigger element.\n *\n * @element ore-popover\n * @attr {string} placement - Preferred placement (default: 'bottom')\n * @attr {string} trigger - 'click' | 'hover' | 'focus' (default: 'click')\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {number} offset - Gap in px (default: 8)\n * @attr {boolean} disabled - Disables the popover\n * @attr {string} label - aria-label on the panel\n * @fires open-change - When the panel state changes. detail: { open, reason }\n * @slot - The trigger element\n * @slot content - Panel content\n * @part panel - Panel container.\n *\n * @example\n * ```html\n * <ore-popover placement=\"bottom\" trigger=\"click\">\n * <ore-button>Open info</ore-button>\n * <div slot=\"content\">\n * <p>Popover body content goes here.</p>\n * </div>\n * </ore-popover>\n * ```\n */\nexport const POPOVER_TAG = 'ore-popover' as const;\ndefine<OrePopoverProps>(POPOVER_TAG, {\n props: {\n ...disablableBundle,\n 'default-open': prop.bool(false),\n label: prop.string(),\n offset: prop.number(PANEL_OFFSET),\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(\n [\n 'bottom',\n 'bottom-end',\n 'bottom-start',\n 'left',\n 'left-end',\n 'left-start',\n 'right',\n 'right-end',\n 'right-start',\n 'top',\n 'top-end',\n 'top-start',\n ] as const,\n 'bottom',\n ),\n trigger: prop.string('click'),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OrePopoverEvents>();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const panelId = createStableId('popover');\n const triggers = computed<PopoverTrigger[]>(() => normalizeTriggers(props.trigger.value));\n let panelEl: HTMLElement | null = null;\n\n const floating = useFloatingTrigger({\n bindTriggerAria: (triggerEl) =>\n bind(\n {\n aria: {\n controls: () => panelId,\n disabled: () => String(isDisabled.value),\n expanded: () => String(floating.visible.value),\n haspopup: 'dialog',\n },\n },\n { target: triggerEl },\n ),\n defaultOpen: props['default-open'],\n disabled: isDisabled,\n getHost: () => el,\n getPanel: () => panelEl,\n offset: props.offset,\n onCleanup,\n onClose: (reason) => emit('open-change', { open: false, reason }),\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n openProp: props.open as typeof props.open & { value: boolean | undefined },\n placement: computed(() => props.placement.value as Placement),\n slot: () => shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])') ?? null,\n slotElements: slots.elements(),\n triggers,\n });\n\n onMounted(() => floating.mount());\n\n return html`\n <slot></slot>\n <div\n class=\"panel\"\n part=\"panel\"\n id=\"${panelId}\"\n role=\"dialog\"\n aria-modal=\"false\"\n popover=\"manual\"\n aria-label=\"${props.label}\"\n aria-hidden=\"${() => String(!floating.visible.value)}\"\n ref=${(ref: HTMLElement) => {\n panelEl = ref;\n }}>\n <slot name=\"content\"></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, styles],\n});\n"],"mappings":"+XAuBA,IAAM,EAAe,EACf,EAAiB,IAAI,IAAoB,CAAC,QAAS,QAAS,OAAO,CAAC,EACpE,EAA6C,CAAC,OAAO,EAErD,EAAqB,GACzB,GAAS,KAAO,IAAA,GAAY,IAAU,IAAM,IAAU,OAElD,EAAqB,GACzB,EAAA,oBAAoB,OAAO,GAAS,EAAE,EAAG,EAAgB,CAAwB,EAkDtE,EAAc,eAC3B,EAAA,EAAA,OAAA,CAAwB,EAAa,CACnC,MAAO,CACL,GAAG,EAAA,iBACH,eAAgB,EAAA,KAAK,KAAK,EAAK,EAC/B,MAAO,EAAA,KAAK,OAAO,EACnB,OAAQ,EAAA,KAAK,OAAO,CAAY,EAChC,KAAM,CAAE,QAAS,IAAA,GAAkC,MAAO,CAAkB,EAC5E,UAAW,EAAA,KAAK,MACd,CACE,SACA,aACA,eACA,OACA,WACA,aACA,QACA,YACA,cACA,MACA,UACA,WACF,EACA,QACF,EACA,QAAS,EAAA,KAAK,OAAO,OAAO,CAC9B,EACA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,GAAA,EAAO,EAAA,QAAA,CAA0B,EACjC,GAAA,EAAQ,EAAA,SAAA,CAAS,EAEjB,EAAa,EAAG,WAChB,GAAA,EAAa,EAAA,SAAA,KAAe,EAAQ,EAAM,SAAS,KAAM,EACzD,GAAA,EAAU,EAAA,eAAA,CAAe,SAAS,EAClC,GAAA,EAAW,EAAA,SAAA,KAAiC,EAAkB,EAAM,QAAQ,KAAK,CAAC,EACpF,EAA8B,KAE5B,EAAW,EAAA,mBAAmB,CAClC,gBAAkB,IAAA,EAChB,EAAA,KAAA,CACE,CACE,KAAM,CACJ,aAAgB,EAChB,aAAgB,OAAO,EAAW,KAAK,EACvC,aAAgB,OAAO,EAAS,QAAQ,KAAK,EAC7C,SAAU,QACZ,CACF,EACA,CAAE,OAAQ,CAAU,CACtB,EACF,YAAa,EAAM,gBACnB,SAAU,EACV,YAAe,EACf,aAAgB,EAChB,OAAQ,EAAM,OACd,UAAA,EAAA,UACA,QAAU,GAAW,EAAK,cAAe,CAAE,KAAM,GAAO,QAAO,CAAC,EAChE,OAAS,GAAW,EAAK,cAAe,CAAE,KAAM,GAAM,QAAO,CAAC,EAC9D,SAAU,EAAM,KAChB,WAAA,EAAW,EAAA,SAAA,KAAe,EAAM,UAAU,KAAkB,EAC5D,SAAY,GAAY,cAA+B,kBAAkB,GAAK,KAC9E,aAAc,EAAM,SAAS,EAC7B,UACF,CAAC,EAID,OAFA,EAAA,EAAA,UAAA,KAAgB,EAAS,MAAM,CAAC,EAEzB,EAAA,IAAI;;;;;cAKD,EAAQ;;;;sBAIA,EAAM,MAAM;2BACL,OAAO,CAAC,EAAS,QAAQ,KAAK,EAAE;cAC9C,GAAqB,CAC1B,EAAU,CACZ,EAAE;;;KAIR,EACA,OAAQ,CAAC,EAAA,mBAAoB,EAAA,OAAM,CACrC,CAAC"}
1
+ {"version":3,"file":"popover.cjs","names":[],"sources":["../src/overlay/popover/popover.ts"],"sourcesContent":["import type { Placement } from '@vielzeug/orbit';\nimport {\n bind,\n createStableId,\n define,\n getHost,\n html,\n onCleanup,\n onMounted,\n prop,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport { type OverlayOpenChangeDetail, parseStringTriggers } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport { useFloatingTrigger } from '../shared/use-floating-trigger';\nimport styles from './popover.css?inline';\n\nexport type PopoverTrigger = 'click' | 'focus' | 'hover';\n\nconst PANEL_OFFSET = 8;\nconst VALID_TRIGGERS = new Set<PopoverTrigger>(['click', 'focus', 'hover']);\nconst DEFAULT_POPOVER_TRIGGERS: PopoverTrigger[] = ['click'];\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\nconst normalizeTriggers = (value: unknown): PopoverTrigger[] =>\n parseStringTriggers(String(value ?? ''), VALID_TRIGGERS, DEFAULT_POPOVER_TRIGGERS);\n\nexport type OrePopoverEvents = {\n 'open-change': OverlayOpenChangeDetail;\n};\n\n/** Popover component properties */\nexport type OrePopoverProps = {\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n /** Disable the popover */\n disabled?: boolean;\n /** Accessible label for the panel */\n label?: string;\n /** Gap between trigger and panel in px */\n offset?: number;\n /** Controlled open state */\n open?: boolean;\n /** Preferred placement relative to the trigger */\n placement?: Placement;\n /** Which trigger(s) open/close the popover */\n trigger?: string;\n};\n\n/**\n * A floating panel anchored to a trigger element.\n *\n * @element ore-popover\n * @attr {string} placement - Preferred placement (default: 'bottom')\n * @attr {string} trigger - 'click' | 'hover' | 'focus' (default: 'click')\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {number} offset - Gap in px (default: 8)\n * @attr {boolean} disabled - Disables the popover\n * @attr {string} label - aria-label on the panel\n * @fires open-change - When the panel state changes. detail: { open, reason }\n * @slot - The trigger element\n * @slot content - Panel content\n * @part panel - Panel container.\n *\n * @example\n * ```html\n * <ore-popover placement=\"bottom\" trigger=\"click\">\n * <ore-button>Open info</ore-button>\n * <div slot=\"content\">\n * <p>Popover body content goes here.</p>\n * </div>\n * </ore-popover>\n * ```\n */\nexport const POPOVER_TAG = 'ore-popover' as const;\ndefine<OrePopoverProps>(POPOVER_TAG, {\n props: {\n ...disablableBundle,\n 'default-open': prop.bool(false),\n label: prop.string(),\n offset: prop.number(PANEL_OFFSET),\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(\n [\n 'bottom',\n 'bottom-end',\n 'bottom-start',\n 'left',\n 'left-end',\n 'left-start',\n 'right',\n 'right-end',\n 'right-start',\n 'top',\n 'top-end',\n 'top-start',\n ] as const,\n 'bottom',\n ),\n trigger: prop.string('click'),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OrePopoverEvents>();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const panelId = createStableId('popover');\n const triggers = computed<PopoverTrigger[]>(() => normalizeTriggers(props.trigger.value));\n let panelEl: HTMLElement | null = null;\n\n const floating = useFloatingTrigger({\n bindTriggerAria: (triggerEl) =>\n bind(\n {\n aria: {\n controls: () => panelId,\n disabled: () => String(isDisabled.value),\n expanded: () => String(floating.visible.value),\n haspopup: 'dialog',\n },\n },\n { target: triggerEl },\n ),\n defaultOpen: props['default-open'],\n disabled: isDisabled,\n getHost: () => el,\n getPanel: () => panelEl,\n offset: props.offset,\n onCleanup,\n onClose: (reason) => emit('open-change', { open: false, reason }),\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n openProp: props.open as typeof props.open & { value: boolean | undefined },\n placement: computed(() => props.placement.value as Placement),\n slot: () => shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])') ?? null,\n slotElements: slots.elements(),\n triggers,\n });\n\n onMounted(() => floating.mount());\n\n return html`\n <slot></slot>\n <div\n class=\"panel\"\n part=\"panel\"\n id=\"${panelId}\"\n role=\"dialog\"\n aria-modal=\"false\"\n popover=\"manual\"\n aria-label=\"${props.label}\"\n aria-hidden=\"${() => String(!floating.visible.value)}\"\n ref=${(ref: HTMLElement) => {\n panelEl = ref;\n }}>\n <slot name=\"content\"></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, styles],\n});\n"],"mappings":"oWAuBA,IAAM,EAAe,EACf,EAAiB,IAAI,IAAoB,CAAC,QAAS,QAAS,OAAO,CAAC,EACpE,EAA6C,CAAC,OAAO,EAErD,EAAqB,GACzB,GAAS,KAAO,IAAA,GAAY,IAAU,IAAM,IAAU,OAElD,EAAqB,GACzB,EAAA,oBAAoB,OAAO,GAAS,EAAE,EAAG,EAAgB,CAAwB,EAkDtE,EAAc,eAC3B,EAAA,EAAA,OAAA,CAAwB,EAAa,CACnC,MAAO,CACL,GAAG,EAAA,iBACH,eAAgB,EAAA,KAAK,KAAK,EAAK,EAC/B,MAAO,EAAA,KAAK,OAAO,EACnB,OAAQ,EAAA,KAAK,OAAO,CAAY,EAChC,KAAM,CAAE,QAAS,IAAA,GAAkC,MAAO,CAAkB,EAC5E,UAAW,EAAA,KAAK,MACd,CACE,SACA,aACA,eACA,OACA,WACA,aACA,QACA,YACA,cACA,MACA,UACA,WACF,EACA,QACF,EACA,QAAS,EAAA,KAAK,OAAO,OAAO,CAC9B,EACA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,GAAA,EAAO,EAAA,QAAA,CAA0B,EACjC,GAAA,EAAQ,EAAA,SAAA,CAAS,EAEjB,EAAa,EAAG,WAChB,GAAA,EAAa,EAAA,SAAA,KAAe,EAAQ,EAAM,SAAS,KAAM,EACzD,GAAA,EAAU,EAAA,eAAA,CAAe,SAAS,EAClC,GAAA,EAAW,EAAA,SAAA,KAAiC,EAAkB,EAAM,QAAQ,KAAK,CAAC,EACpF,EAA8B,KAE5B,EAAW,EAAA,mBAAmB,CAClC,gBAAkB,IAAA,EAChB,EAAA,KAAA,CACE,CACE,KAAM,CACJ,aAAgB,EAChB,aAAgB,OAAO,EAAW,KAAK,EACvC,aAAgB,OAAO,EAAS,QAAQ,KAAK,EAC7C,SAAU,QACZ,CACF,EACA,CAAE,OAAQ,CAAU,CACtB,EACF,YAAa,EAAM,gBACnB,SAAU,EACV,YAAe,EACf,aAAgB,EAChB,OAAQ,EAAM,OACd,UAAA,EAAA,UACA,QAAU,GAAW,EAAK,cAAe,CAAE,KAAM,GAAO,QAAO,CAAC,EAChE,OAAS,GAAW,EAAK,cAAe,CAAE,KAAM,GAAM,QAAO,CAAC,EAC9D,SAAU,EAAM,KAChB,WAAA,EAAW,EAAA,SAAA,KAAe,EAAM,UAAU,KAAkB,EAC5D,SAAY,GAAY,cAA+B,kBAAkB,GAAK,KAC9E,aAAc,EAAM,SAAS,EAC7B,UACF,CAAC,EAID,OAFA,EAAA,EAAA,UAAA,KAAgB,EAAS,MAAM,CAAC,EAEzB,EAAA,IAAI;;;;;cAKD,EAAQ;;;;sBAIA,EAAM,MAAM;2BACL,OAAO,CAAC,EAAS,QAAQ,KAAK,EAAE;cAC9C,GAAqB,CAC1B,EAAU,CACZ,EAAE;;;KAIR,EACA,OAAQ,CAAC,EAAA,mBAAoB,EAAA,OAAM,CACrC,CAAC"}
package/dist/popover.js CHANGED
@@ -5,7 +5,6 @@ import { useFloatingTrigger as r } from "./overlay/shared/use-floating-trigger.j
5
5
  import i from "./overlay/popover/popover.css.js";
6
6
  import { bind as a, createStableId as o, define as s, getHost as c, html as l, onCleanup as u, onMounted as d, prop as f, useEmit as p, useSlots as m } from "@vielzeug/ore";
7
7
  import { computed as h } from "@vielzeug/ripple";
8
- import "@vielzeug/orbit";
9
8
  //#region src/overlay/popover/popover.ts
10
9
  var g = 8, _ = /* @__PURE__ */ new Set([
11
10
  "click",
@@ -1 +1 @@
1
- {"version":3,"file":"popover.js","names":[],"sources":["../src/overlay/popover/popover.ts"],"sourcesContent":["import { type Placement } from '@vielzeug/orbit';\nimport {\n createStableId,\n define,\n html,\n prop,\n bind,\n getHost,\n onCleanup,\n onMounted,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport { type OverlayOpenChangeDetail, parseStringTriggers } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport { useFloatingTrigger } from '../shared/use-floating-trigger';\nimport styles from './popover.css?inline';\n\nexport type PopoverTrigger = 'click' | 'focus' | 'hover';\n\nconst PANEL_OFFSET = 8;\nconst VALID_TRIGGERS = new Set<PopoverTrigger>(['click', 'focus', 'hover']);\nconst DEFAULT_POPOVER_TRIGGERS: PopoverTrigger[] = ['click'];\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\nconst normalizeTriggers = (value: unknown): PopoverTrigger[] =>\n parseStringTriggers(String(value ?? ''), VALID_TRIGGERS, DEFAULT_POPOVER_TRIGGERS);\n\nexport type OrePopoverEvents = {\n 'open-change': OverlayOpenChangeDetail;\n};\n\n/** Popover component properties */\nexport type OrePopoverProps = {\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n /** Disable the popover */\n disabled?: boolean;\n /** Accessible label for the panel */\n label?: string;\n /** Gap between trigger and panel in px */\n offset?: number;\n /** Controlled open state */\n open?: boolean;\n /** Preferred placement relative to the trigger */\n placement?: Placement;\n /** Which trigger(s) open/close the popover */\n trigger?: string;\n};\n\n/**\n * A floating panel anchored to a trigger element.\n *\n * @element ore-popover\n * @attr {string} placement - Preferred placement (default: 'bottom')\n * @attr {string} trigger - 'click' | 'hover' | 'focus' (default: 'click')\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {number} offset - Gap in px (default: 8)\n * @attr {boolean} disabled - Disables the popover\n * @attr {string} label - aria-label on the panel\n * @fires open-change - When the panel state changes. detail: { open, reason }\n * @slot - The trigger element\n * @slot content - Panel content\n * @part panel - Panel container.\n *\n * @example\n * ```html\n * <ore-popover placement=\"bottom\" trigger=\"click\">\n * <ore-button>Open info</ore-button>\n * <div slot=\"content\">\n * <p>Popover body content goes here.</p>\n * </div>\n * </ore-popover>\n * ```\n */\nexport const POPOVER_TAG = 'ore-popover' as const;\ndefine<OrePopoverProps>(POPOVER_TAG, {\n props: {\n ...disablableBundle,\n 'default-open': prop.bool(false),\n label: prop.string(),\n offset: prop.number(PANEL_OFFSET),\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(\n [\n 'bottom',\n 'bottom-end',\n 'bottom-start',\n 'left',\n 'left-end',\n 'left-start',\n 'right',\n 'right-end',\n 'right-start',\n 'top',\n 'top-end',\n 'top-start',\n ] as const,\n 'bottom',\n ),\n trigger: prop.string('click'),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OrePopoverEvents>();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const panelId = createStableId('popover');\n const triggers = computed<PopoverTrigger[]>(() => normalizeTriggers(props.trigger.value));\n let panelEl: HTMLElement | null = null;\n\n const floating = useFloatingTrigger({\n bindTriggerAria: (triggerEl) =>\n bind(\n {\n aria: {\n controls: () => panelId,\n disabled: () => String(isDisabled.value),\n expanded: () => String(floating.visible.value),\n haspopup: 'dialog',\n },\n },\n { target: triggerEl },\n ),\n defaultOpen: props['default-open'],\n disabled: isDisabled,\n getHost: () => el,\n getPanel: () => panelEl,\n offset: props.offset,\n onCleanup,\n onClose: (reason) => emit('open-change', { open: false, reason }),\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n openProp: props.open as typeof props.open & { value: boolean | undefined },\n placement: computed(() => props.placement.value as Placement),\n slot: () => shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])') ?? null,\n slotElements: slots.elements(),\n triggers,\n });\n\n onMounted(() => floating.mount());\n\n return html`\n <slot></slot>\n <div\n class=\"panel\"\n part=\"panel\"\n id=\"${panelId}\"\n role=\"dialog\"\n aria-modal=\"false\"\n popover=\"manual\"\n aria-label=\"${props.label}\"\n aria-hidden=\"${() => String(!floating.visible.value)}\"\n ref=${(ref: HTMLElement) => {\n panelEl = ref;\n }}>\n <slot name=\"content\"></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, styles],\n});\n"],"mappings":";;;;;;;;;AAuBA,IAAM,IAAe,GACf,oBAAiB,IAAI,IAAoB;CAAC;CAAS;CAAS;AAAO,CAAC,GACpE,IAA6C,CAAC,OAAO,GAErD,KAAqB,MACzB,KAAS,OAAO,KAAA,IAAY,MAAU,MAAM,MAAU,QAElD,KAAqB,MACzB,EAAoB,OAAO,KAAS,EAAE,GAAG,GAAgB,CAAwB,GAkDtE,IAAc;AAC3B,EAAwB,GAAa;CACnC,OAAO;EACL,GAAG;EACH,gBAAgB,EAAK,KAAK,EAAK;EAC/B,OAAO,EAAK,OAAO;EACnB,QAAQ,EAAK,OAAO,CAAY;EAChC,MAAM;GAAE,SAAS,KAAA;GAAkC,OAAO;EAAkB;EAC5E,WAAW,EAAK,MACd;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,GACA,QACF;EACA,SAAS,EAAK,OAAO,OAAO;CAC9B;CACA,MAAM,GAAO;EACX,IAAM,IAAK,EAAQ,GACb,IAAO,EAA0B,GACjC,IAAQ,EAAS,GAEjB,IAAa,EAAG,YAChB,IAAa,QAAe,EAAQ,EAAM,SAAS,KAAM,GACzD,IAAU,EAAe,SAAS,GAClC,IAAW,QAAiC,EAAkB,EAAM,QAAQ,KAAK,CAAC,GACpF,IAA8B,MAE5B,IAAW,EAAmB;GAClC,kBAAkB,MAChB,EACE,EACE,MAAM;IACJ,gBAAgB;IAChB,gBAAgB,OAAO,EAAW,KAAK;IACvC,gBAAgB,OAAO,EAAS,QAAQ,KAAK;IAC7C,UAAU;GACZ,EACF,GACA,EAAE,QAAQ,EAAU,CACtB;GACF,aAAa,EAAM;GACnB,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,QAAQ,EAAM;GACd;GACA,UAAU,MAAW,EAAK,eAAe;IAAE,MAAM;IAAO;GAAO,CAAC;GAChE,SAAS,MAAW,EAAK,eAAe;IAAE,MAAM;IAAM;GAAO,CAAC;GAC9D,UAAU,EAAM;GAChB,WAAW,QAAe,EAAM,UAAU,KAAkB;GAC5D,YAAY,GAAY,cAA+B,kBAAkB,KAAK;GAC9E,cAAc,EAAM,SAAS;GAC7B;EACF,CAAC;EAID,OAFA,QAAgB,EAAS,MAAM,CAAC,GAEzB,CAAI;;;;;cAKD,EAAQ;;;;sBAIA,EAAM,MAAM;6BACL,OAAO,CAAC,EAAS,QAAQ,KAAK,EAAE;eAC9C,MAAqB;GAC1B,IAAU;EACZ,EAAE;;;;CAIR;CACA,QAAQ,CAAC,GAAoB,CAAM;AACrC,CAAC"}
1
+ {"version":3,"file":"popover.js","names":[],"sources":["../src/overlay/popover/popover.ts"],"sourcesContent":["import type { Placement } from '@vielzeug/orbit';\nimport {\n bind,\n createStableId,\n define,\n getHost,\n html,\n onCleanup,\n onMounted,\n prop,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport { type OverlayOpenChangeDetail, parseStringTriggers } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport { useFloatingTrigger } from '../shared/use-floating-trigger';\nimport styles from './popover.css?inline';\n\nexport type PopoverTrigger = 'click' | 'focus' | 'hover';\n\nconst PANEL_OFFSET = 8;\nconst VALID_TRIGGERS = new Set<PopoverTrigger>(['click', 'focus', 'hover']);\nconst DEFAULT_POPOVER_TRIGGERS: PopoverTrigger[] = ['click'];\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\nconst normalizeTriggers = (value: unknown): PopoverTrigger[] =>\n parseStringTriggers(String(value ?? ''), VALID_TRIGGERS, DEFAULT_POPOVER_TRIGGERS);\n\nexport type OrePopoverEvents = {\n 'open-change': OverlayOpenChangeDetail;\n};\n\n/** Popover component properties */\nexport type OrePopoverProps = {\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n /** Disable the popover */\n disabled?: boolean;\n /** Accessible label for the panel */\n label?: string;\n /** Gap between trigger and panel in px */\n offset?: number;\n /** Controlled open state */\n open?: boolean;\n /** Preferred placement relative to the trigger */\n placement?: Placement;\n /** Which trigger(s) open/close the popover */\n trigger?: string;\n};\n\n/**\n * A floating panel anchored to a trigger element.\n *\n * @element ore-popover\n * @attr {string} placement - Preferred placement (default: 'bottom')\n * @attr {string} trigger - 'click' | 'hover' | 'focus' (default: 'click')\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {number} offset - Gap in px (default: 8)\n * @attr {boolean} disabled - Disables the popover\n * @attr {string} label - aria-label on the panel\n * @fires open-change - When the panel state changes. detail: { open, reason }\n * @slot - The trigger element\n * @slot content - Panel content\n * @part panel - Panel container.\n *\n * @example\n * ```html\n * <ore-popover placement=\"bottom\" trigger=\"click\">\n * <ore-button>Open info</ore-button>\n * <div slot=\"content\">\n * <p>Popover body content goes here.</p>\n * </div>\n * </ore-popover>\n * ```\n */\nexport const POPOVER_TAG = 'ore-popover' as const;\ndefine<OrePopoverProps>(POPOVER_TAG, {\n props: {\n ...disablableBundle,\n 'default-open': prop.bool(false),\n label: prop.string(),\n offset: prop.number(PANEL_OFFSET),\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(\n [\n 'bottom',\n 'bottom-end',\n 'bottom-start',\n 'left',\n 'left-end',\n 'left-start',\n 'right',\n 'right-end',\n 'right-start',\n 'top',\n 'top-end',\n 'top-start',\n ] as const,\n 'bottom',\n ),\n trigger: prop.string('click'),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OrePopoverEvents>();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const panelId = createStableId('popover');\n const triggers = computed<PopoverTrigger[]>(() => normalizeTriggers(props.trigger.value));\n let panelEl: HTMLElement | null = null;\n\n const floating = useFloatingTrigger({\n bindTriggerAria: (triggerEl) =>\n bind(\n {\n aria: {\n controls: () => panelId,\n disabled: () => String(isDisabled.value),\n expanded: () => String(floating.visible.value),\n haspopup: 'dialog',\n },\n },\n { target: triggerEl },\n ),\n defaultOpen: props['default-open'],\n disabled: isDisabled,\n getHost: () => el,\n getPanel: () => panelEl,\n offset: props.offset,\n onCleanup,\n onClose: (reason) => emit('open-change', { open: false, reason }),\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n openProp: props.open as typeof props.open & { value: boolean | undefined },\n placement: computed(() => props.placement.value as Placement),\n slot: () => shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])') ?? null,\n slotElements: slots.elements(),\n triggers,\n });\n\n onMounted(() => floating.mount());\n\n return html`\n <slot></slot>\n <div\n class=\"panel\"\n part=\"panel\"\n id=\"${panelId}\"\n role=\"dialog\"\n aria-modal=\"false\"\n popover=\"manual\"\n aria-label=\"${props.label}\"\n aria-hidden=\"${() => String(!floating.visible.value)}\"\n ref=${(ref: HTMLElement) => {\n panelEl = ref;\n }}>\n <slot name=\"content\"></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, styles],\n});\n"],"mappings":";;;;;;;;AAuBA,IAAM,IAAe,GACf,oBAAiB,IAAI,IAAoB;CAAC;CAAS;CAAS;AAAO,CAAC,GACpE,IAA6C,CAAC,OAAO,GAErD,KAAqB,MACzB,KAAS,OAAO,KAAA,IAAY,MAAU,MAAM,MAAU,QAElD,KAAqB,MACzB,EAAoB,OAAO,KAAS,EAAE,GAAG,GAAgB,CAAwB,GAkDtE,IAAc;AAC3B,EAAwB,GAAa;CACnC,OAAO;EACL,GAAG;EACH,gBAAgB,EAAK,KAAK,EAAK;EAC/B,OAAO,EAAK,OAAO;EACnB,QAAQ,EAAK,OAAO,CAAY;EAChC,MAAM;GAAE,SAAS,KAAA;GAAkC,OAAO;EAAkB;EAC5E,WAAW,EAAK,MACd;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,GACA,QACF;EACA,SAAS,EAAK,OAAO,OAAO;CAC9B;CACA,MAAM,GAAO;EACX,IAAM,IAAK,EAAQ,GACb,IAAO,EAA0B,GACjC,IAAQ,EAAS,GAEjB,IAAa,EAAG,YAChB,IAAa,QAAe,EAAQ,EAAM,SAAS,KAAM,GACzD,IAAU,EAAe,SAAS,GAClC,IAAW,QAAiC,EAAkB,EAAM,QAAQ,KAAK,CAAC,GACpF,IAA8B,MAE5B,IAAW,EAAmB;GAClC,kBAAkB,MAChB,EACE,EACE,MAAM;IACJ,gBAAgB;IAChB,gBAAgB,OAAO,EAAW,KAAK;IACvC,gBAAgB,OAAO,EAAS,QAAQ,KAAK;IAC7C,UAAU;GACZ,EACF,GACA,EAAE,QAAQ,EAAU,CACtB;GACF,aAAa,EAAM;GACnB,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,QAAQ,EAAM;GACd;GACA,UAAU,MAAW,EAAK,eAAe;IAAE,MAAM;IAAO;GAAO,CAAC;GAChE,SAAS,MAAW,EAAK,eAAe;IAAE,MAAM;IAAM;GAAO,CAAC;GAC9D,UAAU,EAAM;GAChB,WAAW,QAAe,EAAM,UAAU,KAAkB;GAC5D,YAAY,GAAY,cAA+B,kBAAkB,KAAK;GAC9E,cAAc,EAAM,SAAS;GAC7B;EACF,CAAC;EAID,OAFA,QAAgB,EAAS,MAAM,CAAC,GAEzB,CAAI;;;;;cAKD,EAAQ;;;;sBAIA,EAAM,MAAM;6BACL,OAAO,CAAC,EAAS,QAAQ,KAAK,EAAE;eAC9C,MAAqB;GAC1B,IAAU;EACZ,EAAE;;;;CAIR;CACA,QAAQ,CAAC,GAAoB,CAAM;AACrC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"progress.cjs","names":[],"sources":["../src/feedback/progress/progress.ts"],"sourcesContent":["import { define, html, prop, getHost, watchEffect, styleMap } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, reducedMotionMixin } from '../../styles';\nimport componentStyles from './progress.css?inline';\n\n/** Progress bar component properties */\nexport type OreProgressProps = {\n /** Theme color for the fill bar */\n color?: ThemeColor;\n /** Floating chip centered above the fill endpoint (linear only). Hidden in indeterminate mode. Position formula: left = fill% − half chip width (CSS: left:X%; transform:translateX(−50%)). */\n 'floating-label'?: string;\n /** When true, shows an infinite animation — use when progress is unknown. */\n indeterminate?: boolean;\n /** Accessible name AND visible text label.\n * - Linear without `title`: rendered at the end of the bar.\n * - Linear with `title`: moved into the header row above the bar.\n * - Circular: large text centered inside the ring. */\n label?: string;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Size variant controlling bar height */\n size?: ComponentSize;\n /** Title text.\n * - Linear: displayed as a header above the bar; moves `label` into the header row.\n * - Circular: smaller text displayed below the `label` inside the ring. */\n title?: string;\n /** 'linear' (default), 'circular', or 'vertical' */\n type?: 'linear' | 'circular' | 'vertical';\n /** Current progress value (0 to `max`). Ignored when `indeterminate`. */\n value?: number;\n /** Human-readable value text for screen readers (e.g. \"Step 2 of 5\", \"75%\"). Overrides the raw aria-valuenow when set. */\n 'value-text'?: string;\n};\n\n/**\n * A linear progress bar for conveying operation progress.\n * Supports determinate (known value) and indeterminate (unknown duration) modes.\n *\n * @element ore-progress\n *\n * @attr {number} value - Current value (0–max). Defaults to 0.\n * @attr {number} max - Maximum value. Defaults to 100.\n * @attr {boolean} indeterminate - Show infinite animation (ignores value/max).\n * @attr {string} color - Theme color: 'primary' | 'success' | 'warning' | 'error' | …\n * @attr {string} size - Bar height/width: 'sm' | 'md' | 'lg'\n * @attr {string} type - 'linear' (default) | 'circular' | 'vertical'\n *\n * @cssprop --progress-width - Bar width override (vertical only)\n * @attr {string} label - Visible text label + accessible name. Linear: at bar end (or header row with title). Circular: large text centered inside the ring.\n * @attr {string} title - Title text. Linear: header above the bar (moves label to header row). Circular: smaller text below the label inside the ring.\n * @attr {string} floating-label - Floating chip centered above the fill endpoint (linear only); hidden when indeterminate.\n *\n * @cssprop --progress-height - Bar height override\n * @cssprop --progress-track-bg - Track background color\n * @cssprop --progress-fill - Fill bar color\n * @cssprop --progress-radius - Border radius\n * @cssprop --progress-label-gap - Gap between header/bar row and between bar and trailing label (default 0.25 rem)\n * @cssprop --progress-title-color - Title text color (defaults to currentColor)\n * @cssprop --progress-label-color - Label text color (defaults to currentColor)\n * @cssprop --progress-circle-size - Circular indicator diameter (default 6rem)\n * @cssprop --progress-circular-label-size - Font size of the label inside the ring (default --text-xl)\n * @cssprop --progress-circular-title-size - Font size of the title inside the ring (default --text-xs)\n *\n * @part fill - Progress fill element.\n * @example\n * ```html\n * <ore-progress value=\"45\"></ore-progress>\n * <ore-progress value=\"75\" max=\"100\" color=\"success\" size=\"lg\"></ore-progress>\n * <ore-progress indeterminate color=\"primary\" label=\"Loading…\"></ore-progress>\n * ```\n */\nexport const PROGRESS_TAG = 'ore-progress' as const;\ndefine<OreProgressProps>(PROGRESS_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n 'floating-label': prop.string(),\n indeterminate: prop.bool(false),\n label: prop.string(),\n max: prop.number(100),\n title: prop.string(),\n type: prop.oneOf(['linear', 'circular', 'vertical'] as const, 'linear'),\n value: prop.number(0),\n 'value-text': prop.string(),\n },\n\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n // The SVG circle circumference for a radius of 45 (viewBox 0 0 100 100)\n const RADIUS = 45;\n const CIRC = 2 * Math.PI * RADIUS; // ~282.7\n\n const percent = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return `${(v / m) * 100}%`;\n });\n\n const dashoffset = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return CIRC - (v / m) * CIRC;\n });\n\n const ariaValueNow = () => (props.indeterminate.value ? null : String(props.value.value));\n const ariaLabel = () => props.label.value ?? props.title.value ?? 'Progress';\n const circularStyle = styleMap({ '--_circ': `${CIRC}px` });\n const strokeDasharray = () => (props.indeterminate.value ? undefined : `${CIRC}px`);\n const strokeDashoffset = () => (props.indeterminate.value ? undefined : `${dashoffset.value}px`);\n const isVertical = computed(() => props.type.value === 'vertical');\n const linearFillStyle = styleMap({\n height: () => (!props.indeterminate.value && isVertical.value ? percent.value : null),\n width: () => (!props.indeterminate.value && !isVertical.value ? percent.value : null),\n });\n\n watch(() => {\n el.style.setProperty('--_percent', props.indeterminate.value ? '0%' : percent.value);\n });\n\n const circularTemplate = () => html`\n <div\n class=\"circular-track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\"\n style=\"${circularStyle}\">\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle class=\"circle-bg\" cx=\"50\" cy=\"50\" r=\"${RADIUS}\"></circle>\n <circle\n class=\"circle-fill\"\n cx=\"50\"\n cy=\"50\"\n r=\"${RADIUS}\"\n stroke-dasharray=\"${strokeDasharray}\"\n stroke-dashoffset=\"${strokeDashoffset}\"></circle>\n </svg>\n <div class=\"circular-inner\">\n <span class=\"circular-label\">${() => props.label.value ?? ''}</span>\n <span class=\"circular-title\">${() => props.title.value ?? ''}</span>\n </div>\n </div>\n `;\n\n const barTemplate = () => html`\n <div class=\"wrapper\">\n <div class=\"header\">\n <span class=\"progress-title\">${() => props.title.value ?? ''}</span>\n <span class=\"end-label header-label\">${() => props.label.value ?? ''}</span>\n </div>\n <div class=${() => `bar-row${isVertical.value ? ' bar-row-vertical' : ''}`}>\n <div class=\"track-outer\">\n <div\n class=\"track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\">\n <div class=\"fill\" part=\"fill\" style=\"${linearFillStyle}\"></div>\n </div>\n ${() =>\n !isVertical.value\n ? html`\n <span class=\"floating-label\">${props['floating-label']}</span>\n `\n : null}\n </div>\n <span class=\"end-label row-label\">${() => props.label.value ?? ''}</span>\n </div>\n </div>\n `;\n\n return html`\n ${() => (props.type.value === 'circular' ? circularTemplate() : barTemplate())}\n `;\n },\n\n styles: [colorThemeMixin, forcedColorsMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"6TA2EA,IAAa,EAAe,gBAC5B,EAAA,EAAA,OAAA,CAAyB,EAAc,CACrC,MAAO,CACL,GAAG,EAAA,eACH,GAAG,EAAA,cACH,iBAAkB,EAAA,KAAK,OAAO,EAC9B,cAAe,EAAA,KAAK,KAAK,EAAK,EAC9B,MAAO,EAAA,KAAK,OAAO,EACnB,IAAK,EAAA,KAAK,OAAO,GAAG,EACpB,MAAO,EAAA,KAAK,OAAO,EACnB,KAAM,EAAA,KAAK,MAAM,CAAC,SAAU,WAAY,UAAU,EAAY,QAAQ,EACtE,MAAO,EAAA,KAAK,OAAO,CAAC,EACpB,aAAc,EAAA,KAAK,OAAO,CAC5B,EAEA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,EAAQ,EAAA,YAIR,EAAO,EAAI,KAAK,GAAK,GAErB,GAAA,EAAU,EAAA,SAAA,KAIP,GAHG,KAAK,IAAI,EAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAGtE,EAFD,KAAK,IAAI,EAAG,OAAO,EAAM,IAAI,KAAK,CAE7B,EAAK,IAAI,EACzB,EAEK,GAAA,EAAa,EAAA,SAAA,KAAe,CAChC,IAAM,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAAC,EAC5E,EAAI,KAAK,IAAI,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,EAE7C,OAAO,EAAQ,EAAI,EAAK,CAC1B,CAAC,EAEK,MAAsB,EAAM,cAAc,MAAQ,KAAO,OAAO,EAAM,MAAM,KAAK,EACjF,MAAkB,EAAM,MAAM,OAAS,EAAM,MAAM,OAAS,WAC5D,GAAA,EAAgB,EAAA,SAAA,CAAS,CAAE,UAAW,GAAG,EAAK,GAAI,CAAC,EACnD,MAAyB,EAAM,cAAc,MAAQ,IAAA,GAAY,GAAG,EAAK,IACzE,MAA0B,EAAM,cAAc,MAAQ,IAAA,GAAY,GAAG,EAAW,MAAM,IACtF,GAAA,EAAa,EAAA,SAAA,KAAe,EAAM,KAAK,QAAU,UAAU,EAC3D,GAAA,EAAkB,EAAA,SAAA,CAAS,CAC/B,WAAe,CAAC,EAAM,cAAc,OAAS,EAAW,MAAQ,EAAQ,MAAQ,KAChF,UAAc,CAAC,EAAM,cAAc,OAAS,CAAC,EAAW,MAAQ,EAAQ,MAAQ,IAClF,CAAC,EAED,MAAY,CACV,EAAG,MAAM,YAAY,aAAc,EAAM,cAAc,MAAQ,KAAO,EAAQ,KAAK,CACrF,CAAC,EAED,IAAM,MAAyB,EAAA,IAAI;;;;yBAId,EAAa;;yBAEb,EAAM,IAAI;sBACb,EAAU;0BACN,EAAM,cAAc;iBAC7B,EAAc;;yDAE0B,GAAO;;;;;iBAK/C,GAAO;gCACQ,EAAgB;iCACf,EAAiB;;;6CAGH,EAAM,MAAM,OAAS,GAAG;6CACxB,EAAM,MAAM,OAAS,GAAG;;;MAK7D,MAAoB,EAAA,IAAI;;;6CAGa,EAAM,MAAM,OAAS,GAAG;qDAChB,EAAM,MAAM,OAAS,GAAG;;yBAEpD,UAAU,EAAW,MAAQ,oBAAsB,KAAK;;;;;+BAKpD,EAAa;;+BAEb,EAAM,IAAI;4BACb,EAAU;gCACN,EAAM,cAAc;qDACC,EAAgB;;kBAGtD,EAAW,MAIR,KAHA,EAAA,IAAI;mDAC6B,EAAM,kBAAkB;oBAEpD;;kDAE6B,EAAM,MAAM,OAAS,GAAG;;;MAKxE,MAAO,GAAA,IAAI;YACA,EAAM,KAAK,QAAU,WAAa,EAAiB,EAAI,EAAY,EAAG;KAEnF,EAEA,OAAQ,CAAC,EAAA,gBAAiB,EAAA,kBAAmB,EAAA,mBAAoB,EAAA,OAAe,CAClF,CAAC"}
1
+ {"version":3,"file":"progress.cjs","names":[],"sources":["../src/feedback/progress/progress.ts"],"sourcesContent":["import { define, getHost, html, prop, styleMap, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, reducedMotionMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './progress.css?inline';\n\n/** Progress bar component properties */\nexport type OreProgressProps = {\n /** Theme color for the fill bar */\n color?: ThemeColor;\n /** Floating chip centered above the fill endpoint (linear only). Hidden in indeterminate mode. Position formula: left = fill% − half chip width (CSS: left:X%; transform:translateX(−50%)). */\n 'floating-label'?: string;\n /** When true, shows an infinite animation — use when progress is unknown. */\n indeterminate?: boolean;\n /** Accessible name AND visible text label.\n * - Linear without `title`: rendered at the end of the bar.\n * - Linear with `title`: moved into the header row above the bar.\n * - Circular: large text centered inside the ring. */\n label?: string;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Size variant controlling bar height */\n size?: ComponentSize;\n /** Title text.\n * - Linear: displayed as a header above the bar; moves `label` into the header row.\n * - Circular: smaller text displayed below the `label` inside the ring. */\n title?: string;\n /** 'linear' (default), 'circular', or 'vertical' */\n type?: 'linear' | 'circular' | 'vertical';\n /** Current progress value (0 to `max`). Ignored when `indeterminate`. */\n value?: number;\n /** Human-readable value text for screen readers (e.g. \"Step 2 of 5\", \"75%\"). Overrides the raw aria-valuenow when set. */\n 'value-text'?: string;\n};\n\n/**\n * A linear progress bar for conveying operation progress.\n * Supports determinate (known value) and indeterminate (unknown duration) modes.\n *\n * @element ore-progress\n *\n * @attr {number} value - Current value (0–max). Defaults to 0.\n * @attr {number} max - Maximum value. Defaults to 100.\n * @attr {boolean} indeterminate - Show infinite animation (ignores value/max).\n * @attr {string} color - Theme color: 'primary' | 'success' | 'warning' | 'error' | …\n * @attr {string} size - Bar height/width: 'sm' | 'md' | 'lg'\n * @attr {string} type - 'linear' (default) | 'circular' | 'vertical'\n *\n * @cssprop --progress-width - Bar width override (vertical only)\n * @attr {string} label - Visible text label + accessible name. Linear: at bar end (or header row with title). Circular: large text centered inside the ring.\n * @attr {string} title - Title text. Linear: header above the bar (moves label to header row). Circular: smaller text below the label inside the ring.\n * @attr {string} floating-label - Floating chip centered above the fill endpoint (linear only); hidden when indeterminate.\n *\n * @cssprop --progress-height - Bar height override\n * @cssprop --progress-track-bg - Track background color\n * @cssprop --progress-fill - Fill bar color\n * @cssprop --progress-radius - Border radius\n * @cssprop --progress-label-gap - Gap between header/bar row and between bar and trailing label (default 0.25 rem)\n * @cssprop --progress-title-color - Title text color (defaults to currentColor)\n * @cssprop --progress-label-color - Label text color (defaults to currentColor)\n * @cssprop --progress-circle-size - Circular indicator diameter (default 6rem)\n * @cssprop --progress-circular-label-size - Font size of the label inside the ring (default --text-xl)\n * @cssprop --progress-circular-title-size - Font size of the title inside the ring (default --text-xs)\n *\n * @part fill - Progress fill element.\n * @example\n * ```html\n * <ore-progress value=\"45\"></ore-progress>\n * <ore-progress value=\"75\" max=\"100\" color=\"success\" size=\"lg\"></ore-progress>\n * <ore-progress indeterminate color=\"primary\" label=\"Loading…\"></ore-progress>\n * ```\n */\nexport const PROGRESS_TAG = 'ore-progress' as const;\ndefine<OreProgressProps>(PROGRESS_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n 'floating-label': prop.string(),\n indeterminate: prop.bool(false),\n label: prop.string(),\n max: prop.number(100),\n title: prop.string(),\n type: prop.oneOf(['linear', 'circular', 'vertical'] as const, 'linear'),\n value: prop.number(0),\n 'value-text': prop.string(),\n },\n\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n // The SVG circle circumference for a radius of 45 (viewBox 0 0 100 100)\n const RADIUS = 45;\n const CIRC = 2 * Math.PI * RADIUS; // ~282.7\n\n const percent = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return `${(v / m) * 100}%`;\n });\n\n const dashoffset = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return CIRC - (v / m) * CIRC;\n });\n\n const ariaValueNow = () => (props.indeterminate.value ? null : String(props.value.value));\n const ariaLabel = () => props.label.value ?? props.title.value ?? 'Progress';\n const circularStyle = styleMap({ '--_circ': `${CIRC}px` });\n const strokeDasharray = () => (props.indeterminate.value ? undefined : `${CIRC}px`);\n const strokeDashoffset = () => (props.indeterminate.value ? undefined : `${dashoffset.value}px`);\n const isVertical = computed(() => props.type.value === 'vertical');\n const linearFillStyle = styleMap({\n height: () => (!props.indeterminate.value && isVertical.value ? percent.value : null),\n width: () => (!props.indeterminate.value && !isVertical.value ? percent.value : null),\n });\n\n watch(() => {\n el.style.setProperty('--_percent', props.indeterminate.value ? '0%' : percent.value);\n });\n\n const circularTemplate = () => html`\n <div\n class=\"circular-track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\"\n style=\"${circularStyle}\">\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle class=\"circle-bg\" cx=\"50\" cy=\"50\" r=\"${RADIUS}\"></circle>\n <circle\n class=\"circle-fill\"\n cx=\"50\"\n cy=\"50\"\n r=\"${RADIUS}\"\n stroke-dasharray=\"${strokeDasharray}\"\n stroke-dashoffset=\"${strokeDashoffset}\"></circle>\n </svg>\n <div class=\"circular-inner\">\n <span class=\"circular-label\">${() => props.label.value ?? ''}</span>\n <span class=\"circular-title\">${() => props.title.value ?? ''}</span>\n </div>\n </div>\n `;\n\n const barTemplate = () => html`\n <div class=\"wrapper\">\n <div class=\"header\">\n <span class=\"progress-title\">${() => props.title.value ?? ''}</span>\n <span class=\"end-label header-label\">${() => props.label.value ?? ''}</span>\n </div>\n <div class=${() => `bar-row${isVertical.value ? ' bar-row-vertical' : ''}`}>\n <div class=\"track-outer\">\n <div\n class=\"track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\">\n <div class=\"fill\" part=\"fill\" style=\"${linearFillStyle}\"></div>\n </div>\n ${() =>\n !isVertical.value\n ? html`\n <span class=\"floating-label\">${props['floating-label']}</span>\n `\n : null}\n </div>\n <span class=\"end-label row-label\">${() => props.label.value ?? ''}</span>\n </div>\n </div>\n `;\n\n return html`\n ${() => (props.type.value === 'circular' ? circularTemplate() : barTemplate())}\n `;\n },\n\n styles: [colorThemeMixin, forcedColorsMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"6TAyEA,IAAa,EAAe,gBAC5B,EAAA,EAAA,OAAA,CAAyB,EAAc,CACrC,MAAO,CACL,GAAG,EAAA,eACH,GAAG,EAAA,cACH,iBAAkB,EAAA,KAAK,OAAO,EAC9B,cAAe,EAAA,KAAK,KAAK,EAAK,EAC9B,MAAO,EAAA,KAAK,OAAO,EACnB,IAAK,EAAA,KAAK,OAAO,GAAG,EACpB,MAAO,EAAA,KAAK,OAAO,EACnB,KAAM,EAAA,KAAK,MAAM,CAAC,SAAU,WAAY,UAAU,EAAY,QAAQ,EACtE,MAAO,EAAA,KAAK,OAAO,CAAC,EACpB,aAAc,EAAA,KAAK,OAAO,CAC5B,EAEA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,EAAQ,EAAA,YAIR,EAAO,EAAI,KAAK,GAAK,GAErB,GAAA,EAAU,EAAA,SAAA,KAIP,GAHG,KAAK,IAAI,EAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAGtE,EAFD,KAAK,IAAI,EAAG,OAAO,EAAM,IAAI,KAAK,CAE7B,EAAK,IAAI,EACzB,EAEK,GAAA,EAAa,EAAA,SAAA,KAAe,CAChC,IAAM,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAAC,EAC5E,EAAI,KAAK,IAAI,EAAG,OAAO,EAAM,IAAI,KAAK,CAAC,EAE7C,OAAO,EAAQ,EAAI,EAAK,CAC1B,CAAC,EAEK,MAAsB,EAAM,cAAc,MAAQ,KAAO,OAAO,EAAM,MAAM,KAAK,EACjF,MAAkB,EAAM,MAAM,OAAS,EAAM,MAAM,OAAS,WAC5D,GAAA,EAAgB,EAAA,SAAA,CAAS,CAAE,UAAW,GAAG,EAAK,GAAI,CAAC,EACnD,MAAyB,EAAM,cAAc,MAAQ,IAAA,GAAY,GAAG,EAAK,IACzE,MAA0B,EAAM,cAAc,MAAQ,IAAA,GAAY,GAAG,EAAW,MAAM,IACtF,GAAA,EAAa,EAAA,SAAA,KAAe,EAAM,KAAK,QAAU,UAAU,EAC3D,GAAA,EAAkB,EAAA,SAAA,CAAS,CAC/B,WAAe,CAAC,EAAM,cAAc,OAAS,EAAW,MAAQ,EAAQ,MAAQ,KAChF,UAAc,CAAC,EAAM,cAAc,OAAS,CAAC,EAAW,MAAQ,EAAQ,MAAQ,IAClF,CAAC,EAED,MAAY,CACV,EAAG,MAAM,YAAY,aAAc,EAAM,cAAc,MAAQ,KAAO,EAAQ,KAAK,CACrF,CAAC,EAED,IAAM,MAAyB,EAAA,IAAI;;;;yBAId,EAAa;;yBAEb,EAAM,IAAI;sBACb,EAAU;0BACN,EAAM,cAAc;iBAC7B,EAAc;;yDAE0B,GAAO;;;;;iBAK/C,GAAO;gCACQ,EAAgB;iCACf,EAAiB;;;6CAGH,EAAM,MAAM,OAAS,GAAG;6CACxB,EAAM,MAAM,OAAS,GAAG;;;MAK7D,MAAoB,EAAA,IAAI;;;6CAGa,EAAM,MAAM,OAAS,GAAG;qDAChB,EAAM,MAAM,OAAS,GAAG;;yBAEpD,UAAU,EAAW,MAAQ,oBAAsB,KAAK;;;;;+BAKpD,EAAa;;+BAEb,EAAM,IAAI;4BACb,EAAU;gCACN,EAAM,cAAc;qDACC,EAAgB;;kBAGtD,EAAW,MAIR,KAHA,EAAA,IAAI;mDAC6B,EAAM,kBAAkB;oBAEpD;;kDAE6B,EAAM,MAAM,OAAS,GAAG;;;MAKxE,MAAO,GAAA,IAAI;YACA,EAAM,KAAK,QAAU,WAAa,EAAiB,EAAI,EAAY,EAAG;KAEnF,EAEA,OAAQ,CAAC,EAAA,gBAAiB,EAAA,kBAAmB,EAAA,mBAAoB,EAAA,OAAe,CAClF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"progress.js","names":[],"sources":["../src/feedback/progress/progress.ts"],"sourcesContent":["import { define, html, prop, getHost, watchEffect, styleMap } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, reducedMotionMixin } from '../../styles';\nimport componentStyles from './progress.css?inline';\n\n/** Progress bar component properties */\nexport type OreProgressProps = {\n /** Theme color for the fill bar */\n color?: ThemeColor;\n /** Floating chip centered above the fill endpoint (linear only). Hidden in indeterminate mode. Position formula: left = fill% − half chip width (CSS: left:X%; transform:translateX(−50%)). */\n 'floating-label'?: string;\n /** When true, shows an infinite animation — use when progress is unknown. */\n indeterminate?: boolean;\n /** Accessible name AND visible text label.\n * - Linear without `title`: rendered at the end of the bar.\n * - Linear with `title`: moved into the header row above the bar.\n * - Circular: large text centered inside the ring. */\n label?: string;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Size variant controlling bar height */\n size?: ComponentSize;\n /** Title text.\n * - Linear: displayed as a header above the bar; moves `label` into the header row.\n * - Circular: smaller text displayed below the `label` inside the ring. */\n title?: string;\n /** 'linear' (default), 'circular', or 'vertical' */\n type?: 'linear' | 'circular' | 'vertical';\n /** Current progress value (0 to `max`). Ignored when `indeterminate`. */\n value?: number;\n /** Human-readable value text for screen readers (e.g. \"Step 2 of 5\", \"75%\"). Overrides the raw aria-valuenow when set. */\n 'value-text'?: string;\n};\n\n/**\n * A linear progress bar for conveying operation progress.\n * Supports determinate (known value) and indeterminate (unknown duration) modes.\n *\n * @element ore-progress\n *\n * @attr {number} value - Current value (0–max). Defaults to 0.\n * @attr {number} max - Maximum value. Defaults to 100.\n * @attr {boolean} indeterminate - Show infinite animation (ignores value/max).\n * @attr {string} color - Theme color: 'primary' | 'success' | 'warning' | 'error' | …\n * @attr {string} size - Bar height/width: 'sm' | 'md' | 'lg'\n * @attr {string} type - 'linear' (default) | 'circular' | 'vertical'\n *\n * @cssprop --progress-width - Bar width override (vertical only)\n * @attr {string} label - Visible text label + accessible name. Linear: at bar end (or header row with title). Circular: large text centered inside the ring.\n * @attr {string} title - Title text. Linear: header above the bar (moves label to header row). Circular: smaller text below the label inside the ring.\n * @attr {string} floating-label - Floating chip centered above the fill endpoint (linear only); hidden when indeterminate.\n *\n * @cssprop --progress-height - Bar height override\n * @cssprop --progress-track-bg - Track background color\n * @cssprop --progress-fill - Fill bar color\n * @cssprop --progress-radius - Border radius\n * @cssprop --progress-label-gap - Gap between header/bar row and between bar and trailing label (default 0.25 rem)\n * @cssprop --progress-title-color - Title text color (defaults to currentColor)\n * @cssprop --progress-label-color - Label text color (defaults to currentColor)\n * @cssprop --progress-circle-size - Circular indicator diameter (default 6rem)\n * @cssprop --progress-circular-label-size - Font size of the label inside the ring (default --text-xl)\n * @cssprop --progress-circular-title-size - Font size of the title inside the ring (default --text-xs)\n *\n * @part fill - Progress fill element.\n * @example\n * ```html\n * <ore-progress value=\"45\"></ore-progress>\n * <ore-progress value=\"75\" max=\"100\" color=\"success\" size=\"lg\"></ore-progress>\n * <ore-progress indeterminate color=\"primary\" label=\"Loading…\"></ore-progress>\n * ```\n */\nexport const PROGRESS_TAG = 'ore-progress' as const;\ndefine<OreProgressProps>(PROGRESS_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n 'floating-label': prop.string(),\n indeterminate: prop.bool(false),\n label: prop.string(),\n max: prop.number(100),\n title: prop.string(),\n type: prop.oneOf(['linear', 'circular', 'vertical'] as const, 'linear'),\n value: prop.number(0),\n 'value-text': prop.string(),\n },\n\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n // The SVG circle circumference for a radius of 45 (viewBox 0 0 100 100)\n const RADIUS = 45;\n const CIRC = 2 * Math.PI * RADIUS; // ~282.7\n\n const percent = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return `${(v / m) * 100}%`;\n });\n\n const dashoffset = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return CIRC - (v / m) * CIRC;\n });\n\n const ariaValueNow = () => (props.indeterminate.value ? null : String(props.value.value));\n const ariaLabel = () => props.label.value ?? props.title.value ?? 'Progress';\n const circularStyle = styleMap({ '--_circ': `${CIRC}px` });\n const strokeDasharray = () => (props.indeterminate.value ? undefined : `${CIRC}px`);\n const strokeDashoffset = () => (props.indeterminate.value ? undefined : `${dashoffset.value}px`);\n const isVertical = computed(() => props.type.value === 'vertical');\n const linearFillStyle = styleMap({\n height: () => (!props.indeterminate.value && isVertical.value ? percent.value : null),\n width: () => (!props.indeterminate.value && !isVertical.value ? percent.value : null),\n });\n\n watch(() => {\n el.style.setProperty('--_percent', props.indeterminate.value ? '0%' : percent.value);\n });\n\n const circularTemplate = () => html`\n <div\n class=\"circular-track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\"\n style=\"${circularStyle}\">\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle class=\"circle-bg\" cx=\"50\" cy=\"50\" r=\"${RADIUS}\"></circle>\n <circle\n class=\"circle-fill\"\n cx=\"50\"\n cy=\"50\"\n r=\"${RADIUS}\"\n stroke-dasharray=\"${strokeDasharray}\"\n stroke-dashoffset=\"${strokeDashoffset}\"></circle>\n </svg>\n <div class=\"circular-inner\">\n <span class=\"circular-label\">${() => props.label.value ?? ''}</span>\n <span class=\"circular-title\">${() => props.title.value ?? ''}</span>\n </div>\n </div>\n `;\n\n const barTemplate = () => html`\n <div class=\"wrapper\">\n <div class=\"header\">\n <span class=\"progress-title\">${() => props.title.value ?? ''}</span>\n <span class=\"end-label header-label\">${() => props.label.value ?? ''}</span>\n </div>\n <div class=${() => `bar-row${isVertical.value ? ' bar-row-vertical' : ''}`}>\n <div class=\"track-outer\">\n <div\n class=\"track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\">\n <div class=\"fill\" part=\"fill\" style=\"${linearFillStyle}\"></div>\n </div>\n ${() =>\n !isVertical.value\n ? html`\n <span class=\"floating-label\">${props['floating-label']}</span>\n `\n : null}\n </div>\n <span class=\"end-label row-label\">${() => props.label.value ?? ''}</span>\n </div>\n </div>\n `;\n\n return html`\n ${() => (props.type.value === 'circular' ? circularTemplate() : barTemplate())}\n `;\n },\n\n styles: [colorThemeMixin, forcedColorsMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":";;;;;;;AA2EA,IAAa,IAAe;AAC5B,EAAyB,GAAc;CACrC,OAAO;EACL,GAAG;EACH,GAAG;EACH,kBAAkB,EAAK,OAAO;EAC9B,eAAe,EAAK,KAAK,EAAK;EAC9B,OAAO,EAAK,OAAO;EACnB,KAAK,EAAK,OAAO,GAAG;EACpB,OAAO,EAAK,OAAO;EACnB,MAAM,EAAK,MAAM;GAAC;GAAU;GAAY;EAAU,GAAY,QAAQ;EACtE,OAAO,EAAK,OAAO,CAAC;EACpB,cAAc,EAAK,OAAO;CAC5B;CAEA,MAAM,GAAO;EACX,IAAM,IAAK,EAAQ,GACb,IAAQ,GAIR,IAAO,IAAI,KAAK,KAAK,IAErB,IAAU,QAIP,GAHG,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,GAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAGtE,IAFD,KAAK,IAAI,GAAG,OAAO,EAAM,IAAI,KAAK,CAE7B,IAAK,IAAI,EACzB,GAEK,IAAa,QAAe;GAChC,IAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,GAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAAC,GAC5E,IAAI,KAAK,IAAI,GAAG,OAAO,EAAM,IAAI,KAAK,CAAC;GAE7C,OAAO,IAAQ,IAAI,IAAK;EAC1B,CAAC,GAEK,UAAsB,EAAM,cAAc,QAAQ,OAAO,OAAO,EAAM,MAAM,KAAK,GACjF,UAAkB,EAAM,MAAM,SAAS,EAAM,MAAM,SAAS,YAC5D,IAAgB,EAAS,EAAE,WAAW,GAAG,EAAK,IAAI,CAAC,GACnD,UAAyB,EAAM,cAAc,QAAQ,KAAA,IAAY,GAAG,EAAK,KACzE,UAA0B,EAAM,cAAc,QAAQ,KAAA,IAAY,GAAG,EAAW,MAAM,KACtF,IAAa,QAAe,EAAM,KAAK,UAAU,UAAU,GAC3D,IAAkB,EAAS;GAC/B,cAAe,CAAC,EAAM,cAAc,SAAS,EAAW,QAAQ,EAAQ,QAAQ;GAChF,aAAc,CAAC,EAAM,cAAc,SAAS,CAAC,EAAW,QAAQ,EAAQ,QAAQ;EAClF,CAAC;EAED,QAAY;GACV,EAAG,MAAM,YAAY,cAAc,EAAM,cAAc,QAAQ,OAAO,EAAQ,KAAK;EACrF,CAAC;EAED,IAAM,UAAyB,CAAI;;;;yBAId,EAAa;;yBAEb,EAAM,IAAI;sBACb,EAAU;0BACN,EAAM,cAAc;iBAC7B,EAAc;;yDAE0B,GAAO;;;;;iBAK/C,GAAO;gCACQ,EAAgB;iCACf,EAAiB;;;+CAGH,EAAM,MAAM,SAAS,GAAG;+CACxB,EAAM,MAAM,SAAS,GAAG;;;OAK7D,UAAoB,CAAI;;;+CAGa,EAAM,MAAM,SAAS,GAAG;uDAChB,EAAM,MAAM,SAAS,GAAG;;2BAEpD,UAAU,EAAW,QAAQ,sBAAsB,KAAK;;;;;+BAKpD,EAAa;;+BAEb,EAAM,IAAI;4BACb,EAAU;gCACN,EAAM,cAAc;qDACC,EAAgB;;oBAGtD,EAAW,QAIR,OAHA,CAAI;mDAC6B,EAAM,kBAAkB;oBAEpD;;oDAE6B,EAAM,MAAM,SAAS,GAAG;;;;EAKxE,OAAO,CAAI;cACA,EAAM,KAAK,UAAU,aAAa,EAAiB,IAAI,EAAY,EAAG;;CAEnF;CAEA,QAAQ;EAAC;EAAiB;EAAmB;EAAoB;CAAe;AAClF,CAAC"}
1
+ {"version":3,"file":"progress.js","names":[],"sources":["../src/feedback/progress/progress.ts"],"sourcesContent":["import { define, getHost, html, prop, styleMap, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, reducedMotionMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './progress.css?inline';\n\n/** Progress bar component properties */\nexport type OreProgressProps = {\n /** Theme color for the fill bar */\n color?: ThemeColor;\n /** Floating chip centered above the fill endpoint (linear only). Hidden in indeterminate mode. Position formula: left = fill% − half chip width (CSS: left:X%; transform:translateX(−50%)). */\n 'floating-label'?: string;\n /** When true, shows an infinite animation — use when progress is unknown. */\n indeterminate?: boolean;\n /** Accessible name AND visible text label.\n * - Linear without `title`: rendered at the end of the bar.\n * - Linear with `title`: moved into the header row above the bar.\n * - Circular: large text centered inside the ring. */\n label?: string;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Size variant controlling bar height */\n size?: ComponentSize;\n /** Title text.\n * - Linear: displayed as a header above the bar; moves `label` into the header row.\n * - Circular: smaller text displayed below the `label` inside the ring. */\n title?: string;\n /** 'linear' (default), 'circular', or 'vertical' */\n type?: 'linear' | 'circular' | 'vertical';\n /** Current progress value (0 to `max`). Ignored when `indeterminate`. */\n value?: number;\n /** Human-readable value text for screen readers (e.g. \"Step 2 of 5\", \"75%\"). Overrides the raw aria-valuenow when set. */\n 'value-text'?: string;\n};\n\n/**\n * A linear progress bar for conveying operation progress.\n * Supports determinate (known value) and indeterminate (unknown duration) modes.\n *\n * @element ore-progress\n *\n * @attr {number} value - Current value (0–max). Defaults to 0.\n * @attr {number} max - Maximum value. Defaults to 100.\n * @attr {boolean} indeterminate - Show infinite animation (ignores value/max).\n * @attr {string} color - Theme color: 'primary' | 'success' | 'warning' | 'error' | …\n * @attr {string} size - Bar height/width: 'sm' | 'md' | 'lg'\n * @attr {string} type - 'linear' (default) | 'circular' | 'vertical'\n *\n * @cssprop --progress-width - Bar width override (vertical only)\n * @attr {string} label - Visible text label + accessible name. Linear: at bar end (or header row with title). Circular: large text centered inside the ring.\n * @attr {string} title - Title text. Linear: header above the bar (moves label to header row). Circular: smaller text below the label inside the ring.\n * @attr {string} floating-label - Floating chip centered above the fill endpoint (linear only); hidden when indeterminate.\n *\n * @cssprop --progress-height - Bar height override\n * @cssprop --progress-track-bg - Track background color\n * @cssprop --progress-fill - Fill bar color\n * @cssprop --progress-radius - Border radius\n * @cssprop --progress-label-gap - Gap between header/bar row and between bar and trailing label (default 0.25 rem)\n * @cssprop --progress-title-color - Title text color (defaults to currentColor)\n * @cssprop --progress-label-color - Label text color (defaults to currentColor)\n * @cssprop --progress-circle-size - Circular indicator diameter (default 6rem)\n * @cssprop --progress-circular-label-size - Font size of the label inside the ring (default --text-xl)\n * @cssprop --progress-circular-title-size - Font size of the title inside the ring (default --text-xs)\n *\n * @part fill - Progress fill element.\n * @example\n * ```html\n * <ore-progress value=\"45\"></ore-progress>\n * <ore-progress value=\"75\" max=\"100\" color=\"success\" size=\"lg\"></ore-progress>\n * <ore-progress indeterminate color=\"primary\" label=\"Loading…\"></ore-progress>\n * ```\n */\nexport const PROGRESS_TAG = 'ore-progress' as const;\ndefine<OreProgressProps>(PROGRESS_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n 'floating-label': prop.string(),\n indeterminate: prop.bool(false),\n label: prop.string(),\n max: prop.number(100),\n title: prop.string(),\n type: prop.oneOf(['linear', 'circular', 'vertical'] as const, 'linear'),\n value: prop.number(0),\n 'value-text': prop.string(),\n },\n\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n // The SVG circle circumference for a radius of 45 (viewBox 0 0 100 100)\n const RADIUS = 45;\n const CIRC = 2 * Math.PI * RADIUS; // ~282.7\n\n const percent = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return `${(v / m) * 100}%`;\n });\n\n const dashoffset = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return CIRC - (v / m) * CIRC;\n });\n\n const ariaValueNow = () => (props.indeterminate.value ? null : String(props.value.value));\n const ariaLabel = () => props.label.value ?? props.title.value ?? 'Progress';\n const circularStyle = styleMap({ '--_circ': `${CIRC}px` });\n const strokeDasharray = () => (props.indeterminate.value ? undefined : `${CIRC}px`);\n const strokeDashoffset = () => (props.indeterminate.value ? undefined : `${dashoffset.value}px`);\n const isVertical = computed(() => props.type.value === 'vertical');\n const linearFillStyle = styleMap({\n height: () => (!props.indeterminate.value && isVertical.value ? percent.value : null),\n width: () => (!props.indeterminate.value && !isVertical.value ? percent.value : null),\n });\n\n watch(() => {\n el.style.setProperty('--_percent', props.indeterminate.value ? '0%' : percent.value);\n });\n\n const circularTemplate = () => html`\n <div\n class=\"circular-track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\"\n style=\"${circularStyle}\">\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle class=\"circle-bg\" cx=\"50\" cy=\"50\" r=\"${RADIUS}\"></circle>\n <circle\n class=\"circle-fill\"\n cx=\"50\"\n cy=\"50\"\n r=\"${RADIUS}\"\n stroke-dasharray=\"${strokeDasharray}\"\n stroke-dashoffset=\"${strokeDashoffset}\"></circle>\n </svg>\n <div class=\"circular-inner\">\n <span class=\"circular-label\">${() => props.label.value ?? ''}</span>\n <span class=\"circular-title\">${() => props.title.value ?? ''}</span>\n </div>\n </div>\n `;\n\n const barTemplate = () => html`\n <div class=\"wrapper\">\n <div class=\"header\">\n <span class=\"progress-title\">${() => props.title.value ?? ''}</span>\n <span class=\"end-label header-label\">${() => props.label.value ?? ''}</span>\n </div>\n <div class=${() => `bar-row${isVertical.value ? ' bar-row-vertical' : ''}`}>\n <div class=\"track-outer\">\n <div\n class=\"track\"\n role=\"progressbar\"\n aria-valuenow=\"${ariaValueNow}\"\n aria-valuemin=\"0\"\n aria-valuemax=\"${props.max}\"\n aria-label=\"${ariaLabel}\"\n aria-valuetext=\"${props['value-text']}\">\n <div class=\"fill\" part=\"fill\" style=\"${linearFillStyle}\"></div>\n </div>\n ${() =>\n !isVertical.value\n ? html`\n <span class=\"floating-label\">${props['floating-label']}</span>\n `\n : null}\n </div>\n <span class=\"end-label row-label\">${() => props.label.value ?? ''}</span>\n </div>\n </div>\n `;\n\n return html`\n ${() => (props.type.value === 'circular' ? circularTemplate() : barTemplate())}\n `;\n },\n\n styles: [colorThemeMixin, forcedColorsMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":";;;;;;;AAyEA,IAAa,IAAe;AAC5B,EAAyB,GAAc;CACrC,OAAO;EACL,GAAG;EACH,GAAG;EACH,kBAAkB,EAAK,OAAO;EAC9B,eAAe,EAAK,KAAK,EAAK;EAC9B,OAAO,EAAK,OAAO;EACnB,KAAK,EAAK,OAAO,GAAG;EACpB,OAAO,EAAK,OAAO;EACnB,MAAM,EAAK,MAAM;GAAC;GAAU;GAAY;EAAU,GAAY,QAAQ;EACtE,OAAO,EAAK,OAAO,CAAC;EACpB,cAAc,EAAK,OAAO;CAC5B;CAEA,MAAM,GAAO;EACX,IAAM,IAAK,EAAQ,GACb,IAAQ,GAIR,IAAO,IAAI,KAAK,KAAK,IAErB,IAAU,QAIP,GAHG,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,GAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAGtE,IAFD,KAAK,IAAI,GAAG,OAAO,EAAM,IAAI,KAAK,CAE7B,IAAK,IAAI,EACzB,GAEK,IAAa,QAAe;GAChC,IAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,EAAM,MAAM,KAAK,GAAG,OAAO,EAAM,IAAI,KAAK,CAAC,CAAC,GAC5E,IAAI,KAAK,IAAI,GAAG,OAAO,EAAM,IAAI,KAAK,CAAC;GAE7C,OAAO,IAAQ,IAAI,IAAK;EAC1B,CAAC,GAEK,UAAsB,EAAM,cAAc,QAAQ,OAAO,OAAO,EAAM,MAAM,KAAK,GACjF,UAAkB,EAAM,MAAM,SAAS,EAAM,MAAM,SAAS,YAC5D,IAAgB,EAAS,EAAE,WAAW,GAAG,EAAK,IAAI,CAAC,GACnD,UAAyB,EAAM,cAAc,QAAQ,KAAA,IAAY,GAAG,EAAK,KACzE,UAA0B,EAAM,cAAc,QAAQ,KAAA,IAAY,GAAG,EAAW,MAAM,KACtF,IAAa,QAAe,EAAM,KAAK,UAAU,UAAU,GAC3D,IAAkB,EAAS;GAC/B,cAAe,CAAC,EAAM,cAAc,SAAS,EAAW,QAAQ,EAAQ,QAAQ;GAChF,aAAc,CAAC,EAAM,cAAc,SAAS,CAAC,EAAW,QAAQ,EAAQ,QAAQ;EAClF,CAAC;EAED,QAAY;GACV,EAAG,MAAM,YAAY,cAAc,EAAM,cAAc,QAAQ,OAAO,EAAQ,KAAK;EACrF,CAAC;EAED,IAAM,UAAyB,CAAI;;;;yBAId,EAAa;;yBAEb,EAAM,IAAI;sBACb,EAAU;0BACN,EAAM,cAAc;iBAC7B,EAAc;;yDAE0B,GAAO;;;;;iBAK/C,GAAO;gCACQ,EAAgB;iCACf,EAAiB;;;+CAGH,EAAM,MAAM,SAAS,GAAG;+CACxB,EAAM,MAAM,SAAS,GAAG;;;OAK7D,UAAoB,CAAI;;;+CAGa,EAAM,MAAM,SAAS,GAAG;uDAChB,EAAM,MAAM,SAAS,GAAG;;2BAEpD,UAAU,EAAW,QAAQ,sBAAsB,KAAK;;;;;+BAKpD,EAAa;;+BAEb,EAAM,IAAI;4BACb,EAAU;gCACN,EAAM,cAAc;qDACC,EAAgB;;oBAGtD,EAAW,QAIR,OAHA,CAAI;mDAC6B,EAAM,kBAAkB;oBAEpD;;oDAE6B,EAAM,MAAM,SAAS,GAAG;;;;EAKxE,OAAO,CAAI;cACA,EAAM,KAAK,UAAU,aAAa,EAAiB,IAAI,EAAY,EAAG;;CAEnF;CAEA,QAAQ;EAAC;EAAiB;EAAmB;EAAoB;CAAe;AAClF,CAAC"}
@@ -1,12 +1,12 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core/ore.cjs"),t=require("./core/choice-field.cjs"),n=require("./styles/mixins/states.css.cjs"),r=require("./core/light-dom.cjs"),i=require("./core/nav.cjs"),a=require("./shared/prop-bundles.cjs"),o=require("./inputs/radio-group/radio-group.css.cjs");let s=require("@vielzeug/ore");require("@vielzeug/ripple");var c=(0,s.createContext)(`OreRadioGroup`),l=`ore-radio-group`;(0,s.define)(l,{formAssociated:!0,props:{...a.themableBundle,...a.sizableBundle,...a.disablableBundle,error:s.prop.string(),helper:s.prop.string(),label:s.prop.string(),name:s.prop.string(),orientation:s.prop.oneOf([`horizontal`,`vertical`],`vertical`),required:s.prop.bool(!1),value:{...s.prop.string(),reflect:!1}},setup(n){let a=(0,s.getHost)(),o=(0,s.useEmit)(),l=(0,s.useSlots)(),u=s.watchEffect,d=t.createChoiceField({disabled:n.disabled,error:n.error,helper:n.helper,label:n.label,prefix:`radio-group`,required:n.required,signal:e.lifecycleSignal(s.onCleanup),value:n.value});d.attachFormField((0,s.useField)({disabled:d.disabled,onReset:d.reset,toFormValue:e=>e,validationMessage:d.validationMessage,validity:d.validity,value:d.formValue}));let f=d.selectedValue,p=n.disabled;(0,s.bind)({attr:{size:n.size,value:()=>f.value||null}});let m=()=>r.getLightChildrenByTag(a,`ore-radio`),h=()=>p.value?[]:m().filter(e=>!e.hasAttribute(`disabled`)),g=e=>r.getChoiceLabel(m(),e),_=(e,t)=>{d.setValues(e?[e]:[]);let n=e?[g(e)]:[];o(`change`,{labels:n,originalEvent:t,values:e?[e]:[]}),d.triggerValidation(`blur`)};(0,s.provide)(c,{color:n.color,disabled:p,name:n.name,select:_,size:n.size,value:f}),u(()=>{l.elements().value,f.value;let e=m();for(let t of e){let e=t.getAttribute(`value`)??``;t.toggleAttribute(`checked`,e===f.value),n.name.value?t.setAttribute(`name`,n.name.value):t.removeAttribute(`name`),n.color.value?t.setAttribute(`color`,n.color.value):t.removeAttribute(`color`),n.size.value?t.setAttribute(`size`,n.size.value):t.removeAttribute(`size`),t.toggleAttribute(`disabled`,p.value)}}),u(()=>{l.elements().value;let e=m(),t=!1;for(let n of e){let e=n.getAttribute(`value`)===f.value;n.setAttribute(`tabindex`,e&&!p.value?`0`:`-1`),e&&!p.value&&(t=!0)}if(!t&&e.length>0){let t=e.find(e=>!e.hasAttribute(`disabled`));t&&t.setAttribute(`tabindex`,`0`)}});let v=i.createListControl({getItems:h,keys:{next:[`ArrowDown`,`ArrowRight`],prev:[`ArrowUp`,`ArrowLeft`]},loop:!0,onNavigate:(e,t,n)=>{let r=h()[t];r&&(r.focus(),r.tagName===`ORE-RADIO`&&_(r.getAttribute(`value`)??``,n))},signal:e.lifecycleSignal(s.onCleanup)});(0,s.bind)({on:{change:e=>{e.target!==a&&(e.stopPropagation(),_(e.target.getAttribute(`value`)??``,e))},keydown:e=>{let t=h();if(!t.length)return;let n=t.indexOf(document.activeElement);n!==-1&&(v.set(n),v.handleKeydown(e))}}});let y=(0,s.createStableId)(`radio-group-legend`);return s.html`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/states.css.cjs"),t=require("./core/choice-field.cjs"),n=require("./core/light-dom.cjs"),r=require("./core/ore.cjs"),i=require("./core/nav.cjs"),a=require("./shared/prop-bundles.cjs"),o=require("./inputs/radio-group/radio-group.css.cjs");let s=require("@vielzeug/ore");var c=(0,s.createContext)(`OreRadioGroup`),l=`ore-radio-group`;(0,s.define)(l,{formAssociated:!0,props:{...a.themableBundle,...a.sizableBundle,...a.disablableBundle,error:s.prop.string(),helper:s.prop.string(),label:s.prop.string(),name:s.prop.string(),orientation:s.prop.oneOf([`horizontal`,`vertical`],`vertical`),required:s.prop.bool(!1),value:{...s.prop.string(),reflect:!1}},setup(e){let a=(0,s.getHost)(),o=(0,s.useEmit)(),l=(0,s.useSlots)(),u=s.watchEffect,d=t.createChoiceField({disabled:e.disabled,error:e.error,helper:e.helper,label:e.label,prefix:`radio-group`,required:e.required,signal:r.lifecycleSignal(s.onCleanup),value:e.value});d.attachFormField((0,s.useField)({disabled:d.disabled,onReset:d.reset,toFormValue:e=>e,validationMessage:d.validationMessage,validity:d.validity,value:d.formValue}));let f=d.selectedValue,p=e.disabled;(0,s.bind)({attr:{size:e.size,value:()=>f.value||null}});let m=()=>n.getLightChildrenByTag(a,`ore-radio`),h=()=>p.value?[]:m().filter(e=>!e.hasAttribute(`disabled`)),g=e=>n.getChoiceLabel(m(),e),_=(e,t)=>{d.setValues(e?[e]:[]);let n=e?[g(e)]:[];o(`change`,{labels:n,originalEvent:t,values:e?[e]:[]}),d.triggerValidation(`blur`)};(0,s.provide)(c,{color:e.color,disabled:p,name:e.name,select:_,size:e.size,value:f}),u(()=>{l.elements().value,f.value;let t=m();for(let n of t){let t=n.getAttribute(`value`)??``;n.toggleAttribute(`checked`,t===f.value),e.name.value?n.setAttribute(`name`,e.name.value):n.removeAttribute(`name`),e.color.value?n.setAttribute(`color`,e.color.value):n.removeAttribute(`color`),e.size.value?n.setAttribute(`size`,e.size.value):n.removeAttribute(`size`),n.toggleAttribute(`disabled`,p.value)}}),u(()=>{l.elements().value;let e=m(),t=!1;for(let n of e){let e=n.getAttribute(`value`)===f.value;n.setAttribute(`tabindex`,e&&!p.value?`0`:`-1`),e&&!p.value&&(t=!0)}if(!t&&e.length>0){let t=e.find(e=>!e.hasAttribute(`disabled`));t&&t.setAttribute(`tabindex`,`0`)}});let v=i.createListControl({getItems:h,keys:{next:[`ArrowDown`,`ArrowRight`],prev:[`ArrowUp`,`ArrowLeft`]},loop:!0,onNavigate:(e,t,n)=>{let r=h()[t];r&&(r.focus(),r.tagName===`ORE-RADIO`&&_(r.getAttribute(`value`)??``,n))},signal:r.lifecycleSignal(s.onCleanup)});(0,s.bind)({on:{change:e=>{e.target!==a&&(e.stopPropagation(),_(e.target.getAttribute(`value`)??``,e))},keydown:e=>{let t=h();if(!t.length)return;let n=t.indexOf(document.activeElement);n!==-1&&(v.set(n),v.handleKeydown(e))}}});let y=(0,s.createStableId)(`radio-group-legend`);return s.html`
2
2
  <fieldset
3
3
  role="radiogroup"
4
- aria-required="${()=>String(!!n.required.value)}"
4
+ aria-required="${()=>String(!!e.required.value)}"
5
5
  aria-invalid="${d.ariaInvalid}"
6
6
  aria-errormessage="${d.ariaErrorMessage}"
7
7
  aria-describedby="${d.ariaDescribedBy}">
8
- <legend id="${y}" ?hidden=${()=>!n.label.value}>
9
- ${n.label}${(0,s.when)(()=>!!n.required.value,()=>s.html`
8
+ <legend id="${y}" ?hidden=${()=>!e.label.value}>
9
+ ${e.label}${(0,s.when)(()=>!!e.required.value,()=>s.html`
10
10
  <span aria-hidden="true">*</span>
11
11
  `)}
12
12
  </legend>
@@ -23,5 +23,5 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
23
23
  ${()=>d.errorText.value||d.helperText.value}
24
24
  </div>
25
25
  </fieldset>
26
- `},styles:[n.disabledStateMixin,o.default]}),exports.RADIO_GROUP_CTX=c,exports.RADIO_GROUP_TAG=l;
26
+ `},styles:[e.disabledStateMixin,o.default]}),exports.RADIO_GROUP_CTX=c,exports.RADIO_GROUP_TAG=l;
27
27
  //# sourceMappingURL=radio-group.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"radio-group.cjs","names":[],"sources":["../src/inputs/radio-group/radio-group.ts"],"sourcesContent":["import {\n createContext,\n createStableId,\n define,\n html,\n prop,\n bind,\n getHost,\n onCleanup,\n provide,\n useEmit,\n useSlots,\n watchEffect,\n when,\n} from '@vielzeug/ore';\nimport { useField } from '@vielzeug/ore';\nimport { type Readable } from '@vielzeug/ripple';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport {\n type ChoiceChangeDetail,\n lifecycleSignal,\n createChoiceField,\n createListControl,\n getChoiceLabel,\n getLightChildrenByTag,\n} from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledStateMixin } from '../../styles';\nimport componentStyles from './radio-group.css?inline';\n\n/** Radio group component properties */\nexport type OreRadioGroupProps = {\n /** Theme color tint */\n color?: ThemeColor;\n /** Disabled state */\n disabled?: boolean;\n /** Error message text */\n error?: string;\n /** Helper text displayed below the items */\n helper?: string;\n /** Group label text */\n label?: string;\n /** Form field name */\n name?: string;\n /** Layout orientation */\n orientation?: 'horizontal' | 'vertical';\n /** Required field */\n required?: boolean;\n /** Items size preset */\n size?: ComponentSize;\n /** Initial selected value */\n value?: string;\n};\n\nexport type RadioGroupContext = {\n color: Readable<ThemeColor | undefined>;\n disabled: Readable<boolean>;\n name: Readable<string | undefined>;\n select: (value: string, originalEvent?: Event) => void;\n size: Readable<ComponentSize | undefined>;\n value: Readable<string | undefined>;\n};\n\nexport const RADIO_GROUP_CTX = createContext<RadioGroupContext | undefined>('OreRadioGroup');\n\n/** Events emitted by the radio-group component */\nexport type OreRadioGroupEvents = {\n /** Emitted when the selection changes */\n change: ChoiceChangeDetail;\n};\n\n/**\n * A group of radio buttons that allows users to select a single option from a set.\n * Supports keyboard navigation (arrows) and automatic value management.\n *\n * @element ore-radio-group\n *\n * @attr {string} value - Selected value\n * @attr {string} name - Form field name\n * @attr {string} label - Group label\n * @attr {string} orientation - Layout: 'vertical' | 'horizontal'\n * @attr {boolean} required - Required field\n *\n * @fires change - Emitted when a radio is selected. detail: { values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - Place `ore-radio` elements here\n *\n * @cssprop --radio-group-direction - Flex direction of the items list ('row' | 'column')\n * @cssprop --radio-group-gap - Gap between radio items\n * @part items - Items container.\n * @example\n * ```html\n * <ore-radio-group name=\"plan\" label=\"Choose a plan\" value=\"free\" required>\n * <ore-radio value=\"free\">Free</ore-radio>\n * <ore-radio value=\"pro\">Pro</ore-radio>\n * <ore-radio value=\"enterprise\">Enterprise</ore-radio>\n * </ore-radio-group>\n * <ore-radio-group name=\"direction\" orientation=\"horizontal\" color=\"primary\">\n * <ore-radio value=\"left\">Left</ore-radio>\n * <ore-radio value=\"right\">Right</ore-radio>\n * </ore-radio-group>\n * ```\n */\nexport const RADIO_GROUP_TAG = 'ore-radio-group' as const;\ndefine<OreRadioGroupProps>(RADIO_GROUP_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string(),\n name: prop.string(),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'vertical'),\n required: prop.bool(false),\n // Not auto-reflected (`reflect: false`) — the derived, interaction-updated selection\n // (`selectedValue`) is the single writer for this attribute, via `bind()` below; letting\n // `prop.string()`'s own default reflection also write the raw incoming value would leave\n // two effects racing to set the same attribute from different sources.\n value: { ...prop.string(), reflect: false },\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreRadioGroupEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const choice = createChoiceField({\n disabled: props.disabled,\n error: props.error,\n helper: props.helper,\n label: props.label,\n prefix: 'radio-group',\n required: props.required,\n signal: lifecycleSignal(onCleanup),\n value: props.value,\n });\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validationMessage: choice.validationMessage,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const selectedValue = choice.selectedValue;\n const isDisabled = props.disabled;\n\n bind({\n attr: {\n size: props.size,\n value: () => selectedValue.value || null,\n },\n });\n\n const getSlottedRadios = (): HTMLElement[] => getLightChildrenByTag(el, 'ore-radio');\n\n const getEnabledRadios = (): HTMLElement[] =>\n isDisabled.value ? [] : getSlottedRadios().filter((radio) => !radio.hasAttribute('disabled'));\n\n const getLabelForValue = (value: string): string => getChoiceLabel(getSlottedRadios(), value);\n\n const selectRadio = (val: string, originalEvent?: Event): void => {\n choice.setValues(val ? [val] : []);\n\n const labels = val ? [getLabelForValue(val)] : [];\n const values = val ? [val] : [];\n\n emit('change', { labels, originalEvent, values });\n choice.triggerValidation('blur');\n };\n\n provide(RADIO_GROUP_CTX, {\n color: props.color as Readable<ThemeColor | undefined>,\n disabled: isDisabled,\n name: props.name,\n select: selectRadio,\n size: props.size as Readable<ComponentSize | undefined>,\n value: selectedValue,\n });\n\n // Sync name/color/size/disabled/checked onto slotted ore-radio children.\n watch(() => {\n void slots.elements().value;\n void selectedValue.value;\n\n const radios = getSlottedRadios();\n\n for (const radio of radios) {\n const val = radio.getAttribute('value') ?? '';\n\n radio.toggleAttribute('checked', val === selectedValue.value);\n\n if (props.name.value) radio.setAttribute('name', props.name.value);\n else radio.removeAttribute('name');\n\n if (props.color.value) radio.setAttribute('color', props.color.value);\n else radio.removeAttribute('color');\n\n if (props.size.value) radio.setAttribute('size', props.size.value);\n else radio.removeAttribute('size');\n\n radio.toggleAttribute('disabled', isDisabled.value);\n }\n });\n\n // Roving tabindex: only the selected (or first) radio is tabbable.\n watch(() => {\n void slots.elements().value;\n\n const radios = getSlottedRadios();\n let hasFocusable = false;\n\n for (const radio of radios) {\n const isSelected = radio.getAttribute('value') === selectedValue.value;\n\n radio.setAttribute('tabindex', isSelected && !isDisabled.value ? '0' : '-1');\n\n if (isSelected && !isDisabled.value) hasFocusable = true;\n }\n\n if (!hasFocusable && radios.length > 0) {\n const first = radios.find((r) => !r.hasAttribute('disabled'));\n\n if (first) first.setAttribute('tabindex', '0');\n }\n });\n\n const listControl = createListControl<HTMLElement>({\n getItems: getEnabledRadios,\n keys: { next: ['ArrowDown', 'ArrowRight'], prev: ['ArrowUp', 'ArrowLeft'] },\n loop: true,\n onNavigate: (_action, index, event) => {\n const radio = getEnabledRadios()[index];\n\n if (!radio) return;\n\n radio.focus();\n\n if (radio.tagName === 'ORE-RADIO') {\n selectRadio(radio.getAttribute('value') ?? '', event);\n }\n },\n signal: lifecycleSignal(onCleanup),\n });\n\n bind({\n on: {\n change: (e: Event) => {\n if (e.target === el) return;\n\n e.stopPropagation();\n selectRadio((e.target as HTMLElement).getAttribute('value') ?? '', e);\n },\n keydown: (e: KeyboardEvent) => {\n const radios = getEnabledRadios();\n\n if (!radios.length) return;\n\n const focused = radios.indexOf(document.activeElement as HTMLElement);\n\n if (focused === -1) return;\n\n listControl.set(focused);\n listControl.handleKeydown(e);\n },\n },\n });\n\n const legendId = createStableId('radio-group-legend');\n\n return html`\n <fieldset\n role=\"radiogroup\"\n aria-required=\"${() => String(Boolean(props.required.value))}\"\n aria-invalid=\"${choice.ariaInvalid}\"\n aria-errormessage=\"${choice.ariaErrorMessage}\"\n aria-describedby=\"${choice.ariaDescribedBy}\">\n <legend id=\"${legendId}\" ?hidden=${() => !props.label.value}>\n ${props.label}${when(\n () => Boolean(props.required.value),\n () => html`\n <span aria-hidden=\"true\">*</span>\n `,\n )}\n </legend>\n <div class=\"radio-group-items\" part=\"items\">\n <slot></slot>\n </div>\n <div\n class=\"helper-text\"\n part=\"helper\"\n id=\"${choice.assistiveId}\"\n role=\"${() => (choice.errorText.value ? 'alert' : null)}\"\n aria-live=\"polite\"\n ?hidden=\"${() => !choice.errorText.value && !choice.helperText.value}\">\n ${() => choice.errorText.value || choice.helperText.value}\n </div>\n </fieldset>\n `;\n },\n styles: [disabledStateMixin, componentStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"radio-group.cjs","names":[],"sources":["../src/inputs/radio-group/radio-group.ts"],"sourcesContent":["import {\n bind,\n createContext,\n createStableId,\n define,\n getHost,\n html,\n onCleanup,\n prop,\n provide,\n useEmit,\n useField,\n useSlots,\n watchEffect,\n when,\n} from '@vielzeug/ore';\nimport type { Readable } from '@vielzeug/ripple';\nimport {\n type ChoiceChangeDetail,\n createChoiceField,\n createListControl,\n getChoiceLabel,\n getLightChildrenByTag,\n lifecycleSignal,\n} from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledStateMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './radio-group.css?inline';\n\n/** Radio group component properties */\nexport type OreRadioGroupProps = {\n /** Theme color tint */\n color?: ThemeColor;\n /** Disabled state */\n disabled?: boolean;\n /** Error message text */\n error?: string;\n /** Helper text displayed below the items */\n helper?: string;\n /** Group label text */\n label?: string;\n /** Form field name */\n name?: string;\n /** Layout orientation */\n orientation?: 'horizontal' | 'vertical';\n /** Required field */\n required?: boolean;\n /** Items size preset */\n size?: ComponentSize;\n /** Initial selected value */\n value?: string;\n};\n\nexport type RadioGroupContext = {\n color: Readable<ThemeColor | undefined>;\n disabled: Readable<boolean>;\n name: Readable<string | undefined>;\n select: (value: string, originalEvent?: Event) => void;\n size: Readable<ComponentSize | undefined>;\n value: Readable<string | undefined>;\n};\n\nexport const RADIO_GROUP_CTX = createContext<RadioGroupContext | undefined>('OreRadioGroup');\n\n/** Events emitted by the radio-group component */\nexport type OreRadioGroupEvents = {\n /** Emitted when the selection changes */\n change: ChoiceChangeDetail;\n};\n\n/**\n * A group of radio buttons that allows users to select a single option from a set.\n * Supports keyboard navigation (arrows) and automatic value management.\n *\n * @element ore-radio-group\n *\n * @attr {string} value - Selected value\n * @attr {string} name - Form field name\n * @attr {string} label - Group label\n * @attr {string} orientation - Layout: 'vertical' | 'horizontal'\n * @attr {boolean} required - Required field\n *\n * @fires change - Emitted when a radio is selected. detail: { values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - Place `ore-radio` elements here\n *\n * @cssprop --radio-group-direction - Flex direction of the items list ('row' | 'column')\n * @cssprop --radio-group-gap - Gap between radio items\n * @part items - Items container.\n * @example\n * ```html\n * <ore-radio-group name=\"plan\" label=\"Choose a plan\" value=\"free\" required>\n * <ore-radio value=\"free\">Free</ore-radio>\n * <ore-radio value=\"pro\">Pro</ore-radio>\n * <ore-radio value=\"enterprise\">Enterprise</ore-radio>\n * </ore-radio-group>\n * <ore-radio-group name=\"direction\" orientation=\"horizontal\" color=\"primary\">\n * <ore-radio value=\"left\">Left</ore-radio>\n * <ore-radio value=\"right\">Right</ore-radio>\n * </ore-radio-group>\n * ```\n */\nexport const RADIO_GROUP_TAG = 'ore-radio-group' as const;\ndefine<OreRadioGroupProps>(RADIO_GROUP_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n error: prop.string(),\n helper: prop.string(),\n label: prop.string(),\n name: prop.string(),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'vertical'),\n required: prop.bool(false),\n // Not auto-reflected (`reflect: false`) — the derived, interaction-updated selection\n // (`selectedValue`) is the single writer for this attribute, via `bind()` below; letting\n // `prop.string()`'s own default reflection also write the raw incoming value would leave\n // two effects racing to set the same attribute from different sources.\n value: { ...prop.string(), reflect: false },\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreRadioGroupEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const choice = createChoiceField({\n disabled: props.disabled,\n error: props.error,\n helper: props.helper,\n label: props.label,\n prefix: 'radio-group',\n required: props.required,\n signal: lifecycleSignal(onCleanup),\n value: props.value,\n });\n\n choice.attachFormField(\n useField<string>({\n disabled: choice.disabled,\n onReset: choice.reset,\n toFormValue: (v) => v,\n validationMessage: choice.validationMessage,\n validity: choice.validity,\n value: choice.formValue,\n }),\n );\n\n const selectedValue = choice.selectedValue;\n const isDisabled = props.disabled;\n\n bind({\n attr: {\n size: props.size,\n value: () => selectedValue.value || null,\n },\n });\n\n const getSlottedRadios = (): HTMLElement[] => getLightChildrenByTag(el, 'ore-radio');\n\n const getEnabledRadios = (): HTMLElement[] =>\n isDisabled.value ? [] : getSlottedRadios().filter((radio) => !radio.hasAttribute('disabled'));\n\n const getLabelForValue = (value: string): string => getChoiceLabel(getSlottedRadios(), value);\n\n const selectRadio = (val: string, originalEvent?: Event): void => {\n choice.setValues(val ? [val] : []);\n\n const labels = val ? [getLabelForValue(val)] : [];\n const values = val ? [val] : [];\n\n emit('change', { labels, originalEvent, values });\n choice.triggerValidation('blur');\n };\n\n provide(RADIO_GROUP_CTX, {\n color: props.color as Readable<ThemeColor | undefined>,\n disabled: isDisabled,\n name: props.name,\n select: selectRadio,\n size: props.size as Readable<ComponentSize | undefined>,\n value: selectedValue,\n });\n\n // Sync name/color/size/disabled/checked onto slotted ore-radio children.\n watch(() => {\n void slots.elements().value;\n void selectedValue.value;\n\n const radios = getSlottedRadios();\n\n for (const radio of radios) {\n const val = radio.getAttribute('value') ?? '';\n\n radio.toggleAttribute('checked', val === selectedValue.value);\n\n if (props.name.value) radio.setAttribute('name', props.name.value);\n else radio.removeAttribute('name');\n\n if (props.color.value) radio.setAttribute('color', props.color.value);\n else radio.removeAttribute('color');\n\n if (props.size.value) radio.setAttribute('size', props.size.value);\n else radio.removeAttribute('size');\n\n radio.toggleAttribute('disabled', isDisabled.value);\n }\n });\n\n // Roving tabindex: only the selected (or first) radio is tabbable.\n watch(() => {\n void slots.elements().value;\n\n const radios = getSlottedRadios();\n let hasFocusable = false;\n\n for (const radio of radios) {\n const isSelected = radio.getAttribute('value') === selectedValue.value;\n\n radio.setAttribute('tabindex', isSelected && !isDisabled.value ? '0' : '-1');\n\n if (isSelected && !isDisabled.value) hasFocusable = true;\n }\n\n if (!hasFocusable && radios.length > 0) {\n const first = radios.find((r) => !r.hasAttribute('disabled'));\n\n if (first) first.setAttribute('tabindex', '0');\n }\n });\n\n const listControl = createListControl<HTMLElement>({\n getItems: getEnabledRadios,\n keys: { next: ['ArrowDown', 'ArrowRight'], prev: ['ArrowUp', 'ArrowLeft'] },\n loop: true,\n onNavigate: (_action, index, event) => {\n const radio = getEnabledRadios()[index];\n\n if (!radio) return;\n\n radio.focus();\n\n if (radio.tagName === 'ORE-RADIO') {\n selectRadio(radio.getAttribute('value') ?? '', event);\n }\n },\n signal: lifecycleSignal(onCleanup),\n });\n\n bind({\n on: {\n change: (e: Event) => {\n if (e.target === el) return;\n\n e.stopPropagation();\n selectRadio((e.target as HTMLElement).getAttribute('value') ?? '', e);\n },\n keydown: (e: KeyboardEvent) => {\n const radios = getEnabledRadios();\n\n if (!radios.length) return;\n\n const focused = radios.indexOf(document.activeElement as HTMLElement);\n\n if (focused === -1) return;\n\n listControl.set(focused);\n listControl.handleKeydown(e);\n },\n },\n });\n\n const legendId = createStableId('radio-group-legend');\n\n return html`\n <fieldset\n role=\"radiogroup\"\n aria-required=\"${() => String(Boolean(props.required.value))}\"\n aria-invalid=\"${choice.ariaInvalid}\"\n aria-errormessage=\"${choice.ariaErrorMessage}\"\n aria-describedby=\"${choice.ariaDescribedBy}\">\n <legend id=\"${legendId}\" ?hidden=${() => !props.label.value}>\n ${props.label}${when(\n () => Boolean(props.required.value),\n () => html`\n <span aria-hidden=\"true\">*</span>\n `,\n )}\n </legend>\n <div class=\"radio-group-items\" part=\"items\">\n <slot></slot>\n </div>\n <div\n class=\"helper-text\"\n part=\"helper\"\n id=\"${choice.assistiveId}\"\n role=\"${() => (choice.errorText.value ? 'alert' : null)}\"\n aria-live=\"polite\"\n ?hidden=\"${() => !choice.errorText.value && !choice.helperText.value}\">\n ${() => choice.errorText.value || choice.helperText.value}\n </div>\n </fieldset>\n `;\n },\n styles: [disabledStateMixin, componentStyles],\n});\n"],"mappings":"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"}