@vielzeug/refine 1.5.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/dist/accordion.cjs +1 -1
  2. package/dist/accordion.cjs.map +1 -1
  3. package/dist/accordion.js +30 -28
  4. package/dist/accordion.js.map +1 -1
  5. package/dist/async.cjs +11 -11
  6. package/dist/async.cjs.map +1 -1
  7. package/dist/async.js +1 -2
  8. package/dist/async.js.map +1 -1
  9. package/dist/button-group.cjs.map +1 -1
  10. package/dist/button-group.js.map +1 -1
  11. package/dist/button.cjs +1 -1
  12. package/dist/button.cjs.map +1 -1
  13. package/dist/button.js +1 -0
  14. package/dist/button.js.map +1 -1
  15. package/dist/calendar.cjs +26 -26
  16. package/dist/calendar.cjs.map +1 -1
  17. package/dist/calendar.js +4 -5
  18. package/dist/calendar.js.map +1 -1
  19. package/dist/checkbox-group.cjs +9 -9
  20. package/dist/checkbox-group.cjs.map +1 -1
  21. package/dist/checkbox-group.js +50 -58
  22. package/dist/checkbox-group.js.map +1 -1
  23. package/dist/code-window.cjs +4 -4
  24. package/dist/code-window.cjs.map +1 -1
  25. package/dist/code-window.js +1 -2
  26. package/dist/code-window.js.map +1 -1
  27. package/dist/combobox.cjs +29 -28
  28. package/dist/combobox.cjs.map +1 -1
  29. package/dist/combobox.js +201 -195
  30. package/dist/combobox.js.map +1 -1
  31. package/dist/command-palette.cjs +6 -6
  32. package/dist/command-palette.cjs.map +1 -1
  33. package/dist/command-palette.js +46 -47
  34. package/dist/command-palette.js.map +1 -1
  35. package/dist/content/card/card.css.cjs +1 -1
  36. package/dist/content/card/card.css.cjs.map +1 -1
  37. package/dist/content/card/card.css.js +1 -1
  38. package/dist/content/card/card.css.js.map +1 -1
  39. package/dist/content/chat-message/chat-message.css.cjs +1 -1
  40. package/dist/content/chat-message/chat-message.css.cjs.map +1 -1
  41. package/dist/content/chat-message/chat-message.css.js +1 -1
  42. package/dist/content/chat-message/chat-message.css.js.map +1 -1
  43. package/dist/content/code-window/code-window.d.ts.map +1 -1
  44. package/dist/content/icon/icon.d.ts.map +1 -1
  45. package/dist/content/index.d.ts +4 -0
  46. package/dist/content/index.d.ts.map +1 -1
  47. package/dist/content/list/_list-item-reveal.cjs +2 -0
  48. package/dist/content/list/_list-item-reveal.cjs.map +1 -0
  49. package/dist/content/list/_list-item-reveal.d.ts +25 -0
  50. package/dist/content/list/_list-item-reveal.d.ts.map +1 -0
  51. package/dist/content/list/_list-item-reveal.js +33 -0
  52. package/dist/content/list/_list-item-reveal.js.map +1 -0
  53. package/dist/content/list/list-item.css.cjs +2 -0
  54. package/dist/content/list/list-item.css.cjs.map +1 -0
  55. package/dist/content/list/list-item.css.js +6 -0
  56. package/dist/content/list/list-item.css.js.map +1 -0
  57. package/dist/content/list/list-item.d.ts +111 -0
  58. package/dist/content/list/list-item.d.ts.map +1 -0
  59. package/dist/content/list/list.css.cjs +2 -0
  60. package/dist/content/list/list.css.cjs.map +1 -0
  61. package/dist/content/list/list.css.js +6 -0
  62. package/dist/content/list/list.css.js.map +1 -0
  63. package/dist/content/list/list.d.ts +93 -0
  64. package/dist/content/list/list.d.ts.map +1 -0
  65. package/dist/custom-elements.json +5693 -5090
  66. package/dist/datagrid.cjs +2 -2
  67. package/dist/datagrid.js +206 -206
  68. package/dist/datagrid.js.map +1 -1
  69. package/dist/date-picker.cjs +2 -1
  70. package/dist/date-picker.cjs.map +1 -1
  71. package/dist/date-picker.js +2 -0
  72. package/dist/date-picker.js.map +1 -1
  73. package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -1
  74. package/dist/disclosure/tabs/tabs.d.ts.map +1 -1
  75. package/dist/drawer.cjs +1 -1
  76. package/dist/drawer.cjs.map +1 -1
  77. package/dist/drawer.js +47 -48
  78. package/dist/drawer.js.map +1 -1
  79. package/dist/feedback/async/async.d.ts.map +1 -1
  80. package/dist/feedback/progress/progress.d.ts.map +1 -1
  81. package/dist/file-input.cjs +108 -42
  82. package/dist/file-input.cjs.map +1 -1
  83. package/dist/file-input.js +215 -156
  84. package/dist/file-input.js.map +1 -1
  85. package/dist/headless/aria-reflection.cjs +2 -0
  86. package/dist/headless/aria-reflection.cjs.map +1 -0
  87. package/dist/headless/aria-reflection.d.ts +27 -0
  88. package/dist/headless/aria-reflection.d.ts.map +1 -0
  89. package/dist/headless/aria-reflection.js +18 -0
  90. package/dist/headless/aria-reflection.js.map +1 -0
  91. package/dist/headless/checkable.cjs +1 -1
  92. package/dist/headless/checkable.cjs.map +1 -1
  93. package/dist/headless/checkable.d.ts +2 -10
  94. package/dist/headless/checkable.d.ts.map +1 -1
  95. package/dist/headless/checkable.js +29 -29
  96. package/dist/headless/checkable.js.map +1 -1
  97. package/dist/headless/choice-field.cjs +1 -1
  98. package/dist/headless/choice-field.cjs.map +1 -1
  99. package/dist/headless/choice-field.d.ts +2 -7
  100. package/dist/headless/choice-field.d.ts.map +1 -1
  101. package/dist/headless/choice-field.js +37 -37
  102. package/dist/headless/choice-field.js.map +1 -1
  103. package/dist/headless/field-base.cjs +1 -1
  104. package/dist/headless/field-base.cjs.map +1 -1
  105. package/dist/headless/field-base.d.ts +17 -0
  106. package/dist/headless/field-base.d.ts.map +1 -1
  107. package/dist/headless/field-base.js +21 -6
  108. package/dist/headless/field-base.js.map +1 -1
  109. package/dist/headless/focus.cjs +1 -1
  110. package/dist/headless/focus.cjs.map +1 -1
  111. package/dist/headless/focus.d.ts +7 -0
  112. package/dist/headless/focus.d.ts.map +1 -1
  113. package/dist/headless/focus.js +6 -6
  114. package/dist/headless/focus.js.map +1 -1
  115. package/dist/headless/index.d.ts +4 -2
  116. package/dist/headless/index.d.ts.map +1 -1
  117. package/dist/headless/nav.cjs +1 -1
  118. package/dist/headless/nav.cjs.map +1 -1
  119. package/dist/headless/nav.d.ts +12 -0
  120. package/dist/headless/nav.d.ts.map +1 -1
  121. package/dist/headless/nav.js +68 -50
  122. package/dist/headless/nav.js.map +1 -1
  123. package/dist/headless/overlay.cjs +1 -1
  124. package/dist/headless/overlay.cjs.map +1 -1
  125. package/dist/headless/overlay.d.ts +2 -0
  126. package/dist/headless/overlay.d.ts.map +1 -1
  127. package/dist/headless/overlay.js +8 -5
  128. package/dist/headless/overlay.js.map +1 -1
  129. package/dist/headless/ref-callback.cjs +2 -0
  130. package/dist/headless/ref-callback.cjs.map +1 -0
  131. package/dist/headless/ref-callback.d.ts +26 -0
  132. package/dist/headless/ref-callback.d.ts.map +1 -0
  133. package/dist/headless/ref-callback.js +13 -0
  134. package/dist/headless/ref-callback.js.map +1 -0
  135. package/dist/headless/swipe.cjs +1 -1
  136. package/dist/headless/swipe.cjs.map +1 -1
  137. package/dist/headless/swipe.d.ts +2 -0
  138. package/dist/headless/swipe.d.ts.map +1 -1
  139. package/dist/headless/swipe.js +26 -21
  140. package/dist/headless/swipe.js.map +1 -1
  141. package/dist/headless.cjs +1 -1
  142. package/dist/headless.js +28 -26
  143. package/dist/icon.cjs +1 -1
  144. package/dist/icon.cjs.map +1 -1
  145. package/dist/icon.js +35 -38
  146. package/dist/icon.js.map +1 -1
  147. package/dist/index.cjs +1 -1
  148. package/dist/index.js +63 -61
  149. package/dist/input.cjs +29 -26
  150. package/dist/input.cjs.map +1 -1
  151. package/dist/input.js +91 -79
  152. package/dist/input.js.map +1 -1
  153. package/dist/inputs/button/button.css.cjs +1 -1
  154. package/dist/inputs/button/button.css.cjs.map +1 -1
  155. package/dist/inputs/button/button.css.js +1 -1
  156. package/dist/inputs/button/button.css.js.map +1 -1
  157. package/dist/inputs/button/button.d.ts +8 -0
  158. package/dist/inputs/button/button.d.ts.map +1 -1
  159. package/dist/inputs/calendar/calendar.d.ts.map +1 -1
  160. package/dist/inputs/checkbox/checkbox.css.cjs +1 -1
  161. package/dist/inputs/checkbox/checkbox.css.cjs.map +1 -1
  162. package/dist/inputs/checkbox/checkbox.css.js +1 -1
  163. package/dist/inputs/checkbox/checkbox.css.js.map +1 -1
  164. package/dist/inputs/combobox/combobox.d.ts +1 -0
  165. package/dist/inputs/combobox/combobox.d.ts.map +1 -1
  166. package/dist/inputs/date-picker/date-picker.css.cjs +1 -1
  167. package/dist/inputs/date-picker/date-picker.css.cjs.map +1 -1
  168. package/dist/inputs/date-picker/date-picker.css.js +1 -1
  169. package/dist/inputs/date-picker/date-picker.css.js.map +1 -1
  170. package/dist/inputs/date-picker/date-picker.d.ts +6 -0
  171. package/dist/inputs/date-picker/date-picker.d.ts.map +1 -1
  172. package/dist/inputs/file-input/file-input-upload.cjs +2 -0
  173. package/dist/inputs/file-input/file-input-upload.cjs.map +1 -0
  174. package/dist/inputs/file-input/file-input-upload.d.ts +76 -0
  175. package/dist/inputs/file-input/file-input-upload.d.ts.map +1 -0
  176. package/dist/inputs/file-input/file-input-upload.js +145 -0
  177. package/dist/inputs/file-input/file-input-upload.js.map +1 -0
  178. package/dist/inputs/file-input/file-input.css.cjs +1 -1
  179. package/dist/inputs/file-input/file-input.css.cjs.map +1 -1
  180. package/dist/inputs/file-input/file-input.css.js +1 -1
  181. package/dist/inputs/file-input/file-input.css.js.map +1 -1
  182. package/dist/inputs/file-input/file-input.d.ts +54 -1
  183. package/dist/inputs/file-input/file-input.d.ts.map +1 -1
  184. package/dist/inputs/input/input.css.cjs +1 -1
  185. package/dist/inputs/input/input.css.cjs.map +1 -1
  186. package/dist/inputs/input/input.css.js +1 -1
  187. package/dist/inputs/input/input.css.js.map +1 -1
  188. package/dist/inputs/input/input.d.ts +13 -0
  189. package/dist/inputs/input/input.d.ts.map +1 -1
  190. package/dist/inputs/message-composer/message-composer.css.cjs +1 -1
  191. package/dist/inputs/message-composer/message-composer.css.cjs.map +1 -1
  192. package/dist/inputs/message-composer/message-composer.css.js +1 -1
  193. package/dist/inputs/message-composer/message-composer.css.js.map +1 -1
  194. package/dist/inputs/message-composer/message-composer.d.ts +7 -0
  195. package/dist/inputs/message-composer/message-composer.d.ts.map +1 -1
  196. package/dist/inputs/number-input/number-input.css.cjs +1 -1
  197. package/dist/inputs/number-input/number-input.css.cjs.map +1 -1
  198. package/dist/inputs/number-input/number-input.css.js +1 -1
  199. package/dist/inputs/number-input/number-input.css.js.map +1 -1
  200. package/dist/inputs/number-input/number-input.d.ts +15 -0
  201. package/dist/inputs/number-input/number-input.d.ts.map +1 -1
  202. package/dist/inputs/otp-input/otp-input.css.cjs +1 -1
  203. package/dist/inputs/otp-input/otp-input.css.cjs.map +1 -1
  204. package/dist/inputs/otp-input/otp-input.css.js +1 -1
  205. package/dist/inputs/otp-input/otp-input.css.js.map +1 -1
  206. package/dist/inputs/radio/radio.d.ts.map +1 -1
  207. package/dist/inputs/select/select.d.ts +1 -0
  208. package/dist/inputs/select/select.d.ts.map +1 -1
  209. package/dist/inputs/shared/index.d.ts +1 -1
  210. package/dist/inputs/shared/index.d.ts.map +1 -1
  211. package/dist/inputs/shared/templates.cjs +26 -3
  212. package/dist/inputs/shared/templates.cjs.map +1 -1
  213. package/dist/inputs/shared/templates.d.ts +20 -0
  214. package/dist/inputs/shared/templates.d.ts.map +1 -1
  215. package/dist/inputs/shared/templates.js +29 -5
  216. package/dist/inputs/shared/templates.js.map +1 -1
  217. package/dist/inputs/switch/switch.css.cjs +1 -1
  218. package/dist/inputs/switch/switch.css.cjs.map +1 -1
  219. package/dist/inputs/switch/switch.css.js +1 -1
  220. package/dist/inputs/switch/switch.css.js.map +1 -1
  221. package/dist/inputs/switch/switch.d.ts.map +1 -1
  222. package/dist/inputs/textarea/textarea.css.cjs +1 -1
  223. package/dist/inputs/textarea/textarea.css.cjs.map +1 -1
  224. package/dist/inputs/textarea/textarea.css.js +1 -1
  225. package/dist/inputs/textarea/textarea.css.js.map +1 -1
  226. package/dist/inputs/textarea/textarea.d.ts +14 -0
  227. package/dist/inputs/textarea/textarea.d.ts.map +1 -1
  228. package/dist/inputs/time-picker/time-picker.css.cjs +1 -1
  229. package/dist/inputs/time-picker/time-picker.css.cjs.map +1 -1
  230. package/dist/inputs/time-picker/time-picker.css.js +1 -1
  231. package/dist/inputs/time-picker/time-picker.css.js.map +1 -1
  232. package/dist/inputs/time-picker/time-picker.d.ts +6 -0
  233. package/dist/inputs/time-picker/time-picker.d.ts.map +1 -1
  234. package/dist/list-item.cjs +22 -0
  235. package/dist/list-item.cjs.map +1 -0
  236. package/dist/list-item.js +91 -0
  237. package/dist/list-item.js.map +1 -0
  238. package/dist/list.cjs +2 -0
  239. package/dist/list.cjs.map +1 -0
  240. package/dist/list.js +64 -0
  241. package/dist/list.js.map +1 -0
  242. package/dist/menu.cjs +4 -4
  243. package/dist/menu.cjs.map +1 -1
  244. package/dist/menu.js +60 -59
  245. package/dist/menu.js.map +1 -1
  246. package/dist/message-composer.cjs +14 -20
  247. package/dist/message-composer.cjs.map +1 -1
  248. package/dist/message-composer.js +63 -64
  249. package/dist/message-composer.js.map +1 -1
  250. package/dist/number-input.cjs +5 -3
  251. package/dist/number-input.cjs.map +1 -1
  252. package/dist/number-input.js +8 -4
  253. package/dist/number-input.js.map +1 -1
  254. package/dist/otp-input.cjs +9 -9
  255. package/dist/otp-input.cjs.map +1 -1
  256. package/dist/otp-input.js +70 -62
  257. package/dist/otp-input.js.map +1 -1
  258. package/dist/overlay/menu/menu-item.css.cjs +1 -1
  259. package/dist/overlay/menu/menu-item.css.cjs.map +1 -1
  260. package/dist/overlay/menu/menu-item.css.js +1 -1
  261. package/dist/overlay/menu/menu-item.css.js.map +1 -1
  262. package/dist/overlay/menu/menu-separator.css.cjs +1 -1
  263. package/dist/overlay/menu/menu-separator.css.cjs.map +1 -1
  264. package/dist/overlay/menu/menu-separator.css.js +1 -1
  265. package/dist/overlay/menu/menu-separator.css.js.map +1 -1
  266. package/dist/overlay/menu/menu.css.cjs +1 -1
  267. package/dist/overlay/menu/menu.css.cjs.map +1 -1
  268. package/dist/overlay/menu/menu.css.js +1 -1
  269. package/dist/overlay/menu/menu.css.js.map +1 -1
  270. package/dist/overlay/shared/use-dialog.cjs +1 -1
  271. package/dist/overlay/shared/use-dialog.cjs.map +1 -1
  272. package/dist/overlay/shared/use-dialog.d.ts.map +1 -1
  273. package/dist/overlay/shared/use-dialog.js +7 -6
  274. package/dist/overlay/shared/use-dialog.js.map +1 -1
  275. package/dist/progress.cjs +13 -13
  276. package/dist/progress.cjs.map +1 -1
  277. package/dist/progress.js +3 -4
  278. package/dist/progress.js.map +1 -1
  279. package/dist/radio-group.cjs +11 -11
  280. package/dist/radio-group.cjs.map +1 -1
  281. package/dist/radio-group.js +63 -70
  282. package/dist/radio-group.js.map +1 -1
  283. package/dist/radio.cjs +4 -4
  284. package/dist/radio.cjs.map +1 -1
  285. package/dist/radio.js +58 -58
  286. package/dist/radio.js.map +1 -1
  287. package/dist/rating.cjs.map +1 -1
  288. package/dist/rating.js.map +1 -1
  289. package/dist/refine.cjs +502 -309
  290. package/dist/refine.cjs.map +1 -1
  291. package/dist/refine.iife.js +562 -369
  292. package/dist/refine.iife.js.map +1 -1
  293. package/dist/refine.js +558 -365
  294. package/dist/refine.js.map +1 -1
  295. package/dist/select.cjs +21 -21
  296. package/dist/select.cjs.map +1 -1
  297. package/dist/select.js +135 -127
  298. package/dist/select.js.map +1 -1
  299. package/dist/shared/size-presets.cjs +1 -1
  300. package/dist/shared/size-presets.cjs.map +1 -1
  301. package/dist/shared/size-presets.d.ts +74 -0
  302. package/dist/shared/size-presets.d.ts.map +1 -1
  303. package/dist/shared/size-presets.js +48 -1
  304. package/dist/shared/size-presets.js.map +1 -1
  305. package/dist/shared/types.d.ts +5 -0
  306. package/dist/shared/types.d.ts.map +1 -1
  307. package/dist/styles/index.cjs +1 -1
  308. package/dist/styles/index.cjs.map +1 -1
  309. package/dist/styles/index.d.ts +1 -0
  310. package/dist/styles/index.d.ts.map +1 -1
  311. package/dist/styles/index.js +5 -4
  312. package/dist/styles/index.js.map +1 -1
  313. package/dist/styles/mixins/field-variants.css.cjs +85 -0
  314. package/dist/styles/mixins/field-variants.css.cjs.map +1 -0
  315. package/dist/styles/mixins/field-variants.css.d.ts +66 -0
  316. package/dist/styles/mixins/field-variants.css.d.ts.map +1 -0
  317. package/dist/styles/mixins/field-variants.css.js +90 -0
  318. package/dist/styles/mixins/field-variants.css.js.map +1 -0
  319. package/dist/switch.cjs +3 -3
  320. package/dist/switch.cjs.map +1 -1
  321. package/dist/switch.js +38 -36
  322. package/dist/switch.js.map +1 -1
  323. package/dist/tab-item.cjs +8 -8
  324. package/dist/tab-item.cjs.map +1 -1
  325. package/dist/tab-item.js +38 -28
  326. package/dist/tab-item.js.map +1 -1
  327. package/dist/tab-panel.cjs +7 -7
  328. package/dist/tab-panel.cjs.map +1 -1
  329. package/dist/tab-panel.js +33 -26
  330. package/dist/tab-panel.js.map +1 -1
  331. package/dist/tabs.cjs +4 -4
  332. package/dist/tabs.cjs.map +1 -1
  333. package/dist/tabs.js +64 -60
  334. package/dist/tabs.js.map +1 -1
  335. package/dist/testing/index.d.ts +15 -60
  336. package/dist/testing/index.d.ts.map +1 -1
  337. package/dist/testing.cjs +1 -1
  338. package/dist/testing.cjs.map +1 -1
  339. package/dist/testing.js +7 -24
  340. package/dist/testing.js.map +1 -1
  341. package/dist/textarea.cjs +15 -18
  342. package/dist/textarea.cjs.map +1 -1
  343. package/dist/textarea.js +83 -74
  344. package/dist/textarea.js.map +1 -1
  345. package/dist/time-picker.cjs +34 -31
  346. package/dist/time-picker.cjs.map +1 -1
  347. package/dist/time-picker.js +121 -109
  348. package/dist/time-picker.js.map +1 -1
  349. package/package.json +22 -9
  350. package/dist/headless/dialog-focus.cjs +0 -2
  351. package/dist/headless/dialog-focus.cjs.map +0 -1
  352. package/dist/headless/dialog-focus.d.ts +0 -40
  353. package/dist/headless/dialog-focus.d.ts.map +0 -1
  354. package/dist/headless/dialog-focus.js +0 -22
  355. package/dist/headless/dialog-focus.js.map +0 -1
  356. package/dist/headless/focus-trap.cjs +0 -2
  357. package/dist/headless/focus-trap.cjs.map +0 -1
  358. package/dist/headless/focus-trap.d.ts +0 -45
  359. package/dist/headless/focus-trap.d.ts.map +0 -1
  360. package/dist/headless/focus-trap.js +0 -51
  361. package/dist/headless/focus-trap.js.map +0 -1
  362. package/dist/keymap/dist/_dev.cjs +0 -2
  363. package/dist/keymap/dist/_dev.cjs.map +0 -1
  364. package/dist/keymap/dist/_dev.js +0 -4
  365. package/dist/keymap/dist/_dev.js.map +0 -1
  366. package/dist/keymap/dist/format.cjs +0 -1
  367. package/dist/keymap/dist/format.js +0 -1
  368. package/dist/keymap/dist/index.cjs +0 -1
  369. package/dist/keymap/dist/index.js +0 -4
  370. package/dist/keymap/dist/keymap.cjs +0 -2
  371. package/dist/keymap/dist/keymap.cjs.map +0 -1
  372. package/dist/keymap/dist/keymap.js +0 -221
  373. package/dist/keymap/dist/keymap.js.map +0 -1
  374. package/dist/keymap/dist/layer.cjs +0 -1
  375. package/dist/keymap/dist/layer.js +0 -1
package/dist/textarea.js CHANGED
@@ -1,49 +1,53 @@
1
1
  import { sizeVariantMixin as e } from "./styles/mixins/shape.css.js";
2
2
  import { forcedColorsFocusMixin as t } from "./styles/mixins/theme.css.js";
3
- import { fieldMixins as n } from "./styles/index.js";
4
- import { disablableBundle as r, roundableBundle as i, sizableBundle as a, themableBundle as o } from "./shared/prop-bundles.js";
5
- import { TEXTAREA_SIZE_PRESET as s } from "./shared/size-presets.js";
6
- import { lifecycleSignal as c } from "./headless/ore.js";
7
- import { createAutoResize as l } from "./headless/auto-resize.js";
8
- import { counterClassName as u } from "./headless/field-base.js";
9
- import { createTextField as d } from "./headless/text-field.js";
10
- import { errorAttr as f } from "./inputs/shared/field-binding.js";
11
- import { FORM_CTX as p, useFormContext as m } from "./inputs/shared/form-context.js";
12
- import h from "./inputs/textarea/textarea.css.js";
13
- import { bind as g, define as _, html as v, inject as y, onCleanup as b, onElement as x, prop as S, ref as C, useEmit as w, watchEffect as T } from "@vielzeug/ore";
14
- import { live as E } from "@vielzeug/ore/directives";
15
- import { watch as D } from "@vielzeug/ripple";
16
- import { useField as O } from "@vielzeug/ore/forms";
3
+ import { fieldVariantMixin as n } from "./styles/mixins/field-variants.css.js";
4
+ import { fieldMixins as r } from "./styles/index.js";
5
+ import { disablableBundle as i, roundableBundle as a, sizableBundle as o, themableBundle as s } from "./shared/prop-bundles.js";
6
+ import { TEXTAREA_SIZE_PRESET as c } from "./shared/size-presets.js";
7
+ import { lifecycleSignal as l } from "./headless/ore.js";
8
+ import { createAutoResize as u } from "./headless/auto-resize.js";
9
+ import { bindRefCallback as d } from "./headless/ref-callback.js";
10
+ import { createTextField as f } from "./headless/text-field.js";
11
+ import { errorAttr as p } from "./inputs/shared/field-binding.js";
12
+ import { FORM_CTX as m, useFormContext as h } from "./inputs/shared/form-context.js";
13
+ import { renderFieldStatusRegion as g, renderStatusIcon as _ } from "./inputs/shared/templates.js";
14
+ import v from "./inputs/textarea/textarea.css.js";
15
+ import { bind as y, define as b, html as x, inject as S, onCleanup as C, onElement as w, prop as T, ref as E, useEmit as D, watchEffect as O } from "@vielzeug/ore";
16
+ import { computed as k } from "@vielzeug/ripple";
17
+ import { useField as A } from "@vielzeug/ore/forms";
18
+ import { live as j } from "@vielzeug/ore/directives";
17
19
  //#region src/inputs/textarea/textarea.ts
18
- var k = "ore-textarea";
19
- _(k, {
20
+ var M = "ore-textarea";
21
+ b(M, {
20
22
  formAssociated: !0,
21
23
  props: {
24
+ ...s,
22
25
  ...o,
23
- ...a,
24
- ...r,
25
26
  ...i,
26
- "auto-resize": S.bool(!1),
27
- error: S.string(),
28
- fullwidth: S.bool(!1),
29
- helper: S.string(),
30
- label: S.string(),
31
- "label-placement": S.oneOf(["inset", "outside"], "inset"),
32
- maxlength: S.json(void 0),
33
- name: S.string(),
34
- "no-resize": S.bool(!1),
35
- placeholder: S.string(),
36
- readonly: S.bool(!1),
37
- ref: S.json(void 0),
38
- required: S.bool(!1),
39
- resize: S.string(),
40
- rows: S.json(void 0),
41
- value: S.string(),
42
- variant: S.string()
27
+ ...a,
28
+ "auto-resize": T.bool(!1),
29
+ error: T.string(),
30
+ fullwidth: T.bool(!1),
31
+ helper: T.string(),
32
+ label: T.string(),
33
+ "label-placement": T.oneOf(["inset", "outside"], "inset"),
34
+ loading: T.bool(!1),
35
+ maxlength: T.json(void 0),
36
+ name: T.string(),
37
+ "no-resize": T.bool(!1),
38
+ placeholder: T.string(),
39
+ readonly: T.bool(!1),
40
+ ref: T.data(),
41
+ required: T.bool(!1),
42
+ resize: T.string(),
43
+ rows: T.json(void 0),
44
+ success: T.bool(!1),
45
+ value: T.string(),
46
+ variant: T.string()
43
47
  },
44
48
  setup(e) {
45
- let t = w(), n = T, r = y(p), i = m(e, r), a = C(), o = l({ enabled: e["auto-resize"] }), s = c(b), h = d({
46
- disabled: i.disabled,
49
+ let t = D(), n = O, r = S(m), i = h(e, r), a = E(), o = u({ enabled: e["auto-resize"] }), s = k(() => i.disabled.value || e.loading.value), c = l(C), v = f({
50
+ disabled: s,
47
51
  error: e.error,
48
52
  helper: e.helper,
49
53
  label: e.label,
@@ -64,78 +68,83 @@ _(k, {
64
68
  prefix: "textarea",
65
69
  readonly: e.readonly,
66
70
  required: e.required,
67
- signal: s,
71
+ signal: c,
68
72
  validateOn: r?.validateOn,
69
73
  value: e.value
70
74
  });
71
- h.attachFormField(O({
72
- disabled: h.disabled,
75
+ v.attachFormField(A({
76
+ disabled: v.disabled,
73
77
  onReset: () => {
74
- h.reset(), requestAnimationFrame(() => o.recompute());
78
+ v.reset(), requestAnimationFrame(() => o.recompute());
75
79
  },
76
80
  toFormValue: (e) => e,
77
- validationMessage: h.validationMessage,
78
- validity: h.validity,
79
- value: h.value
81
+ validationMessage: v.validationMessage,
82
+ validity: v.validity,
83
+ value: v.value
80
84
  }));
81
- let { ariaDescribedBy: _, ariaErrorMessage: S, ariaInvalid: k, ariaLabelledBy: A, assistiveId: j, counter: M, errorId: N, errorText: P, fieldId: F, helperText: I, labelId: L, labelVisible: R } = h;
82
- return x(a, (t) => {
83
- let r = h.wire(t), i = o.wire(t);
84
- e.ref.value?.(t);
85
- let a = D(e.ref, (e) => {
86
- e?.(t);
87
- }), s = n(() => {
85
+ let { ariaDescribedBy: b, ariaErrorMessage: T, ariaInvalid: M, ariaLabelledBy: N, assistiveId: P, counter: F, errorId: I, errorText: L, fieldId: R, helperText: z, labelId: B, labelVisible: V } = v;
86
+ return w(a, (t) => {
87
+ let r = v.wire(t), i = o.wire(t), a = d(e.ref, t), s = n(() => {
88
88
  t.style.resize = e["auto-resize"].value || e["no-resize"].value ? "none" : e.resize.value || "vertical", requestAnimationFrame(() => o.recompute());
89
89
  });
90
90
  return () => {
91
- a.dispose(), e.ref.value?.(null), r(), i(), s();
91
+ a(), r(), i(), s();
92
92
  };
93
- }), g({ attr: {
94
- error: f(P),
93
+ }), y({ attr: {
94
+ error: p(L),
95
95
  size: i.size,
96
+ success: () => e.success.value && !L.value ? !0 : void 0,
96
97
  variant: i.variant
97
- } }), v`
98
+ } }), x`
98
99
  <div class="textarea-wrapper" part="wrapper">
99
- <label class="label" part="label" for="${F}" id="${L}" ?hidden="${() => !R.value}"
100
+ <label class="label" part="label" for="${R}" id="${B}" ?hidden="${() => !V.value}"
100
101
  >${e.label}</label
101
102
  >
102
103
  <div class="field" part="field">
103
104
  <textarea
104
105
  part="textarea"
105
106
  ref="${a}"
106
- id="${F}"
107
+ id="${R}"
107
108
  :name="${e.name}"
108
109
  :placeholder="${e.placeholder}"
109
110
  :rows="${e.rows}"
110
111
  :maxlength="${e.maxlength}"
111
- ?disabled="${e.disabled}"
112
+ ?disabled="${s}"
112
113
  ?readonly="${e.readonly}"
113
114
  ?required="${e.required}"
114
- :value="${E(h.value)}"
115
- :aria-describedby="${_}"
116
- :aria-errormessage="${S}"
117
- :aria-invalid="${k}"
118
- :aria-labelledby="${A}"></textarea>
119
- </div>
120
- <span class="${() => u(M?.value)}" aria-live="polite" ?hidden="${() => !M}">${() => M?.value.counterText.replace(" / ", "/") ?? ""}</span>
121
- <div id="${j}" class="helper-text" aria-live="polite" part="helper" ?hidden="${() => !!P.value || !I.value}">
122
- ${() => I.value}
123
- </div>
124
- <div id="${N}" class="helper-text" role="alert" part="error" ?hidden="${() => !P.value}">
125
- ${() => P.value}
115
+ :value="${j(v.value)}"
116
+ :aria-describedby="${b}"
117
+ :aria-errormessage="${T}"
118
+ :aria-invalid="${M}"
119
+ :aria-labelledby="${N}"
120
+ :aria-busy="${() => e.loading.value ? "true" : null}"></textarea>
121
+ ${_(L)}
122
+ <span class="field-spinner" part="spinner" role="status" aria-label="Loading"></span>
126
123
  </div>
124
+ ${g({
125
+ assistiveId: P,
126
+ counter: F,
127
+ errorId: I,
128
+ errorText: L,
129
+ helperText: z
130
+ })}
127
131
  </div>
128
132
  `;
129
133
  },
130
134
  shadow: { delegatesFocus: !0 },
131
135
  styles: [
132
- ...n,
133
- e(s),
136
+ ...r,
137
+ e(c),
134
138
  t("textarea"),
135
- h
139
+ v,
140
+ n({
141
+ container: ".field",
142
+ text: "textarea",
143
+ tokenPrefix: "textarea"
144
+ })
136
145
  ]
137
146
  });
138
147
  //#endregion
139
- export { k as TEXTAREA_TAG };
148
+ export { M as TEXTAREA_TAG };
140
149
 
141
150
  //# sourceMappingURL=textarea.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"textarea.js","names":[],"sources":["../src/inputs/textarea/textarea.ts"],"sourcesContent":["import { define, html, inject, prop, ref, bind, onCleanup, onElement, useEmit, watchEffect } from '@vielzeug/ore';\nimport { live } from '@vielzeug/ore/directives';\nimport { useField } from '@vielzeug/ore/forms';\nimport { watch as rippleWatch } from '@vielzeug/ripple';\n\nimport type { TextFieldProps } from '../../shared';\nimport type { VisualVariant } from '../../types';\n\nimport { counterClassName, createAutoResize, lifecycleSignal, createTextField } from '../../headless';\nimport { disablableBundle, roundableBundle, sizableBundle, TEXTAREA_SIZE_PRESET, themableBundle } from '../../shared';\nimport { fieldMixins, forcedColorsFocusMixin, sizeVariantMixin } from '../../styles';\nimport { errorAttr } from '../shared/field-binding';\nimport { FORM_CTX, useFormContext } from '../shared/form-context';\nimport componentStyles from './textarea.css?inline';\n\n/** Textarea component properties */\n\nexport type OreTextareaEvents = {\n change: { originalEvent: Event; value: string };\n input: { originalEvent: Event; value: string };\n};\n\nexport type OreTextareaProps = TextFieldProps<Exclude<VisualVariant, 'frost' | 'text'>> & {\n /** Allow auto-grow with content */\n 'auto-resize'?: boolean;\n /** Maximum character count; shows a counter when set */\n maxlength?: number;\n /** Disable a manual resize handle */\n 'no-resize'?: boolean;\n /**\n * JS-only callback fired with the inner `<textarea>` element when it mounts,\n * and with `null` when it unmounts. Intended for composed components that\n * need imperative access to the raw element.\n * Set as a JS property: `bitTextarea.ref = (el) => { ... }`.\n */\n ref?: ((el: HTMLTextAreaElement | null) => void) | null;\n /** Resize direction override */\n resize?: 'none' | 'horizontal' | 'both' | 'vertical';\n /** Number of visible text rows */\n rows?: number;\n};\n\n/**\n * A multi-line text input with label, helper text, character counter, and auto-resize.\n *\n * @element ore-textarea\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} value - Current value\n * @attr {string} placeholder - Placeholder text\n * @attr {string} name - Form field name\n * @attr {number} rows - Visible row count\n * @attr {number} maxlength - Max character count (shows counter)\n * @attr {string} helper - Helper text below the textarea\n * @attr {string} error - Error message\n * @attr {boolean} disabled - Disable interaction\n * @attr {boolean} readonly - Read-only mode\n * @attr {boolean} required - Required field\n * @attr {boolean} no-resize - Disable manual resize\n * @attr {boolean} auto-resize - Grow with content\n * @attr {string} resize - Resize direction: 'none' | 'horizontal' | 'both' | 'vertical'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n *\n * @fires input - Fired on every keystroke with current value. detail: { value: string; originalEvent: Event }\n * @fires change - Fired on blur with changed value. detail: { value: string; originalEvent: Event }\n *\n * @slot helper - Complex helper content\n *\n * @cssprop --textarea-bg - Background color\n * @cssprop --textarea-border-color - Border color\n * @cssprop --textarea-placeholder-color - Placeholder text color\n * @cssprop --textarea-radius - Border radius\n * @cssprop --textarea-padding - Inner padding (block inline)\n * @cssprop --textarea-gap - Gap between label and field\n * @cssprop --textarea-font-size - Font size\n * @cssprop --textarea-min-height - Minimum field height\n * @cssprop --textarea-max-height - Maximum field height (none = unlimited)\n * @cssprop --textarea-resize - CSS resize direction ('vertical' | 'horizontal' | 'both' | 'none')\n * @cssprop --textarea-hover-bg - Field background on hover (flat/ghost variants)\n * @cssprop --textarea-hover-border-color - Field border on hover (flat/bordered variants)\n * @cssprop --textarea-focus-bg - Field background when focused (flat variant)\n * @cssprop --textarea-focus-border-color - Field border when focused (flat variant)\n *\n * @part wrapper - Outer wrapper element.\n * @part label - Label element.\n * @part field - Field container.\n * @part textarea - The native `<textarea>` element.\n * @part helper - The helper text element.\n * @part error - The error text element (`role=\"alert\"`).\n *\n * @example\n * ```html\n * <ore-textarea></ore-textarea>\n * ```\n */\nexport const TEXTAREA_TAG = 'ore-textarea' as const;\ndefine<OreTextareaProps>(TEXTAREA_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...roundableBundle,\n 'auto-resize': prop.bool(false),\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n maxlength: prop.json(undefined as number | undefined),\n name: prop.string(),\n 'no-resize': prop.bool(false),\n placeholder: prop.string(),\n readonly: prop.bool(false),\n ref: prop.json(undefined as ((el: HTMLTextAreaElement | null) => void) | null | undefined),\n required: prop.bool(false),\n resize: prop.string<'none' | 'both' | 'horizontal' | 'vertical'>(),\n rows: prop.json(undefined as number | undefined),\n value: prop.string(),\n variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n },\n setup(props) {\n const emit = useEmit<OreTextareaEvents>();\n const watch = watchEffect;\n\n const formCtx = inject(FORM_CTX);\n const fCtxProps = useFormContext(props, formCtx);\n\n const textareaRef = ref<HTMLTextAreaElement>();\n const autoResize = createAutoResize({ enabled: props['auto-resize'] });\n\n const abortSignal = lifecycleSignal(onCleanup);\n const tf = createTextField({\n disabled: fCtxProps.disabled,\n error: props.error,\n helper: props.helper,\n label: props.label,\n labelPlacement: props['label-placement'],\n maxLength: props.maxlength,\n onChange: (event: Event, value: string) => {\n emit('change', { originalEvent: event, value });\n },\n onInput: (event: Event, value: string) => {\n emit('input', { originalEvent: event, value });\n },\n prefix: 'textarea',\n readonly: props.readonly,\n required: props.required,\n signal: abortSignal,\n validateOn: formCtx?.validateOn,\n value: props.value,\n });\n\n tf.attachFormField(\n useField<string>({\n disabled: tf.disabled,\n onReset: () => {\n tf.reset();\n requestAnimationFrame(() => autoResize.recompute());\n },\n toFormValue: (v) => v,\n validationMessage: tf.validationMessage,\n validity: tf.validity,\n value: tf.value,\n }),\n );\n\n const {\n ariaDescribedBy,\n ariaErrorMessage,\n ariaInvalid,\n ariaLabelledBy,\n assistiveId,\n counter,\n errorId,\n errorText,\n fieldId: textareaId,\n helperText,\n labelId,\n labelVisible,\n } = tf;\n\n onElement(textareaRef, (textareaEl) => {\n const unwireEl = tf.wire(textareaEl);\n const unwireAutoResize = autoResize.wire(textareaEl);\n\n props.ref.value?.(textareaEl);\n\n const sub = rippleWatch(props.ref, (cb) => {\n cb?.(textareaEl);\n });\n\n const stopLayoutEffect = watch(() => {\n textareaEl.style.resize =\n props['auto-resize'].value || props['no-resize'].value ? 'none' : props.resize.value || 'vertical';\n\n // Deferred a frame: on mount (or right after `auto-resize` flips true) the browser\n // hasn't necessarily finished laying out the textarea yet, so `scrollHeight` read\n // synchronously here could be stale.\n requestAnimationFrame(() => autoResize.recompute());\n });\n\n return () => {\n sub.dispose();\n props.ref.value?.(null);\n unwireEl();\n unwireAutoResize();\n stopLayoutEffect();\n };\n });\n\n bind({\n attr: {\n error: errorAttr(errorText),\n size: fCtxProps.size,\n variant: fCtxProps.variant,\n },\n });\n\n const counterClass = () => counterClassName(counter?.value);\n const counterHidden = () => !counter;\n const counterText = () => counter?.value.counterText.replace(' / ', '/') ?? '';\n const helperHidden = () => !!errorText.value || !helperText.value;\n const errorHidden = () => !errorText.value;\n\n return html`\n <div class=\"textarea-wrapper\" part=\"wrapper\">\n <label class=\"label\" part=\"label\" for=\"${textareaId}\" id=\"${labelId}\" ?hidden=\"${() => !labelVisible.value}\"\n >${props.label}</label\n >\n <div class=\"field\" part=\"field\">\n <textarea\n part=\"textarea\"\n ref=\"${textareaRef}\"\n id=\"${textareaId}\"\n :name=\"${props.name}\"\n :placeholder=\"${props.placeholder}\"\n :rows=\"${props.rows}\"\n :maxlength=\"${props.maxlength}\"\n ?disabled=\"${props.disabled}\"\n ?readonly=\"${props.readonly}\"\n ?required=\"${props.required}\"\n :value=\"${live(tf.value)}\"\n :aria-describedby=\"${ariaDescribedBy}\"\n :aria-errormessage=\"${ariaErrorMessage}\"\n :aria-invalid=\"${ariaInvalid}\"\n :aria-labelledby=\"${ariaLabelledBy}\"></textarea>\n </div>\n <span class=\"${counterClass}\" aria-live=\"polite\" ?hidden=\"${counterHidden}\">${counterText}</span>\n <div id=\"${assistiveId}\" class=\"helper-text\" aria-live=\"polite\" part=\"helper\" ?hidden=\"${helperHidden}\">\n ${() => helperText.value}\n </div>\n <div id=\"${errorId}\" class=\"helper-text\" role=\"alert\" part=\"error\" ?hidden=\"${errorHidden}\">\n ${() => errorText.value}\n </div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [...fieldMixins, sizeVariantMixin(TEXTAREA_SIZE_PRESET), forcedColorsFocusMixin('textarea'), componentStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"textarea.js","names":[],"sources":["../src/inputs/textarea/textarea.ts"],"sourcesContent":["import { define, html, inject, prop, ref, bind, onCleanup, onElement, useEmit, watchEffect } from '@vielzeug/ore';\nimport { live } from '@vielzeug/ore/directives';\nimport { useField } from '@vielzeug/ore/forms';\nimport { computed } from '@vielzeug/ripple';\n\nimport type { TextFieldProps } from '../../shared';\nimport type { VisualVariant } from '../../types';\n\nimport { bindRefCallback, createAutoResize, lifecycleSignal, createTextField } from '../../headless';\nimport '../../content/icon/icon';\nimport { disablableBundle, roundableBundle, sizableBundle, TEXTAREA_SIZE_PRESET, themableBundle } from '../../shared';\nimport { fieldMixins, fieldVariantMixin, forcedColorsFocusMixin, sizeVariantMixin } from '../../styles';\nimport { errorAttr } from '../shared/field-binding';\nimport { FORM_CTX, useFormContext } from '../shared/form-context';\nimport { renderFieldStatusRegion, renderStatusIcon } from '../shared/templates';\nimport componentStyles from './textarea.css?inline';\n\n/** Textarea component properties */\n\nexport type OreTextareaEvents = {\n change: { originalEvent: Event; value: string };\n input: { originalEvent: Event; value: string };\n};\n\nexport type OreTextareaProps = TextFieldProps<Exclude<VisualVariant, 'frost' | 'text'>> & {\n /** Allow auto-grow with content */\n 'auto-resize'?: boolean;\n /**\n * Shows an inline spinner inside the field and forces the inner `<textarea>` into\n * `disabled` for the duration — use while an async validation/submission request\n * is in flight to prevent double-submits.\n */\n loading?: boolean;\n /** Maximum character count; shows a counter when set */\n maxlength?: number;\n /** Disable a manual resize handle */\n 'no-resize'?: boolean;\n /**\n * JS-only callback fired with the inner `<textarea>` element when it mounts,\n * and with `null` when it unmounts. Intended for composed components that\n * need imperative access to the raw element.\n * Set as a JS property: `bitTextarea.ref = (el) => { ... }`.\n */\n ref?: ((el: HTMLTextAreaElement | null) => void) | null;\n /** Resize direction override */\n resize?: 'none' | 'horizontal' | 'both' | 'vertical';\n /** Number of visible text rows */\n rows?: number;\n};\n\n/**\n * A multi-line text input with label, helper text, character counter, and auto-resize.\n *\n * @element ore-textarea\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} value - Current value\n * @attr {string} placeholder - Placeholder text\n * @attr {string} name - Form field name\n * @attr {number} rows - Visible row count\n * @attr {number} maxlength - Max character count (shows counter)\n * @attr {string} helper - Helper text below the textarea\n * @attr {string} error - Error message\n * @attr {boolean} disabled - Disable interaction\n * @attr {boolean} readonly - Read-only mode\n * @attr {boolean} required - Required field\n * @attr {boolean} no-resize - Disable manual resize\n * @attr {boolean} auto-resize - Grow with content\n * @attr {boolean} loading - Show an inline spinner and force the field disabled\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} resize - Resize direction: 'none' | 'horizontal' | 'both' | 'vertical'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n *\n * @fires input - Fired on every keystroke with current value. detail: { value: string; originalEvent: Event }\n * @fires change - Fired on blur with changed value. detail: { value: string; originalEvent: Event }\n *\n * @slot helper - Complex helper content\n *\n * @part status-icon - The inline error/success icon shown inside the field\n * @part spinner - The inline loading spinner shown inside the field while `loading`\n *\n * @cssprop --textarea-bg - Background color\n * @cssprop --textarea-border-color - Border color\n * @cssprop --textarea-placeholder-color - Placeholder text color\n * @cssprop --textarea-radius - Border radius\n * @cssprop --textarea-padding - Inner padding (block inline)\n * @cssprop --textarea-gap - Gap between label and field\n * @cssprop --textarea-font-size - Font size\n * @cssprop --textarea-min-height - Minimum field height\n * @cssprop --textarea-max-height - Maximum field height (none = unlimited)\n * @cssprop --textarea-resize - CSS resize direction ('vertical' | 'horizontal' | 'both' | 'none')\n * @cssprop --textarea-hover-bg - Field background on hover (flat/ghost variants)\n * @cssprop --textarea-hover-border-color - Field border on hover (flat/bordered variants)\n * @cssprop --textarea-focus-bg - Field background when focused (flat variant)\n * @cssprop --textarea-focus-border-color - Field border when focused (flat variant)\n *\n * @part wrapper - Outer wrapper element.\n * @part label - Label element.\n * @part field - Field container.\n * @part textarea - The native `<textarea>` element.\n * @part helper - The helper text element.\n * @part error - The error text element (`role=\"alert\"`).\n *\n * @example\n * ```html\n * <ore-textarea></ore-textarea>\n * <ore-textarea label=\"Bio\" success></ore-textarea>\n * <ore-textarea label=\"Bio\" loading></ore-textarea>\n * ```\n */\nexport const TEXTAREA_TAG = 'ore-textarea' as const;\ndefine<OreTextareaProps>(TEXTAREA_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...roundableBundle,\n 'auto-resize': prop.bool(false),\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n loading: prop.bool(false),\n maxlength: prop.json(undefined as number | undefined),\n name: prop.string(),\n 'no-resize': prop.bool(false),\n placeholder: prop.string(),\n readonly: prop.bool(false),\n ref: prop.data<((el: HTMLTextAreaElement | null) => void) | null>(),\n required: prop.bool(false),\n resize: prop.string<'none' | 'both' | 'horizontal' | 'vertical'>(),\n rows: prop.json(undefined as number | undefined),\n success: prop.bool(false),\n value: prop.string(),\n variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n },\n setup(props) {\n const emit = useEmit<OreTextareaEvents>();\n const watch = watchEffect;\n\n const formCtx = inject(FORM_CTX);\n const fCtxProps = useFormContext(props, formCtx);\n\n const textareaRef = ref<HTMLTextAreaElement>();\n const autoResize = createAutoResize({ enabled: props['auto-resize'] });\n // `loading` behaves like a temporary `disabled` — see ore-input's identical computation.\n const isDisabled = computed(() => fCtxProps.disabled.value || props.loading.value);\n\n const abortSignal = lifecycleSignal(onCleanup);\n const tf = createTextField({\n disabled: isDisabled,\n error: props.error,\n helper: props.helper,\n label: props.label,\n labelPlacement: props['label-placement'],\n maxLength: props.maxlength,\n onChange: (event: Event, value: string) => {\n emit('change', { originalEvent: event, value });\n },\n onInput: (event: Event, value: string) => {\n emit('input', { originalEvent: event, value });\n },\n prefix: 'textarea',\n readonly: props.readonly,\n required: props.required,\n signal: abortSignal,\n validateOn: formCtx?.validateOn,\n value: props.value,\n });\n\n tf.attachFormField(\n useField<string>({\n disabled: tf.disabled,\n onReset: () => {\n tf.reset();\n requestAnimationFrame(() => autoResize.recompute());\n },\n toFormValue: (v) => v,\n validationMessage: tf.validationMessage,\n validity: tf.validity,\n value: tf.value,\n }),\n );\n\n const {\n ariaDescribedBy,\n ariaErrorMessage,\n ariaInvalid,\n ariaLabelledBy,\n assistiveId,\n counter,\n errorId,\n errorText,\n fieldId: textareaId,\n helperText,\n labelId,\n labelVisible,\n } = tf;\n\n onElement(textareaRef, (textareaEl) => {\n const unwireEl = tf.wire(textareaEl);\n const unwireAutoResize = autoResize.wire(textareaEl);\n const unwireRef = bindRefCallback(props.ref, textareaEl);\n\n const stopLayoutEffect = watch(() => {\n textareaEl.style.resize =\n props['auto-resize'].value || props['no-resize'].value ? 'none' : props.resize.value || 'vertical';\n\n // Deferred a frame: on mount (or right after `auto-resize` flips true) the browser\n // hasn't necessarily finished laying out the textarea yet, so `scrollHeight` read\n // synchronously here could be stale.\n requestAnimationFrame(() => autoResize.recompute());\n });\n\n return () => {\n unwireRef();\n unwireEl();\n unwireAutoResize();\n stopLayoutEffect();\n };\n });\n\n bind({\n attr: {\n error: errorAttr(errorText),\n size: fCtxProps.size,\n // Reflects `success` only once `error` is confirmed empty — keeps the two host\n // attributes mutually exclusive even if a consumer sets both props at once.\n success: () => (props.success.value && !errorText.value ? true : undefined),\n variant: fCtxProps.variant,\n },\n });\n\n return html`\n <div class=\"textarea-wrapper\" part=\"wrapper\">\n <label class=\"label\" part=\"label\" for=\"${textareaId}\" id=\"${labelId}\" ?hidden=\"${() => !labelVisible.value}\"\n >${props.label}</label\n >\n <div class=\"field\" part=\"field\">\n <textarea\n part=\"textarea\"\n ref=\"${textareaRef}\"\n id=\"${textareaId}\"\n :name=\"${props.name}\"\n :placeholder=\"${props.placeholder}\"\n :rows=\"${props.rows}\"\n :maxlength=\"${props.maxlength}\"\n ?disabled=\"${isDisabled}\"\n ?readonly=\"${props.readonly}\"\n ?required=\"${props.required}\"\n :value=\"${live(tf.value)}\"\n :aria-describedby=\"${ariaDescribedBy}\"\n :aria-errormessage=\"${ariaErrorMessage}\"\n :aria-invalid=\"${ariaInvalid}\"\n :aria-labelledby=\"${ariaLabelledBy}\"\n :aria-busy=\"${() => (props.loading.value ? 'true' : null)}\"></textarea>\n ${renderStatusIcon(errorText)}\n <span class=\"field-spinner\" part=\"spinner\" role=\"status\" aria-label=\"Loading\"></span>\n </div>\n ${renderFieldStatusRegion({ assistiveId, counter, errorId, errorText, helperText })}\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [\n ...fieldMixins,\n sizeVariantMixin(TEXTAREA_SIZE_PRESET),\n forcedColorsFocusMixin('textarea'),\n componentStyles,\n // Must come after `componentStyles` — see `ore-input`'s identical ordering note for why\n // (`@layer` precedence is fixed by which layer name is *first* referenced across this whole\n // array; `componentStyles` establishes `refine.base`, which this mixin's `refine.variants`\n // rules need to win over).\n fieldVariantMixin({ container: '.field', text: 'textarea', tokenPrefix: 'textarea' }),\n ],\n});\n"],"mappings":"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"}
@@ -1,55 +1,58 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/theme.css.cjs"),n=require("./shared/prop-bundles.cjs"),r=require("./inputs/shared/form-context.cjs"),i=require("./inputs/time-picker/time-picker.css.cjs");let a=require("@vielzeug/ore"),o=require("@vielzeug/ripple"),s=require("@vielzeug/ore/forms");function c(e){if(!e)return null;let t=/^(\d{1,2}):(\d{2})$/.exec(e.trim());if(!t)return null;let n=Number(t[1]),r=Number(t[2]);return n<0||n>23||r<0||r>59?null:{hours:n,minutes:r}}function l(e,t){return`${String(e).padStart(2,`0`)}:${String(t).padStart(2,`0`)}`}function u(e,t,n){if(n===`12`){let n=e>=12?`PM`:`AM`,r=e%12==0?12:e%12;return`${String(r).padStart(2,`0`)}:${String(t).padStart(2,`0`)} ${n}`}return l(e,t)}function d(e,t,n,r){let i=e*60+t,a=c(n),o=c(r),s=a?a.hours*60+a.minutes:0,l=o?o.hours*60+o.minutes:1439,u=Math.min(Math.max(i,s),l);return{hours:Math.floor(u/60),minutes:u%60}}var f=`ore-time-picker`;(0,a.define)(f,{formAssociated:!0,props:{...n.themableBundle,...n.sizableBundle,...n.disablableBundle,...n.roundableBundle,error:a.prop.string(),fullwidth:a.prop.bool(!1),helper:a.prop.string(),label:a.prop.string(),"label-placement":a.prop.oneOf([`inset`,`outside`],`inset`),max:a.prop.string(),min:a.prop.string(),"minute-step":a.prop.number(5),name:a.prop.string(),placeholder:a.prop.string(),required:a.prop.bool(!1),"time-format":a.prop.oneOf([`12`,`24`],`24`),value:a.prop.string(),variant:a.prop.string()},setup(e){let t=(0,a.getHost)(),n=(0,a.useEmit)(),i=(0,o.signal)(!1),f=(0,o.signal)(c(e.value.value)),p=r.useFormContext(e,(0,a.inject)(r.FORM_CTX)),m=p.disabled;(0,s.useField)({disabled:m,toFormValue:e=>e||null,value:(0,o.computed)(()=>{let e=f.value;return e?l(e.hours,e.minutes):``})});let h=(0,o.computed)(()=>e[`time-format`].value??`24`),g=(0,o.computed)(()=>Math.max(1,Math.min(59,e[`minute-step`].value??5))),_=(0,o.computed)(()=>f.value?u(f.value.hours,f.value.minutes,h.value):e.placeholder.value||``),v=(0,o.computed)(()=>h.value===`12`?Array.from({length:12},(e,t)=>t+1):Array.from({length:24},(e,t)=>t)),y=(0,o.computed)(()=>{let e=g.value,t=[];for(let n=0;n<60;n+=e)t.push(n);return t}),b=`time-picker-${Math.random().toString(36).slice(2,9)}-dropdown`;function x(e){if(h.value===`24`)return e;let t=e%12;return t===0?12:t}function S(e,t){return h.value===`24`?e:t===`AM`?e===12?0:e:e===12?12:e+12}function C(t,n){let r=t*60+n,i=c(e.min.value),a=c(e.max.value);return!!(i&&r<i.hours*60+i.minutes||a&&r>a.hours*60+a.minutes)}let w=(0,o.signal)(f.value?.hours??0),T=(0,o.signal)(f.value?.minutes??0),E=(0,o.signal)((f.value?.hours??0)>=12?`PM`:`AM`),D=e.value.value;(0,a.onMounted)(()=>{let t=setInterval(()=>{let t=e.value.value;if(t!==D){D=t;let e=c(t);f.value=e,e&&(w.value=e.hours,T.value=e.minutes,E.value=e.hours>=12?`PM`:`AM`)}},50);return()=>clearInterval(t)});function O(t,r){let i=d(t,r,e.min.value,e.max.value),a=Math.round(i.minutes/g.value)*g.value,o=Math.min(a,59);f.value={hours:i.hours,minutes:o},n(`change`,{value:l(i.hours,o)})}function k(e){let t=h.value===`12`?S(w.value,E.value):w.value;T.value=e,O(t,e),j()}function A(){if(m.value)return;let e=f.value;e?(w.value=h.value===`12`?x(e.hours):e.hours,T.value=e.minutes,E.value=e.hours>=12?`PM`:`AM`):(w.value=h.value===`12`?12:0,T.value=0,E.value=`AM`),i.value=!0}function j(){i.value=!1}function M(){i.value?j():A()}function N(e){i.value&&(e.composedPath().includes(t)||j())}(0,a.onMounted)(()=>(document.addEventListener(`pointerdown`,N,{capture:!0}),()=>document.removeEventListener(`pointerdown`,N,{capture:!0})));function P(e){m.value||(e.key===`Enter`||e.key===` `?(e.preventDefault(),M()):e.key===`Escape`&&i.value?(e.preventDefault(),j()):(e.key===`ArrowDown`||e.key===`ArrowUp`)&&!i.value&&(e.preventDefault(),A()))}function F(e){e.key===`Escape`&&(e.preventDefault(),j())}function I(e){let t=v.value,n=t.indexOf(w.value);e.key===`ArrowUp`?(e.preventDefault(),w.value=t[(n-1+t.length)%t.length]):e.key===`ArrowDown`&&(e.preventDefault(),w.value=t[(n+1)%t.length])}function L(e){let t=y.value,n=t.indexOf(T.value);e.key===`ArrowUp`?(e.preventDefault(),T.value=t[(n-1+t.length)%t.length]):e.key===`ArrowDown`&&(e.preventDefault(),T.value=t[(n+1)%t.length])}function R(e){(e.key===`ArrowUp`||e.key===`ArrowDown`)&&(e.preventDefault(),E.value=E.value===`AM`?`PM`:`AM`)}return(0,a.bind)({attr:{open:()=>i.value?!0:void 0}}),a.html`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/theme.css.cjs"),n=require("./shared/prop-bundles.cjs"),r=require("./headless/positioner.cjs"),i=require("./inputs/shared/form-context.cjs"),a=require("./inputs/time-picker/time-picker.css.cjs");let o=require("@vielzeug/ore"),s=require("@vielzeug/ripple"),c=require("@vielzeug/ore/forms");function l(e){if(!e)return null;let t=/^(\d{1,2}):(\d{2})$/.exec(e.trim());if(!t)return null;let n=Number(t[1]),r=Number(t[2]);return n<0||n>23||r<0||r>59?null:{hours:n,minutes:r}}function u(e,t){return`${String(e).padStart(2,`0`)}:${String(t).padStart(2,`0`)}`}function d(e,t,n){if(n===`12`){let n=e>=12?`PM`:`AM`,r=e%12==0?12:e%12;return`${String(r).padStart(2,`0`)}:${String(t).padStart(2,`0`)} ${n}`}return u(e,t)}function f(e,t,n,r){let i=e*60+t,a=l(n),o=l(r),s=a?a.hours*60+a.minutes:0,c=o?o.hours*60+o.minutes:1439,u=Math.min(Math.max(i,s),c);return{hours:Math.floor(u/60),minutes:u%60}}var p=`ore-time-picker`;(0,o.define)(p,{formAssociated:!0,props:{...n.themableBundle,...n.sizableBundle,...n.disablableBundle,...n.roundableBundle,error:o.prop.string(),fullwidth:o.prop.bool(!1),helper:o.prop.string(),label:o.prop.string(),"label-placement":o.prop.oneOf([`inset`,`outside`],`inset`),max:o.prop.string(),min:o.prop.string(),"minute-step":o.prop.number(5),name:o.prop.string(),placeholder:o.prop.string(),required:o.prop.bool(!1),success:o.prop.bool(!1),"time-format":o.prop.oneOf([`12`,`24`],`24`),value:o.prop.string(),variant:o.prop.string()},setup(e){let t=(0,o.getHost)(),n=(0,o.useEmit)(),a=(0,s.signal)(!1),p=(0,s.signal)(l(e.value.value)),m=(0,o.ref)(),h=(0,o.ref)(),g=r.createDropdownPositioner({getFloating:()=>h.value??null,getReference:()=>m.value??null,matchWidth:!1,offsetPx:4}),_=null,v=i.useFormContext(e,(0,o.inject)(i.FORM_CTX)),y=v.disabled;(0,c.useField)({disabled:y,toFormValue:e=>e||null,value:(0,s.computed)(()=>{let e=p.value;return e?u(e.hours,e.minutes):``})});let b=(0,s.computed)(()=>e[`time-format`].value??`24`),x=(0,s.computed)(()=>Math.max(1,Math.min(59,e[`minute-step`].value??5))),S=(0,s.computed)(()=>p.value?d(p.value.hours,p.value.minutes,b.value):e.placeholder.value||``),C=(0,s.computed)(()=>b.value===`12`?Array.from({length:12},(e,t)=>t+1):Array.from({length:24},(e,t)=>t)),w=(0,s.computed)(()=>{let e=x.value,t=[];for(let n=0;n<60;n+=e)t.push(n);return t}),T=`time-picker-${Math.random().toString(36).slice(2,9)}-dropdown`;function E(e){if(b.value===`24`)return e;let t=e%12;return t===0?12:t}function D(e,t){return b.value===`24`?e:t===`AM`?e===12?0:e:e===12?12:e+12}function O(t,n){let r=t*60+n,i=l(e.min.value),a=l(e.max.value);return!!(i&&r<i.hours*60+i.minutes||a&&r>a.hours*60+a.minutes)}let k=(0,s.signal)(p.value?.hours??0),A=(0,s.signal)(p.value?.minutes??0),j=(0,s.signal)((p.value?.hours??0)>=12?`PM`:`AM`),M=e.value.value;(0,o.onMounted)(()=>{let t=setInterval(()=>{let t=e.value.value;if(t!==M){M=t;let e=l(t);p.value=e,e&&(k.value=e.hours,A.value=e.minutes,j.value=e.hours>=12?`PM`:`AM`)}},50);return()=>clearInterval(t)});function N(t,r){let i=f(t,r,e.min.value,e.max.value),a=Math.round(i.minutes/x.value)*x.value,o=Math.min(a,59);p.value={hours:i.hours,minutes:o},n(`change`,{value:u(i.hours,o)})}function P(e){let t=b.value===`12`?D(k.value,j.value):k.value;A.value=e,N(t,e),I()}function F(){if(y.value)return;let e=p.value;e?(k.value=b.value===`12`?E(e.hours):e.hours,A.value=e.minutes,j.value=e.hours>=12?`PM`:`AM`):(k.value=b.value===`12`?12:0,A.value=0,j.value=`AM`),a.value=!0,g.update(),_=g.startAutoUpdate?.()??null}function I(){a.value=!1,_?.(),_=null}function L(){a.value?I():F()}function R(e){a.value&&(e.composedPath().includes(t)||I())}(0,o.onMounted)(()=>(document.addEventListener(`pointerdown`,R,{capture:!0}),()=>{document.removeEventListener(`pointerdown`,R,{capture:!0}),_?.(),_=null}));function z(e){y.value||(e.key===`Enter`||e.key===` `?(e.preventDefault(),L()):e.key===`Escape`&&a.value?(e.preventDefault(),I()):(e.key===`ArrowDown`||e.key===`ArrowUp`)&&!a.value&&(e.preventDefault(),F()))}function B(e){e.key===`Escape`&&(e.preventDefault(),I())}function V(e){let t=C.value,n=t.indexOf(k.value);e.key===`ArrowUp`?(e.preventDefault(),k.value=t[(n-1+t.length)%t.length]):e.key===`ArrowDown`&&(e.preventDefault(),k.value=t[(n+1)%t.length])}function H(e){let t=w.value,n=t.indexOf(A.value);e.key===`ArrowUp`?(e.preventDefault(),A.value=t[(n-1+t.length)%t.length]):e.key===`ArrowDown`&&(e.preventDefault(),A.value=t[(n+1)%t.length])}function U(e){(e.key===`ArrowUp`||e.key===`ArrowDown`)&&(e.preventDefault(),j.value=j.value===`AM`?`PM`:`AM`)}return(0,o.bind)({attr:{open:()=>a.value?!0:void 0}}),o.html`
2
2
  <!-- Trigger -->
3
3
  <ore-input
4
4
  class="trigger"
5
+ ref="${m}"
5
6
  readonly
6
7
  tabindex="0"
7
8
  role="combobox"
8
9
  aria-haspopup="listbox"
9
- aria-controls="${b}"
10
- :aria-expanded="${()=>String(i.value)}"
11
- :aria-disabled="${()=>m.value?`true`:null}"
12
- :value="${()=>_.value}"
10
+ aria-controls="${T}"
11
+ :aria-expanded="${()=>String(a.value)}"
12
+ :aria-disabled="${()=>y.value?`true`:null}"
13
+ :value="${()=>S.value}"
13
14
  :label="${()=>e.label.value??``}"
14
15
  :placeholder="${()=>e.placeholder.value??``}"
15
16
  :label-placement="${()=>e[`label-placement`].value??`inset`}"
16
17
  :color="${()=>e.color?.value??void 0}"
17
- :size="${()=>p.size?.value??void 0}"
18
- :variant="${()=>p.variant?.value??void 0}"
18
+ :size="${()=>v.size?.value??void 0}"
19
+ :variant="${()=>v.variant?.value??void 0}"
19
20
  :rounded="${()=>e.rounded?.value??void 0}"
20
21
  :helper="${()=>e.helper.value??``}"
21
22
  :error="${()=>e.error.value??``}"
22
- ?disabled="${()=>m.value?!0:void 0}"
23
+ ?disabled="${()=>y.value?!0:void 0}"
23
24
  ?required="${()=>e.required.value?!0:void 0}"
24
25
  ?fullwidth="${()=>e.fullwidth.value?!0:void 0}"
25
- @click="${M}"
26
- @keydown="${P}">
26
+ ?success="${()=>e.success.value}"
27
+ @click="${L}"
28
+ @keydown="${z}">
27
29
  <ore-icon slot="suffix" name="clock" size="16" stroke-width="1.75" aria-hidden="true"></ore-icon>
28
30
  </ore-input>
29
31
 
30
32
  <!-- Dropdown -->
31
33
  <div
32
34
  class="dropdown"
33
- id="${b}"
35
+ ref="${h}"
36
+ id="${T}"
34
37
  role="listbox"
35
38
  aria-label="${()=>e.label.value?`${e.label.value} — select time`:`Select time`}"
36
- ?data-open="${i}"
37
- @keydown="${F}">
39
+ ?data-open="${a}"
40
+ @keydown="${B}">
38
41
  <div class="cols-row">
39
42
  <!-- Hours column -->
40
43
  <div class="col" part="column" role="group" aria-label="Hours">
41
44
  <div class="col-label" aria-hidden="true">HH</div>
42
45
  <div class="col-scroll">
43
- ${()=>v.value.map(e=>{let t=C(h.value===`12`?S(e,E.value):e,T.value);return a.html`<div
46
+ ${()=>C.value.map(e=>{let t=O(b.value===`12`?D(e,j.value):e,A.value);return o.html`<div
44
47
  class="option"
45
48
  part="option"
46
49
  role="option"
47
- tabindex="${()=>w.value===e&&!t?`0`:`-1`}"
48
- :aria-selected="${()=>String(w.value===e)}"
50
+ tabindex="${()=>k.value===e&&!t?`0`:`-1`}"
51
+ :aria-selected="${()=>String(k.value===e)}"
49
52
  :aria-disabled="${()=>String(t)}"
50
53
  ?data-disabled="${()=>t}"
51
- @click="${()=>{t||(w.value=e)}}"
52
- @keydown="${I}">
54
+ @click="${()=>{t||(k.value=e)}}"
55
+ @keydown="${V}">
53
56
  ${String(e).padStart(2,`0`)}
54
57
  </div>`})}
55
58
  </div>
@@ -61,38 +64,38 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
61
64
  <div class="col" part="column" role="group" aria-label="Minutes">
62
65
  <div class="col-label" aria-hidden="true">MM</div>
63
66
  <div class="col-scroll">
64
- ${()=>y.value.map(e=>{let t=C(h.value===`12`?S(w.value,E.value):w.value,e);return a.html`<div
67
+ ${()=>w.value.map(e=>{let t=O(b.value===`12`?D(k.value,j.value):k.value,e);return o.html`<div
65
68
  class="option"
66
69
  part="option"
67
70
  role="option"
68
- tabindex="${()=>T.value===e&&!t?`0`:`-1`}"
69
- :aria-selected="${()=>String(T.value===e)}"
71
+ tabindex="${()=>A.value===e&&!t?`0`:`-1`}"
72
+ :aria-selected="${()=>String(A.value===e)}"
70
73
  :aria-disabled="${()=>String(t)}"
71
74
  ?data-disabled="${()=>t}"
72
- @click="${()=>{t||k(e)}}"
73
- @keydown="${L}">
75
+ @click="${()=>{t||P(e)}}"
76
+ @keydown="${H}">
74
77
  ${String(e).padStart(2,`0`)}
75
78
  </div>`})}
76
79
  </div>
77
80
  </div>
78
81
 
79
82
  <!-- AM/PM column (12h mode only) -->
80
- ${()=>h.value===`12`?a.html` <div class="col col-period" part="column" role="group" aria-label="Period">
83
+ ${()=>b.value===`12`?o.html` <div class="col col-period" part="column" role="group" aria-label="Period">
81
84
  <div class="col-label" aria-hidden="true">AM/PM</div>
82
85
  <div class="col-scroll">
83
- ${[`AM`,`PM`].map(e=>a.html`<div
86
+ ${[`AM`,`PM`].map(e=>o.html`<div
84
87
  class="option"
85
88
  part="option"
86
89
  role="option"
87
- tabindex="${()=>E.value===e?`0`:`-1`}"
88
- :aria-selected="${()=>String(E.value===e)}"
89
- @click="${()=>{E.value=e}}"
90
- @keydown="${R}">
90
+ tabindex="${()=>j.value===e?`0`:`-1`}"
91
+ :aria-selected="${()=>String(j.value===e)}"
92
+ @click="${()=>{j.value=e}}"
93
+ @keydown="${U}">
91
94
  ${e}
92
95
  </div>`)}
93
96
  </div>
94
- </div>`:a.html``}
97
+ </div>`:o.html``}
95
98
  </div>
96
99
  </div>
97
- `},shadow:{delegatesFocus:!0},styles:[t.colorThemeMixin,e.reducedMotionMixin,i.default]}),exports.TIME_PICKER_TAG=f;
100
+ `},shadow:{delegatesFocus:!0},styles:[t.colorThemeMixin,e.reducedMotionMixin,a.default]}),exports.TIME_PICKER_TAG=p;
98
101
  //# sourceMappingURL=time-picker.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"time-picker.cjs","names":[],"sources":["../src/inputs/time-picker/time-picker.ts"],"sourcesContent":["import { define, html, inject, prop, bind, getHost, onMounted, useEmit } from '@vielzeug/ore';\nimport { useField } from '@vielzeug/ore/forms';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport type { VisualVariant } from '../../shared';\n\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin } from '../../styles';\nimport { FORM_CTX, useFormContext } from '../shared/form-context';\nimport componentStyles from './time-picker.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type OreTimePickerEvents = {\n change: { value: string | null };\n};\n\nexport type OreTimePickerProps = {\n /** Theme color */\n color?: string;\n /** Disable the picker */\n disabled?: boolean;\n /** Validation error message */\n error?: string;\n /** Expand to container width */\n fullwidth?: boolean;\n /** Helper text below the field */\n helper?: string;\n /** Visible label */\n label?: string;\n /** Label placement */\n 'label-placement'?: 'inset' | 'outside';\n /** Maximum selectable time in HH:MM format (24-hour) */\n max?: string;\n /** Minimum selectable time in HH:MM format (24-hour) */\n min?: string;\n /** Minute step interval (1–59) */\n 'minute-step'?: number;\n /** Form field name */\n name?: string;\n /** Placeholder shown in the trigger */\n placeholder?: string;\n /** Mark field as required */\n required?: boolean;\n /** Border radius */\n rounded?: string;\n /** Component size */\n size?: string;\n /** Display format: '12' for AM/PM, '24' for 24-hour (default: '24') */\n 'time-format'?: '12' | '24';\n /** Selected time in HH:MM format (24-hour) */\n value?: string;\n /** Visual variant */\n variant?: Exclude<VisualVariant, 'text' | 'frost'>;\n};\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/** Parse \"HH:MM\" → { hours: 0-23, minutes: 0-59 } | null */\nfunction parseTime(val: string | undefined | null): { hours: number; minutes: number } | null {\n if (!val) return null;\n\n const match = /^(\\d{1,2}):(\\d{2})$/.exec(val.trim());\n\n if (!match) return null;\n\n const h = Number(match[1]);\n const m = Number(match[2]);\n\n if (h < 0 || h > 23 || m < 0 || m > 59) return null;\n\n return { hours: h, minutes: m };\n}\n\n/** Format { hours, minutes } → \"HH:MM\" (24-hour, zero-padded) */\nfunction formatTime(h: number, m: number): string {\n return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;\n}\n\n/** Format for display label (respects 12/24 mode) */\nfunction formatDisplay(h: number, m: number, format: '12' | '24'): string {\n if (format === '12') {\n const period = h >= 12 ? 'PM' : 'AM';\n const displayH = h % 12 === 0 ? 12 : h % 12;\n\n return `${String(displayH).padStart(2, '0')}:${String(m).padStart(2, '0')} ${period}`;\n }\n\n return formatTime(h, m);\n}\n\n/** Clamp value to [min, max] in total minutes */\nfunction clampTime(\n h: number,\n m: number,\n minVal: string | undefined | null,\n maxVal: string | undefined | null,\n): { hours: number; minutes: number } {\n const total = h * 60 + m;\n const minParsed = parseTime(minVal);\n const maxParsed = parseTime(maxVal);\n const minMins = minParsed ? minParsed.hours * 60 + minParsed.minutes : 0;\n const maxMins = maxParsed ? maxParsed.hours * 60 + maxParsed.minutes : 23 * 60 + 59;\n const clamped = Math.min(Math.max(total, minMins), maxMins);\n\n return { hours: Math.floor(clamped / 60), minutes: clamped % 60 };\n}\n\n/**\n * An accessible time picker with a scrollable clock dropdown.\n * Supports 12/24-hour display formats, min/max bounds, minute steps, and form association.\n *\n * @element ore-time-picker\n *\n * @attr {string} value - Selected time in HH:MM (24-hour) format\n * @attr {string} min - Minimum selectable time (HH:MM)\n * @attr {string} max - Maximum selectable time (HH:MM)\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} placeholder - Trigger placeholder\n * @attr {boolean} disabled - Disable the picker\n * @attr {boolean} required - Required field\n * @attr {string} name - Form field name\n * @attr {string} error - Error message\n * @attr {string} helper - Helper text\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} time-format - '12' or '24' (default: '24')\n * @attr {number} minute-step - Minute increment (default: 5)\n *\n * @fires change - Fired when a time is selected. detail: { value: string | null }\n *\n * @slot label - Custom label for the trigger field\n * @slot prefix - Content before the trigger text (e.g. icon)\n * @slot helper - Custom helper text\n * @slot error - Custom error content\n *\n * @cssprop --time-picker-bg - Dropdown background\n * @cssprop --time-picker-border-color - Dropdown border color\n * @cssprop --time-picker-radius - Dropdown border radius\n * @cssprop --time-picker-shadow - Dropdown shadow\n * @cssprop --time-picker-selected-bg - Selected option background\n * @cssprop --time-picker-option-hover-bg - Option hover background\n *\n * @part field - The trigger field\n * @part dropdown - The floating time dropdown\n * @part column - A scrollable column (hours / minutes / period)\n * @part option - An individual time option cell\n *\n * @example\n * ```html\n * <!-- 24-hour clock, 15-minute steps -->\n * <ore-time-picker label=\"Meeting time\" value=\"09:30\" minute-step=\"15\" color=\"primary\"></ore-time-picker>\n *\n * <!-- 12-hour AM/PM format -->\n * <ore-time-picker label=\"Appointment\" time-format=\"12\" minute-step=\"30\"></ore-time-picker>\n *\n * <!-- Outside label, bordered variant -->\n * <ore-time-picker label=\"Start time\" label-placement=\"outside\" variant=\"bordered\"></ore-time-picker>\n * ```\n */\nexport const TIME_PICKER_TAG = 'ore-time-picker' as const;\n\ndefine<OreTimePickerProps>(TIME_PICKER_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...roundableBundle,\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n max: prop.string(),\n min: prop.string(),\n 'minute-step': prop.number(5),\n name: prop.string(),\n placeholder: prop.string(),\n required: prop.bool(false),\n 'time-format': prop.oneOf(['12', '24'] as const, '24'),\n value: prop.string(),\n variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n },\n\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreTimePickerEvents>();\n\n // ── Signals ──────────────────────────────────────────────────────────────\n\n const isOpen = signal(false);\n const selectedTime = signal<{ hours: number; minutes: number } | null>(parseTime(props.value.value));\n\n // ── Form context ─────────────────────────────────────────────────────────\n\n const formCtx = inject(FORM_CTX);\n const fCtxProps = useFormContext(props, formCtx);\n const isDisabled = fCtxProps.disabled;\n\n // ── Form value ────────────────────────────────────────────────────────────\n\n useField<string>({\n disabled: isDisabled,\n toFormValue: (v) => v || null,\n value: computed(() => {\n const t = selectedTime.value;\n\n return t ? formatTime(t.hours, t.minutes) : '';\n }),\n });\n\n // ── Computed helpers ──────────────────────────────────────────────────────\n\n const fmt = computed(() => props['time-format'].value ?? '24');\n const minuteStep = computed(() => Math.max(1, Math.min(59, props['minute-step'].value ?? 5)));\n\n const triggerText = computed(() => {\n if (!selectedTime.value) return props.placeholder.value || '';\n\n return formatDisplay(selectedTime.value.hours, selectedTime.value.minutes, fmt.value as '12' | '24');\n });\n\n /** All hour options for the column (0-23 in 24h; 1-12 in 12h) */\n const hourOptions = computed<number[]>(() => {\n if (fmt.value === '12') {\n return Array.from({ length: 12 }, (_, i) => i + 1);\n }\n\n return Array.from({ length: 24 }, (_, i) => i);\n });\n\n /** All minute options for the column, stepped */\n const minuteOptions = computed<number[]>(() => {\n const step = minuteStep.value;\n const opts: number[] = [];\n\n for (let m = 0; m < 60; m += step) opts.push(m);\n\n return opts;\n });\n\n const dialogId = `time-picker-${Math.random().toString(36).slice(2, 9)}-dropdown`;\n\n /** Convert 24h hour to display hour in current format */\n function toDisplayHour(h24: number): number {\n if (fmt.value === '24') return h24;\n\n const h12 = h24 % 12;\n\n return h12 === 0 ? 12 : h12;\n }\n\n /** Convert display hour + period → 24h hour */\n function to24Hour(displayHour: number, period: 'AM' | 'PM'): number {\n if (fmt.value === '24') return displayHour;\n\n if (period === 'AM') return displayHour === 12 ? 0 : displayHour;\n\n return displayHour === 12 ? 12 : displayHour + 12;\n }\n\n /** Whether a given HH:MM is out of [min, max] */\n function isTimeDisabled(h: number, m: number): boolean {\n const total = h * 60 + m;\n const minParsed = parseTime(props.min.value);\n const maxParsed = parseTime(props.max.value);\n\n if (minParsed && total < minParsed.hours * 60 + minParsed.minutes) return true;\n\n if (maxParsed && total > maxParsed.hours * 60 + maxParsed.minutes) return true;\n\n return false;\n }\n\n // ── State for focused/pending selection ───────────────────────────────────\n\n /** Pending hour (24h) while user is navigating columns */\n const pendingHour = signal<number>(selectedTime.value?.hours ?? 0);\n /** Pending minute */\n const pendingMinute = signal<number>(selectedTime.value?.minutes ?? 0);\n /** Pending period (12h mode) */\n const pendingPeriod = signal<'AM' | 'PM'>((selectedTime.value?.hours ?? 0) >= 12 ? 'PM' : 'AM');\n\n // ── Sync value prop externally ────────────────────────────────────────────\n\n let lastValueProp = props.value.value;\n\n onMounted(() => {\n const interval = setInterval(() => {\n const current = props.value.value;\n\n if (current !== lastValueProp) {\n lastValueProp = current;\n\n const parsed = parseTime(current);\n\n selectedTime.value = parsed;\n\n if (parsed) {\n pendingHour.value = parsed.hours;\n pendingMinute.value = parsed.minutes;\n pendingPeriod.value = parsed.hours >= 12 ? 'PM' : 'AM';\n }\n }\n }, 50);\n\n return () => clearInterval(interval);\n });\n\n // ── Commit ────────────────────────────────────────────────────────────────\n\n function commit(h24: number, m: number): void {\n const clamped = clampTime(h24, m, props.min.value, props.max.value);\n const snapped = Math.round(clamped.minutes / minuteStep.value) * minuteStep.value;\n const snappedMin = Math.min(snapped, 59);\n\n selectedTime.value = { hours: clamped.hours, minutes: snappedMin };\n emit('change', { value: formatTime(clamped.hours, snappedMin) });\n }\n\n function commitFromMinute(m: number): void {\n const h24 = fmt.value === '12' ? to24Hour(pendingHour.value, pendingPeriod.value) : pendingHour.value;\n\n pendingMinute.value = m;\n commit(h24, m);\n closePicker();\n }\n\n // ── Open / close ──────────────────────────────────────────────────────────\n\n function openPicker(): void {\n if (isDisabled.value) return;\n\n const current = selectedTime.value;\n\n if (current) {\n pendingHour.value = fmt.value === '12' ? toDisplayHour(current.hours) : current.hours;\n pendingMinute.value = current.minutes;\n pendingPeriod.value = current.hours >= 12 ? 'PM' : 'AM';\n } else {\n pendingHour.value = fmt.value === '12' ? 12 : 0;\n pendingMinute.value = 0;\n pendingPeriod.value = 'AM';\n }\n\n isOpen.value = true;\n }\n\n function closePicker(): void {\n isOpen.value = false;\n }\n\n function handleTriggerClick(): void {\n if (isOpen.value) closePicker();\n else openPicker();\n }\n\n // ── Outside click ─────────────────────────────────────────────────────────\n\n function handleOutsideClick(e: PointerEvent | MouseEvent): void {\n if (!isOpen.value) return;\n\n if (!e.composedPath().includes(el)) closePicker();\n }\n\n onMounted(() => {\n document.addEventListener('pointerdown', handleOutsideClick, { capture: true });\n\n return () => document.removeEventListener('pointerdown', handleOutsideClick, { capture: true });\n });\n\n // ── Keyboard ──────────────────────────────────────────────────────────────\n\n function handleTriggerKeydown(e: KeyboardEvent): void {\n if (isDisabled.value) return;\n\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleTriggerClick();\n } else if (e.key === 'Escape' && isOpen.value) {\n e.preventDefault();\n closePicker();\n } else if ((e.key === 'ArrowDown' || e.key === 'ArrowUp') && !isOpen.value) {\n e.preventDefault();\n openPicker();\n }\n }\n\n function handleDropdownKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n e.preventDefault();\n closePicker();\n }\n }\n\n function handleHourKeydown(e: KeyboardEvent): void {\n const opts = hourOptions.value;\n const idx = opts.indexOf(pendingHour.value);\n\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n pendingHour.value = opts[(idx - 1 + opts.length) % opts.length];\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n pendingHour.value = opts[(idx + 1) % opts.length];\n }\n }\n\n function handleMinuteKeydown(e: KeyboardEvent): void {\n const opts = minuteOptions.value;\n const idx = opts.indexOf(pendingMinute.value);\n\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n pendingMinute.value = opts[(idx - 1 + opts.length) % opts.length];\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n pendingMinute.value = opts[(idx + 1) % opts.length];\n }\n }\n\n function handlePeriodKeydown(e: KeyboardEvent): void {\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n pendingPeriod.value = pendingPeriod.value === 'AM' ? 'PM' : 'AM';\n }\n }\n\n // ── Host bindings ─────────────────────────────────────────────────────────\n\n bind({\n attr: {\n open: () => (isOpen.value ? true : undefined),\n },\n });\n\n // ── ore-input prop helpers ────────────────────────────────────────────────\n\n const inputValue = () => triggerText.value;\n const inputLabel = () => props.label.value ?? '';\n const inputPlaceholder = () => props.placeholder.value ?? '';\n const inputLabelPlacement = () => props['label-placement'].value ?? 'inset';\n const inputColor = () => props.color?.value ?? undefined;\n const inputSize = () => fCtxProps.size?.value ?? undefined;\n const inputVariant = () => fCtxProps.variant?.value ?? undefined;\n const inputRounded = () => props.rounded?.value ?? undefined;\n const inputHelper = () => props.helper.value ?? '';\n const inputError = () => props.error.value ?? '';\n const inputDisabled = () => (isDisabled.value ? true : undefined);\n const inputRequired = () => (props.required.value ? true : undefined);\n const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n\n return html`\n <!-- Trigger -->\n <ore-input\n class=\"trigger\"\n readonly\n tabindex=\"0\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-controls=\"${dialogId}\"\n :aria-expanded=\"${() => String(isOpen.value)}\"\n :aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n :value=\"${inputValue}\"\n :label=\"${inputLabel}\"\n :placeholder=\"${inputPlaceholder}\"\n :label-placement=\"${inputLabelPlacement}\"\n :color=\"${inputColor}\"\n :size=\"${inputSize}\"\n :variant=\"${inputVariant}\"\n :rounded=\"${inputRounded}\"\n :helper=\"${inputHelper}\"\n :error=\"${inputError}\"\n ?disabled=\"${inputDisabled}\"\n ?required=\"${inputRequired}\"\n ?fullwidth=\"${inputFullwidth}\"\n @click=\"${handleTriggerClick}\"\n @keydown=\"${handleTriggerKeydown}\">\n <ore-icon slot=\"suffix\" name=\"clock\" size=\"16\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n </ore-input>\n\n <!-- Dropdown -->\n <div\n class=\"dropdown\"\n id=\"${dialogId}\"\n role=\"listbox\"\n aria-label=\"${() => (props.label.value ? `${props.label.value} — select time` : 'Select time')}\"\n ?data-open=\"${isOpen}\"\n @keydown=\"${handleDropdownKeydown}\">\n <div class=\"cols-row\">\n <!-- Hours column -->\n <div class=\"col\" part=\"column\" role=\"group\" aria-label=\"Hours\">\n <div class=\"col-label\" aria-hidden=\"true\">HH</div>\n <div class=\"col-scroll\">\n ${() =>\n hourOptions.value.map((h) => {\n const h24 = fmt.value === '12' ? to24Hour(h, pendingPeriod.value) : h;\n const disabled = isTimeDisabled(h24, pendingMinute.value);\n\n return html`<div\n class=\"option\"\n part=\"option\"\n role=\"option\"\n tabindex=\"${() => (pendingHour.value === h && !disabled ? '0' : '-1')}\"\n :aria-selected=\"${() => String(pendingHour.value === h)}\"\n :aria-disabled=\"${() => String(disabled)}\"\n ?data-disabled=\"${() => disabled}\"\n @click=\"${() => {\n if (!disabled) pendingHour.value = h;\n }}\"\n @keydown=\"${handleHourKeydown}\">\n ${String(h).padStart(2, '0')}\n </div>`;\n })}\n </div>\n </div>\n\n <div class=\"col-sep\" aria-hidden=\"true\">:</div>\n\n <!-- Minutes column -->\n <div class=\"col\" part=\"column\" role=\"group\" aria-label=\"Minutes\">\n <div class=\"col-label\" aria-hidden=\"true\">MM</div>\n <div class=\"col-scroll\">\n ${() =>\n minuteOptions.value.map((m) => {\n const h24 = fmt.value === '12' ? to24Hour(pendingHour.value, pendingPeriod.value) : pendingHour.value;\n const disabled = isTimeDisabled(h24, m);\n\n return html`<div\n class=\"option\"\n part=\"option\"\n role=\"option\"\n tabindex=\"${() => (pendingMinute.value === m && !disabled ? '0' : '-1')}\"\n :aria-selected=\"${() => String(pendingMinute.value === m)}\"\n :aria-disabled=\"${() => String(disabled)}\"\n ?data-disabled=\"${() => disabled}\"\n @click=\"${() => {\n if (!disabled) commitFromMinute(m);\n }}\"\n @keydown=\"${handleMinuteKeydown}\">\n ${String(m).padStart(2, '0')}\n </div>`;\n })}\n </div>\n </div>\n\n <!-- AM/PM column (12h mode only) -->\n ${() =>\n fmt.value === '12'\n ? html` <div class=\"col col-period\" part=\"column\" role=\"group\" aria-label=\"Period\">\n <div class=\"col-label\" aria-hidden=\"true\">AM/PM</div>\n <div class=\"col-scroll\">\n ${(['AM', 'PM'] as const).map(\n (p) =>\n html`<div\n class=\"option\"\n part=\"option\"\n role=\"option\"\n tabindex=\"${() => (pendingPeriod.value === p ? '0' : '-1')}\"\n :aria-selected=\"${() => String(pendingPeriod.value === p)}\"\n @click=\"${() => {\n pendingPeriod.value = p;\n }}\"\n @keydown=\"${handlePeriodKeydown}\">\n ${p}\n </div>`,\n )}\n </div>\n </div>`\n : html``}\n </div>\n </div>\n `;\n },\n\n shadow: { delegatesFocus: true },\n styles: [colorThemeMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"time-picker.cjs","names":[],"sources":["../src/inputs/time-picker/time-picker.ts"],"sourcesContent":["import { define, html, inject, prop, ref, bind, getHost, onMounted, useEmit } from '@vielzeug/ore';\nimport { useField } from '@vielzeug/ore/forms';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport type { VisualVariant } from '../../shared';\n\nimport { createDropdownPositioner } from '../../headless';\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin } from '../../styles';\nimport { FORM_CTX, useFormContext } from '../shared/form-context';\nimport componentStyles from './time-picker.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type OreTimePickerEvents = {\n change: { value: string | null };\n};\n\nexport type OreTimePickerProps = {\n /** Theme color */\n color?: string;\n /** Disable the picker */\n disabled?: boolean;\n /** Validation error message */\n error?: string;\n /** Expand to container width */\n fullwidth?: boolean;\n /** Helper text below the field */\n helper?: string;\n /** Visible label */\n label?: string;\n /** Label placement */\n 'label-placement'?: 'inset' | 'outside';\n /** Maximum selectable time in HH:MM format (24-hour) */\n max?: string;\n /** Minimum selectable time in HH:MM format (24-hour) */\n min?: string;\n /** Minute step interval (1–59) */\n 'minute-step'?: number;\n /** Form field name */\n name?: string;\n /** Placeholder shown in the trigger */\n placeholder?: string;\n /** Mark field as required */\n required?: boolean;\n /** Border radius */\n rounded?: string;\n /** Component size */\n size?: string;\n /**\n * Shows an inline green check icon inside the field to confirm the value has\n * passed validation. Ignored while `error` is set — an error always wins.\n */\n success?: boolean;\n /** Display format: '12' for AM/PM, '24' for 24-hour (default: '24') */\n 'time-format'?: '12' | '24';\n /** Selected time in HH:MM format (24-hour) */\n value?: string;\n /** Visual variant */\n variant?: Exclude<VisualVariant, 'text' | 'frost'>;\n};\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/** Parse \"HH:MM\" → { hours: 0-23, minutes: 0-59 } | null */\nfunction parseTime(val: string | undefined | null): { hours: number; minutes: number } | null {\n if (!val) return null;\n\n const match = /^(\\d{1,2}):(\\d{2})$/.exec(val.trim());\n\n if (!match) return null;\n\n const h = Number(match[1]);\n const m = Number(match[2]);\n\n if (h < 0 || h > 23 || m < 0 || m > 59) return null;\n\n return { hours: h, minutes: m };\n}\n\n/** Format { hours, minutes } → \"HH:MM\" (24-hour, zero-padded) */\nfunction formatTime(h: number, m: number): string {\n return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;\n}\n\n/** Format for display label (respects 12/24 mode) */\nfunction formatDisplay(h: number, m: number, format: '12' | '24'): string {\n if (format === '12') {\n const period = h >= 12 ? 'PM' : 'AM';\n const displayH = h % 12 === 0 ? 12 : h % 12;\n\n return `${String(displayH).padStart(2, '0')}:${String(m).padStart(2, '0')} ${period}`;\n }\n\n return formatTime(h, m);\n}\n\n/** Clamp value to [min, max] in total minutes */\nfunction clampTime(\n h: number,\n m: number,\n minVal: string | undefined | null,\n maxVal: string | undefined | null,\n): { hours: number; minutes: number } {\n const total = h * 60 + m;\n const minParsed = parseTime(minVal);\n const maxParsed = parseTime(maxVal);\n const minMins = minParsed ? minParsed.hours * 60 + minParsed.minutes : 0;\n const maxMins = maxParsed ? maxParsed.hours * 60 + maxParsed.minutes : 23 * 60 + 59;\n const clamped = Math.min(Math.max(total, minMins), maxMins);\n\n return { hours: Math.floor(clamped / 60), minutes: clamped % 60 };\n}\n\n/**\n * An accessible time picker with a scrollable clock dropdown.\n * Supports 12/24-hour display formats, min/max bounds, minute steps, and form association.\n *\n * @element ore-time-picker\n *\n * @attr {string} value - Selected time in HH:MM (24-hour) format\n * @attr {string} min - Minimum selectable time (HH:MM)\n * @attr {string} max - Maximum selectable time (HH:MM)\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} placeholder - Trigger placeholder\n * @attr {boolean} disabled - Disable the picker\n * @attr {boolean} required - Required field\n * @attr {string} name - Form field name\n * @attr {string} error - Error message\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} helper - Helper text\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} time-format - '12' or '24' (default: '24')\n * @attr {number} minute-step - Minute increment (default: 5)\n *\n * @fires change - Fired when a time is selected. detail: { value: string | null }\n *\n * @slot label - Custom label for the trigger field\n * @slot prefix - Content before the trigger text (e.g. icon)\n * @slot helper - Custom helper text\n * @slot error - Custom error content\n *\n * @cssprop --time-picker-bg - Dropdown background\n * @cssprop --time-picker-border-color - Dropdown border color\n * @cssprop --time-picker-radius - Dropdown border radius\n * @cssprop --time-picker-shadow - Dropdown shadow\n * @cssprop --time-picker-selected-bg - Selected option background\n * @cssprop --time-picker-option-hover-bg - Option hover background\n *\n * @part field - The trigger field\n * @part dropdown - The floating time dropdown\n * @part column - A scrollable column (hours / minutes / period)\n * @part option - An individual time option cell\n *\n * @example\n * ```html\n * <!-- 24-hour clock, 15-minute steps -->\n * <ore-time-picker label=\"Meeting time\" value=\"09:30\" minute-step=\"15\" color=\"primary\"></ore-time-picker>\n *\n * <!-- 12-hour AM/PM format -->\n * <ore-time-picker label=\"Appointment\" time-format=\"12\" minute-step=\"30\"></ore-time-picker>\n *\n * <!-- Outside label, bordered variant -->\n * <ore-time-picker label=\"Start time\" label-placement=\"outside\" variant=\"bordered\"></ore-time-picker>\n * ```\n */\nexport const TIME_PICKER_TAG = 'ore-time-picker' as const;\n\ndefine<OreTimePickerProps>(TIME_PICKER_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...roundableBundle,\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n max: prop.string(),\n min: prop.string(),\n 'minute-step': prop.number(5),\n name: prop.string(),\n placeholder: prop.string(),\n required: prop.bool(false),\n success: prop.bool(false),\n 'time-format': prop.oneOf(['12', '24'] as const, '24'),\n value: prop.string(),\n variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n },\n\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreTimePickerEvents>();\n\n // ── Signals ──────────────────────────────────────────────────────────────\n\n const isOpen = signal(false);\n const selectedTime = signal<{ hours: number; minutes: number } | null>(parseTime(props.value.value));\n\n // ── Floating position ────────────────────────────────────────────────────\n // Same Orbit-powered positioner ore-date-picker's `.calendar` popup uses (see its own\n // comment for the full rationale) — `fixed` + computed `top`/`left` instead of a static\n // `position: absolute; top: 100%`, so the dropdown flips/shifts to stay within the nearest\n // clipping ancestor instead of silently overflowing it.\n const triggerRef = ref<HTMLElement>();\n const dropdownRef = ref<HTMLElement>();\n\n const positioner = createDropdownPositioner({\n getFloating: () => dropdownRef.value ?? null,\n getReference: () => triggerRef.value ?? null,\n matchWidth: false,\n offsetPx: 4,\n });\n\n let stopAutoUpdate: (() => void) | null = null;\n\n // ── Form context ─────────────────────────────────────────────────────────\n\n const formCtx = inject(FORM_CTX);\n const fCtxProps = useFormContext(props, formCtx);\n const isDisabled = fCtxProps.disabled;\n\n // ── Form value ────────────────────────────────────────────────────────────\n\n useField<string>({\n disabled: isDisabled,\n toFormValue: (v) => v || null,\n value: computed(() => {\n const t = selectedTime.value;\n\n return t ? formatTime(t.hours, t.minutes) : '';\n }),\n });\n\n // ── Computed helpers ──────────────────────────────────────────────────────\n\n const fmt = computed(() => props['time-format'].value ?? '24');\n const minuteStep = computed(() => Math.max(1, Math.min(59, props['minute-step'].value ?? 5)));\n\n const triggerText = computed(() => {\n if (!selectedTime.value) return props.placeholder.value || '';\n\n return formatDisplay(selectedTime.value.hours, selectedTime.value.minutes, fmt.value as '12' | '24');\n });\n\n /** All hour options for the column (0-23 in 24h; 1-12 in 12h) */\n const hourOptions = computed<number[]>(() => {\n if (fmt.value === '12') {\n return Array.from({ length: 12 }, (_, i) => i + 1);\n }\n\n return Array.from({ length: 24 }, (_, i) => i);\n });\n\n /** All minute options for the column, stepped */\n const minuteOptions = computed<number[]>(() => {\n const step = minuteStep.value;\n const opts: number[] = [];\n\n for (let m = 0; m < 60; m += step) opts.push(m);\n\n return opts;\n });\n\n const dialogId = `time-picker-${Math.random().toString(36).slice(2, 9)}-dropdown`;\n\n /** Convert 24h hour to display hour in current format */\n function toDisplayHour(h24: number): number {\n if (fmt.value === '24') return h24;\n\n const h12 = h24 % 12;\n\n return h12 === 0 ? 12 : h12;\n }\n\n /** Convert display hour + period → 24h hour */\n function to24Hour(displayHour: number, period: 'AM' | 'PM'): number {\n if (fmt.value === '24') return displayHour;\n\n if (period === 'AM') return displayHour === 12 ? 0 : displayHour;\n\n return displayHour === 12 ? 12 : displayHour + 12;\n }\n\n /** Whether a given HH:MM is out of [min, max] */\n function isTimeDisabled(h: number, m: number): boolean {\n const total = h * 60 + m;\n const minParsed = parseTime(props.min.value);\n const maxParsed = parseTime(props.max.value);\n\n if (minParsed && total < minParsed.hours * 60 + minParsed.minutes) return true;\n\n if (maxParsed && total > maxParsed.hours * 60 + maxParsed.minutes) return true;\n\n return false;\n }\n\n // ── State for focused/pending selection ───────────────────────────────────\n\n /** Pending hour (24h) while user is navigating columns */\n const pendingHour = signal<number>(selectedTime.value?.hours ?? 0);\n /** Pending minute */\n const pendingMinute = signal<number>(selectedTime.value?.minutes ?? 0);\n /** Pending period (12h mode) */\n const pendingPeriod = signal<'AM' | 'PM'>((selectedTime.value?.hours ?? 0) >= 12 ? 'PM' : 'AM');\n\n // ── Sync value prop externally ────────────────────────────────────────────\n\n let lastValueProp = props.value.value;\n\n onMounted(() => {\n const interval = setInterval(() => {\n const current = props.value.value;\n\n if (current !== lastValueProp) {\n lastValueProp = current;\n\n const parsed = parseTime(current);\n\n selectedTime.value = parsed;\n\n if (parsed) {\n pendingHour.value = parsed.hours;\n pendingMinute.value = parsed.minutes;\n pendingPeriod.value = parsed.hours >= 12 ? 'PM' : 'AM';\n }\n }\n }, 50);\n\n return () => clearInterval(interval);\n });\n\n // ── Commit ────────────────────────────────────────────────────────────────\n\n function commit(h24: number, m: number): void {\n const clamped = clampTime(h24, m, props.min.value, props.max.value);\n const snapped = Math.round(clamped.minutes / minuteStep.value) * minuteStep.value;\n const snappedMin = Math.min(snapped, 59);\n\n selectedTime.value = { hours: clamped.hours, minutes: snappedMin };\n emit('change', { value: formatTime(clamped.hours, snappedMin) });\n }\n\n function commitFromMinute(m: number): void {\n const h24 = fmt.value === '12' ? to24Hour(pendingHour.value, pendingPeriod.value) : pendingHour.value;\n\n pendingMinute.value = m;\n commit(h24, m);\n closePicker();\n }\n\n // ── Open / close ──────────────────────────────────────────────────────────\n\n function openPicker(): void {\n if (isDisabled.value) return;\n\n const current = selectedTime.value;\n\n if (current) {\n pendingHour.value = fmt.value === '12' ? toDisplayHour(current.hours) : current.hours;\n pendingMinute.value = current.minutes;\n pendingPeriod.value = current.hours >= 12 ? 'PM' : 'AM';\n } else {\n pendingHour.value = fmt.value === '12' ? 12 : 0;\n pendingMinute.value = 0;\n pendingPeriod.value = 'AM';\n }\n\n isOpen.value = true;\n positioner.update();\n stopAutoUpdate = positioner.startAutoUpdate?.() ?? null;\n }\n\n function closePicker(): void {\n isOpen.value = false;\n stopAutoUpdate?.();\n stopAutoUpdate = null;\n }\n\n function handleTriggerClick(): void {\n if (isOpen.value) closePicker();\n else openPicker();\n }\n\n // ── Outside click ─────────────────────────────────────────────────────────\n\n function handleOutsideClick(e: PointerEvent | MouseEvent): void {\n if (!isOpen.value) return;\n\n if (!e.composedPath().includes(el)) closePicker();\n }\n\n onMounted(() => {\n document.addEventListener('pointerdown', handleOutsideClick, { capture: true });\n\n return () => {\n document.removeEventListener('pointerdown', handleOutsideClick, { capture: true });\n stopAutoUpdate?.();\n stopAutoUpdate = null;\n };\n });\n\n // ── Keyboard ──────────────────────────────────────────────────────────────\n\n function handleTriggerKeydown(e: KeyboardEvent): void {\n if (isDisabled.value) return;\n\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleTriggerClick();\n } else if (e.key === 'Escape' && isOpen.value) {\n e.preventDefault();\n closePicker();\n } else if ((e.key === 'ArrowDown' || e.key === 'ArrowUp') && !isOpen.value) {\n e.preventDefault();\n openPicker();\n }\n }\n\n function handleDropdownKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n e.preventDefault();\n closePicker();\n }\n }\n\n function handleHourKeydown(e: KeyboardEvent): void {\n const opts = hourOptions.value;\n const idx = opts.indexOf(pendingHour.value);\n\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n pendingHour.value = opts[(idx - 1 + opts.length) % opts.length];\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n pendingHour.value = opts[(idx + 1) % opts.length];\n }\n }\n\n function handleMinuteKeydown(e: KeyboardEvent): void {\n const opts = minuteOptions.value;\n const idx = opts.indexOf(pendingMinute.value);\n\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n pendingMinute.value = opts[(idx - 1 + opts.length) % opts.length];\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n pendingMinute.value = opts[(idx + 1) % opts.length];\n }\n }\n\n function handlePeriodKeydown(e: KeyboardEvent): void {\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n pendingPeriod.value = pendingPeriod.value === 'AM' ? 'PM' : 'AM';\n }\n }\n\n // ── Host bindings ─────────────────────────────────────────────────────────\n\n bind({\n attr: {\n open: () => (isOpen.value ? true : undefined),\n },\n });\n\n // ── ore-input prop helpers ────────────────────────────────────────────────\n\n const inputValue = () => triggerText.value;\n const inputLabel = () => props.label.value ?? '';\n const inputPlaceholder = () => props.placeholder.value ?? '';\n const inputLabelPlacement = () => props['label-placement'].value ?? 'inset';\n const inputColor = () => props.color?.value ?? undefined;\n const inputSize = () => fCtxProps.size?.value ?? undefined;\n const inputVariant = () => fCtxProps.variant?.value ?? undefined;\n const inputRounded = () => props.rounded?.value ?? undefined;\n const inputHelper = () => props.helper.value ?? '';\n const inputError = () => props.error.value ?? '';\n const inputDisabled = () => (isDisabled.value ? true : undefined);\n const inputRequired = () => (props.required.value ? true : undefined);\n const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n\n return html`\n <!-- Trigger -->\n <ore-input\n class=\"trigger\"\n ref=\"${triggerRef}\"\n readonly\n tabindex=\"0\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-controls=\"${dialogId}\"\n :aria-expanded=\"${() => String(isOpen.value)}\"\n :aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n :value=\"${inputValue}\"\n :label=\"${inputLabel}\"\n :placeholder=\"${inputPlaceholder}\"\n :label-placement=\"${inputLabelPlacement}\"\n :color=\"${inputColor}\"\n :size=\"${inputSize}\"\n :variant=\"${inputVariant}\"\n :rounded=\"${inputRounded}\"\n :helper=\"${inputHelper}\"\n :error=\"${inputError}\"\n ?disabled=\"${inputDisabled}\"\n ?required=\"${inputRequired}\"\n ?fullwidth=\"${inputFullwidth}\"\n ?success=\"${() => props.success.value}\"\n @click=\"${handleTriggerClick}\"\n @keydown=\"${handleTriggerKeydown}\">\n <ore-icon slot=\"suffix\" name=\"clock\" size=\"16\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n </ore-input>\n\n <!-- Dropdown -->\n <div\n class=\"dropdown\"\n ref=\"${dropdownRef}\"\n id=\"${dialogId}\"\n role=\"listbox\"\n aria-label=\"${() => (props.label.value ? `${props.label.value} — select time` : 'Select time')}\"\n ?data-open=\"${isOpen}\"\n @keydown=\"${handleDropdownKeydown}\">\n <div class=\"cols-row\">\n <!-- Hours column -->\n <div class=\"col\" part=\"column\" role=\"group\" aria-label=\"Hours\">\n <div class=\"col-label\" aria-hidden=\"true\">HH</div>\n <div class=\"col-scroll\">\n ${() =>\n hourOptions.value.map((h) => {\n const h24 = fmt.value === '12' ? to24Hour(h, pendingPeriod.value) : h;\n const disabled = isTimeDisabled(h24, pendingMinute.value);\n\n return html`<div\n class=\"option\"\n part=\"option\"\n role=\"option\"\n tabindex=\"${() => (pendingHour.value === h && !disabled ? '0' : '-1')}\"\n :aria-selected=\"${() => String(pendingHour.value === h)}\"\n :aria-disabled=\"${() => String(disabled)}\"\n ?data-disabled=\"${() => disabled}\"\n @click=\"${() => {\n if (!disabled) pendingHour.value = h;\n }}\"\n @keydown=\"${handleHourKeydown}\">\n ${String(h).padStart(2, '0')}\n </div>`;\n })}\n </div>\n </div>\n\n <div class=\"col-sep\" aria-hidden=\"true\">:</div>\n\n <!-- Minutes column -->\n <div class=\"col\" part=\"column\" role=\"group\" aria-label=\"Minutes\">\n <div class=\"col-label\" aria-hidden=\"true\">MM</div>\n <div class=\"col-scroll\">\n ${() =>\n minuteOptions.value.map((m) => {\n const h24 = fmt.value === '12' ? to24Hour(pendingHour.value, pendingPeriod.value) : pendingHour.value;\n const disabled = isTimeDisabled(h24, m);\n\n return html`<div\n class=\"option\"\n part=\"option\"\n role=\"option\"\n tabindex=\"${() => (pendingMinute.value === m && !disabled ? '0' : '-1')}\"\n :aria-selected=\"${() => String(pendingMinute.value === m)}\"\n :aria-disabled=\"${() => String(disabled)}\"\n ?data-disabled=\"${() => disabled}\"\n @click=\"${() => {\n if (!disabled) commitFromMinute(m);\n }}\"\n @keydown=\"${handleMinuteKeydown}\">\n ${String(m).padStart(2, '0')}\n </div>`;\n })}\n </div>\n </div>\n\n <!-- AM/PM column (12h mode only) -->\n ${() =>\n fmt.value === '12'\n ? html` <div class=\"col col-period\" part=\"column\" role=\"group\" aria-label=\"Period\">\n <div class=\"col-label\" aria-hidden=\"true\">AM/PM</div>\n <div class=\"col-scroll\">\n ${(['AM', 'PM'] as const).map(\n (p) =>\n html`<div\n class=\"option\"\n part=\"option\"\n role=\"option\"\n tabindex=\"${() => (pendingPeriod.value === p ? '0' : '-1')}\"\n :aria-selected=\"${() => String(pendingPeriod.value === p)}\"\n @click=\"${() => {\n pendingPeriod.value = p;\n }}\"\n @keydown=\"${handlePeriodKeydown}\">\n ${p}\n </div>`,\n )}\n </div>\n </div>`\n : html``}\n </div>\n </div>\n `;\n },\n\n shadow: { delegatesFocus: true },\n styles: [colorThemeMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"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"}