@passui/react 0.1.45 → 0.1.46

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 (140) hide show
  1. package/README.md +57 -46
  2. package/dist/types/src/components/accordion/accordion.d.ts +1 -1
  3. package/dist/types/src/components/breadcrumb/breadcrumb.d.ts +1 -1
  4. package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +1 -1
  5. package/dist/types/src/components/popover/anchored-surface.d.ts +5 -1
  6. package/dist/types/src/components/popover/index.d.ts +41 -0
  7. package/dist/types/src/components/popover/popover-content.d.ts +32 -0
  8. package/dist/types/src/components/popover/popover-root.d.ts +22 -0
  9. package/dist/types/src/components/popover/popover-trigger.d.ts +23 -0
  10. package/dist/types/src/components/stepper/rolling-digit.d.ts +1 -1
  11. package/dist/types/src/components/table/table.d.ts +1 -1
  12. package/dist/types/src/components/view-controller/view-controller.d.ts +2 -2
  13. package/dist/types/src/index.d.ts +1 -1
  14. package/dist/types/src/machines/popover.machine.d.ts +30 -0
  15. package/package.json +307 -307
  16. package/src/appearance/index.ts +2 -2
  17. package/src/appearance/platform.tsx +76 -60
  18. package/src/appearance/theme.tsx +409 -377
  19. package/src/components/accordion/accordion.tsx +58 -49
  20. package/src/components/ambient/ambient.tsx +25 -25
  21. package/src/components/ambient/index.ts +1 -1
  22. package/src/components/aspect-ratio/aspect-ratio.tsx +21 -16
  23. package/src/components/breadcrumb/breadcrumb.tsx +63 -57
  24. package/src/components/button/button-styles.ts +39 -32
  25. package/src/components/button/button.tsx +91 -84
  26. package/src/components/button/icon-button.tsx +27 -25
  27. package/src/components/button/pending-spinner.tsx +8 -8
  28. package/src/components/button/use-pending-indicator.ts +11 -11
  29. package/src/components/chip/chip.tsx +35 -30
  30. package/src/components/code-block/code-block.tsx +40 -39
  31. package/src/components/combo-box/combo-box.tsx +5 -5
  32. package/src/components/command/command.tsx +124 -94
  33. package/src/components/compact-date-picker/calendar-month.ts +75 -53
  34. package/src/components/compact-date-picker/compact-date-picker.tsx +308 -289
  35. package/src/components/compact-time-picker/compact-time-picker.tsx +288 -281
  36. package/src/components/compact-time-picker/time-value.ts +32 -29
  37. package/src/components/content-unavailable-view/content-unavailable-view.tsx +64 -48
  38. package/src/components/content-view/content-view.tsx +168 -159
  39. package/src/components/content-view/index.ts +1 -1
  40. package/src/components/context-menu/conceal-menu-source.ts +25 -25
  41. package/src/components/context-menu/context-menu-host.tsx +439 -402
  42. package/src/components/context-menu/context-menu-store.ts +125 -123
  43. package/src/components/context-menu/menu-navigation.ts +25 -18
  44. package/src/components/context-menu/menu-position.ts +33 -29
  45. package/src/components/context-menu/menu-reveal.ts +32 -32
  46. package/src/components/context-menu/use-context-menu.ts +63 -56
  47. package/src/components/conversation/conversation.tsx +265 -263
  48. package/src/components/conversation/index.ts +1 -1
  49. package/src/components/date-picker/date-picker.tsx +95 -94
  50. package/src/components/date-picker/date-value.ts +20 -10
  51. package/src/components/dialog/dialog-host.tsx +105 -103
  52. package/src/components/dialog/dialog-store.ts +37 -36
  53. package/src/components/dialog/dialog.tsx +192 -179
  54. package/src/components/dialog/index.ts +1 -1
  55. package/src/components/disclosure-group/disclosure-group.tsx +93 -86
  56. package/src/components/divider/divider.tsx +24 -22
  57. package/src/components/inline-disclosure/inline-disclosure.tsx +40 -36
  58. package/src/components/keyboard-shortcut/keyboard-shortcut.tsx +23 -19
  59. package/src/components/labeled-content/labeled-content.tsx +68 -68
  60. package/src/components/locale-switcher/index.ts +1 -1
  61. package/src/components/locale-switcher/locale-switcher.tsx +279 -251
  62. package/src/components/menu/menu.tsx +75 -58
  63. package/src/components/morph/index.ts +2 -2
  64. package/src/components/morph/morph.tsx +227 -201
  65. package/src/components/morph/use-morph-disclosure.ts +19 -19
  66. package/src/components/one-time-code/one-time-code.tsx +216 -200
  67. package/src/components/picker/picker-trigger.ts +16 -13
  68. package/src/components/picker/picker.tsx +371 -345
  69. package/src/components/popover/anchored-surface.tsx +253 -229
  70. package/src/components/popover/index.ts +50 -0
  71. package/src/components/popover/popover-content.tsx +334 -0
  72. package/src/components/popover/popover-fit.ts +58 -53
  73. package/src/components/popover/popover-root.tsx +97 -0
  74. package/src/components/popover/popover-trigger.tsx +71 -0
  75. package/src/components/profile-image/profile-image.tsx +80 -64
  76. package/src/components/progress-view/progress-view.tsx +61 -59
  77. package/src/components/progress-view/use-liquid-progress.ts +38 -38
  78. package/src/components/radio-group/radio-group.tsx +71 -68
  79. package/src/components/search-field/expanding-search-field.tsx +191 -177
  80. package/src/components/search-field/search-field.tsx +59 -50
  81. package/src/components/search-list/search-list.tsx +246 -236
  82. package/src/components/section/section.tsx +58 -58
  83. package/src/components/secure-field/secure-field.tsx +3 -3
  84. package/src/components/segmented-control/segmented-control.tsx +136 -136
  85. package/src/components/sheet/modal-environment.ts +71 -64
  86. package/src/components/sheet/sheet-portal.tsx +58 -53
  87. package/src/components/sheet/sheet.tsx +146 -141
  88. package/src/components/sheet/use-sheet-focus.ts +97 -82
  89. package/src/components/sidebar/sidebar.tsx +78 -78
  90. package/src/components/skeleton/skeleton.tsx +30 -21
  91. package/src/components/slider/slider.tsx +113 -104
  92. package/src/components/slosh-slider/liquid-step.ts +32 -31
  93. package/src/components/slosh-slider/slosh-slider.tsx +265 -228
  94. package/src/components/stat-tile/index.ts +1 -1
  95. package/src/components/stat-tile/stat-tile.tsx +79 -68
  96. package/src/components/status-indicator/status-indicator.tsx +40 -37
  97. package/src/components/stepper/rolling-digit.tsx +82 -68
  98. package/src/components/stepper/stepper.tsx +122 -113
  99. package/src/components/swatch-picker/swatch-picker.tsx +120 -120
  100. package/src/components/tab-bar/tab-bar.tsx +149 -148
  101. package/src/components/tab-view/tab-view.tsx +140 -137
  102. package/src/components/table/table.tsx +117 -98
  103. package/src/components/text-editor/text-editor.tsx +34 -29
  104. package/src/components/text-field/text-field.tsx +182 -180
  105. package/src/components/toast/toast-store.ts +127 -115
  106. package/src/components/toast/toaster.tsx +361 -347
  107. package/src/components/toggle/toggle.tsx +297 -282
  108. package/src/components/tooltip/tooltip-host.tsx +157 -150
  109. package/src/components/view-controller/index.ts +1 -1
  110. package/src/components/view-controller/view-controller.tsx +64 -53
  111. package/src/components/wake-slider/wake-slider.tsx +220 -205
  112. package/src/hooks/scroll/minimize-decision.ts +11 -7
  113. package/src/hooks/use-anchored-disclosure.ts +19 -19
  114. package/src/hooks/use-anchored-placement.ts +29 -25
  115. package/src/hooks/use-dismiss.ts +33 -29
  116. package/src/hooks/use-floating-dismiss.ts +24 -22
  117. package/src/hooks/use-media-query.ts +67 -60
  118. package/src/hooks/use-minimize-on-scroll.ts +69 -60
  119. package/src/hooks/use-visual-viewport.ts +63 -63
  120. package/src/hooks/viewport/types.ts +16 -16
  121. package/src/hooks/viewport/viewport-metrics.ts +16 -10
  122. package/src/icons/icons.tsx +440 -328
  123. package/src/index.ts +91 -91
  124. package/src/lib/anchored-placement.ts +70 -65
  125. package/src/lib/class-names.ts +14 -13
  126. package/src/lib/clipboard.ts +8 -7
  127. package/src/lib/date.ts +61 -60
  128. package/src/lib/floating-layers.ts +39 -24
  129. package/src/lib/haptics.ts +10 -10
  130. package/src/lib/language.ts +9 -9
  131. package/src/lib/range-value.ts +27 -21
  132. package/src/lib/screen-edges.ts +33 -30
  133. package/src/lib/shapes.ts +38 -34
  134. package/src/machines/popover.machine.ts +51 -0
  135. package/src/motion/transitions.ts +46 -43
  136. package/src/styles/code-block.css +69 -43
  137. package/src/styles/motion-controls.css +393 -191
  138. package/src/tokens.ts +1 -1
  139. package/dist/types/src/components/popover/popover.d.ts +0 -21
  140. package/src/components/popover/popover.tsx +0 -334
@@ -1,334 +0,0 @@
1
- import {
2
- AnimatePresence,
3
- type HTMLMotionProps,
4
- motion,
5
- useIsPresent,
6
- useReducedMotion,
7
- } from "motion/react"
8
- import { type ReactNode, type RefObject, useLayoutEffect, useRef, useState } from "react"
9
- import { concealMenuSource } from "../context-menu/conceal-menu-source"
10
- import { menuSurfaceExit, menuSurfaceReveal } from "../context-menu/menu-reveal"
11
- import { cn } from "../../lib/class-names"
12
- import { screenEdges } from "../../lib/screen-edges"
13
- import {
14
- contentCrossfade,
15
- floatingPanelMotion,
16
- fluidCollapse,
17
- fluidOvershoot,
18
- spring,
19
- } from "../../motion/transitions"
20
- import { fitPopover, type PopoverFit } from "./popover-fit"
21
-
22
- export type PopoverOrigin = "top-left" | "top-right"
23
- export type PopoverSize = "sm" | "md"
24
-
25
- const surfaceRadius: Record<PopoverSize, string> = {
26
- sm: "rounded-3xl",
27
- md: "rounded-5xl",
28
- }
29
-
30
- export interface PopoverProps extends Omit<HTMLMotionProps<"div">, "children"> {
31
- open: boolean
32
- children?: ReactNode
33
- /** Which corner the popover grows from. */
34
- origin?: PopoverOrigin
35
- /** Trigger whose shape the popover uses during its opening and closing motion. */
36
- anchorRef?: RefObject<HTMLElement | null>
37
- /** Surface corner radius. @default "md" */
38
- size?: PopoverSize
39
- }
40
-
41
- /**
42
- * A glass surface that springs open from its anchor. Position it with
43
- * `className` (it is absolutely positioned within a relative parent); it
44
- * flips above its relative parent when the bottom edge is short, and
45
- * stays inside the visible viewport as it resizes or scrolls.
46
- */
47
- export function Popover({ open, ...props }: PopoverProps) {
48
- return <AnimatePresence>{open && <OpenPopover {...props} />}</AnimatePresence>
49
- }
50
-
51
- function OpenPopover({
52
- origin = "top-left",
53
- anchorRef,
54
- size = "md",
55
- className,
56
- style,
57
- children,
58
- ...props
59
- }: Omit<PopoverProps, "open">) {
60
- const ref = useRef<HTMLDivElement>(null)
61
- const reducedMotion = useReducedMotion()
62
- const present = useIsPresent()
63
- const [settled, setSettled] = useState(false)
64
- const [material, setMaterial] = useState({ width: 0, height: 0, radius: 0 })
65
- const [fit, setFit] = useState<PopoverFit>({
66
- shiftX: 0,
67
- shiftY: 0,
68
- maxWidth: 0,
69
- above: false,
70
- })
71
- const [reveal, setReveal] = useState<ReturnType<typeof menuSurfaceReveal> | null>(null)
72
- const popoverMotion = floatingPanelMotion(fit.above ? "above" : "below")
73
-
74
- // For anchored popovers, the surface morphs from the trigger via
75
- // menuSurfaceReveal. For non-anchored popovers, we use scale + the
76
- // fluid overshoot spring so the panel grows from the origin corner
77
- // with a physical bounce — Apple's matched-geometry feel.
78
-
79
- useLayoutEffect(() => {
80
- const refit = () => {
81
- const element = ref.current
82
- if (!element) return
83
- // Measure the authored position without the opening animation or
84
- // our viewport correction. This prevents cumulative drift.
85
- const transform = element.style.transform
86
- const translate = element.style.translate
87
- const maxHeight = element.style.maxHeight
88
- const maxWidth = element.style.maxWidth
89
- element.style.transform = "none"
90
- element.style.translate = "none"
91
- element.style.maxHeight = "none"
92
- element.style.maxWidth = "none"
93
- const rect = element.getBoundingClientRect()
94
- const neededHeight = Math.max(rect.height, element.scrollHeight)
95
- const radius = Number.parseFloat(getComputedStyle(element).borderTopLeftRadius) || 0
96
- setMaterial((current) =>
97
- current.width === rect.width &&
98
- current.height === neededHeight &&
99
- current.radius === radius
100
- ? current
101
- : { width: rect.width, height: neededHeight, radius }
102
- )
103
- element.style.transform = transform
104
- element.style.translate = translate
105
- element.style.maxHeight = maxHeight
106
- element.style.maxWidth = maxWidth
107
-
108
- const visualViewport = window.visualViewport
109
- const offsetLeft = visualViewport?.offsetLeft ?? 0
110
- const offsetTop = visualViewport?.offsetTop ?? 0
111
- const edges = screenEdges()
112
- const offsetParent = element.offsetParent
113
- const anchor =
114
- offsetParent instanceof HTMLElement && offsetParent !== document.body
115
- ? offsetParent.getBoundingClientRect()
116
- : undefined
117
- const trigger = anchorRef?.current?.getBoundingClientRect()
118
- const target = {
119
- left: trigger
120
- ? origin === "top-right"
121
- ? trigger.right - rect.width
122
- : trigger.left
123
- : rect.left,
124
- top: trigger?.top ?? rect.top,
125
- width: rect.width,
126
- height: neededHeight,
127
- }
128
- const next = fitPopover(
129
- target,
130
- trigger ?? anchor,
131
- {
132
- viewport: {
133
- width: offsetLeft + (visualViewport?.width ?? window.innerWidth),
134
- height: offsetTop + (visualViewport?.height ?? window.innerHeight),
135
- },
136
- edges: {
137
- ...edges,
138
- left: offsetLeft + edges.left,
139
- top: offsetTop + edges.top,
140
- },
141
- },
142
- trigger ? -trigger.height : 6,
143
- origin
144
- )
145
- next.shiftX += target.left - rect.left
146
- next.shiftY += target.top - rect.top
147
- setFit((current) => {
148
- if (
149
- current.shiftX === next.shiftX &&
150
- current.shiftY === next.shiftY &&
151
- current.maxWidth === next.maxWidth &&
152
- current.maxHeight === next.maxHeight &&
153
- current.above === next.above
154
- )
155
- return current
156
- return next
157
- })
158
- }
159
- refit()
160
- let frame = 0
161
- const scheduleRefit = () => {
162
- cancelAnimationFrame(frame)
163
- frame = requestAnimationFrame(refit)
164
- }
165
- const observer = new ResizeObserver(scheduleRefit)
166
- if (ref.current) observer.observe(ref.current)
167
- const viewport = window.visualViewport
168
- viewport?.addEventListener("resize", scheduleRefit)
169
- viewport?.addEventListener("scroll", scheduleRefit)
170
- window.addEventListener("resize", scheduleRefit)
171
- window.addEventListener("scroll", scheduleRefit, true)
172
- return () => {
173
- observer.disconnect()
174
- cancelAnimationFrame(frame)
175
- viewport?.removeEventListener("resize", scheduleRefit)
176
- viewport?.removeEventListener("scroll", scheduleRefit)
177
- window.removeEventListener("resize", scheduleRefit)
178
- window.removeEventListener("scroll", scheduleRefit, true)
179
- }
180
- }, [origin, anchorRef])
181
-
182
- useLayoutEffect(() => {
183
- const source = anchorRef?.current
184
- const panel = ref.current
185
- if (!source || !panel) return
186
- const sourceRect = source.getBoundingClientRect()
187
- const panelRect = panel.getBoundingClientRect()
188
- setReveal(
189
- menuSurfaceReveal(
190
- {
191
- left: sourceRect.left,
192
- top: sourceRect.top,
193
- width: sourceRect.width,
194
- height: sourceRect.height,
195
- },
196
- {
197
- left: panelRect.left,
198
- top: panelRect.top,
199
- width: fit.maxWidth || panelRect.width,
200
- height: fit.maxHeight
201
- ? Math.min(fit.maxHeight, panelRect.height)
202
- : panelRect.height,
203
- }
204
- )
205
- )
206
- }, [anchorRef, fit])
207
-
208
- useLayoutEffect(() => {
209
- const source = anchorRef?.current
210
- if (!source || !present) return
211
- const restoreSource = concealMenuSource(source, false)
212
- return () => {
213
- restoreSource()
214
- }
215
- }, [anchorRef, present])
216
-
217
- return (
218
- <motion.div
219
- ref={ref}
220
- {...(!anchorRef && popoverMotion)}
221
- initial={
222
- anchorRef
223
- ? { "--popover-content-opacity": reducedMotion ? 1 : 0 }
224
- : reducedMotion
225
- ? { opacity: 0 }
226
- : popoverMotion.initial
227
- }
228
- animate={
229
- anchorRef
230
- ? { "--popover-content-opacity": 1 }
231
- : reducedMotion
232
- ? { opacity: 1 }
233
- : popoverMotion.animate
234
- }
235
- exit={
236
- anchorRef
237
- ? {
238
- "--popover-content-opacity": 0,
239
- transition: { duration: reducedMotion ? 0 : 0.06 },
240
- }
241
- : reducedMotion
242
- ? { opacity: 0 }
243
- : popoverMotion.exit
244
- }
245
- transition={
246
- anchorRef
247
- ? reducedMotion
248
- ? { duration: 0 }
249
- : { duration: 0.16, delay: 0.06 }
250
- : reducedMotion
251
- ? { duration: 0 }
252
- : popoverMotion.transition
253
- }
254
- style={{
255
- transformOrigin:
256
- origin === "top-left"
257
- ? `0% ${fit.above ? "100%" : "0%"}`
258
- : `100% ${fit.above ? "100%" : "0%"}`,
259
- translate: `${fit.shiftX}px ${fit.shiftY}px`,
260
- maxWidth: fit.maxWidth || undefined,
261
- maxHeight: fit.maxHeight,
262
- overflowY:
263
- fit.maxHeight !== undefined && (!anchorRef || (present && settled))
264
- ? "auto"
265
- : undefined,
266
- ...style,
267
- }}
268
- className={cn(
269
- anchorRef
270
- ? "isolate [&>:not([data-popover-surface])]:opacity-[var(--popover-content-opacity)]"
271
- : "glass-menu",
272
- "absolute z-40 outline-none",
273
- surfaceRadius[size],
274
- className
275
- )}
276
- {...props}
277
- >
278
- {anchorRef && (
279
- <motion.div
280
- key={reveal ? "surface" : "measure"}
281
- aria-hidden="true"
282
- data-popover-surface=""
283
- onAnimationComplete={() => {
284
- if (reveal) setSettled(true)
285
- }}
286
- className={cn(
287
- "glass-menu pointer-events-none absolute top-0 left-0 -z-10",
288
- surfaceRadius[size]
289
- )}
290
- style={{ width: "100%", height: "100%" }}
291
- initial={reducedMotion || !reveal ? { opacity: 0 } : reveal}
292
- animate={
293
- reveal
294
- ? {
295
- x: 0,
296
- y: 0,
297
- width: material.width,
298
- height: fit.maxHeight
299
- ? Math.min(material.height, fit.maxHeight)
300
- : material.height,
301
- opacity: 1,
302
- borderRadius: material.radius,
303
- }
304
- : undefined
305
- }
306
- exit={
307
- reducedMotion || !reveal
308
- ? { opacity: 0 }
309
- : { ...menuSurfaceExit(reveal), transition: fluidCollapse }
310
- }
311
- transition={
312
- reducedMotion
313
- ? { duration: 0 }
314
- : { ...fluidOvershoot, opacity: { duration: 0.16 } }
315
- }
316
- />
317
- )}
318
- <motion.div
319
- initial={reducedMotion ? false : anchorRef ? { opacity: 0 } : undefined}
320
- animate={reducedMotion ? undefined : anchorRef ? { opacity: 1 } : undefined}
321
- exit={
322
- reducedMotion
323
- ? undefined
324
- : anchorRef
325
- ? { opacity: 0, transition: { duration: 0.12 } }
326
- : undefined
327
- }
328
- transition={reducedMotion ? { duration: 0 } : { duration: 0.16, delay: 0.06 }}
329
- >
330
- {children}
331
- </motion.div>
332
- </motion.div>
333
- )
334
- }