@passui/react 0.1.47 → 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 (427) 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 -38
  259. package/dist/types/src/components/popover/popover-root.d.ts +0 -22
  260. package/dist/types/src/components/popover/popover-trigger.d.ts +0 -23
  261. package/dist/types/src/components/profile-image/profile-image.d.ts +0 -9
  262. package/dist/types/src/components/progress-view/progress-view.d.ts +0 -13
  263. package/dist/types/src/components/progress-view/use-liquid-progress.d.ts +0 -3
  264. package/dist/types/src/components/radio-group/radio-group.d.ts +0 -20
  265. package/dist/types/src/components/search-field/expanding-search-field.d.ts +0 -5
  266. package/dist/types/src/components/search-field/search-field.d.ts +0 -9
  267. package/dist/types/src/components/search-list/search-list.d.ts +0 -22
  268. package/dist/types/src/components/section/section.d.ts +0 -18
  269. package/dist/types/src/components/secure-field/secure-field.d.ts +0 -4
  270. package/dist/types/src/components/segmented-control/segmented-control.d.ts +0 -25
  271. package/dist/types/src/components/sheet/modal-environment.d.ts +0 -2
  272. package/dist/types/src/components/sheet/sheet-portal.d.ts +0 -5
  273. package/dist/types/src/components/sheet/sheet.d.ts +0 -26
  274. package/dist/types/src/components/sheet/use-sheet-focus.d.ts +0 -3
  275. package/dist/types/src/components/sidebar/sidebar.d.ts +0 -24
  276. package/dist/types/src/components/skeleton/skeleton.d.ts +0 -9
  277. package/dist/types/src/components/slider/slider.d.ts +0 -17
  278. package/dist/types/src/components/slosh-slider/liquid-step.d.ts +0 -6
  279. package/dist/types/src/components/slosh-slider/slosh-slider.d.ts +0 -21
  280. package/dist/types/src/components/stat-tile/index.d.ts +0 -1
  281. package/dist/types/src/components/stat-tile/stat-tile.d.ts +0 -20
  282. package/dist/types/src/components/status-indicator/status-indicator.d.ts +0 -17
  283. package/dist/types/src/components/stepper/rolling-digit.d.ts +0 -11
  284. package/dist/types/src/components/stepper/stepper.d.ts +0 -22
  285. package/dist/types/src/components/swatch-picker/swatch-picker.d.ts +0 -22
  286. package/dist/types/src/components/tab-bar/tab-bar.d.ts +0 -43
  287. package/dist/types/src/components/tab-view/tab-view.d.ts +0 -27
  288. package/dist/types/src/components/text-editor/text-editor.d.ts +0 -9
  289. package/dist/types/src/components/text-field/text-field.d.ts +0 -33
  290. package/dist/types/src/components/toast/toast-store.d.ts +0 -52
  291. package/dist/types/src/components/toggle/toggle.d.ts +0 -22
  292. package/dist/types/src/components/tooltip/tooltip-host.d.ts +0 -7
  293. package/dist/types/src/components/view-controller/index.d.ts +0 -1
  294. package/dist/types/src/components/view-controller/view-controller.d.ts +0 -21
  295. package/dist/types/src/components/wake-slider/wake-slider.d.ts +0 -15
  296. package/dist/types/src/hooks/scroll/minimize-decision.d.ts +0 -2
  297. package/dist/types/src/hooks/use-anchored-disclosure.d.ts +0 -9
  298. package/dist/types/src/hooks/use-floating-dismiss.d.ts +0 -3
  299. package/dist/types/src/hooks/viewport/types.d.ts +0 -19
  300. package/dist/types/src/hooks/viewport/viewport-metrics.d.ts +0 -3
  301. package/dist/types/src/icons/icons.d.ts +0 -616
  302. package/dist/types/src/index.d.ts +0 -73
  303. package/dist/types/src/lib/class-names.d.ts +0 -2
  304. package/dist/types/src/lib/date.d.ts +0 -50
  305. package/dist/types/src/lib/floating-layers.d.ts +0 -8
  306. package/dist/types/src/lib/range-value.d.ts +0 -4
  307. package/dist/types/src/machines/popover.machine.d.ts +0 -30
  308. package/dist/types/src/motion/transitions.d.ts +0 -170
  309. package/src/appearance/index.ts +0 -2
  310. package/src/appearance/platform.tsx +0 -102
  311. package/src/appearance/theme.tsx +0 -467
  312. package/src/components/accordion/accordion.tsx +0 -70
  313. package/src/components/ambient/ambient.tsx +0 -35
  314. package/src/components/ambient/index.ts +0 -1
  315. package/src/components/aspect-ratio/aspect-ratio.tsx +0 -27
  316. package/src/components/breadcrumb/breadcrumb.tsx +0 -73
  317. package/src/components/button/button-styles.ts +0 -49
  318. package/src/components/button/button.tsx +0 -107
  319. package/src/components/button/icon-button.tsx +0 -33
  320. package/src/components/button/pending-spinner.tsx +0 -14
  321. package/src/components/button/use-pending-indicator.ts +0 -22
  322. package/src/components/chip/chip.tsx +0 -45
  323. package/src/components/code-block/code-block.tsx +0 -48
  324. package/src/components/combo-box/combo-box.tsx +0 -13
  325. package/src/components/command/command.tsx +0 -149
  326. package/src/components/compact-date-picker/calendar-month.ts +0 -109
  327. package/src/components/compact-date-picker/compact-date-picker.tsx +0 -337
  328. package/src/components/compact-time-picker/compact-time-picker.tsx +0 -321
  329. package/src/components/compact-time-picker/time-value.ts +0 -58
  330. package/src/components/content-unavailable-view/content-unavailable-view.tsx +0 -78
  331. package/src/components/content-view/content-view.tsx +0 -215
  332. package/src/components/content-view/index.ts +0 -1
  333. package/src/components/context-menu/conceal-menu-source.ts +0 -30
  334. package/src/components/context-menu/context-menu-host.tsx +0 -459
  335. package/src/components/context-menu/context-menu-store.ts +0 -167
  336. package/src/components/context-menu/menu-navigation.ts +0 -36
  337. package/src/components/context-menu/menu-position.ts +0 -38
  338. package/src/components/context-menu/menu-reveal.ts +0 -42
  339. package/src/components/context-menu/use-context-menu.ts +0 -73
  340. package/src/components/conversation/conversation.tsx +0 -309
  341. package/src/components/conversation/index.ts +0 -1
  342. package/src/components/date-picker/date-picker.tsx +0 -106
  343. package/src/components/date-picker/date-value.ts +0 -22
  344. package/src/components/dialog/dialog-host.tsx +0 -119
  345. package/src/components/dialog/dialog-store.ts +0 -66
  346. package/src/components/dialog/dialog.tsx +0 -211
  347. package/src/components/dialog/index.ts +0 -1
  348. package/src/components/disclosure-group/disclosure-group.tsx +0 -108
  349. package/src/components/divider/divider.tsx +0 -33
  350. package/src/components/inline-disclosure/inline-disclosure.tsx +0 -53
  351. package/src/components/keyboard-shortcut/keyboard-shortcut.tsx +0 -32
  352. package/src/components/labeled-content/labeled-content.tsx +0 -84
  353. package/src/components/locale-switcher/index.ts +0 -1
  354. package/src/components/locale-switcher/locale-switcher.tsx +0 -310
  355. package/src/components/menu/menu.tsx +0 -85
  356. package/src/components/morph/index.ts +0 -2
  357. package/src/components/morph/morph.tsx +0 -258
  358. package/src/components/morph/use-morph-disclosure.ts +0 -27
  359. package/src/components/one-time-code/one-time-code.tsx +0 -234
  360. package/src/components/picker/picker-trigger.ts +0 -22
  361. package/src/components/picker/picker.tsx +0 -404
  362. package/src/components/popover/anchored-surface.tsx +0 -264
  363. package/src/components/popover/index.ts +0 -50
  364. package/src/components/popover/popover-content.tsx +0 -374
  365. package/src/components/popover/popover-root.tsx +0 -97
  366. package/src/components/popover/popover-trigger.tsx +0 -71
  367. package/src/components/profile-image/profile-image.tsx +0 -96
  368. package/src/components/progress-view/progress-view.tsx +0 -72
  369. package/src/components/progress-view/use-liquid-progress.ts +0 -43
  370. package/src/components/radio-group/radio-group.tsx +0 -86
  371. package/src/components/search-field/expanding-search-field.tsx +0 -197
  372. package/src/components/search-field/search-field.tsx +0 -66
  373. package/src/components/search-list/search-list.tsx +0 -276
  374. package/src/components/section/section.tsx +0 -75
  375. package/src/components/secure-field/secure-field.tsx +0 -8
  376. package/src/components/segmented-control/segmented-control.tsx +0 -157
  377. package/src/components/sheet/modal-environment.ts +0 -82
  378. package/src/components/sheet/sheet-portal.tsx +0 -62
  379. package/src/components/sheet/sheet.tsx +0 -165
  380. package/src/components/sheet/use-sheet-focus.ts +0 -109
  381. package/src/components/sidebar/sidebar.tsx +0 -102
  382. package/src/components/skeleton/skeleton.tsx +0 -38
  383. package/src/components/slider/slider.tsx +0 -134
  384. package/src/components/slosh-slider/liquid-step.ts +0 -43
  385. package/src/components/slosh-slider/slosh-slider.tsx +0 -294
  386. package/src/components/stat-tile/index.ts +0 -1
  387. package/src/components/stat-tile/stat-tile.tsx +0 -90
  388. package/src/components/status-indicator/status-indicator.tsx +0 -54
  389. package/src/components/stepper/rolling-digit.tsx +0 -91
  390. package/src/components/stepper/stepper.tsx +0 -136
  391. package/src/components/swatch-picker/swatch-picker.tsx +0 -138
  392. package/src/components/tab-bar/tab-bar.tsx +0 -182
  393. package/src/components/tab-view/tab-view.tsx +0 -155
  394. package/src/components/table/table.tsx +0 -151
  395. package/src/components/text-editor/text-editor.tsx +0 -42
  396. package/src/components/text-field/text-field.tsx +0 -200
  397. package/src/components/toast/toast-store.ts +0 -164
  398. package/src/components/toast/toaster.tsx +0 -407
  399. package/src/components/toggle/toggle.tsx +0 -320
  400. package/src/components/tooltip/tooltip-host.tsx +0 -178
  401. package/src/components/view-controller/index.ts +0 -1
  402. package/src/components/view-controller/view-controller.tsx +0 -75
  403. package/src/components/wake-slider/wake-slider.tsx +0 -260
  404. package/src/hooks/use-anchored-disclosure.ts +0 -23
  405. package/src/hooks/use-anchored-placement.ts +0 -40
  406. package/src/hooks/use-dismiss.ts +0 -44
  407. package/src/hooks/use-floating-dismiss.ts +0 -30
  408. package/src/hooks/use-media-query.ts +0 -94
  409. package/src/hooks/use-minimize-on-scroll.ts +0 -77
  410. package/src/hooks/viewport/types.ts +0 -19
  411. package/src/hooks/viewport/viewport-metrics.ts +0 -19
  412. package/src/icons/icons.tsx +0 -458
  413. package/src/index.ts +0 -107
  414. package/src/lib/anchored-placement.ts +0 -91
  415. package/src/lib/class-names.ts +0 -21
  416. package/src/lib/clipboard.ts +0 -15
  417. package/src/lib/date.ts +0 -86
  418. package/src/lib/floating-layers.ts +0 -53
  419. package/src/lib/haptics.ts +0 -23
  420. package/src/lib/language.ts +0 -16
  421. package/src/lib/range-value.ts +0 -38
  422. package/src/lib/screen-edges.ts +0 -44
  423. package/src/lib/shapes.ts +0 -59
  424. package/src/machines/popover.machine.ts +0 -51
  425. package/src/motion/transitions.ts +0 -97
  426. package/src/tokens.ts +0 -1
  427. /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
- }