@photon-ai/pho-ui 4.3.1 → 4.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/chunks/{basic-page-OrUVXKrx.js → basic-page-D3MY3uY6.js} +751 -707
- package/dist/chunks/basic-page-D3MY3uY6.js.map +1 -0
- package/dist/chunks/bubble-eaoLJP4N.js +88 -0
- package/dist/chunks/bubble-eaoLJP4N.js.map +1 -0
- package/dist/chunks/{button-CdqS_t5a.js → button-CgUS0j3D.js} +4 -4
- package/dist/chunks/button-CgUS0j3D.js.map +1 -0
- package/dist/chunks/chat-DUqWlXqt.js +619 -0
- package/dist/chunks/chat-DUqWlXqt.js.map +1 -0
- package/dist/chunks/{code-block-BuDIo8Q0.js → code-block-BGgbp-6Q.js} +12 -12
- package/dist/chunks/{code-block-BuDIo8Q0.js.map → code-block-BGgbp-6Q.js.map} +1 -1
- package/dist/chunks/command-BfCCRaoc.js +225 -0
- package/dist/chunks/command-BfCCRaoc.js.map +1 -0
- package/dist/chunks/{copy-button-B_B15mEi.js → copy-button-D8XyP0oR.js} +10 -10
- package/dist/chunks/copy-button-D8XyP0oR.js.map +1 -0
- package/dist/chunks/{description-list-C-mwe4ki.js → description-list-8qm83WZB.js} +17 -17
- package/dist/chunks/description-list-8qm83WZB.js.map +1 -0
- package/dist/chunks/{dialog-BOz_xOrn.js → dialog-DeM4axJ6.js} +3 -3
- package/dist/chunks/{dialog-BOz_xOrn.js.map → dialog-DeM4axJ6.js.map} +1 -1
- package/dist/chunks/{error-BAQgnde7.js → error-VvHnteyf.js} +2 -2
- package/dist/chunks/{error-BAQgnde7.js.map → error-VvHnteyf.js.map} +1 -1
- package/dist/chunks/{filter-bar-Cr_1zBFq.js → filter-bar-BcpeTKCC.js} +38 -36
- package/dist/chunks/filter-bar-BcpeTKCC.js.map +1 -0
- package/dist/chunks/{log-list-BERiO4UJ.js → log-list-Didt-MV4.js} +2 -2
- package/dist/chunks/{log-list-BERiO4UJ.js.map → log-list-Didt-MV4.js.map} +1 -1
- package/dist/chunks/message-CTml-TrB.js +89 -0
- package/dist/chunks/message-CTml-TrB.js.map +1 -0
- package/dist/chunks/{scroll-area-Zik8t1Mk.js → scroll-area-DSwD9th7.js} +2 -2
- package/dist/chunks/{scroll-area-Zik8t1Mk.js.map → scroll-area-DSwD9th7.js.map} +1 -1
- package/dist/chunks/{sidebar-bLsjo_yb.js → sidebar-BmloUwJQ.js} +56 -56
- package/dist/chunks/sidebar-BmloUwJQ.js.map +1 -0
- package/dist/chunks/{toast-72Wwlzg9.js → toast-DUvjSZF7.js} +3 -3
- package/dist/chunks/{toast-72Wwlzg9.js.map → toast-DUvjSZF7.js.map} +1 -1
- package/dist/components/bubble.js +6 -0
- package/dist/components/button.js +1 -1
- package/dist/components/chat.js +5 -0
- package/dist/components/code-block.js +1 -1
- package/dist/components/command.js +1 -1
- package/dist/components/copy-button.js +1 -1
- package/dist/components/description-list.js +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/error.js +1 -1
- package/dist/components/filter-bar.js +1 -1
- package/dist/components/log-list.js +1 -1
- package/dist/components/message.js +7 -0
- package/dist/components/scroll-area.js +1 -1
- package/dist/components/toast.js +1 -1
- package/dist/index.js +145 -136
- package/dist/sections/basic-page.js +1 -1
- package/dist/sections/sidebar.js +1 -1
- package/dist/src/components/bubble/bubble.d.ts +112 -0
- package/dist/src/components/bubble/index.d.ts +1 -0
- package/dist/src/components/chat/chat.d.ts +301 -0
- package/dist/src/components/chat/index.d.ts +1 -0
- package/dist/src/components/command/command.d.ts +14 -4
- package/dist/src/components/command/index.d.ts +1 -1
- package/dist/src/components/filter-bar/filter-bar.d.ts +5 -0
- package/dist/src/components/message/index.d.ts +2 -0
- package/dist/src/components/message/message-status.d.ts +22 -0
- package/dist/src/components/message/message.d.ts +78 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/sections/basic-page/basic-page.d.ts +15 -2
- package/dist/src/sections/sidebar/sidebar.d.ts +10 -1
- package/package.json +13 -1
- package/dist/chunks/basic-page-OrUVXKrx.js.map +0 -1
- package/dist/chunks/button-CdqS_t5a.js.map +0 -1
- package/dist/chunks/command-Cn000hMK.js +0 -192
- package/dist/chunks/command-Cn000hMK.js.map +0 -1
- package/dist/chunks/copy-button-B_B15mEi.js.map +0 -1
- package/dist/chunks/description-list-C-mwe4ki.js.map +0 -1
- package/dist/chunks/filter-bar-Cr_1zBFq.js.map +0 -1
- package/dist/chunks/sidebar-bLsjo_yb.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-area-Zik8t1Mk.js","names":[],"sources":["../../src/components/scroll-area/scroll-area-edges.tsx","../../src/components/scroll-area/scroll-area.tsx"],"sourcesContent":["import { type Ref } from \"react\";\nimport { BLUR_PX } from \"../../motion\";\nimport { cn } from \"../../utils/cn\";\n\n/** Overlay strip height — a short ramp, not a banner. `h-8` = 32px. */\nexport const EDGE_CLASS = \"pointer-events-none absolute inset-x-0 z-10 h-8\";\nexport const EDGE_REVEAL_PX = 32;\n\nconst BLUR_LAYER_COUNT = 8;\n\n/**\n * The system's one blur strength. The edge fade peaks here, and a motion\n * that softens (a scope swap, a bar title) borrows the same value, so\n * every soft focus in the product is the same soft focus.\n */\nexport const BLUR_MAX_PX = BLUR_PX;\n\nfunction buildBlurLayers(count: number, maxPx: number) {\n const segment = 100 / (count + 1);\n return Array.from({ length: count }, (_, i) => ({\n blurPx: (i / (count - 1)) * maxPx,\n window: [\n i * segment,\n (i + 1) * segment,\n (i + 2) * segment,\n (i + 3) * segment,\n ] as const,\n })).filter((layer) => layer.blurPx > 0);\n}\n\nconst BLUR_LAYERS = buildBlurLayers(BLUR_LAYER_COUNT, BLUR_MAX_PX);\n\nfunction edgeMask(edge: \"top\" | \"bottom\", window: readonly number[]) {\n const toEdge = edge === \"top\" ? \"to top\" : \"to bottom\";\n const [a, b, c, d] = window;\n return `linear-gradient(${toEdge}, transparent ${a}%, black ${b}%, black ${c}%, transparent ${d}%)`;\n}\n\n// The wash fades into the block it sits on: every `bg-pho-*` surface\n// registers itself as `--pho-surface` (see the stylesheet), so the nearest\n// surface ancestor's background carries down here — live across themes.\n// The primary surface is the fallback for hosts outside any pho surface.\nconst DEFAULT_SURFACE =\n \"var(--pho-surface, var(--background-color-pho-primary))\";\n\nfunction washGradient(edge: \"top\" | \"bottom\", surface: string) {\n const to = edge === \"top\" ? \"to top\" : \"to bottom\";\n return `linear-gradient(${to}, color-mix(in oklab, ${surface} 20%, transparent) 0%, ${surface} 100%)`;\n}\n\nexport function paintEdge(node: HTMLDivElement | null, progress: number) {\n if (!node) return;\n for (const child of node.children) {\n const el = child as HTMLElement;\n if (el.dataset.scrollFade === \"wash\") {\n el.style.opacity = String(progress);\n continue;\n }\n const blur = `blur(${Number(el.dataset.blurPx) * progress}px)`;\n el.style.backdropFilter = blur;\n el.style.setProperty(\"-webkit-backdrop-filter\", blur);\n }\n}\n\nexport function Edge({\n edge,\n edgeRef,\n surface = DEFAULT_SURFACE,\n className,\n}: {\n edge: \"top\" | \"bottom\";\n edgeRef: Ref<HTMLDivElement>;\n /** The surface the wash fades into — the card by default, or a page. */\n surface?: string;\n /** Position override — the strip sits at the named edge unless placed. */\n className?: string;\n}) {\n return (\n <div\n ref={edgeRef}\n aria-hidden\n data-edge={edge}\n className={cn(\n EDGE_CLASS,\n className ?? (edge === \"top\" ? \"top-0\" : \"bottom-0\"),\n )}\n >\n {BLUR_LAYERS.map(({ blurPx, window }, index) => {\n const mask = edgeMask(edge, window);\n return (\n <div\n key={index}\n data-blur-px={blurPx}\n className=\"absolute inset-0\"\n style={{\n maskImage: mask,\n WebkitMaskImage: mask,\n }}\n />\n );\n })}\n <div\n data-scroll-fade=\"wash\"\n className=\"absolute inset-0 opacity-0\"\n style={{ background: washGradient(edge, surface) }}\n />\n </div>\n );\n}\n","import {\n createContext,\n useContext,\n useLayoutEffect,\n useRef,\n type ComponentProps,\n type ElementType,\n type Ref,\n type RefObject,\n} from \"react\";\nimport { ScrollArea as BaseScrollArea } from \"@base-ui/react/scroll-area\";\nimport { motion } from \"motion/react\";\nimport { cn } from \"../../utils/cn\";\nimport { Edge, EDGE_REVEAL_PX, paintEdge } from \"./scroll-area-edges\";\n\n/** Override Base UI's `string | (state) => string` className with plain string. */\ntype StyledProps<T extends ElementType> = Omit<\n ComponentProps<T>,\n \"className\"\n> & {\n className?: string;\n};\n\nconst ScrollAreaContext = createContext<{\n topEl: RefObject<HTMLDivElement | null>;\n bottomEl: RefObject<HTMLDivElement | null>;\n fade: boolean;\n} | null>(null);\n\nfunction useScrollAreaContext() {\n const ctx = useContext(ScrollAreaContext);\n if (ctx == null) {\n throw new Error(\"ScrollArea parts must be used inside ScrollArea.Root\");\n }\n return ctx;\n}\n\nfunction clamp01(n: number) {\n if (n <= 0) return 0;\n if (n >= 1) return 1;\n return n;\n}\n\nfunction assignRef<T>(ref: Ref<T> | undefined, node: T | null) {\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n // React 18 types `RefObject.current` as readonly; the write is legal.\n (ref as { current: T | null }).current = node;\n }\n}\n\n/**\n * The scrolled content. `inset` is a resting inset in the scroll axis —\n * like a scroll view's safe-area padding: the content stands clear of the\n * edges at rest but scrolls past them to the true edge, and the scrollbar\n * and edge fade stay on `Root`'s edges. `insetTop` / `insetBottom` set the\n * ends separately (they win over `inset`).\n */\nfunction Content({\n inset,\n insetTop,\n insetBottom,\n style,\n ref,\n ...props\n}: ComponentProps<typeof BaseScrollArea.Content> & {\n inset?: number | string;\n insetTop?: number | string;\n insetBottom?: number | string;\n ref?: Ref<HTMLDivElement>;\n}) {\n return (\n <BaseScrollArea.Content\n ref={ref}\n style={{\n paddingTop: insetTop ?? inset,\n paddingBottom: insetBottom ?? inset,\n ...style,\n }}\n {...props}\n />\n );\n}\n\nconst Corner = BaseScrollArea.Corner;\n\nfunction Root({\n className,\n children,\n fade = true,\n ...props\n}: StyledProps<typeof BaseScrollArea.Root> & {\n /**\n * Progressive edge fade (blur + wash). Leave on except for code\n * surfaces — CodeBlock is the only caller that turns it off, so\n * glyphs hard-clip at the border.\n * @default true\n */\n fade?: boolean;\n}) {\n const topEl = useRef<HTMLDivElement | null>(null);\n const bottomEl = useRef<HTMLDivElement | null>(null);\n\n return (\n <BaseScrollArea.Root\n className={cn(\"relative overflow-hidden\", className)}\n {...props}\n >\n <ScrollAreaContext.Provider value={{ topEl, bottomEl, fade }}>\n {children}\n {fade ? (\n <>\n <Edge edge=\"top\" edgeRef={topEl} />\n <Edge edge=\"bottom\" edgeRef={bottomEl} />\n </>\n ) : null}\n </ScrollAreaContext.Provider>\n </BaseScrollArea.Root>\n );\n}\n\nfunction Viewport({\n className,\n ref,\n ...props\n}: StyledProps<typeof BaseScrollArea.Viewport>) {\n const { topEl, bottomEl, fade } = useScrollAreaContext();\n const viewportRef = useRef<HTMLElement | null>(null);\n\n useLayoutEffect(() => {\n const viewport = viewportRef.current;\n if (!viewport || !fade) return;\n\n const paint = () => {\n const reveal =\n topEl.current?.offsetHeight ||\n bottomEl.current?.offsetHeight ||\n EDGE_REVEAL_PX;\n const maxScroll = viewport.scrollHeight - viewport.clientHeight;\n const top = maxScroll <= 0 ? 0 : clamp01(viewport.scrollTop / reveal);\n const bottom =\n maxScroll <= 0 ? 0 : clamp01((maxScroll - viewport.scrollTop) / reveal);\n paintEdge(topEl.current, top);\n paintEdge(bottomEl.current, bottom);\n };\n\n let frame = 0;\n const onScroll = () => {\n if (frame) return;\n frame = requestAnimationFrame(() => {\n frame = 0;\n paint();\n });\n };\n\n paint();\n viewport.addEventListener(\"scroll\", onScroll, { passive: true });\n let observer: ResizeObserver | null = null;\n if (typeof ResizeObserver !== \"undefined\") {\n observer = new ResizeObserver(paint);\n observer.observe(viewport);\n if (viewport.firstElementChild) {\n observer.observe(viewport.firstElementChild);\n }\n }\n return () => {\n viewport.removeEventListener(\"scroll\", onScroll);\n if (frame) cancelAnimationFrame(frame);\n observer?.disconnect();\n };\n }, [topEl, bottomEl, fade]);\n\n return (\n <BaseScrollArea.Viewport\n // A motion element with layoutScroll: any layout-animated content\n // inside (a shared-element morph, a FLIP row) projects against the\n // viewport's scroll offset instead of reading a scroll as a layout\n // change.\n render={<motion.div layoutScroll />}\n className={cn(\n \"outline-pho-brand h-full min-h-0 w-full overscroll-contain rounded-[inherit] focus-visible:outline-2 focus-visible:-outline-offset-1\",\n className,\n )}\n {...props}\n ref={(node) => {\n viewportRef.current = node;\n assignRef(ref, node);\n }}\n />\n );\n}\n\nfunction Scrollbar({\n className,\n ...props\n}: StyledProps<typeof BaseScrollArea.Scrollbar>) {\n return (\n <BaseScrollArea.Scrollbar\n className={cn(\n \"relative z-20 flex touch-none p-0.5 opacity-0 transition-opacity delay-300 select-none\",\n \"data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0 data-[scrolling]:duration-0\",\n \"data-[orientation=horizontal]:h-2.5 data-[orientation=horizontal]:flex-col data-[orientation=vertical]:w-2.5\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Thumb({\n className,\n ...props\n}: StyledProps<typeof BaseScrollArea.Thumb>) {\n return (\n <BaseScrollArea.Thumb\n className={cn(\n \"flex-1 rounded-full bg-[var(--border-color-pho-primary)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Scroll area built on Base UI `ScrollArea` — a capped region with overlay\n * scrollbars and progressive edge fade. Approaching rows blur (0 → 1px) and\n * wash into the surface; strength tracks scroll distance over one strip\n * height. Give `Root` a fixed size; put content in `Viewport` → `Content`\n * and add a `Scrollbar` → `Thumb` per axis.\n */\nexport const ScrollArea = {\n Root,\n Viewport,\n Content,\n Scrollbar,\n Thumb,\n Corner,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"scroll-area-DSwD9th7.js","names":[],"sources":["../../src/components/scroll-area/scroll-area-edges.tsx","../../src/components/scroll-area/scroll-area.tsx"],"sourcesContent":["import { type Ref } from \"react\";\nimport { BLUR_PX } from \"../../motion\";\nimport { cn } from \"../../utils/cn\";\n\n/** Overlay strip height — a short ramp, not a banner. `h-8` = 32px. */\nexport const EDGE_CLASS = \"pointer-events-none absolute inset-x-0 z-10 h-8\";\nexport const EDGE_REVEAL_PX = 32;\n\nconst BLUR_LAYER_COUNT = 8;\n\n/**\n * The system's one blur strength. The edge fade peaks here, and a motion\n * that softens (a scope swap, a bar title) borrows the same value, so\n * every soft focus in the product is the same soft focus.\n */\nexport const BLUR_MAX_PX = BLUR_PX;\n\nfunction buildBlurLayers(count: number, maxPx: number) {\n const segment = 100 / (count + 1);\n return Array.from({ length: count }, (_, i) => ({\n blurPx: (i / (count - 1)) * maxPx,\n window: [\n i * segment,\n (i + 1) * segment,\n (i + 2) * segment,\n (i + 3) * segment,\n ] as const,\n })).filter((layer) => layer.blurPx > 0);\n}\n\nconst BLUR_LAYERS = buildBlurLayers(BLUR_LAYER_COUNT, BLUR_MAX_PX);\n\nfunction edgeMask(edge: \"top\" | \"bottom\", window: readonly number[]) {\n const toEdge = edge === \"top\" ? \"to top\" : \"to bottom\";\n const [a, b, c, d] = window;\n return `linear-gradient(${toEdge}, transparent ${a}%, black ${b}%, black ${c}%, transparent ${d}%)`;\n}\n\n// The wash fades into the block it sits on: every `bg-pho-*` surface\n// registers itself as `--pho-surface` (see the stylesheet), so the nearest\n// surface ancestor's background carries down here — live across themes.\n// The primary surface is the fallback for hosts outside any pho surface.\nconst DEFAULT_SURFACE =\n \"var(--pho-surface, var(--background-color-pho-primary))\";\n\nfunction washGradient(edge: \"top\" | \"bottom\", surface: string) {\n const to = edge === \"top\" ? \"to top\" : \"to bottom\";\n return `linear-gradient(${to}, color-mix(in oklab, ${surface} 20%, transparent) 0%, ${surface} 100%)`;\n}\n\nexport function paintEdge(node: HTMLDivElement | null, progress: number) {\n if (!node) return;\n for (const child of node.children) {\n const el = child as HTMLElement;\n if (el.dataset.scrollFade === \"wash\") {\n el.style.opacity = String(progress);\n continue;\n }\n const blur = `blur(${Number(el.dataset.blurPx) * progress}px)`;\n el.style.backdropFilter = blur;\n el.style.setProperty(\"-webkit-backdrop-filter\", blur);\n }\n}\n\nexport function Edge({\n edge,\n edgeRef,\n surface = DEFAULT_SURFACE,\n className,\n}: {\n edge: \"top\" | \"bottom\";\n edgeRef: Ref<HTMLDivElement>;\n /** The surface the wash fades into — the card by default, or a page. */\n surface?: string;\n /** Position override — the strip sits at the named edge unless placed. */\n className?: string;\n}) {\n return (\n <div\n ref={edgeRef}\n aria-hidden\n data-edge={edge}\n className={cn(\n EDGE_CLASS,\n className ?? (edge === \"top\" ? \"top-0\" : \"bottom-0\"),\n )}\n >\n {BLUR_LAYERS.map(({ blurPx, window }, index) => {\n const mask = edgeMask(edge, window);\n return (\n <div\n key={index}\n data-blur-px={blurPx}\n className=\"absolute inset-0\"\n style={{\n maskImage: mask,\n WebkitMaskImage: mask,\n }}\n />\n );\n })}\n <div\n data-scroll-fade=\"wash\"\n className=\"absolute inset-0 opacity-0\"\n style={{ background: washGradient(edge, surface) }}\n />\n </div>\n );\n}\n","import {\n createContext,\n useContext,\n useLayoutEffect,\n useRef,\n type ComponentProps,\n type ElementType,\n type Ref,\n type RefObject,\n} from \"react\";\nimport { ScrollArea as BaseScrollArea } from \"@base-ui/react/scroll-area\";\nimport { motion } from \"motion/react\";\nimport { cn } from \"../../utils/cn\";\nimport { Edge, EDGE_REVEAL_PX, paintEdge } from \"./scroll-area-edges\";\n\n/** Override Base UI's `string | (state) => string` className with plain string. */\ntype StyledProps<T extends ElementType> = Omit<\n ComponentProps<T>,\n \"className\"\n> & {\n className?: string;\n};\n\nconst ScrollAreaContext = createContext<{\n topEl: RefObject<HTMLDivElement | null>;\n bottomEl: RefObject<HTMLDivElement | null>;\n fade: boolean;\n} | null>(null);\n\nfunction useScrollAreaContext() {\n const ctx = useContext(ScrollAreaContext);\n if (ctx == null) {\n throw new Error(\"ScrollArea parts must be used inside ScrollArea.Root\");\n }\n return ctx;\n}\n\nfunction clamp01(n: number) {\n if (n <= 0) return 0;\n if (n >= 1) return 1;\n return n;\n}\n\nfunction assignRef<T>(ref: Ref<T> | undefined, node: T | null) {\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n // React 18 types `RefObject.current` as readonly; the write is legal.\n (ref as { current: T | null }).current = node;\n }\n}\n\n/**\n * The scrolled content. `inset` is a resting inset in the scroll axis —\n * like a scroll view's safe-area padding: the content stands clear of the\n * edges at rest but scrolls past them to the true edge, and the scrollbar\n * and edge fade stay on `Root`'s edges. `insetTop` / `insetBottom` set the\n * ends separately (they win over `inset`).\n */\nfunction Content({\n inset,\n insetTop,\n insetBottom,\n style,\n ref,\n ...props\n}: ComponentProps<typeof BaseScrollArea.Content> & {\n inset?: number | string;\n insetTop?: number | string;\n insetBottom?: number | string;\n ref?: Ref<HTMLDivElement>;\n}) {\n return (\n <BaseScrollArea.Content\n ref={ref}\n style={{\n paddingTop: insetTop ?? inset,\n paddingBottom: insetBottom ?? inset,\n ...style,\n }}\n {...props}\n />\n );\n}\n\nconst Corner = BaseScrollArea.Corner;\n\nfunction Root({\n className,\n children,\n fade = true,\n ...props\n}: StyledProps<typeof BaseScrollArea.Root> & {\n /**\n * Progressive edge fade (blur + wash). Leave on except for code\n * surfaces — CodeBlock is the only caller that turns it off, so\n * glyphs hard-clip at the border.\n * @default true\n */\n fade?: boolean;\n}) {\n const topEl = useRef<HTMLDivElement | null>(null);\n const bottomEl = useRef<HTMLDivElement | null>(null);\n\n return (\n <BaseScrollArea.Root\n className={cn(\"relative overflow-hidden\", className)}\n {...props}\n >\n <ScrollAreaContext.Provider value={{ topEl, bottomEl, fade }}>\n {children}\n {fade ? (\n <>\n <Edge edge=\"top\" edgeRef={topEl} />\n <Edge edge=\"bottom\" edgeRef={bottomEl} />\n </>\n ) : null}\n </ScrollAreaContext.Provider>\n </BaseScrollArea.Root>\n );\n}\n\nfunction Viewport({\n className,\n ref,\n ...props\n}: StyledProps<typeof BaseScrollArea.Viewport>) {\n const { topEl, bottomEl, fade } = useScrollAreaContext();\n const viewportRef = useRef<HTMLElement | null>(null);\n\n useLayoutEffect(() => {\n const viewport = viewportRef.current;\n if (!viewport || !fade) return;\n\n const paint = () => {\n const reveal =\n topEl.current?.offsetHeight ||\n bottomEl.current?.offsetHeight ||\n EDGE_REVEAL_PX;\n const maxScroll = viewport.scrollHeight - viewport.clientHeight;\n const top = maxScroll <= 0 ? 0 : clamp01(viewport.scrollTop / reveal);\n const bottom =\n maxScroll <= 0 ? 0 : clamp01((maxScroll - viewport.scrollTop) / reveal);\n paintEdge(topEl.current, top);\n paintEdge(bottomEl.current, bottom);\n };\n\n let frame = 0;\n const onScroll = () => {\n if (frame) return;\n frame = requestAnimationFrame(() => {\n frame = 0;\n paint();\n });\n };\n\n paint();\n viewport.addEventListener(\"scroll\", onScroll, { passive: true });\n let observer: ResizeObserver | null = null;\n if (typeof ResizeObserver !== \"undefined\") {\n observer = new ResizeObserver(paint);\n observer.observe(viewport);\n if (viewport.firstElementChild) {\n observer.observe(viewport.firstElementChild);\n }\n }\n return () => {\n viewport.removeEventListener(\"scroll\", onScroll);\n if (frame) cancelAnimationFrame(frame);\n observer?.disconnect();\n };\n }, [topEl, bottomEl, fade]);\n\n return (\n <BaseScrollArea.Viewport\n // A motion element with layoutScroll: any layout-animated content\n // inside (a shared-element morph, a FLIP row) projects against the\n // viewport's scroll offset instead of reading a scroll as a layout\n // change.\n render={<motion.div layoutScroll />}\n // No `overscroll-contain`: a scroll that reaches the viewport's end\n // (or one that has nothing to scroll) chains to the parent, as a\n // native scroll view does. A popup list that must trap the scroll\n // adds it on its own Viewport.\n className={cn(\n \"outline-pho-brand h-full min-h-0 w-full rounded-[inherit] focus-visible:outline-2 focus-visible:-outline-offset-1\",\n className,\n )}\n {...props}\n ref={(node) => {\n viewportRef.current = node;\n assignRef(ref, node);\n }}\n />\n );\n}\n\nfunction Scrollbar({\n className,\n ...props\n}: StyledProps<typeof BaseScrollArea.Scrollbar>) {\n return (\n <BaseScrollArea.Scrollbar\n className={cn(\n \"relative z-20 flex touch-none p-0.5 opacity-0 transition-opacity delay-300 select-none\",\n \"data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0 data-[scrolling]:duration-0\",\n \"data-[orientation=horizontal]:h-2.5 data-[orientation=horizontal]:flex-col data-[orientation=vertical]:w-2.5\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Thumb({\n className,\n ...props\n}: StyledProps<typeof BaseScrollArea.Thumb>) {\n return (\n <BaseScrollArea.Thumb\n className={cn(\n \"flex-1 rounded-full bg-[var(--border-color-pho-primary)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Scroll area built on Base UI `ScrollArea` — a capped region with overlay\n * scrollbars and progressive edge fade. Approaching rows blur (0 → 1px) and\n * wash into the surface; strength tracks scroll distance over one strip\n * height. Give `Root` a fixed size; put content in `Viewport` → `Content`\n * and add a `Scrollbar` → `Thumb` per axis.\n */\nexport const ScrollArea = {\n Root,\n Viewport,\n Content,\n Scrollbar,\n Thumb,\n Corner,\n};\n"],"mappings":"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"}
|
|
@@ -3,18 +3,18 @@ import { t as n } from "./cn-ChIgwEl3.js";
|
|
|
3
3
|
import { t as ee } from "./is-react-component-DSnjtBmo.js";
|
|
4
4
|
import { n as te } from "./link-provider-DXzDQ08N.js";
|
|
5
5
|
import { SPRING_PRESS as re } from "../motion.js";
|
|
6
|
-
import { a as ae, u as ne } from "./button-
|
|
6
|
+
import { a as ae, u as ne } from "./button-CgUS0j3D.js";
|
|
7
7
|
import { t as oe } from "./createReactComponent-BqCmnqfX.js";
|
|
8
8
|
import { t as se } from "./IconArrowUpRight-DGgKzQwV.js";
|
|
9
9
|
import { t as ie } from "./IconChevronRight-CzoJnYNI.js";
|
|
10
10
|
import { n as _ } from "./avatar-BkmGDIqf.js";
|
|
11
11
|
import { t as le } from "./IconSearch-BKAHkLyX.js";
|
|
12
|
-
import { t as
|
|
12
|
+
import { t as x } from "./scroll-area-DSwD9th7.js";
|
|
13
13
|
import { t as L } from "./collapsible-Dv306QOT.js";
|
|
14
14
|
import { t as ce } from "./kbd-DNI10uy7.js";
|
|
15
|
-
import { createContext as P, isValidElement as
|
|
15
|
+
import { createContext as P, isValidElement as pe, useCallback as z, useContext as G, useEffect as T, useId as ue, useLayoutEffect as me, useMemo as K, useRef as w, useState as C } from "react";
|
|
16
16
|
import { Fragment as de, jsx as t, jsxs as c } from "react/jsx-runtime";
|
|
17
|
-
import { motion as
|
|
17
|
+
import { motion as I } from "motion/react";
|
|
18
18
|
import { Collapsible as fe } from "@base-ui/react/collapsible";
|
|
19
19
|
var he = [
|
|
20
20
|
["path", {
|
|
@@ -29,7 +29,7 @@ var he = [
|
|
|
29
29
|
d: "M18 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0",
|
|
30
30
|
key: "svg-2"
|
|
31
31
|
}]
|
|
32
|
-
], xe = oe("outline", "dots", "Dots", he),
|
|
32
|
+
], xe = oe("outline", "dots", "Dots", he), y = {
|
|
33
33
|
initial: !1,
|
|
34
34
|
whileTap: { scale: 0.97 },
|
|
35
35
|
transition: re
|
|
@@ -53,14 +53,14 @@ function Ie({ className: r, inset: e = "base", ...a }) {
|
|
|
53
53
|
})
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
-
function
|
|
56
|
+
function ye({ className: r, ...e }) {
|
|
57
57
|
const a = G(J);
|
|
58
58
|
return /* @__PURE__ */ t("div", {
|
|
59
59
|
className: n("flex items-center gap-2.5 [&:has(+nav)]:mb-0", ve[a], r),
|
|
60
60
|
...e
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
|
-
function
|
|
63
|
+
function Ne({ label: r = "Search", kbd: e = "⌘K", className: a, ...s }) {
|
|
64
64
|
return /* @__PURE__ */ t(ae, {
|
|
65
65
|
variant: "outlined",
|
|
66
66
|
shape: "square",
|
|
@@ -76,20 +76,20 @@ function ye({ label: r = "Search", kbd: e = "⌘K", className: a, ...s }) {
|
|
|
76
76
|
children: r
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
|
-
function Re({ scroll: r = !0, inset: e, insetTop: a = e ?? 24, insetBottom: s = e ?? 16, className: i, style: l, children:
|
|
79
|
+
function Re({ scroll: r = !0, inset: e, insetTop: a = e ?? 24, insetBottom: s = e ?? 16, className: i, style: l, children: p, ...u }) {
|
|
80
80
|
return r ? /* @__PURE__ */ t("nav", {
|
|
81
81
|
className: n("flex min-h-0 flex-1 flex-col", i),
|
|
82
82
|
style: l,
|
|
83
|
-
...
|
|
84
|
-
children: /* @__PURE__ */ c(
|
|
83
|
+
...u,
|
|
84
|
+
children: /* @__PURE__ */ c(x.Root, {
|
|
85
85
|
className: "min-h-0 flex-1",
|
|
86
|
-
children: [/* @__PURE__ */ t(
|
|
86
|
+
children: [/* @__PURE__ */ t(x.Viewport, { children: /* @__PURE__ */ t(x.Content, {
|
|
87
87
|
inset: e,
|
|
88
88
|
insetTop: a,
|
|
89
89
|
insetBottom: s,
|
|
90
90
|
className: "flex flex-col gap-6",
|
|
91
|
-
children:
|
|
92
|
-
}) }), /* @__PURE__ */ t(
|
|
91
|
+
children: p
|
|
92
|
+
}) }), /* @__PURE__ */ t(x.Scrollbar, { children: /* @__PURE__ */ t(x.Thumb, {}) })]
|
|
93
93
|
})
|
|
94
94
|
}) : /* @__PURE__ */ t("nav", {
|
|
95
95
|
className: n("flex flex-col gap-6", i),
|
|
@@ -98,8 +98,8 @@ function Re({ scroll: r = !0, inset: e, insetTop: a = e ?? 24, insetBottom: s =
|
|
|
98
98
|
paddingBottom: s ?? e,
|
|
99
99
|
...l
|
|
100
100
|
},
|
|
101
|
-
...
|
|
102
|
-
children:
|
|
101
|
+
...u,
|
|
102
|
+
children: p
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
105
|
function Se({ className: r, ...e }) {
|
|
@@ -126,96 +126,96 @@ function Ae({ className: r, ...e }) {
|
|
|
126
126
|
...e
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
|
-
function
|
|
129
|
+
function g(r) {
|
|
130
130
|
if (r == null || r === !1) return null;
|
|
131
131
|
let e = null;
|
|
132
|
-
return ee(r) ? e = /* @__PURE__ */ t(r, {}) :
|
|
132
|
+
return ee(r) ? e = /* @__PURE__ */ t(r, {}) : pe(r) && (e = r), e == null ? null : /* @__PURE__ */ t("span", {
|
|
133
133
|
"data-icon": !0,
|
|
134
134
|
className: "pointer-events-none inline-flex shrink-0 items-center [&>svg]:size-4 [&>svg]:shrink-0",
|
|
135
135
|
children: e
|
|
136
136
|
});
|
|
137
137
|
}
|
|
138
|
-
function _e({ icon: r, active: e,
|
|
139
|
-
const
|
|
138
|
+
function _e({ icon: r, active: e, wrap: a = !1, className: s, children: i, href: l, external: p, ...u }) {
|
|
139
|
+
const v = te(), N = K(() => I.create(v), [v]), m = G(Q), h = ue();
|
|
140
140
|
W(() => {
|
|
141
141
|
if (m)
|
|
142
|
-
return m.reportActive(
|
|
142
|
+
return m.reportActive(h, !!e), () => m.reportActive(h, !1);
|
|
143
143
|
}, [
|
|
144
144
|
m,
|
|
145
|
-
|
|
145
|
+
h,
|
|
146
146
|
e
|
|
147
147
|
]);
|
|
148
|
-
const
|
|
149
|
-
className: "min-w-0 flex-1 truncate",
|
|
150
|
-
children:
|
|
148
|
+
const d = n(q, e ? be : $, s), f = /* @__PURE__ */ t("span", {
|
|
149
|
+
className: a ? "line-clamp-2 min-w-0 flex-1 text-balance hyphens-none" : "min-w-0 flex-1 truncate",
|
|
150
|
+
children: i
|
|
151
151
|
});
|
|
152
|
-
return
|
|
153
|
-
href:
|
|
152
|
+
return l !== void 0 ? /* @__PURE__ */ t("li", { children: /* @__PURE__ */ c(N, {
|
|
153
|
+
href: l,
|
|
154
154
|
"aria-current": e ? "page" : void 0,
|
|
155
|
-
...
|
|
155
|
+
...p && {
|
|
156
156
|
target: "_blank",
|
|
157
157
|
rel: "noopener noreferrer"
|
|
158
158
|
},
|
|
159
159
|
...u,
|
|
160
|
-
className:
|
|
161
|
-
...
|
|
160
|
+
className: d,
|
|
161
|
+
...y,
|
|
162
162
|
children: [
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
163
|
+
g(r),
|
|
164
|
+
f,
|
|
165
|
+
p && /* @__PURE__ */ c(de, { children: [g(/* @__PURE__ */ t(se, { "aria-hidden": !0 })), /* @__PURE__ */ t("span", {
|
|
166
166
|
className: "sr-only",
|
|
167
167
|
children: "(opens in a new tab)"
|
|
168
168
|
})] })
|
|
169
169
|
]
|
|
170
|
-
}) }) : /* @__PURE__ */ t("li", { children: /* @__PURE__ */ c(
|
|
170
|
+
}) }) : /* @__PURE__ */ t("li", { children: /* @__PURE__ */ c(I.button, {
|
|
171
171
|
type: "button",
|
|
172
172
|
"aria-current": e ? "page" : void 0,
|
|
173
173
|
...u,
|
|
174
|
-
className:
|
|
175
|
-
...
|
|
176
|
-
children: [
|
|
174
|
+
className: d,
|
|
175
|
+
...y,
|
|
176
|
+
children: [g(r), f]
|
|
177
177
|
}) });
|
|
178
178
|
}
|
|
179
|
-
function we({ label: r, icon: e, open: a, defaultOpen: s = !1, onOpenChange: i, openWhenChildActive: l = !0, active:
|
|
180
|
-
const [
|
|
181
|
-
d ||
|
|
179
|
+
function we({ label: r, icon: e, open: a, defaultOpen: s = !1, onOpenChange: i, openWhenChildActive: l = !0, active: p, className: u, children: v, ...N }) {
|
|
180
|
+
const [m, h] = C(s), d = a !== void 0, f = d ? a : m, R = z((o) => {
|
|
181
|
+
d || h(o), i?.(o);
|
|
182
182
|
}, [d, i]), [B, Y] = C(() => /* @__PURE__ */ new Set()), O = z((o, F) => {
|
|
183
183
|
Y((E) => {
|
|
184
184
|
if (E.has(o) === F) return E;
|
|
185
185
|
const A = new Set(E);
|
|
186
186
|
return F ? A.add(o) : A.delete(o), A;
|
|
187
187
|
});
|
|
188
|
-
}, []), Z = K(() => ({ reportActive: O }), [O]),
|
|
188
|
+
}, []), Z = K(() => ({ reportActive: O }), [O]), b = p ?? B.size > 0, D = w(!1);
|
|
189
189
|
T(() => {
|
|
190
190
|
const o = requestAnimationFrame(() => {
|
|
191
191
|
D.current = !0;
|
|
192
192
|
});
|
|
193
193
|
return () => cancelAnimationFrame(o);
|
|
194
194
|
}, []);
|
|
195
|
-
const [S, k] = C(!1), M = w(
|
|
196
|
-
M.current =
|
|
195
|
+
const [S, k] = C(!1), M = w(f);
|
|
196
|
+
M.current = f;
|
|
197
197
|
const U = w(R);
|
|
198
198
|
return U.current = R, W(() => {
|
|
199
|
-
!l || !
|
|
199
|
+
!l || !b || M.current || (D.current || k(!0), U.current(!0));
|
|
200
200
|
}, [
|
|
201
201
|
B,
|
|
202
|
-
|
|
202
|
+
b,
|
|
203
203
|
l
|
|
204
204
|
]), T(() => {
|
|
205
205
|
if (!S) return;
|
|
206
206
|
const o = requestAnimationFrame(() => k(!1));
|
|
207
207
|
return () => cancelAnimationFrame(o);
|
|
208
208
|
}, [S]), /* @__PURE__ */ c(L.Root, {
|
|
209
|
-
open:
|
|
209
|
+
open: f,
|
|
210
210
|
onOpenChange: (o) => R(o),
|
|
211
211
|
render: /* @__PURE__ */ t("li", {}),
|
|
212
212
|
children: [/* @__PURE__ */ c(fe.Trigger, {
|
|
213
|
-
render: /* @__PURE__ */ t(
|
|
214
|
-
className: n(q, $,
|
|
215
|
-
"data-child-active":
|
|
216
|
-
...
|
|
213
|
+
render: /* @__PURE__ */ t(I.button, { ...y }),
|
|
214
|
+
className: n(q, $, b && "text-pho-primary *:data-icon:text-pho-primary", "data-[panel-open]:*:data-chevron:rotate-90", u),
|
|
215
|
+
"data-child-active": b || void 0,
|
|
216
|
+
...N,
|
|
217
217
|
children: [
|
|
218
|
-
|
|
218
|
+
g(e),
|
|
219
219
|
/* @__PURE__ */ t("span", {
|
|
220
220
|
className: "min-w-0 flex-1 truncate",
|
|
221
221
|
children: r
|
|
@@ -234,7 +234,7 @@ function we({ label: r, icon: e, open: a, defaultOpen: s = !1, onOpenChange: i,
|
|
|
234
234
|
children: /* @__PURE__ */ t("div", {
|
|
235
235
|
"data-submenu-list": !0,
|
|
236
236
|
className: n("pt-0.5", e ? V.withIcon : V.withoutIcon),
|
|
237
|
-
children: /* @__PURE__ */ t(X, { children:
|
|
237
|
+
children: /* @__PURE__ */ t(X, { children: v })
|
|
238
238
|
})
|
|
239
239
|
})
|
|
240
240
|
})]
|
|
@@ -246,11 +246,11 @@ function Te(r) {
|
|
|
246
246
|
return ((e[0]?.[0] ?? r[0] ?? "?") + (e.length >= 2 ? e[e.length - 1]?.[0] ?? "" : "")).toUpperCase();
|
|
247
247
|
}
|
|
248
248
|
function Be({ name: r, avatarSrc: e, initials: a, className: s, ...i }) {
|
|
249
|
-
return /* @__PURE__ */ c(
|
|
249
|
+
return /* @__PURE__ */ c(I.button, {
|
|
250
250
|
type: "button",
|
|
251
251
|
className: n(Ce, s),
|
|
252
252
|
...i,
|
|
253
|
-
...
|
|
253
|
+
...y,
|
|
254
254
|
children: [
|
|
255
255
|
/* @__PURE__ */ c(_.Root, {
|
|
256
256
|
size: "xs",
|
|
@@ -278,8 +278,8 @@ function Be({ name: r, avatarSrc: e, initials: a, className: s, ...i }) {
|
|
|
278
278
|
}
|
|
279
279
|
var Xe = {
|
|
280
280
|
Root: Ie,
|
|
281
|
-
Header:
|
|
282
|
-
Search:
|
|
281
|
+
Header: ye,
|
|
282
|
+
Search: Ne,
|
|
283
283
|
Nav: Re,
|
|
284
284
|
Group: Se,
|
|
285
285
|
GroupLabel: Ee,
|
|
@@ -303,4 +303,4 @@ export {
|
|
|
303
303
|
We as u
|
|
304
304
|
};
|
|
305
305
|
|
|
306
|
-
//# sourceMappingURL=sidebar-
|
|
306
|
+
//# sourceMappingURL=sidebar-BmloUwJQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar-BmloUwJQ.js","names":[],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.mjs","../../src/sections/sidebar/sidebar.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M4 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M11 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M18 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0\", \"key\": \"svg-2\" }]];\nconst IconDots = createReactComponent(\"outline\", \"dots\", \"Dots\", __iconNode);\n\nexport { __iconNode, IconDots as default };\n//# sourceMappingURL=IconDots.mjs.map\n","import {\n createContext,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type AnchorHTMLAttributes,\n type ButtonHTMLAttributes,\n type ComponentProps,\n type ComponentType,\n type FC,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport {\n IconArrowUpRight,\n IconChevronRight,\n IconDots,\n} from \"@tabler/icons-react\";\nimport { Collapsible as BaseCollapsible } from \"@base-ui/react/collapsible\";\nimport { SPRING_PRESS } from \"../../motion\";\nimport { motion } from \"motion/react\";\nimport { IconSearch } from \"@tabler/icons-react\";\nimport { Button } from \"../../components/button\";\nimport { Collapsible } from \"../../components/collapsible\";\nimport { Kbd } from \"../../components/kbd\";\nimport { ScrollArea } from \"../../components/scroll-area\";\nimport { cn } from \"../../utils/cn\";\nimport { isReactComponent } from \"../../utils/is-react-component\";\nimport { useLinkComponent } from \"../../utils/link-provider\";\nimport { Avatar } from \"../../components/avatar\";\nimport { buttonVariants } from \"../../components/button\";\n\n/** Same press compression as `Button` — transform-only, every interactive row. */\nconst SIDEBAR_PRESS_SCALE = 0.97;\n/** Framer source transition shared with `Button`: `spring-physics 200 30 0.1`. */\nconst SIDEBAR_PRESS_SPRING = SPRING_PRESS;\nconst SIDEBAR_PRESS_MOTION = {\n initial: false as const,\n whileTap: { scale: SIDEBAR_PRESS_SCALE },\n transition: SIDEBAR_PRESS_SPRING,\n};\n\n/**\n * Sidebar — Pho's first SECTION: a composed app rail, not a micro component.\n * It encodes the navigation rail used across Photon surfaces (the Pho docs\n * site, the dashboard): a sticky full-height column with a brand header, a\n * scrollable stack of titled nav groups, and a pinned footer that usually\n * carries the account row.\n *\n * Sections stay presentational — no router, no data fetching, no theme\n * plumbing. Links render through the host's `LinkProvider` (same contract as\n * `ButtonLink`), state arrives via props (`active`), and interactive footers\n * compose with other Pho parts (e.g. wrap `Sidebar.AccountRow` in a\n * `Menu.Trigger render={...}` to open an account menu).\n *\n * `Root` takes `inset` (`base` | `sm`, default `base`) for the rail's outer\n * padding and header spacing — prefer that over host-app class overrides.\n */\n\n/* ------------------------------- class map ------------------------------- */\n\n/** The rail itself — sticky, full-height, hairline right edge (no inset). */\nexport const SIDEBAR_ROOT =\n \"border-pho-secondary bg-pho-page sticky top-0 flex h-dvh w-64 shrink-0 flex-col border-r\";\n\n/** Outer inset on `Root` — `base` is the docs/default rail; `sm` is tighter. */\nexport const SIDEBAR_ROOT_INSET = {\n base: \"px-4 pt-5 pb-4\",\n sm: \"px-3 pt-4 pb-3\",\n} as const;\n\n/** `SIDEBAR_ROOT` with the default `base` inset — one string for docs chrome. */\nexport const SIDEBAR_ROOT_BASE = cn(SIDEBAR_ROOT, SIDEBAR_ROOT_INSET.base);\n\n/** Header spacing paired with `Root`'s `inset`. */\nexport const SIDEBAR_HEADER_INSET = {\n base: \"mb-6 px-2\",\n sm: \"mb-3 px-0\",\n} as const;\n\nexport type SidebarInset = keyof typeof SIDEBAR_ROOT_INSET;\n\n/** A nav row at rest and on hover. Active/inactive inks split below. */\nexport const SIDEBAR_ITEM =\n \"outline-pho-brand flex min-h-9 w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-base transition-colors focus-visible:outline-2 focus-visible:-outline-offset-1\";\n\n/**\n * Selected row — lifted onto the primary surface with the site hairline.\n * The icon carries the same ink as the label so the pair reads as one unit.\n */\nexport const SIDEBAR_ITEM_ACTIVE =\n \"bg-pho-primary text-pho-primary ring-pho-secondary font-medium ring-1 ring-inset *:data-icon:text-pho-primary\";\n\n/**\n * Resting row — secondary ink (75%). Hover lifts onto the primary surface\n * (same plane as the active chip, without the ring) so the wash stays quiet\n * on `pho-page`. Icon tracks the label's ink at every state.\n */\nexport const SIDEBAR_ITEM_INACTIVE = cn(\n \"text-pho-secondary *:data-icon:text-pho-secondary\",\n \"hover:bg-pho-primary hover:text-pho-primary hover:*:data-icon:text-pho-primary\",\n);\n\n/**\n * A submenu's parent row while one of its children is the current page —\n * primary ink on label and icon, but no surface or ring: the child row\n * carries the full active chip, the parent only points at it.\n */\nexport const SIDEBAR_SUBMENU_TRIGGER_CHILD_ACTIVE =\n \"text-pho-primary *:data-icon:text-pho-primary\";\n\n/**\n * The trailing chevron on a submenu row — points right at rest, rotates to\n * point down while the panel is open. Base UI sets `data-panel-open` on the\n * trigger; the global reduced-motion guard collapses the rotation.\n */\nexport const SIDEBAR_SUBMENU_CHEVRON =\n \"ml-auto size-4 shrink-0 transition-transform duration-150 ease-out\";\n\n/**\n * Indent for a submenu's rows so their labels line up with the parent's\n * label: parent padding (8px) + icon (16px) + gap (8px) = 32px, minus the\n * child row's own 8px padding. Without a parent icon the label sits at 8px,\n * so children step in by one row padding only.\n */\nexport const SIDEBAR_SUBMENU_LIST_INDENT = {\n withIcon: \"pl-6\",\n withoutIcon: \"pl-4\",\n} as const;\n\nconst SidebarInsetContext = createContext<SidebarInset>(\"base\");\n\n/**\n * Rows inside a `Sidebar.Submenu` report their `active` flag here so the\n * parent can light up and auto-open. `null` outside a submenu.\n */\ninterface SidebarSubmenuContextValue {\n reportActive: (rowId: string, active: boolean) => void;\n}\n\nconst SidebarSubmenuContext = createContext<SidebarSubmenuContextValue | null>(\n null,\n);\n\n// React 18 warns that useLayoutEffect does nothing on the server (19 dropped\n// the warning); fall back to useEffect there so SSR'd docs stay quiet.\nconst useIsoLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\n/* --------------------------------- frame --------------------------------- */\n\ninterface RootProps extends ComponentProps<\"aside\"> {\n /** Outer padding + header spacing. Defaults to `base`. */\n inset?: SidebarInset;\n ref?: Ref<HTMLElement>;\n}\n\n/** The rail — a sticky, full-height `<aside>` with the hairline right edge. */\nfunction Root({ className, inset = \"base\", ...props }: RootProps) {\n return (\n <SidebarInsetContext.Provider value={inset}>\n <aside\n className={cn(SIDEBAR_ROOT, SIDEBAR_ROOT_INSET[inset], className)}\n {...props}\n data-inset={inset}\n />\n </SidebarInsetContext.Provider>\n );\n}\n\n/** Brand slot at the top of the rail — logo, wordmark, workspace switcher. */\nfunction Header({ className, ...props }: ComponentProps<\"div\">) {\n const inset = useContext(SidebarInsetContext);\n return (\n <div\n className={cn(\n \"flex items-center gap-2.5 [&:has(+nav)]:mb-0\",\n SIDEBAR_HEADER_INSET[inset],\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * The rail's search row — an outlined button dressed to `Item` metrics so\n * its label lines up with the rows below, the shortcut at the trailing\n * edge. The press is the Button's own; wire `onClick` (and a global ⌘K)\n * to a `Command.Dialog`.\n */\nfunction Search({\n label = \"Search\",\n kbd = \"⌘K\",\n className,\n ...props\n}: Omit<ComponentProps<typeof Button>, \"children\" | \"variant\" | \"size\"> & {\n label?: ReactNode;\n kbd?: string;\n}) {\n return (\n <Button\n variant=\"outlined\"\n shape=\"square\"\n size=\"md\"\n aria-keyshortcuts={kbd === \"⌘K\" ? \"Meta+K Control+K\" : undefined}\n prefix={<IconSearch aria-hidden />}\n suffix={<Kbd keys={kbd} className=\"pointer-events-none\" />}\n className={cn(\n \"hover:ring-pho-secondary min-h-9 w-full justify-start gap-2 rounded-sm px-2 py-1.5 has-[[data-icon=prefix]]:pl-2 has-[[data-icon=suffix]]:pr-2 [&>[data-text]]:min-w-0 [&>[data-text]]:flex-1 [&>[data-text]]:truncate [&>[data-text]]:px-0 [&>[data-text]]:text-left\",\n className,\n )}\n {...props}\n >\n {label}\n </Button>\n );\n}\n\n/**\n * The scrollable middle — a stack of `Sidebar.Group`s in a `ScrollArea`\n * (overlay scrollbar, edge fade). Pass `scroll={false}` where a parent\n * scrolls the whole rail as one column (a narrow-viewport drawer) — the\n * nav is then a plain stack at its natural height.\n *\n * The nav owns its breathing room toward its neighbors as a resting inset\n * (a scroll view's safe-area padding): 24px above, 16px below by default —\n * rows stand clear of the ends at rest and scroll through the gap, under\n * the edge fade, instead of clipping at a dead margin. `inset` /\n * `insetTop` / `insetBottom` override it; the same values become plain\n * padding when `scroll={false}`, so both modes keep one geometry. A\n * `Header` right before the nav and a `Footer` after it drop their own\n * margins — the gap lives here, not on the neighbors.\n */\nfunction Nav({\n scroll = true,\n inset,\n insetTop = inset ?? 24,\n insetBottom = inset ?? 16,\n className,\n style,\n children,\n ...props\n}: ComponentProps<\"nav\"> & {\n scroll?: boolean;\n inset?: number | string;\n insetTop?: number | string;\n insetBottom?: number | string;\n}) {\n if (!scroll) {\n return (\n <nav\n className={cn(\"flex flex-col gap-6\", className)}\n style={{\n paddingTop: insetTop ?? inset,\n paddingBottom: insetBottom ?? inset,\n ...style,\n }}\n {...props}\n >\n {children}\n </nav>\n );\n }\n return (\n <nav\n className={cn(\"flex min-h-0 flex-1 flex-col\", className)}\n style={style}\n {...props}\n >\n <ScrollArea.Root className=\"min-h-0 flex-1\">\n <ScrollArea.Viewport>\n <ScrollArea.Content\n inset={inset}\n insetTop={insetTop}\n insetBottom={insetBottom}\n className=\"flex flex-col gap-6\"\n >\n {children}\n </ScrollArea.Content>\n </ScrollArea.Viewport>\n <ScrollArea.Scrollbar>\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n </ScrollArea.Root>\n </nav>\n );\n}\n\nfunction Group({ className, ...props }: ComponentProps<\"div\">) {\n return <div className={className} {...props} />;\n}\n\n/** The cluster's caption — description ink, regular weight. */\nfunction GroupLabel({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\n \"text-pho-description mb-2 px-2 text-xs font-normal\",\n className,\n )}\n {...props}\n />\n );\n}\n\ninterface ListProps extends ComponentProps<\"ul\"> {\n /** Lay the rows out in two columns — for long, flat registries. */\n columns?: boolean;\n}\n\n/** The rows of a group. `columns` switches to a two-column grid. */\nfunction List({ className, columns, ...props }: ListProps) {\n return (\n <ul\n className={cn(\n // list-none/m-0/p-0 shield the rail from host prose styles.\n \"m-0 list-none p-0 *:m-0\",\n columns\n ? \"grid grid-cols-2 gap-x-2 gap-y-0.5\"\n : \"flex flex-col gap-0.5\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Pinned bottom cluster — docs link, account row, theme toggle. */\nfunction Footer({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\"mt-4 flex flex-col gap-0.5 [nav~&]:mt-0\", className)}\n {...props}\n />\n );\n}\n\n/* --------------------------------- item ---------------------------------- */\n\n/** An icon slot — a component (`IconBook`) or element (`<IconBook />`). */\ntype Slottable = ReactNode | FC<{ className?: string }>;\n\nfunction renderIcon(icon: Slottable): ReactNode {\n if (icon == null || icon === false) return null;\n let content: ReactNode = null;\n if (isReactComponent(icon)) {\n const Icon = icon;\n content = <Icon />;\n } else if (isValidElement(icon)) {\n content = icon;\n }\n if (content == null) return null;\n return (\n <span\n data-icon\n className=\"pointer-events-none inline-flex shrink-0 items-center [&>svg]:size-4 [&>svg]:shrink-0\"\n >\n {content}\n </span>\n );\n}\n\ninterface ItemBaseProps {\n /** Slot before the label — a component (`IconBook`) or element. */\n icon?: Slottable;\n /** Marks the row as the current destination (adds `aria-current=\"page\"`). */\n active?: boolean;\n /**\n * Let the label break onto two lines instead of truncating. Default\n * rows stay a single truncated line so the rail keeps even height.\n * The row still uses `min-h-9`; wrap only grows it when the text\n * actually breaks. Caps at two lines.\n */\n wrap?: boolean;\n children?: ReactNode;\n className?: string;\n}\n\n/**\n * DOM handlers whose React signatures clash with Motion's gesture props.\n * Same omit list as `Button` — rows render through `motion.*`.\n */\ntype MotionHandlerConflicts =\n | \"onAnimationStart\"\n | \"onAnimationEnd\"\n | \"onAnimationIteration\"\n | \"onDrag\"\n | \"onDragStart\"\n | \"onDragEnd\"\n | \"onDragEnter\"\n | \"onDragExit\"\n | \"onDragLeave\"\n | \"onDragOver\"\n | \"onDrop\";\n\nexport interface SidebarItemLinkProps\n extends\n ItemBaseProps,\n Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n keyof ItemBaseProps | MotionHandlerConflicts\n > {\n /** Destination — rendered through the host's `LinkProvider`. */\n href: string;\n /** Leaves the app: opens in a new tab and renders a ↗ cue. */\n external?: boolean;\n}\n\nexport interface SidebarItemButtonProps\n extends\n ItemBaseProps,\n Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof ItemBaseProps | MotionHandlerConflicts\n > {\n href?: undefined;\n external?: undefined;\n}\n\nexport type SidebarItemProps = SidebarItemLinkProps | SidebarItemButtonProps;\n\n/**\n * A nav row — a link when `href` is given (rendered through the host's\n * `LinkProvider`), otherwise a button. `active` lifts the row onto the\n * primary surface; `external` opens a new tab and appends a ↗ cue.\n * `wrap` drops the single-line truncate so a long product name can sit\n * on two lines; other rows stay one line.\n */\nfunction Item({\n icon,\n active,\n wrap = false,\n className,\n children,\n href,\n external,\n ...rest\n}: SidebarItemProps) {\n const Link = useLinkComponent();\n // Same bridge as `ButtonLink` — host `LinkProvider` + Motion press scale.\n const MotionLink = useMemo(\n () =>\n motion.create(Link as unknown as ComponentType<Record<string, unknown>>),\n [Link],\n );\n // Inside a `Submenu`, tell the parent row when this one is current so it\n // can light up and auto-open. Layout effect: the parent reads the result\n // before first paint, so a route-selected group opens without a flash.\n const submenu = useContext(SidebarSubmenuContext);\n const rowId = useId();\n useIsoLayoutEffect(() => {\n if (!submenu) return;\n submenu.reportActive(rowId, Boolean(active));\n return () => submenu.reportActive(rowId, false);\n }, [submenu, rowId, active]);\n const rowClass = cn(\n SIDEBAR_ITEM,\n active ? SIDEBAR_ITEM_ACTIVE : SIDEBAR_ITEM_INACTIVE,\n className,\n );\n const label = (\n <span\n className={\n wrap\n ? \"line-clamp-2 min-w-0 flex-1 text-balance hyphens-none\"\n : \"min-w-0 flex-1 truncate\"\n }\n >\n {children}\n </span>\n );\n\n if (href !== undefined) {\n return (\n <li>\n <MotionLink\n href={href}\n aria-current={active ? \"page\" : undefined}\n {...(external && { target: \"_blank\", rel: \"noopener noreferrer\" })}\n {...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}\n className={rowClass}\n {...SIDEBAR_PRESS_MOTION}\n >\n {renderIcon(icon)}\n {label}\n {external && (\n <>\n {renderIcon(<IconArrowUpRight aria-hidden />)}\n <span className=\"sr-only\">(opens in a new tab)</span>\n </>\n )}\n </MotionLink>\n </li>\n );\n }\n\n return (\n <li>\n <motion.button\n type=\"button\"\n aria-current={active ? \"page\" : undefined}\n {...(rest as Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n MotionHandlerConflicts\n >)}\n className={rowClass}\n {...SIDEBAR_PRESS_MOTION}\n >\n {renderIcon(icon)}\n {label}\n </motion.button>\n </li>\n );\n}\n\n/* -------------------------------- submenu -------------------------------- */\n\nexport interface SidebarSubmenuProps extends Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n \"children\" | MotionHandlerConflicts\n> {\n /** The parent row's label. */\n label: ReactNode;\n /** Slot before the label — a component (`IconBook`) or element. */\n icon?: Slottable;\n /** Controlled open state. Pair with `onOpenChange`. */\n open?: boolean;\n /** Initial open state when uncontrolled. Defaults to `false`. */\n defaultOpen?: boolean;\n /** Called with the next open state on every toggle (user or auto-open). */\n onOpenChange?: (open: boolean) => void;\n /**\n * Open the panel whenever a child row becomes `active`, so a route-based\n * rail expands the right group on load and on navigation. Defaults to\n * `true`. The user can still collapse the group afterwards.\n */\n openWhenChildActive?: boolean;\n /**\n * Force the parent's child-active ink. Normally derived from the\n * children's `active` flags — set this when the current destination lives\n * under the group but has no row of its own.\n */\n active?: boolean;\n /** The nested rows — `Sidebar.Item`s, no icon needed. */\n children: ReactNode;\n ref?: Ref<HTMLButtonElement>;\n}\n\n/**\n * A nav row that folds open to reveal child rows — `<Item>` metrics on the\n * trigger, a trailing chevron that turns as the panel opens, and the nested\n * list indented to the parent's label. Built on `Collapsible`, so the\n * height animation (and its reduced-motion collapse) is the library's own.\n *\n * Children are ordinary `Sidebar.Item`s: they report `active` upward, so the\n * parent takes primary ink while a child is current and, with\n * `openWhenChildActive` (default), opens on load without a flash.\n *\n * ```tsx\n * <Sidebar.Submenu label=\"Platforms\" icon={IconMessage}>\n * <Sidebar.Item href=\"/platforms/sms\" active>SMS</Sidebar.Item>\n * <Sidebar.Item href=\"/platforms/imessage\">iMessage</Sidebar.Item>\n * </Sidebar.Submenu>\n * ```\n */\nfunction Submenu({\n label,\n icon,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n openWhenChildActive = true,\n active: activeProp,\n className,\n children,\n ...rest\n}: SidebarSubmenuProps) {\n /* ---- open state: controlled when `open` is given, else internal ---- */\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isControlled = openProp !== undefined;\n const open = isControlled ? openProp : uncontrolledOpen;\n const setOpen = useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n /* ---- which child rows are current (reported by `Item`) ---- */\n const [activeRowIds, setActiveRowIds] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n const reportActive = useCallback((rowId: string, isActive: boolean) => {\n setActiveRowIds((previous) => {\n if (previous.has(rowId) === isActive) return previous;\n const next = new Set(previous);\n if (isActive) next.add(rowId);\n else next.delete(rowId);\n return next;\n });\n }, []);\n const submenuContext = useMemo(() => ({ reportActive }), [reportActive]);\n const childActive = activeProp ?? activeRowIds.size > 0;\n\n /* ---- auto-open on an active child ---- */\n // `true` once the browser has painted the first frame. An auto-open that\n // happens before that (the route already sits under this group on load)\n // must not animate — the rail should simply appear expanded.\n const hasPaintedRef = useRef(false);\n useEffect(() => {\n const frame = requestAnimationFrame(() => {\n hasPaintedRef.current = true;\n });\n return () => cancelAnimationFrame(frame);\n }, []);\n // While `true`, the panel's height transition runs at 0s so the pre-paint\n // auto-open lands instantly. Cleared a frame later so the next toggle\n // animates normally.\n const [instantOpen, setInstantOpen] = useState(false);\n // Read through refs so the effect fires only when the active children\n // change — a user collapsing the group must not be undone by a re-render.\n const latestOpenRef = useRef(open);\n latestOpenRef.current = open;\n const latestSetOpenRef = useRef(setOpen);\n latestSetOpenRef.current = setOpen;\n useIsoLayoutEffect(() => {\n if (!openWhenChildActive || !childActive || latestOpenRef.current) return;\n if (!hasPaintedRef.current) setInstantOpen(true);\n latestSetOpenRef.current(true);\n }, [activeRowIds, childActive, openWhenChildActive]);\n useEffect(() => {\n if (!instantOpen) return;\n const frame = requestAnimationFrame(() => setInstantOpen(false));\n return () => cancelAnimationFrame(frame);\n }, [instantOpen]);\n\n return (\n <Collapsible.Root\n open={open}\n onOpenChange={(next) => setOpen(next)}\n render={<li />}\n >\n <BaseCollapsible.Trigger\n // Same press compression as `Item`; Base UI wires aria-expanded,\n // aria-controls, and Enter / Space onto the native button.\n render={<motion.button {...SIDEBAR_PRESS_MOTION} />}\n className={cn(\n SIDEBAR_ITEM,\n SIDEBAR_ITEM_INACTIVE,\n childActive && SIDEBAR_SUBMENU_TRIGGER_CHILD_ACTIVE,\n // The chevron turns to point down while the panel is open.\n \"data-[panel-open]:*:data-chevron:rotate-90\",\n className,\n )}\n data-child-active={childActive || undefined}\n {...rest}\n >\n {renderIcon(icon)}\n <span className=\"min-w-0 flex-1 truncate\">{label}</span>\n <IconChevronRight\n aria-hidden\n data-chevron\n className={SIDEBAR_SUBMENU_CHEVRON}\n />\n </BaseCollapsible.Trigger>\n {/* keepMounted: closed children stay mounted (hidden) so an active\n child keeps reporting and the parent keeps its ink. */}\n <Collapsible.Panel\n keepMounted\n style={instantOpen ? { transitionDuration: \"0s\" } : undefined}\n >\n <SidebarSubmenuContext.Provider value={submenuContext}>\n {/* Indent and top gap live on a wrapper inside the panel: the\n measured height includes them, so a closed group adds no height\n and siblings never shift. (`List` resets its own padding.) */}\n <div\n data-submenu-list\n className={cn(\n \"pt-0.5\",\n icon\n ? SIDEBAR_SUBMENU_LIST_INDENT.withIcon\n : SIDEBAR_SUBMENU_LIST_INDENT.withoutIcon,\n )}\n >\n <List>{children}</List>\n </div>\n </SidebarSubmenuContext.Provider>\n </Collapsible.Panel>\n </Collapsible.Root>\n );\n}\n\n/* ------------------------------ account row ------------------------------ */\n\n/**\n * Whole-row account trigger. The row itself stays visually quiet — it only\n * carries the `group` state (hover/press/popup-open) and the focus ring;\n * all visual feedback renders on the ⋯ circle via `group-*` classes.\n */\nconst ACCOUNT_ROW =\n \"group outline-pho-brand flex w-full cursor-pointer items-center gap-2 rounded-base p-2 text-left focus-visible:outline-2 focus-visible:outline-offset-2\";\n\n/** Avatar initials: first + last word initial, else the first character. */\nfunction initialsFrom(name: string): string {\n const words = name.split(/\\s+/).filter(Boolean);\n const first = words[0]?.[0] ?? name[0] ?? \"?\";\n const last = words.length >= 2 ? (words[words.length - 1]?.[0] ?? \"\") : \"\";\n return (first + last).toUpperCase();\n}\n\nexport interface SidebarAccountRowProps extends Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n \"children\" | MotionHandlerConflicts\n> {\n /** Display name — also the source for fallback initials. */\n name: string;\n /** Avatar image URL; falls back to initials while loading or on error. */\n avatarSrc?: string;\n /** Override the derived initials. */\n initials?: string;\n ref?: Ref<HTMLButtonElement>;\n}\n\n/**\n * The account chip pinned to the rail's footer — an xs avatar, the name, and\n * a decorative ⋯ circle. The WHOLE row is one button, but the row is only the\n * control — the circle is the indicator: hover, press, and menu-open feedback\n * all render on the ⋯ (a span wearing the stock secondary-circle button\n * classes), driven by the row's `group` state, so it reads as a button\n * without nesting one.\n *\n * It renders a plain `<button>` and forwards every prop, so it slots straight\n * into a menu: `<Menu.Trigger render={<Sidebar.AccountRow name=\"…\" />} />` —\n * Base UI's `data-popup-open` / `data-pressed` states light up the circle.\n */\nfunction AccountRow({\n name,\n avatarSrc,\n initials,\n className,\n ...props\n}: SidebarAccountRowProps) {\n return (\n <motion.button\n type=\"button\"\n className={cn(ACCOUNT_ROW, className)}\n {...props}\n {...SIDEBAR_PRESS_MOTION}\n >\n <Avatar.Root size=\"xs\">\n {avatarSrc && <Avatar.Image src={avatarSrc} alt=\"\" />}\n <Avatar.Fallback>{initials ?? initialsFrom(name)}</Avatar.Fallback>\n </Avatar.Root>\n <span className=\"text-pho-primary min-w-0 flex-1 truncate text-base\">\n {name}\n </span>\n <span\n aria-hidden\n className={buttonVariants({\n variant: \"outlined\",\n size: \"sm\",\n shape: \"circle\",\n // Hover / open washes stay on the ⋯; press scale lives on the row\n // (same as Button / Sidebar.Item) so the circle does not double-scale.\n className:\n \"group-hover:bg-pho-primary-hover group-hover:text-pho-secondary-hover group-data-[popup-open]:bg-pho-primary-hover group-data-[popup-open]:text-pho-secondary-hover p-1\",\n })}\n >\n <IconDots className=\"size-4\" />\n </span>\n </motion.button>\n );\n}\n\n/* -------------------------------- assembly ------------------------------- */\n\n/**\n * The composed sidebar rail. Assemble the frame parts and fill them with\n * rows; wire interactivity by composing other Pho parts around them:\n *\n * ```tsx\n * <Sidebar.Root>\n * <Sidebar.Header>…brand…</Sidebar.Header>\n * <Sidebar.Nav>\n * <Sidebar.Group>\n * <Sidebar.GroupLabel>Pages</Sidebar.GroupLabel>\n * <Sidebar.List>\n * <Sidebar.Item href=\"/\" icon={IconHome} active>\n * Overview\n * </Sidebar.Item>\n * <Sidebar.Submenu label=\"Platforms\" icon={IconMessage}>\n * <Sidebar.Item href=\"/platforms/sms\">SMS</Sidebar.Item>\n * <Sidebar.Item href=\"/platforms/email\">Email</Sidebar.Item>\n * </Sidebar.Submenu>\n * </Sidebar.List>\n * </Sidebar.Group>\n * </Sidebar.Nav>\n * <Sidebar.Footer>\n * <Menu.Root>\n * <Menu.Trigger render={<Sidebar.AccountRow name=\"Ada Lovelace\" />} />\n * …\n * </Menu.Root>\n * </Sidebar.Footer>\n * </Sidebar.Root>\n * ```\n */\nexport const Sidebar = {\n Root,\n Header,\n Search,\n Nav,\n Group,\n GroupLabel,\n List,\n Item,\n Submenu,\n Footer,\n AccountRow,\n};\n"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { t as n } from "./cn-ChIgwEl3.js";
|
|
3
3
|
import { FADE_SWAP as _ } from "../motion.js";
|
|
4
4
|
import { n as y } from "./spinner-BzLUo4Xk.js";
|
|
5
|
-
import { a as b } from "./button-
|
|
5
|
+
import { a as b } from "./button-CgUS0j3D.js";
|
|
6
6
|
import { t as i } from "./createReactComponent-BqCmnqfX.js";
|
|
7
7
|
import { t as w } from "./IconX-pZ9vrtSr.js";
|
|
8
|
-
import { n as k } from "./scroll-area-
|
|
8
|
+
import { n as k } from "./scroll-area-DSwD9th7.js";
|
|
9
9
|
import "react";
|
|
10
10
|
import { jsx as t, jsxs as l } from "react/jsx-runtime";
|
|
11
11
|
import { AnimatePresence as z, motion as T, useReducedMotion as N } from "motion/react";
|
|
@@ -162,4 +162,4 @@ export {
|
|
|
162
162
|
tt as t
|
|
163
163
|
};
|
|
164
164
|
|
|
165
|
-
//# sourceMappingURL=toast-
|
|
165
|
+
//# sourceMappingURL=toast-DUvjSZF7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast-72Wwlzg9.js","names":["__iconNode","__iconNode","__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertOctagonFilled.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertTriangleFilled.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleCheckFilled.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconInfoCircleFilled.mjs","../../src/components/toast/toast.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M14.897 1a4 4 0 0 1 2.664 1.016l.165 .156l4.1 4.1a4 4 0 0 1 1.168 2.605l.006 .227v5.794a4 4 0 0 1 -1.016 2.664l-.156 .165l-4.1 4.1a4 4 0 0 1 -2.603 1.168l-.227 .006h-5.795a3.999 3.999 0 0 1 -2.664 -1.017l-.165 -.156l-4.1 -4.1a4 4 0 0 1 -1.168 -2.604l-.006 -.227v-5.794a4 4 0 0 1 1.016 -2.664l.156 -.165l4.1 -4.1a4 4 0 0 1 2.605 -1.168l.227 -.006h5.793zm-2.887 14l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -8a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z\", \"key\": \"svg-0\" }]];\nconst IconAlertOctagonFilled = createReactComponent(\"filled\", \"alert-octagon-filled\", \"AlertOctagonFilled\", __iconNode);\n\nexport { __iconNode, IconAlertOctagonFilled as default };\n//# sourceMappingURL=IconAlertOctagonFilled.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M12 1.67c.955 0 1.845 .467 2.39 1.247l.105 .16l8.114 13.548a2.914 2.914 0 0 1 -2.307 4.363l-.195 .008h-16.225a2.914 2.914 0 0 1 -2.582 -4.2l.099 -.185l8.11 -13.538a2.914 2.914 0 0 1 2.491 -1.403zm.01 13.33l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -7a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z\", \"key\": \"svg-0\" }]];\nconst IconAlertTriangleFilled = createReactComponent(\"filled\", \"alert-triangle-filled\", \"AlertTriangleFilled\", __iconNode);\n\nexport { __iconNode, IconAlertTriangleFilled as default };\n//# sourceMappingURL=IconAlertTriangleFilled.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\", \"key\": \"svg-0\" }]];\nconst IconCircleCheckFilled = createReactComponent(\"filled\", \"circle-check-filled\", \"CircleCheckFilled\", __iconNode);\n\nexport { __iconNode, IconCircleCheckFilled as default };\n//# sourceMappingURL=IconCircleCheckFilled.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M12 2c5.523 0 10 4.477 10 10a10 10 0 0 1 -19.995 .324l-.005 -.324l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm0 9h-1l-.117 .007a1 1 0 0 0 0 1.986l.117 .007v3l.007 .117a1 1 0 0 0 .876 .876l.117 .007h1l.117 -.007a1 1 0 0 0 .876 -.876l.007 -.117l-.007 -.117a1 1 0 0 0 -.764 -.857l-.112 -.02l-.117 -.006v-3l-.007 -.117a1 1 0 0 0 -.876 -.876l-.117 -.007zm.01 -3l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007z\", \"key\": \"svg-0\" }]];\nconst IconInfoCircleFilled = createReactComponent(\"filled\", \"info-circle-filled\", \"InfoCircleFilled\", __iconNode);\n\nexport { __iconNode, IconInfoCircleFilled as default };\n//# sourceMappingURL=IconInfoCircleFilled.mjs.map\n","import { type ComponentProps, type ElementType, type ReactNode } from \"react\";\nimport { FADE_SWAP } from \"../../motion\";\nimport { Toast as BaseToast } from \"@base-ui/react/toast\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\nimport {\n IconAlertOctagonFilled,\n IconAlertTriangleFilled,\n IconCircleCheckFilled,\n IconInfoCircleFilled,\n IconX,\n type Icon,\n} from \"@tabler/icons-react\";\nimport { BLUR_MAX_PX } from \"../scroll-area\";\nimport { Button } from \"../button\";\nimport { Spinner } from \"../spinner\";\nimport { cn } from \"../../utils/cn\";\n\n/** Override Base UI's `string | (state) => string` className with plain string. */\ntype StyledProps<T extends ElementType> = Omit<\n ComponentProps<T>,\n \"className\"\n> & {\n className?: string;\n};\n\n/** The system's swap: fade through the 1px soft focus, ease-out. */\nconst FACE_SWAP = FADE_SWAP;\n\nconst Provider = BaseToast.Provider;\nconst Portal = BaseToast.Portal;\nconst Action = BaseToast.Action;\n\n/** Imperative toast API: `const toast = useToastManager(); toast.add({ title })`. */\nconst useToastManager = BaseToast.useToastManager;\nconst createToastManager = BaseToast.createToastManager;\n\n/**\n * Status glyphs per toast `type` (Kumo's set in Tabler's hand): the glyph\n * and the title take the status ink, the hairline tints with it, and a\n * translucent wash of the same ink sits over the surface. `info` speaks\n * in the brand ink — Pho has no separate info hue. `loading` is what\n * `manager.promise` shows while the work runs.\n */\nconst TOAST_ICONS: Record<string, Icon> = {\n success: IconCircleCheckFilled,\n error: IconAlertOctagonFilled,\n warning: IconAlertTriangleFilled,\n info: IconInfoCircleFilled,\n};\n\nconst TOAST_WASH: Record<string, string> = {\n success:\n \"bg-[color-mix(in_oklab,var(--text-color-pho-success)_7%,transparent)]\",\n error: \"bg-[color-mix(in_oklab,var(--text-color-pho-error)_7%,transparent)]\",\n warning:\n \"bg-[color-mix(in_oklab,var(--text-color-pho-warning)_7%,transparent)]\",\n info: \"bg-[color-mix(in_oklab,var(--text-color-pho-brand)_7%,transparent)]\",\n};\n\nfunction Viewport({\n className,\n ...props\n}: StyledProps<typeof BaseToast.Viewport>) {\n return (\n <BaseToast.Viewport\n // The stack's anchor box; the cards position themselves absolutely\n // against its bottom edge, and hovering any card expands the stack.\n className={cn(\n \"fixed right-4 bottom-4 z-50 flex w-[calc(100%-2rem)] outline-none sm:w-[22rem]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Root({ className, ...props }: StyledProps<typeof BaseToast.Root>) {\n return (\n <BaseToast.Root\n className={cn(\n // Floating layer: keeps its elevation shadow, sits on the card surface\n // with the site hairline (ring-pho-secondary).\n \"bg-pho-primary text-pho-primary shadow-pho-lg ring-pho-secondary rounded-base absolute right-0 bottom-0 w-full origin-bottom ring-1 select-none ring-inset\",\n // Kumo's stack math on Base UI's variables: a 12px gap folded into\n // the expanded offsets, a 12px peek and −10% scale per depth at\n // rest, the newest card on top.\n \"[--gap:0.75rem] [--height:var(--toast-frontmost-height,var(--toast-height))] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))]\",\n \"[--offset-y:calc(var(--toast-offset-y)*-1+var(--toast-index)*var(--gap)*-1+var(--toast-swipe-movement-y,0px))]\",\n \"[z-index:calc(1000-var(--toast-index))] h-[var(--height)]\",\n \"[transform:translateX(var(--toast-swipe-movement-x,0px))_translateY(calc(var(--toast-swipe-movement-y,0px)-(var(--toast-index)*var(--peek))-(var(--shrink)*var(--height))))_scale(var(--scale))]\",\n \"[transition:transform_0.5s_cubic-bezier(0.22,1,0.36,1),opacity_0.5s,height_0.15s,box-shadow_0.2s_ease-out]\",\n // Invisible bridge below each card so the hover survives the gaps.\n \"after:absolute after:top-full after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-['']\",\n // Hovering (or focusing) the stack expands it into a true list.\n \"data-[expanded]:h-[var(--toast-height)] data-[expanded]:[transform:translateX(var(--toast-swipe-movement-x,0px))_translateY(var(--offset-y))]\",\n // Beyond the provider's limit a card parks invisibly until room frees.\n \"data-[limited]:opacity-0\",\n // In from below; out along the swipe, or back down when timed out.\n \"data-[starting-style]:[transform:translateY(150%)]\",\n \"data-[ending-style]:opacity-0\",\n \"[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(150%)]\",\n \"data-[ending-style]:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y,0px)+150%))]\",\n \"data-[ending-style]:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y,0px)-150%))]\",\n \"data-[ending-style]:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x,0px)-150%))_translateY(var(--offset-y))]\",\n \"data-[ending-style]:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x,0px)+150%))_translateY(var(--offset-y))]\",\n \"data-[swiping]:[transition:none]\",\n // Status inks: hairline, glyph, and title tint together per type.\n \"data-[type=success]:[&_[data-toast-icon]]:text-pho-success data-[type=success]:[&_[data-toast-title]]:text-pho-success data-[type=success]:[&_[data-toast-action]]:text-pho-success data-[type=success]:[&_[data-toast-close]]:text-pho-success data-[type=success]:ring-[color-mix(in_oklab,var(--text-color-pho-success)_45%,transparent)] data-[type=success]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-success)_45%,transparent)]\",\n \"data-[type=error]:[&_[data-toast-icon]]:text-pho-error data-[type=error]:[&_[data-toast-title]]:text-pho-error data-[type=error]:[&_[data-toast-action]]:text-pho-error data-[type=error]:[&_[data-toast-close]]:text-pho-error data-[type=error]:ring-[color-mix(in_oklab,var(--text-color-pho-error)_45%,transparent)] data-[type=error]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-error)_45%,transparent)]\",\n \"data-[type=warning]:[&_[data-toast-icon]]:text-pho-warning data-[type=warning]:[&_[data-toast-title]]:text-pho-warning data-[type=warning]:[&_[data-toast-action]]:text-pho-warning data-[type=warning]:[&_[data-toast-close]]:text-pho-warning data-[type=warning]:ring-[color-mix(in_oklab,var(--text-color-pho-warning)_45%,transparent)] data-[type=warning]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-warning)_45%,transparent)]\",\n \"data-[type=info]:[&_[data-toast-icon]]:text-pho-brand data-[type=info]:[&_[data-toast-title]]:text-pho-brand data-[type=info]:[&_[data-toast-action]]:text-pho-brand data-[type=info]:[&_[data-toast-close]]:text-pho-brand data-[type=info]:ring-[color-mix(in_oklab,var(--text-color-pho-brand)_45%,transparent)] data-[type=info]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-brand)_45%,transparent)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Content({\n className,\n ...props\n}: StyledProps<typeof BaseToast.Content>) {\n return (\n <BaseToast.Content\n // Cards behind the front one show only their peeking edge — the\n // words appear when the stack expands.\n className={cn(\n \"isolate flex flex-col p-4 pr-10 transition-opacity [transition-duration:250ms]\",\n \"data-[behind]:pointer-events-none data-[behind]:opacity-0 data-[expanded]:pointer-events-auto data-[expanded]:opacity-100\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Title({ className, ...props }: StyledProps<typeof BaseToast.Title>) {\n return (\n <BaseToast.Title\n data-toast-title\n className={cn(\"text-pho-primary text-md font-medium\", className)}\n {...props}\n />\n );\n}\n\nfunction Description({\n className,\n ...props\n}: StyledProps<typeof BaseToast.Description>) {\n return (\n <BaseToast.Description\n className={cn(\"text-pho-description text-md\", className)}\n {...props}\n />\n );\n}\n\nfunction Close({ className, ...props }: StyledProps<typeof BaseToast.Close>) {\n return (\n <BaseToast.Close\n data-toast-close\n className={cn(\n \"text-pho-secondary hover:text-pho-secondary-hover hover:bg-pho-ghost-hover outline-pho-brand absolute top-2.5 right-2.5 flex size-6 cursor-pointer items-center justify-center rounded-sm transition focus-visible:outline-2 [&>svg]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * The status glyph for a typed toast — its own row above the title, the\n * Dialog header's arrangement at card scale, an 8px breath before the\n * title. `loading` shows the spinner.\n */\nfunction TypeIcon({ type }: { type?: string }) {\n if (type === \"loading\") {\n return <Spinner aria-hidden className=\"mb-2 size-6 shrink-0\" />;\n }\n const Glyph = type != null ? TOAST_ICONS[type] : undefined;\n if (Glyph == null) return null;\n return <Glyph aria-hidden data-toast-icon className=\"mb-2 size-6 shrink-0\" />;\n}\n\nfunction ToastyList() {\n const { toasts, close } = BaseToast.useToastManager();\n const reduceMotion = useReducedMotion();\n const blurAway = reduceMotion ? \"blur(0px)\" : `blur(${BLUR_MAX_PX}px)`;\n return toasts.map((toast) => (\n <Root key={toast.id} toast={toast}>\n {/* The status wash: a breath of the status ink over the surface. */}\n <div\n aria-hidden\n className={cn(\n \"pointer-events-none absolute inset-0 rounded-[inherit] transition-colors duration-200 ease-out\",\n toast.type != null ? TOAST_WASH[toast.type] : undefined,\n )}\n />\n <Content>\n {/* One grid cell, faces stacked: when a promise walks the card\n from loading to its outcome, the old face fades out through\n the system's soft focus exactly where the new one fades in —\n the values ride each face, so the goer keeps its words. */}\n <span className=\"grid\">\n <AnimatePresence initial={false}>\n <motion.div\n key={`${toast.type ?? \"\"}|${String(toast.title ?? \"\")}`}\n className=\"flex min-w-0 flex-col [grid-area:1/1]\"\n initial={{ opacity: 0, filter: blurAway }}\n animate={{ opacity: 1, filter: \"blur(0px)\" }}\n exit={{ opacity: 0, filter: blurAway }}\n transition={FACE_SWAP}\n >\n <TypeIcon type={toast.type} />\n <Title>{toast.title}</Title>\n <Description>{toast.description}</Description>\n {toast.actionProps != null ? (\n <Action\n data-toast-action\n render={<Button variant=\"outlined\" size=\"sm\" />}\n className=\"mt-2 self-start\"\n onClick={(event) => {\n toast.actionProps?.onClick?.(event);\n close(toast.id);\n }}\n >\n {toast.actionProps.children}\n </Action>\n ) : null}\n </motion.div>\n </AnimatePresence>\n </span>\n </Content>\n <Close aria-label=\"Dismiss\">\n <IconX />\n </Close>\n </Root>\n ));\n}\n\n/**\n * Toasty — the whole toast system in one wrapper, Kumo-shaped: provider,\n * portal, viewport, and the stacked card list with status variants. Wrap\n * the app once and call `Toast.useToastManager().add({ title, type })`\n * from any child; pass a `toastManager` from `createToastManager()` so\n * code outside the tree (a form's auto-save, a query cache) can speak\n * through the same lane. `manager.promise` shows loading → success/error\n * with the matching glyphs.\n */\nexport function Toasty({\n children,\n toastManager,\n}: {\n children?: ReactNode;\n toastManager?: ComponentProps<typeof BaseToast.Provider>[\"toastManager\"];\n}) {\n return (\n <Provider toastManager={toastManager}>\n {children}\n <Portal>\n <Viewport>\n <ToastyList />\n </Viewport>\n </Portal>\n </Provider>\n );\n}\n\n/**\n * Toast built on Base UI `Toast` — transient, non-blocking notifications\n * in a sonner-style stack, styled after Cloudflare's Kumo: at rest the\n * cards collapse into a peek (12px rise and −10% scale per depth, words\n * hidden behind the front card), expand into a true list with a 12px gap\n * on hover or focus, swipe to dismiss, three visible at most. `type`\n * (`success` / `error` / `warning` / `info` / `loading`) tints hairline,\n * glyph, and title together. Reach for `Toasty` unless you need to\n * compose the parts yourself.\n */\nexport const Toast = {\n Provider,\n Portal,\n Viewport,\n Root,\n Content,\n Title,\n Description,\n Close,\n Action,\n useToastManager,\n createToastManager,\n};\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"toast-DUvjSZF7.js","names":["__iconNode","__iconNode","__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertOctagonFilled.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertTriangleFilled.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleCheckFilled.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconInfoCircleFilled.mjs","../../src/components/toast/toast.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M14.897 1a4 4 0 0 1 2.664 1.016l.165 .156l4.1 4.1a4 4 0 0 1 1.168 2.605l.006 .227v5.794a4 4 0 0 1 -1.016 2.664l-.156 .165l-4.1 4.1a4 4 0 0 1 -2.603 1.168l-.227 .006h-5.795a3.999 3.999 0 0 1 -2.664 -1.017l-.165 -.156l-4.1 -4.1a4 4 0 0 1 -1.168 -2.604l-.006 -.227v-5.794a4 4 0 0 1 1.016 -2.664l.156 -.165l4.1 -4.1a4 4 0 0 1 2.605 -1.168l.227 -.006h5.793zm-2.887 14l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -8a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z\", \"key\": \"svg-0\" }]];\nconst IconAlertOctagonFilled = createReactComponent(\"filled\", \"alert-octagon-filled\", \"AlertOctagonFilled\", __iconNode);\n\nexport { __iconNode, IconAlertOctagonFilled as default };\n//# sourceMappingURL=IconAlertOctagonFilled.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M12 1.67c.955 0 1.845 .467 2.39 1.247l.105 .16l8.114 13.548a2.914 2.914 0 0 1 -2.307 4.363l-.195 .008h-16.225a2.914 2.914 0 0 1 -2.582 -4.2l.099 -.185l8.11 -13.538a2.914 2.914 0 0 1 2.491 -1.403zm.01 13.33l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -7a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z\", \"key\": \"svg-0\" }]];\nconst IconAlertTriangleFilled = createReactComponent(\"filled\", \"alert-triangle-filled\", \"AlertTriangleFilled\", __iconNode);\n\nexport { __iconNode, IconAlertTriangleFilled as default };\n//# sourceMappingURL=IconAlertTriangleFilled.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\", \"key\": \"svg-0\" }]];\nconst IconCircleCheckFilled = createReactComponent(\"filled\", \"circle-check-filled\", \"CircleCheckFilled\", __iconNode);\n\nexport { __iconNode, IconCircleCheckFilled as default };\n//# sourceMappingURL=IconCircleCheckFilled.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M12 2c5.523 0 10 4.477 10 10a10 10 0 0 1 -19.995 .324l-.005 -.324l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm0 9h-1l-.117 .007a1 1 0 0 0 0 1.986l.117 .007v3l.007 .117a1 1 0 0 0 .876 .876l.117 .007h1l.117 -.007a1 1 0 0 0 .876 -.876l.007 -.117l-.007 -.117a1 1 0 0 0 -.764 -.857l-.112 -.02l-.117 -.006v-3l-.007 -.117a1 1 0 0 0 -.876 -.876l-.117 -.007zm.01 -3l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007z\", \"key\": \"svg-0\" }]];\nconst IconInfoCircleFilled = createReactComponent(\"filled\", \"info-circle-filled\", \"InfoCircleFilled\", __iconNode);\n\nexport { __iconNode, IconInfoCircleFilled as default };\n//# sourceMappingURL=IconInfoCircleFilled.mjs.map\n","import { type ComponentProps, type ElementType, type ReactNode } from \"react\";\nimport { FADE_SWAP } from \"../../motion\";\nimport { Toast as BaseToast } from \"@base-ui/react/toast\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\nimport {\n IconAlertOctagonFilled,\n IconAlertTriangleFilled,\n IconCircleCheckFilled,\n IconInfoCircleFilled,\n IconX,\n type Icon,\n} from \"@tabler/icons-react\";\nimport { BLUR_MAX_PX } from \"../scroll-area\";\nimport { Button } from \"../button\";\nimport { Spinner } from \"../spinner\";\nimport { cn } from \"../../utils/cn\";\n\n/** Override Base UI's `string | (state) => string` className with plain string. */\ntype StyledProps<T extends ElementType> = Omit<\n ComponentProps<T>,\n \"className\"\n> & {\n className?: string;\n};\n\n/** The system's swap: fade through the 1px soft focus, ease-out. */\nconst FACE_SWAP = FADE_SWAP;\n\nconst Provider = BaseToast.Provider;\nconst Portal = BaseToast.Portal;\nconst Action = BaseToast.Action;\n\n/** Imperative toast API: `const toast = useToastManager(); toast.add({ title })`. */\nconst useToastManager = BaseToast.useToastManager;\nconst createToastManager = BaseToast.createToastManager;\n\n/**\n * Status glyphs per toast `type` (Kumo's set in Tabler's hand): the glyph\n * and the title take the status ink, the hairline tints with it, and a\n * translucent wash of the same ink sits over the surface. `info` speaks\n * in the brand ink — Pho has no separate info hue. `loading` is what\n * `manager.promise` shows while the work runs.\n */\nconst TOAST_ICONS: Record<string, Icon> = {\n success: IconCircleCheckFilled,\n error: IconAlertOctagonFilled,\n warning: IconAlertTriangleFilled,\n info: IconInfoCircleFilled,\n};\n\nconst TOAST_WASH: Record<string, string> = {\n success:\n \"bg-[color-mix(in_oklab,var(--text-color-pho-success)_7%,transparent)]\",\n error: \"bg-[color-mix(in_oklab,var(--text-color-pho-error)_7%,transparent)]\",\n warning:\n \"bg-[color-mix(in_oklab,var(--text-color-pho-warning)_7%,transparent)]\",\n info: \"bg-[color-mix(in_oklab,var(--text-color-pho-brand)_7%,transparent)]\",\n};\n\nfunction Viewport({\n className,\n ...props\n}: StyledProps<typeof BaseToast.Viewport>) {\n return (\n <BaseToast.Viewport\n // The stack's anchor box; the cards position themselves absolutely\n // against its bottom edge, and hovering any card expands the stack.\n className={cn(\n \"fixed right-4 bottom-4 z-50 flex w-[calc(100%-2rem)] outline-none sm:w-[22rem]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Root({ className, ...props }: StyledProps<typeof BaseToast.Root>) {\n return (\n <BaseToast.Root\n className={cn(\n // Floating layer: keeps its elevation shadow, sits on the card surface\n // with the site hairline (ring-pho-secondary).\n \"bg-pho-primary text-pho-primary shadow-pho-lg ring-pho-secondary rounded-base absolute right-0 bottom-0 w-full origin-bottom ring-1 select-none ring-inset\",\n // Kumo's stack math on Base UI's variables: a 12px gap folded into\n // the expanded offsets, a 12px peek and −10% scale per depth at\n // rest, the newest card on top.\n \"[--gap:0.75rem] [--height:var(--toast-frontmost-height,var(--toast-height))] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))]\",\n \"[--offset-y:calc(var(--toast-offset-y)*-1+var(--toast-index)*var(--gap)*-1+var(--toast-swipe-movement-y,0px))]\",\n \"[z-index:calc(1000-var(--toast-index))] h-[var(--height)]\",\n \"[transform:translateX(var(--toast-swipe-movement-x,0px))_translateY(calc(var(--toast-swipe-movement-y,0px)-(var(--toast-index)*var(--peek))-(var(--shrink)*var(--height))))_scale(var(--scale))]\",\n \"[transition:transform_0.5s_cubic-bezier(0.22,1,0.36,1),opacity_0.5s,height_0.15s,box-shadow_0.2s_ease-out]\",\n // Invisible bridge below each card so the hover survives the gaps.\n \"after:absolute after:top-full after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-['']\",\n // Hovering (or focusing) the stack expands it into a true list.\n \"data-[expanded]:h-[var(--toast-height)] data-[expanded]:[transform:translateX(var(--toast-swipe-movement-x,0px))_translateY(var(--offset-y))]\",\n // Beyond the provider's limit a card parks invisibly until room frees.\n \"data-[limited]:opacity-0\",\n // In from below; out along the swipe, or back down when timed out.\n \"data-[starting-style]:[transform:translateY(150%)]\",\n \"data-[ending-style]:opacity-0\",\n \"[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(150%)]\",\n \"data-[ending-style]:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y,0px)+150%))]\",\n \"data-[ending-style]:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y,0px)-150%))]\",\n \"data-[ending-style]:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x,0px)-150%))_translateY(var(--offset-y))]\",\n \"data-[ending-style]:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x,0px)+150%))_translateY(var(--offset-y))]\",\n \"data-[swiping]:[transition:none]\",\n // Status inks: hairline, glyph, and title tint together per type.\n \"data-[type=success]:[&_[data-toast-icon]]:text-pho-success data-[type=success]:[&_[data-toast-title]]:text-pho-success data-[type=success]:[&_[data-toast-action]]:text-pho-success data-[type=success]:[&_[data-toast-close]]:text-pho-success data-[type=success]:ring-[color-mix(in_oklab,var(--text-color-pho-success)_45%,transparent)] data-[type=success]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-success)_45%,transparent)]\",\n \"data-[type=error]:[&_[data-toast-icon]]:text-pho-error data-[type=error]:[&_[data-toast-title]]:text-pho-error data-[type=error]:[&_[data-toast-action]]:text-pho-error data-[type=error]:[&_[data-toast-close]]:text-pho-error data-[type=error]:ring-[color-mix(in_oklab,var(--text-color-pho-error)_45%,transparent)] data-[type=error]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-error)_45%,transparent)]\",\n \"data-[type=warning]:[&_[data-toast-icon]]:text-pho-warning data-[type=warning]:[&_[data-toast-title]]:text-pho-warning data-[type=warning]:[&_[data-toast-action]]:text-pho-warning data-[type=warning]:[&_[data-toast-close]]:text-pho-warning data-[type=warning]:ring-[color-mix(in_oklab,var(--text-color-pho-warning)_45%,transparent)] data-[type=warning]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-warning)_45%,transparent)]\",\n \"data-[type=info]:[&_[data-toast-icon]]:text-pho-brand data-[type=info]:[&_[data-toast-title]]:text-pho-brand data-[type=info]:[&_[data-toast-action]]:text-pho-brand data-[type=info]:[&_[data-toast-close]]:text-pho-brand data-[type=info]:ring-[color-mix(in_oklab,var(--text-color-pho-brand)_45%,transparent)] data-[type=info]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-brand)_45%,transparent)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Content({\n className,\n ...props\n}: StyledProps<typeof BaseToast.Content>) {\n return (\n <BaseToast.Content\n // Cards behind the front one show only their peeking edge — the\n // words appear when the stack expands.\n className={cn(\n \"isolate flex flex-col p-4 pr-10 transition-opacity [transition-duration:250ms]\",\n \"data-[behind]:pointer-events-none data-[behind]:opacity-0 data-[expanded]:pointer-events-auto data-[expanded]:opacity-100\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Title({ className, ...props }: StyledProps<typeof BaseToast.Title>) {\n return (\n <BaseToast.Title\n data-toast-title\n className={cn(\"text-pho-primary text-md font-medium\", className)}\n {...props}\n />\n );\n}\n\nfunction Description({\n className,\n ...props\n}: StyledProps<typeof BaseToast.Description>) {\n return (\n <BaseToast.Description\n className={cn(\"text-pho-description text-md\", className)}\n {...props}\n />\n );\n}\n\nfunction Close({ className, ...props }: StyledProps<typeof BaseToast.Close>) {\n return (\n <BaseToast.Close\n data-toast-close\n className={cn(\n \"text-pho-secondary hover:text-pho-secondary-hover hover:bg-pho-ghost-hover outline-pho-brand absolute top-2.5 right-2.5 flex size-6 cursor-pointer items-center justify-center rounded-sm transition focus-visible:outline-2 [&>svg]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * The status glyph for a typed toast — its own row above the title, the\n * Dialog header's arrangement at card scale, an 8px breath before the\n * title. `loading` shows the spinner.\n */\nfunction TypeIcon({ type }: { type?: string }) {\n if (type === \"loading\") {\n return <Spinner aria-hidden className=\"mb-2 size-6 shrink-0\" />;\n }\n const Glyph = type != null ? TOAST_ICONS[type] : undefined;\n if (Glyph == null) return null;\n return <Glyph aria-hidden data-toast-icon className=\"mb-2 size-6 shrink-0\" />;\n}\n\nfunction ToastyList() {\n const { toasts, close } = BaseToast.useToastManager();\n const reduceMotion = useReducedMotion();\n const blurAway = reduceMotion ? \"blur(0px)\" : `blur(${BLUR_MAX_PX}px)`;\n return toasts.map((toast) => (\n <Root key={toast.id} toast={toast}>\n {/* The status wash: a breath of the status ink over the surface. */}\n <div\n aria-hidden\n className={cn(\n \"pointer-events-none absolute inset-0 rounded-[inherit] transition-colors duration-200 ease-out\",\n toast.type != null ? TOAST_WASH[toast.type] : undefined,\n )}\n />\n <Content>\n {/* One grid cell, faces stacked: when a promise walks the card\n from loading to its outcome, the old face fades out through\n the system's soft focus exactly where the new one fades in —\n the values ride each face, so the goer keeps its words. */}\n <span className=\"grid\">\n <AnimatePresence initial={false}>\n <motion.div\n key={`${toast.type ?? \"\"}|${String(toast.title ?? \"\")}`}\n className=\"flex min-w-0 flex-col [grid-area:1/1]\"\n initial={{ opacity: 0, filter: blurAway }}\n animate={{ opacity: 1, filter: \"blur(0px)\" }}\n exit={{ opacity: 0, filter: blurAway }}\n transition={FACE_SWAP}\n >\n <TypeIcon type={toast.type} />\n <Title>{toast.title}</Title>\n <Description>{toast.description}</Description>\n {toast.actionProps != null ? (\n <Action\n data-toast-action\n render={<Button variant=\"outlined\" size=\"sm\" />}\n className=\"mt-2 self-start\"\n onClick={(event) => {\n toast.actionProps?.onClick?.(event);\n close(toast.id);\n }}\n >\n {toast.actionProps.children}\n </Action>\n ) : null}\n </motion.div>\n </AnimatePresence>\n </span>\n </Content>\n <Close aria-label=\"Dismiss\">\n <IconX />\n </Close>\n </Root>\n ));\n}\n\n/**\n * Toasty — the whole toast system in one wrapper, Kumo-shaped: provider,\n * portal, viewport, and the stacked card list with status variants. Wrap\n * the app once and call `Toast.useToastManager().add({ title, type })`\n * from any child; pass a `toastManager` from `createToastManager()` so\n * code outside the tree (a form's auto-save, a query cache) can speak\n * through the same lane. `manager.promise` shows loading → success/error\n * with the matching glyphs.\n */\nexport function Toasty({\n children,\n toastManager,\n}: {\n children?: ReactNode;\n toastManager?: ComponentProps<typeof BaseToast.Provider>[\"toastManager\"];\n}) {\n return (\n <Provider toastManager={toastManager}>\n {children}\n <Portal>\n <Viewport>\n <ToastyList />\n </Viewport>\n </Portal>\n </Provider>\n );\n}\n\n/**\n * Toast built on Base UI `Toast` — transient, non-blocking notifications\n * in a sonner-style stack, styled after Cloudflare's Kumo: at rest the\n * cards collapse into a peek (12px rise and −10% scale per depth, words\n * hidden behind the front card), expand into a true list with a 12px gap\n * on hover or focus, swipe to dismiss, three visible at most. `type`\n * (`success` / `error` / `warning` / `info` / `loading`) tints hairline,\n * glyph, and title together. Reach for `Toasty` unless you need to\n * compose the parts yourself.\n */\nexport const Toast = {\n Provider,\n Portal,\n Viewport,\n Root,\n Content,\n Title,\n Description,\n Close,\n Action,\n useToastManager,\n createToastManager,\n};\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { a, c as s, d as o, i as n, l as T, n as B, o as u, r as e, s as f, t as i, u as r } from "../chunks/button-
|
|
2
|
+
import { a, c as s, d as o, i as n, l as T, n as B, o as u, r as e, s as f, t as i, u as r } from "../chunks/button-CgUS0j3D.js";
|
|
3
3
|
import { t as E } from "../chunks/close-button-GvqWbLl0.js";
|
|
4
4
|
export {
|
|
5
5
|
i as BUTTON_COLORS,
|