@avenue-ticketing/ui 0.2.0 → 0.4.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/badge.d.ts +55 -0
- package/dist/react/badge.js +64 -0
- package/dist/react/badge.js.map +1 -0
- package/dist/react/dialog.d.ts +16 -1
- package/dist/react/dialog.js +242 -101
- package/dist/react/dialog.js.map +1 -1
- package/dist/react/dropdown.d.ts +109 -0
- package/dist/react/dropdown.js +1171 -0
- package/dist/react/dropdown.js.map +1 -0
- package/dist/react/scroll-header.d.ts +19 -1
- package/dist/react/scroll-header.js +129 -40
- package/dist/react/scroll-header.js.map +1 -1
- package/dist/react/sheet.d.ts +15 -1
- package/dist/react/sheet.js +44 -16
- package/dist/react/sheet.js.map +1 -1
- package/dist/react/tabs.d.ts +28 -0
- package/dist/react/tabs.js +267 -0
- package/dist/react/tabs.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
/** Matches `button.tsx` primary / secondary — no separate outline variants. */
|
|
4
|
+
declare const variantClass: {
|
|
5
|
+
readonly primary: "border border-transparent bg-primary text-background";
|
|
6
|
+
readonly secondary: "border border-primary/10 bg-transparent text-primary";
|
|
7
|
+
};
|
|
8
|
+
/** Same keys as `button.tsx` `roundedClass`. */
|
|
9
|
+
declare const roundedClass: {
|
|
10
|
+
readonly full: "rounded-full";
|
|
11
|
+
readonly lg: "rounded-lg";
|
|
12
|
+
readonly md: "rounded-md";
|
|
13
|
+
};
|
|
14
|
+
declare const sizeClass: {
|
|
15
|
+
readonly md: "min-h-6 min-w-6 px-2 text-xs";
|
|
16
|
+
readonly lg: "min-h-7 min-w-7 px-2.5 text-sm";
|
|
17
|
+
};
|
|
18
|
+
type BadgeProps = React.HTMLAttributes<HTMLSpanElement> & {
|
|
19
|
+
/** @default secondary — same as Button default. */
|
|
20
|
+
variant?: keyof typeof variantClass;
|
|
21
|
+
/** @default md */
|
|
22
|
+
size?: keyof typeof sizeClass;
|
|
23
|
+
/**
|
|
24
|
+
* Corner radius — same options as `Button` (`full` | `lg` | `md`).
|
|
25
|
+
* @default full (pill)
|
|
26
|
+
*/
|
|
27
|
+
rounded?: keyof typeof roundedClass;
|
|
28
|
+
/**
|
|
29
|
+
* When set, the label is the number capped at `max` with a "+" suffix
|
|
30
|
+
* (e.g. `max={99}` → `99+`). Ignores `children` for the visible text.
|
|
31
|
+
*/
|
|
32
|
+
count?: number;
|
|
33
|
+
/** Upper bound before showing `{max}+`. Default `99`. */
|
|
34
|
+
max?: number;
|
|
35
|
+
};
|
|
36
|
+
declare const Badge: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & {
|
|
37
|
+
/** @default secondary — same as Button default. */
|
|
38
|
+
variant?: keyof typeof variantClass;
|
|
39
|
+
/** @default md */
|
|
40
|
+
size?: keyof typeof sizeClass;
|
|
41
|
+
/**
|
|
42
|
+
* Corner radius — same options as `Button` (`full` | `lg` | `md`).
|
|
43
|
+
* @default full (pill)
|
|
44
|
+
*/
|
|
45
|
+
rounded?: keyof typeof roundedClass;
|
|
46
|
+
/**
|
|
47
|
+
* When set, the label is the number capped at `max` with a "+" suffix
|
|
48
|
+
* (e.g. `max={99}` → `99+`). Ignores `children` for the visible text.
|
|
49
|
+
*/
|
|
50
|
+
count?: number;
|
|
51
|
+
/** Upper bound before showing `{max}+`. Default `99`. */
|
|
52
|
+
max?: number;
|
|
53
|
+
} & React.RefAttributes<HTMLSpanElement>>;
|
|
54
|
+
|
|
55
|
+
export { Badge, type BadgeProps };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
function cn(...inputs) {
|
|
7
|
+
return twMerge(clsx(inputs));
|
|
8
|
+
}
|
|
9
|
+
var variantClass = {
|
|
10
|
+
primary: "border border-transparent bg-primary text-background",
|
|
11
|
+
secondary: "border border-primary/10 bg-transparent text-primary"
|
|
12
|
+
};
|
|
13
|
+
var roundedClass = {
|
|
14
|
+
full: "rounded-full",
|
|
15
|
+
lg: "rounded-lg",
|
|
16
|
+
md: "rounded-md"
|
|
17
|
+
};
|
|
18
|
+
var sizeClass = {
|
|
19
|
+
md: "min-h-6 min-w-6 px-2 text-xs",
|
|
20
|
+
lg: "min-h-7 min-w-7 px-2.5 text-sm"
|
|
21
|
+
};
|
|
22
|
+
function formatCount(count, max) {
|
|
23
|
+
if (count > max) return `${max}+`;
|
|
24
|
+
return String(count);
|
|
25
|
+
}
|
|
26
|
+
var Badge = React.forwardRef(
|
|
27
|
+
({
|
|
28
|
+
className,
|
|
29
|
+
variant = "secondary",
|
|
30
|
+
size = "md",
|
|
31
|
+
rounded = "full",
|
|
32
|
+
count,
|
|
33
|
+
max = 99,
|
|
34
|
+
children,
|
|
35
|
+
"aria-label": ariaLabelProp,
|
|
36
|
+
...props
|
|
37
|
+
}, ref) => {
|
|
38
|
+
const content = count !== void 0 ? formatCount(count, max) : children;
|
|
39
|
+
return /* @__PURE__ */ jsx(
|
|
40
|
+
"span",
|
|
41
|
+
{
|
|
42
|
+
ref,
|
|
43
|
+
"data-slot": "badge",
|
|
44
|
+
"data-size": size,
|
|
45
|
+
"data-rounded": rounded,
|
|
46
|
+
"aria-label": ariaLabelProp,
|
|
47
|
+
className: cn(
|
|
48
|
+
"inline-flex shrink-0 items-center justify-center font-semibold leading-none tabular-nums",
|
|
49
|
+
roundedClass[rounded],
|
|
50
|
+
sizeClass[size],
|
|
51
|
+
variantClass[variant],
|
|
52
|
+
className
|
|
53
|
+
),
|
|
54
|
+
...props,
|
|
55
|
+
children: content
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
Badge.displayName = "Badge";
|
|
61
|
+
|
|
62
|
+
export { Badge };
|
|
63
|
+
//# sourceMappingURL=badge.js.map
|
|
64
|
+
//# sourceMappingURL=badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/utils.ts","../../src/react/badge.tsx"],"names":[],"mappings":";;;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACEA,IAAM,YAAA,GAAe;AAAA,EACnB,OAAA,EAAS,sDAAA;AAAA,EACT,SAAA,EAAW;AACb,CAAA;AAGA,IAAM,YAAA,GAAe;AAAA,EACnB,IAAA,EAAM,cAAA;AAAA,EACN,EAAA,EAAI,YAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEA,IAAM,SAAA,GAAY;AAAA,EAChB,EAAA,EAAI,8BAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAqBA,SAAS,WAAA,CAAY,OAAe,GAAA,EAAqB;AACvD,EAAA,IAAI,KAAA,GAAQ,GAAA,EAAK,OAAO,CAAA,EAAG,GAAG,CAAA,CAAA,CAAA;AAC9B,EAAA,OAAO,OAAO,KAAK,CAAA;AACrB;AAEA,IAAM,KAAA,GAAc,KAAA,CAAA,UAAA;AAAA,EAClB,CACE;AAAA,IACE,SAAA;AAAA,IACA,OAAA,GAAU,WAAA;AAAA,IACV,IAAA,GAAO,IAAA;AAAA,IACP,OAAA,GAAU,MAAA;AAAA,IACV,KAAA;AAAA,IACA,GAAA,GAAM,EAAA;AAAA,IACN,QAAA;AAAA,IACA,YAAA,EAAc,aAAA;AAAA,IACd,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,UAAU,KAAA,KAAU,MAAA,GAAY,WAAA,CAAY,KAAA,EAAO,GAAG,CAAA,GAAI,QAAA;AAEhE,IAAA,uBACE,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,WAAA,EAAU,OAAA;AAAA,QACV,WAAA,EAAW,IAAA;AAAA,QACX,cAAA,EAAc,OAAA;AAAA,QACd,YAAA,EAAY,aAAA;AAAA,QACZ,SAAA,EAAW,EAAA;AAAA,UACT,0FAAA;AAAA,UACA,aAAa,OAAO,CAAA;AAAA,UACpB,UAAU,IAAI,CAAA;AAAA,UACd,aAAa,OAAO,CAAA;AAAA,UACpB;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA;AAAA,KACH;AAAA,EAEJ;AACF;AAEA,KAAA,CAAM,WAAA,GAAc,OAAA","file":"badge.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\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/** Matches `button.tsx` primary / secondary — no separate outline variants. */\nconst variantClass = {\n primary: \"border border-transparent bg-primary text-background\",\n secondary: \"border border-primary/10 bg-transparent text-primary\",\n} as const;\n\n/** Same keys as `button.tsx` `roundedClass`. */\nconst roundedClass = {\n full: \"rounded-full\",\n lg: \"rounded-lg\",\n md: \"rounded-md\",\n} as const;\n\nconst sizeClass = {\n md: \"min-h-6 min-w-6 px-2 text-xs\",\n lg: \"min-h-7 min-w-7 px-2.5 text-sm\",\n} as const;\n\nexport type BadgeProps = React.HTMLAttributes<HTMLSpanElement> & {\n /** @default secondary — same as Button default. */\n variant?: keyof typeof variantClass;\n /** @default md */\n size?: keyof typeof sizeClass;\n /**\n * Corner radius — same options as `Button` (`full` | `lg` | `md`).\n * @default full (pill)\n */\n rounded?: keyof typeof roundedClass;\n /**\n * When set, the label is the number capped at `max` with a \"+\" suffix\n * (e.g. `max={99}` → `99+`). Ignores `children` for the visible text.\n */\n count?: number;\n /** Upper bound before showing `{max}+`. Default `99`. */\n max?: number;\n};\n\nfunction formatCount(count: number, max: number): string {\n if (count > max) return `${max}+`;\n return String(count);\n}\n\nconst Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n (\n {\n className,\n variant = \"secondary\",\n size = \"md\",\n rounded = \"full\",\n count,\n max = 99,\n children,\n \"aria-label\": ariaLabelProp,\n ...props\n },\n ref,\n ) => {\n const content = count !== undefined ? formatCount(count, max) : children;\n\n return (\n <span\n ref={ref}\n data-slot=\"badge\"\n data-size={size}\n data-rounded={rounded}\n aria-label={ariaLabelProp}\n className={cn(\n \"inline-flex shrink-0 items-center justify-center font-semibold leading-none tabular-nums\",\n roundedClass[rounded],\n sizeClass[size],\n variantClass[variant],\n className,\n )}\n {...props}\n >\n {content}\n </span>\n );\n },\n);\n\nBadge.displayName = \"Badge\";\n\nexport { Badge };\n"]}
|
package/dist/react/dialog.d.ts
CHANGED
|
@@ -14,14 +14,29 @@ declare const DialogClose: React__default.FC<{
|
|
|
14
14
|
children: React__default.ReactNode;
|
|
15
15
|
asChild?: boolean;
|
|
16
16
|
}>;
|
|
17
|
+
interface DialogCloseButtonProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Default dismiss control for {@link DialogContent}. Includes absolute top-right
|
|
21
|
+
* placement; pass `className` to adjust or replace positioning.
|
|
22
|
+
* When `onClick` is omitted, closes via the surrounding `Dialog` context (`setOpen(false)`).
|
|
23
|
+
*/
|
|
24
|
+
declare const DialogCloseButton: React__default.ForwardRefExoticComponent<DialogCloseButtonProps & React__default.RefAttributes<HTMLButtonElement>>;
|
|
17
25
|
interface DialogContentProps extends React__default.HTMLAttributes<HTMLDivElement> {
|
|
18
26
|
size?: "sm" | "md" | "lg" | "xl" | "full";
|
|
19
27
|
duration?: number;
|
|
20
28
|
closeOnOverlayClick?: boolean;
|
|
21
29
|
showClose?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* When `true` (default), viewports ≤1024px use a bottom-anchored panel and
|
|
32
|
+
* slide-up motion (same breakpoint as {@link SheetContent}). Wider viewports
|
|
33
|
+
* keep the centered dialog. Set `false` to always use the centered dialog.
|
|
34
|
+
*/
|
|
35
|
+
mobileBottomSheet?: boolean;
|
|
22
36
|
/**
|
|
23
37
|
* When `true`, panel uses translateY + opacity with fixed timing and separate
|
|
24
38
|
* entry/exit curves (works with any `size`). Default `false` uses scale + fade.
|
|
39
|
+
* Ignored when `mobileBottomSheet` applies on a narrow viewport.
|
|
25
40
|
*/
|
|
26
41
|
slideEntrance?: boolean;
|
|
27
42
|
/** Override slide distance (px); default follows `size` via `SLIDE_ENTRANCE_OFFSET_PX`. */
|
|
@@ -37,4 +52,4 @@ declare const DialogFooter: React__default.FC<React__default.HTMLAttributes<HTML
|
|
|
37
52
|
declare const DialogTitle: React__default.FC<React__default.HTMLAttributes<HTMLHeadingElement>>;
|
|
38
53
|
declare const DialogDescription: React__default.FC<React__default.HTMLAttributes<HTMLParagraphElement>>;
|
|
39
54
|
|
|
40
|
-
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger };
|
|
55
|
+
export { Dialog, DialogClose, DialogCloseButton, type DialogCloseButtonProps, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger };
|
package/dist/react/dialog.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React, { useState,
|
|
1
|
+
import React, { useCallback, useState, useMemo, useEffect, useSyncExternalStore } from 'react';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { twMerge } from 'tailwind-merge';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
5
|
import { X } from 'lucide-react';
|
|
6
|
-
import {
|
|
6
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
7
7
|
|
|
8
8
|
function cn(...inputs) {
|
|
9
9
|
return twMerge(clsx(inputs));
|
|
@@ -11,6 +11,43 @@ function cn(...inputs) {
|
|
|
11
11
|
var DIALOG_MOTION_MS = 200;
|
|
12
12
|
var DIALOG_ENTRY_MOTION_EASING = "cubic-bezier(0.85, 0, 0.15, 1)";
|
|
13
13
|
var DIALOG_EXIT_MOTION_EASING = "cubic-bezier(0.85, 0, 1, 0.15)";
|
|
14
|
+
var DIALOG_MOBILE_BOTTOM_SHEET_MAX_PX = 1024;
|
|
15
|
+
var DIALOG_Z_BASE = 50;
|
|
16
|
+
var DIALOG_Z_STEP = 10;
|
|
17
|
+
var dialogBodyScrollLockCount = 0;
|
|
18
|
+
var dialogEscapeClosers = [];
|
|
19
|
+
function dialogEscapeOnKeydown(e) {
|
|
20
|
+
if (e.key !== "Escape") return;
|
|
21
|
+
const top = dialogEscapeClosers[dialogEscapeClosers.length - 1];
|
|
22
|
+
if (!top) return;
|
|
23
|
+
e.preventDefault();
|
|
24
|
+
top();
|
|
25
|
+
}
|
|
26
|
+
function dialogPushEscapeCloser(closer) {
|
|
27
|
+
dialogEscapeClosers.push(closer);
|
|
28
|
+
if (dialogEscapeClosers.length === 1) {
|
|
29
|
+
window.addEventListener("keydown", dialogEscapeOnKeydown, true);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function dialogPopEscapeCloser(closer) {
|
|
33
|
+
const i = dialogEscapeClosers.lastIndexOf(closer);
|
|
34
|
+
if (i >= 0) dialogEscapeClosers.splice(i, 1);
|
|
35
|
+
if (dialogEscapeClosers.length === 0) {
|
|
36
|
+
window.removeEventListener("keydown", dialogEscapeOnKeydown, true);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function useDialogMobileBottomSheetViewport() {
|
|
40
|
+
const query = `(max-width: ${DIALOG_MOBILE_BOTTOM_SHEET_MAX_PX}px)`;
|
|
41
|
+
return useSyncExternalStore(
|
|
42
|
+
(onChange) => {
|
|
43
|
+
const mq = window.matchMedia(query);
|
|
44
|
+
mq.addEventListener("change", onChange);
|
|
45
|
+
return () => mq.removeEventListener("change", onChange);
|
|
46
|
+
},
|
|
47
|
+
() => window.matchMedia(query).matches,
|
|
48
|
+
() => false
|
|
49
|
+
);
|
|
50
|
+
}
|
|
14
51
|
var SLIDE_ENTRANCE_OFFSET_PX = {
|
|
15
52
|
sm: 16,
|
|
16
53
|
md: 16,
|
|
@@ -18,6 +55,18 @@ var SLIDE_ENTRANCE_OFFSET_PX = {
|
|
|
18
55
|
xl: 16,
|
|
19
56
|
full: 120
|
|
20
57
|
};
|
|
58
|
+
var SIZE_CLASSES = {
|
|
59
|
+
sm: "sm:max-w-sm",
|
|
60
|
+
md: "sm:max-w-md",
|
|
61
|
+
lg: "sm:max-w-lg",
|
|
62
|
+
xl: "sm:max-w-xl"
|
|
63
|
+
};
|
|
64
|
+
var SIZE_CLASSES_LG_ONLY = {
|
|
65
|
+
sm: "lg:max-w-sm",
|
|
66
|
+
md: "lg:max-w-md",
|
|
67
|
+
lg: "lg:max-w-lg",
|
|
68
|
+
xl: "lg:max-w-xl"
|
|
69
|
+
};
|
|
21
70
|
function useDialogRenderLifecycle(open, panelCloseMs) {
|
|
22
71
|
const [shouldRender, setShouldRender] = useState(open);
|
|
23
72
|
const [isAnimating, setIsAnimating] = useState(false);
|
|
@@ -43,7 +92,9 @@ function useDialogRenderLifecycle(open, panelCloseMs) {
|
|
|
43
92
|
}, [shouldRender, open]);
|
|
44
93
|
return { shouldRender, isAnimating };
|
|
45
94
|
}
|
|
46
|
-
var DialogContext = React.createContext(
|
|
95
|
+
var DialogContext = React.createContext(
|
|
96
|
+
void 0
|
|
97
|
+
);
|
|
47
98
|
function useDialog() {
|
|
48
99
|
const context = React.useContext(DialogContext);
|
|
49
100
|
if (!context) {
|
|
@@ -56,6 +107,9 @@ var Dialog = ({
|
|
|
56
107
|
open: controlledOpen,
|
|
57
108
|
onOpenChange
|
|
58
109
|
}) => {
|
|
110
|
+
const parentCtx = React.useContext(DialogContext);
|
|
111
|
+
const parentDepth = parentCtx?.depth ?? 0;
|
|
112
|
+
const depth = parentDepth + 1;
|
|
59
113
|
const [internalOpen, setInternalOpen] = useState(false);
|
|
60
114
|
const isControlled = controlledOpen !== void 0;
|
|
61
115
|
const open = isControlled ? controlledOpen : internalOpen;
|
|
@@ -68,7 +122,11 @@ var Dialog = ({
|
|
|
68
122
|
},
|
|
69
123
|
[isControlled, onOpenChange]
|
|
70
124
|
);
|
|
71
|
-
|
|
125
|
+
const contextValue = useMemo(
|
|
126
|
+
() => ({ open, setOpen, depth }),
|
|
127
|
+
[open, setOpen, depth]
|
|
128
|
+
);
|
|
129
|
+
return /* @__PURE__ */ jsx(DialogContext.Provider, { value: contextValue, children });
|
|
72
130
|
};
|
|
73
131
|
var DialogTrigger = ({ children, asChild }) => {
|
|
74
132
|
const { setOpen } = useDialog();
|
|
@@ -98,6 +156,36 @@ var DialogClose = ({ children, asChild }) => {
|
|
|
98
156
|
}
|
|
99
157
|
return /* @__PURE__ */ jsx("button", { type: "button", onClick: handleClick, children });
|
|
100
158
|
};
|
|
159
|
+
var DialogCloseButton = React.forwardRef(({ className, type = "button", onClick, ...props }, ref) => {
|
|
160
|
+
const { setOpen } = useDialog();
|
|
161
|
+
const handleClick = useCallback(
|
|
162
|
+
(e) => {
|
|
163
|
+
onClick?.(e);
|
|
164
|
+
if (onClick == null) {
|
|
165
|
+
setOpen(false);
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
[onClick, setOpen]
|
|
169
|
+
);
|
|
170
|
+
return /* @__PURE__ */ jsxs(
|
|
171
|
+
"button",
|
|
172
|
+
{
|
|
173
|
+
ref,
|
|
174
|
+
type,
|
|
175
|
+
className: cn(
|
|
176
|
+
"z-100 flex size-12 cursor-pointer items-center justify-center rounded-full transition-all hover:bg-secondary-background active:scale-[0.96]",
|
|
177
|
+
className
|
|
178
|
+
),
|
|
179
|
+
onClick: handleClick,
|
|
180
|
+
...props,
|
|
181
|
+
children: [
|
|
182
|
+
/* @__PURE__ */ jsx(X, { className: "size-5.5" }),
|
|
183
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
184
|
+
]
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
});
|
|
188
|
+
DialogCloseButton.displayName = "DialogCloseButton";
|
|
101
189
|
var DialogContent = ({
|
|
102
190
|
children,
|
|
103
191
|
size = "md",
|
|
@@ -105,118 +193,171 @@ var DialogContent = ({
|
|
|
105
193
|
duration = 200,
|
|
106
194
|
closeOnOverlayClick = true,
|
|
107
195
|
showClose = true,
|
|
196
|
+
mobileBottomSheet = true,
|
|
108
197
|
slideEntrance = false,
|
|
109
198
|
slideEntranceOffsetPx: slideEntranceOffsetPxProp,
|
|
110
|
-
...
|
|
199
|
+
...rest
|
|
111
200
|
}) => {
|
|
112
|
-
const { open, setOpen } = useDialog();
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
|
|
201
|
+
const { open, setOpen, depth } = useDialog();
|
|
202
|
+
const isNarrowViewport = useDialogMobileBottomSheetViewport();
|
|
203
|
+
const useMobileBottomSheet = useMemo(
|
|
204
|
+
() => mobileBottomSheet !== false && isNarrowViewport,
|
|
205
|
+
[mobileBottomSheet, isNarrowViewport]
|
|
206
|
+
);
|
|
207
|
+
const useMobileBottomSheetChrome = useMemo(
|
|
208
|
+
() => mobileBottomSheet !== false && size !== "full",
|
|
209
|
+
[mobileBottomSheet, size]
|
|
210
|
+
);
|
|
211
|
+
const slideOffsetPx = useMemo(
|
|
212
|
+
() => slideEntranceOffsetPxProp ?? SLIDE_ENTRANCE_OFFSET_PX[size],
|
|
213
|
+
[slideEntranceOffsetPxProp, size]
|
|
214
|
+
);
|
|
215
|
+
const useBottomSheetMotion = useMobileBottomSheet;
|
|
216
|
+
const useDesktopSlideEntrance = slideEntrance && !useBottomSheetMotion;
|
|
217
|
+
const panelCloseMs = useMemo(
|
|
218
|
+
() => useBottomSheetMotion ? DIALOG_MOTION_MS : slideEntrance ? DIALOG_MOTION_MS : duration,
|
|
219
|
+
[useBottomSheetMotion, slideEntrance, duration]
|
|
220
|
+
);
|
|
116
221
|
const { shouldRender, isAnimating } = useDialogRenderLifecycle(
|
|
117
222
|
open,
|
|
118
223
|
panelCloseMs
|
|
119
224
|
);
|
|
120
|
-
const slideMotionEasing =
|
|
225
|
+
const slideMotionEasing = useMemo(
|
|
226
|
+
() => open ? DIALOG_ENTRY_MOTION_EASING : DIALOG_EXIT_MOTION_EASING,
|
|
227
|
+
[open]
|
|
228
|
+
);
|
|
229
|
+
const portalZIndex = useMemo(
|
|
230
|
+
() => DIALOG_Z_BASE + (depth - 1) * DIALOG_Z_STEP,
|
|
231
|
+
[depth]
|
|
232
|
+
);
|
|
233
|
+
const handleOverlayClick = useCallback(() => {
|
|
234
|
+
if (closeOnOverlayClick) setOpen(false);
|
|
235
|
+
}, [closeOnOverlayClick, setOpen]);
|
|
121
236
|
useEffect(() => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
document.body.style.overflow = "hidden";
|
|
129
|
-
}
|
|
237
|
+
if (!open || typeof document === "undefined") return;
|
|
238
|
+
const closer = () => setOpen(false);
|
|
239
|
+
dialogPushEscapeCloser(closer);
|
|
240
|
+
dialogBodyScrollLockCount += 1;
|
|
241
|
+
if (dialogBodyScrollLockCount === 1) {
|
|
242
|
+
document.body.style.overflow = "hidden";
|
|
130
243
|
}
|
|
131
244
|
return () => {
|
|
132
|
-
|
|
133
|
-
|
|
245
|
+
dialogPopEscapeCloser(closer);
|
|
246
|
+
dialogBodyScrollLockCount -= 1;
|
|
247
|
+
if (dialogBodyScrollLockCount <= 0) {
|
|
248
|
+
dialogBodyScrollLockCount = 0;
|
|
134
249
|
document.body.style.overflow = "";
|
|
135
250
|
}
|
|
136
251
|
};
|
|
137
252
|
}, [open, setOpen]);
|
|
253
|
+
const rootClassName = useMemo(
|
|
254
|
+
() => cn(
|
|
255
|
+
"fixed inset-0 flex",
|
|
256
|
+
size === "full" ? "h-dvh w-full flex-col p-0" : mobileBottomSheet !== false ? "max-lg:items-end max-lg:justify-center max-lg:p-0 lg:items-center lg:justify-center lg:p-4" : "items-center justify-center p-4"
|
|
257
|
+
),
|
|
258
|
+
[size, mobileBottomSheet]
|
|
259
|
+
);
|
|
260
|
+
const rootStyle = useMemo(
|
|
261
|
+
() => ({ zIndex: portalZIndex }),
|
|
262
|
+
[portalZIndex]
|
|
263
|
+
);
|
|
264
|
+
const overlayClassName = useMemo(
|
|
265
|
+
() => cn(
|
|
266
|
+
"fixed inset-0 bg-black/40 dark:bg-black/60",
|
|
267
|
+
!useBottomSheetMotion && !slideEntrance && "transition-opacity ease-in-out",
|
|
268
|
+
isAnimating ? "opacity-100" : "opacity-0"
|
|
269
|
+
),
|
|
270
|
+
[useBottomSheetMotion, slideEntrance, isAnimating]
|
|
271
|
+
);
|
|
272
|
+
const overlayStyle = useMemo(() => {
|
|
273
|
+
const style = {
|
|
274
|
+
transitionDuration: `${panelCloseMs}ms`
|
|
275
|
+
};
|
|
276
|
+
if (useBottomSheetMotion || slideEntrance) {
|
|
277
|
+
style.transitionProperty = "opacity";
|
|
278
|
+
style.transitionTimingFunction = slideMotionEasing;
|
|
279
|
+
}
|
|
280
|
+
return style;
|
|
281
|
+
}, [panelCloseMs, useBottomSheetMotion, slideEntrance, slideMotionEasing]);
|
|
282
|
+
const panelClassName = useMemo(() => {
|
|
283
|
+
const sizeKey = size === "full" ? null : size;
|
|
284
|
+
return cn(
|
|
285
|
+
"bg-background relative z-10 w-full overflow-hidden shadow-2xl",
|
|
286
|
+
size === "full" ? "flex min-h-0 flex-1 flex-col max-w-none rounded-none" : cn(
|
|
287
|
+
"border-primary/10 border",
|
|
288
|
+
useMobileBottomSheetChrome ? "max-lg:max-h-[min(90dvh,calc(100dvh-env(safe-area-inset-bottom,0px)))] max-lg:rounded-t-2xl max-lg:rounded-b-none max-lg:border-x-0 max-lg:border-b-0 max-lg:border-t max-lg:border-primary/10 lg:rounded-2xl" : "rounded-2xl",
|
|
289
|
+
sizeKey && (useMobileBottomSheetChrome ? SIZE_CLASSES_LG_ONLY[sizeKey] : SIZE_CLASSES[sizeKey])
|
|
290
|
+
),
|
|
291
|
+
!useBottomSheetMotion && !useDesktopSlideEntrance && cn(
|
|
292
|
+
"transition-all ease-in-out",
|
|
293
|
+
isAnimating ? "scale-100 opacity-100" : "scale-95 opacity-0"
|
|
294
|
+
),
|
|
295
|
+
className
|
|
296
|
+
);
|
|
297
|
+
}, [
|
|
298
|
+
size,
|
|
299
|
+
useMobileBottomSheetChrome,
|
|
300
|
+
useBottomSheetMotion,
|
|
301
|
+
useDesktopSlideEntrance,
|
|
302
|
+
isAnimating,
|
|
303
|
+
className
|
|
304
|
+
]);
|
|
305
|
+
const panelStyle = useMemo(() => {
|
|
306
|
+
const base = { ...rest.style };
|
|
307
|
+
if (useBottomSheetMotion) {
|
|
308
|
+
return {
|
|
309
|
+
...base,
|
|
310
|
+
transform: isAnimating ? "translateY(0)" : "translateY(100%)",
|
|
311
|
+
opacity: isAnimating ? 1 : 0,
|
|
312
|
+
transitionProperty: "transform, opacity",
|
|
313
|
+
transitionDuration: `${DIALOG_MOTION_MS}ms`,
|
|
314
|
+
transitionTimingFunction: slideMotionEasing
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
if (useDesktopSlideEntrance) {
|
|
318
|
+
return {
|
|
319
|
+
...base,
|
|
320
|
+
transform: isAnimating ? "translateY(0)" : `translateY(${slideOffsetPx}px)`,
|
|
321
|
+
opacity: isAnimating ? 1 : 0,
|
|
322
|
+
transitionProperty: "transform, opacity",
|
|
323
|
+
transitionDuration: `${DIALOG_MOTION_MS}ms`,
|
|
324
|
+
transitionTimingFunction: slideMotionEasing
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
return {
|
|
328
|
+
...base,
|
|
329
|
+
transitionDuration: `${duration}ms`
|
|
330
|
+
};
|
|
331
|
+
}, [
|
|
332
|
+
rest.style,
|
|
333
|
+
useBottomSheetMotion,
|
|
334
|
+
useDesktopSlideEntrance,
|
|
335
|
+
isAnimating,
|
|
336
|
+
slideOffsetPx,
|
|
337
|
+
slideMotionEasing,
|
|
338
|
+
duration
|
|
339
|
+
]);
|
|
138
340
|
if (!shouldRender) return null;
|
|
139
|
-
const sizeClasses = {
|
|
140
|
-
sm: "sm:max-w-sm",
|
|
141
|
-
md: "sm:max-w-md",
|
|
142
|
-
lg: "sm:max-w-lg",
|
|
143
|
-
xl: "sm:max-w-xl"
|
|
144
|
-
};
|
|
145
341
|
return createPortal(
|
|
146
|
-
/* @__PURE__ */ jsxs(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
transitionProperty: "opacity",
|
|
166
|
-
transitionTimingFunction: slideMotionEasing
|
|
167
|
-
} : {}
|
|
168
|
-
},
|
|
169
|
-
onClick: () => closeOnOverlayClick && setOpen(false)
|
|
170
|
-
}
|
|
171
|
-
),
|
|
172
|
-
/* @__PURE__ */ jsxs(
|
|
173
|
-
"div",
|
|
174
|
-
{
|
|
175
|
-
...props,
|
|
176
|
-
className: cn(
|
|
177
|
-
"bg-background relative z-50 w-full overflow-hidden shadow-2xl",
|
|
178
|
-
size === "full" ? "flex min-h-0 flex-1 flex-col max-w-none rounded-none" : cn("border-primary/10 rounded-2xl border", sizeClasses[size]),
|
|
179
|
-
!slideEntrance && cn(
|
|
180
|
-
"transition-all ease-in-out",
|
|
181
|
-
isAnimating ? "scale-100 opacity-100" : "scale-95 opacity-0"
|
|
182
|
-
),
|
|
183
|
-
className
|
|
184
|
-
),
|
|
185
|
-
style: {
|
|
186
|
-
...props.style,
|
|
187
|
-
...slideEntrance ? {
|
|
188
|
-
transform: isAnimating ? "translateY(0)" : `translateY(${slideOffsetPx}px)`,
|
|
189
|
-
opacity: isAnimating ? 1 : 0,
|
|
190
|
-
transitionProperty: "transform, opacity",
|
|
191
|
-
transitionDuration: `${DIALOG_MOTION_MS}ms`,
|
|
192
|
-
transitionTimingFunction: slideMotionEasing
|
|
193
|
-
} : {
|
|
194
|
-
transitionDuration: `${duration}ms`
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
children: [
|
|
198
|
-
children,
|
|
199
|
-
showClose && /* @__PURE__ */ jsxs(
|
|
200
|
-
"button",
|
|
201
|
-
{
|
|
202
|
-
type: "button",
|
|
203
|
-
onClick: closeDialog,
|
|
204
|
-
className: cn(
|
|
205
|
-
// Above in-panel sticky layers (e.g. ScrollHeaderSticky z-40)
|
|
206
|
-
"absolute top-4 right-4 z-100 flex size-12 cursor-pointer items-center justify-center rounded-full bg-background transition-all hover:bg-secondary-background active:scale-[0.96] md:top-4 md:right-4"
|
|
207
|
-
),
|
|
208
|
-
children: [
|
|
209
|
-
/* @__PURE__ */ jsx(X, { className: "size-5.5" }),
|
|
210
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
211
|
-
]
|
|
212
|
-
}
|
|
213
|
-
)
|
|
214
|
-
]
|
|
215
|
-
}
|
|
216
|
-
)
|
|
217
|
-
]
|
|
218
|
-
}
|
|
219
|
-
),
|
|
342
|
+
/* @__PURE__ */ jsxs("div", { className: rootClassName, style: rootStyle, children: [
|
|
343
|
+
/* @__PURE__ */ jsx(
|
|
344
|
+
"div",
|
|
345
|
+
{
|
|
346
|
+
className: overlayClassName,
|
|
347
|
+
style: overlayStyle,
|
|
348
|
+
onClick: handleOverlayClick
|
|
349
|
+
}
|
|
350
|
+
),
|
|
351
|
+
/* @__PURE__ */ jsxs("div", { ...rest, className: panelClassName, style: panelStyle, children: [
|
|
352
|
+
children,
|
|
353
|
+
showClose && /* @__PURE__ */ jsx(
|
|
354
|
+
DialogCloseButton,
|
|
355
|
+
{
|
|
356
|
+
className: cn("absolute top-4 right-4 md:top-4 md:right-4")
|
|
357
|
+
}
|
|
358
|
+
)
|
|
359
|
+
] })
|
|
360
|
+
] }),
|
|
220
361
|
document.body
|
|
221
362
|
);
|
|
222
363
|
};
|
|
@@ -262,6 +403,6 @@ var DialogDescription = ({ className, ...props }) => {
|
|
|
262
403
|
return /* @__PURE__ */ jsx("p", { className: cn("text-muted-foreground text-sm", className), ...props });
|
|
263
404
|
};
|
|
264
405
|
|
|
265
|
-
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger };
|
|
406
|
+
export { Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger };
|
|
266
407
|
//# sourceMappingURL=dialog.js.map
|
|
267
408
|
//# sourceMappingURL=dialog.js.map
|