@olwiba/ui 0.2.19 → 0.2.21

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,11 +1,11 @@
1
1
  import { cn } from './chunk-AMWLSHD6.js';
2
2
  export { MdxContent, cn } from './chunk-AMWLSHD6.js';
3
- import * as React20 from 'react';
3
+ import * as React21 from 'react';
4
4
  import { useRef, useEffect, useState, useCallback } from 'react';
5
5
  import { Button as Button$1, Card as Card$1, Input as Input$1, Textarea as Textarea$1, Checkbox as Checkbox$1, Switch as Switch$1, useIsMobile, UIVariantProvider, Badge as Badge$1, cn as cn$1, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Avatar, AvatarImage, AvatarFallback, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, Dialog, DialogTrigger, Progress, useUIVariant, Separator, Accordion, AccordionItem, AccordionTrigger, AccordionContent, Label, Sheet, SheetTrigger, SheetContent, StatusIndicator, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandSeparator, CommandGroup, CommandItem, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, ContextMenu as ContextMenu$1, ContextMenuTrigger, ContextMenuContent, AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, CommandShortcut, Popover, PopoverTrigger, PopoverContent, Spinner, SidebarProvider, SidebarInset, CardHeader, CardTitle, CardDescription, CardContent, InputOTP, InputOTPGroup, InputOTPSlot, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose, ContextMenuSeparator, ContextMenuLabel, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent, ContextMenuItem, ContextMenuShortcut, useSidebar, Sidebar, SidebarHeader, SidebarMenu, SidebarMenuItem, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarMenuButton, SidebarFooter, SidebarTrigger, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup } from '@olwiba/cn';
6
6
  export { CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Enchanted } from '@olwiba/cn';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
- import { Search, ArrowUp, ArrowDown, ArrowUpDown, ChevronLeft, ChevronRight, MoreHorizontal, UserPlus, Download, CreditCard, Check, Loader2, ArrowLeft, ArrowUpRight, X, Sparkles, RefreshCw, ArrowRight, Minus, Quote, Star, Twitter, Github, Linkedin, Mail, MessageSquare, ChevronDown, Send, Menu, UploadCloud, File, CheckCircle2, AlertCircle, Bell, Inbox, Activity, TrendingUp, TrendingDown, LayoutGrid, List, Sun, Moon, Palette, AlertTriangle, Rocket, Info, Layers, ShieldCheck, Building2, MoreVerticalIcon, CreditCardIcon, BellIcon, LogOutIcon } from 'lucide-react';
8
+ import { Search, ArrowUp, ArrowDown, ArrowUpDown, ChevronLeft, ChevronRight, MoreHorizontal, UserPlus, Download, CreditCard, Check, Loader2, ArrowLeft, ArrowUpRight, X, Sparkles, RefreshCw, ArrowRight, Minus, Quote, Star, Twitter, Github, Linkedin, Mail, MessageSquare, ChevronDown, Send, Menu, UploadCloud, File, CheckCircle2, AlertCircle, Bell, Inbox, Activity, TrendingUp, TrendingDown, LayoutGrid, List, Sun, Moon, Palette, AlertTriangle, Rocket, Info, Layers, ShieldCheck, Building2, BirdIcon, MoreVerticalIcon, CreditCardIcon, BellIcon, SettingsIcon, LogOutIcon } from 'lucide-react';
9
9
  import { useReactTable, getPaginationRowModel, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
10
10
  import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter } from '@dnd-kit/core';
11
11
  import { sortableKeyboardCoordinates, SortableContext, rectSortingStrategy, horizontalListSortingStrategy, verticalListSortingStrategy, arrayMove, useSortable } from '@dnd-kit/sortable';
@@ -13,26 +13,27 @@ import { CSS } from '@dnd-kit/utilities';
13
13
  import { PieChart, Pie, Cell, BarChart, XAxis, YAxis, Bar, AreaChart, Area, LineChart, Line, ResponsiveContainer, Tooltip as Tooltip$1, CartesianGrid } from 'recharts';
14
14
  import { toast } from 'sonner';
15
15
 
16
- var OlwibaUIContext = React20.createContext({
16
+ var OlwibaUIContext = React21.createContext({
17
17
  isMobile: false,
18
18
  mode: "default",
19
19
  setMode: () => {
20
20
  }
21
21
  });
22
- function OlwibaUIProvider({ children, isMobile: isMobileProp, mode: initialMode = "default" }) {
22
+ function OlwibaUIProvider({ children, isMobile: isMobileProp, mode: modeProp }) {
23
23
  const detectedMobile = useIsMobile();
24
24
  const isMobile = isMobileProp ?? detectedMobile;
25
- const [mode, setMode] = React20.useState(initialMode);
25
+ const [uncontrolledMode, setMode] = React21.useState("default");
26
+ const mode = modeProp ?? uncontrolledMode;
26
27
  const variant = mode !== "default" ? mode : void 0;
27
28
  return /* @__PURE__ */ jsx(OlwibaUIContext.Provider, { value: { isMobile, mode, setMode }, children: /* @__PURE__ */ jsx(UIVariantProvider, { mode: variant, children }) });
28
29
  }
29
30
  function useOlwibaUI() {
30
- return React20.useContext(OlwibaUIContext);
31
+ return React21.useContext(OlwibaUIContext);
31
32
  }
32
33
  function useUIMode() {
33
- return React20.useContext(OlwibaUIContext).mode;
34
+ return React21.useContext(OlwibaUIContext).mode;
34
35
  }
35
- var Button = React20.forwardRef(
36
+ var Button = React21.forwardRef(
36
37
  ({ mode, ...props }, ref) => {
37
38
  const ctxMode = useUIMode();
38
39
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -40,7 +41,7 @@ var Button = React20.forwardRef(
40
41
  }
41
42
  );
42
43
  Button.displayName = "Button";
43
- var Card = React20.forwardRef(
44
+ var Card = React21.forwardRef(
44
45
  ({ mode, ...props }, ref) => {
45
46
  const ctxMode = useUIMode();
46
47
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -51,7 +52,7 @@ Card.displayName = "Card";
51
52
  function Badge(props) {
52
53
  return /* @__PURE__ */ jsx(Badge$1, { ...props });
53
54
  }
54
- var Input = React20.forwardRef(
55
+ var Input = React21.forwardRef(
55
56
  ({ mode, ...props }, ref) => {
56
57
  const ctxMode = useUIMode();
57
58
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -59,7 +60,7 @@ var Input = React20.forwardRef(
59
60
  }
60
61
  );
61
62
  Input.displayName = "Input";
62
- var Textarea = React20.forwardRef(
63
+ var Textarea = React21.forwardRef(
63
64
  ({ mode, ...props }, ref) => {
64
65
  const ctxMode = useUIMode();
65
66
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -67,13 +68,13 @@ var Textarea = React20.forwardRef(
67
68
  }
68
69
  );
69
70
  Textarea.displayName = "Textarea";
70
- var Checkbox = React20.forwardRef(({ mode, ...props }, ref) => {
71
+ var Checkbox = React21.forwardRef(({ mode, ...props }, ref) => {
71
72
  const ctxMode = useUIMode();
72
73
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
73
74
  return /* @__PURE__ */ jsx(Checkbox$1, { mode: resolvedMode, ...props, ref });
74
75
  });
75
76
  Checkbox.displayName = "Checkbox";
76
- var Switch = React20.forwardRef(({ mode: _mode, ...props }, ref) => {
77
+ var Switch = React21.forwardRef(({ mode: _mode, ...props }, ref) => {
77
78
  return /* @__PURE__ */ jsx(Switch$1, { ...props, ref });
78
79
  });
79
80
  Switch.displayName = "Switch";
@@ -262,20 +263,23 @@ function PublicPageFrame({
262
263
  return /* @__PURE__ */ jsx("div", { className: cn("min-h-screen", surfaceMap[surface], className), ...props, children: /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", spacingMap2[spacing], maxWidthMap2[maxWidth]), children }) });
263
264
  }
264
265
  var RAIL_SQUARE = "group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!min-w-8 group-data-[collapsible=icon]:!max-w-8 group-data-[collapsible=icon]:!p-0 group-data-[collapsible=icon]:transition-[width,height]";
265
- function initialsOf(source) {
266
- const base = source.includes("@") ? source.split("@")[0] ?? source : source;
267
- const words = base.split(/[\s._-]+/).filter(Boolean);
268
- if (words.length >= 2) return (words[0][0] + words[1][0]).toUpperCase();
269
- return (words[0] ?? base).slice(0, 2).toUpperCase();
270
- }
271
266
  function identityGradient(seed) {
272
- let hash = 0;
267
+ let hash = 2166136261;
273
268
  for (let i = 0; i < seed.length; i += 1) {
274
- hash = hash * 31 + seed.charCodeAt(i) | 0;
269
+ hash ^= seed.charCodeAt(i);
270
+ hash = Math.imul(hash, 16777619);
275
271
  }
276
- const hue = Math.abs(hash) % 360;
272
+ hash >>>= 0;
273
+ const firstHue = hash % 360;
274
+ const secondHue = (firstHue + 55 + (hash >>> 8) % 70) % 360;
275
+ const thirdHue = (firstHue + 190 + (hash >>> 16) % 110) % 360;
276
+ const angleHash = Math.imul(hash ^ hash >>> 15, 2246822519) >>> 0;
277
+ const angle = angleHash % 360;
277
278
  return {
278
- backgroundImage: `linear-gradient(135deg, oklch(0.62 0.15 ${hue}), oklch(0.52 0.16 ${(hue + 28) % 360}))`,
279
+ backgroundImage: [
280
+ `radial-gradient(circle at 28% 18%, oklch(0.94 0.06 ${thirdHue} / 0.78), transparent 34%)`,
281
+ `linear-gradient(${angle}deg, oklch(0.68 0.18 ${firstHue}), oklch(0.55 0.2 ${secondHue}) 52%, oklch(0.62 0.18 ${thirdHue}))`
282
+ ].join(", "),
279
283
  color: "oklch(0.98 0 0)"
280
284
  };
281
285
  }
@@ -283,8 +287,8 @@ function NavUser({ user }) {
283
287
  const { isMobile } = useSidebar();
284
288
  const uiMode = useUIMode();
285
289
  const avatarMode = uiMode !== "default" ? uiMode : void 0;
286
- const initials = initialsOf(user.name ?? user.email);
287
- const identityTint = identityGradient(user.email);
290
+ const identitySeed = `${user.name?.trim().toLocaleLowerCase() ?? ""}|${user.email.toLocaleLowerCase()}`;
291
+ const identityTint = identityGradient(identitySeed);
288
292
  return /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
289
293
  /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
290
294
  SidebarMenuButton,
@@ -298,7 +302,13 @@ function NavUser({ user }) {
298
302
  children: [
299
303
  /* @__PURE__ */ jsxs(Avatar, { mode: avatarMode, size: "sm", children: [
300
304
  user.avatar && /* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
301
- /* @__PURE__ */ jsx(AvatarFallback, { className: "font-medium", style: identityTint, children: initials })
305
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "text-white", style: identityTint, children: /* @__PURE__ */ jsx(
306
+ BirdIcon,
307
+ {
308
+ "aria-hidden": true,
309
+ className: "size-4 drop-shadow-[0_1px_1px_rgb(0_0_0/0.3)]"
310
+ }
311
+ ) })
302
312
  ] }),
303
313
  /* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
304
314
  /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: user.name ?? user.email }),
@@ -319,14 +329,20 @@ function NavUser({ user }) {
319
329
  /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "p-0 font-normal", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm", children: [
320
330
  /* @__PURE__ */ jsxs(Avatar, { mode: avatarMode, size: "sm", children: [
321
331
  user.avatar && /* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
322
- /* @__PURE__ */ jsx(AvatarFallback, { className: "font-medium", style: identityTint, children: initials })
332
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "text-white", style: identityTint, children: /* @__PURE__ */ jsx(
333
+ BirdIcon,
334
+ {
335
+ "aria-hidden": true,
336
+ className: "size-4 drop-shadow-[0_1px_1px_rgb(0_0_0/0.3)]"
337
+ }
338
+ ) })
323
339
  ] }),
324
340
  /* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
325
341
  /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: user.name ?? user.email }),
326
342
  /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: user.email })
327
343
  ] })
328
344
  ] }) }),
329
- (user.onBilling || user.onNotifications) && /* @__PURE__ */ jsxs(Fragment, { children: [
345
+ (user.onBilling || user.onNotifications || user.onSettings) && /* @__PURE__ */ jsxs(Fragment, { children: [
330
346
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
331
347
  /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
332
348
  user.onBilling && /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: user.onBilling, children: [
@@ -336,6 +352,10 @@ function NavUser({ user }) {
336
352
  user.onNotifications && /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: user.onNotifications, children: [
337
353
  /* @__PURE__ */ jsx(BellIcon, {}),
338
354
  "Notifications"
355
+ ] }),
356
+ user.onSettings && /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: user.onSettings, children: [
357
+ /* @__PURE__ */ jsx(SettingsIcon, {}),
358
+ "Settings"
339
359
  ] })
340
360
  ] })
341
361
  ] }),
@@ -479,7 +499,7 @@ function AppShell({
479
499
  sidebarPosition
480
500
  }
481
501
  ),
482
- /* @__PURE__ */ jsxs(SidebarInset, { className: isContained ? void 0 : "overflow-y-auto", children: [
502
+ /* @__PURE__ */ jsxs(SidebarInset, { className: "overflow-y-auto", children: [
483
503
  /* @__PURE__ */ jsx(ShellHeader, { pageTitle, headerStart, headerEnd }),
484
504
  /* @__PURE__ */ jsx("div", { className: contentClassName, children })
485
505
  ] })
@@ -506,8 +526,14 @@ function AppPageHero({
506
526
  {
507
527
  className: cn(
508
528
  "relative overflow-hidden rounded-3xl border bg-card/80 p-5 shadow-sm sm:p-6",
509
- "before:absolute before:-right-16 before:-top-16 before:size-44 before:rounded-full before:bg-primary/15 before:blur-3xl",
510
- "after:absolute after:-bottom-20 after:left-10 after:size-52 after:rounded-full after:bg-primary/10 after:blur-3xl",
529
+ // The glow blobs are decoration, and `::after` is the section's last
530
+ // child so with everything on `z-index: auto` it paints above the
531
+ // header content and swallows clicks on whatever sits under it. At
532
+ // narrow widths the action row stacks below the copy, right into the
533
+ // bottom-left blob, which is how a visible button stops responding.
534
+ // pointer-events-none keeps them purely visual.
535
+ "before:pointer-events-none before:absolute before:-right-16 before:-top-16 before:size-44 before:rounded-full before:bg-primary/15 before:blur-3xl",
536
+ "after:pointer-events-none after:absolute after:-bottom-20 after:left-10 after:size-52 after:rounded-full after:bg-primary/10 after:blur-3xl",
511
537
  className
512
538
  ),
513
539
  children: [
@@ -626,7 +652,7 @@ function DefaultForm({
626
652
  const isForgotPassword = mode === "forgot-password";
627
653
  const isResetPassword = mode === "reset-password";
628
654
  const isVerify = mode === "verify";
629
- const [code, setCode] = React20.useState("");
655
+ const [code, setCode] = React21.useState("");
630
656
  const hasPrefill = !!(defaultEmail || defaultPassword);
631
657
  const prefillStyle = (active) => active ? { animation: "auth-prefill 1.6s ease-out 0.35s 1 both" } : void 0;
632
658
  const copy = authCopy[mode];
@@ -787,10 +813,10 @@ function DataTable({
787
813
  emptyMessage = "No results.",
788
814
  className
789
815
  }) {
790
- const [sorting, setSorting] = React20.useState([]);
791
- const [rowSelection, setRowSelection] = React20.useState({});
792
- const [globalFilter, setGlobalFilter] = React20.useState("");
793
- const allColumns = React20.useMemo(
816
+ const [sorting, setSorting] = React21.useState([]);
817
+ const [rowSelection, setRowSelection] = React21.useState({});
818
+ const [globalFilter, setGlobalFilter] = React21.useState("");
819
+ const allColumns = React21.useMemo(
794
820
  () => selectable ? [selectColumn, ...columns] : columns,
795
821
  [selectable, columns]
796
822
  );
@@ -812,7 +838,7 @@ function DataTable({
812
838
  initialState: pageSize > 0 ? { pagination: { pageSize } } : void 0,
813
839
  enableRowSelection: selectable
814
840
  });
815
- React20.useEffect(() => {
841
+ React21.useEffect(() => {
816
842
  if (!onSelectionChange) return;
817
843
  onSelectionChange(table.getSelectedRowModel().rows.map((r) => r.original));
818
844
  }, [rowSelection]);
@@ -892,8 +918,8 @@ function DataTable({
892
918
  ] });
893
919
  }
894
920
  function InviteDialog({ roles, onInvite, onClose }) {
895
- const [email, setEmail] = React20.useState("");
896
- const [role, setRole] = React20.useState(roles[roles.length - 1] ?? roles[0]);
921
+ const [email, setEmail] = React21.useState("");
922
+ const [role, setRole] = React21.useState(roles[roles.length - 1] ?? roles[0]);
897
923
  return /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsxs(
898
924
  "form",
899
925
  {
@@ -937,8 +963,8 @@ function TeamMembersPanel({
937
963
  title = "Team members",
938
964
  description = "Manage who has access to this workspace."
939
965
  }) {
940
- const [inviteOpen, setInviteOpen] = React20.useState(false);
941
- const columns = React20.useMemo(() => [
966
+ const [inviteOpen, setInviteOpen] = React21.useState(false);
967
+ const columns = React21.useMemo(() => [
942
968
  {
943
969
  accessorKey: "name",
944
970
  header: "Name",
@@ -1007,7 +1033,7 @@ function BillingPanel({
1007
1033
  onUpdatePaymentMethod,
1008
1034
  className
1009
1035
  }) {
1010
- const invoiceColumns = React20.useMemo(() => [
1036
+ const invoiceColumns = React21.useMemo(() => [
1011
1037
  { accessorKey: "date", header: "Date", enableSorting: false },
1012
1038
  { accessorKey: "amount", header: "Amount", enableSorting: false },
1013
1039
  {
@@ -1086,9 +1112,9 @@ function OnboardingWizard({
1086
1112
  completeLabel = "Finish",
1087
1113
  className
1088
1114
  }) {
1089
- const [internalStep, setInternalStep] = React20.useState(0);
1090
- const [error, setError] = React20.useState(null);
1091
- const [pending, setPending] = React20.useState(false);
1115
+ const [internalStep, setInternalStep] = React21.useState(0);
1116
+ const [error, setError] = React21.useState(null);
1117
+ const [pending, setPending] = React21.useState(false);
1092
1118
  const index = stepProp ?? internalStep;
1093
1119
  const current = steps[index];
1094
1120
  const isLast = index === steps.length - 1;
@@ -1418,10 +1444,10 @@ function UpdateBanner({
1418
1444
  buttonLabel = "Refresh now",
1419
1445
  className
1420
1446
  }) {
1421
- const [show, setShow] = React20.useState(forceShow);
1422
- const [entered, setEntered] = React20.useState(false);
1423
- const [refreshing, setRefreshing] = React20.useState(false);
1424
- React20.useEffect(() => {
1447
+ const [show, setShow] = React21.useState(forceShow);
1448
+ const [entered, setEntered] = React21.useState(false);
1449
+ const [refreshing, setRefreshing] = React21.useState(false);
1450
+ React21.useEffect(() => {
1425
1451
  if (forceShow) {
1426
1452
  setShow(true);
1427
1453
  return;
@@ -1444,7 +1470,7 @@ function UpdateBanner({
1444
1470
  clearInterval(id);
1445
1471
  };
1446
1472
  }, [currentVersion, fetchVersion, forceShow, intervalMs]);
1447
- React20.useEffect(() => {
1473
+ React21.useEffect(() => {
1448
1474
  if (!show) {
1449
1475
  setEntered(false);
1450
1476
  return;
@@ -1517,9 +1543,9 @@ function FadeIn({
1517
1543
  style,
1518
1544
  ...props
1519
1545
  }) {
1520
- const ref = React20.useRef(null);
1521
- const [visible, setVisible] = React20.useState(false);
1522
- React20.useEffect(() => {
1546
+ const ref = React21.useRef(null);
1547
+ const [visible, setVisible] = React21.useState(false);
1548
+ React21.useEffect(() => {
1523
1549
  const el = ref.current;
1524
1550
  if (!el) return;
1525
1551
  const observer = new IntersectionObserver(
@@ -1564,6 +1590,36 @@ var marketingSectionSpacing = {
1564
1590
  standard: "px-6 py-14 sm:px-10 sm:py-20",
1565
1591
  hero: "px-6 pb-14 pt-10 sm:px-10 sm:py-20"
1566
1592
  };
1593
+ var MarketingSurfaceContext = React21.createContext(void 0);
1594
+ function MarketingSurfaceProvider({
1595
+ surface,
1596
+ children
1597
+ }) {
1598
+ return /* @__PURE__ */ jsx(MarketingSurfaceContext.Provider, { value: surface, children });
1599
+ }
1600
+ function useMarketingSurface() {
1601
+ return React21.useContext(MarketingSurfaceContext);
1602
+ }
1603
+ function useSectionSurface(override) {
1604
+ const mode = useUIVariant();
1605
+ const contextSurface = useMarketingSurface();
1606
+ const surface = override ?? contextSurface ?? "card";
1607
+ if (surface === "plain") return "overflow-hidden";
1608
+ if (surface === "soft") {
1609
+ return cn$1(
1610
+ "overflow-hidden border backdrop-blur-md",
1611
+ mode === "smooth" && "rounded-[2rem] border-border/40 bg-card/40",
1612
+ mode === "playful" && "rounded-3xl border-primary/20 bg-card/50",
1613
+ !mode && "rounded-3xl border-border/50 bg-card/45"
1614
+ );
1615
+ }
1616
+ return cn$1(
1617
+ "overflow-hidden bg-card",
1618
+ mode === "smooth" && "rounded-3xl border",
1619
+ mode === "playful" && "rounded-2xl border-primary/25 border",
1620
+ !mode && "rounded-2xl border"
1621
+ );
1622
+ }
1567
1623
  var sizes = {
1568
1624
  sm: { outer: "w-44", height: "h-80", notch: "w-16 h-4", border: "rounded-[2rem]", screen: "rounded-[1.75rem]" },
1569
1625
  md: { outer: "w-56", height: "h-[26rem]", notch: "w-20 h-5", border: "rounded-[2.5rem]", screen: "rounded-[2.25rem]" },
@@ -1724,16 +1780,16 @@ function Carousel({
1724
1780
  className
1725
1781
  }) {
1726
1782
  const mode = useUIVariant();
1727
- const trackRef = React20.useRef(null);
1728
- const [canPrev, setCanPrev] = React20.useState(false);
1729
- const [canNext, setCanNext] = React20.useState(true);
1730
- const updateScrollState = React20.useCallback(() => {
1783
+ const trackRef = React21.useRef(null);
1784
+ const [canPrev, setCanPrev] = React21.useState(false);
1785
+ const [canNext, setCanNext] = React21.useState(true);
1786
+ const updateScrollState = React21.useCallback(() => {
1731
1787
  const track = trackRef.current;
1732
1788
  if (!track) return;
1733
1789
  setCanPrev(track.scrollLeft > 8);
1734
1790
  setCanNext(track.scrollLeft < track.scrollWidth - track.clientWidth - 8);
1735
1791
  }, []);
1736
- React20.useEffect(() => {
1792
+ React21.useEffect(() => {
1737
1793
  const track = trackRef.current;
1738
1794
  if (!track) return;
1739
1795
  updateScrollState();
@@ -1790,7 +1846,7 @@ function Carousel({
1790
1846
  role: "region",
1791
1847
  "aria-label": ariaLabel,
1792
1848
  className: "flex snap-x snap-mandatory gap-6 overflow-x-auto pb-4 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
1793
- children: React20.Children.map(
1849
+ children: React21.Children.map(
1794
1850
  children,
1795
1851
  (child) => child == null ? null : /* @__PURE__ */ jsx("div", { "data-carousel-item": true, className: cn$1("shrink-0 snap-start", itemClassName), children: child })
1796
1852
  )
@@ -1815,9 +1871,9 @@ function StaggerChildren({
1815
1871
  className,
1816
1872
  ...props
1817
1873
  }) {
1818
- const ref = React20.useRef(null);
1819
- const [visible, setVisible] = React20.useState(false);
1820
- React20.useEffect(() => {
1874
+ const ref = React21.useRef(null);
1875
+ const [visible, setVisible] = React21.useState(false);
1876
+ React21.useEffect(() => {
1821
1877
  const el = ref.current;
1822
1878
  if (!el) return;
1823
1879
  const observer = new IntersectionObserver(
@@ -1835,7 +1891,7 @@ function StaggerChildren({
1835
1891
  return () => observer.disconnect();
1836
1892
  }, [once]);
1837
1893
  const [tx, ty] = translateMap2[direction];
1838
- return /* @__PURE__ */ jsx("div", { ref, className: cn$1(className), ...props, children: React20.Children.map(children, (child, i) => /* @__PURE__ */ jsx(
1894
+ return /* @__PURE__ */ jsx("div", { ref, className: cn$1(className), ...props, children: React21.Children.map(children, (child, i) => /* @__PURE__ */ jsx(
1839
1895
  "div",
1840
1896
  {
1841
1897
  className: "h-full",
@@ -1854,15 +1910,10 @@ function FeaturesSection({
1854
1910
  description = "A complete system of components, blocks, and hooks designed to work together - and get out of your way.",
1855
1911
  badge = "Features",
1856
1912
  features,
1857
- layout = "grid"
1913
+ layout = "grid",
1914
+ surface
1858
1915
  }) {
1859
- const mode = useUIVariant();
1860
- const sectionClasses = cn$1(
1861
- "overflow-hidden bg-card",
1862
- mode === "smooth" && "rounded-3xl border",
1863
- mode === "playful" && "rounded-2xl border-primary/25 border",
1864
- !mode && "rounded-2xl border"
1865
- );
1916
+ const sectionClasses = useSectionSurface(surface);
1866
1917
  const cards = features.map((feature) => /* @__PURE__ */ jsx(
1867
1918
  FeatureCard,
1868
1919
  {
@@ -1882,15 +1933,10 @@ function GroupedFeaturesSection({
1882
1933
  badge = "Features",
1883
1934
  title = "Everything you need to ship",
1884
1935
  description,
1885
- groups
1936
+ groups,
1937
+ surface
1886
1938
  }) {
1887
- const mode = useUIVariant();
1888
- const sectionClasses = cn$1(
1889
- "overflow-hidden bg-card",
1890
- mode === "smooth" && "rounded-3xl border",
1891
- mode === "playful" && "rounded-2xl border-primary/25 border",
1892
- !mode && "rounded-2xl border"
1893
- );
1939
+ const sectionClasses = useSectionSurface(surface);
1894
1940
  return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
1895
1941
  /* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
1896
1942
  /* @__PURE__ */ jsx("div", { className: "mt-14 space-y-14", children: groups.map((group, i) => /* @__PURE__ */ jsxs("div", { children: [
@@ -1960,15 +2006,10 @@ function StepsSection({
1960
2006
  description,
1961
2007
  steps,
1962
2008
  variant = "default",
1963
- groups
2009
+ groups,
2010
+ surface
1964
2011
  }) {
1965
- const mode = useUIVariant();
1966
- const sectionClasses = cn$1(
1967
- "overflow-hidden bg-card",
1968
- mode === "smooth" && "rounded-3xl border",
1969
- mode === "playful" && "rounded-2xl border-primary/25 border",
1970
- !mode && "rounded-2xl border"
1971
- );
2012
+ const sectionClasses = useSectionSurface(surface);
1972
2013
  if (variant === "timeline") {
1973
2014
  const resolvedGroups = groups ?? (steps ? [{ steps }] : []);
1974
2015
  let nextNumber = 1;
@@ -1977,7 +2018,7 @@ function StepsSection({
1977
2018
  /* @__PURE__ */ jsx("div", { className: "mt-12", children: resolvedGroups.map((group, groupIndex) => {
1978
2019
  const startNumber = nextNumber;
1979
2020
  nextNumber += group.steps.length;
1980
- return /* @__PURE__ */ jsxs(React20.Fragment, { children: [
2021
+ return /* @__PURE__ */ jsxs(React21.Fragment, { children: [
1981
2022
  /* @__PURE__ */ jsx("div", { className: cn$1(groupIndex > 0 && "mt-10"), children: /* @__PURE__ */ jsx(TimelineGroup, { steps: group.steps, startNumber, fadeIn: groupIndex > 0 }) }),
1982
2023
  group.after && /* @__PURE__ */ jsx("div", { className: "mt-16", children: group.after })
1983
2024
  ] }, groupIndex);
@@ -2021,15 +2062,11 @@ function TechStackSection({
2021
2062
  badge = "Built on",
2022
2063
  title = "The stack",
2023
2064
  description,
2024
- items
2065
+ items,
2066
+ surface
2025
2067
  }) {
2026
2068
  const mode = useUIVariant();
2027
- const sectionClasses = cn$1(
2028
- "overflow-hidden bg-card",
2029
- mode === "smooth" && "rounded-3xl border",
2030
- mode === "playful" && "rounded-2xl border-primary/25 border",
2031
- !mode && "rounded-2xl border"
2032
- );
2069
+ const sectionClasses = useSectionSurface(surface);
2033
2070
  return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
2034
2071
  /* @__PURE__ */ jsx(SectionTitle, { badge, title, description }),
2035
2072
  /* @__PURE__ */ jsx(StaggerChildren, { className: "mt-12 grid gap-4 sm:grid-cols-2 lg:grid-cols-4", children: items.map((item) => {
@@ -2077,16 +2114,11 @@ function FeatureMarqueeSection({
2077
2114
  description,
2078
2115
  rows,
2079
2116
  speed = "normal",
2080
- pauseOnHover = true
2117
+ pauseOnHover = true,
2118
+ surface
2081
2119
  }) {
2082
- const mode = useUIVariant();
2083
2120
  const duration = speedDuration[speed];
2084
- const sectionClasses = cn$1(
2085
- "overflow-hidden bg-card",
2086
- mode === "smooth" && "rounded-3xl border",
2087
- mode === "playful" && "rounded-2xl border-primary/25 border",
2088
- !mode && "rounded-2xl border"
2089
- );
2121
+ const sectionClasses = useSectionSurface(surface);
2090
2122
  return /* @__PURE__ */ jsxs("section", { className: sectionClasses, children: [
2091
2123
  /* @__PURE__ */ jsxs("div", { className: "py-14 sm:py-20", children: [
2092
2124
  (title || badge || description) && /* @__PURE__ */ jsx(FadeIn, { direction: "up", children: /* @__PURE__ */ jsx("div", { className: "mx-auto mb-10 max-w-4xl px-6 sm:px-10", children: /* @__PURE__ */ jsx(SectionTitle, { title: title ?? "", description, badge }) }) }),
@@ -2147,9 +2179,9 @@ function FeatureMarqueeSection({
2147
2179
  ] });
2148
2180
  }
2149
2181
  function useIntersectionObserver(options) {
2150
- const ref = React20.useRef(null);
2151
- const [isIntersecting, setIsIntersecting] = React20.useState(false);
2152
- React20.useEffect(() => {
2182
+ const ref = React21.useRef(null);
2183
+ const [isIntersecting, setIsIntersecting] = React21.useState(false);
2184
+ React21.useEffect(() => {
2153
2185
  const el = ref.current;
2154
2186
  if (!el) return;
2155
2187
  const observer = new IntersectionObserver(([entry]) => {
@@ -2171,8 +2203,8 @@ function ShowcaseCta({
2171
2203
  sectionClasses
2172
2204
  }) {
2173
2205
  const [ref, intersecting] = useIntersectionObserver({ threshold: 0.15 });
2174
- const [visible, setVisible] = React20.useState(false);
2175
- React20.useEffect(() => {
2206
+ const [visible, setVisible] = React21.useState(false);
2207
+ React21.useEffect(() => {
2176
2208
  if (intersecting) setVisible(true);
2177
2209
  }, [intersecting]);
2178
2210
  return /* @__PURE__ */ jsxs(
@@ -2221,15 +2253,11 @@ function CtaSection(props) {
2221
2253
  secondaryCta,
2222
2254
  footnote,
2223
2255
  variant = "default",
2224
- renderLink = defaultRenderLink5
2256
+ renderLink = defaultRenderLink5,
2257
+ surface
2225
2258
  } = props;
2226
2259
  const mode = useUIVariant();
2227
- const sectionClasses = cn$1(
2228
- "overflow-hidden bg-card",
2229
- mode === "smooth" && "rounded-3xl border",
2230
- mode === "playful" && "rounded-2xl border-primary/25 border",
2231
- !mode && "rounded-2xl border"
2232
- );
2260
+ const sectionClasses = useSectionSurface(surface);
2233
2261
  if (variant === "showcase") {
2234
2262
  return /* @__PURE__ */ jsx(ShowcaseCta, { ...props, sectionClasses });
2235
2263
  }
@@ -2313,25 +2341,25 @@ function AnimatedSwap({
2313
2341
  const ms = duration ?? spec?.duration ?? 0;
2314
2342
  const reduced = usePrefersReducedMotion();
2315
2343
  const animated = spec !== null && !reduced;
2316
- const previous = React20.useRef(children);
2317
- const seenKey = React20.useRef(swapKey);
2318
- const [swap, setSwap] = React20.useState(null);
2344
+ const previous = React21.useRef(children);
2345
+ const seenKey = React21.useRef(swapKey);
2346
+ const [swap, setSwap] = React21.useState(null);
2319
2347
  if (seenKey.current !== swapKey) {
2320
2348
  const out = previous.current;
2321
2349
  seenKey.current = swapKey;
2322
2350
  if (animated) setSwap({ key: swapKey, out, running: false });
2323
2351
  }
2324
- React20.useEffect(() => {
2352
+ React21.useEffect(() => {
2325
2353
  previous.current = children;
2326
2354
  });
2327
- React20.useEffect(() => {
2355
+ React21.useEffect(() => {
2328
2356
  if (!swap || swap.running) return;
2329
2357
  const raf = requestAnimationFrame(() => {
2330
2358
  setSwap((s) => s && s.key === swap.key ? { ...s, running: true } : s);
2331
2359
  });
2332
2360
  return () => cancelAnimationFrame(raf);
2333
2361
  }, [swap]);
2334
- React20.useEffect(() => {
2362
+ React21.useEffect(() => {
2335
2363
  if (!swap?.running) return;
2336
2364
  const done = setTimeout(() => {
2337
2365
  setSwap((s) => s && s.key === swap.key ? null : s);
@@ -2361,8 +2389,8 @@ function AnimatedSwap({
2361
2389
  );
2362
2390
  }
2363
2391
  function usePrefersReducedMotion() {
2364
- const [reduced, setReduced] = React20.useState(false);
2365
- React20.useEffect(() => {
2392
+ const [reduced, setReduced] = React21.useState(false);
2393
+ React21.useEffect(() => {
2366
2394
  const query = window.matchMedia?.("(prefers-reduced-motion: reduce)");
2367
2395
  if (!query) return;
2368
2396
  setReduced(query.matches);
@@ -2474,8 +2502,8 @@ function CountdownTimer({
2474
2502
  className,
2475
2503
  compact = false
2476
2504
  }) {
2477
- const [timeLeft, setTimeLeft] = React20.useState(() => getTimeLeft(deadline));
2478
- React20.useEffect(() => {
2505
+ const [timeLeft, setTimeLeft] = React21.useState(() => getTimeLeft(deadline));
2506
+ React21.useEffect(() => {
2479
2507
  setTimeLeft(getTimeLeft(deadline));
2480
2508
  const id = setInterval(() => setTimeLeft(getTimeLeft(deadline)), 1e3);
2481
2509
  return () => clearInterval(id);
@@ -2501,7 +2529,7 @@ function CountdownTimer({
2501
2529
  ];
2502
2530
  return /* @__PURE__ */ jsxs("div", { className: cn$1("flex items-center justify-center gap-2 text-sm", className), children: [
2503
2531
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label }),
2504
- /* @__PURE__ */ jsx("span", { className: "flex items-center gap-1 font-mono font-semibold tabular-nums", children: units.map(({ value, unit }, i) => /* @__PURE__ */ jsxs(React20.Fragment, { children: [
2532
+ /* @__PURE__ */ jsx("span", { className: "flex items-center gap-1 font-mono font-semibold tabular-nums", children: units.map(({ value, unit }, i) => /* @__PURE__ */ jsxs(React21.Fragment, { children: [
2505
2533
  /* @__PURE__ */ jsxs("span", { children: [
2506
2534
  String(value).padStart(2, "0"),
2507
2535
  /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: unit })
@@ -2555,26 +2583,21 @@ function PricingSection({
2555
2583
  defaultCadence,
2556
2584
  onSelectPlan,
2557
2585
  pendingPlanName,
2558
- priceEffect
2586
+ priceEffect,
2587
+ surface
2559
2588
  }) {
2560
- const [annual, setAnnual] = React20.useState(false);
2589
+ const [annual, setAnnual] = React21.useState(false);
2561
2590
  const isOneTime = mode === "one-time";
2562
2591
  const useCadences = !!cadences?.length;
2563
2592
  const initialCadence = (defaultCadence && cadences?.some((c) => c.key === defaultCadence) ? defaultCadence : null) ?? cadences?.[0]?.key ?? "";
2564
- const [activeCadence, setActiveCadence] = React20.useState(initialCadence);
2593
+ const [activeCadence, setActiveCadence] = React21.useState(initialCadence);
2565
2594
  const cadence = cadences?.find((c) => c.key === activeCadence);
2566
- const saveBadges = React20.useMemo(
2595
+ const saveBadges = React21.useMemo(
2567
2596
  () => useCadences ? computeSaveBadges(plans, cadences, initialCadence) : {},
2568
2597
  [useCadences, plans, cadences, initialCadence]
2569
2598
  );
2570
2599
  const showToggle = useCadences ? cadences.length > 1 : !isOneTime;
2571
- const uiMode = useUIVariant();
2572
- const sectionClasses = cn$1(
2573
- "overflow-hidden bg-card",
2574
- uiMode === "smooth" && "rounded-3xl border",
2575
- uiMode === "playful" && "rounded-2xl border-primary/25 border",
2576
- !uiMode && "rounded-2xl border"
2577
- );
2600
+ const sectionClasses = useSectionSurface(surface);
2578
2601
  return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-5xl", children: [
2579
2602
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
2580
2603
  badge && (typeof badge === "string" ? /* @__PURE__ */ jsx(Badge$1, { variant: "secondary", className: "mb-4", children: badge }) : /* @__PURE__ */ jsx("div", { className: "mb-4", children: badge })),
@@ -2729,15 +2752,10 @@ function TestimonialsSection({
2729
2752
  title = "Trusted by teams shipping real products",
2730
2753
  description = "Here's what engineers and product teams say after using Olwiba in production.",
2731
2754
  badge = "Testimonials",
2732
- testimonials
2755
+ testimonials,
2756
+ surface
2733
2757
  }) {
2734
- const mode = useUIVariant();
2735
- const sectionClasses = cn$1(
2736
- "overflow-hidden bg-card",
2737
- mode === "smooth" && "rounded-3xl border",
2738
- mode === "playful" && "rounded-2xl border-primary/25 border",
2739
- !mode && "rounded-2xl border"
2740
- );
2758
+ const sectionClasses = useSectionSurface(surface);
2741
2759
  return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-5xl", children: [
2742
2760
  /* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
2743
2761
  /* @__PURE__ */ jsx(StaggerChildren, { className: "mt-12 columns-1 gap-4 sm:columns-2 lg:columns-3", children: testimonials.map((t) => /* @__PURE__ */ jsx(
@@ -2791,15 +2809,10 @@ function TeamSection({
2791
2809
  members = defaultTeam,
2792
2810
  badge = "Team",
2793
2811
  title = "The people behind Olwiba",
2794
- description = "A small team with deep experience in design systems, open source, and developer tooling."
2812
+ description = "A small team with deep experience in design systems, open source, and developer tooling.",
2813
+ surface
2795
2814
  }) {
2796
- const mode = useUIVariant();
2797
- const sectionClasses = cn$1(
2798
- "overflow-hidden bg-card",
2799
- mode === "smooth" && "rounded-3xl border",
2800
- mode === "playful" && "rounded-2xl border-primary/25 border",
2801
- !mode && "rounded-2xl border"
2802
- );
2815
+ const sectionClasses = useSectionSurface(surface);
2803
2816
  return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-5xl", children: [
2804
2817
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
2805
2818
  /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "mb-4", children: badge }),
@@ -2830,15 +2843,10 @@ function FaqSection({
2830
2843
  title = "Frequently asked questions",
2831
2844
  description = "Everything you need to know before getting started.",
2832
2845
  badge = "FAQ",
2833
- items
2846
+ items,
2847
+ surface
2834
2848
  }) {
2835
- const mode = useUIVariant();
2836
- const sectionClasses = cn$1(
2837
- "overflow-hidden bg-card",
2838
- mode === "smooth" && "rounded-3xl border",
2839
- mode === "playful" && "rounded-2xl border-primary/25 border",
2840
- !mode && "rounded-2xl border"
2841
- );
2849
+ const sectionClasses = useSectionSurface(surface);
2842
2850
  return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-3xl", children: [
2843
2851
  /* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
2844
2852
  /* @__PURE__ */ jsx(FadeIn, { direction: "up", children: /* @__PURE__ */ jsx(Accordion, { type: "single", collapsible: true, className: "mt-10 w-full", children: items.map((item, i) => /* @__PURE__ */ jsxs(AccordionItem, { value: `item-${i}`, children: [
@@ -2858,10 +2866,10 @@ function CountUp({
2858
2866
  className,
2859
2867
  ...props
2860
2868
  }) {
2861
- const ref = React20.useRef(null);
2862
- const [value, setValue] = React20.useState(from);
2863
- const hasStarted = React20.useRef(false);
2864
- React20.useEffect(() => {
2869
+ const ref = React21.useRef(null);
2870
+ const [value, setValue] = React21.useState(from);
2871
+ const hasStarted = React21.useRef(false);
2872
+ React21.useEffect(() => {
2865
2873
  const el = ref.current;
2866
2874
  if (!el) return;
2867
2875
  const observer = new IntersectionObserver(
@@ -2907,15 +2915,10 @@ function StatsSection({
2907
2915
  title = "Built for scale, used in production",
2908
2916
  description,
2909
2917
  badge = "By the numbers",
2910
- stats
2918
+ stats,
2919
+ surface
2911
2920
  }) {
2912
- const mode = useUIVariant();
2913
- const sectionClasses = cn$1(
2914
- "overflow-hidden bg-card",
2915
- mode === "smooth" && "rounded-3xl border",
2916
- mode === "playful" && "rounded-2xl border-primary/25 border",
2917
- !mode && "rounded-2xl border"
2918
- );
2921
+ const sectionClasses = useSectionSurface(surface);
2919
2922
  return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsxs("div", { className: "relative px-6 py-14 sm:px-10 sm:py-20", children: [
2920
2923
  /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-[radial-gradient(ellipse_at_bottom,hsl(var(--primary)/0.08),transparent_60%)]" }),
2921
2924
  /* @__PURE__ */ jsxs("div", { className: "relative mx-auto max-w-4xl", children: [
@@ -2952,17 +2955,12 @@ function NewsletterSection({
2952
2955
  privacyLabel = defaults.privacyLabel,
2953
2956
  successTitle = defaults.successTitle,
2954
2957
  successDescription = defaults.successDescription,
2955
- onSubscribe
2958
+ onSubscribe,
2959
+ surface
2956
2960
  } = {}) {
2957
- const [email, setEmail] = React20.useState("");
2958
- const [submitted, setSubmitted] = React20.useState(false);
2959
- const mode = useUIVariant();
2960
- const sectionClasses = cn$1(
2961
- "overflow-hidden bg-card",
2962
- mode === "smooth" && "rounded-3xl border",
2963
- mode === "playful" && "rounded-2xl border-primary/25 border",
2964
- !mode && "rounded-2xl border"
2965
- );
2961
+ const [email, setEmail] = React21.useState("");
2962
+ const [submitted, setSubmitted] = React21.useState(false);
2963
+ const sectionClasses = useSectionSurface(surface);
2966
2964
  async function handleSubmit(e) {
2967
2965
  e.preventDefault();
2968
2966
  if (!email) return;
@@ -3044,16 +3042,11 @@ function ContactSection({
3044
3042
  successTitle = defaults2.successTitle,
3045
3043
  successDescription = defaults2.successDescription,
3046
3044
  sendAnotherLabel = defaults2.sendAnotherLabel,
3047
- onSubmit
3045
+ onSubmit,
3046
+ surface
3048
3047
  } = {}) {
3049
- const [submitted, setSubmitted] = React20.useState(false);
3050
- const mode = useUIVariant();
3051
- const sectionClasses = cn$1(
3052
- "overflow-hidden bg-card",
3053
- mode === "smooth" && "rounded-3xl border",
3054
- mode === "playful" && "rounded-2xl border-primary/25 border",
3055
- !mode && "rounded-2xl border"
3056
- );
3048
+ const [submitted, setSubmitted] = React21.useState(false);
3049
+ const sectionClasses = useSectionSurface(surface);
3057
3050
  async function handleSubmit(e) {
3058
3051
  e.preventDefault();
3059
3052
  await onSubmit?.(e);
@@ -3237,15 +3230,10 @@ function ComparisonSection({
3237
3230
  badge = "The math",
3238
3231
  title = "The math is simple",
3239
3232
  description,
3240
- columns
3233
+ columns,
3234
+ surface
3241
3235
  }) {
3242
- const mode = useUIVariant();
3243
- const sectionClasses = cn$1(
3244
- "overflow-hidden bg-card",
3245
- mode === "smooth" && "rounded-3xl border",
3246
- mode === "playful" && "rounded-2xl border-primary/25 border",
3247
- !mode && "rounded-2xl border"
3248
- );
3236
+ const sectionClasses = useSectionSurface(surface);
3249
3237
  return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
3250
3238
  /* @__PURE__ */ jsx(SectionTitle, { badge, title, description }),
3251
3239
  /* @__PURE__ */ jsx(StaggerChildren, { className: "mt-12 grid gap-4 sm:grid-cols-3", children: columns.map((col) => /* @__PURE__ */ jsxs(
@@ -3293,15 +3281,10 @@ function QualificationSection({
3293
3281
  badge = "Who it is for",
3294
3282
  title = "Is this for you?",
3295
3283
  description,
3296
- columns
3284
+ columns,
3285
+ surface
3297
3286
  }) {
3298
- const mode = useUIVariant();
3299
- const sectionClasses = cn$1(
3300
- "overflow-hidden bg-card",
3301
- mode === "smooth" && "rounded-3xl border",
3302
- mode === "playful" && "rounded-2xl border-primary/25 border",
3303
- !mode && "rounded-2xl border"
3304
- );
3287
+ const sectionClasses = useSectionSurface(surface);
3305
3288
  return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
3306
3289
  /* @__PURE__ */ jsx(SectionTitle, { badge, title, description }),
3307
3290
  /* @__PURE__ */ jsx(FadeIn, { direction: "up", className: "mt-12 grid gap-6 sm:grid-cols-2", children: columns.map((col) => {
@@ -3344,10 +3327,10 @@ function Navbar({
3344
3327
  controls,
3345
3328
  renderLink = defaultRenderLink7
3346
3329
  }) {
3347
- const [open, setOpen] = React20.useState(false);
3330
+ const [open, setOpen] = React21.useState(false);
3348
3331
  const brandHref = brand.href ?? "/";
3349
3332
  const hasRightContent = controls?.length || cta?.primary || cta?.secondary;
3350
- const closeMobileMenu = React20.useCallback(() => setOpen(false), []);
3333
+ const closeMobileMenu = React21.useCallback(() => setOpen(false), []);
3351
3334
  return /* @__PURE__ */ jsx("section", { className: "overflow-hidden rounded-2xl border bg-card", children: /* @__PURE__ */ jsxs("nav", { className: "grid h-16 grid-cols-[1fr_auto_1fr] items-center px-6", children: [
3352
3335
  renderLink({
3353
3336
  href: brandHref,
@@ -3362,7 +3345,7 @@ function Navbar({
3362
3345
  children: link.label
3363
3346
  }) }, link.label)) }),
3364
3347
  hasRightContent && /* @__PURE__ */ jsxs("div", { className: "hidden items-center justify-end gap-2 md:flex", children: [
3365
- controls?.map((control, i) => /* @__PURE__ */ jsx(React20.Fragment, { children: control }, i)),
3348
+ controls?.map((control, i) => /* @__PURE__ */ jsx(React21.Fragment, { children: control }, i)),
3366
3349
  (cta?.secondary || cta?.primary) && controls?.length ? /* @__PURE__ */ jsx("div", { className: "mx-1 h-4 w-px bg-border" }) : null,
3367
3350
  cta?.secondary && renderLink({
3368
3351
  href: cta.secondary.href,
@@ -3375,7 +3358,7 @@ function Navbar({
3375
3358
  ] }),
3376
3359
  /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
3377
3360
  /* @__PURE__ */ jsxs("div", { className: "col-start-3 flex items-center justify-end gap-1 md:hidden", children: [
3378
- controls?.map((control, i) => /* @__PURE__ */ jsx(React20.Fragment, { children: control }, i)),
3361
+ controls?.map((control, i) => /* @__PURE__ */ jsx(React21.Fragment, { children: control }, i)),
3379
3362
  /* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button$1, { variant: "ghost", size: "icon", children: [
3380
3363
  /* @__PURE__ */ jsx(Menu, { className: "size-5" }),
3381
3364
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Open menu" })
@@ -3537,7 +3520,7 @@ function LogoStrip({
3537
3520
  ] });
3538
3521
  }
3539
3522
  function GridUnderlay({ variant, size = 24, className, ...props }) {
3540
- const id = React20.useId();
3523
+ const id = React21.useId();
3541
3524
  const pattern = variant === "dots" ? /* @__PURE__ */ jsx("circle", { cx: size / 2, cy: size / 2, r: 1, fill: "currentColor" }) : variant === "lines" ? /* @__PURE__ */ jsx("path", { d: `M ${size} 0 L 0 0 0 ${size}`, fill: "none", stroke: "currentColor", strokeWidth: 0.5 }) : /* @__PURE__ */ jsxs(Fragment, { children: [
3542
3525
  /* @__PURE__ */ jsx("line", { x1: size / 2, y1: 0, x2: size / 2, y2: size, stroke: "currentColor", strokeWidth: 0.5 }),
3543
3526
  /* @__PURE__ */ jsx("line", { x1: 0, y1: size / 2, x2: size, y2: size / 2, stroke: "currentColor", strokeWidth: 0.5 })
@@ -3565,9 +3548,9 @@ function GlowUnderlay({
3565
3548
  style,
3566
3549
  ...props
3567
3550
  }) {
3568
- const [pos, setPos] = React20.useState({ x: "50%", y: "50%" });
3569
- const containerRef = React20.useRef(null);
3570
- React20.useEffect(() => {
3551
+ const [pos, setPos] = React21.useState({ x: "50%", y: "50%" });
3552
+ const containerRef = React21.useRef(null);
3553
+ React21.useEffect(() => {
3571
3554
  if (!followCursor) return;
3572
3555
  const handleMouseMove = (e) => {
3573
3556
  const el = containerRef.current;
@@ -3706,8 +3689,8 @@ function PageTransition({
3706
3689
  style,
3707
3690
  ...props
3708
3691
  }) {
3709
- const [mounted, setMounted] = React20.useState(false);
3710
- React20.useEffect(() => {
3692
+ const [mounted, setMounted] = React21.useState(false);
3693
+ React21.useEffect(() => {
3711
3694
  const id = requestAnimationFrame(() => setMounted(true));
3712
3695
  return () => cancelAnimationFrame(id);
3713
3696
  }, []);
@@ -3782,7 +3765,7 @@ function Sortable({
3782
3765
  if (oldIndex === -1 || newIndex === -1) return;
3783
3766
  onReorder(arrayMove(items, oldIndex, newIndex));
3784
3767
  };
3785
- const childArray = React20.Children.toArray(children);
3768
+ const childArray = React21.Children.toArray(children);
3786
3769
  return /* @__PURE__ */ jsx(DndContext, { sensors, collisionDetection: closestCenter, onDragEnd: handleDragEnd, children: /* @__PURE__ */ jsx(SortableContext, { items, strategy: strategies[direction], children: /* @__PURE__ */ jsx("div", { className: cn$1(containerClasses[direction], className), children: childArray.map(
3787
3770
  (child, i) => items[i] === void 0 ? null : /* @__PURE__ */ jsx(SortableItem, { id: items[i], disabled, className: itemClassName, children: child }, items[i])
3788
3771
  ) }) }) });
@@ -3794,8 +3777,8 @@ function Spotlight({
3794
3777
  triggerClassName,
3795
3778
  shortcut = "\u2318K"
3796
3779
  }) {
3797
- const [open, setOpen] = React20.useState(false);
3798
- React20.useEffect(() => {
3780
+ const [open, setOpen] = React21.useState(false);
3781
+ React21.useEffect(() => {
3799
3782
  const down = (e) => {
3800
3783
  if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
3801
3784
  e.preventDefault();
@@ -3825,7 +3808,7 @@ function Spotlight({
3825
3808
  /* @__PURE__ */ jsx(CommandInput, { placeholder }),
3826
3809
  /* @__PURE__ */ jsxs(CommandList, { children: [
3827
3810
  /* @__PURE__ */ jsx(CommandEmpty, { children: "No results found." }),
3828
- groups.map((group, i) => /* @__PURE__ */ jsxs(React20.Fragment, { children: [
3811
+ groups.map((group, i) => /* @__PURE__ */ jsxs(React21.Fragment, { children: [
3829
3812
  i > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
3830
3813
  /* @__PURE__ */ jsx(CommandGroup, { heading: group.heading, children: group.items.map((item) => /* @__PURE__ */ jsxs(
3831
3814
  CommandItem,
@@ -3850,8 +3833,8 @@ function Spotlight({
3850
3833
  var BASE = 40;
3851
3834
  var MAGNIFY_RADIUS = 80;
3852
3835
  function Dock({ items, iconSize = BASE, magnification = 1.7, className, ...props }) {
3853
- const [mouseX, setMouseX] = React20.useState(null);
3854
- const containerRef = React20.useRef(null);
3836
+ const [mouseX, setMouseX] = React21.useState(null);
3837
+ const containerRef = React21.useRef(null);
3855
3838
  function getScale(index) {
3856
3839
  if (mouseX === null || !containerRef.current) return 1;
3857
3840
  const container = containerRef.current;
@@ -3950,7 +3933,7 @@ function ConfirmDialog({ isOpen, options, handleConfirm, handleCancel, destructi
3950
3933
  ] }) });
3951
3934
  }
3952
3935
  function RegisterHotkeys({ hotkeys }) {
3953
- React20.useEffect(() => {
3936
+ React21.useEffect(() => {
3954
3937
  const handleKeyDown = (event) => {
3955
3938
  for (const hotkey of hotkeys) {
3956
3939
  const matches = event.key.toLowerCase() === hotkey.key.toLowerCase() && !!event.ctrlKey === !!hotkey.ctrl && !!event.metaKey === !!hotkey.meta && !!event.shiftKey === !!hotkey.shift && !!event.altKey === !!hotkey.alt;
@@ -3967,10 +3950,10 @@ function RegisterHotkeys({ hotkeys }) {
3967
3950
  return null;
3968
3951
  }
3969
3952
  function useControlledOpen(defaultOpen = false) {
3970
- const [isOpen, setIsOpen] = React20.useState(defaultOpen);
3971
- const open = React20.useCallback(() => setIsOpen(true), []);
3972
- const close = React20.useCallback(() => setIsOpen(false), []);
3973
- const toggle = React20.useCallback(() => setIsOpen((prev) => !prev), []);
3953
+ const [isOpen, setIsOpen] = React21.useState(defaultOpen);
3954
+ const open = React21.useCallback(() => setIsOpen(true), []);
3955
+ const close = React21.useCallback(() => setIsOpen(false), []);
3956
+ const toggle = React21.useCallback(() => setIsOpen((prev) => !prev), []);
3974
3957
  return { isOpen, open, close, toggle, setIsOpen };
3975
3958
  }
3976
3959
  function CommandMenu({
@@ -3983,7 +3966,7 @@ function CommandMenu({
3983
3966
  }) {
3984
3967
  const internal = useControlledOpen(false);
3985
3968
  const isOpen = openProp ?? internal.isOpen;
3986
- const setOpen = React20.useCallback(
3969
+ const setOpen = React21.useCallback(
3987
3970
  (next) => {
3988
3971
  if (openProp === void 0) internal.setIsOpen(next);
3989
3972
  onOpenChange?.(next);
@@ -4008,7 +3991,7 @@ function CommandMenu({
4008
3991
  /* @__PURE__ */ jsx(CommandInput, { placeholder }),
4009
3992
  /* @__PURE__ */ jsxs(CommandList, { children: [
4010
3993
  /* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
4011
- groups.map((group, i) => /* @__PURE__ */ jsxs(React20.Fragment, { children: [
3994
+ groups.map((group, i) => /* @__PURE__ */ jsxs(React21.Fragment, { children: [
4012
3995
  i > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
4013
3996
  /* @__PURE__ */ jsx(CommandGroup, { heading: group.heading, children: group.items.map((item) => /* @__PURE__ */ jsxs(
4014
3997
  CommandItem,
@@ -4063,7 +4046,7 @@ function DataView({
4063
4046
  }
4064
4047
  );
4065
4048
  }
4066
- return /* @__PURE__ */ jsx(AppGrid, { columns: gridColumns, gap, className: cn$1(className), children: items.map((item) => /* @__PURE__ */ jsx(React20.Fragment, { children: renderCard(item) }, getRowId(item))) });
4049
+ return /* @__PURE__ */ jsx(AppGrid, { columns: gridColumns, gap, className: cn$1(className), children: items.map((item) => /* @__PURE__ */ jsx(React21.Fragment, { children: renderCard(item) }, getRowId(item))) });
4067
4050
  }
4068
4051
  var TOKEN_COLORS = ["var(--chart-1)", "var(--chart-2)", "var(--chart-3)", "var(--chart-4)", "var(--chart-5)"];
4069
4052
  var seriesColor = (s, i) => s.color ?? TOKEN_COLORS[i % TOKEN_COLORS.length];
@@ -4237,20 +4220,20 @@ function FileUpload({
4237
4220
  hint,
4238
4221
  className
4239
4222
  }) {
4240
- const [internalFiles, setInternalFiles] = React20.useState(defaultFiles ?? []);
4241
- const [isDragging, setIsDragging] = React20.useState(false);
4242
- const [validationError, setValidationError] = React20.useState(null);
4243
- const inputRef = React20.useRef(null);
4244
- const dragDepth = React20.useRef(0);
4223
+ const [internalFiles, setInternalFiles] = React21.useState(defaultFiles ?? []);
4224
+ const [isDragging, setIsDragging] = React21.useState(false);
4225
+ const [validationError, setValidationError] = React21.useState(null);
4226
+ const inputRef = React21.useRef(null);
4227
+ const dragDepth = React21.useRef(0);
4245
4228
  const files = filesProp ?? internalFiles;
4246
- const setFiles = React20.useCallback(
4229
+ const setFiles = React21.useCallback(
4247
4230
  (next) => {
4248
4231
  if (!filesProp) setInternalFiles(next);
4249
4232
  onFilesChange?.(next);
4250
4233
  },
4251
4234
  [filesProp, onFilesChange]
4252
4235
  );
4253
- const acceptList = React20.useMemo(
4236
+ const acceptList = React21.useMemo(
4254
4237
  () => accept?.split(",").map((a) => a.trim().toLowerCase()).filter(Boolean) ?? [],
4255
4238
  [accept]
4256
4239
  );
@@ -4974,7 +4957,7 @@ function PageHeader({
4974
4957
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1 pb-6", className), children: [
4975
4958
  breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-2 flex items-center gap-1 text-sm text-muted-foreground", children: breadcrumbs.map((crumb, i) => {
4976
4959
  const isLast = i === breadcrumbs.length - 1;
4977
- return /* @__PURE__ */ jsxs(React20.Fragment, { children: [
4960
+ return /* @__PURE__ */ jsxs(React21.Fragment, { children: [
4978
4961
  i > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5 shrink-0" }),
4979
4962
  isLast || !crumb.href ? /* @__PURE__ */ jsx("span", { className: cn(isLast && "text-foreground font-medium"), children: crumb.label }) : renderLink({
4980
4963
  href: crumb.href,
@@ -5010,7 +4993,7 @@ function PageHeader({
5010
4993
  ] });
5011
4994
  }
5012
4995
  function Suspensed({ children, fallback }) {
5013
- return /* @__PURE__ */ jsx(React20.Suspense, { fallback: fallback ?? /* @__PURE__ */ jsx(Spinner, {}), children });
4996
+ return /* @__PURE__ */ jsx(React21.Suspense, { fallback: fallback ?? /* @__PURE__ */ jsx(Spinner, {}), children });
5014
4997
  }
5015
4998
  function getInitialTheme() {
5016
4999
  if (typeof document === "undefined") return "dark";
@@ -5018,7 +5001,7 @@ function getInitialTheme() {
5018
5001
  return stored ?? (document.documentElement.classList.contains("dark") ? "dark" : "light");
5019
5002
  }
5020
5003
  function ThemeSwitchMinimal() {
5021
- const [theme, setThemeState] = React20.useState(getInitialTheme);
5004
+ const [theme, setThemeState] = React21.useState(getInitialTheme);
5022
5005
  const toggle = () => {
5023
5006
  const next = theme === "dark" ? "light" : "dark";
5024
5007
  setThemeState(next);
@@ -5144,9 +5127,9 @@ function getInitialColorName() {
5144
5127
  return localStorage.getItem(STORAGE_KEY) ?? "emerald";
5145
5128
  }
5146
5129
  function BrandColorSwitchMinimal() {
5147
- const [active, setActive] = React20.useState(getInitialColorName);
5148
- const [open, setOpen] = React20.useState(false);
5149
- React20.useEffect(() => {
5130
+ const [active, setActive] = React21.useState(getInitialColorName);
5131
+ const [open, setOpen] = React21.useState(false);
5132
+ React21.useEffect(() => {
5150
5133
  const saved = localStorage.getItem(STORAGE_KEY) ?? "emerald";
5151
5134
  const color = BRAND_COLORS.find((c) => c.name === saved);
5152
5135
  if (color) applyColor(color);
@@ -5207,7 +5190,7 @@ function BrandColorSwitchMinimal() {
5207
5190
  ] });
5208
5191
  }
5209
5192
  function ThemeColorUpdater({ colorTheme }) {
5210
- React20.useEffect(() => {
5193
+ React21.useEffect(() => {
5211
5194
  if (colorTheme) {
5212
5195
  document.documentElement.setAttribute("data-theme", colorTheme);
5213
5196
  } else {
@@ -5217,7 +5200,7 @@ function ThemeColorUpdater({ colorTheme }) {
5217
5200
  return null;
5218
5201
  }
5219
5202
  function VersionBanner({ version, message, className, onDismiss }) {
5220
- const [dismissed, setDismissed] = React20.useState(false);
5203
+ const [dismissed, setDismissed] = React21.useState(false);
5221
5204
  if (dismissed) return null;
5222
5205
  return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-4 bg-primary/10 px-4 py-2 text-sm", className), children: [
5223
5206
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
@@ -5474,29 +5457,29 @@ function useMounted() {
5474
5457
  return mounted;
5475
5458
  }
5476
5459
  function useConfirm() {
5477
- const [isOpen, setIsOpen] = React20.useState(false);
5478
- const [options, setOptions] = React20.useState({});
5479
- const resolveRef = React20.useRef(null);
5480
- const confirm = React20.useCallback((opts = {}) => {
5460
+ const [isOpen, setIsOpen] = React21.useState(false);
5461
+ const [options, setOptions] = React21.useState({});
5462
+ const resolveRef = React21.useRef(null);
5463
+ const confirm = React21.useCallback((opts = {}) => {
5481
5464
  setOptions(opts);
5482
5465
  setIsOpen(true);
5483
5466
  return new Promise((resolve) => {
5484
5467
  resolveRef.current = resolve;
5485
5468
  });
5486
5469
  }, []);
5487
- const handleConfirm = React20.useCallback(() => {
5470
+ const handleConfirm = React21.useCallback(() => {
5488
5471
  resolveRef.current?.(true);
5489
5472
  setIsOpen(false);
5490
5473
  }, []);
5491
- const handleCancel = React20.useCallback(() => {
5474
+ const handleCancel = React21.useCallback(() => {
5492
5475
  resolveRef.current?.(false);
5493
5476
  setIsOpen(false);
5494
5477
  }, []);
5495
5478
  return { confirm, isOpen, options, handleConfirm, handleCancel };
5496
5479
  }
5497
5480
  function useScrolledPast(threshold) {
5498
- const [scrolledPast, setScrolledPast] = React20.useState(false);
5499
- React20.useEffect(() => {
5481
+ const [scrolledPast, setScrolledPast] = React21.useState(false);
5482
+ React21.useEffect(() => {
5500
5483
  const handleScroll = () => {
5501
5484
  setScrolledPast(window.scrollY > threshold);
5502
5485
  };
@@ -5507,28 +5490,28 @@ function useScrolledPast(threshold) {
5507
5490
  return scrolledPast;
5508
5491
  }
5509
5492
  function useCopyToClipboard() {
5510
- const [copied, setCopied] = React20.useState(false);
5511
- const timeoutRef = React20.useRef(void 0);
5512
- const copy = React20.useCallback((text) => {
5493
+ const [copied, setCopied] = React21.useState(false);
5494
+ const timeoutRef = React21.useRef(void 0);
5495
+ const copy = React21.useCallback((text) => {
5513
5496
  navigator.clipboard.writeText(text).then(() => {
5514
5497
  setCopied(true);
5515
5498
  clearTimeout(timeoutRef.current);
5516
5499
  timeoutRef.current = setTimeout(() => setCopied(false), 2e3);
5517
5500
  });
5518
5501
  }, []);
5519
- React20.useEffect(() => () => clearTimeout(timeoutRef.current), []);
5502
+ React21.useEffect(() => () => clearTimeout(timeoutRef.current), []);
5520
5503
  return [copied, copy];
5521
5504
  }
5522
5505
  function useDebounce(value, delay) {
5523
- const [debounced, setDebounced] = React20.useState(value);
5524
- React20.useEffect(() => {
5506
+ const [debounced, setDebounced] = React21.useState(value);
5507
+ React21.useEffect(() => {
5525
5508
  const timer = setTimeout(() => setDebounced(value), delay);
5526
5509
  return () => clearTimeout(timer);
5527
5510
  }, [value, delay]);
5528
5511
  return debounced;
5529
5512
  }
5530
5513
  function useLocalStorage(key, initialValue) {
5531
- const [storedValue, setStoredValue] = React20.useState(() => {
5514
+ const [storedValue, setStoredValue] = React21.useState(() => {
5532
5515
  if (typeof window === "undefined") return initialValue;
5533
5516
  try {
5534
5517
  const item = window.localStorage.getItem(key);
@@ -5537,7 +5520,7 @@ function useLocalStorage(key, initialValue) {
5537
5520
  return initialValue;
5538
5521
  }
5539
5522
  });
5540
- const setValue = React20.useCallback(
5523
+ const setValue = React21.useCallback(
5541
5524
  (value) => {
5542
5525
  try {
5543
5526
  setStoredValue(value);
@@ -5559,11 +5542,11 @@ function useViewMode(key = "view-mode", fallback = "cards") {
5559
5542
  return { view: mounted ? stored : fallback, setView: setStored, ready: mounted };
5560
5543
  }
5561
5544
  function useMediaQuery(query) {
5562
- const [matches, setMatches] = React20.useState(() => {
5545
+ const [matches, setMatches] = React21.useState(() => {
5563
5546
  if (typeof window === "undefined") return false;
5564
5547
  return window.matchMedia(query).matches;
5565
5548
  });
5566
- React20.useEffect(() => {
5549
+ React21.useEffect(() => {
5567
5550
  if (typeof window === "undefined") return;
5568
5551
  const mql = window.matchMedia(query);
5569
5552
  setMatches(mql.matches);
@@ -5574,18 +5557,18 @@ function useMediaQuery(query) {
5574
5557
  return matches;
5575
5558
  }
5576
5559
  function usePagination(total, pageSize) {
5577
- const [page, setPage] = React20.useState(1);
5560
+ const [page, setPage] = React21.useState(1);
5578
5561
  const totalPages = Math.max(1, Math.ceil(total / pageSize));
5579
5562
  const offset = (page - 1) * pageSize;
5580
- const goTo = React20.useCallback(
5563
+ const goTo = React21.useCallback(
5581
5564
  (p) => setPage(Math.min(Math.max(1, p), totalPages)),
5582
5565
  [totalPages]
5583
5566
  );
5584
- const next = React20.useCallback(() => goTo(page + 1), [page, goTo]);
5585
- const prev = React20.useCallback(() => goTo(page - 1), [page, goTo]);
5567
+ const next = React21.useCallback(() => goTo(page + 1), [page, goTo]);
5568
+ const prev = React21.useCallback(() => goTo(page - 1), [page, goTo]);
5586
5569
  return { page, pageSize, totalPages, offset, hasPrev: page > 1, hasNext: page < totalPages, goTo, next, prev };
5587
5570
  }
5588
5571
 
5589
- export { ActivityFeed, AnimatedPill, AnimatedSwap, AppContent, AppGrid, AppGridCell, AppPageHero, AppScreen, AppShell, AuthSection, Badge, BillingPanel, BrandColorSwitchMinimal, Button, Card, Carousel, ChangelogCard, ChangelogList, Chart, Checkbox, CommandMenu, ComparisonSection, ConfirmDialog, ContactSection, ContextMenu, CountUp, CountdownTimer, CtaSection, DataTable, DataView, DevBanner, Dock, EmptyState, ErrorPage, FadeIn, FaqSection, FeatureCard, FeatureMarqueeSection, FeaturesSection, FileUpload, FlowBracket, FlowConnector, Footer, FullPageSpinner, GlassCard, Grid, GridItem, GroupedFeaturesSection, HeroSection, ImageCard, Input, LogoStrip, MediaCard, ModeSwitchMinimal, Navbar, NewsletterSection, NotificationToast, NotificationsPopover, OlwibaUIProvider, OnboardingWizard, Overlay, PageHeader, PageTransition, PhoneFrame, PostCard, PostList, PricingCard, PricingSection, PublicPageFrame, QualificationSection, RegisterHotkeys, RootErrorFallback, Section, SectionTitle, SettingsSection, Sortable, Spotlight, Stack, StaggerChildren, StatCard, StatsSection, StepsSection, Suspensed, Switch, TeamMembersPanel, TeamSection, TechStackSection, TestimonialCard, TestimonialsSection, Textarea, ThemeColorUpdater, ThemeSwitchMinimal, Underlay, UpdateBanner, UpgradePrompt, VersionBanner, ViewToggle, marketingSectionSpacing, notify, useConfirm, useControlledOpen, useCopyToClipboard, useDebounce, useIntersectionObserver, useLocalStorage, useMediaQuery, useMounted, useOlwibaUI, usePagination, useScrolledPast, useUIMode, useViewMode };
5572
+ export { ActivityFeed, AnimatedPill, AnimatedSwap, AppContent, AppGrid, AppGridCell, AppPageHero, AppScreen, AppShell, AuthSection, Badge, BillingPanel, BrandColorSwitchMinimal, Button, Card, Carousel, ChangelogCard, ChangelogList, Chart, Checkbox, CommandMenu, ComparisonSection, ConfirmDialog, ContactSection, ContextMenu, CountUp, CountdownTimer, CtaSection, DataTable, DataView, DevBanner, Dock, EmptyState, ErrorPage, FadeIn, FaqSection, FeatureCard, FeatureMarqueeSection, FeaturesSection, FileUpload, FlowBracket, FlowConnector, Footer, FullPageSpinner, GlassCard, Grid, GridItem, GroupedFeaturesSection, HeroSection, ImageCard, Input, LogoStrip, MarketingSurfaceProvider, MediaCard, ModeSwitchMinimal, Navbar, NewsletterSection, NotificationToast, NotificationsPopover, OlwibaUIProvider, OnboardingWizard, Overlay, PageHeader, PageTransition, PhoneFrame, PostCard, PostList, PricingCard, PricingSection, PublicPageFrame, QualificationSection, RegisterHotkeys, RootErrorFallback, Section, SectionTitle, SettingsSection, Sortable, Spotlight, Stack, StaggerChildren, StatCard, StatsSection, StepsSection, Suspensed, Switch, TeamMembersPanel, TeamSection, TechStackSection, TestimonialCard, TestimonialsSection, Textarea, ThemeColorUpdater, ThemeSwitchMinimal, Underlay, UpdateBanner, UpgradePrompt, VersionBanner, ViewToggle, marketingSectionSpacing, notify, useConfirm, useControlledOpen, useCopyToClipboard, useDebounce, useIntersectionObserver, useLocalStorage, useMarketingSurface, useMediaQuery, useMounted, useOlwibaUI, usePagination, useScrolledPast, useSectionSurface, useUIMode, useViewMode };
5590
5573
  //# sourceMappingURL=index.js.map
5591
5574
  //# sourceMappingURL=index.js.map