@passui/react 0.1.16 → 0.1.19

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 (366) hide show
  1. package/README.md +102 -1
  2. package/dist/types/src/appearance/index.d.ts +2 -0
  3. package/dist/types/src/appearance/platform.d.ts +9 -0
  4. package/dist/types/src/appearance/theme.d.ts +71 -0
  5. package/dist/types/src/components/ambient/ambient.d.ts +12 -0
  6. package/dist/types/src/components/ambient/index.d.ts +1 -0
  7. package/dist/types/src/components/button/button-styles.d.ts +12 -0
  8. package/dist/types/src/components/button/button.d.ts +30 -0
  9. package/dist/types/src/components/button/icon-button.d.ts +10 -0
  10. package/dist/types/src/components/button/pending-spinner.d.ts +5 -0
  11. package/dist/types/src/components/button/use-pending-indicator.d.ts +2 -0
  12. package/dist/types/src/components/chip/chip.d.ts +7 -0
  13. package/dist/types/src/components/compact-date-picker/calendar-month.d.ts +25 -0
  14. package/dist/types/src/components/compact-date-picker/compact-date-picker.d.ts +27 -0
  15. package/dist/types/src/components/compact-time-picker/compact-time-picker.d.ts +26 -0
  16. package/dist/types/src/components/compact-time-picker/time-value.d.ts +18 -0
  17. package/dist/types/src/components/content-view/content-view.d.ts +48 -0
  18. package/dist/types/src/components/content-view/index.d.ts +1 -0
  19. package/dist/types/src/components/context-menu/conceal-menu-source.d.ts +2 -0
  20. package/dist/types/src/components/context-menu/context-menu-host.d.ts +2 -0
  21. package/dist/types/src/components/context-menu/context-menu-store.d.ts +57 -0
  22. package/dist/types/src/components/context-menu/menu-navigation.d.ts +6 -0
  23. package/dist/types/src/components/context-menu/menu-position.d.ts +21 -0
  24. package/dist/types/src/components/context-menu/menu-reveal.d.ts +22 -0
  25. package/dist/types/src/components/context-menu/use-context-menu.d.ts +14 -0
  26. package/dist/types/src/components/conversation/conversation.d.ts +43 -0
  27. package/dist/types/src/components/conversation/index.d.ts +1 -0
  28. package/dist/types/src/components/date-picker/date-picker.d.ts +16 -0
  29. package/dist/types/src/components/date-picker/date-value.d.ts +2 -0
  30. package/dist/types/src/components/dialog/dialog-host.d.ts +6 -0
  31. package/dist/types/src/components/dialog/dialog-store.d.ts +21 -0
  32. package/dist/types/src/components/dialog/dialog.d.ts +30 -0
  33. package/dist/types/src/components/dialog/index.d.ts +1 -0
  34. package/dist/types/src/components/disclosure-group/disclosure-group.d.ts +13 -0
  35. package/dist/types/src/components/divider/divider.d.ts +9 -0
  36. package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +15 -0
  37. package/dist/types/src/components/labeled-content/labeled-content.d.ts +19 -0
  38. package/dist/types/src/components/locale-switcher/index.d.ts +1 -0
  39. package/dist/types/src/components/locale-switcher/locale-switcher.d.ts +10 -0
  40. package/dist/types/src/components/menu/menu.d.ts +16 -0
  41. package/dist/types/src/components/picker/picker-trigger.d.ts +2 -0
  42. package/dist/types/src/components/picker/picker.d.ts +37 -0
  43. package/dist/types/src/components/popover/popover-fit.d.ts +21 -0
  44. package/dist/types/src/components/popover/popover.d.ts +14 -0
  45. package/dist/types/src/components/profile-image/profile-image.d.ts +4 -0
  46. package/dist/types/src/components/progress-view/progress-view.d.ts +13 -0
  47. package/dist/types/src/components/search-field/search-field.d.ts +2 -0
  48. package/dist/types/src/components/search-list/search-list.d.ts +19 -0
  49. package/dist/types/src/components/section/section.d.ts +15 -0
  50. package/dist/types/src/components/secure-field/secure-field.d.ts +4 -0
  51. package/dist/types/src/components/segmented-control/segmented-control.d.ts +20 -0
  52. package/dist/types/src/components/sheet/modal-environment.d.ts +2 -0
  53. package/dist/types/src/components/sheet/sheet-portal.d.ts +5 -0
  54. package/dist/types/src/components/sheet/sheet.d.ts +21 -0
  55. package/dist/types/src/components/sheet/use-sheet-focus.d.ts +3 -0
  56. package/dist/types/src/components/sidebar/sidebar.d.ts +18 -0
  57. package/dist/types/src/components/slider/slider.d.ts +14 -0
  58. package/dist/types/src/components/stat-tile/index.d.ts +1 -0
  59. package/dist/types/src/components/stat-tile/stat-tile.d.ts +15 -0
  60. package/dist/types/src/components/status-indicator/status-indicator.d.ts +14 -0
  61. package/dist/types/src/components/stepper/stepper.d.ts +19 -0
  62. package/dist/types/src/components/swatch-picker/swatch-picker.d.ts +17 -0
  63. package/dist/types/src/components/tab-bar/tab-bar.d.ts +40 -0
  64. package/dist/types/src/components/tab-view/tab-view.d.ts +24 -0
  65. package/dist/types/src/components/table/table.d.ts +10 -0
  66. package/dist/types/src/components/text-editor/text-editor.d.ts +2 -0
  67. package/dist/types/src/components/text-field/text-field.d.ts +18 -0
  68. package/dist/types/src/components/toast/toast-store.d.ts +47 -0
  69. package/dist/types/src/components/toast/toaster.d.ts +10 -0
  70. package/dist/types/src/components/toggle/toggle.d.ts +17 -0
  71. package/dist/types/src/components/tooltip/tooltip-host.d.ts +6 -0
  72. package/dist/types/src/components/view-controller/index.d.ts +1 -0
  73. package/dist/types/src/components/view-controller/view-controller.d.ts +21 -0
  74. package/dist/types/src/hooks/scroll/minimize-decision.d.ts +2 -0
  75. package/dist/types/src/hooks/use-anchored-placement.d.ts +7 -0
  76. package/dist/types/src/hooks/use-dismiss.d.ts +9 -0
  77. package/dist/types/src/hooks/use-floating-dismiss.d.ts +3 -0
  78. package/dist/types/src/hooks/use-media-query.d.ts +21 -0
  79. package/dist/types/src/hooks/use-minimize-on-scroll.d.ts +6 -0
  80. package/dist/types/src/hooks/use-visual-viewport.d.ts +4 -0
  81. package/dist/types/src/hooks/viewport/types.d.ts +19 -0
  82. package/dist/types/src/hooks/viewport/viewport-metrics.d.ts +3 -0
  83. package/dist/types/src/icons/icons.d.ts +612 -0
  84. package/dist/types/src/index.d.ts +58 -0
  85. package/dist/types/src/lib/anchored-placement.d.ts +39 -0
  86. package/dist/types/src/lib/class-names.d.ts +2 -0
  87. package/dist/types/src/lib/clipboard.d.ts +6 -0
  88. package/dist/types/src/lib/date.d.ts +50 -0
  89. package/dist/types/src/lib/floating-layers.d.ts +8 -0
  90. package/dist/types/src/lib/haptics.d.ts +8 -0
  91. package/dist/types/src/lib/language.d.ts +4 -0
  92. package/dist/types/src/lib/range-value.d.ts +4 -0
  93. package/dist/types/src/lib/screen-edges.d.ts +12 -0
  94. package/dist/types/src/lib/shapes.d.ts +17 -0
  95. package/dist/types/src/motion/transitions.d.ts +97 -0
  96. package/dist/types/src/tokens.d.ts +1 -0
  97. package/package.json +192 -40
  98. package/src/appearance/platform.tsx +10 -47
  99. package/src/appearance/theme.tsx +42 -142
  100. package/src/components/ambient/ambient.tsx +2 -10
  101. package/src/components/button/button-styles.ts +13 -31
  102. package/src/components/button/button.tsx +19 -14
  103. package/src/components/button/icon-button.tsx +14 -56
  104. package/src/components/button/use-pending-indicator.ts +2 -7
  105. package/src/components/chip/chip.tsx +8 -13
  106. package/src/components/compact-date-picker/calendar-month.ts +13 -57
  107. package/src/components/compact-date-picker/compact-date-picker.tsx +44 -123
  108. package/src/components/compact-time-picker/compact-time-picker.tsx +46 -130
  109. package/src/components/compact-time-picker/time-value.ts +4 -16
  110. package/src/components/content-view/content-view.tsx +13 -56
  111. package/src/components/context-menu/conceal-menu-source.ts +1 -4
  112. package/src/components/context-menu/context-menu-host.tsx +125 -195
  113. package/src/components/context-menu/context-menu-store.ts +3 -11
  114. package/src/components/context-menu/menu-navigation.ts +29 -0
  115. package/src/components/context-menu/menu-position.ts +6 -27
  116. package/src/components/context-menu/menu-reveal.ts +13 -54
  117. package/src/components/context-menu/use-context-menu.ts +6 -30
  118. package/src/components/conversation/conversation.tsx +26 -72
  119. package/src/components/date-picker/date-picker.tsx +8 -37
  120. package/src/components/date-picker/date-value.ts +5 -30
  121. package/src/components/dialog/dialog-host.tsx +31 -76
  122. package/src/components/dialog/dialog-store.ts +1 -3
  123. package/src/components/dialog/dialog.tsx +23 -80
  124. package/src/components/disclosure-group/disclosure-group.tsx +70 -0
  125. package/src/components/divider/divider.tsx +31 -0
  126. package/src/components/inline-disclosure/inline-disclosure.tsx +49 -0
  127. package/src/components/labeled-content/labeled-content.tsx +24 -18
  128. package/src/components/locale-switcher/locale-switcher.tsx +20 -70
  129. package/src/components/menu/menu.tsx +68 -0
  130. package/src/components/picker/picker-trigger.ts +10 -0
  131. package/src/components/picker/picker.tsx +72 -203
  132. package/src/components/popover/popover-fit.ts +69 -0
  133. package/src/components/popover/popover.tsx +94 -77
  134. package/src/components/profile-image/profile-image.tsx +6 -28
  135. package/src/components/progress-view/progress-view.tsx +65 -0
  136. package/src/components/search-field/search-field.tsx +27 -25
  137. package/src/components/search-list/search-list.tsx +43 -69
  138. package/src/components/section/section.tsx +18 -17
  139. package/src/components/secure-field/secure-field.tsx +5 -7
  140. package/src/components/segmented-control/segmented-control.tsx +20 -29
  141. package/src/components/sheet/modal-environment.ts +16 -54
  142. package/src/components/sheet/sheet-portal.tsx +10 -42
  143. package/src/components/sheet/sheet.tsx +17 -25
  144. package/src/components/sheet/use-sheet-focus.ts +15 -51
  145. package/src/components/sidebar/sidebar.tsx +27 -30
  146. package/src/components/slider/slider.tsx +76 -0
  147. package/src/components/stat-tile/stat-tile.tsx +9 -30
  148. package/src/components/status-indicator/status-indicator.tsx +12 -19
  149. package/src/components/stepper/stepper.tsx +80 -0
  150. package/src/components/swatch-picker/swatch-picker.tsx +19 -15
  151. package/src/components/tab-bar/tab-bar.tsx +59 -59
  152. package/src/components/tab-view/tab-view.tsx +52 -57
  153. package/src/components/table/table.tsx +14 -62
  154. package/src/components/text-editor/text-editor.tsx +2 -12
  155. package/src/components/text-field/text-field.tsx +11 -40
  156. package/src/components/toast/toast-store.ts +9 -30
  157. package/src/components/toast/toaster.tsx +90 -104
  158. package/src/components/toggle/toggle.tsx +28 -24
  159. package/src/components/tooltip/tooltip-host.tsx +71 -69
  160. package/src/components/view-controller/view-controller.tsx +4 -21
  161. package/src/hooks/scroll/minimize-decision.ts +1 -5
  162. package/src/hooks/use-anchored-placement.ts +4 -14
  163. package/src/hooks/use-dismiss.ts +5 -23
  164. package/src/hooks/use-floating-dismiss.ts +28 -0
  165. package/src/hooks/use-media-query.ts +12 -31
  166. package/src/hooks/use-minimize-on-scroll.ts +10 -34
  167. package/src/hooks/use-visual-viewport.ts +5 -14
  168. package/src/hooks/viewport/viewport-metrics.ts +4 -16
  169. package/src/icons/icons.tsx +167 -121
  170. package/src/index.ts +9 -1
  171. package/src/lib/anchored-placement.ts +5 -15
  172. package/src/lib/class-names.ts +1 -2
  173. package/src/lib/clipboard.ts +14 -0
  174. package/src/lib/date.ts +4 -15
  175. package/src/lib/floating-layers.ts +18 -8
  176. package/src/lib/haptics.ts +1 -3
  177. package/src/lib/language.ts +2 -7
  178. package/src/lib/range-value.ts +32 -0
  179. package/src/lib/screen-edges.ts +2 -6
  180. package/src/lib/shapes.ts +5 -20
  181. package/src/motion/transitions.ts +18 -12
  182. package/src/components/ambient/ambient.docs.tsx +0 -68
  183. package/src/components/ambient/examples/ambient-images.tsx +0 -30
  184. package/src/components/ambient/examples/ambient-now-playing.tsx +0 -55
  185. package/src/components/ambient/examples/ambient-showcase.tsx +0 -33
  186. package/src/components/ambient/examples/ambient-usage.tsx +0 -19
  187. package/src/components/button/button.docs.tsx +0 -116
  188. package/src/components/button/examples/button-disabled.tsx +0 -19
  189. package/src/components/button/examples/button-icon.tsx +0 -39
  190. package/src/components/button/examples/button-link.tsx +0 -12
  191. package/src/components/button/examples/button-pending.tsx +0 -27
  192. package/src/components/button/examples/button-showcase.tsx +0 -115
  193. package/src/components/button/examples/button-sizes.tsx +0 -12
  194. package/src/components/button/examples/button-usage.tsx +0 -12
  195. package/src/components/button/examples/button-variants.tsx +0 -15
  196. package/src/components/button/examples/button-with-icon.tsx +0 -32
  197. package/src/components/button/examples/icon-button-player.tsx +0 -38
  198. package/src/components/button/examples/icon-button-showcase.tsx +0 -83
  199. package/src/components/button/examples/icon-button-usage.tsx +0 -11
  200. package/src/components/button/examples/icon-button-variants.tsx +0 -39
  201. package/src/components/button/icon-button.docs.tsx +0 -68
  202. package/src/components/chip/chip.docs.tsx +0 -37
  203. package/src/components/chip/examples/chip-in-rows.tsx +0 -19
  204. package/src/components/chip/examples/chip-showcase.tsx +0 -51
  205. package/src/components/chip/examples/chip-tones.tsx +0 -13
  206. package/src/components/chip/examples/chip-usage.tsx +0 -5
  207. package/src/components/compact-date-picker/compact-date-picker.docs.tsx +0 -81
  208. package/src/components/compact-date-picker/examples/compact-date-picker-showcase.tsx +0 -35
  209. package/src/components/compact-date-picker/examples/compact-date-picker-usage.tsx +0 -22
  210. package/src/components/compact-time-picker/compact-time-picker.docs.tsx +0 -80
  211. package/src/components/compact-time-picker/examples/compact-time-picker-showcase.tsx +0 -31
  212. package/src/components/compact-time-picker/examples/compact-time-picker-usage.tsx +0 -21
  213. package/src/components/content-view/content-view.docs.tsx +0 -61
  214. package/src/components/content-view/examples/content-view-header-action.tsx +0 -33
  215. package/src/components/content-view/examples/content-view-showcase.tsx +0 -65
  216. package/src/components/content-view/examples/content-view-stats.tsx +0 -35
  217. package/src/components/content-view/examples/content-view-usage.tsx +0 -14
  218. package/src/components/context-menu/context-menu.docs.tsx +0 -92
  219. package/src/components/context-menu/examples/context-menu-checked.tsx +0 -37
  220. package/src/components/context-menu/examples/context-menu-list.tsx +0 -85
  221. package/src/components/context-menu/examples/context-menu-showcase.tsx +0 -56
  222. package/src/components/context-menu/examples/context-menu-toolbar.tsx +0 -63
  223. package/src/components/context-menu/examples/context-menu-usage.tsx +0 -24
  224. package/src/components/conversation/conversation.docs.tsx +0 -88
  225. package/src/components/conversation/examples/conversation-composer.tsx +0 -36
  226. package/src/components/conversation/examples/conversation-days.tsx +0 -48
  227. package/src/components/conversation/examples/conversation-showcase.tsx +0 -71
  228. package/src/components/conversation/examples/conversation-usage.tsx +0 -28
  229. package/src/components/date-picker/date-picker.docs.tsx +0 -88
  230. package/src/components/date-picker/examples/date-picker-locales.tsx +0 -41
  231. package/src/components/date-picker/examples/date-picker-past-only.tsx +0 -29
  232. package/src/components/date-picker/examples/date-picker-showcase.tsx +0 -49
  233. package/src/components/date-picker/examples/date-picker-usage.tsx +0 -22
  234. package/src/components/dialog/dialog.docs.tsx +0 -114
  235. package/src/components/dialog/examples/dialog-confirm.tsx +0 -24
  236. package/src/components/dialog/examples/dialog-form.tsx +0 -46
  237. package/src/components/dialog/examples/dialog-inline.tsx +0 -48
  238. package/src/components/dialog/examples/dialog-showcase.tsx +0 -53
  239. package/src/components/dialog/examples/dialog-usage.tsx +0 -31
  240. package/src/components/labeled-content/examples/labeled-content-descriptions.tsx +0 -37
  241. package/src/components/labeled-content/examples/labeled-content-showcase.tsx +0 -54
  242. package/src/components/labeled-content/examples/labeled-content-usage.tsx +0 -22
  243. package/src/components/labeled-content/examples/labeled-content-values.tsx +0 -26
  244. package/src/components/labeled-content/examples/labeled-content-wide.tsx +0 -46
  245. package/src/components/labeled-content/labeled-content.docs.tsx +0 -69
  246. package/src/components/locale-switcher/examples/locale-switcher-native-names.tsx +0 -30
  247. package/src/components/locale-switcher/examples/locale-switcher-showcase.tsx +0 -46
  248. package/src/components/locale-switcher/examples/locale-switcher-translated-page.tsx +0 -35
  249. package/src/components/locale-switcher/examples/locale-switcher-usage.tsx +0 -20
  250. package/src/components/locale-switcher/locale-switcher.docs.tsx +0 -91
  251. package/src/components/picker/examples/picker-details.tsx +0 -44
  252. package/src/components/picker/examples/picker-searchable.tsx +0 -48
  253. package/src/components/picker/examples/picker-showcase.tsx +0 -66
  254. package/src/components/picker/examples/picker-usage.tsx +0 -20
  255. package/src/components/picker/picker.docs.tsx +0 -68
  256. package/src/components/popover/examples/popover-help.tsx +0 -57
  257. package/src/components/popover/examples/popover-menu.tsx +0 -51
  258. package/src/components/popover/examples/popover-showcase.tsx +0 -61
  259. package/src/components/popover/examples/popover-usage.tsx +0 -31
  260. package/src/components/popover/popover.docs.tsx +0 -84
  261. package/src/components/profile-image/examples/profile-image-fallbacks.tsx +0 -29
  262. package/src/components/profile-image/examples/profile-image-group.tsx +0 -34
  263. package/src/components/profile-image/examples/profile-image-showcase.tsx +0 -30
  264. package/src/components/profile-image/examples/profile-image-usage.tsx +0 -14
  265. package/src/components/profile-image/profile-image.docs.tsx +0 -81
  266. package/src/components/search-field/examples/search-field-filter.tsx +0 -53
  267. package/src/components/search-field/examples/search-field-showcase.tsx +0 -56
  268. package/src/components/search-field/examples/search-field-toolbar.tsx +0 -27
  269. package/src/components/search-field/examples/search-field-usage.tsx +0 -18
  270. package/src/components/search-field/search-field.docs.tsx +0 -58
  271. package/src/components/search-list/examples/search-list-dropdown.tsx +0 -53
  272. package/src/components/search-list/examples/search-list-groups.tsx +0 -64
  273. package/src/components/search-list/examples/search-list-showcase.tsx +0 -67
  274. package/src/components/search-list/examples/search-list-usage.tsx +0 -27
  275. package/src/components/search-list/search-list.docs.tsx +0 -87
  276. package/src/components/section/examples/section-actions.tsx +0 -35
  277. package/src/components/section/examples/section-groups.tsx +0 -41
  278. package/src/components/section/examples/section-showcase.tsx +0 -63
  279. package/src/components/section/examples/section-usage.tsx +0 -19
  280. package/src/components/section/section.docs.tsx +0 -51
  281. package/src/components/secure-field/examples/secure-field-new-password.tsx +0 -56
  282. package/src/components/secure-field/examples/secure-field-reveal.tsx +0 -20
  283. package/src/components/secure-field/examples/secure-field-showcase.tsx +0 -62
  284. package/src/components/secure-field/examples/secure-field-usage.tsx +0 -19
  285. package/src/components/secure-field/secure-field.docs.tsx +0 -72
  286. package/src/components/segmented-control/examples/segmented-control-overflow.tsx +0 -28
  287. package/src/components/segmented-control/examples/segmented-control-showcase.tsx +0 -59
  288. package/src/components/segmented-control/examples/segmented-control-usage.tsx +0 -20
  289. package/src/components/segmented-control/examples/segmented-control-views.tsx +0 -32
  290. package/src/components/segmented-control/segmented-control.docs.tsx +0 -61
  291. package/src/components/sheet/examples/sheet-choices.tsx +0 -58
  292. package/src/components/sheet/examples/sheet-share.tsx +0 -51
  293. package/src/components/sheet/examples/sheet-showcase.tsx +0 -74
  294. package/src/components/sheet/examples/sheet-usage.tsx +0 -32
  295. package/src/components/sheet/sheet.docs.tsx +0 -75
  296. package/src/components/sidebar/examples/sidebar-groups.tsx +0 -133
  297. package/src/components/sidebar/examples/sidebar-showcase.tsx +0 -123
  298. package/src/components/sidebar/examples/sidebar-unread.tsx +0 -66
  299. package/src/components/sidebar/examples/sidebar-usage.tsx +0 -52
  300. package/src/components/sidebar/sidebar.docs.tsx +0 -135
  301. package/src/components/stat-tile/examples/stat-tile-filters.tsx +0 -32
  302. package/src/components/stat-tile/examples/stat-tile-grid.tsx +0 -21
  303. package/src/components/stat-tile/examples/stat-tile-showcase.tsx +0 -52
  304. package/src/components/stat-tile/examples/stat-tile-usage.tsx +0 -13
  305. package/src/components/stat-tile/stat-tile.docs.tsx +0 -60
  306. package/src/components/status-indicator/examples/status-indicator-live.tsx +0 -34
  307. package/src/components/status-indicator/examples/status-indicator-showcase.tsx +0 -39
  308. package/src/components/status-indicator/examples/status-indicator-states.tsx +0 -17
  309. package/src/components/status-indicator/examples/status-indicator-usage.tsx +0 -9
  310. package/src/components/status-indicator/status-indicator.docs.tsx +0 -43
  311. package/src/components/swatch-picker/examples/swatch-picker-accents.tsx +0 -42
  312. package/src/components/swatch-picker/examples/swatch-picker-labels.tsx +0 -45
  313. package/src/components/swatch-picker/examples/swatch-picker-showcase.tsx +0 -70
  314. package/src/components/swatch-picker/examples/swatch-picker-usage.tsx +0 -39
  315. package/src/components/swatch-picker/swatch-picker.docs.tsx +0 -60
  316. package/src/components/tab-bar/examples/tab-bar-five-tabs.tsx +0 -66
  317. package/src/components/tab-bar/examples/tab-bar-minimize.tsx +0 -71
  318. package/src/components/tab-bar/examples/tab-bar-showcase.tsx +0 -82
  319. package/src/components/tab-bar/examples/tab-bar-usage.tsx +0 -54
  320. package/src/components/tab-bar/tab-bar.docs.tsx +0 -136
  321. package/src/components/tab-view/examples/tab-view-keyboard.tsx +0 -39
  322. package/src/components/tab-view/examples/tab-view-settings.tsx +0 -56
  323. package/src/components/tab-view/examples/tab-view-showcase.tsx +0 -53
  324. package/src/components/tab-view/examples/tab-view-usage.tsx +0 -23
  325. package/src/components/tab-view/tab-view.docs.tsx +0 -77
  326. package/src/components/table/examples/table-empty.tsx +0 -53
  327. package/src/components/table/examples/table-invoices.tsx +0 -102
  328. package/src/components/table/examples/table-selection.tsx +0 -150
  329. package/src/components/table/examples/table-showcase.tsx +0 -115
  330. package/src/components/table/examples/table-usage.tsx +0 -67
  331. package/src/components/table/examples/table-wide.tsx +0 -75
  332. package/src/components/table/table.docs.tsx +0 -131
  333. package/src/components/text-editor/examples/text-editor-comment.tsx +0 -48
  334. package/src/components/text-editor/examples/text-editor-count.tsx +0 -38
  335. package/src/components/text-editor/examples/text-editor-showcase.tsx +0 -58
  336. package/src/components/text-editor/examples/text-editor-usage.tsx +0 -25
  337. package/src/components/text-editor/text-editor.docs.tsx +0 -61
  338. package/src/components/text-field/examples/text-field-icons.tsx +0 -72
  339. package/src/components/text-field/examples/text-field-showcase.tsx +0 -50
  340. package/src/components/text-field/examples/text-field-usage.tsx +0 -18
  341. package/src/components/text-field/examples/text-field-validation.tsx +0 -27
  342. package/src/components/text-field/text-field.docs.tsx +0 -118
  343. package/src/components/toast/examples/toast-action.tsx +0 -32
  344. package/src/components/toast/examples/toast-promise.tsx +0 -45
  345. package/src/components/toast/examples/toast-showcase.tsx +0 -49
  346. package/src/components/toast/examples/toast-usage.tsx +0 -13
  347. package/src/components/toast/toast.docs.tsx +0 -79
  348. package/src/components/toggle/examples/toggle-checkboxes.tsx +0 -43
  349. package/src/components/toggle/examples/toggle-settings.tsx +0 -31
  350. package/src/components/toggle/examples/toggle-showcase.tsx +0 -59
  351. package/src/components/toggle/examples/toggle-usage.tsx +0 -13
  352. package/src/components/toggle/toggle.docs.tsx +0 -69
  353. package/src/components/tooltip/examples/tooltip-icon-buttons.tsx +0 -27
  354. package/src/components/tooltip/examples/tooltip-shortcuts.tsx +0 -38
  355. package/src/components/tooltip/examples/tooltip-showcase.tsx +0 -44
  356. package/src/components/tooltip/examples/tooltip-usage.tsx +0 -13
  357. package/src/components/tooltip/tooltip.docs.tsx +0 -56
  358. package/src/components/view-controller/examples/view-controller-action.tsx +0 -27
  359. package/src/components/view-controller/examples/view-controller-settings.tsx +0 -31
  360. package/src/components/view-controller/examples/view-controller-showcase.tsx +0 -45
  361. package/src/components/view-controller/examples/view-controller-usage.tsx +0 -19
  362. package/src/components/view-controller/view-controller.docs.tsx +0 -71
  363. package/src/docs/index.ts +0 -3
  364. package/src/docs/registry.ts +0 -113
  365. package/src/docs/snippet.ts +0 -17
  366. package/src/docs/types.ts +0 -180
@@ -1,35 +1,22 @@
1
- import { Sheet } from "@passui/react/sheet"
2
- import {
3
- AnimatePresence,
4
- motion,
5
- useReducedMotion,
6
- } from "motion/react"
7
- import { createPortal } from "react-dom"
8
- import { Button } from "@passui/react/button"
9
- import { cn } from "@passui/react/cn"
1
+ import { Sheet } from "../sheet/sheet"
2
+ import { AnimatePresence, motion, useReducedMotion } from "motion/react"
3
+ import { Button } from "../button/button"
4
+ import { cn } from "../../lib/class-names"
10
5
  import { spring } from "../../motion/transitions"
11
- import {
12
- createContext,
13
- useContext,
14
- useId,
15
- type FormEvent,
16
- type ReactNode,
17
- } from "react"
6
+ import { createContext, useContext, useId, type FormEvent, type ReactNode } from "react"
18
7
 
19
8
  const CloseContext = createContext<() => void>(() => {})
20
- export type DialogPresentation =
21
- | "drawer"
22
- | "center"
23
- | "inline"
9
+ export type DialogPresentation = "drawer" | "center" | "inline"
24
10
  export type DialogTone = "default" | "destructive"
25
11
 
26
- type DialogProps = {
12
+ export type DialogProps = {
27
13
  open: boolean
28
14
  onOpenChange: (open: boolean) => void
29
15
  title: ReactNode
30
16
  description?: ReactNode
31
17
  children?: ReactNode
32
18
  footer?: ReactNode
19
+ /** `drawer` (responsive sheet), `center` (floating panel), or `inline`. @default "drawer" */
33
20
  presentation?: DialogPresentation
34
21
  className?: string
35
22
  onSubmit?: (event: FormEvent<HTMLFormElement>) => void
@@ -60,28 +47,13 @@ export function Dialog({
60
47
  const content = (
61
48
  <>
62
49
  {presentation !== "inline" && (
63
- <h2
64
- id={titleId}
65
- className="text-title3 font-semibold"
66
- >
50
+ <h2 id={titleId} className="text-title3 font-semibold">
67
51
  {title}
68
52
  </h2>
69
53
  )}
70
- {description && (
71
- <p className="text-footnote text-label-secondary">
72
- {description}
73
- </p>
74
- )}
75
- {children && (
76
- <div className="flex flex-col gap-4">
77
- {children}
78
- </div>
79
- )}
80
- {footer && (
81
- <div className="flex flex-wrap justify-end gap-2 pt-3">
82
- {footer}
83
- </div>
84
- )}
54
+ {description && <div className="text-footnote text-label-secondary">{description}</div>}
55
+ {children && <div className="flex flex-col gap-4">{children}</div>}
56
+ {footer && <div className="flex flex-wrap justify-end gap-2 pt-3">{footer}</div>}
85
57
  </>
86
58
  )
87
59
  const body = (
@@ -89,20 +61,12 @@ export function Dialog({
89
61
  {onSubmit ? (
90
62
  <form
91
63
  onSubmit={onSubmit}
92
- className={cn(
93
- "flex min-h-0 flex-col gap-4 overflow-y-auto p-5",
94
- className
95
- )}
64
+ className={cn("flex min-h-0 flex-col gap-4 overflow-y-auto p-5", className)}
96
65
  >
97
66
  {content}
98
67
  </form>
99
68
  ) : (
100
- <div
101
- className={cn(
102
- "flex min-h-0 flex-col gap-4 overflow-y-auto p-5",
103
- className
104
- )}
105
- >
69
+ <div className={cn("flex min-h-0 flex-col gap-4 overflow-y-auto p-5", className)}>
106
70
  {content}
107
71
  </div>
108
72
  )}
@@ -115,9 +79,7 @@ export function Dialog({
115
79
  <motion.div
116
80
  key={titleId}
117
81
  initial={{
118
- height: reducedMotion
119
- ? "auto"
120
- : 0,
82
+ height: reducedMotion ? "auto" : 0,
121
83
  opacity: 0,
122
84
  }}
123
85
  animate={{
@@ -125,16 +87,10 @@ export function Dialog({
125
87
  opacity: 1,
126
88
  }}
127
89
  exit={{
128
- height: reducedMotion
129
- ? "auto"
130
- : 0,
90
+ height: reducedMotion ? "auto" : 0,
131
91
  opacity: 0,
132
92
  }}
133
- transition={
134
- reducedMotion
135
- ? { duration: 0 }
136
- : spring.smooth
137
- }
93
+ transition={reducedMotion ? { duration: 0 } : spring.smooth}
138
94
  className="overflow-hidden"
139
95
  >
140
96
  {body}
@@ -142,17 +98,16 @@ export function Dialog({
142
98
  )}
143
99
  </AnimatePresence>
144
100
  )
145
- if (typeof document === "undefined") return null
146
- return createPortal(
101
+ return (
147
102
  <Sheet
148
103
  open={open}
149
104
  onClose={close}
150
105
  label=""
151
106
  labelledBy={titleId}
107
+ placement={presentation === "center" ? "center" : "adaptive"}
152
108
  >
153
109
  {body}
154
- </Sheet>,
155
- document.body
110
+ </Sheet>
156
111
  )
157
112
  }
158
113
 
@@ -170,27 +125,15 @@ function Actions({
170
125
  <>
171
126
  <Button
172
127
  type={onConfirm ? "button" : "submit"}
173
- variant={
174
- tone === "destructive"
175
- ? "ghost"
176
- : "default"
177
- }
178
- className={
179
- tone === "destructive"
180
- ? "bg-danger/10 text-danger"
181
- : undefined
182
- }
128
+ variant={tone === "destructive" ? "ghost" : "default"}
129
+ className={tone === "destructive" ? "bg-danger/10 text-danger" : undefined}
183
130
  isPending={pending}
184
131
  disabled={disabled}
185
132
  onClick={onConfirm}
186
133
  >
187
134
  {submitLabel}
188
135
  </Button>
189
- <Button
190
- type="button"
191
- variant="secondary"
192
- onClick={close}
193
- >
136
+ <Button type="button" variant="secondary" onClick={close}>
194
137
  {cancelLabel}
195
138
  </Button>
196
139
  </>
@@ -0,0 +1,70 @@
1
+ import { type ReactNode, useId } from "react"
2
+ import { ChevronDownIcon } from "../../icons/icons"
3
+ import { cn } from "../../lib/class-names"
4
+ import { InlineDisclosure } from "../inline-disclosure/inline-disclosure"
5
+
6
+ export interface DisclosureGroupProps {
7
+ label: string
8
+ open: boolean
9
+ onOpenChange: (open: boolean) => void
10
+ children: ReactNode
11
+ disabled?: boolean
12
+ className?: string
13
+ /** Supporting text beneath the title. */
14
+ description?: string
15
+ }
16
+
17
+ /** A controlled, accessible disclosure row with the shared inline reveal. */
18
+ export function DisclosureGroup({
19
+ label,
20
+ open,
21
+ onOpenChange,
22
+ children,
23
+ disabled = false,
24
+ className,
25
+ description,
26
+ }: DisclosureGroupProps) {
27
+ const id = useId()
28
+
29
+ return (
30
+ <div className={cn("min-w-0", className)}>
31
+ <h3 className="m-0">
32
+ <button
33
+ type="button"
34
+ id={`${id}-trigger`}
35
+ aria-expanded={open}
36
+ aria-controls={id}
37
+ disabled={disabled}
38
+ onClick={() => onOpenChange(!open)}
39
+ className={cn(
40
+ "flex min-h-11 w-full items-center justify-between gap-3 rounded-xl px-3 py-2 text-start",
41
+ "text-subheadline text-label hover:bg-fill/60 focus-visible:outline-2 focus-visible:outline-offset-2",
42
+ "focus-visible:outline-accent-text disabled:cursor-not-allowed disabled:opacity-40"
43
+ )}
44
+ >
45
+ <span className="flex min-w-0 flex-col gap-0.5">
46
+ <span className="font-semibold">{label}</span>
47
+ {description && (
48
+ <span className="text-footnote font-normal text-label-secondary">
49
+ {description}
50
+ </span>
51
+ )}
52
+ </span>
53
+ <ChevronDownIcon
54
+ size={17}
55
+ aria-hidden="true"
56
+ className={cn(
57
+ "shrink-0 text-label-tertiary transition-transform duration-normal motion-reduce:transition-none",
58
+ open && "rotate-180"
59
+ )}
60
+ />
61
+ </button>
62
+ </h3>
63
+ <section id={id} aria-labelledby={`${id}-trigger`}>
64
+ <InlineDisclosure open={open}>
65
+ <div className="px-3 pb-3">{children}</div>
66
+ </InlineDisclosure>
67
+ </section>
68
+ </div>
69
+ )
70
+ }
@@ -0,0 +1,31 @@
1
+ import type { HTMLAttributes } from "react"
2
+ import { cn } from "../../lib/class-names"
3
+
4
+ export type DividerOrientation = "horizontal" | "vertical"
5
+
6
+ export interface DividerProps extends HTMLAttributes<HTMLHRElement> {
7
+ orientation?: DividerOrientation
8
+ /** Decorative separators are omitted from the accessibility tree. @default true */
9
+ decorative?: boolean
10
+ }
11
+
12
+ /** A semantic separator using the shared surface color. */
13
+ export function Divider({
14
+ orientation = "horizontal",
15
+ decorative = true,
16
+ className,
17
+ ...props
18
+ }: DividerProps) {
19
+ return (
20
+ <hr
21
+ {...props}
22
+ role={decorative ? "none" : "separator"}
23
+ aria-orientation={decorative ? undefined : orientation}
24
+ className={cn(
25
+ "shrink-0 border-0 bg-separator",
26
+ orientation === "horizontal" ? "h-px w-full" : "h-full w-px self-stretch",
27
+ className
28
+ )}
29
+ />
30
+ )
31
+ }
@@ -0,0 +1,49 @@
1
+ import { AnimatePresence, motion, useReducedMotion } from "motion/react"
2
+ import type { ReactNode } from "react"
3
+ import { cn } from "../../lib/class-names"
4
+ import { spring } from "../../motion/transitions"
5
+
6
+ export interface InlineDisclosureProps {
7
+ /** Whether the content is expanded. */
8
+ open: boolean
9
+ children: ReactNode
10
+ className?: string
11
+ }
12
+
13
+ /**
14
+ * An inline, spring-driven reveal for settings editors and small details.
15
+ *
16
+ * Height and opacity animate together so following rows move continuously
17
+ * instead of jumping. Motion is disabled when the user requests less motion.
18
+ * The content unmounts after its exit animation completes.
19
+ */
20
+ export function InlineDisclosure({ open, children, className }: InlineDisclosureProps) {
21
+ const reduceMotion = useReducedMotion()
22
+
23
+ return (
24
+ <AnimatePresence initial={false}>
25
+ {open && (
26
+ <motion.div
27
+ key="inline-disclosure"
28
+ initial={reduceMotion ? false : { height: 0, opacity: 0 }}
29
+ animate={{ height: "auto", opacity: 1 }}
30
+ exit={reduceMotion ? { opacity: 0 } : { height: 0, opacity: 0 }}
31
+ transition={
32
+ reduceMotion
33
+ ? { duration: 0 }
34
+ : {
35
+ height: spring.smooth,
36
+ opacity: {
37
+ duration: 0.18,
38
+ ease: "easeOut",
39
+ },
40
+ }
41
+ }
42
+ className={cn("overflow-hidden", className)}
43
+ >
44
+ {children}
45
+ </motion.div>
46
+ )}
47
+ </AnimatePresence>
48
+ )
49
+ }
@@ -1,6 +1,19 @@
1
- import type { ReactNode } from "react"
1
+ import type { HTMLAttributes, ReactNode } from "react"
2
2
  import { cn } from "../../lib/class-names"
3
3
 
4
+ export interface LabeledContentProps extends HTMLAttributes<HTMLDivElement> {
5
+ /** The visible name of the row. */
6
+ label: string
7
+ /** Supporting text below the label. */
8
+ description?: string
9
+ /** The row's control or value. */
10
+ children: ReactNode
11
+ /** Places the control below the label at every width. @default false */
12
+ stacked?: boolean
13
+ /** Places a wide control below its label on phones. @default false */
14
+ wide?: boolean
15
+ }
16
+
4
17
  /**
5
18
  * A row: a label, an optional description, and its control at the trailing
6
19
  * end, as SwiftUI's `LabeledContent`. Wide controls move under the label
@@ -12,38 +25,31 @@ export function LabeledContent({
12
25
  children,
13
26
  stacked,
14
27
  wide,
15
- }: {
16
- label: string
17
- description?: string
18
- children: ReactNode
19
- /** Put the control under the label, for wide controls. */
20
- stacked?: boolean
21
- /** A wide control (segmented) that moves under the label on phones. */
22
- wide?: boolean
23
- }) {
28
+ className,
29
+ ...props
30
+ }: LabeledContentProps) {
24
31
  return (
25
32
  <div
26
33
  className={cn(
27
- "flex flex-wrap gap-x-4 gap-y-2.5 px-4 py-3",
34
+ "flex flex-wrap gap-x-4 gap-y-2 px-4 py-3",
28
35
  stacked
29
36
  ? "flex-col items-stretch"
30
37
  : cn(
31
38
  "items-center justify-between",
32
- wide &&
33
- "max-sm:flex-col max-sm:items-stretch max-sm:gap-2.5"
34
- )
39
+ wide && "max-sm:flex-col max-sm:items-stretch max-sm:gap-2"
40
+ ),
41
+ className
35
42
  )}
43
+ {...props}
36
44
  >
37
45
  <div
38
46
  className={cn(
39
- "flex min-w-0 flex-1 flex-col break-normal",
47
+ "flex min-w-0 flex-1 flex-col gap-2 break-normal",
40
48
  !stacked && "basis-36",
41
49
  wide && "max-sm:basis-auto"
42
50
  )}
43
51
  >
44
- <span className="text-subheadline text-label">
45
- {label}
46
- </span>
52
+ <span className="text-subheadline text-label">{label}</span>
47
53
  {description && (
48
54
  <span className="text-footnote leading-snug text-label-secondary">
49
55
  {description}
@@ -1,11 +1,6 @@
1
1
  import { getNativeLanguageName } from "../../lib/language"
2
2
  import { cn } from "../../lib/class-names"
3
- import {
4
- AnimatePresence,
5
- motion,
6
- useDragControls,
7
- useMotionValue,
8
- } from "motion/react"
3
+ import { AnimatePresence, motion, useDragControls, useMotionValue } from "motion/react"
9
4
  import { useEffect, useRef, useState } from "react"
10
5
 
11
6
  type Side = "left" | "right"
@@ -31,10 +26,8 @@ function loadStoredAnchor(storageKey: string): Anchor | null {
31
26
  if (!raw) return null
32
27
  const parsed = JSON.parse(raw) as Partial<Anchor>
33
28
  if (
34
- (parsed.side === "left" ||
35
- parsed.side === "right") &&
36
- (parsed.edge === "top" ||
37
- parsed.edge === "bottom") &&
29
+ (parsed.side === "left" || parsed.side === "right") &&
30
+ (parsed.edge === "top" || parsed.edge === "bottom") &&
38
31
  typeof parsed.x === "number" &&
39
32
  typeof parsed.y === "number"
40
33
  ) {
@@ -49,15 +42,9 @@ function loadStoredAnchor(storageKey: string): Anchor | null {
49
42
  return null
50
43
  }
51
44
 
52
- function saveStoredAnchor(
53
- storageKey: string,
54
- anchor: Anchor
55
- ) {
45
+ function saveStoredAnchor(storageKey: string, anchor: Anchor) {
56
46
  try {
57
- localStorage.setItem(
58
- storageKey,
59
- JSON.stringify(anchor)
60
- )
47
+ localStorage.setItem(storageKey, JSON.stringify(anchor))
61
48
  } catch {}
62
49
  }
63
50
 
@@ -98,50 +85,25 @@ export function LocaleSwitcher<L extends string>({
98
85
  useEffect(() => {
99
86
  if (!open) return
100
87
  function handlePointerDown(e: PointerEvent) {
101
- if (
102
- containerRef.current &&
103
- !containerRef.current.contains(
104
- e.target as Node
105
- )
106
- ) {
88
+ if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
107
89
  setOpen(false)
108
90
  }
109
91
  }
110
- document.addEventListener(
111
- "pointerdown",
112
- handlePointerDown
113
- )
114
- return () =>
115
- document.removeEventListener(
116
- "pointerdown",
117
- handlePointerDown
118
- )
92
+ document.addEventListener("pointerdown", handlePointerDown)
93
+ return () => document.removeEventListener("pointerdown", handlePointerDown)
119
94
  }, [open])
120
95
 
121
96
  function commitDraggedPosition() {
122
97
  const el = containerRef.current
123
98
  if (!el) return
124
99
  const rect = el.getBoundingClientRect()
125
- const side: Side =
126
- rect.left + rect.width / 2 < window.innerWidth / 2
127
- ? "left"
128
- : "right"
129
- const edge: Edge =
130
- rect.top + rect.height / 2 <
131
- window.innerHeight / 2
132
- ? "top"
133
- : "bottom"
100
+ const side: Side = rect.left + rect.width / 2 < window.innerWidth / 2 ? "left" : "right"
101
+ const edge: Edge = rect.top + rect.height / 2 < window.innerHeight / 2 ? "top" : "bottom"
134
102
  const next: Anchor = {
135
103
  side,
136
104
  edge,
137
- x:
138
- side === "left"
139
- ? rect.left
140
- : window.innerWidth - rect.right,
141
- y:
142
- edge === "top"
143
- ? rect.top
144
- : window.innerHeight - rect.bottom,
105
+ x: side === "left" ? rect.left : window.innerWidth - rect.right,
106
+ y: edge === "top" ? rect.top : window.innerHeight - rect.bottom,
145
107
  }
146
108
  setAnchor(next)
147
109
  saveStoredAnchor(storageKey, next)
@@ -163,12 +125,8 @@ export function LocaleSwitcher<L extends string>({
163
125
  position: "fixed",
164
126
  x,
165
127
  y,
166
- ...(anchor.side === "left"
167
- ? { left: anchor.x }
168
- : { right: anchor.x }),
169
- ...(anchor.edge === "top"
170
- ? { top: anchor.y }
171
- : { bottom: anchor.y }),
128
+ ...(anchor.side === "left" ? { left: anchor.x } : { right: anchor.x }),
129
+ ...(anchor.edge === "top" ? { top: anchor.y } : { bottom: anchor.y }),
172
130
  }}
173
131
  onDragEnd={commitDraggedPosition}
174
132
  onMouseLeave={() => open && setOpen(false)}
@@ -182,7 +140,7 @@ export function LocaleSwitcher<L extends string>({
182
140
  stiffness: 380,
183
141
  }}
184
142
  className={cn(
185
- "overflow-hidden rounded-2xl border border-border/35 bg-popover/80 shadow-lg",
143
+ "overflow-hidden rounded-2xl border border-separator/35 bg-elevated/80 shadow-lg",
186
144
  "backdrop-blur-xl backdrop-saturate-150",
187
145
  "flex",
188
146
  growsUp ? "flex-col-reverse" : "flex-col",
@@ -193,16 +151,12 @@ export function LocaleSwitcher<L extends string>({
193
151
  type="button"
194
152
  aria-label={label}
195
153
  aria-expanded={open}
196
- onPointerDown={(e) =>
197
- dragControls.start(e)
198
- }
154
+ onPointerDown={(e) => dragControls.start(e)}
199
155
  onClick={() => setOpen((prev) => !prev)}
200
156
  className={cn(
201
157
  "flex shrink-0 cursor-grab items-center justify-center",
202
158
  "active:cursor-grabbing text-xs font-semibold",
203
- open
204
- ? "h-9 w-full rounded-lg hover:bg-accent"
205
- : "size-10 rounded-2xl"
159
+ open ? "h-9 w-full rounded-lg hover:bg-accent" : "size-10 rounded-2xl"
206
160
  )}
207
161
  >
208
162
  {locale.toUpperCase()}
@@ -218,8 +172,7 @@ export function LocaleSwitcher<L extends string>({
218
172
  className="flex flex-col gap-px"
219
173
  >
220
174
  {langs.map((item) => {
221
- const active =
222
- item.value === locale
175
+ const active = item.value === locale
223
176
  return (
224
177
  <button
225
178
  key={item.value}
@@ -227,16 +180,13 @@ export function LocaleSwitcher<L extends string>({
227
180
  onClick={() => {
228
181
  setOpen(false)
229
182
  if (!active) {
230
- onSelect(
231
- item.value
232
- )
183
+ onSelect(item.value)
233
184
  }
234
185
  }}
235
186
  className={cn(
236
187
  "rounded-sm px-2 py-1.5 text-left text-sm",
237
188
  "hover:bg-accent transition-colors",
238
- active &&
239
- "text-primary font-medium"
189
+ active && "text-primary font-medium"
240
190
  )}
241
191
  >
242
192
  {item.label}
@@ -0,0 +1,68 @@
1
+ import { forwardRef, type ReactNode, useRef, useSyncExternalStore } from "react"
2
+ import { Button, type ButtonProps } from "../button/button"
3
+ import {
4
+ closeContextMenu,
5
+ getContextMenu,
6
+ openMenu,
7
+ subscribeContextMenu,
8
+ type ContextMenuEdge,
9
+ type ContextMenuItem,
10
+ } from "../context-menu/context-menu-store"
11
+
12
+ export interface MenuProps extends Omit<ButtonProps, "onClick" | "children"> {
13
+ /** Accessible name for the menu trigger. */
14
+ label: string
15
+ /** Items are rendered by the app's existing ContextMenuHost. */
16
+ items: readonly ContextMenuItem[]
17
+ children: ReactNode
18
+ /** Logical edge used to align the menu, including RTL. @default "leading" */
19
+ edge?: ContextMenuEdge
20
+ /** Open above the trigger instead of below it. @default false */
21
+ above?: boolean
22
+ }
23
+
24
+ /** A declarative menu button using the same native host as context menus. */
25
+ export const Menu = forwardRef<HTMLButtonElement, MenuProps>(function Menu(
26
+ { label, items, children, edge = "leading", above = false, disabled, ...props },
27
+ forwardedRef
28
+ ) {
29
+ const trigger = useRef<HTMLButtonElement>(null)
30
+ const current = useSyncExternalStore(subscribeContextMenu, getContextMenu, () => null)
31
+ const expanded = Boolean(current && current.anchor === trigger.current)
32
+
33
+ const toggle = () => {
34
+ if (!trigger.current || disabled) return
35
+ if (expanded) closeContextMenu(false)
36
+ else openMenu(trigger.current, [...items], { edge, above })
37
+ }
38
+
39
+ return (
40
+ <Button
41
+ {...props}
42
+ ref={(node) => {
43
+ trigger.current = node
44
+ if (typeof forwardedRef === "function") forwardedRef(node)
45
+ else if (forwardedRef) forwardedRef.current = node
46
+ }}
47
+ type="button"
48
+ aria-label={label}
49
+ aria-haspopup="menu"
50
+ aria-expanded={expanded}
51
+ disabled={disabled}
52
+ onClick={toggle}
53
+ onKeyDown={(event) => {
54
+ props.onKeyDown?.(event)
55
+ if (event.defaultPrevented) return
56
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
57
+ event.preventDefault()
58
+ if (!expanded) toggle()
59
+ } else if (event.key === "Escape" && expanded) {
60
+ event.preventDefault()
61
+ closeContextMenu()
62
+ }
63
+ }}
64
+ >
65
+ {children}
66
+ </Button>
67
+ )
68
+ })
@@ -0,0 +1,10 @@
1
+ import { cn } from "../../lib/class-names"
2
+
3
+ /** Shared field treatment for the popup-based Picker, date and time controls. */
4
+ export function pickerTriggerStyle(className?: string) {
5
+ return cn(
6
+ "flex w-full min-w-0 items-center gap-2 rounded-lg control-field px-3 py-2 text-start text-subheadline text-label",
7
+ "disabled:cursor-not-allowed disabled:opacity-40",
8
+ className
9
+ )
10
+ }