@avenue-ticketing/ui 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/avatar.d.ts +42 -0
- package/dist/react/avatar.js +159 -0
- package/dist/react/avatar.js.map +1 -0
- package/dist/react/badge.d.ts +12 -0
- package/dist/react/badge.js +35 -1
- package/dist/react/badge.js.map +1 -1
- package/dist/react/button.d.ts +1 -1
- package/dist/react/button.js +3 -3
- package/dist/react/button.js.map +1 -1
- package/dist/react/calendar.d.ts +13 -0
- package/dist/react/calendar.js +4639 -0
- package/dist/react/calendar.js.map +1 -0
- package/dist/react/card.d.ts +11 -0
- package/dist/react/card.js +113 -0
- package/dist/react/card.js.map +1 -0
- package/dist/react/checkbox.d.ts +11 -0
- package/dist/react/checkbox.js +129 -0
- package/dist/react/checkbox.js.map +1 -0
- package/dist/react/datetime-picker.d.ts +21 -0
- package/dist/react/datetime-picker.js +6124 -0
- package/dist/react/datetime-picker.js.map +1 -0
- package/dist/react/dialog.js +1 -1
- package/dist/react/dialog.js.map +1 -1
- package/dist/react/dropdown.d.ts +34 -9
- package/dist/react/dropdown.js +295 -144
- package/dist/react/dropdown.js.map +1 -1
- package/dist/react/input.d.ts +7 -0
- package/dist/react/input.js +15 -2
- package/dist/react/input.js.map +1 -1
- package/dist/react/pagination.d.ts +28 -0
- package/dist/react/pagination.js +262 -0
- package/dist/react/pagination.js.map +1 -0
- package/dist/react/popover.d.ts +76 -0
- package/dist/react/popover.js +564 -0
- package/dist/react/popover.js.map +1 -0
- package/dist/react/scroll-header.js +13 -1
- package/dist/react/scroll-header.js.map +1 -1
- package/dist/react/scroll-wheel.d.ts +45 -0
- package/dist/react/scroll-wheel.js +557 -0
- package/dist/react/scroll-wheel.js.map +1 -0
- package/dist/react/select.d.ts +62 -0
- package/dist/react/select.js +889 -0
- package/dist/react/select.js.map +1 -0
- package/dist/react/sheet.js +1 -1
- package/dist/react/sheet.js.map +1 -1
- package/dist/react/switch.d.ts +38 -0
- package/dist/react/switch.js +117 -0
- package/dist/react/switch.js.map +1 -0
- package/dist/react/table-pagination.d.ts +15 -0
- package/dist/react/table-pagination.js +1153 -0
- package/dist/react/table-pagination.js.map +1 -0
- package/dist/react/table-view/column-menu.d.ts +15 -0
- package/dist/react/table-view/column-menu.js +955 -0
- package/dist/react/table-view/column-menu.js.map +1 -0
- package/dist/react/table-view/index.d.ts +70 -0
- package/dist/react/table-view/index.js +2190 -0
- package/dist/react/table-view/index.js.map +1 -0
- package/dist/react/table.d.ts +86 -0
- package/dist/react/table.js +414 -0
- package/dist/react/table.js.map +1 -0
- package/dist/react/tabs.d.ts +9 -3
- package/dist/react/tabs.js +204 -48
- package/dist/react/tabs.js.map +1 -1
- package/dist/react/textarea.d.ts +6 -0
- package/dist/react/textarea.js +33 -0
- package/dist/react/textarea.js.map +1 -0
- package/dist/react/time-picker.d.ts +22 -0
- package/dist/react/time-picker.js +856 -0
- package/dist/react/time-picker.js.map +1 -0
- package/dist/react/tooltip.d.ts +45 -0
- package/dist/react/tooltip.js +540 -0
- package/dist/react/tooltip.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
import React, { useState, useRef, useCallback, useMemo, useEffect, useLayoutEffect } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
import { X } from 'lucide-react';
|
|
4
|
+
import { clsx } from 'clsx';
|
|
5
|
+
import { twMerge } from 'tailwind-merge';
|
|
6
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
function cn(...inputs) {
|
|
9
|
+
return twMerge(clsx(inputs));
|
|
10
|
+
}
|
|
11
|
+
var POPOVER_MOBILE_SHEET_MAX_PX = 1024;
|
|
12
|
+
var POPOVER_MOBILE_SHEET_MOTION_MS = 175;
|
|
13
|
+
var POPOVER_MOBILE_SHEET_ENTRY_EASING = "cubic-bezier(0.85, 0, 0.15, 1)";
|
|
14
|
+
var POPOVER_MOBILE_SHEET_EXIT_EASING = "cubic-bezier(0.85, 0, 1, 0.15)";
|
|
15
|
+
var POPOVER_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX = 120;
|
|
16
|
+
function usePopoverIsMobile(breakpoint = 1025) {
|
|
17
|
+
const [isMobile, setIsMobile] = useState(false);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
|
|
20
|
+
setIsMobile(mq.matches);
|
|
21
|
+
const handler = (e) => setIsMobile(e.matches);
|
|
22
|
+
mq.addEventListener("change", handler);
|
|
23
|
+
return () => mq.removeEventListener("change", handler);
|
|
24
|
+
}, [breakpoint]);
|
|
25
|
+
return isMobile;
|
|
26
|
+
}
|
|
27
|
+
var PopoverContext = React.createContext(
|
|
28
|
+
void 0
|
|
29
|
+
);
|
|
30
|
+
function usePopover() {
|
|
31
|
+
const context = React.useContext(PopoverContext);
|
|
32
|
+
if (!context) {
|
|
33
|
+
throw new Error("Popover components must be used within a <Popover />");
|
|
34
|
+
}
|
|
35
|
+
return context;
|
|
36
|
+
}
|
|
37
|
+
var Popover = ({ children, open: controlledOpen, onOpenChange }) => {
|
|
38
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
39
|
+
const isControlled = controlledOpen !== void 0;
|
|
40
|
+
const open = isControlled ? controlledOpen : internalOpen;
|
|
41
|
+
const triggerRef = useRef(null);
|
|
42
|
+
const setOpen = useCallback(
|
|
43
|
+
(value) => {
|
|
44
|
+
if (!isControlled) setInternalOpen(value);
|
|
45
|
+
onOpenChange?.(value);
|
|
46
|
+
},
|
|
47
|
+
[isControlled, onOpenChange]
|
|
48
|
+
);
|
|
49
|
+
return /* @__PURE__ */ jsx(PopoverContext.Provider, { value: { open, setOpen, triggerRef }, children });
|
|
50
|
+
};
|
|
51
|
+
var PopoverTrigger = ({ children, asChild }) => {
|
|
52
|
+
const { open, setOpen, triggerRef } = usePopover();
|
|
53
|
+
const handleClick = (e) => {
|
|
54
|
+
e.stopPropagation();
|
|
55
|
+
setOpen(!open);
|
|
56
|
+
};
|
|
57
|
+
if (asChild && React.isValidElement(children)) {
|
|
58
|
+
const child = children;
|
|
59
|
+
return React.cloneElement(child, {
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
|
+
ref: (el) => {
|
|
62
|
+
triggerRef.current = el;
|
|
63
|
+
},
|
|
64
|
+
onClick: (e) => {
|
|
65
|
+
child.props.onClick?.(e);
|
|
66
|
+
handleClick(e);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return /* @__PURE__ */ jsx(
|
|
71
|
+
"button",
|
|
72
|
+
{
|
|
73
|
+
type: "button",
|
|
74
|
+
ref: (el) => {
|
|
75
|
+
triggerRef.current = el;
|
|
76
|
+
},
|
|
77
|
+
onClick: handleClick,
|
|
78
|
+
children
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
var PopoverClose = ({ children, asChild }) => {
|
|
83
|
+
const { setOpen } = usePopover();
|
|
84
|
+
const handleClick = () => setOpen(false);
|
|
85
|
+
if (asChild && React.isValidElement(children)) {
|
|
86
|
+
const child = children;
|
|
87
|
+
return React.cloneElement(child, {
|
|
88
|
+
onClick: (e) => {
|
|
89
|
+
child.props.onClick?.(e);
|
|
90
|
+
handleClick();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return /* @__PURE__ */ jsx("button", { type: "button", onClick: handleClick, children });
|
|
95
|
+
};
|
|
96
|
+
function resolvePopoverMobileSheet(mobileOptions) {
|
|
97
|
+
return {
|
|
98
|
+
sheet: mobileOptions?.sheet ?? false,
|
|
99
|
+
title: mobileOptions?.title,
|
|
100
|
+
sheetExtraClassName: mobileOptions?.className,
|
|
101
|
+
contentClassName: mobileOptions?.contentClassName
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
var PopoverMobileClose = React.forwardRef(({ className, type = "button", ...props }, ref) => {
|
|
105
|
+
return /* @__PURE__ */ jsxs(
|
|
106
|
+
"button",
|
|
107
|
+
{
|
|
108
|
+
ref,
|
|
109
|
+
type,
|
|
110
|
+
className: cn(
|
|
111
|
+
"z-100 flex size-12 shrink-0 cursor-pointer items-center justify-center rounded-full transition-all hover:bg-secondary-background active:scale-[0.96]",
|
|
112
|
+
className
|
|
113
|
+
),
|
|
114
|
+
...props,
|
|
115
|
+
children: [
|
|
116
|
+
/* @__PURE__ */ jsx(X, { className: "size-5.5" }),
|
|
117
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
PopoverMobileClose.displayName = "PopoverMobileClose";
|
|
123
|
+
function PopoverMobileBottomSheetPortal({
|
|
124
|
+
open,
|
|
125
|
+
isAnimating,
|
|
126
|
+
slideEntrance,
|
|
127
|
+
slideOffsetPx,
|
|
128
|
+
sheetTitle,
|
|
129
|
+
sheetExtraClassName,
|
|
130
|
+
contentClassName,
|
|
131
|
+
onRequestClose,
|
|
132
|
+
menuRef,
|
|
133
|
+
dismissOnBackdropPress = true,
|
|
134
|
+
children,
|
|
135
|
+
className,
|
|
136
|
+
style,
|
|
137
|
+
...panelProps
|
|
138
|
+
}) {
|
|
139
|
+
const sheetMotion = open ? POPOVER_MOBILE_SHEET_ENTRY_EASING : POPOVER_MOBILE_SHEET_EXIT_EASING;
|
|
140
|
+
const sheetHiddenTransform = slideEntrance ? `translateY(${slideOffsetPx}px)` : "translateY(100%)";
|
|
141
|
+
return createPortal(
|
|
142
|
+
/* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex items-end justify-center p-0", children: [
|
|
143
|
+
/* @__PURE__ */ jsx(
|
|
144
|
+
"div",
|
|
145
|
+
{
|
|
146
|
+
className: cn(
|
|
147
|
+
"fixed inset-0 bg-black/40 dark:bg-black/60",
|
|
148
|
+
isAnimating ? "opacity-100" : "opacity-0"
|
|
149
|
+
),
|
|
150
|
+
style: {
|
|
151
|
+
transitionProperty: "opacity",
|
|
152
|
+
transitionDuration: `${POPOVER_MOBILE_SHEET_MOTION_MS}ms`,
|
|
153
|
+
transitionTimingFunction: sheetMotion
|
|
154
|
+
},
|
|
155
|
+
onClick: dismissOnBackdropPress ? onRequestClose : void 0,
|
|
156
|
+
"aria-hidden": true
|
|
157
|
+
}
|
|
158
|
+
),
|
|
159
|
+
/* @__PURE__ */ jsxs(
|
|
160
|
+
"div",
|
|
161
|
+
{
|
|
162
|
+
...panelProps,
|
|
163
|
+
ref: menuRef,
|
|
164
|
+
className: cn(
|
|
165
|
+
// Panel chrome + padding rhythm matches `DropdownMobileBottomSheetPortal`.
|
|
166
|
+
"bg-background border-primary/10 relative z-10 flex w-full max-h-[min(90dvh,calc(100dvh-env(safe-area-inset-bottom,0px)))] flex-col overflow-hidden shadow-2xl outline-none",
|
|
167
|
+
"rounded-t-2xl rounded-b-none border-x-0 border-b-0 border-t",
|
|
168
|
+
sheetExtraClassName,
|
|
169
|
+
className
|
|
170
|
+
),
|
|
171
|
+
style: {
|
|
172
|
+
transform: isAnimating ? "translateY(0)" : sheetHiddenTransform,
|
|
173
|
+
opacity: isAnimating ? 1 : 0,
|
|
174
|
+
transitionProperty: "transform, opacity",
|
|
175
|
+
transitionDuration: `${POPOVER_MOBILE_SHEET_MOTION_MS}ms`,
|
|
176
|
+
transitionTimingFunction: sheetMotion,
|
|
177
|
+
...style
|
|
178
|
+
},
|
|
179
|
+
children: [
|
|
180
|
+
/* @__PURE__ */ jsxs(
|
|
181
|
+
"div",
|
|
182
|
+
{
|
|
183
|
+
className: cn(
|
|
184
|
+
"flex w-full shrink-0 items-center py-2 pl-4 pr-2",
|
|
185
|
+
sheetTitle ? "justify-between gap-3" : "justify-end"
|
|
186
|
+
),
|
|
187
|
+
children: [
|
|
188
|
+
sheetTitle ? /* @__PURE__ */ jsx("p", { className: "text-foreground min-w-0 flex-1 truncate text-base font-semibold", children: sheetTitle }) : null,
|
|
189
|
+
/* @__PURE__ */ jsx(
|
|
190
|
+
PopoverMobileClose,
|
|
191
|
+
{
|
|
192
|
+
onClick: (e) => {
|
|
193
|
+
e.stopPropagation();
|
|
194
|
+
onRequestClose();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
),
|
|
201
|
+
/* @__PURE__ */ jsx(
|
|
202
|
+
"div",
|
|
203
|
+
{
|
|
204
|
+
className: cn(
|
|
205
|
+
"min-h-0 flex-1 overflow-y-auto px-4 pt-3",
|
|
206
|
+
contentClassName,
|
|
207
|
+
"pb-[calc(5rem+env(safe-area-inset-bottom,0px))]"
|
|
208
|
+
),
|
|
209
|
+
children
|
|
210
|
+
}
|
|
211
|
+
)
|
|
212
|
+
]
|
|
213
|
+
}
|
|
214
|
+
)
|
|
215
|
+
] }),
|
|
216
|
+
document.body
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
function computePosition(trigger, popover, side, align, offset, viewportPadding) {
|
|
220
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
221
|
+
const pw = popover.offsetWidth;
|
|
222
|
+
const ph = popover.offsetHeight;
|
|
223
|
+
const vw = window.innerWidth;
|
|
224
|
+
const vh = window.innerHeight;
|
|
225
|
+
let top = 0;
|
|
226
|
+
let left = 0;
|
|
227
|
+
let effectiveSide = side;
|
|
228
|
+
const place = (s) => {
|
|
229
|
+
switch (s) {
|
|
230
|
+
case "bottom":
|
|
231
|
+
top = triggerRect.bottom + offset;
|
|
232
|
+
break;
|
|
233
|
+
case "top":
|
|
234
|
+
top = triggerRect.top - ph - offset;
|
|
235
|
+
break;
|
|
236
|
+
case "right":
|
|
237
|
+
left = triggerRect.right + offset;
|
|
238
|
+
top = align === "start" ? triggerRect.top : align === "end" ? triggerRect.bottom - ph : triggerRect.top + triggerRect.height / 2 - ph / 2;
|
|
239
|
+
return;
|
|
240
|
+
case "left":
|
|
241
|
+
left = triggerRect.left - pw - offset;
|
|
242
|
+
top = align === "start" ? triggerRect.top : align === "end" ? triggerRect.bottom - ph : triggerRect.top + triggerRect.height / 2 - ph / 2;
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (align === "start") left = triggerRect.left;
|
|
246
|
+
else if (align === "end") left = triggerRect.right - pw;
|
|
247
|
+
else left = triggerRect.left + triggerRect.width / 2 - pw / 2;
|
|
248
|
+
};
|
|
249
|
+
place(side);
|
|
250
|
+
const tryFlip = () => {
|
|
251
|
+
if (side === "bottom" && top + ph > vh - viewportPadding) {
|
|
252
|
+
const flipped = "top";
|
|
253
|
+
const newTop = triggerRect.top - ph - offset;
|
|
254
|
+
if (newTop >= viewportPadding) {
|
|
255
|
+
effectiveSide = flipped;
|
|
256
|
+
top = newTop;
|
|
257
|
+
}
|
|
258
|
+
} else if (side === "top" && top < viewportPadding) {
|
|
259
|
+
const flipped = "bottom";
|
|
260
|
+
const newTop = triggerRect.bottom + offset;
|
|
261
|
+
if (newTop + ph <= vh - viewportPadding) {
|
|
262
|
+
effectiveSide = flipped;
|
|
263
|
+
top = newTop;
|
|
264
|
+
}
|
|
265
|
+
} else if (side === "right" && left + pw > vw - viewportPadding) {
|
|
266
|
+
const flipped = "left";
|
|
267
|
+
const newLeft = triggerRect.left - pw - offset;
|
|
268
|
+
if (newLeft >= viewportPadding) {
|
|
269
|
+
effectiveSide = flipped;
|
|
270
|
+
left = newLeft;
|
|
271
|
+
}
|
|
272
|
+
} else if (side === "left" && left < viewportPadding) {
|
|
273
|
+
const flipped = "right";
|
|
274
|
+
const newLeft = triggerRect.right + offset;
|
|
275
|
+
if (newLeft + pw <= vw - viewportPadding) {
|
|
276
|
+
effectiveSide = flipped;
|
|
277
|
+
left = newLeft;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
tryFlip();
|
|
282
|
+
left = Math.max(
|
|
283
|
+
viewportPadding,
|
|
284
|
+
Math.min(left, vw - pw - viewportPadding)
|
|
285
|
+
);
|
|
286
|
+
top = Math.max(
|
|
287
|
+
viewportPadding,
|
|
288
|
+
Math.min(top, vh - ph - viewportPadding)
|
|
289
|
+
);
|
|
290
|
+
return { top, left, side: effectiveSide };
|
|
291
|
+
}
|
|
292
|
+
var ARROW_SIZE = 6;
|
|
293
|
+
var PopoverContent = ({
|
|
294
|
+
children,
|
|
295
|
+
side = "bottom",
|
|
296
|
+
align = "center",
|
|
297
|
+
offset = 10,
|
|
298
|
+
showArrow = false,
|
|
299
|
+
closeOnClickOutside = true,
|
|
300
|
+
closeOnEscape = true,
|
|
301
|
+
duration = 80,
|
|
302
|
+
viewportPadding = 8,
|
|
303
|
+
container,
|
|
304
|
+
width = "auto",
|
|
305
|
+
mobileOptions,
|
|
306
|
+
slideEntrance = true,
|
|
307
|
+
slideEntranceOffsetPx: slideEntranceOffsetPxProp,
|
|
308
|
+
className,
|
|
309
|
+
style,
|
|
310
|
+
...props
|
|
311
|
+
}) => {
|
|
312
|
+
const { open, setOpen, triggerRef } = usePopover();
|
|
313
|
+
const isMobile = usePopoverIsMobile(POPOVER_MOBILE_SHEET_MAX_PX + 1);
|
|
314
|
+
const resolvedMobile = useMemo(
|
|
315
|
+
() => resolvePopoverMobileSheet(mobileOptions),
|
|
316
|
+
[mobileOptions]
|
|
317
|
+
);
|
|
318
|
+
const sheetMode = isMobile && resolvedMobile.sheet;
|
|
319
|
+
const slideOffsetPx = useMemo(
|
|
320
|
+
() => slideEntranceOffsetPxProp ?? POPOVER_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX,
|
|
321
|
+
[slideEntranceOffsetPxProp]
|
|
322
|
+
);
|
|
323
|
+
const closeDuration = sheetMode ? POPOVER_MOBILE_SHEET_MOTION_MS : duration;
|
|
324
|
+
const [shouldRender, setShouldRender] = useState(false);
|
|
325
|
+
const [isAnimating, setIsAnimating] = useState(false);
|
|
326
|
+
const [position, setPosition] = useState({
|
|
327
|
+
top: -9999,
|
|
328
|
+
left: -9999,
|
|
329
|
+
side
|
|
330
|
+
});
|
|
331
|
+
const [triggerWidth, setTriggerWidth] = useState(0);
|
|
332
|
+
const popoverRef = useRef(null);
|
|
333
|
+
const closePopover = useCallback(() => setOpen(false), [setOpen]);
|
|
334
|
+
useEffect(() => {
|
|
335
|
+
if (open) {
|
|
336
|
+
setShouldRender(true);
|
|
337
|
+
} else {
|
|
338
|
+
setIsAnimating(false);
|
|
339
|
+
const timer = setTimeout(() => setShouldRender(false), closeDuration);
|
|
340
|
+
return () => clearTimeout(timer);
|
|
341
|
+
}
|
|
342
|
+
}, [open, closeDuration]);
|
|
343
|
+
useEffect(() => {
|
|
344
|
+
if (!shouldRender || !open) return;
|
|
345
|
+
let raf2 = 0;
|
|
346
|
+
const raf1 = requestAnimationFrame(() => {
|
|
347
|
+
raf2 = requestAnimationFrame(() => setIsAnimating(true));
|
|
348
|
+
});
|
|
349
|
+
return () => {
|
|
350
|
+
cancelAnimationFrame(raf1);
|
|
351
|
+
if (raf2) cancelAnimationFrame(raf2);
|
|
352
|
+
};
|
|
353
|
+
}, [shouldRender, open]);
|
|
354
|
+
useLayoutEffect(() => {
|
|
355
|
+
if (!shouldRender || !open || sheetMode || !triggerRef.current || !popoverRef.current)
|
|
356
|
+
return;
|
|
357
|
+
const update = () => {
|
|
358
|
+
if (!triggerRef.current || !popoverRef.current) return;
|
|
359
|
+
setTriggerWidth(triggerRef.current.getBoundingClientRect().width);
|
|
360
|
+
const pos = computePosition(
|
|
361
|
+
triggerRef.current,
|
|
362
|
+
popoverRef.current,
|
|
363
|
+
side,
|
|
364
|
+
align,
|
|
365
|
+
offset,
|
|
366
|
+
viewportPadding
|
|
367
|
+
);
|
|
368
|
+
setPosition(pos);
|
|
369
|
+
};
|
|
370
|
+
update();
|
|
371
|
+
window.addEventListener("resize", update);
|
|
372
|
+
window.addEventListener("scroll", update, true);
|
|
373
|
+
return () => {
|
|
374
|
+
window.removeEventListener("resize", update);
|
|
375
|
+
window.removeEventListener("scroll", update, true);
|
|
376
|
+
};
|
|
377
|
+
}, [shouldRender, open, sheetMode, side, align, offset, viewportPadding]);
|
|
378
|
+
useEffect(() => {
|
|
379
|
+
if (open && sheetMode) {
|
|
380
|
+
document.body.style.overflow = "hidden";
|
|
381
|
+
}
|
|
382
|
+
return () => {
|
|
383
|
+
document.body.style.overflow = "";
|
|
384
|
+
};
|
|
385
|
+
}, [open, sheetMode]);
|
|
386
|
+
useEffect(() => {
|
|
387
|
+
if (!open || !closeOnClickOutside || sheetMode) return;
|
|
388
|
+
const handler = (e) => {
|
|
389
|
+
const target = e.target;
|
|
390
|
+
if (popoverRef.current?.contains(target) || triggerRef.current?.contains(target))
|
|
391
|
+
return;
|
|
392
|
+
setOpen(false);
|
|
393
|
+
};
|
|
394
|
+
document.addEventListener("mousedown", handler);
|
|
395
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
396
|
+
}, [open, closeOnClickOutside, sheetMode, setOpen, triggerRef]);
|
|
397
|
+
useEffect(() => {
|
|
398
|
+
if (!open || !closeOnEscape) return;
|
|
399
|
+
const handler = (e) => {
|
|
400
|
+
if (e.key === "Escape") setOpen(false);
|
|
401
|
+
};
|
|
402
|
+
window.addEventListener("keydown", handler);
|
|
403
|
+
return () => window.removeEventListener("keydown", handler);
|
|
404
|
+
}, [open, closeOnEscape, setOpen]);
|
|
405
|
+
if (!shouldRender) return null;
|
|
406
|
+
if (sheetMode && typeof document !== "undefined") {
|
|
407
|
+
return /* @__PURE__ */ jsx(
|
|
408
|
+
PopoverMobileBottomSheetPortal,
|
|
409
|
+
{
|
|
410
|
+
...props,
|
|
411
|
+
open,
|
|
412
|
+
isAnimating,
|
|
413
|
+
slideEntrance,
|
|
414
|
+
slideOffsetPx,
|
|
415
|
+
sheetTitle: resolvedMobile.title,
|
|
416
|
+
sheetExtraClassName: resolvedMobile.sheetExtraClassName,
|
|
417
|
+
contentClassName: cn(resolvedMobile.contentClassName, className),
|
|
418
|
+
onRequestClose: closePopover,
|
|
419
|
+
dismissOnBackdropPress: closeOnClickOutside,
|
|
420
|
+
menuRef: popoverRef,
|
|
421
|
+
role: "dialog",
|
|
422
|
+
"aria-modal": "true",
|
|
423
|
+
tabIndex: -1,
|
|
424
|
+
className: void 0,
|
|
425
|
+
style,
|
|
426
|
+
"data-slot": "popover-content",
|
|
427
|
+
children
|
|
428
|
+
}
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
const transformOrigin = {
|
|
432
|
+
bottom: "top center",
|
|
433
|
+
top: "bottom center",
|
|
434
|
+
left: "right center",
|
|
435
|
+
right: "left center"
|
|
436
|
+
};
|
|
437
|
+
const hiddenTransform = {
|
|
438
|
+
bottom: "translateY(-6px) scale(0.97)",
|
|
439
|
+
top: "translateY(6px) scale(0.97)",
|
|
440
|
+
left: "translateX(6px) scale(0.97)",
|
|
441
|
+
right: "translateX(-6px) scale(0.97)"
|
|
442
|
+
};
|
|
443
|
+
const resolvedWidth = width === "trigger" ? triggerWidth : width === "auto" ? void 0 : width;
|
|
444
|
+
const arrowStyles = () => {
|
|
445
|
+
const base = {
|
|
446
|
+
position: "absolute",
|
|
447
|
+
width: 0,
|
|
448
|
+
height: 0,
|
|
449
|
+
pointerEvents: "none"
|
|
450
|
+
};
|
|
451
|
+
switch (position.side) {
|
|
452
|
+
case "bottom":
|
|
453
|
+
return {
|
|
454
|
+
...base,
|
|
455
|
+
top: -ARROW_SIZE,
|
|
456
|
+
left: "50%",
|
|
457
|
+
transform: "translateX(-50%)",
|
|
458
|
+
borderLeft: `${ARROW_SIZE}px solid transparent`,
|
|
459
|
+
borderRight: `${ARROW_SIZE}px solid transparent`,
|
|
460
|
+
borderBottom: `${ARROW_SIZE}px solid var(--border)`
|
|
461
|
+
};
|
|
462
|
+
case "top":
|
|
463
|
+
return {
|
|
464
|
+
...base,
|
|
465
|
+
bottom: -ARROW_SIZE,
|
|
466
|
+
left: "50%",
|
|
467
|
+
transform: "translateX(-50%)",
|
|
468
|
+
borderLeft: `${ARROW_SIZE}px solid transparent`,
|
|
469
|
+
borderRight: `${ARROW_SIZE}px solid transparent`,
|
|
470
|
+
borderTop: `${ARROW_SIZE}px solid var(--border)`
|
|
471
|
+
};
|
|
472
|
+
case "right":
|
|
473
|
+
return {
|
|
474
|
+
...base,
|
|
475
|
+
left: -ARROW_SIZE,
|
|
476
|
+
top: "50%",
|
|
477
|
+
transform: "translateY(-50%)",
|
|
478
|
+
borderTop: `${ARROW_SIZE}px solid transparent`,
|
|
479
|
+
borderBottom: `${ARROW_SIZE}px solid transparent`,
|
|
480
|
+
borderRight: `${ARROW_SIZE}px solid var(--border)`
|
|
481
|
+
};
|
|
482
|
+
case "left":
|
|
483
|
+
return {
|
|
484
|
+
...base,
|
|
485
|
+
right: -ARROW_SIZE,
|
|
486
|
+
top: "50%",
|
|
487
|
+
transform: "translateY(-50%)",
|
|
488
|
+
borderTop: `${ARROW_SIZE}px solid transparent`,
|
|
489
|
+
borderBottom: `${ARROW_SIZE}px solid transparent`,
|
|
490
|
+
borderLeft: `${ARROW_SIZE}px solid var(--border)`
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
const resolvedContainer = container !== void 0 ? container : typeof document !== "undefined" ? document.body : null;
|
|
495
|
+
if (!resolvedContainer) return null;
|
|
496
|
+
return createPortal(
|
|
497
|
+
/* @__PURE__ */ jsxs(
|
|
498
|
+
"div",
|
|
499
|
+
{
|
|
500
|
+
...props,
|
|
501
|
+
ref: popoverRef,
|
|
502
|
+
className: cn(
|
|
503
|
+
"bg-background border-primary/10 fixed z-50 overflow-hidden rounded-xl border shadow-xl outline-none",
|
|
504
|
+
className
|
|
505
|
+
),
|
|
506
|
+
"data-slot": "popover-content",
|
|
507
|
+
style: {
|
|
508
|
+
position: "fixed",
|
|
509
|
+
top: position.top,
|
|
510
|
+
left: position.left,
|
|
511
|
+
width: resolvedWidth,
|
|
512
|
+
transformOrigin: transformOrigin[position.side],
|
|
513
|
+
transform: isAnimating ? "none" : hiddenTransform[position.side],
|
|
514
|
+
opacity: isAnimating ? 1 : 0,
|
|
515
|
+
transition: `opacity ${duration}ms ease, transform ${duration}ms ease`,
|
|
516
|
+
...style
|
|
517
|
+
},
|
|
518
|
+
children: [
|
|
519
|
+
showArrow && /* @__PURE__ */ jsx("div", { style: arrowStyles() }),
|
|
520
|
+
children
|
|
521
|
+
]
|
|
522
|
+
}
|
|
523
|
+
),
|
|
524
|
+
resolvedContainer
|
|
525
|
+
);
|
|
526
|
+
};
|
|
527
|
+
var PopoverHeader = ({
|
|
528
|
+
className,
|
|
529
|
+
...props
|
|
530
|
+
}) => /* @__PURE__ */ jsx(
|
|
531
|
+
"div",
|
|
532
|
+
{
|
|
533
|
+
className: cn(
|
|
534
|
+
"border-primary/10 flex flex-col space-y-1 border-b px-4 py-3",
|
|
535
|
+
className
|
|
536
|
+
),
|
|
537
|
+
...props
|
|
538
|
+
}
|
|
539
|
+
);
|
|
540
|
+
var PopoverFooter = ({
|
|
541
|
+
className,
|
|
542
|
+
...props
|
|
543
|
+
}) => /* @__PURE__ */ jsx(
|
|
544
|
+
"div",
|
|
545
|
+
{
|
|
546
|
+
className: cn(
|
|
547
|
+
"border-primary/10 flex flex-row justify-end gap-2 border-t px-4 py-3",
|
|
548
|
+
className
|
|
549
|
+
),
|
|
550
|
+
...props
|
|
551
|
+
}
|
|
552
|
+
);
|
|
553
|
+
var PopoverTitle = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
554
|
+
"h4",
|
|
555
|
+
{
|
|
556
|
+
className: cn("text-primary text-sm leading-none font-semibold", className),
|
|
557
|
+
...props
|
|
558
|
+
}
|
|
559
|
+
);
|
|
560
|
+
var PopoverDescription = ({ className, ...props }) => /* @__PURE__ */ jsx("p", { className: cn("text-muted-foreground text-xs", className), ...props });
|
|
561
|
+
|
|
562
|
+
export { Popover, PopoverClose, PopoverContent, PopoverDescription, PopoverFooter, PopoverHeader, PopoverMobileClose, PopoverTitle, PopoverTrigger };
|
|
563
|
+
//# sourceMappingURL=popover.js.map
|
|
564
|
+
//# sourceMappingURL=popover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/utils.ts","../../src/react/popover.tsx"],"names":[],"mappings":"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","file":"popover.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\nimport React, {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\n\n/** Mobile popover as bottom sheet — same cutoff and motion as {@link DropdownContent}. */\nconst POPOVER_MOBILE_SHEET_MAX_PX = 1024;\nconst POPOVER_MOBILE_SHEET_MOTION_MS = 175;\nconst POPOVER_MOBILE_SHEET_ENTRY_EASING = \"cubic-bezier(0.85, 0, 0.15, 1)\";\nconst POPOVER_MOBILE_SHEET_EXIT_EASING = \"cubic-bezier(0.85, 0, 1, 0.15)\";\nconst POPOVER_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX = 120;\n\nfunction usePopoverIsMobile(breakpoint = 1025): boolean {\n const [isMobile, setIsMobile] = useState(false);\n useEffect(() => {\n const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n setIsMobile(mq.matches);\n const handler = (e: MediaQueryListEvent) => setIsMobile(e.matches);\n mq.addEventListener(\"change\", handler);\n return () => mq.removeEventListener(\"change\", handler);\n }, [breakpoint]);\n return isMobile;\n}\n\n//////////////////////////////////////////////// Context\n\ntype PopoverContextValue = {\n open: boolean;\n setOpen: (open: boolean) => void;\n triggerRef: React.RefObject<HTMLElement | null>;\n};\n\nconst PopoverContext = React.createContext<PopoverContextValue | undefined>(\n undefined,\n);\n\nfunction usePopover() {\n const context = React.useContext(PopoverContext);\n if (!context) {\n throw new Error(\"Popover components must be used within a <Popover />\");\n }\n return context;\n}\n\n//////////////////////////////////////////////// Main\n\nexport const Popover: React.FC<{\n children: React.ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}> = ({ children, open: controlledOpen, onOpenChange }) => {\n const [internalOpen, setInternalOpen] = useState(false);\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n const triggerRef = useRef<HTMLElement | null>(null);\n\n const setOpen = useCallback(\n (value: boolean) => {\n if (!isControlled) setInternalOpen(value);\n onOpenChange?.(value);\n },\n [isControlled, onOpenChange],\n );\n\n return (\n <PopoverContext.Provider value={{ open, setOpen, triggerRef }}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\n//////////////////////////////////////////////// Trigger\n\nexport const PopoverTrigger: React.FC<{\n children: React.ReactNode;\n asChild?: boolean;\n}> = ({ children, asChild }) => {\n const { open, setOpen, triggerRef } = usePopover();\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n setOpen(!open);\n };\n\n if (asChild && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n onClick?: React.MouseEventHandler;\n ref?: React.Ref<unknown>;\n }>;\n return React.cloneElement(child, {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref: (el: HTMLElement) => {\n triggerRef.current = el;\n },\n onClick: (e: React.MouseEvent) => {\n child.props.onClick?.(e);\n handleClick(e);\n },\n } as Partial<typeof child.props>);\n }\n\n return (\n <button\n type=\"button\"\n ref={(el) => {\n triggerRef.current = el;\n }}\n onClick={handleClick}\n >\n {children}\n </button>\n );\n};\n\n//////////////////////////////////////////////// Close\n\nexport const PopoverClose: React.FC<{\n children: React.ReactNode;\n asChild?: boolean;\n}> = ({ children, asChild }) => {\n const { setOpen } = usePopover();\n const handleClick = () => setOpen(false);\n\n if (asChild && React.isValidElement(children)) {\n const child = children as React.ReactElement<{\n onClick?: React.MouseEventHandler;\n }>;\n return React.cloneElement(child, {\n onClick: (e: React.MouseEvent) => {\n child.props.onClick?.(e);\n handleClick();\n },\n } as Partial<typeof child.props>);\n }\n\n return (\n <button type=\"button\" onClick={handleClick}>\n {children}\n </button>\n );\n};\n\n//////////////////////////////////////////////// Mobile sheet (popover-specific; mirrors dropdown behavior)\n\n/**\n * Narrow-viewport (≤1024px) bottom-sheet options for {@link PopoverContent}.\n * `className` merges onto the sheet panel root (after base sheet styles).\n */\nexport interface PopoverMobileSheetOptions {\n /** When `true`, use a bottom sheet on narrow viewports. Default `false`. */\n sheet?: boolean;\n title?: string;\n className?: string;\n contentClassName?: string;\n}\n\nfunction resolvePopoverMobileSheet(\n mobileOptions: PopoverMobileSheetOptions | undefined,\n) {\n return {\n sheet: mobileOptions?.sheet ?? false,\n title: mobileOptions?.title,\n sheetExtraClassName: mobileOptions?.className,\n contentClassName: mobileOptions?.contentClassName,\n };\n}\n\nexport interface PopoverMobileCloseProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\n/**\n * Dismiss control for the mobile bottom-sheet popover. Styling matches\n * {@link DialogCloseButton} (circular hit target, X icon).\n */\nexport const PopoverMobileClose = React.forwardRef<\n HTMLButtonElement,\n PopoverMobileCloseProps\n>(({ className, type = \"button\", ...props }, ref) => {\n return (\n <button\n ref={ref}\n type={type}\n className={cn(\n \"z-100 flex size-12 shrink-0 cursor-pointer items-center justify-center rounded-full transition-all hover:bg-secondary-background active:scale-[0.96]\",\n className,\n )}\n {...props}\n >\n <X className=\"size-5.5\" />\n <span className=\"sr-only\">Close</span>\n </button>\n );\n});\nPopoverMobileClose.displayName = \"PopoverMobileClose\";\n\ninterface PopoverMobileBottomSheetPortalProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n \"ref\"\n> {\n children: React.ReactNode;\n open: boolean;\n isAnimating: boolean;\n slideEntrance: boolean;\n slideOffsetPx: number;\n sheetTitle?: string;\n sheetExtraClassName?: string;\n contentClassName?: string;\n onRequestClose: () => void;\n menuRef: React.RefObject<HTMLDivElement | null>;\n /** When `false`, scrim taps do not close (matches `closeOnClickOutside={false}`). */\n dismissOnBackdropPress?: boolean;\n}\n\nfunction PopoverMobileBottomSheetPortal({\n open,\n isAnimating,\n slideEntrance,\n slideOffsetPx,\n sheetTitle,\n sheetExtraClassName,\n contentClassName,\n onRequestClose,\n menuRef,\n dismissOnBackdropPress = true,\n children,\n className,\n style,\n ...panelProps\n}: PopoverMobileBottomSheetPortalProps) {\n const sheetMotion = open\n ? POPOVER_MOBILE_SHEET_ENTRY_EASING\n : POPOVER_MOBILE_SHEET_EXIT_EASING;\n const sheetHiddenTransform = slideEntrance\n ? `translateY(${slideOffsetPx}px)`\n : \"translateY(100%)\";\n\n return createPortal(\n <div className=\"fixed inset-0 z-50 flex items-end justify-center p-0\">\n <div\n className={cn(\n \"fixed inset-0 bg-black/40 dark:bg-black/60\",\n isAnimating ? \"opacity-100\" : \"opacity-0\",\n )}\n style={{\n transitionProperty: \"opacity\",\n transitionDuration: `${POPOVER_MOBILE_SHEET_MOTION_MS}ms`,\n transitionTimingFunction: sheetMotion,\n }}\n onClick={dismissOnBackdropPress ? onRequestClose : undefined}\n aria-hidden\n />\n <div\n {...panelProps}\n ref={menuRef}\n className={cn(\n // Panel chrome + padding rhythm matches `DropdownMobileBottomSheetPortal`.\n \"bg-background border-primary/10 relative z-10 flex w-full max-h-[min(90dvh,calc(100dvh-env(safe-area-inset-bottom,0px)))] flex-col overflow-hidden shadow-2xl outline-none\",\n \"rounded-t-2xl rounded-b-none border-x-0 border-b-0 border-t\",\n sheetExtraClassName,\n className,\n )}\n style={{\n transform: isAnimating ? \"translateY(0)\" : sheetHiddenTransform,\n opacity: isAnimating ? 1 : 0,\n transitionProperty: \"transform, opacity\",\n transitionDuration: `${POPOVER_MOBILE_SHEET_MOTION_MS}ms`,\n transitionTimingFunction: sheetMotion,\n ...style,\n }}\n >\n <div\n className={cn(\n \"flex w-full shrink-0 items-center py-2 pl-4 pr-2\",\n sheetTitle ? \"justify-between gap-3\" : \"justify-end\",\n )}\n >\n {sheetTitle ? (\n <p className=\"text-foreground min-w-0 flex-1 truncate text-base font-semibold\">\n {sheetTitle}\n </p>\n ) : null}\n <PopoverMobileClose\n onClick={(e) => {\n e.stopPropagation();\n onRequestClose();\n }}\n />\n </div>\n <div\n className={cn(\n \"min-h-0 flex-1 overflow-y-auto px-4 pt-3\",\n contentClassName,\n \"pb-[calc(5rem+env(safe-area-inset-bottom,0px))]\",\n )}\n >\n {children}\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n\n//////////////////////////////////////////////// Content\n\ntype Side = \"top\" | \"right\" | \"bottom\" | \"left\";\ntype Align = \"start\" | \"center\" | \"end\";\n\ninterface PopoverContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Which side of the trigger to render on */\n side?: Side;\n /** Alignment along the cross-axis */\n align?: Align;\n /** Gap between trigger and popover in px */\n offset?: number;\n /** Show a small arrow pointing to the trigger */\n showArrow?: boolean;\n /** Close when clicking outside */\n closeOnClickOutside?: boolean;\n /** Close when Escape key is pressed */\n closeOnEscape?: boolean;\n /** Animation duration in ms */\n duration?: number;\n /** Minimum distance from the viewport edge in px */\n viewportPadding?: number;\n /** Portal container – defaults to document.body */\n container?: HTMLElement | null;\n /** Width of the popover. 'trigger' matches the trigger width. */\n width?: \"auto\" | \"trigger\" | number;\n /**\n * Narrow-viewport (≤1024px) bottom sheet — same options as dropdown\n * `mobileOptions`, except `sheet` defaults to `false`.\n */\n mobileOptions?: PopoverMobileSheetOptions;\n /**\n * Mobile bottom sheet only. When `true` (default), panel motion matches Dialog\n * `slideEntrance`; when `false`, uses full `translateY(100%)`.\n */\n slideEntrance?: boolean;\n /** Mobile sheet only; defaults to 120px (same as dropdown / dialog full sheet). */\n slideEntranceOffsetPx?: number;\n}\n\ninterface Position {\n top: number;\n left: number;\n side: Side; // actual side after flip\n}\n\nfunction computePosition(\n trigger: HTMLElement,\n popover: HTMLElement,\n side: Side,\n align: Align,\n offset: number,\n viewportPadding: number,\n): Position {\n const triggerRect = trigger.getBoundingClientRect();\n /** Layout box — not affected by exit/enter `transform: scale()`, unlike `getBoundingClientRect()`. */\n const pw = popover.offsetWidth;\n const ph = popover.offsetHeight;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n let top = 0;\n let left = 0;\n let effectiveSide: Side = side;\n\n /** Viewport-space coords — pairs with `position: fixed` on the portal root. */\n const place = (s: Side) => {\n switch (s) {\n case \"bottom\":\n top = triggerRect.bottom + offset;\n break;\n case \"top\":\n top = triggerRect.top - ph - offset;\n break;\n case \"right\":\n left = triggerRect.right + offset;\n top =\n align === \"start\"\n ? triggerRect.top\n : align === \"end\"\n ? triggerRect.bottom - ph\n : triggerRect.top + triggerRect.height / 2 - ph / 2;\n return;\n case \"left\":\n left = triggerRect.left - pw - offset;\n top =\n align === \"start\"\n ? triggerRect.top\n : align === \"end\"\n ? triggerRect.bottom - ph\n : triggerRect.top + triggerRect.height / 2 - ph / 2;\n return;\n }\n // horizontal alignment for top/bottom\n if (align === \"start\") left = triggerRect.left;\n else if (align === \"end\") left = triggerRect.right - pw;\n else left = triggerRect.left + triggerRect.width / 2 - pw / 2;\n };\n\n place(side);\n\n // ----- flip if overflowing viewport -----\n const tryFlip = () => {\n if (side === \"bottom\" && top + ph > vh - viewportPadding) {\n const flipped: Side = \"top\";\n const newTop = triggerRect.top - ph - offset;\n if (newTop >= viewportPadding) {\n effectiveSide = flipped;\n top = newTop;\n }\n } else if (side === \"top\" && top < viewportPadding) {\n const flipped: Side = \"bottom\";\n const newTop = triggerRect.bottom + offset;\n if (newTop + ph <= vh - viewportPadding) {\n effectiveSide = flipped;\n top = newTop;\n }\n } else if (side === \"right\" && left + pw > vw - viewportPadding) {\n const flipped: Side = \"left\";\n const newLeft = triggerRect.left - pw - offset;\n if (newLeft >= viewportPadding) {\n effectiveSide = flipped;\n left = newLeft;\n }\n } else if (side === \"left\" && left < viewportPadding) {\n const flipped: Side = \"right\";\n const newLeft = triggerRect.right + offset;\n if (newLeft + pw <= vw - viewportPadding) {\n effectiveSide = flipped;\n left = newLeft;\n }\n }\n };\n tryFlip();\n\n // ----- clamp to viewport -----\n left = Math.max(\n viewportPadding,\n Math.min(left, vw - pw - viewportPadding),\n );\n top = Math.max(\n viewportPadding,\n Math.min(top, vh - ph - viewportPadding),\n );\n\n return { top, left, side: effectiveSide };\n}\n\nconst ARROW_SIZE = 6;\n\nexport const PopoverContent: React.FC<PopoverContentProps> = ({\n children,\n side = \"bottom\",\n align = \"center\",\n offset = 10,\n showArrow = false,\n closeOnClickOutside = true,\n closeOnEscape = true,\n duration = 80,\n viewportPadding = 8,\n container,\n width = \"auto\",\n mobileOptions,\n slideEntrance = true,\n slideEntranceOffsetPx: slideEntranceOffsetPxProp,\n className,\n style,\n ...props\n}) => {\n const { open, setOpen, triggerRef } = usePopover();\n const isMobile = usePopoverIsMobile(POPOVER_MOBILE_SHEET_MAX_PX + 1);\n const resolvedMobile = useMemo(\n () => resolvePopoverMobileSheet(mobileOptions),\n [mobileOptions],\n );\n const sheetMode = isMobile && resolvedMobile.sheet;\n const slideOffsetPx = useMemo(\n () =>\n slideEntranceOffsetPxProp ??\n POPOVER_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX,\n [slideEntranceOffsetPxProp],\n );\n const closeDuration = sheetMode\n ? POPOVER_MOBILE_SHEET_MOTION_MS\n : duration;\n\n const [shouldRender, setShouldRender] = useState(false);\n const [isAnimating, setIsAnimating] = useState(false);\n const [position, setPosition] = useState<Position>({\n top: -9999,\n left: -9999,\n side,\n });\n const [triggerWidth, setTriggerWidth] = useState<number>(0);\n const popoverRef = useRef<HTMLDivElement>(null);\n\n const closePopover = useCallback(() => setOpen(false), [setOpen]);\n\n /** Same open/close sequencing as dropdown mobile sheet / `DialogContent`. */\n useEffect(() => {\n if (open) {\n setShouldRender(true);\n } else {\n setIsAnimating(false);\n const timer = setTimeout(() => setShouldRender(false), closeDuration);\n return () => clearTimeout(timer);\n }\n }, [open, closeDuration]);\n\n useEffect(() => {\n if (!shouldRender || !open) return;\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => setIsAnimating(true));\n });\n return () => {\n cancelAnimationFrame(raf1);\n if (raf2) cancelAnimationFrame(raf2);\n };\n }, [shouldRender, open]);\n\n // Position calculation – runs after render so the popover has dimensions.\n // Skip while `open` is false: panel still mounts for the exit animation, but\n // `getBoundingClientRect` on the root would reflect `scale()` and re-trigger a jump.\n useLayoutEffect(() => {\n if (\n !shouldRender ||\n !open ||\n sheetMode ||\n !triggerRef.current ||\n !popoverRef.current\n )\n return;\n\n const update = () => {\n if (!triggerRef.current || !popoverRef.current) return;\n setTriggerWidth(triggerRef.current.getBoundingClientRect().width);\n const pos = computePosition(\n triggerRef.current,\n popoverRef.current,\n side,\n align,\n offset,\n viewportPadding,\n );\n setPosition(pos);\n };\n\n update();\n window.addEventListener(\"resize\", update);\n window.addEventListener(\"scroll\", update, true);\n return () => {\n window.removeEventListener(\"resize\", update);\n window.removeEventListener(\"scroll\", update, true);\n };\n }, [shouldRender, open, sheetMode, side, align, offset, viewportPadding]);\n\n // Body scroll lock (mobile sheet)\n useEffect(() => {\n if (open && sheetMode) {\n document.body.style.overflow = \"hidden\";\n }\n return () => {\n document.body.style.overflow = \"\";\n };\n }, [open, sheetMode]);\n\n // Close on outside click (floating only — sheet uses scrim `dismissOnBackdropPress`)\n useEffect(() => {\n if (!open || !closeOnClickOutside || sheetMode) return;\n const handler = (e: MouseEvent) => {\n const target = e.target as Node;\n if (\n popoverRef.current?.contains(target) ||\n triggerRef.current?.contains(target)\n )\n return;\n setOpen(false);\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open, closeOnClickOutside, sheetMode, setOpen, triggerRef]);\n\n // Close on Escape\n useEffect(() => {\n if (!open || !closeOnEscape) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [open, closeOnEscape, setOpen]);\n\n if (!shouldRender) return null;\n\n if (sheetMode && typeof document !== \"undefined\") {\n return (\n <PopoverMobileBottomSheetPortal\n {...props}\n open={open}\n isAnimating={isAnimating}\n slideEntrance={slideEntrance}\n slideOffsetPx={slideOffsetPx}\n sheetTitle={resolvedMobile.title}\n sheetExtraClassName={resolvedMobile.sheetExtraClassName}\n contentClassName={cn(resolvedMobile.contentClassName, className)}\n onRequestClose={closePopover}\n dismissOnBackdropPress={closeOnClickOutside}\n menuRef={popoverRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n className={undefined}\n style={style}\n data-slot=\"popover-content\"\n >\n {children}\n </PopoverMobileBottomSheetPortal>\n );\n }\n\n // Animation direction by side\n const transformOrigin: Record<Side, string> = {\n bottom: \"top center\",\n top: \"bottom center\",\n left: \"right center\",\n right: \"left center\",\n };\n\n const hiddenTransform: Record<Side, string> = {\n bottom: \"translateY(-6px) scale(0.97)\",\n top: \"translateY(6px) scale(0.97)\",\n left: \"translateX(6px) scale(0.97)\",\n right: \"translateX(-6px) scale(0.97)\",\n };\n\n const resolvedWidth =\n width === \"trigger\" ? triggerWidth : width === \"auto\" ? undefined : width;\n\n // Arrow position relative to popover\n const arrowStyles = (): React.CSSProperties => {\n const base: React.CSSProperties = {\n position: \"absolute\",\n width: 0,\n height: 0,\n pointerEvents: \"none\",\n };\n switch (position.side) {\n case \"bottom\":\n return {\n ...base,\n top: -ARROW_SIZE,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n borderLeft: `${ARROW_SIZE}px solid transparent`,\n borderRight: `${ARROW_SIZE}px solid transparent`,\n borderBottom: `${ARROW_SIZE}px solid var(--border)`,\n };\n case \"top\":\n return {\n ...base,\n bottom: -ARROW_SIZE,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n borderLeft: `${ARROW_SIZE}px solid transparent`,\n borderRight: `${ARROW_SIZE}px solid transparent`,\n borderTop: `${ARROW_SIZE}px solid var(--border)`,\n };\n case \"right\":\n return {\n ...base,\n left: -ARROW_SIZE,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n borderTop: `${ARROW_SIZE}px solid transparent`,\n borderBottom: `${ARROW_SIZE}px solid transparent`,\n borderRight: `${ARROW_SIZE}px solid var(--border)`,\n };\n case \"left\":\n return {\n ...base,\n right: -ARROW_SIZE,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n borderTop: `${ARROW_SIZE}px solid transparent`,\n borderBottom: `${ARROW_SIZE}px solid transparent`,\n borderLeft: `${ARROW_SIZE}px solid var(--border)`,\n };\n }\n };\n\n const resolvedContainer =\n container !== undefined\n ? container\n : typeof document !== \"undefined\"\n ? document.body\n : null;\n\n if (!resolvedContainer) return null;\n\n return createPortal(\n <div\n {...props}\n ref={popoverRef}\n className={cn(\n \"bg-background border-primary/10 fixed z-50 overflow-hidden rounded-xl border shadow-xl outline-none\",\n className,\n )}\n data-slot=\"popover-content\"\n style={{\n position: \"fixed\",\n top: position.top,\n left: position.left,\n width: resolvedWidth,\n transformOrigin: transformOrigin[position.side],\n transform: isAnimating ? \"none\" : hiddenTransform[position.side],\n opacity: isAnimating ? 1 : 0,\n transition: `opacity ${duration}ms ease, transform ${duration}ms ease`,\n ...style,\n }}\n >\n {showArrow && <div style={arrowStyles()} />}\n {children}\n </div>,\n resolvedContainer,\n );\n};\n\n//////////////////////////////////////////////// Sub-components\n\nexport const PopoverHeader: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n}) => (\n <div\n className={cn(\n \"border-primary/10 flex flex-col space-y-1 border-b px-4 py-3\",\n className,\n )}\n {...props}\n />\n);\n\nexport const PopoverFooter: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n}) => (\n <div\n className={cn(\n \"border-primary/10 flex flex-row justify-end gap-2 border-t px-4 py-3\",\n className,\n )}\n {...props}\n />\n);\n\nexport const PopoverTitle: React.FC<\n React.HTMLAttributes<HTMLHeadingElement>\n> = ({ className, ...props }) => (\n <h4\n className={cn(\"text-primary text-sm leading-none font-semibold\", className)}\n {...props}\n />\n);\n\nexport const PopoverDescription: React.FC<\n React.HTMLAttributes<HTMLParagraphElement>\n> = ({ className, ...props }) => (\n <p className={cn(\"text-muted-foreground text-xs\", className)} {...props} />\n);\n"]}
|
|
@@ -158,7 +158,19 @@ var ScrollHeaderSticky = ({
|
|
|
158
158
|
...props,
|
|
159
159
|
children
|
|
160
160
|
}
|
|
161
|
-
) : /* @__PURE__ */ jsx("div", { className: stickyChromeBgClass, children: /* @__PURE__ */ jsx(
|
|
161
|
+
) : /* @__PURE__ */ jsx("div", { className: stickyChromeBgClass, children: /* @__PURE__ */ jsx(
|
|
162
|
+
"div",
|
|
163
|
+
{
|
|
164
|
+
className: cn(
|
|
165
|
+
stickyChromeBorderClass,
|
|
166
|
+
"transition-[border-color] duration-300 motion-reduce:duration-0 motion-reduce:transition-none",
|
|
167
|
+
'[.scroll-header:not([data-scrolled="true"])_&]:border-b-transparent',
|
|
168
|
+
className
|
|
169
|
+
),
|
|
170
|
+
...props,
|
|
171
|
+
children
|
|
172
|
+
}
|
|
173
|
+
) })
|
|
162
174
|
}
|
|
163
175
|
);
|
|
164
176
|
};
|