@sckyzo/cosmos-react 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { clsx } from 'clsx';
2
2
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
3
3
  import { forwardRef, createContext, Children, Fragment, cloneElement, isValidElement, useState, useRef, useCallback, useEffect, useId, useContext, useMemo } from 'react';
4
- import { ChevronRight, Check, Copy, BellOff, Bell, CheckCircle2, Info, AlertTriangle, XCircle, ChevronDown, Sun, Moon, MoonStar, ExternalLink, Search, EyeOff, Eye, Minus, Paperclip, Clock, X, ChevronLeft, Dot as Dot$1, ArrowRight, HelpCircle, Home, Inbox, AlertCircle, CheckCircle, RefreshCw, Loader2, Save, Megaphone, Cookie, ArrowUp, ChevronUp, Plus, Maximize2, RotateCcw, Camera, Trash2, Upload, File, ChevronsUpDown, Filter, Quote, Calendar as Calendar$1 } from 'lucide-react';
4
+ import { ChevronRight, Check, Copy, BellOff, Bell, CheckCircle2, Info, AlertTriangle, XCircle, ChevronDown, Sun, Moon, MoonStar, ExternalLink, Search, EyeOff, Eye, Minus, Paperclip, Clock, X, ChevronLeft, Dot as Dot$1, ArrowRight, HelpCircle, Home, Inbox, AlertCircle, CheckCircle, RefreshCw, Loader2, Save, Megaphone, Cookie, ArrowUp, ChevronUp, Plus, Maximize2, RotateCcw, Camera, Trash2, Upload, File, ChevronsUpDown, Filter, MailCheck, ArrowLeft, Mail, User, ShieldCheck, Quote, Calendar as Calendar$1 } from 'lucide-react';
5
5
  import { createPortal } from 'react-dom';
6
6
  import Autoplay from 'embla-carousel-autoplay';
7
7
  import useEmblaCarousel from 'embla-carousel-react';
@@ -12,93 +12,6 @@ import { Command } from 'cmdk';
12
12
  import { getDefaultClassNames, DayPicker } from 'react-day-picker';
13
13
  import 'react-day-picker/style.css';
14
14
 
15
- // src/storybook-avatars.ts
16
- var PALETTE = [
17
- ["#6366f1", "#ffffff"],
18
- // indigo
19
- ["#8b5cf6", "#ffffff"],
20
- // violet
21
- ["#0ea5e9", "#ffffff"],
22
- // sky
23
- ["#10b981", "#ffffff"],
24
- // emerald
25
- ["#f59e0b", "#1f2937"],
26
- // amber (dark text on warm bg)
27
- ["#f43f5e", "#ffffff"],
28
- // rose
29
- ["#14b8a6", "#ffffff"],
30
- // teal
31
- ["#ec4899", "#ffffff"],
32
- // pink
33
- ["#64748b", "#ffffff"],
34
- // slate
35
- ["#a855f7", "#ffffff"]
36
- // purple
37
- ];
38
- var hashSeed = (seed) => {
39
- let h = 5381;
40
- for (let i = 0; i < seed.length; i += 1) {
41
- h = (h << 5) + h + seed.charCodeAt(i) | 0;
42
- }
43
- return Math.abs(h);
44
- };
45
- var extractInitials = (seed) => {
46
- const cleaned = seed.replace(/[^\p{L}\p{N}\s'.-]/gu, " ").trim();
47
- if (!cleaned) return "?";
48
- const parts = cleaned.split(/[\s.'-]+/).filter(Boolean);
49
- if (parts.length >= 2) {
50
- return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
51
- }
52
- return cleaned.slice(0, 2).toUpperCase();
53
- };
54
- var buildSvg = (initials, bg, fg, size) => {
55
- const fontSize = initials.length === 1 ? 56 : 42;
56
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 100 100"><rect width="100" height="100" fill="${bg}"/><text x="50" y="50" font-family="ui-sans-serif,system-ui,sans-serif" font-size="${fontSize}" font-weight="600" fill="${fg}" text-anchor="middle" dominant-baseline="central">${initials}</text></svg>`;
57
- };
58
- var placeholderAvatar = (seed, size = 64, opts = {}) => {
59
- const initials = extractInitials(seed);
60
- const [defaultBg, defaultFg] = PALETTE[hashSeed(seed) % PALETTE.length];
61
- const bg = opts.bg ?? defaultBg;
62
- const fg = opts.fg ?? defaultFg;
63
- const svg = buildSvg(initials, bg, fg, size);
64
- return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
65
- };
66
- var buildCoverSvg = (seed, from, to, width, height) => {
67
- const h = hashSeed(seed);
68
- const angle = h % 180;
69
- const cx1 = h % 60 + 20;
70
- const cy1 = (h >> 3) % 60 + 20;
71
- const r1 = (h >> 5) % 35 + 25;
72
- const cx2 = (h >> 7) % 60 + 20;
73
- const cy2 = (h >> 9) % 60 + 20;
74
- const r2 = (h >> 11) % 25 + 15;
75
- const gradientId = `g-${(h % 1e5).toString(36)}`;
76
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 100 100" preserveAspectRatio="none"><defs><linearGradient id="${gradientId}" gradientTransform="rotate(${angle})"><stop offset="0" stop-color="${from}"/><stop offset="1" stop-color="${to}"/></linearGradient></defs><rect width="100" height="100" fill="url(#${gradientId})"/><circle cx="${cx1}" cy="${cy1}" r="${r1}" fill="rgba(255,255,255,0.08)"/><circle cx="${cx2}" cy="${cy2}" r="${r2}" fill="rgba(0,0,0,0.10)"/></svg>`;
77
- };
78
- var placeholderCover = (seed, width = 1600, height = 700, opts = {}) => {
79
- const h = hashSeed(seed);
80
- const [from] = PALETTE[h % PALETTE.length];
81
- const [to] = PALETTE[(h + 3) % PALETTE.length];
82
- const svg = buildCoverSvg(seed, opts.from ?? from, opts.to ?? to, width, height);
83
- return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
84
- };
85
-
86
- // src/storybook-helpers.ts
87
- var buildParams = (height) => ({
88
- layout: "fullscreen",
89
- docs: {
90
- story: {
91
- inline: false,
92
- iframeHeight: `${height}px`
93
- }
94
- }
95
- });
96
- var fn = ((height = 480) => buildParams(height));
97
- fn.sm = () => buildParams(320);
98
- fn.md = () => buildParams(480);
99
- fn.lg = () => buildParams(640);
100
- fn.full = () => buildParams(800);
101
- var portalDocsParams = fn;
102
15
  var Root = ({
103
16
  inset,
104
17
  align = "center",
@@ -2068,6 +1981,8 @@ var Dropdown = ({
2068
1981
  }) => {
2069
1982
  const [open, setOpen] = useState(false);
2070
1983
  const ref = useRef(null);
1984
+ const triggerRef = useRef(null);
1985
+ const menuRef = useRef(null);
2071
1986
  useEffect(() => {
2072
1987
  if (!open) return;
2073
1988
  const handler = (e) => {
@@ -2076,15 +1991,47 @@ var Dropdown = ({
2076
1991
  document.addEventListener("mousedown", handler);
2077
1992
  return () => document.removeEventListener("mousedown", handler);
2078
1993
  }, [open]);
1994
+ useEffect(() => {
1995
+ if (!open) return;
1996
+ const first = menuRef.current?.querySelector('[role="menuitem"]:not(:disabled)');
1997
+ first?.focus();
1998
+ }, [open]);
1999
+ const closeAndRefocus = () => {
2000
+ setOpen(false);
2001
+ triggerRef.current?.focus();
2002
+ };
2003
+ const onMenuKeyDown = (e) => {
2004
+ if (e.key === "Escape") {
2005
+ e.preventDefault();
2006
+ closeAndRefocus();
2007
+ return;
2008
+ }
2009
+ const items = Array.from(
2010
+ menuRef.current?.querySelectorAll('[role="menuitem"]:not(:disabled)') ?? []
2011
+ );
2012
+ if (items.length === 0) return;
2013
+ const currentIndex = items.indexOf(document.activeElement);
2014
+ const focusAt = (i) => {
2015
+ e.preventDefault();
2016
+ items[(i + items.length) % items.length]?.focus();
2017
+ };
2018
+ if (e.key === "ArrowDown") focusAt(currentIndex + 1);
2019
+ else if (e.key === "ArrowUp") focusAt(currentIndex - 1);
2020
+ else if (e.key === "Home") focusAt(0);
2021
+ else if (e.key === "End") focusAt(items.length - 1);
2022
+ };
2079
2023
  const selected = options.find((o) => !isDivider(o) && o.value === value);
2080
2024
  const displayLabel = selected?.label ?? placeholder ?? label ?? "Select\u2026";
2081
2025
  return /* @__PURE__ */ jsxs("div", { ref, className: clsx("relative inline-block", className), children: [
2082
2026
  /* @__PURE__ */ jsxs(
2083
2027
  "button",
2084
2028
  {
2029
+ ref: triggerRef,
2085
2030
  type: "button",
2086
2031
  onClick: () => !disabled && setOpen((v) => !v),
2087
2032
  disabled,
2033
+ "aria-haspopup": "menu",
2034
+ "aria-expanded": open,
2088
2035
  className: clsx(
2089
2036
  "flex h-9 items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700",
2090
2037
  open && "ring-brand-500/30 ring-2"
@@ -2109,6 +2056,10 @@ var Dropdown = ({
2109
2056
  /* @__PURE__ */ jsx(
2110
2057
  "div",
2111
2058
  {
2059
+ ref: menuRef,
2060
+ role: "menu",
2061
+ "aria-label": label,
2062
+ onKeyDown: onMenuKeyDown,
2112
2063
  className: clsx(
2113
2064
  "absolute top-full z-50 mt-1 min-w-[180px] overflow-hidden rounded-xl border border-gray-200 bg-white shadow-lg dark:border-gray-700 dark:bg-gray-800",
2114
2065
  align === "right" ? "right-0" : "left-0"
@@ -2130,10 +2081,11 @@ var Dropdown = ({
2130
2081
  "button",
2131
2082
  {
2132
2083
  type: "button",
2084
+ role: "menuitem",
2133
2085
  disabled: opt.disabled,
2134
2086
  onClick: () => {
2135
2087
  onChange?.(opt.value);
2136
- setOpen(false);
2088
+ closeAndRefocus();
2137
2089
  },
2138
2090
  className: clsx(
2139
2091
  "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50",
@@ -2153,6 +2105,51 @@ var Dropdown = ({
2153
2105
  ] })
2154
2106
  ] });
2155
2107
  };
2108
+ var FOCUSABLE_SELECTOR = [
2109
+ "a[href]",
2110
+ "button:not([disabled])",
2111
+ "textarea:not([disabled])",
2112
+ "input:not([disabled])",
2113
+ "select:not([disabled])",
2114
+ '[tabindex]:not([tabindex="-1"])'
2115
+ ].join(",");
2116
+ function useFocusTrap(active) {
2117
+ const ref = useRef(null);
2118
+ useEffect(() => {
2119
+ if (!active) return;
2120
+ const node = ref.current;
2121
+ if (!node) return;
2122
+ const previouslyFocused = document.activeElement;
2123
+ const focusables = () => Array.from(node.querySelectorAll(FOCUSABLE_SELECTOR));
2124
+ (focusables()[0] ?? node).focus();
2125
+ const onKeyDown = (e) => {
2126
+ if (e.key !== "Tab") return;
2127
+ const items = focusables();
2128
+ if (items.length === 0) {
2129
+ e.preventDefault();
2130
+ return;
2131
+ }
2132
+ const first = items[0];
2133
+ const last = items[items.length - 1];
2134
+ if (e.shiftKey && document.activeElement === first) {
2135
+ e.preventDefault();
2136
+ last.focus();
2137
+ } else if (!e.shiftKey && document.activeElement === last) {
2138
+ e.preventDefault();
2139
+ first.focus();
2140
+ }
2141
+ };
2142
+ node.addEventListener("keydown", onKeyDown);
2143
+ return () => {
2144
+ node.removeEventListener("keydown", onKeyDown);
2145
+ previouslyFocused?.focus?.();
2146
+ };
2147
+ }, [active]);
2148
+ return ref;
2149
+ }
2150
+ var DialogTitleContext = createContext(void 0);
2151
+ var DialogTitleProvider = DialogTitleContext.Provider;
2152
+ var useDialogTitleId = () => useContext(DialogTitleContext);
2156
2153
  var SIZE_CLASS5 = {
2157
2154
  sm: "max-w-sm",
2158
2155
  md: "max-w-md",
@@ -2160,7 +2157,9 @@ var SIZE_CLASS5 = {
2160
2157
  xl: "max-w-2xl",
2161
2158
  full: "h-full w-full max-w-none rounded-none"
2162
2159
  };
2163
- var Root8 = ({ open, onClose, size = "md", className, children }) => {
2160
+ var Root8 = ({ open, onClose, size = "md", className, ariaLabel, children }) => {
2161
+ const titleId = useId();
2162
+ const trapRef = useFocusTrap(open);
2164
2163
  useEffect(() => {
2165
2164
  if (!open) return;
2166
2165
  const handler = (e) => {
@@ -2175,12 +2174,16 @@ var Root8 = ({ open, onClose, size = "md", className, children }) => {
2175
2174
  /* @__PURE__ */ jsxs(
2176
2175
  "div",
2177
2176
  {
2177
+ ref: trapRef,
2178
+ tabIndex: -1,
2178
2179
  className: clsx(
2179
2180
  "fixed inset-0 z-50 flex",
2180
2181
  isFull ? "items-stretch justify-stretch" : "items-center justify-center p-4"
2181
2182
  ),
2182
2183
  role: "dialog",
2183
2184
  "aria-modal": "true",
2185
+ "aria-label": ariaLabel,
2186
+ "aria-labelledby": ariaLabel ? void 0 : titleId,
2184
2187
  children: [
2185
2188
  /* @__PURE__ */ jsx(
2186
2189
  "div",
@@ -2199,7 +2202,7 @@ var Root8 = ({ open, onClose, size = "md", className, children }) => {
2199
2202
  SIZE_CLASS5[size],
2200
2203
  className
2201
2204
  ),
2202
- children
2205
+ children: /* @__PURE__ */ jsx(DialogTitleProvider, { value: titleId, children })
2203
2206
  }
2204
2207
  )
2205
2208
  ]
@@ -2208,32 +2211,35 @@ var Root8 = ({ open, onClose, size = "md", className, children }) => {
2208
2211
  document.body
2209
2212
  );
2210
2213
  };
2211
- var Header2 = ({ title, description, onClose, className, children }) => /* @__PURE__ */ jsxs(
2212
- "div",
2213
- {
2214
- className: clsx(
2215
- "flex items-start justify-between gap-4 border-b border-gray-200 px-5 py-4 dark:border-gray-800",
2216
- className
2217
- ),
2218
- children: [
2219
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2220
- title && /* @__PURE__ */ jsx("h2", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: title }),
2221
- description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description }),
2222
- children
2223
- ] }),
2224
- onClose && /* @__PURE__ */ jsx(
2225
- "button",
2226
- {
2227
- type: "button",
2228
- onClick: onClose,
2229
- "aria-label": "Close modal",
2230
- className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-white/5 dark:hover:text-gray-300",
2231
- children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
2232
- }
2233
- )
2234
- ]
2235
- }
2236
- );
2214
+ var Header2 = ({ title, description, onClose, className, children }) => {
2215
+ const titleId = useDialogTitleId();
2216
+ return /* @__PURE__ */ jsxs(
2217
+ "div",
2218
+ {
2219
+ className: clsx(
2220
+ "flex items-start justify-between gap-4 border-b border-gray-200 px-5 py-4 dark:border-gray-800",
2221
+ className
2222
+ ),
2223
+ children: [
2224
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2225
+ title && /* @__PURE__ */ jsx("h2", { id: titleId, className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: title }),
2226
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description }),
2227
+ children
2228
+ ] }),
2229
+ onClose && /* @__PURE__ */ jsx(
2230
+ "button",
2231
+ {
2232
+ type: "button",
2233
+ onClick: onClose,
2234
+ "aria-label": "Close modal",
2235
+ className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-white/5 dark:hover:text-gray-300",
2236
+ children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
2237
+ }
2238
+ )
2239
+ ]
2240
+ }
2241
+ );
2242
+ };
2237
2243
  var Body3 = ({ children, className }) => /* @__PURE__ */ jsx("div", { className: clsx("px-5 py-4", className), children });
2238
2244
  var Footer3 = ({ children, className }) => /* @__PURE__ */ jsx(
2239
2245
  "div",
@@ -2282,7 +2288,7 @@ var Alert = ({
2282
2288
  const handleConfirm = () => onConfirm ? onConfirm() : onClose();
2283
2289
  const handleCancel = () => onCancel ? onCancel() : onClose();
2284
2290
  if (layout === "horizontal") {
2285
- return /* @__PURE__ */ jsxs(Root8, { open, onClose, size: "lg", children: [
2291
+ return /* @__PURE__ */ jsxs(Root8, { open, onClose, size: "lg", ariaLabel: title, children: [
2286
2292
  /* @__PURE__ */ jsxs("div", { className: "bg-white sm:flex sm:items-start sm:p-6 dark:bg-gray-900", children: [
2287
2293
  /* @__PURE__ */ jsx(
2288
2294
  "div",
@@ -2314,7 +2320,7 @@ var Alert = ({
2314
2320
  ] })
2315
2321
  ] });
2316
2322
  }
2317
- return /* @__PURE__ */ jsx(Root8, { open, onClose, size: "sm", children: /* @__PURE__ */ jsxs("div", { className: "p-6 text-center", children: [
2323
+ return /* @__PURE__ */ jsx(Root8, { open, onClose, size: "sm", ariaLabel: title, children: /* @__PURE__ */ jsxs("div", { className: "p-6 text-center", children: [
2318
2324
  /* @__PURE__ */ jsx(
2319
2325
  "div",
2320
2326
  {
@@ -2392,9 +2398,12 @@ var Root9 = ({
2392
2398
  size = "md",
2393
2399
  withBackdrop = true,
2394
2400
  closeOutside = false,
2401
+ ariaLabel,
2395
2402
  className,
2396
2403
  children
2397
2404
  }) => {
2405
+ const titleId = useId();
2406
+ const trapRef = useFocusTrap(open);
2398
2407
  useEffect(() => {
2399
2408
  if (!open) return;
2400
2409
  const handler = (e) => {
@@ -2434,6 +2443,8 @@ var Root9 = ({
2434
2443
  /* @__PURE__ */ jsx(
2435
2444
  "aside",
2436
2445
  {
2446
+ ref: trapRef,
2447
+ tabIndex: -1,
2437
2448
  className: clsx(
2438
2449
  "fixed top-0 bottom-0 z-50 flex flex-col border-gray-200 bg-white shadow-2xl transition-transform duration-300 ease-in-out dark:border-gray-800 dark:bg-gray-900",
2439
2450
  SIDE_CLASS[side],
@@ -2443,7 +2454,9 @@ var Root9 = ({
2443
2454
  ),
2444
2455
  role: "dialog",
2445
2456
  "aria-modal": "true",
2446
- children
2457
+ "aria-label": ariaLabel,
2458
+ "aria-labelledby": ariaLabel ? void 0 : titleId,
2459
+ children: /* @__PURE__ */ jsx(DialogTitleProvider, { value: titleId, children })
2447
2460
  }
2448
2461
  )
2449
2462
  ] }),
@@ -2457,37 +2470,47 @@ var Header3 = ({
2457
2470
  onClose,
2458
2471
  className,
2459
2472
  children
2460
- }) => /* @__PURE__ */ jsxs(
2461
- "div",
2462
- {
2463
- className: clsx(
2464
- "flex shrink-0 items-center justify-between border-b border-gray-200 p-5 dark:border-gray-800",
2465
- className
2466
- ),
2467
- children: [
2468
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
2469
- Icon2 && /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-800", children: /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4 text-gray-500 dark:text-gray-400" }) }),
2470
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2471
- /* @__PURE__ */ jsx("h3", { className: "truncate text-base font-semibold text-gray-900 dark:text-white", children: title }),
2472
- description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 truncate text-sm text-gray-500 dark:text-gray-400", children: description })
2473
+ }) => {
2474
+ const titleId = useDialogTitleId();
2475
+ return /* @__PURE__ */ jsxs(
2476
+ "div",
2477
+ {
2478
+ className: clsx(
2479
+ "flex shrink-0 items-center justify-between border-b border-gray-200 p-5 dark:border-gray-800",
2480
+ className
2481
+ ),
2482
+ children: [
2483
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
2484
+ Icon2 && /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-800", children: /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4 text-gray-500 dark:text-gray-400" }) }),
2485
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2486
+ /* @__PURE__ */ jsx(
2487
+ "h3",
2488
+ {
2489
+ id: titleId,
2490
+ className: "truncate text-base font-semibold text-gray-900 dark:text-white",
2491
+ children: title
2492
+ }
2493
+ ),
2494
+ description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 truncate text-sm text-gray-500 dark:text-gray-400", children: description })
2495
+ ] })
2496
+ ] }),
2497
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2498
+ children,
2499
+ onClose && /* @__PURE__ */ jsx(
2500
+ "button",
2501
+ {
2502
+ type: "button",
2503
+ onClick: onClose,
2504
+ "aria-label": "Close drawer",
2505
+ className: "text-gray-400 transition-colors hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300",
2506
+ children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" })
2507
+ }
2508
+ )
2473
2509
  ] })
2474
- ] }),
2475
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2476
- children,
2477
- onClose && /* @__PURE__ */ jsx(
2478
- "button",
2479
- {
2480
- type: "button",
2481
- onClick: onClose,
2482
- "aria-label": "Close drawer",
2483
- className: "text-gray-400 transition-colors hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300",
2484
- children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" })
2485
- }
2486
- )
2487
- ] })
2488
- ]
2489
- }
2490
- );
2510
+ ]
2511
+ }
2512
+ );
2513
+ };
2491
2514
  var Body4 = ({ children, className }) => /* @__PURE__ */ jsx("div", { className: clsx("flex-1 overflow-y-auto p-5", className), children });
2492
2515
  var Footer4 = ({ children, className }) => /* @__PURE__ */ jsx(
2493
2516
  "div",
@@ -3072,6 +3095,8 @@ var ConfirmationModal = ({
3072
3095
  saveLabel = "Save & go",
3073
3096
  hideSave = false
3074
3097
  }) => {
3098
+ const titleId = useId();
3099
+ const trapRef = useFocusTrap(open);
3075
3100
  useEffect(() => {
3076
3101
  if (!open) return;
3077
3102
  const handler = (e) => {
@@ -3085,24 +3110,19 @@ var ConfirmationModal = ({
3085
3110
  /* @__PURE__ */ jsxs(
3086
3111
  "div",
3087
3112
  {
3113
+ ref: trapRef,
3114
+ tabIndex: -1,
3088
3115
  className: "fixed inset-0 z-50 flex items-center justify-center p-4",
3089
3116
  role: "dialog",
3090
3117
  "aria-modal": "true",
3091
- "aria-labelledby": "cosmos-confirmation-title",
3118
+ "aria-labelledby": titleId,
3092
3119
  children: [
3093
3120
  /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: onStay, "aria-hidden": true }),
3094
3121
  /* @__PURE__ */ jsxs("div", { className: "relative w-full max-w-md overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-2xl dark:border-gray-700 dark:bg-gray-900", children: [
3095
3122
  /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4 p-6", children: [
3096
3123
  /* @__PURE__ */ jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-amber-50 dark:bg-amber-500/10", children: /* @__PURE__ */ jsx(AlertTriangle, { className: "h-5 w-5 text-amber-500" }) }),
3097
3124
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
3098
- /* @__PURE__ */ jsx(
3099
- "h3",
3100
- {
3101
- id: "cosmos-confirmation-title",
3102
- className: "font-semibold text-gray-900 dark:text-white",
3103
- children: title
3104
- }
3105
- ),
3125
+ /* @__PURE__ */ jsx("h3", { id: titleId, className: "font-semibold text-gray-900 dark:text-white", children: title }),
3106
3126
  /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: message })
3107
3127
  ] }),
3108
3128
  /* @__PURE__ */ jsx(
@@ -8111,6 +8131,34 @@ var DataTable = ({
8111
8131
  }
8112
8132
  );
8113
8133
  };
8134
+ var AuthLayout = ({
8135
+ logo: Logo,
8136
+ title,
8137
+ subtitle,
8138
+ brand,
8139
+ children,
8140
+ className
8141
+ }) => {
8142
+ const showBuiltInBrand = brand === void 0 && (Logo || title || subtitle);
8143
+ const renderBrand = brand !== void 0 ? brand : showBuiltInBrand ? /* @__PURE__ */ jsxs("div", { className: "mb-8 flex flex-col items-center gap-2 text-center", children: [
8144
+ Logo && /* @__PURE__ */ jsx("div", { className: "bg-brand-500 flex h-12 w-12 items-center justify-center rounded-xl text-white", children: /* @__PURE__ */ jsx(Logo, { className: "h-6 w-6" }) }),
8145
+ title && /* @__PURE__ */ jsx("h1", { className: "text-xl font-bold text-gray-900 dark:text-white", children: title }),
8146
+ subtitle && /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: subtitle })
8147
+ ] }) : null;
8148
+ return /* @__PURE__ */ jsx(
8149
+ "div",
8150
+ {
8151
+ className: clsx(
8152
+ "flex min-h-screen items-center justify-center bg-gray-50 p-4 dark:bg-gray-950",
8153
+ className
8154
+ ),
8155
+ children: /* @__PURE__ */ jsx("div", { className: "w-full max-w-md", children: /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-gray-200 bg-white p-8 shadow-sm dark:border-gray-800 dark:bg-gray-900", children: [
8156
+ renderBrand,
8157
+ children
8158
+ ] }) })
8159
+ }
8160
+ );
8161
+ };
8114
8162
  var ErrorPage = ({
8115
8163
  code,
8116
8164
  title,
@@ -8134,6 +8182,462 @@ var ErrorPage = ({
8134
8182
  ]
8135
8183
  }
8136
8184
  );
8185
+ var STATUS_LABEL2 = {
8186
+ connected: "Connected",
8187
+ available: "Available",
8188
+ error: "Error",
8189
+ pending: "Pending"
8190
+ };
8191
+ var STATUS_VARIANT = {
8192
+ connected: "success",
8193
+ available: "neutral",
8194
+ error: "danger",
8195
+ pending: "warning"
8196
+ };
8197
+ var IntegrationCard = ({
8198
+ logo,
8199
+ name,
8200
+ description,
8201
+ status,
8202
+ category,
8203
+ actionLabel,
8204
+ actionVariant = "primary",
8205
+ onAction,
8206
+ secondaryLabel,
8207
+ onSecondary,
8208
+ loading = false,
8209
+ className
8210
+ }) => /* @__PURE__ */ jsxs(
8211
+ "div",
8212
+ {
8213
+ className: clsx(
8214
+ "flex h-full flex-col rounded-2xl border border-gray-200 bg-white p-5 transition-shadow hover:shadow-md dark:border-gray-700 dark:bg-gray-800",
8215
+ className
8216
+ ),
8217
+ children: [
8218
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
8219
+ /* @__PURE__ */ jsx("div", { className: "flex h-12 w-12 shrink-0 items-center justify-center overflow-hidden rounded-xl border border-gray-100 bg-white dark:border-gray-700 dark:bg-gray-900 [&_img]:h-full [&_img]:w-full [&_img]:object-contain [&_svg]:h-7 [&_svg]:w-7", children: logo }),
8220
+ status && /* @__PURE__ */ jsx(Badge, { variant: STATUS_VARIANT[status], appearance: "light", children: STATUS_LABEL2[status] })
8221
+ ] }),
8222
+ /* @__PURE__ */ jsxs("div", { className: "mt-4 min-w-0 flex-1", children: [
8223
+ category && /* @__PURE__ */ jsx("p", { className: "font-mono text-[10px] tracking-wide text-gray-400 uppercase dark:text-gray-500", children: category }),
8224
+ /* @__PURE__ */ jsx("h3", { className: "mt-0.5 truncate text-sm font-semibold text-gray-900 dark:text-white", children: name }),
8225
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 line-clamp-2 text-xs text-gray-600 dark:text-gray-400", children: description })
8226
+ ] }),
8227
+ (actionLabel || secondaryLabel) && /* @__PURE__ */ jsxs("div", { className: "mt-4 flex items-center justify-end gap-2", children: [
8228
+ secondaryLabel && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onSecondary, disabled: loading, children: secondaryLabel }),
8229
+ actionLabel && /* @__PURE__ */ jsx(
8230
+ Button,
8231
+ {
8232
+ variant: actionVariant,
8233
+ size: "sm",
8234
+ onClick: onAction,
8235
+ loading,
8236
+ disabled: loading,
8237
+ children: actionLabel
8238
+ }
8239
+ )
8240
+ ] })
8241
+ ]
8242
+ }
8243
+ );
8244
+ var ResetPasswordForm = ({
8245
+ onSubmit,
8246
+ signInHref,
8247
+ signInLabel = "Back to sign in",
8248
+ sent = false,
8249
+ sentEmail,
8250
+ loading = false,
8251
+ error,
8252
+ title = "Reset your password",
8253
+ description = "Enter your email and we\u2019ll send you a link to reset your password.",
8254
+ submitLabel = "Send reset link",
8255
+ onResend,
8256
+ resendLabel = "Resend",
8257
+ className
8258
+ }) => {
8259
+ const [email, setEmail] = useState("");
8260
+ const handleSubmit = (e) => {
8261
+ e.preventDefault();
8262
+ if (loading || email.length === 0) return;
8263
+ void onSubmit(email);
8264
+ };
8265
+ if (sent) {
8266
+ return /* @__PURE__ */ jsxs("div", { className, children: [
8267
+ /* @__PURE__ */ jsx("div", { className: "bg-brand-500/10 text-brand-600 dark:text-brand-400 mx-auto flex h-12 w-12 items-center justify-center rounded-full", children: /* @__PURE__ */ jsx(MailCheck, { className: "h-6 w-6", "aria-hidden": true }) }),
8268
+ /* @__PURE__ */ jsx("h1", { className: "mt-4 text-center text-xl font-semibold text-gray-900 dark:text-white", children: "Check your inbox" }),
8269
+ /* @__PURE__ */ jsxs("p", { className: "mt-2 text-center text-sm text-gray-500 dark:text-gray-400", children: [
8270
+ "We've sent a reset link to",
8271
+ " ",
8272
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-700 dark:text-gray-200", children: sentEmail ?? email }),
8273
+ ". The link expires in 1 hour."
8274
+ ] }),
8275
+ /* @__PURE__ */ jsxs("div", { className: "mt-6 flex flex-col items-stretch gap-2", children: [
8276
+ onResend && /* @__PURE__ */ jsx(Button, { variant: "secondary", loading, disabled: loading, onClick: onResend, children: resendLabel }),
8277
+ signInHref && /* @__PURE__ */ jsxs(Link, { href: signInHref, variant: "subtle", className: "justify-center", children: [
8278
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "h-3.5 w-3.5", "aria-hidden": true }),
8279
+ signInLabel
8280
+ ] })
8281
+ ] })
8282
+ ] });
8283
+ }
8284
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className, children: [
8285
+ /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
8286
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-gray-900 dark:text-white", children: title }),
8287
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description })
8288
+ ] }),
8289
+ error && /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx(AlertBanner, { variant: "error", children: error }) }),
8290
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
8291
+ /* @__PURE__ */ jsx(
8292
+ Input,
8293
+ {
8294
+ label: "Email",
8295
+ type: "email",
8296
+ icon: Mail,
8297
+ autoComplete: "email",
8298
+ required: true,
8299
+ placeholder: "john@example.com",
8300
+ value: email,
8301
+ onChange: (e) => setEmail(e.target.value),
8302
+ disabled: loading
8303
+ }
8304
+ ),
8305
+ /* @__PURE__ */ jsx(
8306
+ Button,
8307
+ {
8308
+ type: "submit",
8309
+ loading,
8310
+ disabled: loading || email.length === 0,
8311
+ className: "w-full",
8312
+ children: submitLabel
8313
+ }
8314
+ )
8315
+ ] }),
8316
+ signInHref && /* @__PURE__ */ jsx("p", { className: "mt-5 text-center text-xs text-[var(--color-text-muted)]", children: /* @__PURE__ */ jsxs(Link, { href: signInHref, variant: "colored", children: [
8317
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "h-3.5 w-3.5", "aria-hidden": true }),
8318
+ signInLabel
8319
+ ] }) })
8320
+ ] });
8321
+ };
8322
+ var SignInForm = ({
8323
+ onSubmit,
8324
+ onForgotPassword,
8325
+ signUpHref,
8326
+ signUpLabel = "Create one",
8327
+ title = "Sign in",
8328
+ description = "Welcome back \u2014 enter your credentials below.",
8329
+ emailLabel = "Email",
8330
+ passwordLabel = "Password",
8331
+ rememberLabel = "Keep me signed in",
8332
+ submitLabel = "Sign in",
8333
+ forgotLabel = "Forgot password?",
8334
+ loading = false,
8335
+ error,
8336
+ extraTop,
8337
+ className
8338
+ }) => {
8339
+ const [email, setEmail] = useState("");
8340
+ const [password, setPassword] = useState("");
8341
+ const [remember, setRemember] = useState(false);
8342
+ const handleSubmit = (e) => {
8343
+ e.preventDefault();
8344
+ if (loading) return;
8345
+ void onSubmit({ email, password, remember });
8346
+ };
8347
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className, children: [
8348
+ /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
8349
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-gray-900 dark:text-white", children: title }),
8350
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description })
8351
+ ] }),
8352
+ extraTop && /* @__PURE__ */ jsx("div", { className: "mb-5", children: extraTop }),
8353
+ error && /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx(AlertBanner, { variant: "error", children: error }) }),
8354
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
8355
+ /* @__PURE__ */ jsx(
8356
+ Input,
8357
+ {
8358
+ label: emailLabel,
8359
+ type: "email",
8360
+ icon: Mail,
8361
+ autoComplete: "email",
8362
+ required: true,
8363
+ placeholder: "john@example.com",
8364
+ value: email,
8365
+ onChange: (e) => setEmail(e.target.value),
8366
+ disabled: loading
8367
+ }
8368
+ ),
8369
+ /* @__PURE__ */ jsx(
8370
+ PasswordInput,
8371
+ {
8372
+ label: passwordLabel,
8373
+ autoComplete: "current-password",
8374
+ required: true,
8375
+ value: password,
8376
+ onChange: (e) => setPassword(e.target.value),
8377
+ disabled: loading
8378
+ }
8379
+ ),
8380
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
8381
+ /* @__PURE__ */ jsx(
8382
+ Checkbox,
8383
+ {
8384
+ label: rememberLabel,
8385
+ checked: remember,
8386
+ onChange: (c) => setRemember(c),
8387
+ disabled: loading
8388
+ }
8389
+ ),
8390
+ onForgotPassword && /* @__PURE__ */ jsx(
8391
+ "button",
8392
+ {
8393
+ type: "button",
8394
+ onClick: onForgotPassword,
8395
+ className: "text-brand-500 hover:text-brand-600 text-xs font-medium transition-colors",
8396
+ children: forgotLabel
8397
+ }
8398
+ )
8399
+ ] }),
8400
+ /* @__PURE__ */ jsx(Button, { type: "submit", loading, disabled: loading, className: "w-full", children: submitLabel })
8401
+ ] }),
8402
+ signUpHref && /* @__PURE__ */ jsxs("p", { className: "mt-5 text-center text-xs text-[var(--color-text-muted)]", children: [
8403
+ "No account?",
8404
+ " ",
8405
+ /* @__PURE__ */ jsx(Link, { href: signUpHref, variant: "colored", children: signUpLabel })
8406
+ ] })
8407
+ ] });
8408
+ };
8409
+ var SignUpForm = ({
8410
+ onSubmit,
8411
+ signInHref,
8412
+ signInLabel = "Sign in",
8413
+ termsHref = "#",
8414
+ privacyHref = "#",
8415
+ showPolicy = true,
8416
+ loading = false,
8417
+ error,
8418
+ title = "Create your account",
8419
+ description = "A few details to get you started.",
8420
+ submitLabel = "Create account",
8421
+ extraTop,
8422
+ className
8423
+ }) => {
8424
+ const [firstName, setFirstName] = useState("");
8425
+ const [lastName, setLastName] = useState("");
8426
+ const [email, setEmail] = useState("");
8427
+ const [password, setPassword] = useState("");
8428
+ const [agreedToTerms, setAgreedToTerms] = useState(false);
8429
+ const rules = useMemo(() => defaultPasswordRules(password), [password]);
8430
+ const allRulesPass = rules.every((r) => r.ok);
8431
+ const canSubmit = firstName.length > 0 && lastName.length > 0 && email.length > 0 && (showPolicy ? allRulesPass : password.length > 0) && agreedToTerms && !loading;
8432
+ const handleSubmit = (e) => {
8433
+ e.preventDefault();
8434
+ if (!canSubmit) return;
8435
+ void onSubmit({ firstName, lastName, email, password, agreedToTerms });
8436
+ };
8437
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className, children: [
8438
+ /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
8439
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-gray-900 dark:text-white", children: title }),
8440
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description })
8441
+ ] }),
8442
+ extraTop && /* @__PURE__ */ jsx("div", { className: "mb-5", children: extraTop }),
8443
+ error && /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx(AlertBanner, { variant: "error", children: error }) }),
8444
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
8445
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
8446
+ /* @__PURE__ */ jsx(
8447
+ Input,
8448
+ {
8449
+ label: "First name",
8450
+ icon: User,
8451
+ autoComplete: "given-name",
8452
+ required: true,
8453
+ placeholder: "John",
8454
+ value: firstName,
8455
+ onChange: (e) => setFirstName(e.target.value),
8456
+ disabled: loading
8457
+ }
8458
+ ),
8459
+ /* @__PURE__ */ jsx(
8460
+ Input,
8461
+ {
8462
+ label: "Last name",
8463
+ autoComplete: "family-name",
8464
+ required: true,
8465
+ placeholder: "Doe",
8466
+ value: lastName,
8467
+ onChange: (e) => setLastName(e.target.value),
8468
+ disabled: loading
8469
+ }
8470
+ )
8471
+ ] }),
8472
+ /* @__PURE__ */ jsx(
8473
+ Input,
8474
+ {
8475
+ label: "Email",
8476
+ type: "email",
8477
+ icon: Mail,
8478
+ autoComplete: "email",
8479
+ required: true,
8480
+ placeholder: "john@example.com",
8481
+ value: email,
8482
+ onChange: (e) => setEmail(e.target.value),
8483
+ disabled: loading
8484
+ }
8485
+ ),
8486
+ /* @__PURE__ */ jsx(
8487
+ PasswordInput,
8488
+ {
8489
+ label: "Password",
8490
+ autoComplete: "new-password",
8491
+ required: true,
8492
+ value: password,
8493
+ onChange: (e) => setPassword(e.target.value),
8494
+ disabled: loading
8495
+ }
8496
+ ),
8497
+ showPolicy && password.length > 0 && /* @__PURE__ */ jsx(PasswordPolicyChecker, { rules }),
8498
+ /* @__PURE__ */ jsx(
8499
+ Checkbox,
8500
+ {
8501
+ label: /* @__PURE__ */ jsxs("span", { children: [
8502
+ "I agree to the",
8503
+ " ",
8504
+ /* @__PURE__ */ jsx(Link, { href: termsHref, variant: "underline", className: "text-current", children: "terms" }),
8505
+ " ",
8506
+ "and",
8507
+ " ",
8508
+ /* @__PURE__ */ jsx(Link, { href: privacyHref, variant: "underline", className: "text-current", children: "privacy policy" }),
8509
+ "."
8510
+ ] }),
8511
+ checked: agreedToTerms,
8512
+ onChange: (c) => setAgreedToTerms(c),
8513
+ disabled: loading
8514
+ }
8515
+ ),
8516
+ /* @__PURE__ */ jsx(Button, { type: "submit", loading, disabled: !canSubmit, className: "w-full", children: submitLabel })
8517
+ ] }),
8518
+ signInHref && /* @__PURE__ */ jsxs("p", { className: "mt-5 text-center text-xs text-[var(--color-text-muted)]", children: [
8519
+ "Already have an account?",
8520
+ " ",
8521
+ /* @__PURE__ */ jsx(Link, { href: signInHref, variant: "colored", children: signInLabel })
8522
+ ] })
8523
+ ] });
8524
+ };
8525
+ var PROVIDER_NAME = {
8526
+ google: "Google",
8527
+ github: "GitHub",
8528
+ x: "X",
8529
+ facebook: "Facebook",
8530
+ apple: "Apple",
8531
+ microsoft: "Microsoft"
8532
+ };
8533
+ var GoogleIcon = () => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", "aria-hidden": true, children: [
8534
+ /* @__PURE__ */ jsx(
8535
+ "path",
8536
+ {
8537
+ fill: "#4285F4",
8538
+ d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
8539
+ }
8540
+ ),
8541
+ /* @__PURE__ */ jsx(
8542
+ "path",
8543
+ {
8544
+ fill: "#34A853",
8545
+ d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84A10.99 10.99 0 0 0 12 23z"
8546
+ }
8547
+ ),
8548
+ /* @__PURE__ */ jsx(
8549
+ "path",
8550
+ {
8551
+ fill: "#FBBC05",
8552
+ d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18a10.99 10.99 0 0 0 0 9.86l3.66-2.84z"
8553
+ }
8554
+ ),
8555
+ /* @__PURE__ */ jsx(
8556
+ "path",
8557
+ {
8558
+ fill: "#EA4335",
8559
+ d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1a10.99 10.99 0 0 0-9.82 6.07l3.66 2.84C6.71 7.31 9.14 5.38 12 5.38z"
8560
+ }
8561
+ )
8562
+ ] });
8563
+ var GithubIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4 fill-current", "aria-hidden": true, children: /* @__PURE__ */ jsx(
8564
+ "path",
8565
+ {
8566
+ fillRule: "evenodd",
8567
+ clipRule: "evenodd",
8568
+ d: "M12 2C6.48 2 2 6.58 2 12.26c0 4.49 2.87 8.3 6.84 9.65.5.09.68-.22.68-.49 0-.24-.01-.88-.01-1.73-2.78.62-3.37-1.36-3.37-1.36-.46-1.18-1.11-1.5-1.11-1.5-.91-.63.07-.62.07-.62 1 .07 1.53 1.05 1.53 1.05.89 1.56 2.34 1.11 2.91.85.09-.66.35-1.11.63-1.36-2.22-.26-4.55-1.13-4.55-5.04 0-1.11.39-2.02 1.03-2.74-.1-.26-.45-1.3.1-2.71 0 0 .84-.27 2.75 1.05A9.4 9.4 0 0 1 12 6.99c.85 0 1.71.12 2.51.34 1.91-1.32 2.75-1.05 2.75-1.05.55 1.41.2 2.45.1 2.71.64.72 1.03 1.63 1.03 2.74 0 3.92-2.34 4.78-4.57 5.03.36.32.68.94.68 1.9 0 1.37-.01 2.48-.01 2.81 0 .27.18.59.69.49A10.04 10.04 0 0 0 22 12.26C22 6.58 17.52 2 12 2z"
8569
+ }
8570
+ ) });
8571
+ var XIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4 fill-current", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231 5.45-6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117l11.966 15.644Z" }) });
8572
+ var FacebookIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", "aria-hidden": true, children: /* @__PURE__ */ jsx(
8573
+ "path",
8574
+ {
8575
+ fill: "#1877F2",
8576
+ d: "M24 12.07C24 5.41 18.63 0 12 0S0 5.41 0 12.07c0 6.02 4.39 11.01 10.13 11.93v-8.44H7.08v-3.49h3.05V9.41c0-3.02 1.79-4.69 4.53-4.69 1.31 0 2.69.23 2.69.23v2.97h-1.51c-1.49 0-1.96.93-1.96 1.89v2.26h3.33l-.53 3.49h-2.8V24C19.61 23.08 24 18.09 24 12.07Z"
8577
+ }
8578
+ ) });
8579
+ var AppleIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4 fill-current", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M17.05 12.04c-.03-2.97 2.43-4.4 2.54-4.47-1.39-2.03-3.55-2.31-4.32-2.34-1.83-.19-3.59 1.08-4.52 1.08-.95 0-2.38-1.06-3.92-1.03-2.01.03-3.88 1.18-4.92 2.97-2.1 3.65-.54 9.05 1.51 12.01 1 1.45 2.18 3.07 3.74 3.01 1.51-.06 2.07-.97 3.89-.97 1.81 0 2.32.97 3.92.94 1.62-.03 2.65-1.46 3.62-2.92 1.15-1.67 1.62-3.32 1.65-3.4-.04-.01-3.16-1.21-3.19-4.81zM14.06 3.74c.81-1 1.36-2.39 1.21-3.78-1.17.05-2.6.79-3.44 1.78-.74.87-1.4 2.28-1.23 3.64 1.31.1 2.65-.66 3.46-1.65z" }) });
8580
+ var MicrosoftIcon = () => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", "aria-hidden": true, children: [
8581
+ /* @__PURE__ */ jsx("path", { fill: "#F25022", d: "M11.4 11.4H1V1h10.4v10.4Z" }),
8582
+ /* @__PURE__ */ jsx("path", { fill: "#7FBA00", d: "M23 11.4H12.6V1H23v10.4Z" }),
8583
+ /* @__PURE__ */ jsx("path", { fill: "#00A4EF", d: "M11.4 23H1V12.6h10.4V23Z" }),
8584
+ /* @__PURE__ */ jsx("path", { fill: "#FFB900", d: "M23 23H12.6V12.6H23V23Z" })
8585
+ ] });
8586
+ var PROVIDER_ICON = {
8587
+ google: GoogleIcon,
8588
+ github: GithubIcon,
8589
+ x: XIcon,
8590
+ facebook: FacebookIcon,
8591
+ apple: AppleIcon,
8592
+ microsoft: MicrosoftIcon
8593
+ };
8594
+ var SocialAuthButtons = ({
8595
+ providers,
8596
+ onProviderClick,
8597
+ loading,
8598
+ divider = true,
8599
+ dividerLabel = "OR continue with",
8600
+ layout = "stacked",
8601
+ labelFor,
8602
+ position = "above",
8603
+ className
8604
+ }) => {
8605
+ if (providers.length === 0) return null;
8606
+ const buttonsList = /* @__PURE__ */ jsx("div", { className: clsx(layout === "grid" ? "grid grid-cols-2 gap-2" : "flex flex-col gap-2"), children: providers.map((provider) => {
8607
+ const Icon2 = PROVIDER_ICON[provider];
8608
+ const isLoading = loading === provider;
8609
+ const isDisabled = loading !== void 0 && loading !== null;
8610
+ const label = labelFor ? labelFor(provider) : `Continue with ${PROVIDER_NAME[provider]}`;
8611
+ return /* @__PURE__ */ jsxs(
8612
+ "button",
8613
+ {
8614
+ type: "button",
8615
+ onClick: () => onProviderClick(provider),
8616
+ disabled: isDisabled,
8617
+ "aria-label": label,
8618
+ className: "flex h-10 items-center justify-center gap-2 rounded-lg border border-gray-200 bg-white text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700",
8619
+ children: [
8620
+ isLoading ? /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(Icon2, {}),
8621
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: label })
8622
+ ]
8623
+ },
8624
+ provider
8625
+ );
8626
+ }) });
8627
+ if (!divider) return /* @__PURE__ */ jsx("div", { className, children: buttonsList });
8628
+ const dividerNode = /* @__PURE__ */ jsxs("div", { className: "my-4 flex items-center gap-3", children: [
8629
+ /* @__PURE__ */ jsx("div", { className: "h-px flex-1 bg-gray-200 dark:bg-gray-700" }),
8630
+ /* @__PURE__ */ jsx("span", { className: "text-xs tracking-wide text-gray-400 uppercase dark:text-gray-500", children: dividerLabel }),
8631
+ /* @__PURE__ */ jsx("div", { className: "h-px flex-1 bg-gray-200 dark:bg-gray-700" })
8632
+ ] });
8633
+ return /* @__PURE__ */ jsx("div", { className, children: position === "above" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
8634
+ buttonsList,
8635
+ dividerNode
8636
+ ] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
8637
+ dividerNode,
8638
+ buttonsList
8639
+ ] }) });
8640
+ };
8137
8641
  var StickyScrollNav = ({
8138
8642
  sections,
8139
8643
  onNavigate,
@@ -8169,6 +8673,80 @@ var StickyScrollNav = ({
8169
8673
  }
8170
8674
  );
8171
8675
  };
8676
+ var TwoStepVerificationForm = ({
8677
+ onSubmit,
8678
+ onResend,
8679
+ sentTo,
8680
+ length = 6,
8681
+ loading = false,
8682
+ error,
8683
+ autoSubmit = true,
8684
+ cancelHref,
8685
+ cancelLabel = "Back to sign in",
8686
+ title = "Two-step verification",
8687
+ submitLabel = "Verify my account",
8688
+ resendLabel = "Resend code",
8689
+ className
8690
+ }) => {
8691
+ const [code, setCode] = useState("");
8692
+ const description = sentTo ? `Enter the ${length}-digit code we sent to ${sentTo}.` : `Enter the ${length}-digit verification code from your authenticator app.`;
8693
+ const handleSubmit = (e) => {
8694
+ e.preventDefault();
8695
+ if (loading || code.length !== length) return;
8696
+ void onSubmit(code);
8697
+ };
8698
+ const handleComplete = (value) => {
8699
+ if (autoSubmit && !loading) void onSubmit(value);
8700
+ };
8701
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className, children: [
8702
+ /* @__PURE__ */ jsx("div", { className: "bg-brand-500/10 text-brand-600 dark:text-brand-400 mx-auto flex h-12 w-12 items-center justify-center rounded-full", children: /* @__PURE__ */ jsx(ShieldCheck, { className: "h-6 w-6", "aria-hidden": true }) }),
8703
+ /* @__PURE__ */ jsx("h1", { className: "mt-4 text-center text-xl font-semibold text-gray-900 dark:text-white", children: title }),
8704
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-center text-sm text-gray-500 dark:text-gray-400", children: description }),
8705
+ error && /* @__PURE__ */ jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsx(AlertBanner, { variant: "error", children: error }) }),
8706
+ /* @__PURE__ */ jsx("div", { className: "mt-6 flex justify-center", children: /* @__PURE__ */ jsx(
8707
+ OtpInput,
8708
+ {
8709
+ length,
8710
+ value: code,
8711
+ onChange: setCode,
8712
+ onComplete: handleComplete,
8713
+ disabled: loading,
8714
+ error: !!error,
8715
+ autoFocus: true
8716
+ }
8717
+ ) }),
8718
+ /* @__PURE__ */ jsxs("div", { className: "mt-6 space-y-2", children: [
8719
+ /* @__PURE__ */ jsx(
8720
+ Button,
8721
+ {
8722
+ type: "submit",
8723
+ loading,
8724
+ disabled: loading || code.length !== length,
8725
+ className: "w-full",
8726
+ children: submitLabel
8727
+ }
8728
+ ),
8729
+ onResend && /* @__PURE__ */ jsxs("p", { className: "text-center text-xs text-[var(--color-text-muted)]", children: [
8730
+ "Didn't get a code?",
8731
+ " ",
8732
+ /* @__PURE__ */ jsx(
8733
+ "button",
8734
+ {
8735
+ type: "button",
8736
+ onClick: onResend,
8737
+ disabled: loading,
8738
+ className: "text-brand-500 hover:text-brand-600 font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
8739
+ children: resendLabel
8740
+ }
8741
+ )
8742
+ ] }),
8743
+ cancelHref && /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxs(Link, { href: cancelHref, variant: "subtle", children: [
8744
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "h-3.5 w-3.5", "aria-hidden": true }),
8745
+ cancelLabel
8746
+ ] }) })
8747
+ ] })
8748
+ ] });
8749
+ };
8172
8750
  var ColorSwatch = ({
8173
8751
  hex,
8174
8752
  label,
@@ -8541,6 +9119,6 @@ var Figure = ({
8541
9119
  caption && /* @__PURE__ */ jsx("figcaption", { className: "mt-2 text-center text-xs text-gray-500 italic dark:text-gray-400", children: caption })
8542
9120
  ] });
8543
9121
 
8544
- export { AccentPicker, Accordion2 as Accordion, ActionPanel, ActiveFiltersBar, ActivityFeed, AlertBanner, AnnouncementBar, Avatar, AvatarUploader, BackToTopFab, Backdrop, Badge, Blockquote, Breadcrumb, Button, ButtonGroup, Calendar, Card2 as Card, Carousel, CarouselRoot, Checkbox, CheckboxGroup, ClickableRow, Clipboard, CodeBlock, ColBox, ColorSwatch, ColumnFilterDropdown, ColumnHeader, Combobox, CommandPalette, ConfirmationModal, ContentNarrow, ContentStackedList, CookieBanner, DataTable, DatePicker, DescriptionList, Divider, Drawer, Dropdown, Dropzone, EmptyState, ErrorPage, ErrorState, Figure, FileInput, FilterPills, FormFooter, FormRow, GridList, HealthBadge, HealthDot, HelpOverlay, IconBox, ImageGrid, Input, Kbd2 as Kbd, KpiCard, Link, List2 as List, LoadingState, MediaObject, MiniCalendar, Modal, NarrowStackedList, Navbar, NotificationCard, NotificationsPanel, NumberInput, OptionCard, OptionPicker, OtpInput, PageActionButton, PageActionIconButton, PageBreadcrumb, PageCard, PageHeader, Pagination, PaletteCard, PalettePicker, PasswordInput, PasswordPolicyChecker, Popover, ProgressBar, REFRESH_OPTIONS, Radio, RadioGroup, RefreshButton, Ribbon, RowActionButton, STATUS_COLOR, STATUS_PILL, SearchInput, SectionCard, SectionLabel, SegmentedControl, Select, SelectInput, Shell, Sidebar, SimpleRow, Sk, SkeletonList, SkeletonTable, SkeletonText, Spinner, StackedList, StackedListInCard, StatefulSaveButton, StatusBadge, StatusRow, Stepper, StepperInput, StepperRoot, StickyScrollNav, Tabs, Textarea, ThemeToggle, ThemeToggleTri, TimePicker, Timeline, Toaster, Toggle, Tooltip, TooltipHelp, Topbar, UnsavedIndicator, UserMenu, VerticalNavigation, VideoEmbed, ZoomBar, defaultPasswordRules, placeholderAvatar, placeholderCover, portalDocsParams, useAutoRefresh };
9122
+ export { AccentPicker, Accordion2 as Accordion, ActionPanel, ActiveFiltersBar, ActivityFeed, AlertBanner, AnnouncementBar, AuthLayout, Avatar, AvatarUploader, BackToTopFab, Backdrop, Badge, Blockquote, Breadcrumb, Button, ButtonGroup, Calendar, Card2 as Card, Carousel, CarouselRoot, Checkbox, CheckboxGroup, ClickableRow, Clipboard, CodeBlock, ColBox, ColorSwatch, ColumnFilterDropdown, ColumnHeader, Combobox, CommandPalette, ConfirmationModal, ContentNarrow, ContentStackedList, CookieBanner, DataTable, DatePicker, DescriptionList, Divider, Drawer, Dropdown, Dropzone, EmptyState, ErrorPage, ErrorState, Figure, FileInput, FilterPills, FormFooter, FormRow, GridList, HealthBadge, HealthDot, HelpOverlay, IconBox, ImageGrid, Input, IntegrationCard, Kbd2 as Kbd, KpiCard, Link, List2 as List, LoadingState, MediaObject, MiniCalendar, Modal, NarrowStackedList, Navbar, NotificationCard, NotificationsPanel, NumberInput, OptionCard, OptionPicker, OtpInput, PageActionButton, PageActionIconButton, PageBreadcrumb, PageCard, PageHeader, Pagination, PaletteCard, PalettePicker, PasswordInput, PasswordPolicyChecker, Popover, ProgressBar, REFRESH_OPTIONS, Radio, RadioGroup, RefreshButton, ResetPasswordForm, Ribbon, RowActionButton, STATUS_COLOR, STATUS_PILL, SearchInput, SectionCard, SectionLabel, SegmentedControl, Select, SelectInput, Shell, Sidebar, SignInForm, SignUpForm, SimpleRow, Sk, SkeletonList, SkeletonTable, SkeletonText, SocialAuthButtons, Spinner, StackedList, StackedListInCard, StatefulSaveButton, StatusBadge, StatusRow, Stepper, StepperInput, StepperRoot, StickyScrollNav, Tabs, Textarea, ThemeToggle, ThemeToggleTri, TimePicker, Timeline, Toaster, Toggle, Tooltip, TooltipHelp, Topbar, TwoStepVerificationForm, UnsavedIndicator, UserMenu, VerticalNavigation, VideoEmbed, ZoomBar, defaultPasswordRules, useAutoRefresh };
8545
9123
  //# sourceMappingURL=index.js.map
8546
9124
  //# sourceMappingURL=index.js.map