@avenue-ticketing/ui 0.3.0 → 0.5.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 +131 -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.d.ts +7 -0
- package/dist/react/dialog.js +211 -90
- package/dist/react/dialog.js.map +1 -1
- package/dist/react/dropdown.d.ts +126 -0
- package/dist/react/dropdown.js +1269 -0
- package/dist/react/dropdown.js.map +1 -0
- 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 +918 -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 +2155 -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 +217 -57
- 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 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/utils.ts","../../src/react/button.tsx","../../src/react/pagination.tsx"],"names":["React","jsx","Pagination"],"mappings":"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","file":"pagination.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","import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst sizeClass = {\n xs: \"h-8 min-h-8 gap-2 px-4 text-sm has-[>svg]:px-3 [&_svg:not([class*='size-'])]:size-3\",\n default:\n \"h-10 min-h-10 gap-2 px-5 text-sm has-[>svg]:px-4 [&_svg:not([class*='size-'])]:size-4\",\n lg: \"h-11 min-h-11 gap-2 px-6 text-base has-[>svg]:px-5 [&_svg:not([class*='size-'])]:size-5\",\n} as const;\n\n/** Square hit targets for `iconOnly` — same keys as `sizeClass` (`default` | `lg`). */\nconst iconOnlySizeClass = {\n xs: \"size-8 min-h-8 min-w-8 gap-0 p-0 [&_svg:not([class*='size-'])]:size-3\",\n default:\n \"size-10 min-h-10 min-w-10 gap-0 p-0 [&_svg:not([class*='size-'])]:size-4\",\n lg: \"size-11 min-h-11 min-w-11 gap-0 p-0 [&_svg:not([class*='size-'])]:size-5\",\n} as const;\n\nconst roundedClass = {\n full: \"rounded-full\",\n lg: \"rounded-lg\",\n md: \"rounded-md\",\n} as const;\n\nconst variantClass = {\n primary:\n \"bg-primary text-background border border-transparent hover:bg-primary/90 active:bg-primary/85\",\n secondary:\n \"bg-background text-primary border border-primary/10 hover:bg-primary/5\",\n destructive:\n \"bg-background text-red-500 border border-red-500/25 hover:bg-red-500/5\",\n success:\n \"bg-background text-green-500 border border-green-500/25 hover:bg-green-500/5\",\n} as const;\n\nexport type ButtonProps = React.ComponentProps<\"button\"> & {\n /**\n * Visual style: neutral (`secondary`, `primary`), or outline (`destructive`,\n * `success`) using Tailwind `red-500` / `green-500` text and matching borders on\n * `bg-background` (no solid fill).\n */\n variant?: keyof typeof variantClass;\n /**\n * Corner radius. Labeled buttons default to `full` (pill). `iconOnly` buttons\n * default to `md` (square corners) unless you pass `rounded` explicitly.\n */\n rounded?: keyof typeof roundedClass;\n /** Height and horizontal padding: `default` or `lg` only. */\n size?: keyof typeof sizeClass;\n /**\n * Square icon-only control; same `size` presets (`default` | `lg`). Pair with\n * `aria-label` (or `title`) when there is no visible text.\n */\n iconOnly?: boolean;\n};\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n type = \"button\",\n variant = \"secondary\",\n rounded: roundedProp,\n size = \"default\",\n iconOnly = false,\n disabled,\n ...props\n },\n ref,\n ) => {\n const rounded = roundedProp ?? (iconOnly ? \"md\" : \"full\");\n\n return (\n <button\n type={type}\n disabled={disabled}\n data-slot=\"button\"\n data-icon-only={iconOnly ? \"\" : undefined}\n className={cn(\n \"inline-flex shrink-0 cursor-pointer items-center justify-center whitespace-nowrap outline-none scale-100 transition-[color,background-color,box-shadow,transform] duration-150 ease-out active:scale-[0.98] active:duration-100 active:ease-linear [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\",\n \"focus-visible:border-ring font-medium lg:tracking-wide focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n iconOnly ? iconOnlySizeClass[size] : sizeClass[size],\n roundedClass[rounded],\n variantClass[variant],\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n },\n);\nButton.displayName = \"Button\";\n\nexport { Button };\n","\"use client\";\n\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Button, type ButtonProps } from \"./button\";\n\nexport type PaginationMeta = {\n currentPage: number;\n totalItems: number;\n itemsPerPage: number;\n /** omit to derive `ceil(totalItems / itemsPerPage)` (minimum 1) */\n totalPages?: number;\n};\n\nexport type PaginationProps = {\n meta: PaginationMeta;\n onPageChange?: (page: number) => void;\n className?: string;\n /** max page numbers in the sliding window (excluding first/last when ellipses show; default 3) */\n maxVisibleButtons?: number;\n disabled?: boolean;\n /**\n * density preset → resolved `Button` size for every control (`xs` → `default`;\n * `default` / `lg` → `lg`) so chevrons and page cells share one hit grid.\n */\n size?: ButtonProps[\"size\"];\n /** same as `Button` `rounded`; pagination defaults to `full` */\n rounded?: NonNullable<ButtonProps[\"rounded\"]>;\n};\n\nconst PaginationInner = React.forwardRef<HTMLDivElement, PaginationProps>(\n function Pagination(\n {\n meta,\n onPageChange,\n className,\n maxVisibleButtons = 3,\n disabled = false,\n size = \"default\",\n rounded = \"full\",\n },\n ref,\n ) {\n const handlePageChange = React.useCallback(\n (page: number) => {\n onPageChange?.(page);\n },\n [onPageChange],\n );\n\n const totalPages = React.useMemo(() => {\n const totalItems = Math.max(0, Number(meta.totalItems) || 0);\n const itemsPerPage = Math.max(1, Number(meta.itemsPerPage) || 16);\n if (meta.totalPages != null && Number.isFinite(meta.totalPages)) {\n return Math.max(1, Math.floor(Number(meta.totalPages)));\n }\n return Math.max(1, Math.ceil(totalItems / itemsPerPage));\n }, [meta.totalItems, meta.itemsPerPage, meta.totalPages]);\n\n const currentPage = React.useMemo(\n () => Math.max(1, Number(meta.currentPage) || 1),\n [meta.currentPage],\n );\n\n const { endPage, adjustedStart } = React.useMemo(() => {\n const sp = Math.max(1, currentPage - Math.floor(maxVisibleButtons / 2));\n const ep = Math.min(totalPages, sp + maxVisibleButtons - 1);\n const adj =\n ep - sp + 1 < maxVisibleButtons ? Math.max(1, ep - maxVisibleButtons + 1) : sp;\n return { endPage: ep, adjustedStart: adj };\n }, [currentPage, totalPages, maxVisibleButtons]);\n\n const middlePageNumbers = React.useMemo(\n () =>\n Array.from({ length: endPage - adjustedStart + 1 }, (_, i) => adjustedStart + i),\n [endPage, adjustedStart],\n );\n\n const navButtonSize = React.useMemo(\n (): NonNullable<ButtonProps[\"size\"]> => (size === \"xs\" ? \"default\" : \"lg\"),\n [size],\n );\n\n const ellipsisClassName = React.useMemo(\n () =>\n cn(\n \"inline-flex shrink-0 items-center justify-center\",\n navButtonSize === \"lg\"\n ? \"size-11 min-h-11 min-w-11\"\n : \"size-10 min-h-10 min-w-10\",\n rounded === \"full\"\n ? \"rounded-full\"\n : rounded === \"lg\"\n ? \"rounded-lg\"\n : \"rounded-md\",\n ),\n [navButtonSize, rounded],\n );\n\n const gapIconClassName = React.useMemo(\n () =>\n cn(\n \"mx-auto shrink-0 text-primary/45\",\n navButtonSize === \"lg\" ? \"size-[18px]\" : \"size-4\",\n ),\n [navButtonSize],\n );\n\n if (totalPages <= 1) return null;\n\n return (\n <div ref={ref} className={cn(\"flex w-full justify-center\", className)}>\n <nav\n role=\"navigation\"\n aria-label=\"Pagination\"\n className=\"text-primary flex items-center justify-center gap-0.5 text-base font-medium tabular-nums tracking-tight\"\n >\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-0 tracking-tight focus-visible:border-transparent focus-visible:ring-0\"\n disabled={disabled || currentPage <= 1}\n onClick={() => handlePageChange(currentPage - 1)}\n aria-label=\"Previous page\"\n >\n <ChevronLeft aria-hidden className=\"size-5 shrink-0 mr-0.5\" />\n </Button>\n <div className=\"flex items-center gap-0.5\">\n {adjustedStart > 1 && (\n <>\n {currentPage === 1 ? (\n <Button\n type=\"button\"\n variant=\"primary\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"tracking-tight\"\n aria-current=\"page\"\n tabIndex={-1}\n >\n <span className=\"tabular-nums\">{1}</span>\n </Button>\n ) : (\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-none tracking-tight\"\n disabled={disabled}\n onClick={() => handlePageChange(1)}\n aria-label=\"Go to page 1\"\n >\n <span className=\"tabular-nums\">1</span>\n </Button>\n )}\n {adjustedStart > 2 && (\n <span aria-hidden className={ellipsisClassName}>\n <MoreHorizontal className={gapIconClassName} aria-hidden />\n </span>\n )}\n </>\n )}\n {middlePageNumbers.map((page) =>\n currentPage === page ? (\n <Button\n key={page}\n type=\"button\"\n variant=\"primary\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"tracking-tight\"\n aria-current=\"page\"\n tabIndex={-1}\n >\n <span className=\"tabular-nums\">{page}</span>\n </Button>\n ) : (\n <Button\n key={page}\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-none tracking-tight\"\n disabled={disabled}\n onClick={() => handlePageChange(page)}\n aria-label={`Go to page ${page}`}\n >\n <span className=\"tabular-nums\">{page}</span>\n </Button>\n ),\n )}\n {endPage < totalPages && (\n <>\n {endPage < totalPages - 1 && (\n <span aria-hidden className={ellipsisClassName}>\n <MoreHorizontal className={gapIconClassName} aria-hidden />\n </span>\n )}\n {currentPage === totalPages ? (\n <Button\n type=\"button\"\n variant=\"primary\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"tracking-tight\"\n aria-current=\"page\"\n tabIndex={-1}\n >\n <span className=\"tabular-nums\">{totalPages}</span>\n </Button>\n ) : (\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-none tracking-tight\"\n disabled={disabled}\n onClick={() => handlePageChange(totalPages)}\n aria-label={`Go to page ${totalPages}`}\n >\n <span className=\"tabular-nums\">{totalPages}</span>\n </Button>\n )}\n </>\n )}\n </div>\n <Button\n type=\"button\"\n rounded={rounded}\n iconOnly\n size={navButtonSize}\n className=\"border-0 tracking-tight focus-visible:border-transparent focus-visible:ring-0\"\n disabled={disabled || currentPage >= totalPages}\n onClick={() => handlePageChange(currentPage + 1)}\n aria-label=\"Next page\"\n >\n <ChevronRight aria-hidden className=\"size-5 shrink-0 ml-0.5\" />\n </Button>\n </nav>\n </div>\n );\n },\n);\n\nPaginationInner.displayName = \"Pagination\";\n\nexport const Pagination = React.memo(PaginationInner);\n"]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
declare const Popover: React__default.FC<{
|
|
4
|
+
children: React__default.ReactNode;
|
|
5
|
+
open?: boolean;
|
|
6
|
+
onOpenChange?: (open: boolean) => void;
|
|
7
|
+
}>;
|
|
8
|
+
declare const PopoverTrigger: React__default.FC<{
|
|
9
|
+
children: React__default.ReactNode;
|
|
10
|
+
asChild?: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
declare const PopoverClose: React__default.FC<{
|
|
13
|
+
children: React__default.ReactNode;
|
|
14
|
+
asChild?: boolean;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* Narrow-viewport (≤1024px) bottom-sheet options for {@link PopoverContent}.
|
|
18
|
+
* `className` merges onto the sheet panel root (after base sheet styles).
|
|
19
|
+
*/
|
|
20
|
+
interface PopoverMobileSheetOptions {
|
|
21
|
+
/** When `true`, use a bottom sheet on narrow viewports. Default `false`. */
|
|
22
|
+
sheet?: boolean;
|
|
23
|
+
title?: string;
|
|
24
|
+
className?: string;
|
|
25
|
+
contentClassName?: string;
|
|
26
|
+
}
|
|
27
|
+
interface PopoverMobileCloseProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Dismiss control for the mobile bottom-sheet popover. Styling matches
|
|
31
|
+
* {@link DialogCloseButton} (circular hit target, X icon).
|
|
32
|
+
*/
|
|
33
|
+
declare const PopoverMobileClose: React__default.ForwardRefExoticComponent<PopoverMobileCloseProps & React__default.RefAttributes<HTMLButtonElement>>;
|
|
34
|
+
type Side = "top" | "right" | "bottom" | "left";
|
|
35
|
+
type Align = "start" | "center" | "end";
|
|
36
|
+
interface PopoverContentProps extends React__default.HTMLAttributes<HTMLDivElement> {
|
|
37
|
+
/** Which side of the trigger to render on */
|
|
38
|
+
side?: Side;
|
|
39
|
+
/** Alignment along the cross-axis */
|
|
40
|
+
align?: Align;
|
|
41
|
+
/** Gap between trigger and popover in px */
|
|
42
|
+
offset?: number;
|
|
43
|
+
/** Show a small arrow pointing to the trigger */
|
|
44
|
+
showArrow?: boolean;
|
|
45
|
+
/** Close when clicking outside */
|
|
46
|
+
closeOnClickOutside?: boolean;
|
|
47
|
+
/** Close when Escape key is pressed */
|
|
48
|
+
closeOnEscape?: boolean;
|
|
49
|
+
/** Animation duration in ms */
|
|
50
|
+
duration?: number;
|
|
51
|
+
/** Minimum distance from the viewport edge in px */
|
|
52
|
+
viewportPadding?: number;
|
|
53
|
+
/** Portal container – defaults to document.body */
|
|
54
|
+
container?: HTMLElement | null;
|
|
55
|
+
/** Width of the popover. 'trigger' matches the trigger width. */
|
|
56
|
+
width?: "auto" | "trigger" | number;
|
|
57
|
+
/**
|
|
58
|
+
* Narrow-viewport (≤1024px) bottom sheet — same options as dropdown
|
|
59
|
+
* `mobileOptions`, except `sheet` defaults to `false`.
|
|
60
|
+
*/
|
|
61
|
+
mobileOptions?: PopoverMobileSheetOptions;
|
|
62
|
+
/**
|
|
63
|
+
* Mobile bottom sheet only. When `true` (default), panel motion matches Dialog
|
|
64
|
+
* `slideEntrance`; when `false`, uses full `translateY(100%)`.
|
|
65
|
+
*/
|
|
66
|
+
slideEntrance?: boolean;
|
|
67
|
+
/** Mobile sheet only; defaults to 120px (same as dropdown / dialog full sheet). */
|
|
68
|
+
slideEntranceOffsetPx?: number;
|
|
69
|
+
}
|
|
70
|
+
declare const PopoverContent: React__default.FC<PopoverContentProps>;
|
|
71
|
+
declare const PopoverHeader: React__default.FC<React__default.HTMLAttributes<HTMLDivElement>>;
|
|
72
|
+
declare const PopoverFooter: React__default.FC<React__default.HTMLAttributes<HTMLDivElement>>;
|
|
73
|
+
declare const PopoverTitle: React__default.FC<React__default.HTMLAttributes<HTMLHeadingElement>>;
|
|
74
|
+
declare const PopoverDescription: React__default.FC<React__default.HTMLAttributes<HTMLParagraphElement>>;
|
|
75
|
+
|
|
76
|
+
export { Popover, PopoverClose, PopoverContent, PopoverDescription, PopoverFooter, PopoverHeader, PopoverMobileClose, type PopoverMobileCloseProps, type PopoverMobileSheetOptions, PopoverTitle, PopoverTrigger };
|
|
@@ -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
|