@passui/react 0.1.17 → 0.1.20

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 (408) hide show
  1. package/README.md +140 -1
  2. package/THIRD_PARTY_NOTICES.md +25 -0
  3. package/dist/types/src/appearance/index.d.ts +2 -0
  4. package/dist/types/src/appearance/platform.d.ts +9 -0
  5. package/dist/types/src/appearance/theme.d.ts +71 -0
  6. package/dist/types/src/components/accordion/accordion.d.ts +19 -0
  7. package/dist/types/src/components/ambient/ambient.d.ts +12 -0
  8. package/dist/types/src/components/ambient/index.d.ts +1 -0
  9. package/dist/types/src/components/aspect-ratio/aspect-ratio.d.ts +7 -0
  10. package/dist/types/src/components/breadcrumb/breadcrumb.d.ts +16 -0
  11. package/dist/types/src/components/button/button-styles.d.ts +12 -0
  12. package/dist/types/src/components/button/button.d.ts +32 -0
  13. package/dist/types/src/components/button/icon-button.d.ts +10 -0
  14. package/dist/types/src/components/button/pending-spinner.d.ts +5 -0
  15. package/dist/types/src/components/button/use-pending-indicator.d.ts +2 -0
  16. package/dist/types/src/components/chip/chip.d.ts +7 -0
  17. package/dist/types/src/components/code-block/code-block.d.ts +10 -0
  18. package/dist/types/src/components/combo-box/combo-box.d.ts +9 -0
  19. package/dist/types/src/components/command/command.d.ts +18 -0
  20. package/dist/types/src/components/compact-date-picker/calendar-month.d.ts +25 -0
  21. package/dist/types/src/components/compact-date-picker/compact-date-picker.d.ts +27 -0
  22. package/dist/types/src/components/compact-time-picker/compact-time-picker.d.ts +26 -0
  23. package/dist/types/src/components/compact-time-picker/time-value.d.ts +18 -0
  24. package/dist/types/src/components/content-unavailable-view/content-unavailable-view.d.ts +9 -0
  25. package/dist/types/src/components/content-view/content-view.d.ts +48 -0
  26. package/dist/types/src/components/content-view/index.d.ts +1 -0
  27. package/dist/types/src/components/context-menu/conceal-menu-source.d.ts +2 -0
  28. package/dist/types/src/components/context-menu/context-menu-host.d.ts +2 -0
  29. package/dist/types/src/components/context-menu/context-menu-store.d.ts +57 -0
  30. package/dist/types/src/components/context-menu/menu-navigation.d.ts +6 -0
  31. package/dist/types/src/components/context-menu/menu-position.d.ts +21 -0
  32. package/dist/types/src/components/context-menu/menu-reveal.d.ts +17 -0
  33. package/dist/types/src/components/context-menu/use-context-menu.d.ts +14 -0
  34. package/dist/types/src/components/conversation/conversation.d.ts +43 -0
  35. package/dist/types/src/components/conversation/index.d.ts +1 -0
  36. package/dist/types/src/components/date-picker/date-picker.d.ts +16 -0
  37. package/dist/types/src/components/date-picker/date-value.d.ts +2 -0
  38. package/dist/types/src/components/dialog/dialog-host.d.ts +6 -0
  39. package/dist/types/src/components/dialog/dialog-store.d.ts +23 -0
  40. package/dist/types/src/components/dialog/dialog.d.ts +30 -0
  41. package/dist/types/src/components/dialog/index.d.ts +1 -0
  42. package/dist/types/src/components/disclosure-group/disclosure-group.d.ts +15 -0
  43. package/dist/types/src/components/divider/divider.d.ts +9 -0
  44. package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +15 -0
  45. package/dist/types/src/components/keyboard-shortcut/keyboard-shortcut.d.ts +5 -0
  46. package/dist/types/src/components/labeled-content/labeled-content.d.ts +19 -0
  47. package/dist/types/src/components/locale-switcher/index.d.ts +1 -0
  48. package/dist/types/src/components/locale-switcher/locale-switcher.d.ts +10 -0
  49. package/dist/types/src/components/menu/menu.d.ts +16 -0
  50. package/dist/types/src/components/one-time-code/one-time-code.d.ts +18 -0
  51. package/dist/types/src/components/picker/picker-trigger.d.ts +2 -0
  52. package/dist/types/src/components/picker/picker.d.ts +43 -0
  53. package/dist/types/src/components/popover/anchored-surface.d.ts +13 -0
  54. package/dist/types/src/components/popover/popover-fit.d.ts +21 -0
  55. package/dist/types/src/components/popover/popover.d.ts +18 -0
  56. package/dist/types/src/components/profile-image/profile-image.d.ts +4 -0
  57. package/dist/types/src/components/progress-view/progress-view.d.ts +13 -0
  58. package/dist/types/src/components/progress-view/use-liquid-progress.d.ts +3 -0
  59. package/dist/types/src/components/radio-group/radio-group.d.ts +17 -0
  60. package/dist/types/src/components/search-field/expanding-search-field.d.ts +5 -0
  61. package/dist/types/src/components/search-field/search-field.d.ts +6 -0
  62. package/dist/types/src/components/search-list/search-list.d.ts +19 -0
  63. package/dist/types/src/components/section/section.d.ts +15 -0
  64. package/dist/types/src/components/secure-field/secure-field.d.ts +4 -0
  65. package/dist/types/src/components/segmented-control/segmented-control.d.ts +20 -0
  66. package/dist/types/src/components/sheet/modal-environment.d.ts +2 -0
  67. package/dist/types/src/components/sheet/sheet-portal.d.ts +5 -0
  68. package/dist/types/src/components/sheet/sheet.d.ts +21 -0
  69. package/dist/types/src/components/sheet/use-sheet-focus.d.ts +3 -0
  70. package/dist/types/src/components/sidebar/sidebar.d.ts +19 -0
  71. package/dist/types/src/components/skeleton/skeleton.d.ts +6 -0
  72. package/dist/types/src/components/slider/slider.d.ts +14 -0
  73. package/dist/types/src/components/slosh-slider/liquid-step.d.ts +6 -0
  74. package/dist/types/src/components/slosh-slider/slosh-slider.d.ts +18 -0
  75. package/dist/types/src/components/stat-tile/index.d.ts +1 -0
  76. package/dist/types/src/components/stat-tile/stat-tile.d.ts +15 -0
  77. package/dist/types/src/components/status-indicator/status-indicator.d.ts +14 -0
  78. package/dist/types/src/components/stepper/rolling-digit.d.ts +11 -0
  79. package/dist/types/src/components/stepper/stepper.d.ts +19 -0
  80. package/dist/types/src/components/swatch-picker/swatch-picker.d.ts +17 -0
  81. package/dist/types/src/components/tab-bar/tab-bar.d.ts +40 -0
  82. package/dist/types/src/components/tab-view/tab-view.d.ts +24 -0
  83. package/dist/types/src/components/table/table.d.ts +10 -0
  84. package/dist/types/src/components/text-editor/text-editor.d.ts +2 -0
  85. package/dist/types/src/components/text-field/text-field.d.ts +20 -0
  86. package/dist/types/src/components/toast/toast-store.d.ts +47 -0
  87. package/dist/types/src/components/toast/toaster.d.ts +10 -0
  88. package/dist/types/src/components/toggle/toggle.d.ts +17 -0
  89. package/dist/types/src/components/tooltip/tooltip-host.d.ts +6 -0
  90. package/dist/types/src/components/view-controller/index.d.ts +1 -0
  91. package/dist/types/src/components/view-controller/view-controller.d.ts +21 -0
  92. package/dist/types/src/components/wake-slider/wake-slider.d.ts +12 -0
  93. package/dist/types/src/hooks/scroll/minimize-decision.d.ts +2 -0
  94. package/dist/types/src/hooks/use-anchored-disclosure.d.ts +9 -0
  95. package/dist/types/src/hooks/use-anchored-placement.d.ts +7 -0
  96. package/dist/types/src/hooks/use-dismiss.d.ts +9 -0
  97. package/dist/types/src/hooks/use-floating-dismiss.d.ts +3 -0
  98. package/dist/types/src/hooks/use-media-query.d.ts +21 -0
  99. package/dist/types/src/hooks/use-minimize-on-scroll.d.ts +6 -0
  100. package/dist/types/src/hooks/use-visual-viewport.d.ts +4 -0
  101. package/dist/types/src/hooks/viewport/types.d.ts +19 -0
  102. package/dist/types/src/hooks/viewport/viewport-metrics.d.ts +3 -0
  103. package/dist/types/src/icons/icons.d.ts +612 -0
  104. package/dist/types/src/index.d.ts +71 -0
  105. package/dist/types/src/lib/anchored-placement.d.ts +39 -0
  106. package/dist/types/src/lib/class-names.d.ts +2 -0
  107. package/dist/types/src/lib/clipboard.d.ts +6 -0
  108. package/dist/types/src/lib/date.d.ts +50 -0
  109. package/dist/types/src/lib/floating-layers.d.ts +8 -0
  110. package/dist/types/src/lib/haptics.d.ts +8 -0
  111. package/dist/types/src/lib/language.d.ts +4 -0
  112. package/dist/types/src/lib/range-value.d.ts +4 -0
  113. package/dist/types/src/lib/screen-edges.d.ts +12 -0
  114. package/dist/types/src/lib/shapes.d.ts +17 -0
  115. package/dist/types/src/motion/transitions.d.ts +97 -0
  116. package/dist/types/src/tokens.d.ts +1 -0
  117. package/package.json +248 -40
  118. package/src/appearance/platform.tsx +10 -47
  119. package/src/appearance/theme.tsx +42 -142
  120. package/src/components/accordion/accordion.tsx +48 -0
  121. package/src/components/ambient/ambient.tsx +2 -10
  122. package/src/components/aspect-ratio/aspect-ratio.tsx +22 -0
  123. package/src/components/breadcrumb/breadcrumb.tsx +53 -0
  124. package/src/components/button/button-styles.ts +13 -31
  125. package/src/components/button/button.tsx +24 -15
  126. package/src/components/button/icon-button.tsx +14 -56
  127. package/src/components/button/use-pending-indicator.ts +2 -7
  128. package/src/components/chip/chip.tsx +8 -13
  129. package/src/components/code-block/code-block.tsx +41 -0
  130. package/src/components/combo-box/combo-box.tsx +13 -0
  131. package/src/components/command/command.tsx +119 -0
  132. package/src/components/compact-date-picker/calendar-month.ts +13 -57
  133. package/src/components/compact-date-picker/compact-date-picker.tsx +72 -195
  134. package/src/components/compact-time-picker/compact-time-picker.tsx +74 -195
  135. package/src/components/compact-time-picker/time-value.ts +4 -16
  136. package/src/components/content-unavailable-view/content-unavailable-view.tsx +37 -0
  137. package/src/components/content-view/content-view.tsx +13 -56
  138. package/src/components/context-menu/conceal-menu-source.ts +1 -4
  139. package/src/components/context-menu/context-menu-host.tsx +132 -198
  140. package/src/components/context-menu/context-menu-store.ts +5 -14
  141. package/src/components/context-menu/menu-navigation.ts +29 -0
  142. package/src/components/context-menu/menu-position.ts +6 -27
  143. package/src/components/context-menu/menu-reveal.ts +14 -52
  144. package/src/components/context-menu/use-context-menu.ts +6 -30
  145. package/src/components/conversation/conversation.tsx +26 -72
  146. package/src/components/date-picker/date-picker.tsx +8 -37
  147. package/src/components/date-picker/date-value.ts +5 -30
  148. package/src/components/dialog/dialog-host.tsx +37 -76
  149. package/src/components/dialog/dialog-store.ts +16 -7
  150. package/src/components/dialog/dialog.tsx +23 -80
  151. package/src/components/disclosure-group/disclosure-group.tsx +79 -0
  152. package/src/components/divider/divider.tsx +31 -0
  153. package/src/components/inline-disclosure/inline-disclosure.tsx +49 -0
  154. package/src/components/keyboard-shortcut/keyboard-shortcut.tsx +17 -0
  155. package/src/components/labeled-content/labeled-content.tsx +24 -18
  156. package/src/components/locale-switcher/locale-switcher.tsx +20 -70
  157. package/src/components/menu/menu.tsx +68 -0
  158. package/src/components/one-time-code/one-time-code.tsx +168 -0
  159. package/src/components/picker/picker-trigger.ts +10 -0
  160. package/src/components/picker/picker.tsx +165 -283
  161. package/src/components/popover/anchored-surface.tsx +223 -0
  162. package/src/components/popover/popover-fit.ts +69 -0
  163. package/src/components/popover/popover.tsx +209 -63
  164. package/src/components/profile-image/profile-image.tsx +6 -28
  165. package/src/components/progress-view/progress-view.tsx +70 -0
  166. package/src/components/progress-view/use-liquid-progress.ts +43 -0
  167. package/src/components/radio-group/radio-group.tsx +63 -0
  168. package/src/components/search-field/expanding-search-field.tsx +183 -0
  169. package/src/components/search-field/search-field.tsx +25 -7
  170. package/src/components/search-list/search-list.tsx +58 -75
  171. package/src/components/section/section.tsx +18 -17
  172. package/src/components/secure-field/secure-field.tsx +5 -7
  173. package/src/components/segmented-control/segmented-control.tsx +20 -29
  174. package/src/components/sheet/modal-environment.ts +16 -54
  175. package/src/components/sheet/sheet-portal.tsx +10 -42
  176. package/src/components/sheet/sheet.tsx +17 -25
  177. package/src/components/sheet/use-sheet-focus.ts +15 -51
  178. package/src/components/sidebar/sidebar.tsx +44 -38
  179. package/src/components/skeleton/skeleton.tsx +19 -0
  180. package/src/components/slider/slider.tsx +76 -0
  181. package/src/components/slosh-slider/liquid-step.ts +42 -0
  182. package/src/components/slosh-slider/slosh-slider.tsx +251 -0
  183. package/src/components/stat-tile/stat-tile.tsx +9 -30
  184. package/src/components/status-indicator/status-indicator.tsx +12 -19
  185. package/src/components/stepper/rolling-digit.tsx +77 -0
  186. package/src/components/stepper/stepper.tsx +101 -0
  187. package/src/components/swatch-picker/swatch-picker.tsx +19 -15
  188. package/src/components/tab-bar/tab-bar.tsx +59 -59
  189. package/src/components/tab-view/tab-view.tsx +52 -57
  190. package/src/components/table/table.tsx +14 -62
  191. package/src/components/text-editor/text-editor.tsx +2 -12
  192. package/src/components/text-field/text-field.tsx +53 -44
  193. package/src/components/toast/toast-store.ts +9 -30
  194. package/src/components/toast/toaster.tsx +90 -104
  195. package/src/components/toggle/toggle.tsx +165 -44
  196. package/src/components/tooltip/tooltip-host.tsx +70 -67
  197. package/src/components/view-controller/view-controller.tsx +4 -21
  198. package/src/components/wake-slider/wake-slider.tsx +237 -0
  199. package/src/hooks/scroll/minimize-decision.ts +1 -5
  200. package/src/hooks/use-anchored-disclosure.ts +23 -0
  201. package/src/hooks/use-anchored-placement.ts +7 -14
  202. package/src/hooks/use-dismiss.ts +5 -23
  203. package/src/hooks/use-floating-dismiss.ts +28 -0
  204. package/src/hooks/use-media-query.ts +12 -31
  205. package/src/hooks/use-minimize-on-scroll.ts +10 -34
  206. package/src/hooks/use-visual-viewport.ts +5 -14
  207. package/src/hooks/viewport/viewport-metrics.ts +4 -16
  208. package/src/icons/icons.tsx +229 -183
  209. package/src/index.ts +27 -1
  210. package/src/lib/anchored-placement.ts +12 -18
  211. package/src/lib/class-names.ts +1 -2
  212. package/src/lib/clipboard.ts +14 -0
  213. package/src/lib/date.ts +4 -15
  214. package/src/lib/floating-layers.ts +18 -8
  215. package/src/lib/haptics.ts +1 -3
  216. package/src/lib/language.ts +2 -7
  217. package/src/lib/range-value.ts +32 -0
  218. package/src/lib/screen-edges.ts +2 -6
  219. package/src/lib/shapes.ts +5 -20
  220. package/src/motion/transitions.ts +18 -12
  221. package/src/styles/code-block.css +33 -0
  222. package/src/styles/motion-controls.css +189 -0
  223. package/src/styles/styles.css +3 -0
  224. package/src/components/ambient/ambient.docs.tsx +0 -68
  225. package/src/components/ambient/examples/ambient-images.tsx +0 -30
  226. package/src/components/ambient/examples/ambient-now-playing.tsx +0 -55
  227. package/src/components/ambient/examples/ambient-showcase.tsx +0 -33
  228. package/src/components/ambient/examples/ambient-usage.tsx +0 -19
  229. package/src/components/button/button.docs.tsx +0 -116
  230. package/src/components/button/examples/button-disabled.tsx +0 -19
  231. package/src/components/button/examples/button-icon.tsx +0 -39
  232. package/src/components/button/examples/button-link.tsx +0 -12
  233. package/src/components/button/examples/button-pending.tsx +0 -27
  234. package/src/components/button/examples/button-showcase.tsx +0 -115
  235. package/src/components/button/examples/button-sizes.tsx +0 -12
  236. package/src/components/button/examples/button-usage.tsx +0 -12
  237. package/src/components/button/examples/button-variants.tsx +0 -15
  238. package/src/components/button/examples/button-with-icon.tsx +0 -32
  239. package/src/components/button/examples/icon-button-player.tsx +0 -38
  240. package/src/components/button/examples/icon-button-showcase.tsx +0 -83
  241. package/src/components/button/examples/icon-button-usage.tsx +0 -11
  242. package/src/components/button/examples/icon-button-variants.tsx +0 -39
  243. package/src/components/button/icon-button.docs.tsx +0 -68
  244. package/src/components/chip/chip.docs.tsx +0 -37
  245. package/src/components/chip/examples/chip-in-rows.tsx +0 -19
  246. package/src/components/chip/examples/chip-showcase.tsx +0 -51
  247. package/src/components/chip/examples/chip-tones.tsx +0 -13
  248. package/src/components/chip/examples/chip-usage.tsx +0 -5
  249. package/src/components/compact-date-picker/compact-date-picker.docs.tsx +0 -81
  250. package/src/components/compact-date-picker/examples/compact-date-picker-showcase.tsx +0 -35
  251. package/src/components/compact-date-picker/examples/compact-date-picker-usage.tsx +0 -22
  252. package/src/components/compact-time-picker/compact-time-picker.docs.tsx +0 -80
  253. package/src/components/compact-time-picker/examples/compact-time-picker-showcase.tsx +0 -31
  254. package/src/components/compact-time-picker/examples/compact-time-picker-usage.tsx +0 -21
  255. package/src/components/content-view/content-view.docs.tsx +0 -61
  256. package/src/components/content-view/examples/content-view-header-action.tsx +0 -33
  257. package/src/components/content-view/examples/content-view-showcase.tsx +0 -65
  258. package/src/components/content-view/examples/content-view-stats.tsx +0 -35
  259. package/src/components/content-view/examples/content-view-usage.tsx +0 -14
  260. package/src/components/context-menu/context-menu.docs.tsx +0 -92
  261. package/src/components/context-menu/examples/context-menu-checked.tsx +0 -37
  262. package/src/components/context-menu/examples/context-menu-list.tsx +0 -85
  263. package/src/components/context-menu/examples/context-menu-showcase.tsx +0 -56
  264. package/src/components/context-menu/examples/context-menu-toolbar.tsx +0 -63
  265. package/src/components/context-menu/examples/context-menu-usage.tsx +0 -24
  266. package/src/components/conversation/conversation.docs.tsx +0 -88
  267. package/src/components/conversation/examples/conversation-composer.tsx +0 -36
  268. package/src/components/conversation/examples/conversation-days.tsx +0 -48
  269. package/src/components/conversation/examples/conversation-showcase.tsx +0 -71
  270. package/src/components/conversation/examples/conversation-usage.tsx +0 -28
  271. package/src/components/date-picker/date-picker.docs.tsx +0 -88
  272. package/src/components/date-picker/examples/date-picker-locales.tsx +0 -41
  273. package/src/components/date-picker/examples/date-picker-past-only.tsx +0 -29
  274. package/src/components/date-picker/examples/date-picker-showcase.tsx +0 -49
  275. package/src/components/date-picker/examples/date-picker-usage.tsx +0 -22
  276. package/src/components/dialog/dialog.docs.tsx +0 -114
  277. package/src/components/dialog/examples/dialog-confirm.tsx +0 -24
  278. package/src/components/dialog/examples/dialog-form.tsx +0 -46
  279. package/src/components/dialog/examples/dialog-inline.tsx +0 -48
  280. package/src/components/dialog/examples/dialog-showcase.tsx +0 -53
  281. package/src/components/dialog/examples/dialog-usage.tsx +0 -31
  282. package/src/components/labeled-content/examples/labeled-content-descriptions.tsx +0 -37
  283. package/src/components/labeled-content/examples/labeled-content-showcase.tsx +0 -54
  284. package/src/components/labeled-content/examples/labeled-content-usage.tsx +0 -22
  285. package/src/components/labeled-content/examples/labeled-content-values.tsx +0 -26
  286. package/src/components/labeled-content/examples/labeled-content-wide.tsx +0 -46
  287. package/src/components/labeled-content/labeled-content.docs.tsx +0 -69
  288. package/src/components/locale-switcher/examples/locale-switcher-native-names.tsx +0 -30
  289. package/src/components/locale-switcher/examples/locale-switcher-showcase.tsx +0 -46
  290. package/src/components/locale-switcher/examples/locale-switcher-translated-page.tsx +0 -35
  291. package/src/components/locale-switcher/examples/locale-switcher-usage.tsx +0 -20
  292. package/src/components/locale-switcher/locale-switcher.docs.tsx +0 -91
  293. package/src/components/picker/examples/picker-details.tsx +0 -44
  294. package/src/components/picker/examples/picker-searchable.tsx +0 -48
  295. package/src/components/picker/examples/picker-showcase.tsx +0 -66
  296. package/src/components/picker/examples/picker-usage.tsx +0 -20
  297. package/src/components/picker/picker.docs.tsx +0 -68
  298. package/src/components/popover/examples/popover-help.tsx +0 -57
  299. package/src/components/popover/examples/popover-menu.tsx +0 -51
  300. package/src/components/popover/examples/popover-showcase.tsx +0 -61
  301. package/src/components/popover/examples/popover-usage.tsx +0 -31
  302. package/src/components/popover/popover.docs.tsx +0 -84
  303. package/src/components/profile-image/examples/profile-image-fallbacks.tsx +0 -29
  304. package/src/components/profile-image/examples/profile-image-group.tsx +0 -34
  305. package/src/components/profile-image/examples/profile-image-showcase.tsx +0 -30
  306. package/src/components/profile-image/examples/profile-image-usage.tsx +0 -14
  307. package/src/components/profile-image/profile-image.docs.tsx +0 -81
  308. package/src/components/search-field/examples/search-field-filter.tsx +0 -53
  309. package/src/components/search-field/examples/search-field-showcase.tsx +0 -56
  310. package/src/components/search-field/examples/search-field-toolbar.tsx +0 -27
  311. package/src/components/search-field/examples/search-field-usage.tsx +0 -18
  312. package/src/components/search-field/search-field.docs.tsx +0 -58
  313. package/src/components/search-list/examples/search-list-dropdown.tsx +0 -53
  314. package/src/components/search-list/examples/search-list-groups.tsx +0 -64
  315. package/src/components/search-list/examples/search-list-showcase.tsx +0 -67
  316. package/src/components/search-list/examples/search-list-usage.tsx +0 -27
  317. package/src/components/search-list/search-list.docs.tsx +0 -87
  318. package/src/components/section/examples/section-actions.tsx +0 -35
  319. package/src/components/section/examples/section-groups.tsx +0 -41
  320. package/src/components/section/examples/section-showcase.tsx +0 -63
  321. package/src/components/section/examples/section-usage.tsx +0 -19
  322. package/src/components/section/section.docs.tsx +0 -51
  323. package/src/components/secure-field/examples/secure-field-new-password.tsx +0 -56
  324. package/src/components/secure-field/examples/secure-field-reveal.tsx +0 -20
  325. package/src/components/secure-field/examples/secure-field-showcase.tsx +0 -62
  326. package/src/components/secure-field/examples/secure-field-usage.tsx +0 -19
  327. package/src/components/secure-field/secure-field.docs.tsx +0 -72
  328. package/src/components/segmented-control/examples/segmented-control-overflow.tsx +0 -28
  329. package/src/components/segmented-control/examples/segmented-control-showcase.tsx +0 -59
  330. package/src/components/segmented-control/examples/segmented-control-usage.tsx +0 -20
  331. package/src/components/segmented-control/examples/segmented-control-views.tsx +0 -32
  332. package/src/components/segmented-control/segmented-control.docs.tsx +0 -61
  333. package/src/components/sheet/examples/sheet-choices.tsx +0 -58
  334. package/src/components/sheet/examples/sheet-share.tsx +0 -51
  335. package/src/components/sheet/examples/sheet-showcase.tsx +0 -74
  336. package/src/components/sheet/examples/sheet-usage.tsx +0 -32
  337. package/src/components/sheet/sheet.docs.tsx +0 -75
  338. package/src/components/sidebar/examples/sidebar-groups.tsx +0 -133
  339. package/src/components/sidebar/examples/sidebar-showcase.tsx +0 -123
  340. package/src/components/sidebar/examples/sidebar-unread.tsx +0 -66
  341. package/src/components/sidebar/examples/sidebar-usage.tsx +0 -52
  342. package/src/components/sidebar/sidebar.docs.tsx +0 -135
  343. package/src/components/stat-tile/examples/stat-tile-filters.tsx +0 -32
  344. package/src/components/stat-tile/examples/stat-tile-grid.tsx +0 -21
  345. package/src/components/stat-tile/examples/stat-tile-showcase.tsx +0 -52
  346. package/src/components/stat-tile/examples/stat-tile-usage.tsx +0 -13
  347. package/src/components/stat-tile/stat-tile.docs.tsx +0 -60
  348. package/src/components/status-indicator/examples/status-indicator-live.tsx +0 -34
  349. package/src/components/status-indicator/examples/status-indicator-showcase.tsx +0 -39
  350. package/src/components/status-indicator/examples/status-indicator-states.tsx +0 -17
  351. package/src/components/status-indicator/examples/status-indicator-usage.tsx +0 -9
  352. package/src/components/status-indicator/status-indicator.docs.tsx +0 -43
  353. package/src/components/swatch-picker/examples/swatch-picker-accents.tsx +0 -42
  354. package/src/components/swatch-picker/examples/swatch-picker-labels.tsx +0 -45
  355. package/src/components/swatch-picker/examples/swatch-picker-showcase.tsx +0 -70
  356. package/src/components/swatch-picker/examples/swatch-picker-usage.tsx +0 -39
  357. package/src/components/swatch-picker/swatch-picker.docs.tsx +0 -60
  358. package/src/components/tab-bar/examples/tab-bar-five-tabs.tsx +0 -66
  359. package/src/components/tab-bar/examples/tab-bar-minimize.tsx +0 -71
  360. package/src/components/tab-bar/examples/tab-bar-showcase.tsx +0 -82
  361. package/src/components/tab-bar/examples/tab-bar-usage.tsx +0 -54
  362. package/src/components/tab-bar/tab-bar.docs.tsx +0 -136
  363. package/src/components/tab-view/examples/tab-view-keyboard.tsx +0 -39
  364. package/src/components/tab-view/examples/tab-view-settings.tsx +0 -56
  365. package/src/components/tab-view/examples/tab-view-showcase.tsx +0 -53
  366. package/src/components/tab-view/examples/tab-view-usage.tsx +0 -23
  367. package/src/components/tab-view/tab-view.docs.tsx +0 -77
  368. package/src/components/table/examples/table-empty.tsx +0 -53
  369. package/src/components/table/examples/table-invoices.tsx +0 -102
  370. package/src/components/table/examples/table-selection.tsx +0 -150
  371. package/src/components/table/examples/table-showcase.tsx +0 -115
  372. package/src/components/table/examples/table-usage.tsx +0 -67
  373. package/src/components/table/examples/table-wide.tsx +0 -75
  374. package/src/components/table/table.docs.tsx +0 -131
  375. package/src/components/text-editor/examples/text-editor-comment.tsx +0 -48
  376. package/src/components/text-editor/examples/text-editor-count.tsx +0 -38
  377. package/src/components/text-editor/examples/text-editor-showcase.tsx +0 -58
  378. package/src/components/text-editor/examples/text-editor-usage.tsx +0 -25
  379. package/src/components/text-editor/text-editor.docs.tsx +0 -61
  380. package/src/components/text-field/examples/text-field-icons.tsx +0 -72
  381. package/src/components/text-field/examples/text-field-showcase.tsx +0 -50
  382. package/src/components/text-field/examples/text-field-usage.tsx +0 -18
  383. package/src/components/text-field/examples/text-field-validation.tsx +0 -27
  384. package/src/components/text-field/text-field.docs.tsx +0 -118
  385. package/src/components/toast/examples/toast-action.tsx +0 -32
  386. package/src/components/toast/examples/toast-promise.tsx +0 -45
  387. package/src/components/toast/examples/toast-showcase.tsx +0 -49
  388. package/src/components/toast/examples/toast-usage.tsx +0 -13
  389. package/src/components/toast/toast.docs.tsx +0 -79
  390. package/src/components/toggle/examples/toggle-checkboxes.tsx +0 -43
  391. package/src/components/toggle/examples/toggle-settings.tsx +0 -31
  392. package/src/components/toggle/examples/toggle-showcase.tsx +0 -59
  393. package/src/components/toggle/examples/toggle-usage.tsx +0 -13
  394. package/src/components/toggle/toggle.docs.tsx +0 -69
  395. package/src/components/tooltip/examples/tooltip-icon-buttons.tsx +0 -27
  396. package/src/components/tooltip/examples/tooltip-shortcuts.tsx +0 -38
  397. package/src/components/tooltip/examples/tooltip-showcase.tsx +0 -44
  398. package/src/components/tooltip/examples/tooltip-usage.tsx +0 -13
  399. package/src/components/tooltip/tooltip.docs.tsx +0 -56
  400. package/src/components/view-controller/examples/view-controller-action.tsx +0 -27
  401. package/src/components/view-controller/examples/view-controller-settings.tsx +0 -31
  402. package/src/components/view-controller/examples/view-controller-showcase.tsx +0 -45
  403. package/src/components/view-controller/examples/view-controller-usage.tsx +0 -19
  404. package/src/components/view-controller/view-controller.docs.tsx +0 -71
  405. package/src/docs/index.ts +0 -3
  406. package/src/docs/registry.ts +0 -113
  407. package/src/docs/snippet.ts +0 -17
  408. package/src/docs/types.ts +0 -180
@@ -0,0 +1,223 @@
1
+ import { springs } from "@passui/tokens/motion"
2
+ import { useMediaQuery } from "../../hooks/use-media-query"
3
+ import { forwardRef, type HTMLAttributes, useLayoutEffect, useRef, useState } from "react"
4
+ import { useAnchoredPlacement } from "../../hooks/use-anchored-placement"
5
+ import { FLOATING_LAYER } from "../../hooks/use-dismiss"
6
+ import { useFloatingDismiss } from "../../hooks/use-floating-dismiss"
7
+ import { cn } from "../../lib/class-names"
8
+ import { registerFloatingLayer } from "../../lib/floating-layers"
9
+ import { concealMenuSource } from "../context-menu/conceal-menu-source"
10
+ import { menuSurfaceReveal } from "../context-menu/menu-reveal"
11
+
12
+ interface AnchoredSurfaceProps extends HTMLAttributes<HTMLDivElement> {
13
+ open: boolean
14
+ onExited: () => void
15
+ anchor: HTMLElement
16
+ width: number
17
+ needed: number
18
+ onClose: (restoreFocus: boolean) => void
19
+ contentClassName?: string
20
+ }
21
+
22
+ /** Shared material and lifetime for portaled pickers; their content owns selection. */
23
+ export const AnchoredSurface = forwardRef<HTMLDivElement, AnchoredSurfaceProps>(
24
+ function AnchoredSurface(
25
+ {
26
+ open: present,
27
+ onExited: remove,
28
+ anchor,
29
+ width,
30
+ needed,
31
+ onClose,
32
+ children,
33
+ className,
34
+ contentClassName,
35
+ ...props
36
+ },
37
+ forwardedRef
38
+ ) {
39
+ const root = useRef<HTMLDivElement>(null)
40
+ const reducedMotion = useMediaQuery("(prefers-reduced-motion: reduce)")
41
+ const material = useRef<HTMLDivElement>(null)
42
+ const content = useRef<HTMLDivElement>(null)
43
+ const animated = useRef<{ values: number[]; velocities: number[]; opacity: number } | null>(
44
+ null
45
+ )
46
+ const placement = useAnchoredPlacement(anchor, width, needed, true)
47
+ const [geometry, setGeometry] = useState<{
48
+ source: ReturnType<typeof menuSurfaceReveal>
49
+ width: number
50
+ height: number
51
+ radius: number
52
+ } | null>(null)
53
+
54
+ // biome-ignore lint/correctness/useExhaustiveDependencies: Placement can move without resizing; remeasure the source-relative reveal.
55
+ useLayoutEffect(() => {
56
+ const panel = root.current
57
+ if (!panel || !present) return
58
+ const measure = () => {
59
+ const target = panel.getBoundingClientRect()
60
+ const source = anchor.getBoundingClientRect()
61
+ const radius = Number.parseFloat(getComputedStyle(panel).borderTopLeftRadius) || 0
62
+ const reveal = menuSurfaceReveal(source, target)
63
+ setGeometry((current) =>
64
+ current &&
65
+ current.width === target.width &&
66
+ current.height === target.height &&
67
+ current.radius === radius &&
68
+ current.source.x === reveal.x &&
69
+ current.source.y === reveal.y &&
70
+ current.source.width === reveal.width &&
71
+ current.source.height === reveal.height
72
+ ? current
73
+ : { source: reveal, width: target.width, height: target.height, radius }
74
+ )
75
+ }
76
+ measure()
77
+ const observer = new ResizeObserver(measure)
78
+ observer.observe(panel)
79
+ return () => observer.disconnect()
80
+ }, [anchor, present, placement.left, placement.top, placement.bottom, placement.width])
81
+
82
+ useLayoutEffect(() => {
83
+ if (!root.current) return
84
+ const unregister = registerFloatingLayer(root.current, anchor)
85
+ const restore = concealMenuSource(anchor, false)
86
+ return () => {
87
+ unregister()
88
+ restore()
89
+ }
90
+ }, [anchor])
91
+
92
+ useLayoutEffect(() => {
93
+ if (!geometry || !material.current || !content.current) {
94
+ if (!present) remove?.()
95
+ return
96
+ }
97
+ const pane = material.current,
98
+ body = content.current
99
+ const source = [
100
+ geometry.source.x,
101
+ geometry.source.y,
102
+ geometry.source.width,
103
+ geometry.source.height,
104
+ geometry.source.borderRadius,
105
+ ]
106
+ const target = present
107
+ ? [0, 0, geometry.width, geometry.height, geometry.radius]
108
+ : source
109
+ const state = animated.current ?? {
110
+ values: [...source],
111
+ velocities: source.map(() => 0),
112
+ opacity: 0,
113
+ }
114
+ animated.current = state
115
+ let frame = 0,
116
+ previous = 0
117
+ const paint = () => {
118
+ const [x, y, width, height, radius] = state.values
119
+ pane.style.transform = `translate(${x}px, ${y}px)`
120
+ pane.style.width = `${Math.max(0, width)}px`
121
+ pane.style.height = `${Math.max(0, height)}px`
122
+ pane.style.borderRadius = `${Math.max(0, radius)}px`
123
+ body.style.opacity = String(state.opacity)
124
+ }
125
+ const tick = (now: number) => {
126
+ const dt = previous ? Math.min(0.032, (now - previous) / 1000) : 1 / 60
127
+ previous = now
128
+ const { stiffness, damping, mass } = springs.smooth
129
+ let resting = true
130
+ for (let index = 0; index < target.length; index++) {
131
+ state.velocities[index] +=
132
+ (((target[index] - state.values[index]) * stiffness -
133
+ state.velocities[index] * damping) /
134
+ mass) *
135
+ dt
136
+ state.values[index] += state.velocities[index] * dt
137
+ if (
138
+ Math.abs(target[index] - state.values[index]) > 0.05 ||
139
+ Math.abs(state.velocities[index]) > 0.05
140
+ )
141
+ resting = false
142
+ }
143
+ const progress = Math.max(
144
+ 0,
145
+ Math.min(
146
+ 1,
147
+ 1 -
148
+ Math.abs(geometry.height - state.values[3]) /
149
+ Math.max(1, Math.abs(geometry.height - source[3]))
150
+ )
151
+ )
152
+ const opacity = present ? Math.max(0, (progress - 0.25) / 0.75) : 0
153
+ state.opacity += (opacity - state.opacity) * (1 - Math.exp(-dt / 0.04))
154
+ paint()
155
+ if (resting && Math.abs(opacity - state.opacity) < 0.01) {
156
+ state.values = [...target]
157
+ state.velocities.fill(0)
158
+ state.opacity = present ? 1 : 0
159
+ paint()
160
+ if (!present) remove?.()
161
+ return
162
+ }
163
+ frame = requestAnimationFrame(tick)
164
+ }
165
+ if (reducedMotion) {
166
+ state.values = [...target]
167
+ state.velocities.fill(0)
168
+ state.opacity = present ? 1 : 0
169
+ paint()
170
+ if (!present) remove?.()
171
+ } else {
172
+ paint()
173
+ frame = requestAnimationFrame(tick)
174
+ }
175
+ return () => cancelAnimationFrame(frame)
176
+ }, [geometry, present, remove, reducedMotion])
177
+
178
+ useFloatingDismiss(root, anchor, (restore) => {
179
+ if (present) onClose(restore)
180
+ })
181
+
182
+ return (
183
+ <div
184
+ {...props}
185
+ ref={(node) => {
186
+ root.current = node
187
+ if (typeof forwardedRef === "function") forwardedRef(node)
188
+ else if (forwardedRef) forwardedRef.current = node
189
+ }}
190
+ {...{ [FLOATING_LAYER]: "" }}
191
+ inert={!present}
192
+ className={cn(
193
+ "fixed z-[80] isolate flex min-w-0 flex-col rounded-3xl outline-none",
194
+ !present && "pointer-events-none",
195
+ className
196
+ )}
197
+ style={{
198
+ left: placement.left,
199
+ top: placement.top,
200
+ bottom: placement.bottom,
201
+ width: placement.width,
202
+ maxHeight: placement.maxHeight ?? 420,
203
+ }}
204
+ >
205
+ <div
206
+ ref={material}
207
+ aria-hidden="true"
208
+ className="glass-menu pointer-events-none absolute top-0 left-0 -z-10"
209
+ />
210
+ <div
211
+ ref={content}
212
+ style={{ opacity: 0 }}
213
+ className={cn(
214
+ "flex min-h-0 flex-col overflow-y-auto overscroll-contain",
215
+ contentClassName
216
+ )}
217
+ >
218
+ {children}
219
+ </div>
220
+ </div>
221
+ )
222
+ }
223
+ )
@@ -0,0 +1,69 @@
1
+ import { type PlacementFrame, placeInViewport } from "../../lib/anchored-placement"
2
+
3
+ interface PanelRect {
4
+ left: number
5
+ top: number
6
+ width: number
7
+ height: number
8
+ }
9
+
10
+ interface AnchorRect {
11
+ top: number
12
+ bottom: number
13
+ }
14
+
15
+ export interface PopoverFit {
16
+ shiftX: number
17
+ shiftY: number
18
+ maxWidth: number
19
+ maxHeight?: number
20
+ above: boolean
21
+ }
22
+
23
+ /** Keep an absolutely positioned popover visible without scaling its contents. */
24
+ export function fitPopover(
25
+ panel: PanelRect,
26
+ anchor: AnchorRect | undefined,
27
+ frame: Pick<PlacementFrame, "viewport" | "edges">,
28
+ gap = 6,
29
+ origin: "top-left" | "top-right" = "top-left"
30
+ ): PopoverFit {
31
+ const { viewport, edges } = frame
32
+ const topEdge = edges.top
33
+ const bottomEdge = viewport.height - edges.bottom
34
+ const availableHeight = Math.max(0, bottomEdge - topEdge)
35
+ const placement = placeInViewport(
36
+ {
37
+ ...frame,
38
+ anchor: {
39
+ left: panel.left,
40
+ top: anchor?.top ?? panel.top,
41
+ bottom: anchor?.bottom ?? panel.top,
42
+ },
43
+ },
44
+ panel.width,
45
+ panel.height,
46
+ gap
47
+ )
48
+
49
+ const above = Boolean(anchor && panel.top + panel.height > bottomEdge && placement.above)
50
+ const aboveHeight = anchor ? Math.max(0, anchor.top - topEdge - gap) : 0
51
+ const visibleHeight = above
52
+ ? Math.min(panel.height, aboveHeight)
53
+ : Math.min(panel.height, availableHeight)
54
+ const desiredTop = above
55
+ ? (anchor?.top ?? panel.top) - gap - visibleHeight
56
+ : Math.max(topEdge, Math.min(panel.top, bottomEdge - visibleHeight))
57
+ const heightRoom = above ? aboveHeight : Math.max(0, bottomEdge - desiredTop)
58
+
59
+ return {
60
+ shiftX:
61
+ placement.left -
62
+ panel.left -
63
+ (origin === "top-right" ? panel.width - placement.width : 0),
64
+ shiftY: desiredTop - panel.top,
65
+ maxWidth: Math.max(0, viewport.width - edges.left - edges.right),
66
+ maxHeight: panel.height > heightRoom ? heightRoom : undefined,
67
+ above,
68
+ }
69
+ }
@@ -2,43 +2,41 @@ import {
2
2
  AnimatePresence,
3
3
  type HTMLMotionProps,
4
4
  motion,
5
+ useIsPresent,
5
6
  useReducedMotion,
6
7
  } from "motion/react"
7
- import { useLayoutEffect, useRef, useState } from "react"
8
+ import { type ReactNode, type RefObject, useLayoutEffect, useRef, useState } from "react"
9
+ import { concealMenuSource } from "../context-menu/conceal-menu-source"
10
+ import { menuSurfaceReveal } from "../context-menu/menu-reveal"
8
11
  import { cn } from "../../lib/class-names"
9
12
  import { screenEdges } from "../../lib/screen-edges"
10
- import { popoverMotion } from "../../motion/transitions"
13
+ import { floatingPanelMotion, spring } from "../../motion/transitions"
14
+ import { fitPopover, type PopoverFit } from "./popover-fit"
11
15
 
12
16
  export type PopoverOrigin = "top-left" | "top-right"
13
17
 
14
- export interface PopoverProps extends HTMLMotionProps<"div"> {
18
+ export interface PopoverProps extends Omit<HTMLMotionProps<"div">, "children"> {
15
19
  open: boolean
20
+ children?: ReactNode
16
21
  /** Which corner the popover grows from. */
17
22
  origin?: PopoverOrigin
18
- }
19
-
20
- interface PopoverFit {
21
- shift: number
22
- maxWidth?: number
23
- maxHeight?: number
23
+ /** Trigger whose shape the popover uses during its opening and closing motion. */
24
+ anchorRef?: RefObject<HTMLElement | null>
24
25
  }
25
26
 
26
27
  /**
27
28
  * A glass surface that springs open from its anchor. Position it with
28
29
  * `className` (it is absolutely positioned within a relative parent); it
29
- * moves itself back inside the screen if that would cross an edge, and
30
- * keeps checking while the viewport resizes or anything scrolls.
30
+ * flips above its relative parent when the bottom edge is short, and
31
+ * stays inside the visible viewport as it resizes or scrolls.
31
32
  */
32
33
  export function Popover({ open, ...props }: PopoverProps) {
33
- return (
34
- <AnimatePresence>
35
- {open && <OpenPopover {...props} />}
36
- </AnimatePresence>
37
- )
34
+ return <AnimatePresence>{open && <OpenPopover {...props} />}</AnimatePresence>
38
35
  }
39
36
 
40
37
  function OpenPopover({
41
38
  origin = "top-left",
39
+ anchorRef,
42
40
  className,
43
41
  style,
44
42
  children,
@@ -46,92 +44,240 @@ function OpenPopover({
46
44
  }: Omit<PopoverProps, "open">) {
47
45
  const ref = useRef<HTMLDivElement>(null)
48
46
  const reducedMotion = useReducedMotion()
49
- const [fit, setFit] = useState<PopoverFit>({ shift: 0 })
47
+ const present = useIsPresent()
48
+ const [settled, setSettled] = useState(false)
49
+ const [material, setMaterial] = useState({ width: 0, height: 0, radius: 0 })
50
+ const [fit, setFit] = useState<PopoverFit>({
51
+ shiftX: 0,
52
+ shiftY: 0,
53
+ maxWidth: 0,
54
+ above: false,
55
+ })
56
+ const [reveal, setReveal] = useState<ReturnType<typeof menuSurfaceReveal> | null>(null)
57
+ const popoverMotion = floatingPanelMotion(fit.above ? "above" : "below")
50
58
 
51
59
  useLayoutEffect(() => {
52
60
  const refit = () => {
53
61
  const element = ref.current
54
62
  if (!element) return
55
- // Where it sits once open: measured without the opening scale, before paint.
63
+ // Measure the authored position without the opening animation or
64
+ // our viewport correction. This prevents cumulative drift.
56
65
  const transform = element.style.transform
66
+ const translate = element.style.translate
67
+ const maxHeight = element.style.maxHeight
68
+ const maxWidth = element.style.maxWidth
57
69
  element.style.transform = "none"
70
+ element.style.translate = "none"
71
+ element.style.maxHeight = "none"
72
+ element.style.maxWidth = "none"
58
73
  const rect = element.getBoundingClientRect()
74
+ const neededHeight = Math.max(rect.height, element.scrollHeight)
75
+ const radius = Number.parseFloat(getComputedStyle(element).borderTopLeftRadius) || 0
76
+ setMaterial((current) =>
77
+ current.width === rect.width &&
78
+ current.height === neededHeight &&
79
+ current.radius === radius
80
+ ? current
81
+ : { width: rect.width, height: neededHeight, radius }
82
+ )
59
83
  element.style.transform = transform
84
+ element.style.translate = translate
85
+ element.style.maxHeight = maxHeight
86
+ element.style.maxWidth = maxWidth
87
+
88
+ const visualViewport = window.visualViewport
89
+ const offsetLeft = visualViewport?.offsetLeft ?? 0
90
+ const offsetTop = visualViewport?.offsetTop ?? 0
60
91
  const edges = screenEdges()
61
- const right = window.innerWidth - edges.right
62
- let shift = 0
63
- if (rect.right > right) shift = right - rect.right
64
- if (rect.left + shift < edges.left)
65
- shift = edges.left - rect.left
66
- const room =
67
- window.innerHeight - edges.bottom - rect.top
68
- setFit({
69
- shift,
70
- maxWidth:
71
- window.innerWidth -
72
- edges.left -
73
- edges.right,
74
- maxHeight:
75
- rect.height > room
76
- ? Math.max(room, 0)
77
- : undefined,
92
+ const offsetParent = element.offsetParent
93
+ const anchor =
94
+ offsetParent instanceof HTMLElement && offsetParent !== document.body
95
+ ? offsetParent.getBoundingClientRect()
96
+ : undefined
97
+ const trigger = anchorRef?.current?.getBoundingClientRect()
98
+ const target = {
99
+ left: trigger
100
+ ? origin === "top-right"
101
+ ? trigger.right - rect.width
102
+ : trigger.left
103
+ : rect.left,
104
+ top: trigger?.top ?? rect.top,
105
+ width: rect.width,
106
+ height: neededHeight,
107
+ }
108
+ const next = fitPopover(
109
+ target,
110
+ trigger ?? anchor,
111
+ {
112
+ viewport: {
113
+ width: offsetLeft + (visualViewport?.width ?? window.innerWidth),
114
+ height: offsetTop + (visualViewport?.height ?? window.innerHeight),
115
+ },
116
+ edges: {
117
+ ...edges,
118
+ left: offsetLeft + edges.left,
119
+ top: offsetTop + edges.top,
120
+ },
121
+ },
122
+ trigger ? -trigger.height : 6,
123
+ origin
124
+ )
125
+ next.shiftX += target.left - rect.left
126
+ next.shiftY += target.top - rect.top
127
+ setFit((current) => {
128
+ if (
129
+ current.shiftX === next.shiftX &&
130
+ current.shiftY === next.shiftY &&
131
+ current.maxWidth === next.maxWidth &&
132
+ current.maxHeight === next.maxHeight &&
133
+ current.above === next.above
134
+ )
135
+ return current
136
+ return next
78
137
  })
79
138
  }
80
139
  refit()
140
+ let frame = 0
141
+ const scheduleRefit = () => {
142
+ cancelAnimationFrame(frame)
143
+ frame = requestAnimationFrame(refit)
144
+ }
145
+ const observer = new ResizeObserver(scheduleRefit)
146
+ if (ref.current) observer.observe(ref.current)
81
147
  const viewport = window.visualViewport
82
- viewport?.addEventListener("resize", refit)
83
- viewport?.addEventListener("scroll", refit)
84
- window.addEventListener("resize", refit)
85
- window.addEventListener("scroll", refit, true)
148
+ viewport?.addEventListener("resize", scheduleRefit)
149
+ viewport?.addEventListener("scroll", scheduleRefit)
150
+ window.addEventListener("resize", scheduleRefit)
151
+ window.addEventListener("scroll", scheduleRefit, true)
86
152
  return () => {
87
- viewport?.removeEventListener("resize", refit)
88
- viewport?.removeEventListener("scroll", refit)
89
- window.removeEventListener("resize", refit)
90
- window.removeEventListener("scroll", refit, true)
153
+ observer.disconnect()
154
+ cancelAnimationFrame(frame)
155
+ viewport?.removeEventListener("resize", scheduleRefit)
156
+ viewport?.removeEventListener("scroll", scheduleRefit)
157
+ window.removeEventListener("resize", scheduleRefit)
158
+ window.removeEventListener("scroll", scheduleRefit, true)
91
159
  }
92
- }, [])
160
+ }, [origin, anchorRef])
161
+
162
+ useLayoutEffect(() => {
163
+ const source = anchorRef?.current
164
+ const panel = ref.current
165
+ if (!source || !panel) return
166
+ const sourceRect = source.getBoundingClientRect()
167
+ const panelRect = panel.getBoundingClientRect()
168
+ setReveal(
169
+ menuSurfaceReveal(
170
+ {
171
+ left: sourceRect.left,
172
+ top: sourceRect.top,
173
+ width: sourceRect.width,
174
+ height: sourceRect.height,
175
+ },
176
+ {
177
+ left: panelRect.left,
178
+ top: panelRect.top,
179
+ width: fit.maxWidth || panelRect.width,
180
+ height: fit.maxHeight
181
+ ? Math.min(fit.maxHeight, panelRect.height)
182
+ : panelRect.height,
183
+ }
184
+ )
185
+ )
186
+ const restoreSource = concealMenuSource(source, false)
187
+ return () => {
188
+ restoreSource()
189
+ }
190
+ }, [anchorRef, fit])
93
191
 
94
192
  return (
95
193
  <motion.div
96
194
  ref={ref}
97
- {...popoverMotion}
195
+ {...(!anchorRef && popoverMotion)}
98
196
  initial={
99
- reducedMotion
100
- ? { opacity: 0 }
101
- : popoverMotion.initial
197
+ anchorRef
198
+ ? { "--popover-content-opacity": reducedMotion ? 1 : 0 }
199
+ : reducedMotion
200
+ ? { opacity: 0 }
201
+ : popoverMotion.initial
102
202
  }
103
203
  animate={
104
- reducedMotion
105
- ? { opacity: 1 }
106
- : popoverMotion.animate
204
+ anchorRef
205
+ ? { "--popover-content-opacity": 1 }
206
+ : reducedMotion
207
+ ? { opacity: 1 }
208
+ : popoverMotion.animate
107
209
  }
108
210
  exit={
109
- reducedMotion
110
- ? { opacity: 0 }
111
- : popoverMotion.exit
211
+ anchorRef
212
+ ? {
213
+ "--popover-content-opacity": 0,
214
+ transition: { duration: reducedMotion ? 0 : 0.06 },
215
+ }
216
+ : reducedMotion
217
+ ? { opacity: 0 }
218
+ : popoverMotion.exit
112
219
  }
113
220
  transition={
114
- reducedMotion
115
- ? { duration: 0 }
116
- : popoverMotion.transition
221
+ anchorRef
222
+ ? reducedMotion
223
+ ? { duration: 0 }
224
+ : { duration: 0.16, delay: 0.06 }
225
+ : reducedMotion
226
+ ? { duration: 0 }
227
+ : popoverMotion.transition
117
228
  }
118
229
  style={{
119
230
  transformOrigin:
120
231
  origin === "top-left"
121
- ? "0% 0%"
122
- : "100% 0%",
123
- x: fit.shift,
124
- maxWidth: fit.maxWidth,
232
+ ? `0% ${fit.above ? "100%" : "0%"}`
233
+ : `100% ${fit.above ? "100%" : "0%"}`,
234
+ translate: `${fit.shiftX}px ${fit.shiftY}px`,
235
+ maxWidth: fit.maxWidth || undefined,
125
236
  maxHeight: fit.maxHeight,
126
- overflowY: fit.maxHeight ? "auto" : undefined,
237
+ overflowY:
238
+ fit.maxHeight !== undefined && (!anchorRef || (present && settled))
239
+ ? "auto"
240
+ : undefined,
127
241
  ...style,
128
242
  }}
129
243
  className={cn(
130
- "glass-menu absolute z-40 rounded-5xl",
244
+ anchorRef
245
+ ? "isolate [&>:not([data-popover-surface])]:opacity-[var(--popover-content-opacity)]"
246
+ : "glass-menu",
247
+ "absolute z-40 rounded-5xl outline-none",
131
248
  className
132
249
  )}
133
250
  {...props}
134
251
  >
252
+ {anchorRef && (
253
+ <motion.div
254
+ key={reveal ? "surface" : "measure"}
255
+ aria-hidden="true"
256
+ data-popover-surface=""
257
+ onAnimationComplete={() => {
258
+ if (reveal) setSettled(true)
259
+ }}
260
+ className="glass-menu pointer-events-none absolute top-0 left-0 -z-10 rounded-5xl"
261
+ style={{ width: "100%", height: "100%" }}
262
+ initial={reducedMotion || !reveal ? false : reveal}
263
+ animate={
264
+ reveal
265
+ ? {
266
+ x: 0,
267
+ y: 0,
268
+ width: material.width,
269
+ height: fit.maxHeight
270
+ ? Math.min(material.height, fit.maxHeight)
271
+ : material.height,
272
+ opacity: 1,
273
+ borderRadius: material.radius,
274
+ }
275
+ : undefined
276
+ }
277
+ exit={reducedMotion ? { opacity: 0 } : (reveal ?? { opacity: 0 })}
278
+ transition={reducedMotion ? { duration: 0 } : spring.smooth}
279
+ />
280
+ )}
135
281
  {children}
136
282
  </motion.div>
137
283
  )