@passui/react 0.1.44 → 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 -398
  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 -322
@@ -1,322 +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
- fluidOvershoot,
17
- spring,
18
- } from "../../motion/transitions"
19
- import { fitPopover, type PopoverFit } from "./popover-fit"
20
-
21
- export type PopoverOrigin = "top-left" | "top-right"
22
- export type PopoverSize = "sm" | "md"
23
-
24
- const surfaceRadius: Record<PopoverSize, string> = {
25
- sm: "rounded-3xl",
26
- md: "rounded-5xl",
27
- }
28
-
29
- export interface PopoverProps extends Omit<HTMLMotionProps<"div">, "children"> {
30
- open: boolean
31
- children?: ReactNode
32
- /** Which corner the popover grows from. */
33
- origin?: PopoverOrigin
34
- /** Trigger whose shape the popover uses during its opening and closing motion. */
35
- anchorRef?: RefObject<HTMLElement | null>
36
- /** Surface corner radius. @default "md" */
37
- size?: PopoverSize
38
- }
39
-
40
- /**
41
- * A glass surface that springs open from its anchor. Position it with
42
- * `className` (it is absolutely positioned within a relative parent); it
43
- * flips above its relative parent when the bottom edge is short, and
44
- * stays inside the visible viewport as it resizes or scrolls.
45
- */
46
- export function Popover({ open, ...props }: PopoverProps) {
47
- return <AnimatePresence>{open && <OpenPopover {...props} />}</AnimatePresence>
48
- }
49
-
50
- function OpenPopover({
51
- origin = "top-left",
52
- anchorRef,
53
- size = "md",
54
- className,
55
- style,
56
- children,
57
- ...props
58
- }: Omit<PopoverProps, "open">) {
59
- const ref = useRef<HTMLDivElement>(null)
60
- const reducedMotion = useReducedMotion()
61
- const present = useIsPresent()
62
- const [settled, setSettled] = useState(false)
63
- const [material, setMaterial] = useState({ width: 0, height: 0, radius: 0 })
64
- const [fit, setFit] = useState<PopoverFit>({
65
- shiftX: 0,
66
- shiftY: 0,
67
- maxWidth: 0,
68
- above: false,
69
- })
70
- const [reveal, setReveal] = useState<ReturnType<typeof menuSurfaceReveal> | null>(null)
71
- const popoverMotion = floatingPanelMotion(fit.above ? "above" : "below")
72
-
73
- // For anchored popovers, the surface morphs from the trigger via
74
- // menuSurfaceReveal. For non-anchored popovers, we use scale + the
75
- // fluid overshoot spring so the panel grows from the origin corner
76
- // with a physical bounce — Apple's matched-geometry feel.
77
-
78
- useLayoutEffect(() => {
79
- const refit = () => {
80
- const element = ref.current
81
- if (!element) return
82
- // Measure the authored position without the opening animation or
83
- // our viewport correction. This prevents cumulative drift.
84
- const transform = element.style.transform
85
- const translate = element.style.translate
86
- const maxHeight = element.style.maxHeight
87
- const maxWidth = element.style.maxWidth
88
- element.style.transform = "none"
89
- element.style.translate = "none"
90
- element.style.maxHeight = "none"
91
- element.style.maxWidth = "none"
92
- const rect = element.getBoundingClientRect()
93
- const neededHeight = Math.max(rect.height, element.scrollHeight)
94
- const radius = Number.parseFloat(getComputedStyle(element).borderTopLeftRadius) || 0
95
- setMaterial((current) =>
96
- current.width === rect.width &&
97
- current.height === neededHeight &&
98
- current.radius === radius
99
- ? current
100
- : { width: rect.width, height: neededHeight, radius }
101
- )
102
- element.style.transform = transform
103
- element.style.translate = translate
104
- element.style.maxHeight = maxHeight
105
- element.style.maxWidth = maxWidth
106
-
107
- const visualViewport = window.visualViewport
108
- const offsetLeft = visualViewport?.offsetLeft ?? 0
109
- const offsetTop = visualViewport?.offsetTop ?? 0
110
- const edges = screenEdges()
111
- const offsetParent = element.offsetParent
112
- const anchor =
113
- offsetParent instanceof HTMLElement && offsetParent !== document.body
114
- ? offsetParent.getBoundingClientRect()
115
- : undefined
116
- const trigger = anchorRef?.current?.getBoundingClientRect()
117
- const target = {
118
- left: trigger
119
- ? origin === "top-right"
120
- ? trigger.right - rect.width
121
- : trigger.left
122
- : rect.left,
123
- top: trigger?.top ?? rect.top,
124
- width: rect.width,
125
- height: neededHeight,
126
- }
127
- const next = fitPopover(
128
- target,
129
- trigger ?? anchor,
130
- {
131
- viewport: {
132
- width: offsetLeft + (visualViewport?.width ?? window.innerWidth),
133
- height: offsetTop + (visualViewport?.height ?? window.innerHeight),
134
- },
135
- edges: {
136
- ...edges,
137
- left: offsetLeft + edges.left,
138
- top: offsetTop + edges.top,
139
- },
140
- },
141
- trigger ? -trigger.height : 6,
142
- origin
143
- )
144
- next.shiftX += target.left - rect.left
145
- next.shiftY += target.top - rect.top
146
- setFit((current) => {
147
- if (
148
- current.shiftX === next.shiftX &&
149
- current.shiftY === next.shiftY &&
150
- current.maxWidth === next.maxWidth &&
151
- current.maxHeight === next.maxHeight &&
152
- current.above === next.above
153
- )
154
- return current
155
- return next
156
- })
157
- }
158
- refit()
159
- let frame = 0
160
- const scheduleRefit = () => {
161
- cancelAnimationFrame(frame)
162
- frame = requestAnimationFrame(refit)
163
- }
164
- const observer = new ResizeObserver(scheduleRefit)
165
- if (ref.current) observer.observe(ref.current)
166
- const viewport = window.visualViewport
167
- viewport?.addEventListener("resize", scheduleRefit)
168
- viewport?.addEventListener("scroll", scheduleRefit)
169
- window.addEventListener("resize", scheduleRefit)
170
- window.addEventListener("scroll", scheduleRefit, true)
171
- return () => {
172
- observer.disconnect()
173
- cancelAnimationFrame(frame)
174
- viewport?.removeEventListener("resize", scheduleRefit)
175
- viewport?.removeEventListener("scroll", scheduleRefit)
176
- window.removeEventListener("resize", scheduleRefit)
177
- window.removeEventListener("scroll", scheduleRefit, true)
178
- }
179
- }, [origin, anchorRef])
180
-
181
- useLayoutEffect(() => {
182
- const source = anchorRef?.current
183
- const panel = ref.current
184
- if (!source || !panel) return
185
- const sourceRect = source.getBoundingClientRect()
186
- const panelRect = panel.getBoundingClientRect()
187
- setReveal(
188
- menuSurfaceReveal(
189
- {
190
- left: sourceRect.left,
191
- top: sourceRect.top,
192
- width: sourceRect.width,
193
- height: sourceRect.height,
194
- },
195
- {
196
- left: panelRect.left,
197
- top: panelRect.top,
198
- width: fit.maxWidth || panelRect.width,
199
- height: fit.maxHeight
200
- ? Math.min(fit.maxHeight, panelRect.height)
201
- : panelRect.height,
202
- }
203
- )
204
- )
205
- }, [anchorRef, fit])
206
-
207
- useLayoutEffect(() => {
208
- const source = anchorRef?.current
209
- if (!source || !present) return
210
- const restoreSource = concealMenuSource(source, false)
211
- return () => {
212
- restoreSource()
213
- }
214
- }, [anchorRef, present])
215
-
216
- return (
217
- <motion.div
218
- ref={ref}
219
- {...(!anchorRef && popoverMotion)}
220
- initial={
221
- anchorRef
222
- ? { "--popover-content-opacity": reducedMotion ? 1 : 0 }
223
- : reducedMotion
224
- ? { opacity: 0 }
225
- : popoverMotion.initial
226
- }
227
- animate={
228
- anchorRef
229
- ? { "--popover-content-opacity": 1 }
230
- : reducedMotion
231
- ? { opacity: 1 }
232
- : popoverMotion.animate
233
- }
234
- exit={
235
- anchorRef
236
- ? {
237
- "--popover-content-opacity": 0,
238
- transition: { duration: reducedMotion ? 0 : 0.06 },
239
- }
240
- : reducedMotion
241
- ? { opacity: 0 }
242
- : popoverMotion.exit
243
- }
244
- transition={
245
- anchorRef
246
- ? reducedMotion
247
- ? { duration: 0 }
248
- : { duration: 0.16, delay: 0.06 }
249
- : reducedMotion
250
- ? { duration: 0 }
251
- : popoverMotion.transition
252
- }
253
- style={{
254
- transformOrigin:
255
- origin === "top-left"
256
- ? `0% ${fit.above ? "100%" : "0%"}`
257
- : `100% ${fit.above ? "100%" : "0%"}`,
258
- translate: `${fit.shiftX}px ${fit.shiftY}px`,
259
- maxWidth: fit.maxWidth || undefined,
260
- maxHeight: fit.maxHeight,
261
- overflowY:
262
- fit.maxHeight !== undefined && (!anchorRef || (present && settled))
263
- ? "auto"
264
- : undefined,
265
- ...style,
266
- }}
267
- className={cn(
268
- anchorRef
269
- ? "isolate [&>:not([data-popover-surface])]:opacity-[var(--popover-content-opacity)]"
270
- : "glass-menu",
271
- "absolute z-40 outline-none",
272
- surfaceRadius[size],
273
- className
274
- )}
275
- {...props}
276
- >
277
- {anchorRef && (
278
- <motion.div
279
- key={reveal ? "surface" : "measure"}
280
- aria-hidden="true"
281
- data-popover-surface=""
282
- onAnimationComplete={() => {
283
- if (reveal) setSettled(true)
284
- }}
285
- className={cn(
286
- "glass-menu pointer-events-none absolute top-0 left-0 -z-10",
287
- surfaceRadius[size]
288
- )}
289
- style={{ width: "100%", height: "100%" }}
290
- initial={reducedMotion || !reveal ? { opacity: 0 } : reveal}
291
- animate={
292
- reveal
293
- ? {
294
- x: 0,
295
- y: 0,
296
- width: material.width,
297
- height: fit.maxHeight
298
- ? Math.min(material.height, fit.maxHeight)
299
- : material.height,
300
- opacity: 1,
301
- borderRadius: material.radius,
302
- }
303
- : undefined
304
- }
305
- exit={reducedMotion || !reveal ? { opacity: 0 } : menuSurfaceExit(reveal)}
306
- transition={
307
- reducedMotion
308
- ? { duration: 0 }
309
- : { ...fluidOvershoot, opacity: { duration: 0.16 } }
310
- }
311
- />
312
- )}
313
- <motion.div
314
- initial={reducedMotion ? false : anchorRef ? { opacity: 0 } : undefined}
315
- animate={reducedMotion ? undefined : anchorRef ? { opacity: 1 } : undefined}
316
- transition={reducedMotion ? { duration: 0 } : { duration: 0.16, delay: 0.06 }}
317
- >
318
- {children}
319
- </motion.div>
320
- </motion.div>
321
- )
322
- }