@passui/react 0.1.46 → 0.2.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 (429) hide show
  1. package/README.md +29 -109
  2. package/THIRD_PARTY_NOTICES.md +29 -0
  3. package/dist/accordion.d.ts +15 -0
  4. package/dist/accordion.js +93 -0
  5. package/dist/alert-dialog.d.ts +26 -0
  6. package/dist/alert-dialog.js +142 -0
  7. package/dist/alert.d.ts +10 -0
  8. package/dist/alert.js +28 -0
  9. package/dist/{types/src/components/ambient/ambient.d.ts → ambient.d.ts} +4 -4
  10. package/dist/ambient.js +22 -0
  11. package/dist/{types/src/appearance → appearance}/platform.d.ts +3 -3
  12. package/dist/appearance/platform.js +43 -0
  13. package/dist/appearance/theme.d.ts +71 -0
  14. package/dist/appearance/theme.js +236 -0
  15. package/dist/appearance.d.ts +3 -0
  16. package/dist/appearance.js +3 -0
  17. package/dist/{types/src/components/aspect-ratio/aspect-ratio.d.ts → aspect-ratio.d.ts} +4 -4
  18. package/dist/aspect-ratio.js +17 -0
  19. package/dist/avatar.d.ts +5 -0
  20. package/dist/avatar.js +43 -0
  21. package/dist/badge.d.ts +8 -0
  22. package/dist/badge.js +21 -0
  23. package/dist/breadcrumb.d.ts +13 -0
  24. package/dist/breadcrumb.js +63 -0
  25. package/dist/button-group.d.ts +5 -0
  26. package/dist/button-group.js +14 -0
  27. package/dist/button.d.ts +21 -0
  28. package/dist/button.js +58 -0
  29. package/dist/calendar.d.ts +35 -0
  30. package/dist/calendar.js +225 -0
  31. package/dist/card.d.ts +9 -0
  32. package/dist/card.js +54 -0
  33. package/dist/chart.d.ts +30 -0
  34. package/dist/chart.js +226 -0
  35. package/dist/checkbox.d.ts +13 -0
  36. package/dist/checkbox.js +53 -0
  37. package/dist/{types/src/lib/clipboard.d.ts → clipboard.d.ts} +1 -1
  38. package/dist/clipboard.js +16 -0
  39. package/dist/cn.d.ts +2 -0
  40. package/dist/cn.js +10 -0
  41. package/dist/code-block.d.ts +34 -0
  42. package/dist/code-block.js +87 -0
  43. package/dist/collapsible.d.ts +13 -0
  44. package/dist/collapsible.js +49 -0
  45. package/dist/combobox.d.ts +25 -0
  46. package/dist/combobox.js +112 -0
  47. package/dist/command.d.ts +22 -0
  48. package/dist/command.js +129 -0
  49. package/dist/components/toast/toast-store.d.ts +60 -0
  50. package/dist/components/toast/toast-store.js +96 -0
  51. package/dist/{types/src/components → components}/toast/toaster.d.ts +4 -4
  52. package/dist/components/toast/toaster.js +345 -0
  53. package/dist/context-menu.d.ts +2 -0
  54. package/dist/context-menu.js +2 -0
  55. package/dist/conversation.d.ts +48 -0
  56. package/dist/conversation.js +202 -0
  57. package/dist/date-time-picker.d.ts +50 -0
  58. package/dist/date-time-picker.js +235 -0
  59. package/dist/date.d.ts +50 -0
  60. package/dist/date.js +77 -0
  61. package/dist/dialog.d.ts +21 -0
  62. package/dist/dialog.js +113 -0
  63. package/dist/drawer.d.ts +30 -0
  64. package/dist/drawer.js +140 -0
  65. package/dist/dropdown-menu.d.ts +56 -0
  66. package/dist/dropdown-menu.js +295 -0
  67. package/dist/empty.d.ts +11 -0
  68. package/dist/empty.js +51 -0
  69. package/dist/field.d.ts +16 -0
  70. package/dist/field.js +47 -0
  71. package/{src/hooks/scroll/minimize-decision.ts → dist/hooks/scroll/minimize-decision.js} +3 -5
  72. package/dist/{types/src/hooks → hooks}/use-anchored-placement.d.ts +2 -2
  73. package/dist/hooks/use-anchored-placement.js +33 -0
  74. package/dist/{types/src/hooks → hooks}/use-minimize-on-scroll.d.ts +1 -1
  75. package/dist/hooks/use-minimize-on-scroll.js +59 -0
  76. package/dist/{types/src/hooks → hooks}/use-visual-viewport.d.ts +2 -2
  77. package/{src/hooks/use-visual-viewport.ts → dist/hooks/use-visual-viewport.js} +20 -35
  78. package/dist/hooks/viewport/types.d.ts +7 -0
  79. package/dist/hooks/viewport/viewport-metrics.js +13 -0
  80. package/dist/index.d.ts +84 -0
  81. package/dist/index.js +80 -0
  82. package/dist/input-group.d.ts +17 -0
  83. package/dist/input-group.js +55 -0
  84. package/dist/input-otp.d.ts +13 -0
  85. package/dist/input-otp.js +36 -0
  86. package/dist/input.d.ts +4 -0
  87. package/dist/input.js +14 -0
  88. package/dist/item.d.ts +49 -0
  89. package/dist/item.js +142 -0
  90. package/dist/kbd.d.ts +4 -0
  91. package/dist/kbd.js +86 -0
  92. package/dist/label.d.ts +3 -0
  93. package/dist/label.js +12 -0
  94. package/dist/labeled-content.d.ts +24 -0
  95. package/dist/labeled-content.js +41 -0
  96. package/dist/{types/src/lib/language.d.ts → language.d.ts} +1 -1
  97. package/dist/language.js +11 -0
  98. package/dist/layout.d.ts +24 -0
  99. package/dist/layout.js +36 -0
  100. package/dist/{types/src/lib → lib}/anchored-placement.d.ts +27 -27
  101. package/dist/lib/anchored-placement.js +42 -0
  102. package/dist/lib/calendar-month.js +90 -0
  103. package/dist/lib/cx.js +6 -0
  104. package/dist/lib/drawer.math.js +29 -0
  105. package/dist/lib/floating-layers.d.ts +3 -0
  106. package/dist/lib/floating-layers.js +25 -0
  107. package/dist/{types/src/lib → lib}/haptics.d.ts +1 -1
  108. package/dist/lib/haptics.js +13 -0
  109. package/dist/lib/liquid-step.js +33 -0
  110. package/dist/lib/page-scale.js +58 -0
  111. package/dist/lib/portal.js +12 -0
  112. package/dist/lib/presence.js +53 -0
  113. package/dist/lib/range-value.js +25 -0
  114. package/dist/lib/render.d.ts +8 -0
  115. package/dist/lib/render.js +42 -0
  116. package/dist/lib/rolling-digit.js +83 -0
  117. package/dist/{types/src/lib → lib}/screen-edges.d.ts +5 -5
  118. package/dist/lib/screen-edges.js +30 -0
  119. package/dist/lib/swipe-touch-action.js +34 -0
  120. package/dist/lib/visual-viewport.js +27 -0
  121. package/dist/lib/water-drop.js +412 -0
  122. package/dist/lib/wheel.js +125 -0
  123. package/dist/list.d.ts +26 -0
  124. package/dist/list.js +80 -0
  125. package/dist/locales.d.ts +18 -0
  126. package/dist/locales.js +36 -0
  127. package/dist/marker.d.ts +13 -0
  128. package/dist/marker.js +33 -0
  129. package/dist/motion/transitions.d.ts +170 -0
  130. package/dist/motion/transitions.js +156 -0
  131. package/dist/pagination.d.ts +30 -0
  132. package/dist/pagination.js +117 -0
  133. package/dist/popover.d.ts +26 -0
  134. package/dist/popover.js +101 -0
  135. package/dist/progress.d.ts +9 -0
  136. package/dist/progress.js +24 -0
  137. package/dist/questionnaire.d.ts +46 -0
  138. package/dist/questionnaire.js +133 -0
  139. package/dist/radio-group.d.ts +21 -0
  140. package/dist/radio-group.js +67 -0
  141. package/dist/search-field.d.ts +18 -0
  142. package/dist/search-field.js +45 -0
  143. package/dist/segmented-control.d.ts +16 -0
  144. package/dist/segmented-control.js +25 -0
  145. package/dist/select.d.ts +24 -0
  146. package/dist/select.js +107 -0
  147. package/dist/separator.d.ts +9 -0
  148. package/dist/separator.js +17 -0
  149. package/dist/{types/src/lib/shapes.d.ts → shapes.d.ts} +2 -2
  150. package/dist/shapes.js +65 -0
  151. package/dist/sheet.d.ts +24 -0
  152. package/dist/sheet.js +141 -0
  153. package/dist/sidebar.d.ts +32 -0
  154. package/dist/sidebar.js +85 -0
  155. package/dist/skeleton.d.ts +3 -0
  156. package/dist/skeleton.js +13 -0
  157. package/dist/slider.d.ts +9 -0
  158. package/dist/slider.js +42 -0
  159. package/dist/slosh-slider.d.ts +21 -0
  160. package/dist/slosh-slider.js +205 -0
  161. package/dist/spinner.d.ts +3 -0
  162. package/dist/spinner.js +20 -0
  163. package/dist/stat-tile.d.ts +20 -0
  164. package/dist/stat-tile.js +53 -0
  165. package/dist/stepper.d.ts +22 -0
  166. package/dist/stepper.js +98 -0
  167. package/dist/swatch-picker.d.ts +22 -0
  168. package/dist/swatch-picker.js +70 -0
  169. package/dist/switch.d.ts +10 -0
  170. package/dist/switch.js +44 -0
  171. package/dist/tab-bar.d.ts +15 -0
  172. package/dist/tab-bar.js +34 -0
  173. package/dist/{types/src/components/table/table.d.ts → table.d.ts} +3 -3
  174. package/dist/table.js +93 -0
  175. package/dist/tabs.d.ts +32 -0
  176. package/dist/tabs.js +131 -0
  177. package/dist/text.d.ts +25 -0
  178. package/dist/text.js +44 -0
  179. package/dist/textarea.d.ts +3 -0
  180. package/dist/textarea.js +13 -0
  181. package/dist/toast.d.ts +3 -0
  182. package/dist/toast.js +3 -0
  183. package/dist/toggle-group.d.ts +20 -0
  184. package/dist/toggle-group.js +68 -0
  185. package/dist/toggle.d.ts +24 -0
  186. package/dist/toggle.js +37 -0
  187. package/dist/tokens.d.ts +1 -0
  188. package/dist/tooltip.d.ts +21 -0
  189. package/dist/tooltip.js +61 -0
  190. package/dist/trace.d.ts +14 -0
  191. package/dist/trace.js +54 -0
  192. package/dist/{types/src/hooks/use-dismiss.d.ts → use-dismiss.d.ts} +3 -3
  193. package/dist/use-dismiss.js +38 -0
  194. package/dist/{types/src/hooks/use-media-query.d.ts → use-media-query.d.ts} +12 -12
  195. package/dist/use-media-query.js +56 -0
  196. package/dist/use-os.d.ts +12 -0
  197. package/dist/use-os.js +17 -0
  198. package/dist/wake-slider.d.ts +15 -0
  199. package/dist/wake-slider.js +174 -0
  200. package/package.json +122 -253
  201. package/src/styles/code-block.css +4 -0
  202. package/src/styles/globals.css +5 -0
  203. package/src/styles/motion-controls.css +10 -0
  204. package/src/styles/page-scale.css +27 -0
  205. package/src/styles/styles.css +4 -2
  206. package/dist/types/src/appearance/index.d.ts +0 -2
  207. package/dist/types/src/appearance/theme.d.ts +0 -71
  208. package/dist/types/src/components/accordion/accordion.d.ts +0 -23
  209. package/dist/types/src/components/ambient/index.d.ts +0 -1
  210. package/dist/types/src/components/breadcrumb/breadcrumb.d.ts +0 -19
  211. package/dist/types/src/components/button/button-styles.d.ts +0 -12
  212. package/dist/types/src/components/button/button.d.ts +0 -32
  213. package/dist/types/src/components/button/icon-button.d.ts +0 -10
  214. package/dist/types/src/components/button/pending-spinner.d.ts +0 -5
  215. package/dist/types/src/components/button/use-pending-indicator.d.ts +0 -2
  216. package/dist/types/src/components/chip/chip.d.ts +0 -10
  217. package/dist/types/src/components/code-block/code-block.d.ts +0 -13
  218. package/dist/types/src/components/combo-box/combo-box.d.ts +0 -9
  219. package/dist/types/src/components/command/command.d.ts +0 -18
  220. package/dist/types/src/components/compact-date-picker/calendar-month.d.ts +0 -25
  221. package/dist/types/src/components/compact-date-picker/compact-date-picker.d.ts +0 -30
  222. package/dist/types/src/components/compact-time-picker/compact-time-picker.d.ts +0 -29
  223. package/dist/types/src/components/compact-time-picker/time-value.d.ts +0 -18
  224. package/dist/types/src/components/content-unavailable-view/content-unavailable-view.d.ts +0 -12
  225. package/dist/types/src/components/content-view/content-view.d.ts +0 -51
  226. package/dist/types/src/components/content-view/index.d.ts +0 -1
  227. package/dist/types/src/components/context-menu/conceal-menu-source.d.ts +0 -2
  228. package/dist/types/src/components/context-menu/context-menu-host.d.ts +0 -2
  229. package/dist/types/src/components/context-menu/context-menu-store.d.ts +0 -62
  230. package/dist/types/src/components/context-menu/menu-navigation.d.ts +0 -6
  231. package/dist/types/src/components/context-menu/menu-position.d.ts +0 -21
  232. package/dist/types/src/components/context-menu/menu-reveal.d.ts +0 -26
  233. package/dist/types/src/components/context-menu/use-context-menu.d.ts +0 -14
  234. package/dist/types/src/components/conversation/conversation.d.ts +0 -48
  235. package/dist/types/src/components/conversation/index.d.ts +0 -1
  236. package/dist/types/src/components/date-picker/date-picker.d.ts +0 -19
  237. package/dist/types/src/components/date-picker/date-value.d.ts +0 -2
  238. package/dist/types/src/components/dialog/dialog-host.d.ts +0 -6
  239. package/dist/types/src/components/dialog/dialog-store.d.ts +0 -23
  240. package/dist/types/src/components/dialog/dialog.d.ts +0 -33
  241. package/dist/types/src/components/dialog/index.d.ts +0 -1
  242. package/dist/types/src/components/disclosure-group/disclosure-group.d.ts +0 -18
  243. package/dist/types/src/components/divider/divider.d.ts +0 -9
  244. package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +0 -15
  245. package/dist/types/src/components/keyboard-shortcut/keyboard-shortcut.d.ts +0 -8
  246. package/dist/types/src/components/labeled-content/labeled-content.d.ts +0 -22
  247. package/dist/types/src/components/locale-switcher/index.d.ts +0 -1
  248. package/dist/types/src/components/locale-switcher/locale-switcher.d.ts +0 -13
  249. package/dist/types/src/components/menu/menu.d.ts +0 -16
  250. package/dist/types/src/components/morph/index.d.ts +0 -2
  251. package/dist/types/src/components/morph/morph.d.ts +0 -32
  252. package/dist/types/src/components/morph/use-morph-disclosure.d.ts +0 -13
  253. package/dist/types/src/components/one-time-code/one-time-code.d.ts +0 -26
  254. package/dist/types/src/components/picker/picker-trigger.d.ts +0 -3
  255. package/dist/types/src/components/picker/picker.d.ts +0 -46
  256. package/dist/types/src/components/popover/anchored-surface.d.ts +0 -17
  257. package/dist/types/src/components/popover/index.d.ts +0 -41
  258. package/dist/types/src/components/popover/popover-content.d.ts +0 -32
  259. package/dist/types/src/components/popover/popover-fit.d.ts +0 -21
  260. package/dist/types/src/components/popover/popover-root.d.ts +0 -22
  261. package/dist/types/src/components/popover/popover-trigger.d.ts +0 -23
  262. package/dist/types/src/components/profile-image/profile-image.d.ts +0 -9
  263. package/dist/types/src/components/progress-view/progress-view.d.ts +0 -13
  264. package/dist/types/src/components/progress-view/use-liquid-progress.d.ts +0 -3
  265. package/dist/types/src/components/radio-group/radio-group.d.ts +0 -20
  266. package/dist/types/src/components/search-field/expanding-search-field.d.ts +0 -5
  267. package/dist/types/src/components/search-field/search-field.d.ts +0 -9
  268. package/dist/types/src/components/search-list/search-list.d.ts +0 -22
  269. package/dist/types/src/components/section/section.d.ts +0 -18
  270. package/dist/types/src/components/secure-field/secure-field.d.ts +0 -4
  271. package/dist/types/src/components/segmented-control/segmented-control.d.ts +0 -25
  272. package/dist/types/src/components/sheet/modal-environment.d.ts +0 -2
  273. package/dist/types/src/components/sheet/sheet-portal.d.ts +0 -5
  274. package/dist/types/src/components/sheet/sheet.d.ts +0 -26
  275. package/dist/types/src/components/sheet/use-sheet-focus.d.ts +0 -3
  276. package/dist/types/src/components/sidebar/sidebar.d.ts +0 -24
  277. package/dist/types/src/components/skeleton/skeleton.d.ts +0 -9
  278. package/dist/types/src/components/slider/slider.d.ts +0 -17
  279. package/dist/types/src/components/slosh-slider/liquid-step.d.ts +0 -6
  280. package/dist/types/src/components/slosh-slider/slosh-slider.d.ts +0 -21
  281. package/dist/types/src/components/stat-tile/index.d.ts +0 -1
  282. package/dist/types/src/components/stat-tile/stat-tile.d.ts +0 -20
  283. package/dist/types/src/components/status-indicator/status-indicator.d.ts +0 -17
  284. package/dist/types/src/components/stepper/rolling-digit.d.ts +0 -11
  285. package/dist/types/src/components/stepper/stepper.d.ts +0 -22
  286. package/dist/types/src/components/swatch-picker/swatch-picker.d.ts +0 -22
  287. package/dist/types/src/components/tab-bar/tab-bar.d.ts +0 -43
  288. package/dist/types/src/components/tab-view/tab-view.d.ts +0 -27
  289. package/dist/types/src/components/text-editor/text-editor.d.ts +0 -9
  290. package/dist/types/src/components/text-field/text-field.d.ts +0 -33
  291. package/dist/types/src/components/toast/toast-store.d.ts +0 -52
  292. package/dist/types/src/components/toggle/toggle.d.ts +0 -22
  293. package/dist/types/src/components/tooltip/tooltip-host.d.ts +0 -7
  294. package/dist/types/src/components/view-controller/index.d.ts +0 -1
  295. package/dist/types/src/components/view-controller/view-controller.d.ts +0 -21
  296. package/dist/types/src/components/wake-slider/wake-slider.d.ts +0 -15
  297. package/dist/types/src/hooks/scroll/minimize-decision.d.ts +0 -2
  298. package/dist/types/src/hooks/use-anchored-disclosure.d.ts +0 -9
  299. package/dist/types/src/hooks/use-floating-dismiss.d.ts +0 -3
  300. package/dist/types/src/hooks/viewport/types.d.ts +0 -19
  301. package/dist/types/src/hooks/viewport/viewport-metrics.d.ts +0 -3
  302. package/dist/types/src/icons/icons.d.ts +0 -616
  303. package/dist/types/src/index.d.ts +0 -73
  304. package/dist/types/src/lib/class-names.d.ts +0 -2
  305. package/dist/types/src/lib/date.d.ts +0 -50
  306. package/dist/types/src/lib/floating-layers.d.ts +0 -8
  307. package/dist/types/src/lib/range-value.d.ts +0 -4
  308. package/dist/types/src/machines/popover.machine.d.ts +0 -30
  309. package/dist/types/src/motion/transitions.d.ts +0 -170
  310. package/src/appearance/index.ts +0 -2
  311. package/src/appearance/platform.tsx +0 -102
  312. package/src/appearance/theme.tsx +0 -467
  313. package/src/components/accordion/accordion.tsx +0 -70
  314. package/src/components/ambient/ambient.tsx +0 -35
  315. package/src/components/ambient/index.ts +0 -1
  316. package/src/components/aspect-ratio/aspect-ratio.tsx +0 -27
  317. package/src/components/breadcrumb/breadcrumb.tsx +0 -73
  318. package/src/components/button/button-styles.ts +0 -49
  319. package/src/components/button/button.tsx +0 -107
  320. package/src/components/button/icon-button.tsx +0 -33
  321. package/src/components/button/pending-spinner.tsx +0 -14
  322. package/src/components/button/use-pending-indicator.ts +0 -22
  323. package/src/components/chip/chip.tsx +0 -45
  324. package/src/components/code-block/code-block.tsx +0 -48
  325. package/src/components/combo-box/combo-box.tsx +0 -13
  326. package/src/components/command/command.tsx +0 -149
  327. package/src/components/compact-date-picker/calendar-month.ts +0 -109
  328. package/src/components/compact-date-picker/compact-date-picker.tsx +0 -337
  329. package/src/components/compact-time-picker/compact-time-picker.tsx +0 -321
  330. package/src/components/compact-time-picker/time-value.ts +0 -58
  331. package/src/components/content-unavailable-view/content-unavailable-view.tsx +0 -78
  332. package/src/components/content-view/content-view.tsx +0 -215
  333. package/src/components/content-view/index.ts +0 -1
  334. package/src/components/context-menu/conceal-menu-source.ts +0 -30
  335. package/src/components/context-menu/context-menu-host.tsx +0 -459
  336. package/src/components/context-menu/context-menu-store.ts +0 -167
  337. package/src/components/context-menu/menu-navigation.ts +0 -36
  338. package/src/components/context-menu/menu-position.ts +0 -38
  339. package/src/components/context-menu/menu-reveal.ts +0 -42
  340. package/src/components/context-menu/use-context-menu.ts +0 -73
  341. package/src/components/conversation/conversation.tsx +0 -309
  342. package/src/components/conversation/index.ts +0 -1
  343. package/src/components/date-picker/date-picker.tsx +0 -106
  344. package/src/components/date-picker/date-value.ts +0 -22
  345. package/src/components/dialog/dialog-host.tsx +0 -119
  346. package/src/components/dialog/dialog-store.ts +0 -66
  347. package/src/components/dialog/dialog.tsx +0 -211
  348. package/src/components/dialog/index.ts +0 -1
  349. package/src/components/disclosure-group/disclosure-group.tsx +0 -108
  350. package/src/components/divider/divider.tsx +0 -33
  351. package/src/components/inline-disclosure/inline-disclosure.tsx +0 -53
  352. package/src/components/keyboard-shortcut/keyboard-shortcut.tsx +0 -32
  353. package/src/components/labeled-content/labeled-content.tsx +0 -84
  354. package/src/components/locale-switcher/index.ts +0 -1
  355. package/src/components/locale-switcher/locale-switcher.tsx +0 -311
  356. package/src/components/menu/menu.tsx +0 -85
  357. package/src/components/morph/index.ts +0 -2
  358. package/src/components/morph/morph.tsx +0 -258
  359. package/src/components/morph/use-morph-disclosure.ts +0 -27
  360. package/src/components/one-time-code/one-time-code.tsx +0 -234
  361. package/src/components/picker/picker-trigger.ts +0 -22
  362. package/src/components/picker/picker.tsx +0 -404
  363. package/src/components/popover/anchored-surface.tsx +0 -264
  364. package/src/components/popover/index.ts +0 -50
  365. package/src/components/popover/popover-content.tsx +0 -334
  366. package/src/components/popover/popover-fit.ts +0 -74
  367. package/src/components/popover/popover-root.tsx +0 -97
  368. package/src/components/popover/popover-trigger.tsx +0 -71
  369. package/src/components/profile-image/profile-image.tsx +0 -96
  370. package/src/components/progress-view/progress-view.tsx +0 -72
  371. package/src/components/progress-view/use-liquid-progress.ts +0 -43
  372. package/src/components/radio-group/radio-group.tsx +0 -86
  373. package/src/components/search-field/expanding-search-field.tsx +0 -197
  374. package/src/components/search-field/search-field.tsx +0 -66
  375. package/src/components/search-list/search-list.tsx +0 -276
  376. package/src/components/section/section.tsx +0 -75
  377. package/src/components/secure-field/secure-field.tsx +0 -8
  378. package/src/components/segmented-control/segmented-control.tsx +0 -157
  379. package/src/components/sheet/modal-environment.ts +0 -82
  380. package/src/components/sheet/sheet-portal.tsx +0 -62
  381. package/src/components/sheet/sheet.tsx +0 -165
  382. package/src/components/sheet/use-sheet-focus.ts +0 -109
  383. package/src/components/sidebar/sidebar.tsx +0 -102
  384. package/src/components/skeleton/skeleton.tsx +0 -38
  385. package/src/components/slider/slider.tsx +0 -134
  386. package/src/components/slosh-slider/liquid-step.ts +0 -43
  387. package/src/components/slosh-slider/slosh-slider.tsx +0 -294
  388. package/src/components/stat-tile/index.ts +0 -1
  389. package/src/components/stat-tile/stat-tile.tsx +0 -90
  390. package/src/components/status-indicator/status-indicator.tsx +0 -54
  391. package/src/components/stepper/rolling-digit.tsx +0 -91
  392. package/src/components/stepper/stepper.tsx +0 -136
  393. package/src/components/swatch-picker/swatch-picker.tsx +0 -138
  394. package/src/components/tab-bar/tab-bar.tsx +0 -182
  395. package/src/components/tab-view/tab-view.tsx +0 -155
  396. package/src/components/table/table.tsx +0 -151
  397. package/src/components/text-editor/text-editor.tsx +0 -42
  398. package/src/components/text-field/text-field.tsx +0 -200
  399. package/src/components/toast/toast-store.ts +0 -164
  400. package/src/components/toast/toaster.tsx +0 -407
  401. package/src/components/toggle/toggle.tsx +0 -320
  402. package/src/components/tooltip/tooltip-host.tsx +0 -178
  403. package/src/components/view-controller/index.ts +0 -1
  404. package/src/components/view-controller/view-controller.tsx +0 -75
  405. package/src/components/wake-slider/wake-slider.tsx +0 -260
  406. package/src/hooks/use-anchored-disclosure.ts +0 -23
  407. package/src/hooks/use-anchored-placement.ts +0 -40
  408. package/src/hooks/use-dismiss.ts +0 -44
  409. package/src/hooks/use-floating-dismiss.ts +0 -30
  410. package/src/hooks/use-media-query.ts +0 -94
  411. package/src/hooks/use-minimize-on-scroll.ts +0 -77
  412. package/src/hooks/viewport/types.ts +0 -19
  413. package/src/hooks/viewport/viewport-metrics.ts +0 -19
  414. package/src/icons/icons.tsx +0 -458
  415. package/src/index.ts +0 -107
  416. package/src/lib/anchored-placement.ts +0 -91
  417. package/src/lib/class-names.ts +0 -21
  418. package/src/lib/clipboard.ts +0 -15
  419. package/src/lib/date.ts +0 -86
  420. package/src/lib/floating-layers.ts +0 -53
  421. package/src/lib/haptics.ts +0 -23
  422. package/src/lib/language.ts +0 -16
  423. package/src/lib/range-value.ts +0 -38
  424. package/src/lib/screen-edges.ts +0 -44
  425. package/src/lib/shapes.ts +0 -59
  426. package/src/machines/popover.machine.ts +0 -51
  427. package/src/motion/transitions.ts +0 -97
  428. package/src/tokens.ts +0 -1
  429. /package/dist/{types/src/tokens.d.ts → tokens.js} +0 -0
@@ -1,337 +0,0 @@
1
- import { useAnchoredDisclosure } from "../../hooks/use-anchored-disclosure";
2
- import { AnchoredSurface } from "../popover/anchored-surface";
3
- import {
4
- type KeyboardEvent,
5
- useEffect,
6
- useId,
7
- useMemo,
8
- useRef,
9
- useState,
10
- } from "react";
11
- import { createPortal } from "react-dom";
12
- import {
13
- CalendarIcon,
14
- ChevronLeftIcon,
15
- ChevronRightIcon,
16
- } from "../../icons/icons";
17
- import { cn } from "../../lib/class-names";
18
- import { haptic } from "../../lib/haptics";
19
- import { IconButton } from "../button/icon-button";
20
- import { pickerTriggerStyle, type PickerSize } from "../picker/picker-trigger";
21
- import {
22
- addDays,
23
- addMonths,
24
- type CalendarDay,
25
- firstWeekday,
26
- formatDay,
27
- monthGrid,
28
- parseDay,
29
- withinBounds,
30
- } from "./calendar-month";
31
-
32
- export interface CompactDatePickerProps {
33
- /** `YYYY-MM-DD`, or "" when no date is chosen. */
34
- value: string;
35
- onChange: (value: string) => void;
36
- /** Names the button and the calendar for assistive technology. */
37
- label: string;
38
- locale: string;
39
- min?: string;
40
- max?: string;
41
- /** Shown when no date is chosen. */
42
- placeholder?: string;
43
- labels: {
44
- previousMonth: string;
45
- nextMonth: string;
46
- /** Offers to remove the date, for optional dates. */
47
- clear?: string;
48
- };
49
- className?: string;
50
- /** Prevents opening the date panel. @default false */
51
- disabled?: boolean;
52
- /** Trigger button density; matches Picker's sm | md | lg. @default "md" */
53
- size?: PickerSize;
54
- }
55
-
56
- const WIDTH = 308;
57
-
58
- const toDate = ({ year, month, day }: CalendarDay) =>
59
- new Date(Date.UTC(year, month - 1, day));
60
-
61
- function todayDay(): CalendarDay {
62
- const now = new Date();
63
- return {
64
- year: now.getFullYear(),
65
- month: now.getMonth() + 1,
66
- day: now.getDate(),
67
- };
68
- }
69
-
70
- /**
71
- * A date as a compact button that opens a month calendar, like SwiftUI's
72
- * compact DatePicker: for dates on a calendar, such as an event or an
73
- * invoice. For dates people know by heart, like a birthday, use DatePicker.
74
- */
75
- export function CompactDatePicker({
76
- value,
77
- onChange,
78
- label,
79
- locale,
80
- min,
81
- max,
82
- placeholder,
83
- labels,
84
- className,
85
- disabled = false,
86
- size = "md",
87
- }: CompactDatePickerProps) {
88
- const panel = useAnchoredDisclosure(disabled);
89
- const { open } = panel;
90
- const trigger = useRef<HTMLButtonElement>(null);
91
- const calendarId = useId();
92
- const chosen = parseDay(value);
93
- const shown = chosen
94
- ? new Intl.DateTimeFormat(locale, {
95
- dateStyle: "medium",
96
- timeZone: "UTC",
97
- }).format(toDate(chosen))
98
- : (placeholder ?? "");
99
-
100
- const close = (restoreFocus: boolean) => {
101
- panel.close();
102
- if (restoreFocus) trigger.current?.focus({ preventScroll: true });
103
- };
104
-
105
- return (
106
- <>
107
- <button
108
- ref={trigger}
109
- type="button"
110
- aria-label={chosen ? `${label}, ${shown}` : label}
111
- aria-haspopup="dialog"
112
- aria-expanded={open && !disabled}
113
- aria-controls={open && !disabled ? calendarId : undefined}
114
- disabled={disabled}
115
- onClick={() => panel.toggle()}
116
- className={pickerTriggerStyle(className, size)}
117
- >
118
- <span
119
- className={cn(
120
- "min-w-0 grow truncate tabular-nums",
121
- !chosen && "text-label-tertiary",
122
- )}
123
- >
124
- {shown}
125
- </span>
126
- <CalendarIcon size={16} className="text-label-tertiary shrink-0" />
127
- </button>
128
- {typeof document !== "undefined" &&
129
- createPortal(
130
- panel.mounted && trigger.current ? (
131
- <MonthCalendar
132
- open={open}
133
- onExited={panel.onExited}
134
- id={calendarId}
135
- anchor={trigger.current}
136
- label={label}
137
- locale={locale}
138
- value={value}
139
- min={min}
140
- max={max}
141
- labels={labels}
142
- onChoose={(next) => {
143
- haptic("selection");
144
- onChange(next);
145
- close(true);
146
- }}
147
- onClose={close}
148
- />
149
- ) : null,
150
- document.body,
151
- )}
152
- </>
153
- );
154
- }
155
-
156
- function MonthCalendar({
157
- open,
158
- onExited,
159
- id,
160
- anchor,
161
- label,
162
- locale,
163
- value,
164
- min,
165
- max,
166
- labels,
167
- onChoose,
168
- onClose,
169
- }: {
170
- open: boolean;
171
- onExited: () => void;
172
- id: string;
173
- anchor: HTMLElement;
174
- label: string;
175
- locale: string;
176
- value: string;
177
- min?: string;
178
- max?: string;
179
- labels: CompactDatePickerProps["labels"];
180
- onChoose: (value: string) => void;
181
- onClose: (restoreFocus: boolean) => void;
182
- }) {
183
- const root = useRef<HTMLDivElement>(null);
184
- const today = todayDay();
185
- const [focused, setFocused] = useState<CalendarDay>(
186
- () => parseDay(value) ?? today,
187
- );
188
- const firstDay = useMemo(() => firstWeekday(locale), [locale]);
189
- const days = monthGrid(focused.year, focused.month, firstDay);
190
- const title = new Intl.DateTimeFormat(locale, {
191
- month: "long",
192
- year: "numeric",
193
- timeZone: "UTC",
194
- }).format(toDate({ ...focused, day: 1 }));
195
- const weekdays = days.slice(0, 7).map((day) =>
196
- new Intl.DateTimeFormat(locale, {
197
- weekday: "narrow",
198
- timeZone: "UTC",
199
- }).format(toDate(day)),
200
- );
201
- const fullDate = new Intl.DateTimeFormat(locale, {
202
- dateStyle: "full",
203
- timeZone: "UTC",
204
- });
205
-
206
- // The focused day takes keyboard focus as it moves.
207
- useEffect(() => {
208
- root.current
209
- ?.querySelector<HTMLButtonElement>(`[data-day="${formatDay(focused)}"]`)
210
- ?.focus();
211
- }, [focused]);
212
-
213
- const move = (next: CalendarDay) => setFocused(next);
214
-
215
- const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
216
- const rtl =
217
- getComputedStyle(event.currentTarget).direction === "rtl" ? -1 : 1;
218
- const keys: Record<string, () => void> = {
219
- ArrowLeft: () => move(addDays(focused, -rtl)),
220
- ArrowRight: () => move(addDays(focused, rtl)),
221
- ArrowUp: () => move(addDays(focused, -7)),
222
- ArrowDown: () => move(addDays(focused, 7)),
223
- PageUp: () => move(addMonths(focused, event.shiftKey ? -12 : -1)),
224
- PageDown: () => move(addMonths(focused, event.shiftKey ? 12 : 1)),
225
- Escape: () => onClose(true),
226
- };
227
- const action = keys[event.key];
228
- if (!action) return;
229
- event.preventDefault();
230
- event.stopPropagation();
231
- action();
232
- };
233
-
234
- return (
235
- <AnchoredSurface
236
- open={open}
237
- onExited={onExited}
238
- ref={root}
239
- anchor={anchor}
240
- width={WIDTH}
241
- needed={360}
242
- onClose={onClose}
243
- id={id}
244
- role="dialog"
245
- aria-label={label}
246
- contentClassName="gap-2 p-3"
247
- onKeyDown={onKeyDown}
248
- >
249
- <div className="flex items-center justify-between gap-2 ps-2">
250
- <p className="text-headline font-semibold" aria-live="polite">
251
- {title}
252
- </p>
253
- <div className="flex items-center rtl:flex-row-reverse">
254
- <IconButton
255
- variant="ghost"
256
- size="icon-sm"
257
- label={labels.previousMonth}
258
- onClick={() => move(addMonths(focused, -1))}
259
- className="text-accent-text"
260
- >
261
- <ChevronLeftIcon size={20} />
262
- </IconButton>
263
- <IconButton
264
- variant="ghost"
265
- size="icon-sm"
266
- label={labels.nextMonth}
267
- onClick={() => move(addMonths(focused, 1))}
268
- className="text-accent-text"
269
- >
270
- <ChevronRightIcon size={20} />
271
- </IconButton>
272
- </div>
273
- </div>
274
- <div
275
- role="grid"
276
- aria-label={title}
277
- className="grid grid-cols-7 gap-y-0.5"
278
- >
279
- <div role="row" className="contents">
280
- {weekdays.map((weekday, index) => (
281
- <span
282
- key={days[index].toString()}
283
- role="columnheader"
284
- className="text-caption2 text-label-tertiary pb-1 text-center font-semibold"
285
- >
286
- {weekday}
287
- </span>
288
- ))}
289
- </div>
290
- {days.map((day) => {
291
- const key = formatDay(day);
292
- const selected = key === value;
293
- const isToday = key === formatDay(today);
294
- const isFocused = key === formatDay(focused);
295
- const allowed = withinBounds(key, min, max);
296
- return (
297
- <button
298
- key={key}
299
- type="button"
300
- role="gridcell"
301
- data-day={key}
302
- tabIndex={isFocused ? 0 : -1}
303
- disabled={!allowed}
304
- aria-selected={selected}
305
- aria-current={isToday ? "date" : undefined}
306
- aria-label={fullDate.format(toDate(day))}
307
- onClick={() => onChoose(key)}
308
- className={cn(
309
- "text-body mx-auto flex size-10 items-center justify-center rounded-full tabular-nums transition-colors",
310
- "focus-visible:ring-accent/70 focus-visible:ring-2 focus-visible:outline-none",
311
- selected
312
- ? "bg-accent text-on-accent font-semibold"
313
- : isToday
314
- ? "text-accent-text hover:bg-fill/80 font-semibold"
315
- : day.inMonth
316
- ? "text-label hover:bg-fill/80"
317
- : "text-label-tertiary hover:bg-fill/60",
318
- !allowed && "opacity-30",
319
- )}
320
- >
321
- {day.day}
322
- </button>
323
- );
324
- })}
325
- </div>
326
- {labels.clear && value && (
327
- <button
328
- type="button"
329
- onClick={() => onChoose("")}
330
- className="text-subheadline text-accent-text hover:bg-fill/80 self-center rounded-full px-3 py-1.5"
331
- >
332
- {labels.clear}
333
- </button>
334
- )}
335
- </AnchoredSurface>
336
- );
337
- }
@@ -1,321 +0,0 @@
1
- import { useAnchoredDisclosure } from "../../hooks/use-anchored-disclosure";
2
- import { AnchoredSurface } from "../popover/anchored-surface";
3
- import { type KeyboardEvent, useEffect, useId, useRef } from "react";
4
- import { createPortal } from "react-dom";
5
- import { ClockIcon } from "../../icons/icons";
6
- import { cn } from "../../lib/class-names";
7
- import { haptic } from "../../lib/haptics";
8
- import { pickerTriggerStyle, type PickerSize } from "../picker/picker-trigger";
9
- import {
10
- formatTime,
11
- fromTwelveHours,
12
- minuteChoices,
13
- parseTime,
14
- type TimeOfDay,
15
- toTwelveHours,
16
- usesTwelveHours,
17
- } from "./time-value";
18
-
19
- export interface CompactTimePickerProps {
20
- /** `HH:MM` on a 24 hour clock, or "" when no time is chosen. */
21
- value: string;
22
- onChange: (value: string) => void;
23
- /** Names the button and the panel for assistive technology. */
24
- label: string;
25
- locale: string;
26
- /** Minutes offered, in steps; an exact time already chosen is kept. */
27
- minuteStep?: number;
28
- /** Shown when no time is chosen. */
29
- placeholder?: string;
30
- labels: { hour: string; minute: string; period: string };
31
- className?: string;
32
- /** Prevents opening the time panel. @default false */
33
- disabled?: boolean;
34
- /** Trigger button density; matches Picker's sm | md | lg. @default "md" */
35
- size?: PickerSize;
36
- }
37
-
38
- /**
39
- * A time as a compact button that opens columns of hours and minutes,
40
- * like SwiftUI's compact DatePicker for times, on the clock the locale
41
- * reads (12 hours with AM and PM, or 24).
42
- */
43
- export function CompactTimePicker({
44
- value,
45
- onChange,
46
- label,
47
- locale,
48
- minuteStep = 5,
49
- placeholder,
50
- labels,
51
- className,
52
- disabled = false,
53
- size = "md",
54
- }: CompactTimePickerProps) {
55
- const panel = useAnchoredDisclosure(disabled);
56
- const { open } = panel;
57
- const trigger = useRef<HTMLButtonElement>(null);
58
- const panelId = useId();
59
- const chosen = parseTime(value);
60
- const shown = chosen
61
- ? new Intl.DateTimeFormat(locale, {
62
- hour: "numeric",
63
- minute: "2-digit",
64
- timeZone: "UTC",
65
- }).format(new Date(Date.UTC(2000, 0, 1, chosen.hour, chosen.minute)))
66
- : (placeholder ?? "");
67
-
68
- return (
69
- <>
70
- <button
71
- ref={trigger}
72
- type="button"
73
- aria-label={chosen ? `${label}, ${shown}` : label}
74
- aria-haspopup="dialog"
75
- aria-expanded={open && !disabled}
76
- aria-controls={open && !disabled ? panelId : undefined}
77
- disabled={disabled}
78
- onClick={() => panel.toggle()}
79
- className={pickerTriggerStyle(className, size)}
80
- >
81
- <span
82
- className={cn(
83
- "min-w-0 grow truncate tabular-nums",
84
- !chosen && "text-label-tertiary",
85
- )}
86
- >
87
- {shown}
88
- </span>
89
- <ClockIcon size={16} className="text-label-tertiary shrink-0" />
90
- </button>
91
- {typeof document !== "undefined" &&
92
- createPortal(
93
- panel.mounted && trigger.current ? (
94
- <TimeColumns
95
- open={open}
96
- onExited={panel.onExited}
97
- id={panelId}
98
- anchor={trigger.current}
99
- label={label}
100
- locale={locale}
101
- time={
102
- chosen ?? {
103
- hour: 9,
104
- minute: 0,
105
- }
106
- }
107
- minuteStep={minuteStep}
108
- labels={labels}
109
- onChange={(next) => {
110
- haptic("selection");
111
- onChange(formatTime(next));
112
- }}
113
- onClose={(restoreFocus) => {
114
- panel.close();
115
- if (restoreFocus)
116
- trigger.current?.focus({ preventScroll: true });
117
- }}
118
- />
119
- ) : null,
120
- document.body,
121
- )}
122
- </>
123
- );
124
- }
125
-
126
- interface ColumnItem {
127
- key: number;
128
- text: string;
129
- }
130
-
131
- function TimeColumns({
132
- open,
133
- onExited,
134
- id,
135
- anchor,
136
- label,
137
- locale,
138
- time,
139
- minuteStep,
140
- labels,
141
- onChange,
142
- onClose,
143
- }: {
144
- open: boolean;
145
- onExited: () => void;
146
- id: string;
147
- anchor: HTMLElement;
148
- label: string;
149
- locale: string;
150
- time: TimeOfDay;
151
- minuteStep: number;
152
- labels: CompactTimePickerProps["labels"];
153
- onChange: (time: TimeOfDay) => void;
154
- onClose: (restoreFocus: boolean) => void;
155
- }) {
156
- const root = useRef<HTMLDivElement>(null);
157
- const twelve = usesTwelveHours(locale);
158
- const number = new Intl.NumberFormat(locale, {
159
- minimumIntegerDigits: 2,
160
- });
161
- const plain = new Intl.NumberFormat(locale);
162
- const clock = toTwelveHours(time.hour);
163
-
164
- const hours: ColumnItem[] = twelve
165
- ? [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((hour) => ({
166
- key: hour,
167
- text: plain.format(hour),
168
- }))
169
- : Array.from({ length: 24 }, (_, hour) => ({
170
- key: hour,
171
- text: number.format(hour),
172
- }));
173
- const minutes = minuteChoices(minuteStep, time.minute).map((minute) => ({
174
- key: minute,
175
- text: number.format(minute),
176
- }));
177
- // The locale's own words for morning and afternoon.
178
- const periodName = (pm: boolean) =>
179
- new Intl.DateTimeFormat(locale, {
180
- hour: "numeric",
181
- hour12: true,
182
- timeZone: "UTC",
183
- })
184
- .formatToParts(new Date(Date.UTC(2000, 0, 1, pm ? 13 : 1)))
185
- .find((part) => part.type === "dayPeriod")?.value ?? (pm ? "PM" : "AM");
186
- const periods = [
187
- { key: 0, text: periodName(false) },
188
- { key: 1, text: periodName(true) },
189
- ];
190
-
191
- return (
192
- <AnchoredSurface
193
- open={open}
194
- onExited={onExited}
195
- ref={root}
196
- anchor={anchor}
197
- width={twelve ? 240 : 180}
198
- needed={280}
199
- onClose={onClose}
200
- id={id}
201
- role="dialog"
202
- aria-label={label}
203
- contentClassName="flex-row gap-1 overflow-hidden p-2"
204
- onKeyDown={(event) => {
205
- if (event.key !== "Escape") return;
206
- event.preventDefault();
207
- event.stopPropagation();
208
- onClose(true);
209
- }}
210
- >
211
- <Column
212
- label={labels.hour}
213
- items={hours}
214
- selected={twelve ? clock.hour : time.hour}
215
- autoFocus
216
- onSelect={(hour) =>
217
- onChange({
218
- ...time,
219
- hour: twelve ? fromTwelveHours(hour, clock.pm) : hour,
220
- })
221
- }
222
- />
223
- <Column
224
- label={labels.minute}
225
- items={minutes}
226
- selected={time.minute}
227
- onSelect={(minute) => onChange({ ...time, minute })}
228
- />
229
- {twelve && (
230
- <Column
231
- label={labels.period}
232
- items={periods}
233
- selected={clock.pm ? 1 : 0}
234
- onSelect={(period) =>
235
- onChange({
236
- ...time,
237
- hour: fromTwelveHours(clock.hour, period === 1),
238
- })
239
- }
240
- />
241
- )}
242
- </AnchoredSurface>
243
- );
244
- }
245
-
246
- /** One scrolling column of choices; Up and Down move through it. */
247
- function Column({
248
- label,
249
- items,
250
- selected,
251
- autoFocus = false,
252
- onSelect,
253
- }: {
254
- label: string;
255
- items: ColumnItem[];
256
- selected: number;
257
- autoFocus?: boolean;
258
- onSelect: (key: number) => void;
259
- }) {
260
- const list = useRef<HTMLDivElement>(null);
261
-
262
- // The chosen item starts in the middle of the column, then follows changes.
263
- useEffect(() => {
264
- const element = list.current?.querySelector<HTMLElement>(
265
- `[data-key="${selected}"]`,
266
- );
267
- element?.scrollIntoView({ block: "center" });
268
- if (autoFocus && list.current?.contains(document.activeElement) === false)
269
- element?.focus();
270
- }, [selected, autoFocus]);
271
-
272
- const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
273
- const step =
274
- event.key === "ArrowDown" ? 1 : event.key === "ArrowUp" ? -1 : 0;
275
- if (!step) return;
276
- event.preventDefault();
277
- const index = items.findIndex((item) => item.key === selected);
278
- const next = items[(index + step + items.length) % items.length];
279
- if (!next) return;
280
- onSelect(next.key);
281
- requestAnimationFrame(() =>
282
- list.current
283
- ?.querySelector<HTMLElement>(`[data-key="${next.key}"]`)
284
- ?.focus(),
285
- );
286
- };
287
-
288
- return (
289
- <div
290
- ref={list}
291
- role="listbox"
292
- aria-label={label}
293
- onKeyDown={onKeyDown}
294
- className="flex max-h-56 flex-1 snap-y snap-mandatory [scrollbar-width:none] flex-col overflow-y-auto overscroll-contain py-[5.25rem]"
295
- >
296
- {items.map((item) => {
297
- const isSelected = item.key === selected;
298
- return (
299
- <button
300
- key={item.key}
301
- type="button"
302
- role="option"
303
- data-key={item.key}
304
- aria-selected={isSelected}
305
- tabIndex={isSelected ? 0 : -1}
306
- onClick={() => onSelect(item.key)}
307
- className={cn(
308
- "text-title3 flex h-11 shrink-0 snap-center items-center justify-center rounded-xl tabular-nums transition-colors",
309
- "focus-visible:ring-accent/70 focus-visible:ring-2 focus-visible:outline-none",
310
- isSelected
311
- ? "bg-fill text-label font-semibold"
312
- : "text-label-secondary hover:bg-fill/60",
313
- )}
314
- >
315
- {item.text}
316
- </button>
317
- );
318
- })}
319
- </div>
320
- );
321
- }
@@ -1,58 +0,0 @@
1
- /** A time of day on a 24 hour clock. */
2
- export interface TimeOfDay {
3
- hour: number;
4
- minute: number;
5
- }
6
-
7
- /** Reads `HH:MM` (24 hour); null for anything else. */
8
- export function parseTime(value: string): TimeOfDay | null {
9
- const match = /^(\d{2}):(\d{2})$/.exec(value);
10
- if (!match) return null;
11
- const hour = Number(match[1]);
12
- const minute = Number(match[2]);
13
- return hour < 24 && minute < 60 ? { hour, minute } : null;
14
- }
15
-
16
- export function formatTime({ hour, minute }: TimeOfDay): string {
17
- return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
18
- }
19
-
20
- /** Whether people where `locale` is used read time on a 12 hour clock. */
21
- export function usesTwelveHours(locale: string): boolean {
22
- try {
23
- const cycle = new Intl.DateTimeFormat(locale, {
24
- hour: "numeric",
25
- }).resolvedOptions().hourCycle;
26
- return cycle === "h11" || cycle === "h12";
27
- } catch {
28
- return false;
29
- }
30
- }
31
-
32
- /** The hour as shown on a 12 hour clock (12, 1 to 11) and whether it's after noon. */
33
- export function toTwelveHours(hour: number): {
34
- hour: number;
35
- pm: boolean;
36
- } {
37
- return {
38
- hour: hour % 12 === 0 ? 12 : hour % 12,
39
- pm: hour >= 12,
40
- };
41
- }
42
-
43
- export function fromTwelveHours(hour: number, pm: boolean): number {
44
- return (hour % 12) + (pm ? 12 : 0);
45
- }
46
-
47
- /** Minutes offered in steps of `step`, keeping `current` when it falls between them. */
48
- export function minuteChoices(step: number, current?: number): number[] {
49
- const choices = Array.from(
50
- { length: Math.ceil(60 / step) },
51
- (_, index) => index * step,
52
- );
53
- if (current !== undefined && !choices.includes(current)) {
54
- choices.push(current);
55
- choices.sort((a, b) => a - b);
56
- }
57
- return choices;
58
- }