@exegia/corpora-ui 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist-lib/components/blocks/auth/auth-shell.d.ts +56 -0
- package/dist-lib/components/blocks/auth/code-auth-block.d.ts +22 -0
- package/dist-lib/components/blocks/auth/forgot-password-block.d.ts +15 -0
- package/dist-lib/components/blocks/auth/login-block.d.ts +25 -0
- package/dist-lib/components/blocks/auth/signup-block.d.ts +26 -0
- package/dist-lib/components/composed/password-input.d.ts +30 -0
- package/dist-lib/components/composed/social-providers.d.ts +22 -0
- package/dist-lib/components/docs/code-block.d.ts +4 -0
- package/dist-lib/components/docs/component-preview.d.ts +10 -0
- package/dist-lib/components/docs/demo-controls.d.ts +28 -0
- package/dist-lib/components/docs/props-table.d.ts +4 -0
- package/dist-lib/components/theme-provider.d.ts +15 -0
- package/dist-lib/components/ui/button.d.ts +28 -0
- package/dist-lib/components/ui/card.d.ts +16 -0
- package/dist-lib/components/ui/checkbox.d.ts +7 -0
- package/dist-lib/components/ui/field.d.ts +10 -0
- package/dist-lib/components/ui/frame.d.ts +7 -0
- package/dist-lib/components/ui/glasscn/glass-button.d.ts +6 -0
- package/dist-lib/components/ui/glasscn/liquid-glass.d.ts +31 -0
- package/dist-lib/components/ui/input-group.d.ts +13 -0
- package/dist-lib/components/ui/input.d.ts +9 -0
- package/dist-lib/components/ui/label.d.ts +11 -0
- package/dist-lib/components/ui/otp-field.d.ts +11 -0
- package/dist-lib/components/ui/separator.d.ts +4 -0
- package/dist-lib/components/ui/spinner.d.ts +3 -0
- package/dist-lib/components/ui/textarea.d.ts +8 -0
- package/dist-lib/index.d.ts +29 -0
- package/dist-lib/index.js +1617 -0
- package/dist-lib/index.js.map +1 -0
- package/dist-lib/lib/auth-accent.d.ts +33 -0
- package/dist-lib/lib/glass-variants.d.ts +6 -0
- package/dist-lib/lib/sound.d.ts +13 -0
- package/dist-lib/lib/utils.d.ts +2 -0
- package/dist-lib/lib/utils.test.d.ts +1 -0
- package/package.json +80 -0
- package/src/components/blocks/.gitkeep +0 -0
- package/src/components/blocks/auth/auth-shell.tsx +266 -0
- package/src/components/blocks/auth/code-auth-block.tsx +190 -0
- package/src/components/blocks/auth/forgot-password-block.tsx +123 -0
- package/src/components/blocks/auth/login-block.tsx +239 -0
- package/src/components/blocks/auth/signup-block.tsx +260 -0
- package/src/components/composed/.gitkeep +0 -0
- package/src/components/composed/password-input.tsx +179 -0
- package/src/components/composed/social-providers.tsx +89 -0
- package/src/components/docs/code-block.tsx +8 -0
- package/src/components/docs/component-preview.tsx +28 -0
- package/src/components/docs/demo-controls.tsx +118 -0
- package/src/components/docs/props-table.tsx +35 -0
- package/src/components/theme-provider.tsx +230 -0
- package/src/components/ui/button.tsx +199 -0
- package/src/components/ui/card.tsx +253 -0
- package/src/components/ui/checkbox.tsx +83 -0
- package/src/components/ui/field.tsx +89 -0
- package/src/components/ui/frame.tsx +87 -0
- package/src/components/ui/glasscn/glass-button.tsx +25 -0
- package/src/components/ui/glasscn/liquid-glass.tsx +276 -0
- package/src/components/ui/input-group.tsx +105 -0
- package/src/components/ui/input.tsx +70 -0
- package/src/components/ui/label.tsx +36 -0
- package/src/components/ui/otp-field.tsx +88 -0
- package/src/components/ui/separator.tsx +23 -0
- package/src/components/ui/spinner.tsx +17 -0
- package/src/components/ui/textarea.tsx +58 -0
- package/src/index.css +171 -0
- package/src/index.ts +37 -0
- package/src/lib/auth-accent.ts +49 -0
- package/src/lib/glass-variants.ts +57 -0
- package/src/lib/sound.ts +39 -0
- package/src/lib/utils.test.ts +22 -0
- package/src/lib/utils.ts +6 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/lib/utils.ts","../src/components/ui/spinner.tsx","../src/components/ui/glasscn/liquid-glass.tsx","../src/lib/glass-variants.ts","../src/components/ui/button.tsx","../src/components/ui/card.tsx","../src/lib/sound.ts","../src/components/ui/checkbox.tsx","../src/components/ui/field.tsx","../src/components/ui/frame.tsx","../src/components/ui/input.tsx","../src/components/ui/textarea.tsx","../src/components/ui/input-group.tsx","../src/components/ui/label.tsx","../src/components/ui/separator.tsx","../src/components/ui/otp-field.tsx","../src/components/composed/password-input.tsx","../src/components/composed/social-providers.tsx","../src/lib/auth-accent.ts","../src/components/blocks/auth/auth-shell.tsx","../src/components/blocks/auth/code-auth-block.tsx","../src/components/blocks/auth/forgot-password-block.tsx","../src/components/blocks/auth/login-block.tsx","../src/components/blocks/auth/signup-block.tsx"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import { Loader2Icon } from \"lucide-react\";\nimport type React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport function Spinner({\n className,\n ...props\n}: React.ComponentProps<typeof Loader2Icon>): React.ReactElement {\n return (\n <Loader2Icon\n aria-label=\"Loading\"\n className={cn(\"animate-spin\", className)}\n role=\"status\"\n {...props}\n />\n );\n}\n","\"use client\";\n\nimport {\n type CSSProperties,\n type HTMLAttributes,\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype MapGeometry = {\n width: number; // element width, CSS px, integer\n height: number; // element height, CSS px, integer\n radius: number; // corner radius, CSS px, already clamped to min(width, height) / 2\n bezel: number; // fraction (0..1] of the half-min-dimension used as the refractive band\n};\n\nconst MAX_TEXTURE_SIZE = 480;\nconst EDGE_TAPER_PX = 1.25;\n\nconst displacementMapCache = new Map<string, string>();\n\n// CSS.supports(\"backdrop-filter\", \"url(#f)\") returns true in Safari and\n// Firefox (they parse the value) but neither browser actually renders SVG\n// filters through backdrop-filter. UA sniffing is the only reliable approach.\n// When WebKit ships support (track WebKit bug 245510), loosen this function.\nfunction supportsSvgBackdropFilter() {\n if (typeof navigator === \"undefined\") return false;\n const ua = navigator.userAgent;\n const isChromium = /Chrom(e|ium)/.test(ua) || /Edg\\//.test(ua);\n return isChromium && !/Firefox/.test(ua);\n}\n\n// NOTE: Per-corner radii and percentage radii are NOT supported. The map\n// reads only borderTopLeftRadius in px. If a future consumer needs\n// asymmetric corners, extend the corner SDF branch to accept four radii.\n//\n// NOTE: Map regeneration renders a ≤480 px texture and encodes a PNG for\n// each unique (width, height, radius, bezel). Continuously animating the\n// element's SIZE will thrash the cache; animate transform: scale instead.\nfunction createDisplacementMap({ width, height, radius, bezel }: MapGeometry) {\n const cacheKey = `${width}:${height}:${radius}:${bezel}`;\n const cached = displacementMapCache.get(cacheKey);\n if (cached !== undefined) return cached;\n\n const downscale = Math.min(1, MAX_TEXTURE_SIZE / Math.max(width, height));\n const texWidth = Math.max(2, Math.round(width * downscale));\n const texHeight = Math.max(2, Math.round(height * downscale));\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = texWidth;\n canvas.height = texHeight;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return \"\";\n\n const image = ctx.createImageData(texWidth, texHeight);\n const data = image.data;\n const halfWidth = width / 2;\n const halfHeight = height / 2;\n const r = Math.min(radius, halfWidth, halfHeight);\n const bezelPx = Math.max(1, bezel * Math.min(halfWidth, halfHeight));\n\n for (let ty = 0; ty < texHeight; ty += 1) {\n for (let tx = 0; tx < texWidth; tx += 1) {\n // Texel center in element coordinates, origin at element center.\n const px = ((tx + 0.5) / texWidth) * width - halfWidth;\n const py = ((ty + 0.5) / texHeight) * height - halfHeight;\n\n // Signed distance + outward normal of the rounded-rectangle contour.\n const qx = Math.abs(px) - (halfWidth - r);\n const qy = Math.abs(py) - (halfHeight - r);\n let signedDistance: number;\n let dirX = 0;\n let dirY = 0;\n if (qx > 0 && qy > 0) {\n const len = Math.hypot(qx, qy);\n signedDistance = len - r;\n dirX = (Math.sign(px) * qx) / len;\n dirY = (Math.sign(py) * qy) / len;\n } else if (qx > qy) {\n signedDistance = qx - r;\n dirX = Math.sign(px);\n } else {\n signedDistance = qy - r;\n dirY = Math.sign(py);\n }\n\n const index = (ty * texWidth + tx) * 4;\n const inside = -signedDistance; // px from the contour, positive inside\n\n if (inside <= 0) {\n data[index] = 128;\n data[index + 1] = 128;\n data[index + 2] = 128;\n data[index + 3] = 255;\n continue;\n }\n\n const t = Math.min(1, inside / bezelPx); // 0 at the edge → 1 at the bezel's inner end\n let magnitude = 1 - convexSquircle(t); // max refraction at the edge, optically flat interior\n magnitude *= Math.min(1, inside / EDGE_TAPER_PX); // avoid sampling artifacts on the outermost pixels\n\n data[index] = Math.round(128 + dirX * magnitude * 127);\n data[index + 1] = Math.round(128 + dirY * magnitude * 127);\n data[index + 2] = 128;\n data[index + 3] = 255;\n }\n }\n\n ctx.putImageData(image, 0, 0);\n const mapUrl = canvas.toDataURL(\"image/png\");\n displacementMapCache.set(cacheKey, mapUrl);\n return mapUrl;\n}\n\nfunction convexSquircle(x: number) {\n return Math.pow(1 - Math.pow(1 - x, 4), 0.25);\n}\n\nexport type LiquidGlassProps = HTMLAttributes<HTMLDivElement> & {\n /** Extra blur mixed into the backdrop-filter after the SVG refraction. */\n blur?: number;\n /** SVG displacement strength. Higher values bend the sampled backdrop more. */\n refraction?: number;\n /**\n * @deprecated Texture size now derives from element size. Accepted for\n * backwards-compatibility but has no effect.\n */\n mapSize?: number;\n /** Fraction of the radius used as the curved edge where most refraction happens. */\n bezel?: number;\n /** Backdrop saturation. */\n saturation?: number;\n};\n\nexport const LiquidGlass = forwardRef<HTMLDivElement, LiquidGlassProps>(function LiquidGlass(\n {\n blur = 2,\n refraction = 15,\n mapSize: _mapSize,\n bezel = 0.34,\n saturation = 1.28,\n className,\n style,\n children,\n ...props\n },\n ref,\n) {\n const rawId = useId();\n const filterId = useMemo(() => `liquid-glass-${rawId.replace(/:/g, \"\")}`, [rawId]);\n console.log(_mapSize)\n // -------------------------------------------------------------------------\n // Ref merge — we need the DOM node to measure geometry while still\n // forwarding the ref to the consumer.\n // -------------------------------------------------------------------------\n\n const localRef = useRef<HTMLDivElement | null>(null);\n const setRefs = useCallback(\n (node: HTMLDivElement | null) => {\n localRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n },\n [ref],\n );\n\n // -------------------------------------------------------------------------\n // Geometry measurement via ResizeObserver\n // -------------------------------------------------------------------------\n\n const [geometry, setGeometry] = useState<MapGeometry | null>(null);\n\n useEffect(() => {\n const el = localRef.current;\n if (!el) return;\n const measure = () => {\n const rect = el.getBoundingClientRect();\n const width = Math.round(rect.width);\n const height = Math.round(rect.height);\n if (!width || !height) return;\n const parsed = Number.parseFloat(getComputedStyle(el).borderTopLeftRadius);\n const radius = Math.min(Number.isFinite(parsed) ? parsed : Math.min(width, height) / 2, width / 2, height / 2);\n setGeometry((prev) =>\n prev && prev.width === width && prev.height === height && prev.radius === radius && prev.bezel === bezel\n ? prev\n : { width, height, radius, bezel },\n );\n };\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n return () => observer.disconnect();\n }, [bezel]);\n\n const mapUrl = useMemo(() => (geometry ? createDisplacementMap(geometry) : \"\"), [geometry]);\n\n // -------------------------------------------------------------------------\n // Browser capability gate\n //\n // Both SSR and the first client render take the fallback branch so hydration\n // never mismatches. The state is set in an effect (client-only).\n // -------------------------------------------------------------------------\n\n const [supported, setSupported] = useState(false);\n\n useEffect(() => {\n setSupported(supportsSvgBackdropFilter());\n }, []);\n\n const refractionActive = supported && mapUrl !== \"\";\n const backdropFilter = refractionActive\n ? `url(#${filterId}) blur(${blur}px) saturate(${saturation})`\n : `blur(${blur + 2}px) saturate(${saturation})`;\n\n return (\n <>\n <div\n ref={setRefs}\n className={cn(\n \"relative overflow-hidden rounded-full bg-white/[0.08]\",\n className,\n )}\n style={{ ...style, backdropFilter, WebkitBackdropFilter: backdropFilter } as CSSProperties}\n {...props}\n >\n {children}\n <span\n aria-hidden\n className=\"pointer-events-none absolute inset-0 rounded-[inherit]\"\n style={{\n // Rim thickness, overridable per-consumer via --liquid-glass-rim-width.\n padding: \"var(--liquid-glass-rim-width, 0.5px)\",\n background:\n // iOS 27 liquid-glass rim. Each gradient runs ALONG its edges and\n // fades to nothing at the corners, uniform in between:\n // - to right → white streak on the top + bottom runs\n // - to bottom → dark streak on the left + right runs\n // Streak colors are overridable per-consumer via the\n // --liquid-glass-rim-light / --liquid-glass-rim-dark variables;\n // --liquid-glass-rim-fade sets how far from each corner the\n // streak takes to reach full strength (smaller = longer streak).\n \"linear-gradient(to right, rgba(255,255,255,0), var(--liquid-glass-rim-light, rgba(255,255,255,0.25)) var(--liquid-glass-rim-fade, 18%), var(--liquid-glass-rim-light, rgba(255,255,255,0.25)) calc(100% - var(--liquid-glass-rim-fade, 18%)), rgba(255,255,255,0)), \" +\n \"linear-gradient(to bottom, rgba(0,0,0,0), var(--liquid-glass-rim-dark, rgba(0,0,0,0.2)) var(--liquid-glass-rim-fade, 18%), var(--liquid-glass-rim-dark, rgba(0,0,0,0.2)) calc(100% - var(--liquid-glass-rim-fade, 18%)), rgba(0,0,0,0))\",\n WebkitMask: \"linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0)\",\n WebkitMaskComposite: \"xor\",\n mask: \"linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0)\",\n }}\n />\n </div>\n\n {refractionActive && (\n <svg className=\"absolute size-0 overflow-hidden\" aria-hidden>\n <filter id={filterId} x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" colorInterpolationFilters=\"sRGB\">\n <feImage href={mapUrl} x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" preserveAspectRatio=\"none\" result=\"map\" />\n <feDisplacementMap\n in=\"SourceGraphic\"\n in2=\"map\"\n scale={refraction}\n xChannelSelector=\"R\"\n yChannelSelector=\"G\"\n result=\"displaced\"\n />\n <feGaussianBlur in=\"displaced\" stdDeviation=\"0.15\" />\n </filter>\n </svg>\n )}\n </>\n );\n});\n","export type FrostGlassVariant = \"clear\" | \"frosted\" | \"subtle\" | \"liquid\" | \"liquid-refract\";\nexport type FrostGlassVariantProp = { glassVariant?: FrostGlassVariant };\n\nexport const liquidRefractStyles = \"bg-transparent border-0 shadow-none\";\n\nexport const glassVariantStyles: Record<FrostGlassVariant, string> = {\n clear: [\n \"backdrop-blur-[2px] backdrop-saturate-[1.9]\",\n \"bg-white/[0.25] dark:bg-black/[0.25]\",\n \"border border-white/[0.5] dark:border-white/[0.12]\",\n \"shadow-[0_1px_12px_rgba(0,0,0,0.05)] dark:shadow-[0_1px_12px_rgba(0,0,0,0.2)]\",\n ].join(\" \"),\n frosted: [\n \"backdrop-blur-[16px] backdrop-saturate-[1.6]\",\n \"bg-white/[0.55] dark:bg-black/[0.35]\",\n \"border border-white/[0.4] dark:border-white/10\",\n \"shadow-[0_2px_20px_rgba(0,0,0,0.06)] dark:shadow-[0_2px_20px_rgba(0,0,0,0.3)]\",\n ].join(\" \"),\n subtle: [\n \"backdrop-blur-[4px] backdrop-saturate-[1.5]\",\n \"bg-white/[0.3] dark:bg-white/[0.06]\",\n \"border border-black/[0.05] dark:border-white/[0.08]\",\n \"shadow-sm\",\n ].join(\" \"),\n liquid: [\n // 1) Refractive backdrop — lighter than frosted so the background reads\n // clearly through the lens; saturation + brightness lift makes it bloom.\n \"backdrop-blur-[12px] backdrop-saturate-[1.8] backdrop-brightness-[1.05]\",\n \"dark:backdrop-saturate-[1.6] dark:backdrop-brightness-[0.95]\",\n\n // 2) Base translucent fill (acts as the panel's \"tint\").\n \"bg-white/[0.10] dark:bg-white/[0.04]\",\n\n // 3) Layered radial-gradient sheen + warm bottom tint + vertical wash.\n // Underscores represent spaces inside Tailwind arbitrary values.\n \"[background-image:radial-gradient(120%_85%_at_15%_8%,rgba(255,255,255,0.55)_0%,rgba(255,255,255,0.18)_38%,rgba(255,255,255,0)_70%),radial-gradient(110%_80%_at_85%_100%,rgba(255,210,230,0.22)_0%,rgba(255,255,255,0)_60%),linear-gradient(180deg,rgba(255,255,255,0.28)_0%,rgba(255,255,255,0.12)_100%)]\",\n \"dark:[background-image:radial-gradient(120%_85%_at_15%_8%,rgba(255,255,255,0.18)_0%,rgba(255,255,255,0.05)_40%,rgba(255,255,255,0)_70%),radial-gradient(110%_80%_at_85%_100%,rgba(120,170,255,0.12)_0%,rgba(0,0,0,0)_60%),linear-gradient(180deg,rgba(255,255,255,0.06)_0%,rgba(0,0,0,0.18)_100%)]\",\n \"[background-size:200%_200%,180%_180%,100%_100%]\",\n \"[background-repeat:no-repeat]\",\n\n // 4) Multi-layer bevel:\n // - inset top hairline highlight (light-from-above)\n // - inset fish-eye glow at the bottom (lensing artifact)\n // - thin inset side rails\n // - outer contact shadow + broader halo (panel feels floating)\n \"shadow-[inset_0_1px_0_0_rgba(255,255,255,0.65),inset_0_-12px_24px_-10px_rgba(255,255,255,0.45),inset_1px_0_0_0_rgba(255,255,255,0.22),inset_-1px_0_0_0_rgba(255,255,255,0.18),0_24px_60px_-18px_rgba(15,23,42,0.30),0_8px_24px_-8px_rgba(15,23,42,0.18)]\",\n \"dark:shadow-[inset_0_1px_0_0_rgba(255,255,255,0.30),inset_0_-14px_28px_-10px_rgba(180,210,255,0.18),inset_1px_0_0_0_rgba(255,255,255,0.10),inset_-1px_0_0_0_rgba(255,255,255,0.08),0_28px_70px_-18px_rgba(0,0,0,0.55),0_10px_28px_-10px_rgba(0,0,0,0.40)]\",\n\n // 5) Hairline border for the chamfer's outer edge.\n \"border border-white/[0.45] dark:border-white/[0.10]\",\n\n // 6) Slow ambient drift; respects prefers-reduced-motion.\n \"animate-[liquid-drift_18s_ease-in-out_infinite] motion-reduce:animate-none\",\n \"[will-change:background-position]\",\n ].join(\" \"),\n \"liquid-refract\": \"\",\n};\n","\"use client\";\n\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { Spinner } from \"@/components/ui/spinner\";\nimport { LiquidGlass } from \"@/components/ui/glasscn/liquid-glass\";\nimport {\n type FrostGlassVariant,\n glassVariantStyles,\n liquidRefractStyles,\n} from \"@/lib/glass-variants\";\n\nexport const buttonVariants = cva(\n \"relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-lg border font-medium text-base outline-none transition-[scale,box-shadow,width,height,background-color,border-color] [transition-duration:150ms,150ms,300ms,300ms,150ms,150ms] ease-smooth-out active:scale-97 data-pressed:scale-97 motion-reduce:transition-none motion-reduce:active:scale-100 motion-reduce:data-pressed:scale-100 [&_svg]:transition-transform [&_svg]:duration-150 [&_svg]:ease-smooth-out motion-reduce:[&_svg]:transition-none before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 data-loading:select-none sm:text-sm [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:-mx-0.5 [&_svg]:shrink-0\",\n {\n compoundVariants: [\n {\n // `link` is inline text, not a control surface: drop the button box so\n // it sits with the surrounding copy instead of riding high in a 32/36px\n // flex box. Both the bare and `sm:` heights have to be reset —\n // tailwind-merge keeps modifier-prefixed classes in a separate group,\n // so a call-site `h-auto` alone still loses to `sm:h-8`. border-0 makes\n // the inline box exactly one line-height so it doesn't grow the line.\n //\n // align-middle is the alignment that holds: an inline-flex box exposes\n // the baseline of its *first* flex item, which here is the always-\n // mounted loading indicator rather than the label, so plain baseline\n // alignment leaves the text ~3px high. `items-baseline` fixes that but\n // then hangs icons 3px above the label. Centering the box lands within\n // ~1px in every state without touching the loading-morph machinery.\n //\n // Icon sizes are excluded; they keep their square hit area.\n class: \"h-auto border-0 px-0 align-middle sm:h-auto\",\n size: [\"xs\", \"sm\", \"default\", \"lg\", \"xl\"],\n variant: \"link\",\n },\n ],\n defaultVariants: {\n size: \"default\",\n variant: \"default\",\n },\n variants: {\n size: {\n default: \"h-9 px-[calc(--spacing(3)-1px)] sm:h-8\",\n icon: \"size-9 sm:size-8\",\n \"icon-lg\": \"size-10 sm:size-9\",\n \"icon-sm\": \"size-8 sm:size-7\",\n \"icon-xl\":\n \"size-11 sm:size-10 [&_svg:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5\",\n \"icon-xs\":\n \"size-7 rounded-md before:rounded-[calc(var(--radius-md)-1px)] sm:size-6 not-in-data-[slot=input-group]:[&_svg:not([class*='size-'])]:size-4 sm:not-in-data-[slot=input-group]:[&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-10 px-[calc(--spacing(3.5)-1px)] sm:h-9\",\n sm: \"h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:h-7\",\n xl: \"h-11 px-[calc(--spacing(4)-1px)] text-lg sm:h-10 sm:text-base [&_svg:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5\",\n xs: \"h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-sm before:rounded-[calc(var(--radius-md)-1px)] sm:h-6 sm:text-xs [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5\",\n },\n variant: {\n default:\n \"not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-primary bg-primary text-primary-foreground shadow-primary/24 shadow-xs hover:bg-primary/90 data-pressed:bg-primary/90 *:data-[slot=button-loading-indicator]:text-primary-foreground [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none\",\n destructive:\n \"not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-destructive bg-destructive text-white shadow-destructive/24 shadow-xs hover:bg-destructive/90 data-pressed:bg-destructive/90 *:data-[slot=button-loading-indicator]:text-white [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none\",\n \"destructive-outline\":\n \"border-input bg-popover not-dark:bg-clip-padding text-destructive-foreground shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] hover:border-destructive/32 hover:bg-destructive/4 data-pressed:border-destructive/32 data-pressed:bg-destructive/4 *:data-[slot=button-loading-indicator]:text-foreground dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none\",\n ghost:\n \"border-transparent text-foreground hover:bg-accent data-pressed:bg-accent *:data-[slot=button-loading-indicator]:text-foreground\",\n // Base for the glass treatment. The finish itself (blur, tint, bevel)\n // comes from glassVariantStyles keyed by the `glassVariant` prop,\n // which is only accepted when variant is \"glass\".\n glass:\n \"border-transparent text-foreground *:data-[slot=button-loading-indicator]:text-foreground\",\n link: \"border-transparent text-foreground underline-offset-4 hover:underline data-pressed:underline *:data-[slot=button-loading-indicator]:text-foreground\",\n outline:\n \"border-input bg-popover not-dark:bg-clip-padding text-foreground shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] hover:bg-accent/50 data-pressed:bg-accent/50 *:data-[slot=button-loading-indicator]:text-foreground dark:bg-input/32 dark:data-pressed:bg-input/64 dark:hover:bg-input/64 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/90 data-pressed:bg-secondary/90 *:data-[slot=button-loading-indicator]:text-secondary-foreground [:active,[data-pressed]]:bg-secondary/80\",\n },\n },\n },\n);\n\ntype ButtonVariant = VariantProps<typeof buttonVariants>[\"variant\"];\n\ninterface ButtonBaseProps extends useRender.ComponentProps<\"button\"> {\n size?: VariantProps<typeof buttonVariants>[\"size\"];\n loading?: boolean;\n /**\n * Emit cuelume press/release attributes. Inert unless the app opts into\n * interaction sound by calling `bindSounds()` once.\n */\n sound?: boolean;\n}\n\nexport type ButtonProps = ButtonBaseProps &\n (\n | {\n variant: \"glass\";\n /** Glass finish. Only available when `variant` is \"glass\". */\n glassVariant?: FrostGlassVariant;\n }\n | {\n variant?: Exclude<ButtonVariant, \"glass\">;\n glassVariant?: never;\n }\n );\n\nexport function Button({\n className,\n variant,\n size,\n render,\n children,\n loading = false,\n disabled: disabledProp,\n glassVariant,\n sound = true,\n ...props\n}: ButtonProps): React.ReactElement {\n const isDisabled: boolean = Boolean(loading || disabledProp);\n const typeValue: React.ButtonHTMLAttributes<HTMLButtonElement>[\"type\"] =\n render ? undefined : \"button\";\n\n const resolvedGlassVariant: FrostGlassVariant | undefined =\n variant === \"glass\" ? (glassVariant ?? \"liquid-refract\") : undefined;\n const isLiquidRefract = resolvedGlassVariant === \"liquid-refract\";\n\n // Icon-only sizes overlay the spinner on top of the (hidden) icon; text\n // sizes keep the label visible and show the spinner inline before it.\n const isIconSize = (size ?? \"default\").startsWith(\"icon\");\n\n const defaultProps = {\n children: (\n <>\n {!isIconSize && (\n // Always mounted so the button width morphs as the slot collapses\n // and expands; the closed state cancels the flex gap (which varies\n // per size) with a matching negative margin.\n <span\n aria-hidden={loading ? undefined : true}\n data-slot=\"button-loading-indicator\"\n className={cn(\n \"pointer-events-none inline-flex shrink-0 items-center overflow-hidden transition-[max-width,margin-inline-start,opacity,filter] duration-300 ease-smooth-out motion-reduce:transition-none\",\n loading\n ? \"max-w-6\"\n : cn(\n \"max-w-0 opacity-0 blur-[2px]\",\n size === \"xs\" ? \"-ms-1\" : size === \"sm\" ? \"-ms-1.5\" : \"-ms-2\",\n ),\n )}\n >\n <Spinner className={loading ? undefined : \"animate-none\"} />\n </span>\n )}\n {children}\n {loading && isIconSize && (\n <Spinner\n className=\"pointer-events-none absolute\"\n data-slot=\"button-loading-indicator\"\n />\n )}\n </>\n ),\n className: cn(\n buttonVariants({ size, variant }),\n // Label + icon buttons: icons do a gentle scale bump on hover. The\n // class-based :not() skips the spinner (animate-spin / animate-none).\n !isIconSize &&\n \"hover:[&_svg:not([class*='animate-'])]:scale-110 motion-reduce:hover:[&_svg]:scale-100\",\n loading && isIconSize && \"data-loading:text-transparent\",\n resolvedGlassVariant && glassVariantStyles[resolvedGlassVariant],\n isLiquidRefract && liquidRefractStyles,\n className,\n ),\n \"aria-disabled\": loading || undefined,\n \"data-cuelume-press\": sound ? \"\" : undefined,\n \"data-cuelume-release\": sound ? \"\" : undefined,\n \"data-loading\": loading ? \"\" : undefined,\n \"data-glass-variant\": resolvedGlassVariant,\n \"data-slot\": \"button\",\n disabled: isDisabled,\n type: typeValue,\n };\n\n const element = useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(defaultProps, props),\n render,\n });\n\n // liquid-refract delegates the finish to the LiquidGlass wrapper, which\n // renders the SVG-displacement backdrop behind an unstyled button.\n if (isLiquidRefract) {\n return <LiquidGlass>{element}</LiquidGlass>;\n }\n\n return element;\n}\n","\"use client\";\n\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport type React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport function Card({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\n \"relative flex flex-col rounded-2xl border bg-card not-dark:bg-clip-padding text-card-foreground shadow-xs/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]\",\n className,\n ),\n \"data-slot\": \"card\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardFrame({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\n \"relative flex flex-col rounded-2xl border bg-card not-dark:bg-clip-padding text-card-foreground shadow-xs/5 [--clip-bottom:-1rem] [--clip-top:-1rem] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:bg-muted/72 before:shadow-[0_1px_--theme(--color-black/4%)] has-data-[slot=table-container]:overflow-hidden *:data-[slot=card]:-m-px *:data-[slot=table-container]:-m-px *:data-[slot=table-container]:w-[calc(100%+2px)] *:not-first:data-[slot=card]:rounded-t-xl *:not-last:data-[slot=card]:rounded-b-xl *:data-[slot=card]:bg-clip-padding *:data-[slot=card]:shadow-none *:data-[slot=card]:before:hidden *:not-first:data-[slot=card]:before:rounded-t-[calc(var(--radius-xl)-1px)] *:not-last:data-[slot=card]:before:rounded-b-[calc(var(--radius-xl)-1px)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)] *:data-[slot=card]:[clip-path:inset(var(--clip-top)_1px_var(--clip-bottom)_1px_round_calc(var(--radius-2xl)-1px))] *:data-[slot=card]:last:[--clip-bottom:1px] *:data-[slot=card]:first:[--clip-top:1px]\",\n className,\n ),\n \"data-slot\": \"card-frame\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardFrameHeader({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\n \"relative flex grid auto-rows-min grid-rows-[auto_auto] flex-col items-start gap-x-4 px-6 py-4 has-data-[slot=card-frame-action]:grid-cols-[1fr_auto]\",\n className,\n ),\n \"data-slot\": \"card-frame-header\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardFrameTitle({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\"self-center font-semibold text-sm\", className),\n \"data-slot\": \"card-frame-title\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardFrameDescription({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\"self-center text-muted-foreground text-sm\", className),\n \"data-slot\": \"card-frame-description\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardFrameAction({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\n \"col-start-2 nth-3:row-span-2 nth-3:row-start-1 inline-flex self-center justify-self-end\",\n className,\n ),\n \"data-slot\": \"card-frame-action\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardFrameFooter({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\"px-6 py-4\", className),\n \"data-slot\": \"card-frame-footer\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardHeader({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\n \"grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 p-6 in-[[data-slot=card]:has(>[data-slot=card-panel])]:pb-4 has-data-[slot=card-action]:grid-cols-[1fr_auto]\",\n className,\n ),\n \"data-slot\": \"card-header\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardTitle({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\"font-heading font-semibold text-lg leading-none\", className),\n \"data-slot\": \"card-title\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardDescription({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\"text-muted-foreground text-sm\", className),\n \"data-slot\": \"card-description\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardAction({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\n \"col-start-2 row-span-2 row-start-1 inline-flex self-start justify-self-end\",\n className,\n ),\n \"data-slot\": \"card-action\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardPanel({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\n \"flex-1 p-6 in-[[data-slot=card]:has(>[data-slot=card-header]:not(.border-b))]:pt-0 in-[[data-slot=card]:has(>[data-slot=card-footer]:not(.border-t))]:pb-0\",\n className,\n ),\n \"data-slot\": \"card-panel\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport function CardFooter({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">): React.ReactElement {\n const defaultProps = {\n className: cn(\n \"flex items-center p-6 in-[[data-slot=card]:has(>[data-slot=card-panel])]:pt-4\",\n className,\n ),\n \"data-slot\": \"card-footer\",\n };\n\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(defaultProps, props),\n render,\n });\n}\n\nexport { CardPanel as CardContent };\n","/**\n * Interaction sound for the library, powered by cuelume (Web Audio synthesis,\n * zero runtime deps, SSR-safe).\n *\n * Components only emit inert `data-cuelume-*` attributes — nothing plays\n * until the consuming app opts in once:\n *\n * import { bindSounds } from \"@corpora/ui\"\n * bindSounds()\n *\n * The app owns preferences via setSoundEnabled / setSoundVolume.\n */\nimport { bind, play } from \"cuelume\";\nimport type { SoundName } from \"cuelume\";\n\nlet bound = false;\n\n/** Opt into interaction sound. Delegated and idempotent (see cuelume bind). */\nexport function bindSounds(root?: ParentNode): void {\n bound = true;\n bind(root);\n}\n\n/**\n * Imperative cue used by library components for keyboard-driven interactions\n * the data attributes can't cover (OTP typing, visibility toggles, …).\n * No-op until the app has opted in via bindSounds().\n */\nexport function playCue(name: SoundName, options?: { volume?: number }): void {\n if (bound) play(name, options);\n}\n\nexport {\n play as playSound,\n setEnabled as setSoundEnabled,\n setVolume as setSoundVolume,\n sounds,\n} from \"cuelume\";\nexport type { SoundName };\n","\"use client\";\n\nimport { Checkbox as CheckboxPrimitive } from \"@base-ui/react/checkbox\";\nimport type React from \"react\";\nimport { playCue } from \"@/lib/sound\";\nimport { cn } from \"@/lib/utils\";\n\nexport function Checkbox({\n className,\n sound = true,\n onCheckedChange,\n ...props\n}: CheckboxPrimitive.Root.Props & {\n /** Play the cuelume toggle cue on check/uncheck. Silent until bindSounds(). */\n sound?: boolean;\n}): React.ReactElement {\n return (\n <CheckboxPrimitive.Root\n // Cued off the state change rather than data-cuelume-toggle: Base UI\n // renders the native input as a *sibling* of this root, so a click on an\n // associated <label> never bubbles through an element carrying the\n // attribute and would toggle silently. This fires once for box clicks,\n // label clicks and keyboard Space alike, and not for programmatic changes.\n onCheckedChange={(checked, eventDetails) => {\n if (sound) playCue(\"toggle\");\n onCheckedChange?.(checked, eventDetails);\n }}\n className={cn(\n \"relative inline-flex size-4.5 shrink-0 cursor-pointer items-center justify-center rounded-[.25rem] border border-input bg-background not-dark:bg-clip-padding shadow-xs/5 outline-none ring-ring transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[3px] not-data-disabled:not-data-checked:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-offset-background aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/48 data-disabled:cursor-not-allowed data-disabled:opacity-64 sm:size-4 dark:not-data-checked:bg-input/32 dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-data-checked:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)] [[data-disabled],[data-checked],[aria-invalid]]:shadow-none\",\n className,\n )}\n data-slot=\"checkbox\"\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className=\"absolute -inset-px flex items-center justify-center rounded-[.25rem] text-primary-foreground data-unchecked:hidden data-checked:bg-primary data-indeterminate:text-foreground\"\n data-slot=\"checkbox-indicator\"\n render={(\n props: React.ComponentProps<\"span\">,\n state: CheckboxPrimitive.Indicator.State,\n ) => (\n <span {...props}>\n {state.indeterminate ? (\n <svg\n aria-hidden=\"true\"\n className=\"size-3.5 sm:size-3\"\n fill=\"none\"\n height=\"24\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"3\"\n viewBox=\"0 0 24 24\"\n width=\"24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M5.252 12h13.496\" />\n </svg>\n ) : (\n <svg\n aria-hidden=\"true\"\n className=\"size-3.5 sm:size-3\"\n fill=\"none\"\n height=\"24\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"3\"\n viewBox=\"0 0 24 24\"\n width=\"24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M5.252 12.7 10.2 18.63 18.748 5.37\" />\n </svg>\n )}\n </span>\n )}\n />\n </CheckboxPrimitive.Root>\n );\n}\n\nexport { CheckboxPrimitive };\n","\"use client\";\n\nimport { Field as FieldPrimitive } from \"@base-ui/react/field\";\nimport type React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport function Field({\n className,\n ...props\n}: FieldPrimitive.Root.Props): React.ReactElement {\n return (\n <FieldPrimitive.Root\n className={cn(\"flex flex-col items-start gap-2\", className)}\n data-slot=\"field\"\n {...props}\n />\n );\n}\n\nexport function FieldLabel({\n className,\n ...props\n}: FieldPrimitive.Label.Props): React.ReactElement {\n return (\n <FieldPrimitive.Label\n className={cn(\n \"inline-flex cursor-pointer items-center gap-2 font-medium text-base/4 text-foreground data-disabled:cursor-not-allowed data-disabled:opacity-64 sm:text-xs/3.5 ml-3\",\n className,\n )}\n data-slot=\"field-label\"\n {...props}\n />\n );\n}\n\nexport function FieldItem({\n className,\n ...props\n}: FieldPrimitive.Item.Props): React.ReactElement {\n return (\n <FieldPrimitive.Item\n className={cn(\"flex\", className)}\n data-slot=\"field-item\"\n {...props}\n />\n );\n}\n\nexport function FieldDescription({\n className,\n ...props\n}: FieldPrimitive.Description.Props): React.ReactElement {\n return (\n <FieldPrimitive.Description\n // Entrance morph when conditionally shown: height tweens from 0 via\n // interpolate-size (set on :root) plus a fade/blur rise. Removal is\n // unmount-instant; wrap in AnimatePresence when an exit is needed.\n className={cn(\n \"overflow-hidden text-muted-foreground text-xs transition-[height,opacity,filter,translate] duration-300 ease-smooth-out starting:h-0 starting:translate-y-1 starting:opacity-0 starting:blur-[2px] motion-reduce:transition-none\",\n className,\n )}\n data-slot=\"field-description\"\n {...props}\n />\n );\n}\n\nexport function FieldError({\n className,\n ...props\n}: FieldPrimitive.Error.Props): React.ReactElement {\n return (\n <FieldPrimitive.Error\n className={cn(\n \"overflow-hidden text-destructive-foreground text-xs transition-[height,opacity,filter,translate] duration-300 ease-smooth-out starting:h-0 starting:translate-y-1 starting:opacity-0 starting:blur-[2px] motion-reduce:transition-none\",\n className,\n )}\n data-slot=\"field-error\"\n {...props}\n />\n );\n}\n\nexport const FieldControl: typeof FieldPrimitive.Control =\n FieldPrimitive.Control;\nexport const FieldValidity: typeof FieldPrimitive.Validity =\n FieldPrimitive.Validity;\n\nexport { FieldPrimitive };\n","import type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport function Frame({\n className,\n ...props\n}: React.ComponentProps<\"div\">): React.ReactElement {\n return (\n <div\n className={cn(\n \"relative flex flex-col rounded-2xl bg-muted/72 p-1\",\n \"*:[[data-slot=frame-panel]+[data-slot=frame-panel]]:mt-1\",\n className,\n )}\n data-slot=\"frame\"\n {...props}\n />\n );\n}\n\nexport function FramePanel({\n className,\n ...props\n}: React.ComponentProps<\"div\">): React.ReactElement {\n return (\n <div\n className={cn(\n \"relative rounded-xl border bg-background bg-clip-padding p-5 shadow-xs/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]\",\n className,\n )}\n data-slot=\"frame-panel\"\n {...props}\n />\n );\n}\n\nexport function FrameHeader({\n className,\n ...props\n}: React.ComponentProps<\"header\">): React.ReactElement {\n return (\n <header\n className={cn(\"flex flex-col px-5 py-4\", className)}\n data-slot=\"frame-panel-header\"\n {...props}\n />\n );\n}\n\nexport function FrameTitle({\n className,\n ...props\n}: React.ComponentProps<\"div\">): React.ReactElement {\n return (\n <div\n className={cn(\"font-semibold text-sm\", className)}\n data-slot=\"frame-panel-title\"\n {...props}\n />\n );\n}\n\nexport function FrameDescription({\n className,\n ...props\n}: React.ComponentProps<\"div\">): React.ReactElement {\n return (\n <div\n className={cn(\"text-muted-foreground text-sm\", className)}\n data-slot=\"frame-panel-description\"\n {...props}\n />\n );\n}\n\nexport function FrameFooter({\n className,\n ...props\n}: React.ComponentProps<\"footer\">): React.ReactElement {\n return (\n <footer\n className={cn(\"px-5 py-4\", className)}\n data-slot=\"frame-panel-footer\"\n {...props}\n />\n );\n}\n","\"use client\";\n\nimport { Input as InputPrimitive } from \"@base-ui/react/input\";\nimport type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type InputProps = Omit<\n InputPrimitive.Props & React.RefAttributes<HTMLInputElement>,\n \"size\"\n> & {\n size?: \"sm\" | \"default\" | \"lg\" | number;\n unstyled?: boolean;\n nativeInput?: boolean;\n};\n\nexport function Input({\n className,\n size = \"default\",\n unstyled = false,\n nativeInput = false,\n style,\n ...props\n}: InputProps): React.ReactElement {\n const inputClassName = cn(\n // The 5000000s background-color entry is the autofill-flash suppression\n // hack; height/line-height/padding tween size-prop changes.\n \"h-8.5 w-full min-w-0 rounded-[inherit] px-[calc(--spacing(3)-1px)] leading-8.5 outline-none [transition:background-color_5000000s_ease-in-out_0s,height_300ms_var(--ease-smooth-out),line-height_300ms_var(--ease-smooth-out),padding_300ms_var(--ease-smooth-out),font-size_300ms_var(--ease-smooth-out)] placeholder:text-muted-foreground/72 motion-reduce:[transition:background-color_5000000s_ease-in-out_0s] sm:h-7.5 sm:leading-7.5\",\n size === \"sm\" &&\n \"h-7.5 px-[calc(--spacing(2.5)-1px)] leading-7.5 sm:h-6.5 sm:leading-6.5\",\n size === \"lg\" && \"h-9.5 leading-9.5 sm:h-8.5 sm:leading-8.5\",\n props.type === \"search\" &&\n \"[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none\",\n props.type === \"file\" &&\n \"text-muted-foreground file:me-3 file:bg-transparent file:font-medium file:text-foreground file:text-sm\",\n );\n\n return (\n <span\n className={\n cn(\n !unstyled &&\n \"relative inline-flex w-full rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 ring-ring/24 transition-[box-shadow,border-color] duration-150 ease-smooth-out has-aria-invalid:animate-input-shake motion-reduce:animate-none motion-reduce:transition-none before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-autofill:bg-foreground/4 has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] sm:text-sm dark:bg-input/32 dark:has-autofill:bg-foreground/8 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]\",\n className,\n ) || undefined\n }\n data-size={size}\n data-slot=\"input-control\"\n >\n {nativeInput ? (\n <input\n className={inputClassName}\n data-slot=\"input\"\n size={typeof size === \"number\" ? size : undefined}\n style={typeof style === \"function\" ? undefined : style}\n {...props}\n />\n ) : (\n <InputPrimitive\n className={inputClassName}\n data-slot=\"input\"\n size={typeof size === \"number\" ? size : undefined}\n style={style}\n {...props}\n />\n )}\n </span>\n );\n}\n\nexport { InputPrimitive };\n","\"use client\";\n\nimport { Field as FieldPrimitive } from \"@base-ui/react/field\";\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type TextareaProps = React.ComponentPropsWithoutRef<\"textarea\"> &\n React.RefAttributes<HTMLTextAreaElement> & {\n size?: \"sm\" | \"default\" | \"lg\" | number;\n unstyled?: boolean;\n };\n\nexport function Textarea({\n className,\n size = \"default\",\n unstyled = false,\n ref,\n ...props\n}: TextareaProps): React.ReactElement {\n return (\n <span\n className={\n cn(\n !unstyled &&\n \"relative inline-flex w-full rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] not-has-disabled:has-not-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] sm:text-sm dark:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:has-not-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]\",\n className,\n ) || undefined\n }\n data-size={size}\n data-slot=\"textarea-control\"\n >\n <FieldPrimitive.Control\n ref={ref}\n value={props.value}\n defaultValue={props.defaultValue}\n disabled={props.disabled}\n id={props.id}\n name={props.name}\n render={(defaultProps: React.ComponentProps<\"textarea\">) => (\n <textarea\n className={cn(\n \"field-sizing-content min-h-17.5 w-full rounded-[inherit] px-[calc(--spacing(3)-1px)] py-[calc(--spacing(1.5)-1px)] outline-none max-sm:min-h-20.5\",\n size === \"sm\" &&\n \"min-h-16.5 px-[calc(--spacing(2.5)-1px)] py-[calc(--spacing(1)-1px)] max-sm:min-h-19.5\",\n size === \"lg\" &&\n \"min-h-18.5 py-[calc(--spacing(2)-1px)] max-sm:min-h-21.5\",\n )}\n data-slot=\"textarea\"\n {...mergeProps(defaultProps, props)}\n />\n )}\n />\n </span>\n );\n}\n\nexport { FieldPrimitive };\n","\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { Input, type InputProps } from \"@/components/ui/input\";\nimport { Textarea, type TextareaProps } from \"@/components/ui/textarea\";\n\nconst inputGroupAddonVariants = cva(\n \"flex h-auto cursor-text select-none items-center justify-center gap-2 leading-none [&>kbd]:rounded-[calc(var(--radius)-5px)] in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 [&_svg]:-mx-0.5 not-has-[button]:**:[svg:not([class*='opacity-'])]:opacity-80\",\n {\n defaultVariants: {\n align: \"inline-start\",\n },\n variants: {\n align: {\n \"block-end\":\n \"order-last w-full justify-start px-[calc(--spacing(3)-1px)] pb-[calc(--spacing(3)-1px)] [.border-t]:pt-[calc(--spacing(3)-1px)] [[data-size=sm]+&]:px-[calc(--spacing(2.5)-1px)]\",\n \"block-start\":\n \"order-first w-full justify-start px-[calc(--spacing(3)-1px)] pt-[calc(--spacing(3)-1px)] [.border-b]:pb-[calc(--spacing(3)-1px)] [[data-size=sm]+&]:px-[calc(--spacing(2.5)-1px)]\",\n \"inline-end\":\n \"order-last pe-[calc(--spacing(3)-1px)] has-[>:last-child[data-slot=badge]]:-me-1.5 has-[>button]:-me-2 has-[>kbd:last-child]:me-[-0.35rem] [[data-size=sm]+&]:pe-[calc(--spacing(2.5)-1px)]\",\n \"inline-start\":\n \"order-first ps-[calc(--spacing(3)-1px)] has-[>:last-child[data-slot=badge]]:-ms-1.5 has-[>button]:-ms-2 has-[>kbd:last-child]:ms-[-0.35rem] [[data-size=sm]+&]:ps-[calc(--spacing(2.5)-1px)]\",\n },\n },\n },\n);\n\nexport function InputGroup({\n className,\n ...props\n}: React.ComponentProps<\"div\">): React.ReactElement {\n return (\n <div\n className={cn(\n \"relative inline-flex w-full min-w-0 items-center rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-[input:disabled,textarea:disabled]:not-has-[input:focus-visible,textarea:focus-visible]:not-has-[input[aria-invalid],textarea[aria-invalid]]:before:shadow-[0_1px_--theme(--color-black/4%)] has-[input:focus-visible,textarea:focus-visible]:has-[input[aria-invalid],textarea[aria-invalid]]:border-destructive/64 has-[input:focus-visible,textarea:focus-visible]:has-[input[aria-invalid],textarea[aria-invalid]]:ring-destructive/16 has-[textarea]:h-auto has-data-[align=block-end]:h-auto has-data-[align=block-start]:h-auto has-data-[align=block-end]:flex-col has-data-[align=block-start]:flex-col has-[input:focus-visible,textarea:focus-visible]:border-ring has-[input[aria-invalid],textarea[aria-invalid]]:border-destructive/36 has-autofill:bg-foreground/4 has-[input:disabled,textarea:disabled]:opacity-64 has-[input:disabled,textarea:disabled,input:focus-visible,textarea:focus-visible,input[aria-invalid],textarea[aria-invalid]]:shadow-none has-[input:focus-visible,textarea:focus-visible]:ring-[3px] sm:text-sm dark:bg-input/32 dark:has-autofill:bg-foreground/8 dark:has-[input[aria-invalid],textarea[aria-invalid]]:ring-destructive/24 dark:not-has-[input:disabled,textarea:disabled]:not-has-[input:focus-visible,textarea:focus-visible]:not-has-[input[aria-invalid],textarea[aria-invalid]]:before:shadow-[0_-1px_--theme(--color-white/6%)] has-data-[align=inline-start]:**:[[data-size=sm]_input]:ps-1.5 has-data-[align=inline-end]:**:[[data-size=sm]_input]:pe-1.5 *:[[data-slot=input-control],[data-slot=textarea-control]]:contents *:[[data-slot=input-control],[data-slot=textarea-control]]:before:hidden has-[[data-align=block-start],[data-align=block-end]]:**:[input]:h-auto has-data-[align=inline-start]:**:[input]:ps-2 has-data-[align=inline-end]:**:[input]:pe-2 has-data-[align=block-end]:**:[input]:pt-1.5 has-data-[align=block-start]:**:[input]:pb-1.5 **:[textarea]:min-h-20.5 **:[textarea]:resize-none **:[textarea]:py-[calc(--spacing(3)-1px)] **:[textarea]:max-sm:min-h-23.5 **:[textarea_button]:rounded-[calc(var(--radius-md)-1px)]\",\n className,\n )}\n data-slot=\"input-group\"\n role=\"group\"\n {...props}\n />\n );\n}\n\nexport function InputGroupAddon({\n className,\n align = \"inline-start\",\n ...props\n}: React.ComponentProps<\"div\"> &\n VariantProps<typeof inputGroupAddonVariants>): React.ReactElement {\n return (\n <div\n className={cn(inputGroupAddonVariants({ align }), className)}\n data-align={align}\n data-slot=\"input-group-addon\"\n onMouseDown={(e: React.MouseEvent<HTMLDivElement>) => {\n const target = e.target as HTMLElement;\n const isInteractive = target.closest(\n \"button, a, input, select, textarea, [role='button'], [role='combobox'], [role='listbox'], [data-slot='select-trigger']\",\n );\n if (isInteractive) return;\n e.preventDefault();\n const parent = e.currentTarget.parentElement;\n const input = parent?.querySelector<\n HTMLInputElement | HTMLTextAreaElement\n >(\"input, textarea\");\n if (input && !parent?.querySelector(\"input:focus, textarea:focus\")) {\n input.focus();\n }\n }}\n {...props}\n />\n );\n}\n\nexport function InputGroupText({\n className,\n ...props\n}: React.ComponentProps<\"span\">): React.ReactElement {\n return (\n <span\n className={cn(\n \"line-clamp-1 flex items-center gap-2 whitespace-nowrap text-muted-foreground leading-none in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:-mx-0.5\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport function InputGroupInput({\n className,\n ...props\n}: InputProps): React.ReactElement {\n return <Input className={className} unstyled {...props} />;\n}\n\nexport function InputGroupTextarea({\n className,\n ...props\n}: TextareaProps): React.ReactElement {\n return <Textarea className={className} unstyled {...props} />;\n}\n","\"use client\";\n\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport type React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport function Label({\n className,\n render,\n sound = false,\n ...props\n}: useRender.ComponentProps<\"label\"> & {\n /**\n * Emit the cuelume hover tick. Opt-in: a label is a click target for its\n * control, and that control already owns the interaction cue (Checkbox\n * plays `toggle` on check/uncheck), so hover-ticking here double-sounds.\n * Inert until the app calls bindSounds().\n */\n sound?: boolean;\n}): React.ReactElement {\n const defaultProps = {\n className: cn(\n \"inline-flex cursor-pointer items-center gap-2 font-medium text-base/4.5 text-foreground sm:text-sm/4\",\n className,\n ),\n \"data-cuelume-hover\": sound ? \"tick\" : undefined,\n \"data-slot\": \"label\",\n };\n\n return useRender({\n defaultTagName: \"label\",\n props: mergeProps<\"label\">(defaultProps, props),\n render,\n });\n}\n","import { Separator as SeparatorPrimitive } from \"@base-ui/react/separator\";\nimport type React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport function Separator({\n className,\n orientation = \"horizontal\",\n ...props\n}: SeparatorPrimitive.Props): React.ReactElement {\n return (\n <SeparatorPrimitive\n className={cn(\n \"shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:not-[[class^='h-']]:not-[[class*='_h-']]:self-stretch\",\n className,\n )}\n data-slot=\"separator\"\n orientation={orientation}\n {...props}\n />\n );\n}\n\nexport { SeparatorPrimitive };\n","\"use client\";\n\nimport { OTPField as OTPFieldPrimitive } from \"@base-ui/react/otp-field\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { playCue } from \"@/lib/sound\";\nimport { Separator } from \"@/components/ui/separator\";\n\nexport function OTPField({\n className,\n size = \"default\",\n sound = true,\n onValueChange,\n ...props\n}: React.ComponentProps<typeof OTPFieldPrimitive.Root> & {\n size?: \"default\" | \"lg\";\n /** Play a tick cue per entered character. Inert until bindSounds(). */\n sound?: boolean;\n}): React.ReactElement {\n // Typing is keyboard-driven, so the cue is imperative (playCue is gated on\n // the app having called bindSounds). Tick only when characters are added.\n const lastLength = React.useRef(\n String(props.value ?? props.defaultValue ?? \"\").length,\n );\n\n const handleValueChange: NonNullable<typeof onValueChange> = (\n value,\n ...rest\n ) => {\n if (sound && value.length > lastLength.current) {\n playCue(\"tick\");\n }\n lastLength.current = value.length;\n onValueChange?.(value, ...rest);\n };\n\n return (\n <OTPFieldPrimitive.Root\n className={cn(\n \"flex items-center gap-2 has-disabled:opacity-64 has-disabled:**:data-[slot=otp-field-input]:shadow-none has-disabled:**:data-[slot=otp-field-input]:before:shadow-none!\",\n className,\n )}\n data-size={size}\n data-slot=\"otp-field\"\n onValueChange={handleValueChange}\n {...props}\n />\n );\n}\n\nexport function OTPFieldInput({\n className,\n ...props\n}: React.ComponentProps<typeof OTPFieldPrimitive.Input>): React.ReactElement {\n return (\n <OTPFieldPrimitive.Input\n className={cn(\n \"relative in-[[data-slot=otp-field][data-size=lg]]:size-10 size-9 min-w-0 rounded-lg border border-input bg-background not-dark:bg-clip-padding text-center in-[[data-slot=otp-field][data-size=lg]]:text-lg text-base text-foreground in-[[data-slot=otp-field][data-size=lg]]:leading-10 leading-9 shadow-xs/5 outline-none ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-focus-visible:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] focus-visible:z-10 focus-visible:border-ring focus-visible:shadow-none focus-visible:ring-[3px] focus-visible:ring-ring/24 aria-invalid:border-destructive/36 aria-invalid:shadow-none aria-invalid:focus-visible:border-destructive/64 aria-invalid:focus-visible:ring-destructive/16 sm:in-[[data-slot=otp-field][data-size=lg]]:size-9 sm:size-8 sm:in-[[data-slot=otp-field][data-size=lg]]:text-base sm:text-sm sm:in-[[data-slot=otp-field][data-size=lg]]:leading-9 sm:leading-8 dark:bg-input/32 dark:aria-invalid:focus-visible:ring-destructive/24 dark:not-focus-visible:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]\",\n className,\n )}\n data-slot=\"otp-field-input\"\n spellCheck={false}\n {...props}\n />\n );\n}\n\nexport function OTPFieldSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof Separator>): React.ReactElement {\n return (\n <OTPFieldPrimitive.Separator\n render={\n <Separator\n className={cn(\n \"rounded-full bg-input data-[orientation=horizontal]:h-0.5 data-[orientation=horizontal]:w-3\",\n className,\n )}\n orientation=\"horizontal\"\n {...props}\n />\n }\n />\n );\n}\n\nexport { OTPFieldPrimitive };\n","\"use client\";\n\nimport { CheckIcon, EyeIcon, EyeOffIcon, XIcon } from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"@/components/ui/input-group\";\nimport { playCue } from \"@/lib/sound\";\nimport { cn } from \"@/lib/utils\";\n\n// transitions.dev motion scale\nconst EASE = [0.22, 1, 0.36, 1] as const;\n\nexport const passwordRequirements = [\n { regex: /.{8,}/, text: \"At least 8 characters\" },\n { regex: /[0-9]/, text: \"At least 1 number\" },\n { regex: /[a-z]/, text: \"At least 1 lowercase letter\" },\n { regex: /[A-Z]/, text: \"At least 1 uppercase letter\" },\n] as const;\n\nexport function getPasswordStrength(password: string): number {\n return passwordRequirements.filter((req) => req.regex.test(password)).length;\n}\n\nconst STRENGTH_COLORS = [\n \"bg-border\",\n \"bg-red-500\",\n \"bg-orange-500\",\n \"bg-amber-500\",\n \"bg-emerald-500\",\n] as const;\n\nexport interface PasswordInputProps\n extends Omit<React.ComponentProps<typeof InputGroupInput>, \"type\" | \"size\"> {\n /** Render the eye toggle button. */\n visibilityToggle?: boolean;\n /** Render the animated strength meter and requirement checklist. */\n showStrength?: boolean;\n /** Play reveal/hide cues on the visibility toggle. Inert until bindSounds(). */\n sound?: boolean;\n}\n\n/**\n * Password field with visibility toggle and optional strength meter.\n * Composition of InputGroup + Button (coss particles p-input-9 and\n * p-input-group-26).\n */\nexport function PasswordInput({\n visibilityToggle = true,\n showStrength = false,\n sound = true,\n className,\n value: valueProp,\n defaultValue,\n onChange,\n ...props\n}: PasswordInputProps) {\n const [visible, setVisible] = React.useState(false);\n const [uncontrolled, setUncontrolled] = React.useState(\n String(defaultValue ?? \"\"),\n );\n const value = valueProp !== undefined ? String(valueProp) : uncontrolled;\n const score = getPasswordStrength(value);\n\n return (\n <div className={cn(\"flex w-full flex-col gap-3\", className)}>\n <InputGroup>\n <InputGroupInput\n placeholder=\"Enter your password\"\n {...props}\n type={visible ? \"text\" : \"password\"}\n value={value}\n onChange={(event) => {\n setUncontrolled(event.target.value);\n onChange?.(event);\n }}\n />\n {visibilityToggle && (\n <InputGroupAddon align=\"inline-end\">\n <Button\n aria-label={visible ? \"Hide password\" : \"Show password\"}\n onClick={() => {\n // Semantic cues from the cuelume palette: bloom = reveal,\n // droplet = dismiss. Press/release stays off to avoid layering.\n if (sound) playCue(visible ? \"droplet\" : \"bloom\");\n setVisible((v) => !v);\n }}\n size=\"icon-xs\"\n variant=\"ghost\"\n sound={false}\n >\n <AnimatePresence mode=\"wait\" initial={false}>\n <motion.span\n key={visible ? \"off\" : \"on\"}\n className=\"inline-flex\"\n initial={{ opacity: 0, scale: 0.8, filter: \"blur(2px)\" }}\n animate={{ opacity: 1, scale: 1, filter: \"blur(0px)\" }}\n exit={{ opacity: 0, scale: 0.8, filter: \"blur(2px)\" }}\n transition={{ duration: 0.15, ease: EASE }}\n >\n {visible ? (\n <EyeOffIcon aria-hidden=\"true\" />\n ) : (\n <EyeIcon aria-hidden=\"true\" />\n )}\n </motion.span>\n </AnimatePresence>\n </Button>\n </InputGroupAddon>\n )}\n </InputGroup>\n\n <AnimatePresence initial={false}>\n {showStrength && (\n <motion.div\n className=\"flex flex-col gap-2 overflow-hidden\"\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: \"auto\", opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={{ duration: 0.25, ease: EASE }}\n >\n <div\n aria-label=\"Password strength\"\n aria-valuemax={4}\n aria-valuemin={0}\n aria-valuenow={score}\n className=\"h-1 w-full overflow-hidden rounded-full bg-border\"\n role=\"progressbar\"\n >\n <motion.div\n className={cn(\"h-full rounded-full\", STRENGTH_COLORS[score])}\n animate={{ width: `${(score / 4) * 100}%` }}\n transition={{ duration: 0.4, ease: EASE }}\n />\n </div>\n <ul\n aria-label=\"Password requirements\"\n className=\"flex flex-col gap-1\"\n >\n {passwordRequirements.map((req) => {\n const met = req.regex.test(value);\n return (\n <li className=\"flex items-center gap-2 text-xs\" key={req.text}>\n {met ? (\n <CheckIcon\n aria-hidden=\"true\"\n className=\"size-3.5 text-emerald-500\"\n />\n ) : (\n <XIcon\n aria-hidden=\"true\"\n className=\"size-3.5 text-muted-foreground/80\"\n />\n )}\n <span\n className={\n met ? \"text-emerald-600\" : \"text-muted-foreground\"\n }\n >\n {req.text}\n <span className=\"sr-only\">\n {met ? \" - met\" : \" - not met\"}\n </span>\n </span>\n </li>\n );\n })}\n </ul>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n RiAppleFill,\n RiGithubFill,\n RiGoogleFill,\n RiTwitterXFill,\n} from \"@remixicon/react\";\nimport type * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\nexport type SocialProvider = \"google\" | \"apple\" | \"github\" | \"x\";\n\nconst PROVIDERS: Record<\n SocialProvider,\n { label: string; Icon: React.ComponentType<{ className?: string }> }\n> = {\n google: { label: \"Google\", Icon: RiGoogleFill },\n apple: { label: \"Apple\", Icon: RiAppleFill },\n github: { label: \"GitHub\", Icon: RiGithubFill },\n x: { label: \"X\", Icon: RiTwitterXFill },\n};\n\nconst ACTION_LABELS = {\n login: \"Login with\",\n signup: \"Sign up with\",\n continue: \"Continue with\",\n} as const;\n\nexport interface SocialProvidersProps {\n providers?: SocialProvider[];\n /** Verb used in the stacked layout labels. */\n action?: keyof typeof ACTION_LABELS;\n /** \"stack\" = full-width labeled buttons; \"row\" = icon-only buttons. */\n layout?: \"stack\" | \"row\";\n /** Shows the matching button in its loading state and disables the rest. */\n loadingProvider?: SocialProvider | null;\n disabled?: boolean;\n onSelect?: (provider: SocialProvider) => void;\n className?: string;\n}\n\n/** Social auth buttons (coss particle p-button-38). UI only — wire onSelect. */\nexport function SocialProviders({\n providers = [\"google\", \"apple\", \"github\"],\n action = \"continue\",\n layout = \"stack\",\n loadingProvider = null,\n disabled = false,\n onSelect,\n className,\n}: SocialProvidersProps) {\n const row = layout === \"row\";\n\n return (\n <div\n className={cn(\n \"flex w-full gap-2\",\n row ? \"flex-row justify-center\" : \"flex-col\",\n className,\n )}\n >\n {providers.map((provider) => {\n const { label, Icon } = PROVIDERS[provider];\n return (\n <Button\n key={provider}\n variant=\"outline\"\n size={row ? \"icon\" : \"default\"}\n className={row ? undefined : \"w-full\"}\n aria-label={`${ACTION_LABELS[action]} ${label}`}\n loading={loadingProvider === provider}\n disabled={disabled || (loadingProvider !== null && loadingProvider !== provider)}\n onClick={() => onSelect?.(provider)}\n >\n <Icon aria-hidden=\"true\" />\n {!row && (\n <span className=\"flex-1\">\n {ACTION_LABELS[action]} {label}\n </span>\n )}\n </Button>\n );\n })}\n </div>\n );\n}\n","/**\n * Brand accents for the auth blocks.\n *\n * An accent is a set of custom properties set on the AuthCard root plus one\n * class string applied to the card's primary action. Splitting it this way\n * keeps the accent inheritable — anything else inside the card can opt into\n * `var(--auth-accent)` without the shell knowing about it.\n */\n\n/** Brand accents available to the auth blocks. */\nexport type AuthAccent = \"corpora\" | \"exegia\";\n\n/**\n * Custom properties an accent contributes, set on the AuthCard root.\n *\n * The gradient lives in `--auth-accent-image` because `background-color` can't\n * hold one; `--auth-accent` sits underneath as the solid that paints wherever\n * the image is `none`. Foregrounds are fixed rather than themed — the accent\n * itself is a constant, so its contrast pair has to be too (white on the\n * corpora yellow fails badly).\n */\nexport const authAccentVars: Record<AuthAccent, Record<string, string>> = {\n corpora: {\n \"--auth-accent\": \"#E8B124\",\n \"--auth-accent-image\": \"none\",\n \"--auth-accent-foreground\": \"oklch(0.145 0 0)\",\n },\n exegia: {\n \"--auth-accent\": \"#3B0080\",\n \"--auth-accent-image\":\n \"linear-gradient(44deg in oklab, rgba(29,0,202,0.66) 3%, #3B0080 37%, rgba(36,0,72,0.86) 98%)\",\n \"--auth-accent-foreground\": \"oklch(0.985 0 0)\",\n },\n};\n\n/**\n * Applied to the primary action inside an accented AuthCard, after the button\n * cva output so tailwind-merge lets it win over `bg-primary`. The hover and\n * pressed background entries are required: `hover:bg-primary/90` lives in a\n * different modifier group from `bg-*` and would otherwise survive and repaint\n * the button on hover.\n *\n * Hover uses `brightness` rather than a background tween because the button's\n * `transition-property` list is shared with its press/size animations — adding\n * `filter` to it means restating the whole list and its per-property\n * durations. The trade is an instant hover change instead of a 150ms one.\n */\nexport const authAccentActionStyles =\n \"border-transparent bg-[var(--auth-accent)] bg-[image:var(--auth-accent-image)] text-[var(--auth-accent-foreground)] shadow-none hover:bg-[var(--auth-accent)] hover:brightness-110 data-pressed:bg-[var(--auth-accent)] data-pressed:brightness-110 *:data-[slot=button-loading-indicator]:text-[var(--auth-accent-foreground)]\";\n","\"use client\";\n\nimport { AnimatePresence, MotionConfig, motion } from \"motion/react\";\nimport * as React from \"react\";\n\nimport {\n Card,\n CardDescription,\n CardHeader,\n CardPanel,\n CardTitle,\n} from \"@/components/ui/card\";\nimport { Frame, FrameFooter } from \"@/components/ui/frame\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { type AuthAccent, authAccentVars } from \"@/lib/auth-accent\";\nimport { cn } from \"@/lib/utils\";\n\n/** transitions.dev motion scale, shared by all auth blocks. */\nexport const EASE = [0.22, 1, 0.36, 1] as const;\n\nexport type AuthStatus = \"idle\" | \"loading\" | \"success\" | \"error\";\n\n/**\n * Frame shell shared by the auth blocks (coss particle p-card-8): a raised\n * Card inside a muted Frame, with the footer in the frame strip below the\n * card. Wraps content in a MotionConfig that honors prefers-reduced-motion\n * and layout-animates height changes so step swaps morph instead of jumping.\n */\nexport function AuthCard({\n title,\n description,\n children,\n footer,\n className,\n logo,\n accent,\n}: {\n title: React.ReactNode;\n description?: React.ReactNode;\n children: React.ReactNode;\n footer?: React.ReactNode;\n className?: string;\n /** Brand mark rendered above the title. Omit for no logo row at all. */\n logo?: React.ReactNode;\n /** Brand accent for the card's primary action. Omit to keep `bg-primary`. */\n accent?: AuthAccent;\n}) {\n return (\n <MotionConfig reducedMotion=\"user\">\n <Frame\n className={cn(\"w-full max-w-sm\", className)}\n data-accent={accent}\n style={\n accent ? (authAccentVars[accent] as React.CSSProperties) : undefined\n }\n >\n <motion.div\n layout\n transition={{ duration: 0.3, ease: EASE }}\n className=\"flex flex-col\"\n >\n <Card>\n <CardHeader>\n {logo && (\n // Sized like the button's icon rule: a bare img/svg gets a\n // default height, an explicitly sized one keeps its own.\n <div\n className=\"mb-1.5 flex items-center [&_img:not([class*='h-'])]:h-8 [&_img]:w-auto [&_svg:not([class*='size-'])]:size-8\"\n data-slot=\"auth-logo\"\n >\n {logo}\n </div>\n )}\n <CardTitle>{title}</CardTitle>\n {description && <CardDescription>{description}</CardDescription>}\n </CardHeader>\n <CardPanel className=\"overflow-hidden\">{children}</CardPanel>\n </Card>\n {footer && (\n <FrameFooter className=\"text-center text-sm text-muted-foreground\">\n {footer}\n </FrameFooter>\n )}\n </motion.div>\n </Frame>\n </MotionConfig>\n );\n}\n\n/** Cross-morphs between steps (form → success, …) keyed by `step`. */\nexport function MorphStep({\n step,\n children,\n className,\n}: {\n step: string;\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <AnimatePresence mode=\"popLayout\" initial={false}>\n <motion.div\n key={step}\n className={className}\n initial={{ opacity: 0, y: 8, filter: \"blur(2px)\" }}\n animate={{ opacity: 1, y: 0, filter: \"blur(0px)\" }}\n exit={{ opacity: 0, y: -8, filter: \"blur(2px)\" }}\n transition={{ duration: 0.25, ease: EASE }}\n >\n {children}\n </motion.div>\n </AnimatePresence>\n );\n}\n\n/**\n * Progressive-disclosure wrapper: collapses/expands a step as `show` flips.\n *\n * `overflow-hidden` is only worn while the height is in flight — leaving it on\n * would clip the focus ring of any full-width control inside (the ring sits\n * 3px outside the input's border box, so the left/right edges would be cut).\n */\nexport function Reveal({\n show,\n children,\n className,\n}: {\n show: boolean;\n children: React.ReactNode;\n className?: string;\n}) {\n // Reset during render (not in an effect) when `show` flips, matching\n // useCountdown below.\n const [state, setState] = React.useState({ show, settled: show });\n if (state.show !== show) setState({ show, settled: false });\n\n return (\n <AnimatePresence initial={false}>\n {show && (\n <motion.div\n className={cn(!state.settled && \"overflow-hidden\", className)}\n initial={{ height: 0, opacity: 0, y: -4, filter: \"blur(2px)\" }}\n animate={{ height: \"auto\", opacity: 1, y: 0, filter: \"blur(0px)\" }}\n exit={{ height: 0, opacity: 0, y: -4, filter: \"blur(2px)\" }}\n transition={{ duration: 0.25, ease: EASE }}\n onAnimationComplete={() =>\n setState((current) => ({ ...current, settled: true }))\n }\n >\n {children}\n </motion.div>\n )}\n </AnimatePresence>\n );\n}\n\n/** Inline error message that shakes each time `message` changes. */\nexport function AuthError({ message }: { message: string | null }) {\n return (\n <AnimatePresence initial={false}>\n {message && (\n <motion.p\n key={message}\n role=\"alert\"\n className=\"text-sm text-destructive-foreground\"\n initial={{ opacity: 0, height: 0 }}\n animate={{\n opacity: 1,\n height: \"auto\",\n x: [0, -6, 6, -4, 4, 0],\n }}\n exit={{ opacity: 0, height: 0 }}\n transition={{\n duration: 0.25,\n ease: EASE,\n x: { duration: 0.4, ease: \"easeInOut\" },\n }}\n >\n {message}\n </motion.p>\n )}\n </AnimatePresence>\n );\n}\n\n/** Success panel with a stroke-drawn check. */\nexport function AuthSuccess({\n title,\n description,\n children,\n}: {\n title: React.ReactNode;\n description?: React.ReactNode;\n children?: React.ReactNode;\n}) {\n return (\n <div className=\"flex flex-col items-center gap-3 py-4 text-center\">\n <motion.span\n className=\"flex size-12 items-center justify-center rounded-full bg-emerald-500/12 text-emerald-600\"\n initial={{ scale: 0.6, opacity: 0 }}\n animate={{ scale: 1, opacity: 1 }}\n transition={{ duration: 0.4, ease: EASE }}\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n className=\"size-6\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <motion.path\n d=\"M4 12.5l5 5L20 6.5\"\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={{ duration: 0.4, delay: 0.15, ease: EASE }}\n />\n </svg>\n </motion.span>\n <div className=\"flex flex-col gap-1\">\n <p className=\"font-medium\">{title}</p>\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n {children}\n </div>\n );\n}\n\n/** \"Or continue with\" style divider. */\nexport function AuthSeparator({ label = \"Or\" }: { label?: string }) {\n return (\n <div className=\"flex items-center gap-3\">\n <Separator className=\"flex-1\" />\n <span className=\"text-xs text-muted-foreground uppercase\">{label}</span>\n <Separator className=\"flex-1\" />\n </div>\n );\n}\n\n/** Countdown for resend links; restarts when `restartKey` changes. */\nexport function useCountdown(seconds: number, restartKey: number) {\n const [state, setState] = React.useState({ restartKey, seconds, remaining: seconds });\n\n // Reset during render (not in an effect) when the inputs change.\n if (state.restartKey !== restartKey || state.seconds !== seconds) {\n setState({ restartKey, seconds, remaining: seconds });\n }\n\n React.useEffect(() => {\n if (seconds <= 0) return;\n const interval = window.setInterval(() => {\n setState((current) =>\n current.remaining <= 0\n ? current\n : { ...current, remaining: current.remaining - 1 },\n );\n }, 1000);\n return () => window.clearInterval(interval);\n }, [seconds, restartKey]);\n\n return state.remaining;\n}\n","\"use client\";\n\nimport { MailIcon, SmartphoneIcon } from \"lucide-react\";\nimport { motion } from \"motion/react\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { OTPField, OTPFieldInput } from \"@/components/ui/otp-field\";\nimport { type AuthAccent, authAccentActionStyles } from \"@/lib/auth-accent\";\nimport { cn } from \"@/lib/utils\";\nimport {\n AuthCard,\n AuthError,\n AuthSuccess,\n EASE,\n MorphStep,\n useCountdown,\n type AuthStatus,\n} from \"./auth-shell\";\n\nexport interface CodeAuthBlockProps {\n /** Brand mark rendered above the title. Omit for no logo row at all. */\n logo?: React.ReactNode;\n /** Brand accent for the primary action. Omit to keep the default primary. */\n accent?: AuthAccent;\n /** Where the code was sent; drives copy and icon. */\n channel?: \"email\" | \"sms\";\n /** Masked destination shown in the description, e.g. \"y•••@example.com\". */\n destination?: string;\n length?: number;\n /** Submit automatically once all digits are entered. */\n autoSubmit?: boolean;\n /** Seconds before \"Resend code\" becomes available. 0 disables the wait. */\n resendSeconds?: number;\n /** Reject (or throw) to show the error shake and clear the code. */\n onVerify?: (code: string) => Promise<void> | void;\n onResend?: () => Promise<void> | void;\n onBack?: () => void;\n}\n\nexport function CodeAuthBlock({\n channel = \"email\",\n logo,\n accent,\n destination,\n length = 6,\n autoSubmit = true,\n resendSeconds = 30,\n onVerify,\n onResend,\n onBack,\n}: CodeAuthBlockProps) {\n const [status, setStatus] = React.useState<AuthStatus>(\"idle\");\n const [error, setError] = React.useState<string | null>(null);\n const [code, setCode] = React.useState(\"\");\n const [resendCount, setResendCount] = React.useState(0);\n const remaining = useCountdown(resendSeconds, resendCount);\n\n const ChannelIcon = channel === \"sms\" ? SmartphoneIcon : MailIcon;\n const channelLabel = channel === \"sms\" ? \"phone\" : \"email\";\n\n const verify = React.useCallback(\n async (value: string) => {\n setError(null);\n setStatus(\"loading\");\n try {\n await onVerify?.(value);\n setStatus(\"success\");\n } catch (cause) {\n setStatus(\"idle\");\n setCode(\"\");\n setError(cause instanceof Error ? cause.message : \"Invalid code.\");\n }\n },\n [onVerify],\n );\n\n function handleChange(value: string) {\n setCode(value);\n if (error) setError(null);\n if (autoSubmit && value.length === length && status === \"idle\") {\n void verify(value);\n }\n }\n\n async function handleResend() {\n setResendCount((count) => count + 1);\n setCode(\"\");\n setError(null);\n await onResend?.();\n }\n\n return (\n <AuthCard\n title=\"Enter verification code\"\n logo={logo}\n accent={accent}\n description={\n <span className=\"inline-flex items-center gap-1.5\">\n <ChannelIcon className=\"size-3.5 shrink-0\" />\n <span>\n We sent a {length}-digit code to your {channelLabel}\n {destination ? (\n <>\n {\" \"}\n <span className=\"font-medium text-foreground\">\n {destination}\n </span>\n </>\n ) : null}\n .\n </span>\n </span>\n }\n footer={\n status !== \"success\" && (\n <Button variant=\"link\" onClick={onBack}>\n Use a different {channelLabel}\n </Button>\n )\n }\n >\n <MorphStep step={status === \"success\" ? \"success\" : \"form\"}>\n {status === \"success\" ? (\n <AuthSuccess\n title=\"Verified\"\n description=\"Your identity has been confirmed.\"\n />\n ) : (\n <div className=\"flex flex-col items-center gap-4\">\n <motion.div\n // Shake the whole field on error; keying by message replays it.\n key={error ?? \"steady\"}\n animate={error ? { x: [0, -8, 8, -5, 5, 0] } : { x: 0 }}\n transition={{ duration: 0.4, ease: \"easeInOut\" }}\n >\n <OTPField\n length={length}\n value={code}\n onValueChange={handleChange}\n disabled={status === \"loading\"}\n >\n {Array.from({ length }, (_, index) => (\n <OTPFieldInput\n key={`slot-${index}`}\n aria-invalid={error ? true : undefined}\n aria-label={`Digit ${index + 1} of ${length}`}\n />\n ))}\n </OTPField>\n </motion.div>\n <AuthError message={error} />\n {!autoSubmit && (\n <Button\n className={cn(\"w-full\", accent && authAccentActionStyles)}\n loading={status === \"loading\"}\n disabled={code.length !== length}\n onClick={() => void verify(code)}\n >\n Verify\n </Button>\n )}\n <motion.p\n layout\n transition={{ duration: 0.25, ease: EASE }}\n className=\"text-center text-sm text-muted-foreground\"\n >\n {remaining > 0 ? (\n <>\n Resend code in{\" \"}\n <span className=\"font-medium tabular-nums text-foreground\">\n {remaining}s\n </span>\n </>\n ) : (\n <Button\n variant=\"link\"\n disabled={status === \"loading\"}\n onClick={() => void handleResend()}\n >\n Resend code\n </Button>\n )}\n </motion.p>\n </div>\n )}\n </MorphStep>\n </AuthCard>\n );\n}\n","\"use client\";\n\nimport { ArrowLeftIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Field, FieldLabel } from \"@/components/ui/field\";\nimport { Input } from \"@/components/ui/input\";\nimport { type AuthAccent, authAccentActionStyles } from \"@/lib/auth-accent\";\nimport { cn } from \"@/lib/utils\";\nimport {\n AuthCard,\n AuthError,\n AuthSuccess,\n MorphStep,\n type AuthStatus,\n} from \"./auth-shell\";\n\nexport interface ForgotPasswordBlockProps {\n title?: string;\n description?: string;\n /** Brand mark rendered above the title. Omit for no logo row at all. */\n logo?: React.ReactNode;\n /** Brand accent for the primary action. Omit to keep the default primary. */\n accent?: AuthAccent;\n onSubmit?: (data: { email: string }) => Promise<void> | void;\n onBackToLogin?: () => void;\n}\n\nexport function ForgotPasswordBlock({\n title = \"Reset your password\",\n logo,\n accent,\n description = \"Enter your email and we will send you a reset link\",\n onSubmit,\n onBackToLogin,\n}: ForgotPasswordBlockProps) {\n const emailId = React.useId();\n const [status, setStatus] = React.useState<AuthStatus>(\"idle\");\n const [error, setError] = React.useState<string | null>(null);\n const [email, setEmail] = React.useState(\"\");\n\n async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault();\n setError(null);\n setStatus(\"loading\");\n try {\n await onSubmit?.({ email });\n setStatus(\"success\");\n } catch (cause) {\n setStatus(\"idle\");\n setError(\n cause instanceof Error ? cause.message : \"Unable to send reset link.\",\n );\n }\n }\n\n return (\n <AuthCard\n title={title}\n description={description}\n logo={logo}\n accent={accent}\n footer={\n <Button\n variant=\"link\"\n className=\"gap-1\"\n onClick={onBackToLogin}\n >\n <ArrowLeftIcon className=\"size-3.5\" />\n Back to login\n </Button>\n }\n >\n <MorphStep step={status === \"success\" ? \"success\" : \"form\"}>\n {status === \"success\" ? (\n <AuthSuccess\n title=\"Check your inbox\"\n description={\n <>\n We sent a password reset link to{\" \"}\n <span className=\"font-medium text-foreground\">{email}</span>.\n </>\n }\n >\n <Button\n variant=\"link\"\n className=\"text-xs sm:text-xs\"\n onClick={() => setStatus(\"idle\")}\n >\n Use a different email\n </Button>\n </AuthSuccess>\n ) : (\n <form className=\"flex flex-col gap-4\" onSubmit={handleSubmit}>\n <Field name=\"email\">\n <FieldLabel htmlFor={emailId}>Email</FieldLabel>\n <Input\n id={emailId}\n name=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n required\n disabled={status === \"loading\"}\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n />\n </Field>\n <AuthError message={error} />\n <Button\n className={cn(\"w-full\", accent && authAccentActionStyles)}\n type=\"submit\"\n loading={status === \"loading\"}\n >\n Send reset link\n </Button>\n </form>\n )}\n </MorphStep>\n </AuthCard>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { PasswordInput } from \"@/components/composed/password-input\";\nimport {\n SocialProviders,\n type SocialProvider,\n} from \"@/components/composed/social-providers\";\nimport { Button } from \"@/components/ui/button\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport { Field, FieldLabel } from \"@/components/ui/field\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { type AuthAccent, authAccentActionStyles } from \"@/lib/auth-accent\";\nimport { cn } from \"@/lib/utils\";\nimport {\n AuthCard,\n AuthError,\n AuthSeparator,\n AuthSuccess,\n MorphStep,\n Reveal,\n type AuthStatus,\n} from \"./auth-shell\";\n\nexport interface LoginBlockProps {\n title?: string;\n description?: string;\n /** Brand mark rendered above the title. Omit for no logo row at all. */\n logo?: React.ReactNode;\n /** Brand accent for the primary action. Omit to keep the default primary. */\n accent?: AuthAccent;\n /** Social providers to offer; empty array hides the social section. */\n providers?: SocialProvider[];\n showRememberMe?: boolean;\n showForgotPassword?: boolean;\n /** Reject (or throw) to show the error state with the error's message. */\n onSubmit?: (data: {\n email: string;\n password: string;\n remember: boolean;\n }) => Promise<void> | void;\n onProviderSelect?: (provider: SocialProvider) => Promise<void> | void;\n onForgotPassword?: () => void;\n onSignup?: () => void;\n}\n\nexport function LoginBlock({\n title = \"Login to your account\",\n description = \"Enter your email and password to login\",\n logo,\n accent,\n providers = [\"google\", \"apple\", \"github\"],\n showRememberMe = true,\n showForgotPassword = true,\n onSubmit,\n onProviderSelect,\n onForgotPassword,\n onSignup,\n}: LoginBlockProps) {\n const emailId = React.useId();\n const rememberId = React.useId();\n const [status, setStatus] = React.useState<AuthStatus>(\"idle\");\n const [error, setError] = React.useState<string | null>(null);\n const [loadingProvider, setLoadingProvider] =\n React.useState<SocialProvider | null>(null);\n const [remember, setRemember] = React.useState(false);\n const [email, setEmail] = React.useState(\"\");\n const [emailValid, setEmailValid] = React.useState(false);\n const [password, setPassword] = React.useState(\"\");\n\n const busy = status === \"loading\" || loadingProvider !== null;\n\n // Progressive disclosure: each step unlocks the next. The password field is\n // gated on the email input's own constraint validation (required + type\n // email), the submit button on the password being non-empty — a login form\n // verifies a credential rather than enforcing policy, so strength rules here\n // would lock out anyone whose password predates them. The submit gate\n // re-checks emailValid so a stale password (typed, then the email was edited\n // back into an invalid state) can't leave the button on its own.\n const passwordValid = password.trim().length > 0;\n const canSubmit = emailValid && passwordValid;\n\n async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault();\n // Enter in any field submits the form even while the button is hidden.\n if (!canSubmit) return;\n const form = new FormData(event.currentTarget);\n setError(null);\n setStatus(\"loading\");\n try {\n await onSubmit?.({\n email: String(form.get(\"email\") ?? \"\"),\n password: String(form.get(\"password\") ?? \"\"),\n remember,\n });\n setStatus(\"success\");\n } catch (cause) {\n setStatus(\"idle\");\n setError(cause instanceof Error ? cause.message : \"Unable to login.\");\n }\n }\n\n async function handleProvider(provider: SocialProvider) {\n setError(null);\n setLoadingProvider(provider);\n try {\n await onProviderSelect?.(provider);\n setStatus(\"success\");\n } catch (cause) {\n setError(\n cause instanceof Error ? cause.message : \"Unable to login.\",\n );\n } finally {\n setLoadingProvider(null);\n }\n }\n\n return (\n <AuthCard\n title={title}\n description={description}\n logo={logo}\n accent={accent}\n footer={\n status !== \"success\" && (\n <>\n Don't have an account?{\" \"}\n <Button variant=\"link\" onClick={onSignup}>\n Sign up\n </Button>\n </>\n )\n }\n >\n <MorphStep step={status === \"success\" ? \"success\" : \"form\"}>\n {status === \"success\" ? (\n <AuthSuccess\n title=\"Welcome back\"\n description=\"You are now logged in.\"\n />\n ) : (\n <div className=\"flex flex-col gap-4\">\n <form className=\"flex flex-col gap-4\" onSubmit={handleSubmit}>\n <Field name=\"email\">\n <FieldLabel htmlFor={emailId}>Email</FieldLabel>\n <Input\n id={emailId}\n aria-label=\"Email\"\n name=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n required\n disabled={busy}\n value={email}\n onChange={(event) => {\n setEmail(event.currentTarget.value);\n setEmailValid(event.currentTarget.validity.valid);\n }}\n />\n </Field>\n <Reveal show={emailValid}>\n <Field name=\"password\">\n <FieldLabel htmlFor=\"password\">Password</FieldLabel>\n <PasswordInput\n id=\"password\"\n name=\"password\"\n autoComplete=\"current-password\"\n required\n disabled={busy}\n value={password}\n onChange={(event) => setPassword(event.target.value)}\n />\n {showForgotPassword && (\n // self-end: Field root is items-start, so this aligns the\n // link with the input's trailing edge. sm:text-xs is\n // required — the cva's sm:text-sm survives tailwind-merge\n // and would otherwise win at the breakpoint.\n <Button\n variant=\"link\"\n type=\"button\"\n className=\"self-end font-normal text-muted-foreground text-xs hover:text-foreground sm:text-xs\"\n onClick={onForgotPassword}\n >\n Forgot password?\n </Button>\n )}\n </Field>\n </Reveal>\n {showRememberMe && (\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id={rememberId}\n checked={remember}\n onCheckedChange={(checked) => setRemember(checked)}\n disabled={busy}\n />\n <Label htmlFor={rememberId} className=\"font-normal\">\n Remember me\n </Label>\n </div>\n )}\n <AuthError message={error} />\n <Reveal show={canSubmit}>\n <Button\n className={cn(\"w-full\", accent && authAccentActionStyles)}\n type=\"submit\"\n loading={status === \"loading\"}\n disabled={busy}\n >\n Login\n </Button>\n </Reveal>\n </form>\n {providers.length > 0 && (\n // The social providers retire once the email path is filled in\n // and valid — the user has committed to a path, so the\n // alternatives are just noise. They come back if a field is\n // invalidated again. gap-4 on the wrapper reproduces the spacing\n // the two children had as direct flex items of the column above.\n <Reveal show={!canSubmit} className=\"flex flex-col gap-4\">\n <AuthSeparator label=\"Or continue with\" />\n <SocialProviders\n providers={providers}\n action=\"login\"\n loadingProvider={loadingProvider}\n disabled={status === \"loading\"}\n onSelect={handleProvider}\n />\n </Reveal>\n )}\n </div>\n )}\n </MorphStep>\n </AuthCard>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport {\n PasswordInput,\n getPasswordStrength,\n passwordRequirements,\n} from \"@/components/composed/password-input\";\nimport {\n SocialProviders,\n type SocialProvider,\n} from \"@/components/composed/social-providers\";\nimport { Button } from \"@/components/ui/button\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport { Field, FieldLabel } from \"@/components/ui/field\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { type AuthAccent, authAccentActionStyles } from \"@/lib/auth-accent\";\nimport { cn } from \"@/lib/utils\";\nimport {\n AuthCard,\n AuthError,\n AuthSeparator,\n AuthSuccess,\n MorphStep,\n Reveal,\n type AuthStatus,\n} from \"./auth-shell\";\n\nexport interface SignupBlockProps {\n title?: string;\n description?: string;\n /** Brand mark rendered above the title. Omit for no logo row at all. */\n logo?: React.ReactNode;\n /** Brand accent for the primary action. Omit to keep the default primary. */\n accent?: AuthAccent;\n providers?: SocialProvider[];\n showNameField?: boolean;\n /** Require the terms checkbox before submitting. */\n showTerms?: boolean;\n /** Block submission until every password requirement is met. */\n enforceStrongPassword?: boolean;\n onSubmit?: (data: {\n name: string;\n email: string;\n password: string;\n }) => Promise<void> | void;\n onProviderSelect?: (provider: SocialProvider) => Promise<void> | void;\n onLogin?: () => void;\n onTerms?: () => void;\n}\n\nexport function SignupBlock({\n title = \"Create your account\",\n description = \"Start exploring manuscripts in minutes\",\n logo,\n accent,\n providers = [\"google\", \"apple\", \"github\"],\n showNameField = true,\n showTerms = true,\n enforceStrongPassword = true,\n onSubmit,\n onProviderSelect,\n onLogin,\n onTerms,\n}: SignupBlockProps) {\n const nameId = React.useId();\n const emailId = React.useId();\n const termsId = React.useId();\n const [status, setStatus] = React.useState<AuthStatus>(\"idle\");\n const [error, setError] = React.useState<string | null>(null);\n const [loadingProvider, setLoadingProvider] =\n React.useState<SocialProvider | null>(null);\n const [password, setPassword] = React.useState(\"\");\n const [terms, setTerms] = React.useState(false);\n // Tracked from each input's own constraint validation rather than a regex.\n // The values stay uncontrolled — only validity is needed, and the form reads\n // values from FormData on submit.\n const [emailValid, setEmailValid] = React.useState(false);\n const [nameValid, setNameValid] = React.useState(false);\n\n const busy = status === \"loading\" || loadingProvider !== null;\n const strongEnough =\n !enforceStrongPassword ||\n getPasswordStrength(password) === passwordRequirements.length;\n\n // The social providers retire once the email path is filled in and valid —\n // the user has committed to a path, so the alternatives are just noise. It\n // comes back if they invalidate a field again.\n const passwordValid = password.trim().length > 0 && strongEnough;\n const emailPathComplete =\n (!showNameField || nameValid) && emailValid && passwordValid;\n\n async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault();\n setError(null);\n if (!strongEnough) {\n setError(\"Please meet all password requirements.\");\n return;\n }\n if (showTerms && !terms) {\n setError(\"Please accept the terms to continue.\");\n return;\n }\n const form = new FormData(event.currentTarget);\n setStatus(\"loading\");\n try {\n await onSubmit?.({\n name: String(form.get(\"name\") ?? \"\"),\n email: String(form.get(\"email\") ?? \"\"),\n password,\n });\n setStatus(\"success\");\n } catch (cause) {\n setStatus(\"idle\");\n setError(\n cause instanceof Error ? cause.message : \"Unable to create account.\",\n );\n }\n }\n\n async function handleProvider(provider: SocialProvider) {\n setError(null);\n setLoadingProvider(provider);\n try {\n await onProviderSelect?.(provider);\n setStatus(\"success\");\n } catch (cause) {\n setError(\n cause instanceof Error ? cause.message : \"Unable to create account.\",\n );\n } finally {\n setLoadingProvider(null);\n }\n }\n\n return (\n <AuthCard\n title={title}\n description={description}\n logo={logo}\n accent={accent}\n footer={\n status !== \"success\" && (\n <>\n Already have an account?{\" \"}\n <Button variant=\"link\" onClick={onLogin}>\n Login\n </Button>\n </>\n )\n }\n >\n <MorphStep step={status === \"success\" ? \"success\" : \"form\"}>\n {status === \"success\" ? (\n <AuthSuccess\n title=\"Account created\"\n description=\"Check your inbox to confirm your email address.\"\n />\n ) : (\n <div className=\"flex flex-col gap-4\">\n {providers.length > 0 && (\n // gap-4 on the wrapper reproduces the spacing the two children\n // had as direct flex items of the column above.\n <Reveal show={!emailPathComplete} className=\"flex flex-col gap-4\">\n <SocialProviders\n providers={providers}\n action=\"signup\"\n loadingProvider={loadingProvider}\n disabled={status === \"loading\"}\n onSelect={handleProvider}\n />\n <AuthSeparator label=\"Or with email\" />\n </Reveal>\n )}\n <form className=\"flex flex-col gap-4\" onSubmit={handleSubmit}>\n {showNameField && (\n <Field name=\"name\">\n <FieldLabel htmlFor={nameId}>Name</FieldLabel>\n <Input\n aria-label=\"Name\"\n id={nameId}\n name=\"name\"\n autoComplete=\"name\"\n placeholder=\"Your name\"\n required\n disabled={busy}\n onChange={(event) =>\n setNameValid(event.currentTarget.validity.valid)\n }\n />\n </Field>\n )}\n <Field name=\"email\">\n <FieldLabel htmlFor={emailId}>Email</FieldLabel>\n <Input\n id={emailId}\n name=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n required\n disabled={busy}\n onChange={(event) =>\n setEmailValid(event.currentTarget.validity.valid)\n }\n />\n </Field>\n <Reveal show={emailValid}>\n <Field name=\"password\">\n <FieldLabel>Password</FieldLabel>\n <PasswordInput\n name=\"password\"\n autoComplete=\"new-password\"\n placeholder=\"Create a password\"\n showStrength\n required\n disabled={busy}\n value={password}\n onChange={(event) => setPassword(event.target.value)}\n />\n </Field>\n </Reveal>\n {showTerms && (\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id={termsId}\n checked={terms}\n onCheckedChange={(checked) => setTerms(checked === true)}\n disabled={busy}\n />\n <Label htmlFor={termsId} className=\"font-normal\">\n I agree to the{\" \"}\n <Button\n variant=\"link\"\n type=\"button\"\n onClick={onTerms}\n >\n terms\n </Button>\n </Label>\n </div>\n )}\n <AuthError message={error} />\n <Button\n className={cn(\"w-full\", accent && authAccentActionStyles)}\n type=\"submit\"\n loading={status === \"loading\"}\n disabled={busy}\n >\n Create account\n </Button>\n </form>\n </div>\n )}\n </MorphStep>\n </AuthCard>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brand accents for the auth blocks.
|
|
3
|
+
*
|
|
4
|
+
* An accent is a set of custom properties set on the AuthCard root plus one
|
|
5
|
+
* class string applied to the card's primary action. Splitting it this way
|
|
6
|
+
* keeps the accent inheritable — anything else inside the card can opt into
|
|
7
|
+
* `var(--auth-accent)` without the shell knowing about it.
|
|
8
|
+
*/
|
|
9
|
+
/** Brand accents available to the auth blocks. */
|
|
10
|
+
export type AuthAccent = "corpora" | "exegia";
|
|
11
|
+
/**
|
|
12
|
+
* Custom properties an accent contributes, set on the AuthCard root.
|
|
13
|
+
*
|
|
14
|
+
* The gradient lives in `--auth-accent-image` because `background-color` can't
|
|
15
|
+
* hold one; `--auth-accent` sits underneath as the solid that paints wherever
|
|
16
|
+
* the image is `none`. Foregrounds are fixed rather than themed — the accent
|
|
17
|
+
* itself is a constant, so its contrast pair has to be too (white on the
|
|
18
|
+
* corpora yellow fails badly).
|
|
19
|
+
*/
|
|
20
|
+
export declare const authAccentVars: Record<AuthAccent, Record<string, string>>;
|
|
21
|
+
/**
|
|
22
|
+
* Applied to the primary action inside an accented AuthCard, after the button
|
|
23
|
+
* cva output so tailwind-merge lets it win over `bg-primary`. The hover and
|
|
24
|
+
* pressed background entries are required: `hover:bg-primary/90` lives in a
|
|
25
|
+
* different modifier group from `bg-*` and would otherwise survive and repaint
|
|
26
|
+
* the button on hover.
|
|
27
|
+
*
|
|
28
|
+
* Hover uses `brightness` rather than a background tween because the button's
|
|
29
|
+
* `transition-property` list is shared with its press/size animations — adding
|
|
30
|
+
* `filter` to it means restating the whole list and its per-property
|
|
31
|
+
* durations. The trade is an instant hover change instead of a 150ms one.
|
|
32
|
+
*/
|
|
33
|
+
export declare const authAccentActionStyles = "border-transparent bg-[var(--auth-accent)] bg-[image:var(--auth-accent-image)] text-[var(--auth-accent-foreground)] shadow-none hover:bg-[var(--auth-accent)] hover:brightness-110 data-pressed:bg-[var(--auth-accent)] data-pressed:brightness-110 *:data-[slot=button-loading-indicator]:text-[var(--auth-accent-foreground)]";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type FrostGlassVariant = "clear" | "frosted" | "subtle" | "liquid" | "liquid-refract";
|
|
2
|
+
export type FrostGlassVariantProp = {
|
|
3
|
+
glassVariant?: FrostGlassVariant;
|
|
4
|
+
};
|
|
5
|
+
export declare const liquidRefractStyles = "bg-transparent border-0 shadow-none";
|
|
6
|
+
export declare const glassVariantStyles: Record<FrostGlassVariant, string>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SoundName } from 'cuelume';
|
|
2
|
+
/** Opt into interaction sound. Delegated and idempotent (see cuelume bind). */
|
|
3
|
+
export declare function bindSounds(root?: ParentNode): void;
|
|
4
|
+
/**
|
|
5
|
+
* Imperative cue used by library components for keyboard-driven interactions
|
|
6
|
+
* the data attributes can't cover (OTP typing, visibility toggles, …).
|
|
7
|
+
* No-op until the app has opted in via bindSounds().
|
|
8
|
+
*/
|
|
9
|
+
export declare function playCue(name: SoundName, options?: {
|
|
10
|
+
volume?: number;
|
|
11
|
+
}): void;
|
|
12
|
+
export { play as playSound, setEnabled as setSoundEnabled, setVolume as setSoundVolume, sounds, } from 'cuelume';
|
|
13
|
+
export type { SoundName };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@exegia/corpora-ui",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "shadcn-ready React UI library for the corpora manuscript-research apps.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/exegia/corpora-ui.git"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"module": "./dist-lib/index.js",
|
|
13
|
+
"types": "./dist-lib/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist-lib/index.d.ts",
|
|
17
|
+
"import": "./dist-lib/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./index.css": "./src/index.css",
|
|
20
|
+
"./package.json": "./package.json"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist-lib",
|
|
24
|
+
"src/components",
|
|
25
|
+
"src/lib",
|
|
26
|
+
"src/index.css",
|
|
27
|
+
"src/index.ts"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"dev": "vite",
|
|
31
|
+
"build": "tsc -b && vite build && bun run build:lib",
|
|
32
|
+
"build:lib": "vite build --config vite.lib.config.ts",
|
|
33
|
+
"lint": "eslint .",
|
|
34
|
+
"format": "prettier --write \"**/*.{ts,tsx}\"",
|
|
35
|
+
"test": "bun test",
|
|
36
|
+
"typecheck": "tsc -b --noEmit",
|
|
37
|
+
"preview": "vite preview"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"react": "^19.0.0",
|
|
41
|
+
"react-dom": "^19.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@base-ui/react": "^1.6.0",
|
|
45
|
+
"@remixicon/react": "^4.9.0",
|
|
46
|
+
"class-variance-authority": "^0.7.1",
|
|
47
|
+
"clsx": "^2.1.1",
|
|
48
|
+
"cuelume": "^0.2.1",
|
|
49
|
+
"lucide-react": "^1.27.0",
|
|
50
|
+
"motion": "^12.43.0",
|
|
51
|
+
"tailwind-merge": "^3.6.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@eslint/js": "^10",
|
|
55
|
+
"@fontsource-variable/figtree": "^5.3.0",
|
|
56
|
+
"@fontsource-variable/inter": "^5.3.0",
|
|
57
|
+
"@tailwindcss/vite": "^4",
|
|
58
|
+
"@types/bun": "^1.3.14",
|
|
59
|
+
"@types/node": "^24",
|
|
60
|
+
"@types/react": "^19",
|
|
61
|
+
"@types/react-dom": "^19",
|
|
62
|
+
"@vitejs/plugin-react": "^6",
|
|
63
|
+
"eslint": "^10",
|
|
64
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
65
|
+
"eslint-plugin-react-refresh": "^0.5.2",
|
|
66
|
+
"globals": "^17",
|
|
67
|
+
"prettier": "^3.8.3",
|
|
68
|
+
"prettier-plugin-tailwindcss": "^0.8.0",
|
|
69
|
+
"react": "^19.2.6",
|
|
70
|
+
"react-dom": "^19.2.6",
|
|
71
|
+
"react-router": "^8.3.0",
|
|
72
|
+
"shadcn": "^4.16.0",
|
|
73
|
+
"tailwindcss": "^4",
|
|
74
|
+
"tw-animate-css": "^1.4.0",
|
|
75
|
+
"typescript": "~6",
|
|
76
|
+
"typescript-eslint": "^8",
|
|
77
|
+
"vite": "^8",
|
|
78
|
+
"vite-plugin-dts": "^5.0.3"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
File without changes
|