@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.cjs CHANGED
@@ -37,93 +37,6 @@ var Autoplay__default = /*#__PURE__*/_interopDefault(Autoplay);
37
37
  var useEmblaCarousel__default = /*#__PURE__*/_interopDefault(useEmblaCarousel);
38
38
  var RadixAccordion__namespace = /*#__PURE__*/_interopNamespace(RadixAccordion);
39
39
 
40
- // src/storybook-avatars.ts
41
- var PALETTE = [
42
- ["#6366f1", "#ffffff"],
43
- // indigo
44
- ["#8b5cf6", "#ffffff"],
45
- // violet
46
- ["#0ea5e9", "#ffffff"],
47
- // sky
48
- ["#10b981", "#ffffff"],
49
- // emerald
50
- ["#f59e0b", "#1f2937"],
51
- // amber (dark text on warm bg)
52
- ["#f43f5e", "#ffffff"],
53
- // rose
54
- ["#14b8a6", "#ffffff"],
55
- // teal
56
- ["#ec4899", "#ffffff"],
57
- // pink
58
- ["#64748b", "#ffffff"],
59
- // slate
60
- ["#a855f7", "#ffffff"]
61
- // purple
62
- ];
63
- var hashSeed = (seed) => {
64
- let h = 5381;
65
- for (let i = 0; i < seed.length; i += 1) {
66
- h = (h << 5) + h + seed.charCodeAt(i) | 0;
67
- }
68
- return Math.abs(h);
69
- };
70
- var extractInitials = (seed) => {
71
- const cleaned = seed.replace(/[^\p{L}\p{N}\s'.-]/gu, " ").trim();
72
- if (!cleaned) return "?";
73
- const parts = cleaned.split(/[\s.'-]+/).filter(Boolean);
74
- if (parts.length >= 2) {
75
- return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
76
- }
77
- return cleaned.slice(0, 2).toUpperCase();
78
- };
79
- var buildSvg = (initials, bg, fg, size) => {
80
- const fontSize = initials.length === 1 ? 56 : 42;
81
- 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>`;
82
- };
83
- var placeholderAvatar = (seed, size = 64, opts = {}) => {
84
- const initials = extractInitials(seed);
85
- const [defaultBg, defaultFg] = PALETTE[hashSeed(seed) % PALETTE.length];
86
- const bg = opts.bg ?? defaultBg;
87
- const fg = opts.fg ?? defaultFg;
88
- const svg = buildSvg(initials, bg, fg, size);
89
- return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
90
- };
91
- var buildCoverSvg = (seed, from, to, width, height) => {
92
- const h = hashSeed(seed);
93
- const angle = h % 180;
94
- const cx1 = h % 60 + 20;
95
- const cy1 = (h >> 3) % 60 + 20;
96
- const r1 = (h >> 5) % 35 + 25;
97
- const cx2 = (h >> 7) % 60 + 20;
98
- const cy2 = (h >> 9) % 60 + 20;
99
- const r2 = (h >> 11) % 25 + 15;
100
- const gradientId = `g-${(h % 1e5).toString(36)}`;
101
- 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>`;
102
- };
103
- var placeholderCover = (seed, width = 1600, height = 700, opts = {}) => {
104
- const h = hashSeed(seed);
105
- const [from] = PALETTE[h % PALETTE.length];
106
- const [to] = PALETTE[(h + 3) % PALETTE.length];
107
- const svg = buildCoverSvg(seed, opts.from ?? from, opts.to ?? to, width, height);
108
- return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
109
- };
110
-
111
- // src/storybook-helpers.ts
112
- var buildParams = (height) => ({
113
- layout: "fullscreen",
114
- docs: {
115
- story: {
116
- inline: false,
117
- iframeHeight: `${height}px`
118
- }
119
- }
120
- });
121
- var fn = ((height = 480) => buildParams(height));
122
- fn.sm = () => buildParams(320);
123
- fn.md = () => buildParams(480);
124
- fn.lg = () => buildParams(640);
125
- fn.full = () => buildParams(800);
126
- var portalDocsParams = fn;
127
40
  var Root = ({
128
41
  inset,
129
42
  align = "center",
@@ -2093,6 +2006,8 @@ var Dropdown = ({
2093
2006
  }) => {
2094
2007
  const [open, setOpen] = react.useState(false);
2095
2008
  const ref = react.useRef(null);
2009
+ const triggerRef = react.useRef(null);
2010
+ const menuRef = react.useRef(null);
2096
2011
  react.useEffect(() => {
2097
2012
  if (!open) return;
2098
2013
  const handler = (e) => {
@@ -2101,15 +2016,47 @@ var Dropdown = ({
2101
2016
  document.addEventListener("mousedown", handler);
2102
2017
  return () => document.removeEventListener("mousedown", handler);
2103
2018
  }, [open]);
2019
+ react.useEffect(() => {
2020
+ if (!open) return;
2021
+ const first = menuRef.current?.querySelector('[role="menuitem"]:not(:disabled)');
2022
+ first?.focus();
2023
+ }, [open]);
2024
+ const closeAndRefocus = () => {
2025
+ setOpen(false);
2026
+ triggerRef.current?.focus();
2027
+ };
2028
+ const onMenuKeyDown = (e) => {
2029
+ if (e.key === "Escape") {
2030
+ e.preventDefault();
2031
+ closeAndRefocus();
2032
+ return;
2033
+ }
2034
+ const items = Array.from(
2035
+ menuRef.current?.querySelectorAll('[role="menuitem"]:not(:disabled)') ?? []
2036
+ );
2037
+ if (items.length === 0) return;
2038
+ const currentIndex = items.indexOf(document.activeElement);
2039
+ const focusAt = (i) => {
2040
+ e.preventDefault();
2041
+ items[(i + items.length) % items.length]?.focus();
2042
+ };
2043
+ if (e.key === "ArrowDown") focusAt(currentIndex + 1);
2044
+ else if (e.key === "ArrowUp") focusAt(currentIndex - 1);
2045
+ else if (e.key === "Home") focusAt(0);
2046
+ else if (e.key === "End") focusAt(items.length - 1);
2047
+ };
2104
2048
  const selected = options.find((o) => !isDivider(o) && o.value === value);
2105
2049
  const displayLabel = selected?.label ?? placeholder ?? label ?? "Select\u2026";
2106
2050
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: clsx.clsx("relative inline-block", className), children: [
2107
2051
  /* @__PURE__ */ jsxRuntime.jsxs(
2108
2052
  "button",
2109
2053
  {
2054
+ ref: triggerRef,
2110
2055
  type: "button",
2111
2056
  onClick: () => !disabled && setOpen((v) => !v),
2112
2057
  disabled,
2058
+ "aria-haspopup": "menu",
2059
+ "aria-expanded": open,
2113
2060
  className: clsx.clsx(
2114
2061
  "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",
2115
2062
  open && "ring-brand-500/30 ring-2"
@@ -2134,6 +2081,10 @@ var Dropdown = ({
2134
2081
  /* @__PURE__ */ jsxRuntime.jsx(
2135
2082
  "div",
2136
2083
  {
2084
+ ref: menuRef,
2085
+ role: "menu",
2086
+ "aria-label": label,
2087
+ onKeyDown: onMenuKeyDown,
2137
2088
  className: clsx.clsx(
2138
2089
  "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",
2139
2090
  align === "right" ? "right-0" : "left-0"
@@ -2155,10 +2106,11 @@ var Dropdown = ({
2155
2106
  "button",
2156
2107
  {
2157
2108
  type: "button",
2109
+ role: "menuitem",
2158
2110
  disabled: opt.disabled,
2159
2111
  onClick: () => {
2160
2112
  onChange?.(opt.value);
2161
- setOpen(false);
2113
+ closeAndRefocus();
2162
2114
  },
2163
2115
  className: clsx.clsx(
2164
2116
  "flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50",
@@ -2178,6 +2130,51 @@ var Dropdown = ({
2178
2130
  ] })
2179
2131
  ] });
2180
2132
  };
2133
+ var FOCUSABLE_SELECTOR = [
2134
+ "a[href]",
2135
+ "button:not([disabled])",
2136
+ "textarea:not([disabled])",
2137
+ "input:not([disabled])",
2138
+ "select:not([disabled])",
2139
+ '[tabindex]:not([tabindex="-1"])'
2140
+ ].join(",");
2141
+ function useFocusTrap(active) {
2142
+ const ref = react.useRef(null);
2143
+ react.useEffect(() => {
2144
+ if (!active) return;
2145
+ const node = ref.current;
2146
+ if (!node) return;
2147
+ const previouslyFocused = document.activeElement;
2148
+ const focusables = () => Array.from(node.querySelectorAll(FOCUSABLE_SELECTOR));
2149
+ (focusables()[0] ?? node).focus();
2150
+ const onKeyDown = (e) => {
2151
+ if (e.key !== "Tab") return;
2152
+ const items = focusables();
2153
+ if (items.length === 0) {
2154
+ e.preventDefault();
2155
+ return;
2156
+ }
2157
+ const first = items[0];
2158
+ const last = items[items.length - 1];
2159
+ if (e.shiftKey && document.activeElement === first) {
2160
+ e.preventDefault();
2161
+ last.focus();
2162
+ } else if (!e.shiftKey && document.activeElement === last) {
2163
+ e.preventDefault();
2164
+ first.focus();
2165
+ }
2166
+ };
2167
+ node.addEventListener("keydown", onKeyDown);
2168
+ return () => {
2169
+ node.removeEventListener("keydown", onKeyDown);
2170
+ previouslyFocused?.focus?.();
2171
+ };
2172
+ }, [active]);
2173
+ return ref;
2174
+ }
2175
+ var DialogTitleContext = react.createContext(void 0);
2176
+ var DialogTitleProvider = DialogTitleContext.Provider;
2177
+ var useDialogTitleId = () => react.useContext(DialogTitleContext);
2181
2178
  var SIZE_CLASS5 = {
2182
2179
  sm: "max-w-sm",
2183
2180
  md: "max-w-md",
@@ -2185,7 +2182,9 @@ var SIZE_CLASS5 = {
2185
2182
  xl: "max-w-2xl",
2186
2183
  full: "h-full w-full max-w-none rounded-none"
2187
2184
  };
2188
- var Root8 = ({ open, onClose, size = "md", className, children }) => {
2185
+ var Root8 = ({ open, onClose, size = "md", className, ariaLabel, children }) => {
2186
+ const titleId = react.useId();
2187
+ const trapRef = useFocusTrap(open);
2189
2188
  react.useEffect(() => {
2190
2189
  if (!open) return;
2191
2190
  const handler = (e) => {
@@ -2200,12 +2199,16 @@ var Root8 = ({ open, onClose, size = "md", className, children }) => {
2200
2199
  /* @__PURE__ */ jsxRuntime.jsxs(
2201
2200
  "div",
2202
2201
  {
2202
+ ref: trapRef,
2203
+ tabIndex: -1,
2203
2204
  className: clsx.clsx(
2204
2205
  "fixed inset-0 z-50 flex",
2205
2206
  isFull ? "items-stretch justify-stretch" : "items-center justify-center p-4"
2206
2207
  ),
2207
2208
  role: "dialog",
2208
2209
  "aria-modal": "true",
2210
+ "aria-label": ariaLabel,
2211
+ "aria-labelledby": ariaLabel ? void 0 : titleId,
2209
2212
  children: [
2210
2213
  /* @__PURE__ */ jsxRuntime.jsx(
2211
2214
  "div",
@@ -2224,7 +2227,7 @@ var Root8 = ({ open, onClose, size = "md", className, children }) => {
2224
2227
  SIZE_CLASS5[size],
2225
2228
  className
2226
2229
  ),
2227
- children
2230
+ children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitleProvider, { value: titleId, children })
2228
2231
  }
2229
2232
  )
2230
2233
  ]
@@ -2233,32 +2236,35 @@ var Root8 = ({ open, onClose, size = "md", className, children }) => {
2233
2236
  document.body
2234
2237
  );
2235
2238
  };
2236
- var Header2 = ({ title, description, onClose, className, children }) => /* @__PURE__ */ jsxRuntime.jsxs(
2237
- "div",
2238
- {
2239
- className: clsx.clsx(
2240
- "flex items-start justify-between gap-4 border-b border-gray-200 px-5 py-4 dark:border-gray-800",
2241
- className
2242
- ),
2243
- children: [
2244
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
2245
- title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: title }),
2246
- description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description }),
2247
- children
2248
- ] }),
2249
- onClose && /* @__PURE__ */ jsxRuntime.jsx(
2250
- "button",
2251
- {
2252
- type: "button",
2253
- onClick: onClose,
2254
- "aria-label": "Close modal",
2255
- 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",
2256
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" })
2257
- }
2258
- )
2259
- ]
2260
- }
2261
- );
2239
+ var Header2 = ({ title, description, onClose, className, children }) => {
2240
+ const titleId = useDialogTitleId();
2241
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2242
+ "div",
2243
+ {
2244
+ className: clsx.clsx(
2245
+ "flex items-start justify-between gap-4 border-b border-gray-200 px-5 py-4 dark:border-gray-800",
2246
+ className
2247
+ ),
2248
+ children: [
2249
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
2250
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { id: titleId, className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: title }),
2251
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description }),
2252
+ children
2253
+ ] }),
2254
+ onClose && /* @__PURE__ */ jsxRuntime.jsx(
2255
+ "button",
2256
+ {
2257
+ type: "button",
2258
+ onClick: onClose,
2259
+ "aria-label": "Close modal",
2260
+ 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",
2261
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" })
2262
+ }
2263
+ )
2264
+ ]
2265
+ }
2266
+ );
2267
+ };
2262
2268
  var Body3 = ({ children, className }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx.clsx("px-5 py-4", className), children });
2263
2269
  var Footer3 = ({ children, className }) => /* @__PURE__ */ jsxRuntime.jsx(
2264
2270
  "div",
@@ -2307,7 +2313,7 @@ var Alert = ({
2307
2313
  const handleConfirm = () => onConfirm ? onConfirm() : onClose();
2308
2314
  const handleCancel = () => onCancel ? onCancel() : onClose();
2309
2315
  if (layout === "horizontal") {
2310
- return /* @__PURE__ */ jsxRuntime.jsxs(Root8, { open, onClose, size: "lg", children: [
2316
+ return /* @__PURE__ */ jsxRuntime.jsxs(Root8, { open, onClose, size: "lg", ariaLabel: title, children: [
2311
2317
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white sm:flex sm:items-start sm:p-6 dark:bg-gray-900", children: [
2312
2318
  /* @__PURE__ */ jsxRuntime.jsx(
2313
2319
  "div",
@@ -2339,7 +2345,7 @@ var Alert = ({
2339
2345
  ] })
2340
2346
  ] });
2341
2347
  }
2342
- return /* @__PURE__ */ jsxRuntime.jsx(Root8, { open, onClose, size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 text-center", children: [
2348
+ return /* @__PURE__ */ jsxRuntime.jsx(Root8, { open, onClose, size: "sm", ariaLabel: title, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 text-center", children: [
2343
2349
  /* @__PURE__ */ jsxRuntime.jsx(
2344
2350
  "div",
2345
2351
  {
@@ -2417,9 +2423,12 @@ var Root9 = ({
2417
2423
  size = "md",
2418
2424
  withBackdrop = true,
2419
2425
  closeOutside = false,
2426
+ ariaLabel,
2420
2427
  className,
2421
2428
  children
2422
2429
  }) => {
2430
+ const titleId = react.useId();
2431
+ const trapRef = useFocusTrap(open);
2423
2432
  react.useEffect(() => {
2424
2433
  if (!open) return;
2425
2434
  const handler = (e) => {
@@ -2459,6 +2468,8 @@ var Root9 = ({
2459
2468
  /* @__PURE__ */ jsxRuntime.jsx(
2460
2469
  "aside",
2461
2470
  {
2471
+ ref: trapRef,
2472
+ tabIndex: -1,
2462
2473
  className: clsx.clsx(
2463
2474
  "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",
2464
2475
  SIDE_CLASS[side],
@@ -2468,7 +2479,9 @@ var Root9 = ({
2468
2479
  ),
2469
2480
  role: "dialog",
2470
2481
  "aria-modal": "true",
2471
- children
2482
+ "aria-label": ariaLabel,
2483
+ "aria-labelledby": ariaLabel ? void 0 : titleId,
2484
+ children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitleProvider, { value: titleId, children })
2472
2485
  }
2473
2486
  )
2474
2487
  ] }),
@@ -2482,37 +2495,47 @@ var Header3 = ({
2482
2495
  onClose,
2483
2496
  className,
2484
2497
  children
2485
- }) => /* @__PURE__ */ jsxRuntime.jsxs(
2486
- "div",
2487
- {
2488
- className: clsx.clsx(
2489
- "flex shrink-0 items-center justify-between border-b border-gray-200 p-5 dark:border-gray-800",
2490
- className
2491
- ),
2492
- children: [
2493
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
2494
- Icon2 && /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(Icon2, { className: "h-4 w-4 text-gray-500 dark:text-gray-400" }) }),
2495
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
2496
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "truncate text-base font-semibold text-gray-900 dark:text-white", children: title }),
2497
- description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 truncate text-sm text-gray-500 dark:text-gray-400", children: description })
2498
+ }) => {
2499
+ const titleId = useDialogTitleId();
2500
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2501
+ "div",
2502
+ {
2503
+ className: clsx.clsx(
2504
+ "flex shrink-0 items-center justify-between border-b border-gray-200 p-5 dark:border-gray-800",
2505
+ className
2506
+ ),
2507
+ children: [
2508
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
2509
+ Icon2 && /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(Icon2, { className: "h-4 w-4 text-gray-500 dark:text-gray-400" }) }),
2510
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
2511
+ /* @__PURE__ */ jsxRuntime.jsx(
2512
+ "h3",
2513
+ {
2514
+ id: titleId,
2515
+ className: "truncate text-base font-semibold text-gray-900 dark:text-white",
2516
+ children: title
2517
+ }
2518
+ ),
2519
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 truncate text-sm text-gray-500 dark:text-gray-400", children: description })
2520
+ ] })
2521
+ ] }),
2522
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2523
+ children,
2524
+ onClose && /* @__PURE__ */ jsxRuntime.jsx(
2525
+ "button",
2526
+ {
2527
+ type: "button",
2528
+ onClick: onClose,
2529
+ "aria-label": "Close drawer",
2530
+ className: "text-gray-400 transition-colors hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300",
2531
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" })
2532
+ }
2533
+ )
2498
2534
  ] })
2499
- ] }),
2500
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2501
- children,
2502
- onClose && /* @__PURE__ */ jsxRuntime.jsx(
2503
- "button",
2504
- {
2505
- type: "button",
2506
- onClick: onClose,
2507
- "aria-label": "Close drawer",
2508
- className: "text-gray-400 transition-colors hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300",
2509
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" })
2510
- }
2511
- )
2512
- ] })
2513
- ]
2514
- }
2515
- );
2535
+ ]
2536
+ }
2537
+ );
2538
+ };
2516
2539
  var Body4 = ({ children, className }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx.clsx("flex-1 overflow-y-auto p-5", className), children });
2517
2540
  var Footer4 = ({ children, className }) => /* @__PURE__ */ jsxRuntime.jsx(
2518
2541
  "div",
@@ -3097,6 +3120,8 @@ var ConfirmationModal = ({
3097
3120
  saveLabel = "Save & go",
3098
3121
  hideSave = false
3099
3122
  }) => {
3123
+ const titleId = react.useId();
3124
+ const trapRef = useFocusTrap(open);
3100
3125
  react.useEffect(() => {
3101
3126
  if (!open) return;
3102
3127
  const handler = (e) => {
@@ -3110,24 +3135,19 @@ var ConfirmationModal = ({
3110
3135
  /* @__PURE__ */ jsxRuntime.jsxs(
3111
3136
  "div",
3112
3137
  {
3138
+ ref: trapRef,
3139
+ tabIndex: -1,
3113
3140
  className: "fixed inset-0 z-50 flex items-center justify-center p-4",
3114
3141
  role: "dialog",
3115
3142
  "aria-modal": "true",
3116
- "aria-labelledby": "cosmos-confirmation-title",
3143
+ "aria-labelledby": titleId,
3117
3144
  children: [
3118
3145
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: onStay, "aria-hidden": true }),
3119
3146
  /* @__PURE__ */ jsxRuntime.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: [
3120
3147
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-4 p-6", children: [
3121
3148
  /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-5 w-5 text-amber-500" }) }),
3122
3149
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
3123
- /* @__PURE__ */ jsxRuntime.jsx(
3124
- "h3",
3125
- {
3126
- id: "cosmos-confirmation-title",
3127
- className: "font-semibold text-gray-900 dark:text-white",
3128
- children: title
3129
- }
3130
- ),
3150
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { id: titleId, className: "font-semibold text-gray-900 dark:text-white", children: title }),
3131
3151
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: message })
3132
3152
  ] }),
3133
3153
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -8136,6 +8156,34 @@ var DataTable = ({
8136
8156
  }
8137
8157
  );
8138
8158
  };
8159
+ var AuthLayout = ({
8160
+ logo: Logo,
8161
+ title,
8162
+ subtitle,
8163
+ brand,
8164
+ children,
8165
+ className
8166
+ }) => {
8167
+ const showBuiltInBrand = brand === void 0 && (Logo || title || subtitle);
8168
+ const renderBrand = brand !== void 0 ? brand : showBuiltInBrand ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-8 flex flex-col items-center gap-2 text-center", children: [
8169
+ Logo && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-brand-500 flex h-12 w-12 items-center justify-center rounded-xl text-white", children: /* @__PURE__ */ jsxRuntime.jsx(Logo, { className: "h-6 w-6" }) }),
8170
+ title && /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-bold text-gray-900 dark:text-white", children: title }),
8171
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: subtitle })
8172
+ ] }) : null;
8173
+ return /* @__PURE__ */ jsxRuntime.jsx(
8174
+ "div",
8175
+ {
8176
+ className: clsx.clsx(
8177
+ "flex min-h-screen items-center justify-center bg-gray-50 p-4 dark:bg-gray-950",
8178
+ className
8179
+ ),
8180
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full max-w-md", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl border border-gray-200 bg-white p-8 shadow-sm dark:border-gray-800 dark:bg-gray-900", children: [
8181
+ renderBrand,
8182
+ children
8183
+ ] }) })
8184
+ }
8185
+ );
8186
+ };
8139
8187
  var ErrorPage = ({
8140
8188
  code,
8141
8189
  title,
@@ -8159,6 +8207,462 @@ var ErrorPage = ({
8159
8207
  ]
8160
8208
  }
8161
8209
  );
8210
+ var STATUS_LABEL2 = {
8211
+ connected: "Connected",
8212
+ available: "Available",
8213
+ error: "Error",
8214
+ pending: "Pending"
8215
+ };
8216
+ var STATUS_VARIANT = {
8217
+ connected: "success",
8218
+ available: "neutral",
8219
+ error: "danger",
8220
+ pending: "warning"
8221
+ };
8222
+ var IntegrationCard = ({
8223
+ logo,
8224
+ name,
8225
+ description,
8226
+ status,
8227
+ category,
8228
+ actionLabel,
8229
+ actionVariant = "primary",
8230
+ onAction,
8231
+ secondaryLabel,
8232
+ onSecondary,
8233
+ loading = false,
8234
+ className
8235
+ }) => /* @__PURE__ */ jsxRuntime.jsxs(
8236
+ "div",
8237
+ {
8238
+ className: clsx.clsx(
8239
+ "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",
8240
+ className
8241
+ ),
8242
+ children: [
8243
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
8244
+ /* @__PURE__ */ jsxRuntime.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 }),
8245
+ status && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: STATUS_VARIANT[status], appearance: "light", children: STATUS_LABEL2[status] })
8246
+ ] }),
8247
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 min-w-0 flex-1", children: [
8248
+ category && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-[10px] tracking-wide text-gray-400 uppercase dark:text-gray-500", children: category }),
8249
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mt-0.5 truncate text-sm font-semibold text-gray-900 dark:text-white", children: name }),
8250
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 line-clamp-2 text-xs text-gray-600 dark:text-gray-400", children: description })
8251
+ ] }),
8252
+ (actionLabel || secondaryLabel) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center justify-end gap-2", children: [
8253
+ secondaryLabel && /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", onClick: onSecondary, disabled: loading, children: secondaryLabel }),
8254
+ actionLabel && /* @__PURE__ */ jsxRuntime.jsx(
8255
+ Button,
8256
+ {
8257
+ variant: actionVariant,
8258
+ size: "sm",
8259
+ onClick: onAction,
8260
+ loading,
8261
+ disabled: loading,
8262
+ children: actionLabel
8263
+ }
8264
+ )
8265
+ ] })
8266
+ ]
8267
+ }
8268
+ );
8269
+ var ResetPasswordForm = ({
8270
+ onSubmit,
8271
+ signInHref,
8272
+ signInLabel = "Back to sign in",
8273
+ sent = false,
8274
+ sentEmail,
8275
+ loading = false,
8276
+ error,
8277
+ title = "Reset your password",
8278
+ description = "Enter your email and we\u2019ll send you a link to reset your password.",
8279
+ submitLabel = "Send reset link",
8280
+ onResend,
8281
+ resendLabel = "Resend",
8282
+ className
8283
+ }) => {
8284
+ const [email, setEmail] = react.useState("");
8285
+ const handleSubmit = (e) => {
8286
+ e.preventDefault();
8287
+ if (loading || email.length === 0) return;
8288
+ void onSubmit(email);
8289
+ };
8290
+ if (sent) {
8291
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
8292
+ /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(lucideReact.MailCheck, { className: "h-6 w-6", "aria-hidden": true }) }),
8293
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mt-4 text-center text-xl font-semibold text-gray-900 dark:text-white", children: "Check your inbox" }),
8294
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-2 text-center text-sm text-gray-500 dark:text-gray-400", children: [
8295
+ "We've sent a reset link to",
8296
+ " ",
8297
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-700 dark:text-gray-200", children: sentEmail ?? email }),
8298
+ ". The link expires in 1 hour."
8299
+ ] }),
8300
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 flex flex-col items-stretch gap-2", children: [
8301
+ onResend && /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "secondary", loading, disabled: loading, onClick: onResend, children: resendLabel }),
8302
+ signInHref && /* @__PURE__ */ jsxRuntime.jsxs(Link, { href: signInHref, variant: "subtle", className: "justify-center", children: [
8303
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "h-3.5 w-3.5", "aria-hidden": true }),
8304
+ signInLabel
8305
+ ] })
8306
+ ] })
8307
+ ] });
8308
+ }
8309
+ return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className, children: [
8310
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6", children: [
8311
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-gray-900 dark:text-white", children: title }),
8312
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description })
8313
+ ] }),
8314
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(AlertBanner, { variant: "error", children: error }) }),
8315
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
8316
+ /* @__PURE__ */ jsxRuntime.jsx(
8317
+ Input,
8318
+ {
8319
+ label: "Email",
8320
+ type: "email",
8321
+ icon: lucideReact.Mail,
8322
+ autoComplete: "email",
8323
+ required: true,
8324
+ placeholder: "john@example.com",
8325
+ value: email,
8326
+ onChange: (e) => setEmail(e.target.value),
8327
+ disabled: loading
8328
+ }
8329
+ ),
8330
+ /* @__PURE__ */ jsxRuntime.jsx(
8331
+ Button,
8332
+ {
8333
+ type: "submit",
8334
+ loading,
8335
+ disabled: loading || email.length === 0,
8336
+ className: "w-full",
8337
+ children: submitLabel
8338
+ }
8339
+ )
8340
+ ] }),
8341
+ signInHref && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-5 text-center text-xs text-[var(--color-text-muted)]", children: /* @__PURE__ */ jsxRuntime.jsxs(Link, { href: signInHref, variant: "colored", children: [
8342
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "h-3.5 w-3.5", "aria-hidden": true }),
8343
+ signInLabel
8344
+ ] }) })
8345
+ ] });
8346
+ };
8347
+ var SignInForm = ({
8348
+ onSubmit,
8349
+ onForgotPassword,
8350
+ signUpHref,
8351
+ signUpLabel = "Create one",
8352
+ title = "Sign in",
8353
+ description = "Welcome back \u2014 enter your credentials below.",
8354
+ emailLabel = "Email",
8355
+ passwordLabel = "Password",
8356
+ rememberLabel = "Keep me signed in",
8357
+ submitLabel = "Sign in",
8358
+ forgotLabel = "Forgot password?",
8359
+ loading = false,
8360
+ error,
8361
+ extraTop,
8362
+ className
8363
+ }) => {
8364
+ const [email, setEmail] = react.useState("");
8365
+ const [password, setPassword] = react.useState("");
8366
+ const [remember, setRemember] = react.useState(false);
8367
+ const handleSubmit = (e) => {
8368
+ e.preventDefault();
8369
+ if (loading) return;
8370
+ void onSubmit({ email, password, remember });
8371
+ };
8372
+ return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className, children: [
8373
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6", children: [
8374
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-gray-900 dark:text-white", children: title }),
8375
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description })
8376
+ ] }),
8377
+ extraTop && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-5", children: extraTop }),
8378
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(AlertBanner, { variant: "error", children: error }) }),
8379
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
8380
+ /* @__PURE__ */ jsxRuntime.jsx(
8381
+ Input,
8382
+ {
8383
+ label: emailLabel,
8384
+ type: "email",
8385
+ icon: lucideReact.Mail,
8386
+ autoComplete: "email",
8387
+ required: true,
8388
+ placeholder: "john@example.com",
8389
+ value: email,
8390
+ onChange: (e) => setEmail(e.target.value),
8391
+ disabled: loading
8392
+ }
8393
+ ),
8394
+ /* @__PURE__ */ jsxRuntime.jsx(
8395
+ PasswordInput,
8396
+ {
8397
+ label: passwordLabel,
8398
+ autoComplete: "current-password",
8399
+ required: true,
8400
+ value: password,
8401
+ onChange: (e) => setPassword(e.target.value),
8402
+ disabled: loading
8403
+ }
8404
+ ),
8405
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
8406
+ /* @__PURE__ */ jsxRuntime.jsx(
8407
+ Checkbox,
8408
+ {
8409
+ label: rememberLabel,
8410
+ checked: remember,
8411
+ onChange: (c) => setRemember(c),
8412
+ disabled: loading
8413
+ }
8414
+ ),
8415
+ onForgotPassword && /* @__PURE__ */ jsxRuntime.jsx(
8416
+ "button",
8417
+ {
8418
+ type: "button",
8419
+ onClick: onForgotPassword,
8420
+ className: "text-brand-500 hover:text-brand-600 text-xs font-medium transition-colors",
8421
+ children: forgotLabel
8422
+ }
8423
+ )
8424
+ ] }),
8425
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", loading, disabled: loading, className: "w-full", children: submitLabel })
8426
+ ] }),
8427
+ signUpHref && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-5 text-center text-xs text-[var(--color-text-muted)]", children: [
8428
+ "No account?",
8429
+ " ",
8430
+ /* @__PURE__ */ jsxRuntime.jsx(Link, { href: signUpHref, variant: "colored", children: signUpLabel })
8431
+ ] })
8432
+ ] });
8433
+ };
8434
+ var SignUpForm = ({
8435
+ onSubmit,
8436
+ signInHref,
8437
+ signInLabel = "Sign in",
8438
+ termsHref = "#",
8439
+ privacyHref = "#",
8440
+ showPolicy = true,
8441
+ loading = false,
8442
+ error,
8443
+ title = "Create your account",
8444
+ description = "A few details to get you started.",
8445
+ submitLabel = "Create account",
8446
+ extraTop,
8447
+ className
8448
+ }) => {
8449
+ const [firstName, setFirstName] = react.useState("");
8450
+ const [lastName, setLastName] = react.useState("");
8451
+ const [email, setEmail] = react.useState("");
8452
+ const [password, setPassword] = react.useState("");
8453
+ const [agreedToTerms, setAgreedToTerms] = react.useState(false);
8454
+ const rules = react.useMemo(() => defaultPasswordRules(password), [password]);
8455
+ const allRulesPass = rules.every((r) => r.ok);
8456
+ const canSubmit = firstName.length > 0 && lastName.length > 0 && email.length > 0 && (showPolicy ? allRulesPass : password.length > 0) && agreedToTerms && !loading;
8457
+ const handleSubmit = (e) => {
8458
+ e.preventDefault();
8459
+ if (!canSubmit) return;
8460
+ void onSubmit({ firstName, lastName, email, password, agreedToTerms });
8461
+ };
8462
+ return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className, children: [
8463
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6", children: [
8464
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-gray-900 dark:text-white", children: title }),
8465
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description })
8466
+ ] }),
8467
+ extraTop && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-5", children: extraTop }),
8468
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(AlertBanner, { variant: "error", children: error }) }),
8469
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
8470
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
8471
+ /* @__PURE__ */ jsxRuntime.jsx(
8472
+ Input,
8473
+ {
8474
+ label: "First name",
8475
+ icon: lucideReact.User,
8476
+ autoComplete: "given-name",
8477
+ required: true,
8478
+ placeholder: "John",
8479
+ value: firstName,
8480
+ onChange: (e) => setFirstName(e.target.value),
8481
+ disabled: loading
8482
+ }
8483
+ ),
8484
+ /* @__PURE__ */ jsxRuntime.jsx(
8485
+ Input,
8486
+ {
8487
+ label: "Last name",
8488
+ autoComplete: "family-name",
8489
+ required: true,
8490
+ placeholder: "Doe",
8491
+ value: lastName,
8492
+ onChange: (e) => setLastName(e.target.value),
8493
+ disabled: loading
8494
+ }
8495
+ )
8496
+ ] }),
8497
+ /* @__PURE__ */ jsxRuntime.jsx(
8498
+ Input,
8499
+ {
8500
+ label: "Email",
8501
+ type: "email",
8502
+ icon: lucideReact.Mail,
8503
+ autoComplete: "email",
8504
+ required: true,
8505
+ placeholder: "john@example.com",
8506
+ value: email,
8507
+ onChange: (e) => setEmail(e.target.value),
8508
+ disabled: loading
8509
+ }
8510
+ ),
8511
+ /* @__PURE__ */ jsxRuntime.jsx(
8512
+ PasswordInput,
8513
+ {
8514
+ label: "Password",
8515
+ autoComplete: "new-password",
8516
+ required: true,
8517
+ value: password,
8518
+ onChange: (e) => setPassword(e.target.value),
8519
+ disabled: loading
8520
+ }
8521
+ ),
8522
+ showPolicy && password.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(PasswordPolicyChecker, { rules }),
8523
+ /* @__PURE__ */ jsxRuntime.jsx(
8524
+ Checkbox,
8525
+ {
8526
+ label: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
8527
+ "I agree to the",
8528
+ " ",
8529
+ /* @__PURE__ */ jsxRuntime.jsx(Link, { href: termsHref, variant: "underline", className: "text-current", children: "terms" }),
8530
+ " ",
8531
+ "and",
8532
+ " ",
8533
+ /* @__PURE__ */ jsxRuntime.jsx(Link, { href: privacyHref, variant: "underline", className: "text-current", children: "privacy policy" }),
8534
+ "."
8535
+ ] }),
8536
+ checked: agreedToTerms,
8537
+ onChange: (c) => setAgreedToTerms(c),
8538
+ disabled: loading
8539
+ }
8540
+ ),
8541
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", loading, disabled: !canSubmit, className: "w-full", children: submitLabel })
8542
+ ] }),
8543
+ signInHref && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-5 text-center text-xs text-[var(--color-text-muted)]", children: [
8544
+ "Already have an account?",
8545
+ " ",
8546
+ /* @__PURE__ */ jsxRuntime.jsx(Link, { href: signInHref, variant: "colored", children: signInLabel })
8547
+ ] })
8548
+ ] });
8549
+ };
8550
+ var PROVIDER_NAME = {
8551
+ google: "Google",
8552
+ github: "GitHub",
8553
+ x: "X",
8554
+ facebook: "Facebook",
8555
+ apple: "Apple",
8556
+ microsoft: "Microsoft"
8557
+ };
8558
+ var GoogleIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", "aria-hidden": true, children: [
8559
+ /* @__PURE__ */ jsxRuntime.jsx(
8560
+ "path",
8561
+ {
8562
+ fill: "#4285F4",
8563
+ 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"
8564
+ }
8565
+ ),
8566
+ /* @__PURE__ */ jsxRuntime.jsx(
8567
+ "path",
8568
+ {
8569
+ fill: "#34A853",
8570
+ 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"
8571
+ }
8572
+ ),
8573
+ /* @__PURE__ */ jsxRuntime.jsx(
8574
+ "path",
8575
+ {
8576
+ fill: "#FBBC05",
8577
+ 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"
8578
+ }
8579
+ ),
8580
+ /* @__PURE__ */ jsxRuntime.jsx(
8581
+ "path",
8582
+ {
8583
+ fill: "#EA4335",
8584
+ 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"
8585
+ }
8586
+ )
8587
+ ] });
8588
+ var GithubIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4 fill-current", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
8589
+ "path",
8590
+ {
8591
+ fillRule: "evenodd",
8592
+ clipRule: "evenodd",
8593
+ 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"
8594
+ }
8595
+ ) });
8596
+ var XIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4 fill-current", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.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" }) });
8597
+ var FacebookIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
8598
+ "path",
8599
+ {
8600
+ fill: "#1877F2",
8601
+ 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"
8602
+ }
8603
+ ) });
8604
+ var AppleIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4 fill-current", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.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" }) });
8605
+ var MicrosoftIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", "aria-hidden": true, children: [
8606
+ /* @__PURE__ */ jsxRuntime.jsx("path", { fill: "#F25022", d: "M11.4 11.4H1V1h10.4v10.4Z" }),
8607
+ /* @__PURE__ */ jsxRuntime.jsx("path", { fill: "#7FBA00", d: "M23 11.4H12.6V1H23v10.4Z" }),
8608
+ /* @__PURE__ */ jsxRuntime.jsx("path", { fill: "#00A4EF", d: "M11.4 23H1V12.6h10.4V23Z" }),
8609
+ /* @__PURE__ */ jsxRuntime.jsx("path", { fill: "#FFB900", d: "M23 23H12.6V12.6H23V23Z" })
8610
+ ] });
8611
+ var PROVIDER_ICON = {
8612
+ google: GoogleIcon,
8613
+ github: GithubIcon,
8614
+ x: XIcon,
8615
+ facebook: FacebookIcon,
8616
+ apple: AppleIcon,
8617
+ microsoft: MicrosoftIcon
8618
+ };
8619
+ var SocialAuthButtons = ({
8620
+ providers,
8621
+ onProviderClick,
8622
+ loading,
8623
+ divider = true,
8624
+ dividerLabel = "OR continue with",
8625
+ layout = "stacked",
8626
+ labelFor,
8627
+ position = "above",
8628
+ className
8629
+ }) => {
8630
+ if (providers.length === 0) return null;
8631
+ const buttonsList = /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx.clsx(layout === "grid" ? "grid grid-cols-2 gap-2" : "flex flex-col gap-2"), children: providers.map((provider) => {
8632
+ const Icon2 = PROVIDER_ICON[provider];
8633
+ const isLoading = loading === provider;
8634
+ const isDisabled = loading !== void 0 && loading !== null;
8635
+ const label = labelFor ? labelFor(provider) : `Continue with ${PROVIDER_NAME[provider]}`;
8636
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8637
+ "button",
8638
+ {
8639
+ type: "button",
8640
+ onClick: () => onProviderClick(provider),
8641
+ disabled: isDisabled,
8642
+ "aria-label": label,
8643
+ 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",
8644
+ children: [
8645
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon2, {}),
8646
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label })
8647
+ ]
8648
+ },
8649
+ provider
8650
+ );
8651
+ }) });
8652
+ if (!divider) return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: buttonsList });
8653
+ const dividerNode = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "my-4 flex items-center gap-3", children: [
8654
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px flex-1 bg-gray-200 dark:bg-gray-700" }),
8655
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs tracking-wide text-gray-400 uppercase dark:text-gray-500", children: dividerLabel }),
8656
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px flex-1 bg-gray-200 dark:bg-gray-700" })
8657
+ ] });
8658
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: position === "above" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8659
+ buttonsList,
8660
+ dividerNode
8661
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8662
+ dividerNode,
8663
+ buttonsList
8664
+ ] }) });
8665
+ };
8162
8666
  var StickyScrollNav = ({
8163
8667
  sections,
8164
8668
  onNavigate,
@@ -8194,6 +8698,80 @@ var StickyScrollNav = ({
8194
8698
  }
8195
8699
  );
8196
8700
  };
8701
+ var TwoStepVerificationForm = ({
8702
+ onSubmit,
8703
+ onResend,
8704
+ sentTo,
8705
+ length = 6,
8706
+ loading = false,
8707
+ error,
8708
+ autoSubmit = true,
8709
+ cancelHref,
8710
+ cancelLabel = "Back to sign in",
8711
+ title = "Two-step verification",
8712
+ submitLabel = "Verify my account",
8713
+ resendLabel = "Resend code",
8714
+ className
8715
+ }) => {
8716
+ const [code, setCode] = react.useState("");
8717
+ const description = sentTo ? `Enter the ${length}-digit code we sent to ${sentTo}.` : `Enter the ${length}-digit verification code from your authenticator app.`;
8718
+ const handleSubmit = (e) => {
8719
+ e.preventDefault();
8720
+ if (loading || code.length !== length) return;
8721
+ void onSubmit(code);
8722
+ };
8723
+ const handleComplete = (value) => {
8724
+ if (autoSubmit && !loading) void onSubmit(value);
8725
+ };
8726
+ return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className, children: [
8727
+ /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(lucideReact.ShieldCheck, { className: "h-6 w-6", "aria-hidden": true }) }),
8728
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mt-4 text-center text-xl font-semibold text-gray-900 dark:text-white", children: title }),
8729
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-center text-sm text-gray-500 dark:text-gray-400", children: description }),
8730
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsxRuntime.jsx(AlertBanner, { variant: "error", children: error }) }),
8731
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-6 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
8732
+ OtpInput,
8733
+ {
8734
+ length,
8735
+ value: code,
8736
+ onChange: setCode,
8737
+ onComplete: handleComplete,
8738
+ disabled: loading,
8739
+ error: !!error,
8740
+ autoFocus: true
8741
+ }
8742
+ ) }),
8743
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 space-y-2", children: [
8744
+ /* @__PURE__ */ jsxRuntime.jsx(
8745
+ Button,
8746
+ {
8747
+ type: "submit",
8748
+ loading,
8749
+ disabled: loading || code.length !== length,
8750
+ className: "w-full",
8751
+ children: submitLabel
8752
+ }
8753
+ ),
8754
+ onResend && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-center text-xs text-[var(--color-text-muted)]", children: [
8755
+ "Didn't get a code?",
8756
+ " ",
8757
+ /* @__PURE__ */ jsxRuntime.jsx(
8758
+ "button",
8759
+ {
8760
+ type: "button",
8761
+ onClick: onResend,
8762
+ disabled: loading,
8763
+ className: "text-brand-500 hover:text-brand-600 font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
8764
+ children: resendLabel
8765
+ }
8766
+ )
8767
+ ] }),
8768
+ cancelHref && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs(Link, { href: cancelHref, variant: "subtle", children: [
8769
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "h-3.5 w-3.5", "aria-hidden": true }),
8770
+ cancelLabel
8771
+ ] }) })
8772
+ ] })
8773
+ ] });
8774
+ };
8197
8775
  var ColorSwatch = ({
8198
8776
  hex,
8199
8777
  label,
@@ -8577,6 +9155,7 @@ exports.ActiveFiltersBar = ActiveFiltersBar;
8577
9155
  exports.ActivityFeed = ActivityFeed;
8578
9156
  exports.AlertBanner = AlertBanner;
8579
9157
  exports.AnnouncementBar = AnnouncementBar;
9158
+ exports.AuthLayout = AuthLayout;
8580
9159
  exports.Avatar = Avatar;
8581
9160
  exports.AvatarUploader = AvatarUploader;
8582
9161
  exports.BackToTopFab = BackToTopFab;
@@ -8627,6 +9206,7 @@ exports.HelpOverlay = HelpOverlay;
8627
9206
  exports.IconBox = IconBox;
8628
9207
  exports.ImageGrid = ImageGrid;
8629
9208
  exports.Input = Input;
9209
+ exports.IntegrationCard = IntegrationCard;
8630
9210
  exports.Kbd = Kbd2;
8631
9211
  exports.KpiCard = KpiCard;
8632
9212
  exports.Link = Link;
@@ -8659,6 +9239,7 @@ exports.REFRESH_OPTIONS = REFRESH_OPTIONS;
8659
9239
  exports.Radio = Radio;
8660
9240
  exports.RadioGroup = RadioGroup;
8661
9241
  exports.RefreshButton = RefreshButton;
9242
+ exports.ResetPasswordForm = ResetPasswordForm;
8662
9243
  exports.Ribbon = Ribbon;
8663
9244
  exports.RowActionButton = RowActionButton;
8664
9245
  exports.STATUS_COLOR = STATUS_COLOR;
@@ -8671,11 +9252,14 @@ exports.Select = Select;
8671
9252
  exports.SelectInput = SelectInput;
8672
9253
  exports.Shell = Shell;
8673
9254
  exports.Sidebar = Sidebar;
9255
+ exports.SignInForm = SignInForm;
9256
+ exports.SignUpForm = SignUpForm;
8674
9257
  exports.SimpleRow = SimpleRow;
8675
9258
  exports.Sk = Sk;
8676
9259
  exports.SkeletonList = SkeletonList;
8677
9260
  exports.SkeletonTable = SkeletonTable;
8678
9261
  exports.SkeletonText = SkeletonText;
9262
+ exports.SocialAuthButtons = SocialAuthButtons;
8679
9263
  exports.Spinner = Spinner;
8680
9264
  exports.StackedList = StackedList;
8681
9265
  exports.StackedListInCard = StackedListInCard;
@@ -8697,15 +9281,13 @@ exports.Toggle = Toggle;
8697
9281
  exports.Tooltip = Tooltip;
8698
9282
  exports.TooltipHelp = TooltipHelp;
8699
9283
  exports.Topbar = Topbar;
9284
+ exports.TwoStepVerificationForm = TwoStepVerificationForm;
8700
9285
  exports.UnsavedIndicator = UnsavedIndicator;
8701
9286
  exports.UserMenu = UserMenu;
8702
9287
  exports.VerticalNavigation = VerticalNavigation;
8703
9288
  exports.VideoEmbed = VideoEmbed;
8704
9289
  exports.ZoomBar = ZoomBar;
8705
9290
  exports.defaultPasswordRules = defaultPasswordRules;
8706
- exports.placeholderAvatar = placeholderAvatar;
8707
- exports.placeholderCover = placeholderCover;
8708
- exports.portalDocsParams = portalDocsParams;
8709
9291
  exports.useAutoRefresh = useAutoRefresh;
8710
9292
  //# sourceMappingURL=index.cjs.map
8711
9293
  //# sourceMappingURL=index.cjs.map