@avenue-ticketing/ui 0.1.0 → 0.3.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.
@@ -0,0 +1,169 @@
1
+ import { clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+ import { createContext, useRef, useContext, useEffect, Children, isValidElement } from 'react';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ function cn(...inputs) {
7
+ return twMerge(clsx(inputs));
8
+ }
9
+ var DATA_ATTR = "data-scrolled";
10
+ var ScrollHeaderContext = createContext({
11
+ revealAt: "center",
12
+ slideIn: true,
13
+ onRevealChange: void 0
14
+ });
15
+ function isScrollHeaderStickyEl(child) {
16
+ return child.type.displayName === "ScrollHeaderSticky";
17
+ }
18
+ function isScrollHeaderTopEl(child) {
19
+ return child.type.displayName === "ScrollHeaderTop";
20
+ }
21
+ function reorderScrollHeaderChildren(children) {
22
+ const sticky = [];
23
+ const top = [];
24
+ const rest = [];
25
+ Children.forEach(children, (child) => {
26
+ if (!isValidElement(child)) {
27
+ if (child != null && child !== false) rest.push(child);
28
+ return;
29
+ }
30
+ if (isScrollHeaderStickyEl(child)) sticky.push(child);
31
+ else if (isScrollHeaderTopEl(child)) top.push(child);
32
+ else rest.push(child);
33
+ });
34
+ return [...sticky, ...top, ...rest];
35
+ }
36
+ var ScrollHeader = ({
37
+ revealAt,
38
+ slideIn = true,
39
+ onRevealChange,
40
+ children,
41
+ className,
42
+ ...props
43
+ }) => {
44
+ const ref = useRef(null);
45
+ const resolvedRevealAt = revealAt ?? (slideIn ? "center" : "start");
46
+ return /* @__PURE__ */ jsx(
47
+ ScrollHeaderContext.Provider,
48
+ {
49
+ value: {
50
+ revealAt: resolvedRevealAt,
51
+ slideIn,
52
+ onRevealChange
53
+ },
54
+ children: /* @__PURE__ */ jsx(
55
+ "div",
56
+ {
57
+ ref,
58
+ "data-scrolled": "false",
59
+ className: cn(
60
+ "scroll-header bg-background flex h-full flex-col overflow-y-auto",
61
+ className
62
+ ),
63
+ ...props,
64
+ children: reorderScrollHeaderChildren(children)
65
+ }
66
+ )
67
+ }
68
+ );
69
+ };
70
+ var sentinelClass = "pointer-events-none h-px w-full shrink-0";
71
+ var ScrollHeaderTop = ({
72
+ children,
73
+ className,
74
+ ...props
75
+ }) => {
76
+ const { revealAt, onRevealChange } = useContext(ScrollHeaderContext);
77
+ const sentinelRef = useRef(null);
78
+ const onRevealChangeRef = useRef(onRevealChange);
79
+ onRevealChangeRef.current = onRevealChange;
80
+ const lastRevealedRef = useRef(void 0);
81
+ useEffect(() => {
82
+ const sentinel = sentinelRef.current;
83
+ if (!sentinel) return;
84
+ const container = sentinel.closest("[data-scrolled]");
85
+ if (!container) return;
86
+ lastRevealedRef.current = void 0;
87
+ const observer = new IntersectionObserver(
88
+ ([entry]) => {
89
+ if (!entry) return;
90
+ const revealed = !entry.isIntersecting;
91
+ container.setAttribute(DATA_ATTR, revealed ? "true" : "false");
92
+ if (lastRevealedRef.current !== revealed) {
93
+ lastRevealedRef.current = revealed;
94
+ onRevealChangeRef.current?.(revealed);
95
+ }
96
+ },
97
+ { root: container, threshold: 0 }
98
+ );
99
+ observer.observe(sentinel);
100
+ return () => observer.disconnect();
101
+ }, [revealAt]);
102
+ if (revealAt === "end") {
103
+ return /* @__PURE__ */ jsxs("div", { className: cn("shrink-0", className), ...props, children: [
104
+ children,
105
+ /* @__PURE__ */ jsx("div", { ref: sentinelRef, className: sentinelClass, "aria-hidden": true })
106
+ ] });
107
+ }
108
+ if (revealAt === "center") {
109
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative shrink-0", className), ...props, children: [
110
+ /* @__PURE__ */ jsx(
111
+ "div",
112
+ {
113
+ ref: sentinelRef,
114
+ className: cn(
115
+ sentinelClass,
116
+ "absolute left-0 right-0 top-1/2 z-0 -translate-y-1/2"
117
+ ),
118
+ "aria-hidden": true
119
+ }
120
+ ),
121
+ children
122
+ ] });
123
+ }
124
+ return /* @__PURE__ */ jsxs("div", { className: cn("shrink-0", className), ...props, children: [
125
+ /* @__PURE__ */ jsx("div", { ref: sentinelRef, className: sentinelClass, "aria-hidden": true }),
126
+ children
127
+ ] });
128
+ };
129
+ ScrollHeaderTop.displayName = "ScrollHeaderTop";
130
+ var stickyChromeBgClass = "bg-background supports-backdrop-filter:bg-background";
131
+ var stickyChromeBorderClass = "border-primary/10 border-b";
132
+ var stickyChromeClass = cn(stickyChromeBgClass, stickyChromeBorderClass);
133
+ var revealEase = "duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:duration-0 motion-reduce:transition-none";
134
+ var ScrollHeaderSticky = ({
135
+ children,
136
+ className,
137
+ ...props
138
+ }) => {
139
+ const { slideIn } = useContext(ScrollHeaderContext);
140
+ return /* @__PURE__ */ jsx(
141
+ "div",
142
+ {
143
+ className: cn(
144
+ "sticky top-0 z-40",
145
+ slideIn ? "h-0 overflow-visible" : "shrink-0"
146
+ ),
147
+ children: slideIn ? /* @__PURE__ */ jsx(
148
+ "div",
149
+ {
150
+ className: cn(
151
+ stickyChromeClass,
152
+ "transition-[opacity, transform]",
153
+ revealEase,
154
+ '[.scroll-header:not([data-scrolled="true"])_&]:pointer-events-none [.scroll-header:not([data-scrolled="true"])_&]:-translate-y-1 [.scroll-header:not([data-scrolled="true"])_&]:opacity-0',
155
+ '[.scroll-header[data-scrolled="true"]_&]:translate-y-0 [.scroll-header[data-scrolled="true"]_&]:opacity-100',
156
+ className
157
+ ),
158
+ ...props,
159
+ children
160
+ }
161
+ ) : /* @__PURE__ */ jsx("div", { className: stickyChromeBgClass, children: /* @__PURE__ */ jsx("div", { className: cn(stickyChromeBorderClass, className), ...props, children }) })
162
+ }
163
+ );
164
+ };
165
+ ScrollHeaderSticky.displayName = "ScrollHeaderSticky";
166
+
167
+ export { ScrollHeader, ScrollHeaderSticky, ScrollHeaderTop };
168
+ //# sourceMappingURL=scroll-header.js.map
169
+ //# sourceMappingURL=scroll-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/utils.ts","../../src/react/scroll-header.tsx"],"names":[],"mappings":"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","file":"scroll-header.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 { cn } from \"@/lib/utils\";\nimport {\n Children,\n createContext,\n isValidElement,\n ReactElement,\n ReactNode,\n useContext,\n useEffect,\n useRef,\n} from \"react\";\n\nconst DATA_ATTR = \"data-scrolled\";\n\nexport type ScrollHeaderRevealAt = \"start\" | \"center\" | \"end\";\n\ninterface ScrollHeaderContextValue {\n revealAt: ScrollHeaderRevealAt;\n slideIn: boolean;\n onRevealChange?: (revealed: boolean) => void;\n}\n\nconst ScrollHeaderContext = createContext<ScrollHeaderContextValue>({\n revealAt: \"center\",\n slideIn: true,\n onRevealChange: undefined,\n});\n\nfunction isScrollHeaderStickyEl(child: ReactElement): boolean {\n return (\n (child.type as { displayName?: string }).displayName ===\n \"ScrollHeaderSticky\"\n );\n}\n\nfunction isScrollHeaderTopEl(child: ReactElement): boolean {\n return (\n (child.type as { displayName?: string }).displayName === \"ScrollHeaderTop\"\n );\n}\n\n/** Sticky first so `position: sticky; top: 0` pins to the scrollport, not below the hero. */\nfunction reorderScrollHeaderChildren(children: ReactNode): ReactNode[] {\n const sticky: ReactNode[] = [];\n const top: ReactNode[] = [];\n const rest: ReactNode[] = [];\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) {\n if (child != null && child !== false) rest.push(child);\n return;\n }\n if (isScrollHeaderStickyEl(child)) sticky.push(child);\n else if (isScrollHeaderTopEl(child)) top.push(child);\n else rest.push(child);\n });\n\n return [...sticky, ...top, ...rest];\n}\n\ninterface ScrollHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n /**\n * Which part of `ScrollHeaderTop` must leave the scrollport before the sticky bar shows.\n * `start` — top edge (earliest). `center` — vertical midpoint. `end` — bottom edge (latest).\n * If omitted: defaults to `center` when `slideIn` is true, and `start` when `slideIn` is false (in-flow bar).\n */\n revealAt?: ScrollHeaderRevealAt;\n /**\n * When `true` (default), `ScrollHeaderSticky` overlays without layout height and slides in with opacity.\n * When `false`, the sticky bar stays in document flow (takes vertical space); use `onRevealChange` and\n * your own styles for any fade or toolbar behavior.\n */\n slideIn?: boolean;\n /**\n * Called when the sticky header reveal state changes after scroll.\n * `true` once the top section has crossed the reveal threshold (same moment as `data-scrolled=\"true\"`).\n */\n onRevealChange?: (revealed: boolean) => void;\n}\n\nconst ScrollHeader: React.FC<ScrollHeaderProps> = ({\n revealAt,\n slideIn = true,\n onRevealChange,\n children,\n className,\n ...props\n}) => {\n const ref = useRef<HTMLDivElement>(null);\n const resolvedRevealAt = revealAt ?? (slideIn ? \"center\" : \"start\");\n\n return (\n <ScrollHeaderContext.Provider\n value={{\n revealAt: resolvedRevealAt,\n slideIn,\n onRevealChange,\n }}\n >\n <div\n ref={ref}\n data-scrolled=\"false\"\n className={cn(\n \"scroll-header bg-background flex h-full flex-col overflow-y-auto\",\n className,\n )}\n {...props}\n >\n {reorderScrollHeaderChildren(children)}\n </div>\n </ScrollHeaderContext.Provider>\n );\n};\n\nconst sentinelClass = \"pointer-events-none h-px w-full shrink-0\";\n\nconst ScrollHeaderTop: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n}) => {\n const { revealAt, onRevealChange } = useContext(ScrollHeaderContext);\n const sentinelRef = useRef<HTMLDivElement>(null);\n const onRevealChangeRef = useRef(onRevealChange);\n onRevealChangeRef.current = onRevealChange;\n const lastRevealedRef = useRef<boolean | undefined>(undefined);\n\n useEffect(() => {\n const sentinel = sentinelRef.current;\n if (!sentinel) return;\n\n const container = sentinel.closest<HTMLElement>(\"[data-scrolled]\");\n if (!container) return;\n\n lastRevealedRef.current = undefined;\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (!entry) return;\n const revealed = !entry.isIntersecting;\n container.setAttribute(DATA_ATTR, revealed ? \"true\" : \"false\");\n if (lastRevealedRef.current !== revealed) {\n lastRevealedRef.current = revealed;\n onRevealChangeRef.current?.(revealed);\n }\n },\n { root: container, threshold: 0 },\n );\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [revealAt]);\n\n if (revealAt === \"end\") {\n return (\n <div className={cn(\"shrink-0\", className)} {...props}>\n {children}\n <div ref={sentinelRef} className={sentinelClass} aria-hidden />\n </div>\n );\n }\n\n if (revealAt === \"center\") {\n return (\n <div className={cn(\"relative shrink-0\", className)} {...props}>\n <div\n ref={sentinelRef}\n className={cn(\n sentinelClass,\n \"absolute left-0 right-0 top-1/2 z-0 -translate-y-1/2\",\n )}\n aria-hidden\n />\n {children}\n </div>\n );\n }\n\n return (\n <div className={cn(\"shrink-0\", className)} {...props}>\n <div ref={sentinelRef} className={sentinelClass} aria-hidden />\n {children}\n </div>\n );\n};\n\nScrollHeaderTop.displayName = \"ScrollHeaderTop\";\n\nconst stickyChromeBgClass =\n \"bg-background supports-backdrop-filter:bg-background\";\n\nconst stickyChromeBorderClass = \"border-primary/10 border-b\";\n\nconst stickyChromeClass = cn(stickyChromeBgClass, stickyChromeBorderClass);\n\nconst revealEase =\n \"duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:duration-0 motion-reduce:transition-none\";\n\nconst ScrollHeaderSticky: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n}) => {\n const { slideIn } = useContext(ScrollHeaderContext);\n\n return (\n <div\n className={cn(\n \"sticky top-0 z-40\",\n slideIn ? \"h-0 overflow-visible\" : \"shrink-0\",\n )}\n >\n {slideIn ? (\n <div\n className={cn(\n stickyChromeClass,\n \"transition-[opacity, transform]\",\n revealEase,\n '[.scroll-header:not([data-scrolled=\"true\"])_&]:pointer-events-none [.scroll-header:not([data-scrolled=\"true\"])_&]:-translate-y-1 [.scroll-header:not([data-scrolled=\"true\"])_&]:opacity-0',\n '[.scroll-header[data-scrolled=\"true\"]_&]:translate-y-0 [.scroll-header[data-scrolled=\"true\"]_&]:opacity-100',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n ) : (\n <div className={stickyChromeBgClass}>\n <div className={cn(stickyChromeBorderClass, className)} {...props}>\n {children}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nScrollHeaderSticky.displayName = \"ScrollHeaderSticky\";\n\nexport { ScrollHeader, ScrollHeaderSticky, ScrollHeaderTop };\n"]}
@@ -1,10 +1,10 @@
1
- import React from 'react';
1
+ import React__default from 'react';
2
2
 
3
- declare const SheetBoundary: React.FC<React.HTMLAttributes<HTMLDivElement> & {
4
- children: React.ReactNode;
3
+ declare const SheetBoundary: React__default.FC<React__default.HTMLAttributes<HTMLDivElement> & {
4
+ children: React__default.ReactNode;
5
5
  }>;
6
- declare const Sheet: React.FC<{
7
- children: React.ReactNode;
6
+ declare const Sheet: React__default.FC<{
7
+ children: React__default.ReactNode;
8
8
  open?: boolean;
9
9
  onOpenChange?: (open: boolean) => void;
10
10
  /**
@@ -13,16 +13,30 @@ declare const Sheet: React.FC<{
13
13
  */
14
14
  showBackdrop?: boolean;
15
15
  }>;
16
- declare const SheetTrigger: React.FC<{
17
- children: React.ReactNode;
16
+ declare const SheetTrigger: React__default.FC<{
17
+ children: React__default.ReactNode;
18
18
  asChild?: boolean;
19
19
  }>;
20
- declare const SheetClose: React.FC<{
21
- children: React.ReactNode;
20
+ declare const SheetClose: React__default.FC<{
21
+ children: React__default.ReactNode;
22
22
  asChild?: boolean;
23
23
  afterClose?: () => void;
24
24
  }>;
25
- interface SheetContentProps extends React.HTMLAttributes<HTMLDivElement> {
25
+ type SheetCloseButtonSide = "top" | "right" | "bottom" | "left";
26
+ interface SheetCloseButtonProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
27
+ /**
28
+ * Desktop offset matches {@link SheetContent} for the same `side`; default
29
+ * `right` matches `SheetContent` default.
30
+ */
31
+ side?: SheetCloseButtonSide;
32
+ }
33
+ /**
34
+ * Default dismiss control for {@link SheetContent}. Includes absolute placement
35
+ * for the given `side`; pass `className` to adjust or replace positioning.
36
+ * When `onClick` is omitted, uses sheet context to call `setOpen(false)`.
37
+ */
38
+ declare const SheetCloseButton: React__default.ForwardRefExoticComponent<SheetCloseButtonProps & React__default.RefAttributes<HTMLButtonElement>>;
39
+ interface SheetContentProps extends React__default.HTMLAttributes<HTMLDivElement> {
26
40
  side?: "top" | "right" | "bottom" | "left";
27
41
  size?: "sm" | "md" | "lg" | "xl" | "full";
28
42
  closeThreshold?: number;
@@ -31,15 +45,15 @@ interface SheetContentProps extends React.HTMLAttributes<HTMLDivElement> {
31
45
  showClose?: boolean;
32
46
  duration?: number;
33
47
  }
34
- declare const SheetContent: React.FC<SheetContentProps>;
35
- declare const SheetHeader: React.FC<React.HTMLAttributes<HTMLDivElement> & {
48
+ declare const SheetContent: React__default.FC<SheetContentProps>;
49
+ declare const SheetHeader: React__default.FC<React__default.HTMLAttributes<HTMLDivElement> & {
36
50
  fixed?: boolean;
37
51
  }>;
38
- declare const SheetFooter: React.FC<React.HTMLAttributes<HTMLDivElement> & {
52
+ declare const SheetFooter: React__default.FC<React__default.HTMLAttributes<HTMLDivElement> & {
39
53
  fixed?: boolean;
40
54
  }>;
41
- declare const SheetTitle: React.FC<React.HTMLAttributes<HTMLHeadingElement>>;
42
- declare const SheetDescription: React.FC<React.HTMLAttributes<HTMLParagraphElement>>;
55
+ declare const SheetTitle: React__default.FC<React__default.HTMLAttributes<HTMLHeadingElement>>;
56
+ declare const SheetDescription: React__default.FC<React__default.HTMLAttributes<HTMLParagraphElement>>;
43
57
  /**
44
58
  * Circular back control for nested sheets (arrow, same footprint as the default
45
59
  * sheet close icon). Wraps `SheetClose` with `asChild`.
@@ -49,8 +63,8 @@ declare const SheetDescription: React.FC<React.HTMLAttributes<HTMLParagraphEleme
49
63
  * over a delayed `onClick` when opening another sheet so the exit uses the
50
64
  * handoff timing built into `Sheet`.
51
65
  */
52
- declare const SheetNestedClose: React.FC<React.ComponentPropsWithoutRef<"button"> & {
53
- children?: React.ReactNode;
66
+ declare const SheetNestedClose: React__default.FC<React__default.ComponentPropsWithoutRef<"button"> & {
67
+ children?: React__default.ReactNode;
54
68
  /**
55
69
  * Runs after the close animation when chaining another sheet. Uses a shorter
56
70
  * exit (see `SheetSetOpenOptions.afterClose`).
@@ -58,4 +72,4 @@ declare const SheetNestedClose: React.FC<React.ComponentPropsWithoutRef<"button"
58
72
  afterClose?: () => void;
59
73
  }>;
60
74
 
61
- export { Sheet, SheetBoundary, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetNestedClose, SheetTitle, SheetTrigger };
75
+ export { Sheet, SheetBoundary, SheetClose, SheetCloseButton, type SheetCloseButtonProps, type SheetCloseButtonSide, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetNestedClose, SheetTitle, SheetTrigger };
@@ -1,9 +1,9 @@
1
- import React, { useState, useCallback, useMemo, useEffect, useLayoutEffect } from 'react';
1
+ import React, { useCallback, useState, useMemo, useEffect, useLayoutEffect } from 'react';
2
2
  import { createPortal } from 'react-dom';
3
3
  import { X, ArrowLeft } from 'lucide-react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
7
 
8
8
  function cn(...inputs) {
9
9
  return twMerge(clsx(inputs));
@@ -29,6 +29,8 @@ var DIALOG_EXIT_MOTION_EASING = "cubic-bezier(0.85, 0, 1, 0.15)";
29
29
  var DIALOG_MOTION_OFFSET_PX = 120;
30
30
  var PANEL_OFF_X = "112%";
31
31
  var PANEL_OFF_Y = "100%";
32
+ var SHEET_Z_PANEL_CLOSE = 100;
33
+ var SHEET_Z_PORTAL_STEP = 10;
32
34
  var SIDE_LAYOUT = {
33
35
  top: "top-0 left-0 right-0 border-b border-primary/10",
34
36
  bottom: "bottom-0 left-0 right-0 border-t border-primary/10",
@@ -255,6 +257,39 @@ function useSheetScrollLock(open, setOpen, bounded, nestDepth) {
255
257
  return () => window.removeEventListener("keydown", handleEscNested, true);
256
258
  }, [open, setOpen, bounded, nestDepth]);
257
259
  }
260
+ var SheetCloseButton = React.forwardRef(
261
+ ({ className, side = "right", style, type = "button", onClick, ...props }, ref) => {
262
+ const { setOpen } = useSheetContext();
263
+ const handleClick = useCallback(
264
+ (e) => {
265
+ onClick?.(e);
266
+ if (onClick == null) {
267
+ setOpen(false);
268
+ }
269
+ },
270
+ [onClick, setOpen]
271
+ );
272
+ return /* @__PURE__ */ jsxs(
273
+ "button",
274
+ {
275
+ ref,
276
+ type,
277
+ style: { zIndex: SHEET_Z_PANEL_CLOSE, ...style },
278
+ className: cn(
279
+ "flex size-12 cursor-pointer items-center justify-center rounded-full md:bg-background transition-all hover:bg-secondary-background active:scale-[0.96] md:border md:border-primary/10 md:shadow-xl hover:border-primary/20",
280
+ className
281
+ ),
282
+ onClick: handleClick,
283
+ ...props,
284
+ children: [
285
+ /* @__PURE__ */ jsx(X, { className: "size-5.5" }),
286
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
287
+ ]
288
+ }
289
+ );
290
+ }
291
+ );
292
+ SheetCloseButton.displayName = "SheetCloseButton";
258
293
  var SheetContent = ({
259
294
  children,
260
295
  side = "right",
@@ -499,7 +534,7 @@ var SheetContent = ({
499
534
  [dialogMotion, isAnimating, side, bounded]
500
535
  );
501
536
  const boundaryDepth = boundaryCtx?.depth ?? 0;
502
- const zIndex = bounded ? 10 + boundaryDepth * 10 + (nestDepth - 1) * 2 : 50 + (nestDepth - 1) * 10;
537
+ const zIndex = bounded ? SHEET_Z_PANEL_CLOSE + SHEET_Z_PORTAL_STEP + boundaryDepth * SHEET_Z_PORTAL_STEP + (nestDepth - 1) * 2 : SHEET_Z_PANEL_CLOSE - 5 * SHEET_Z_PORTAL_STEP + (nestDepth - 1) * SHEET_Z_PORTAL_STEP;
503
538
  const layerPosition = bounded ? "absolute" : "fixed";
504
539
  const backdropStyle = useMemo(() => {
505
540
  if (!showBackdrop) return { transition: "none" };
@@ -599,23 +634,17 @@ var SheetContent = ({
599
634
  onTouchEnd: swipeActive ? handleTouchEnd : void 0,
600
635
  children: [
601
636
  children,
602
- showClose && /* @__PURE__ */ jsxs(
603
- "button",
637
+ showClose && /* @__PURE__ */ jsx(
638
+ SheetCloseButton,
604
639
  {
605
- type: "button",
606
- onClick: closeSheet,
640
+ side,
607
641
  className: cn(
608
- "absolute flex size-12 cursor-pointer items-center justify-center rounded-full md:border md:border-primary/10 bg-background md:shadow-xl transition-all hover:bg-secondary-background hover:border-primary/20 active:scale-[0.96]",
609
- "top-4 right-4",
642
+ "absolute top-4 right-4",
610
643
  side === "right" && "md:top-5 md:right-auto md:-left-16",
611
644
  side === "left" && "md:top-5 md:-right-16 md:left-auto",
612
645
  side === "top" && "md:top-auto md:right-auto md:-bottom-15 md:left-1/2 md:-translate-x-1/2",
613
646
  side === "bottom" && "md:-top-15 md:right-auto md:bottom-auto md:left-1/2 md:-translate-x-1/2"
614
- ),
615
- children: [
616
- /* @__PURE__ */ jsx(X, { className: "size-5.5" }),
617
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
618
- ]
647
+ )
619
648
  }
620
649
  )
621
650
  ]
@@ -679,6 +708,6 @@ var SheetNestedClose = ({ className, children, onClick, afterClose, ...props })
679
708
  }
680
709
  ) });
681
710
 
682
- export { Sheet, SheetBoundary, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetNestedClose, SheetTitle, SheetTrigger };
711
+ export { Sheet, SheetBoundary, SheetClose, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetNestedClose, SheetTitle, SheetTrigger };
683
712
  //# sourceMappingURL=sheet.js.map
684
713
  //# sourceMappingURL=sheet.js.map