@olwiba/ui 0.2.3 → 0.2.5

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 React32 from 'react';
3
+ import * as React34 from 'react';
4
4
  import { useRef, useEffect, useState } 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, Sidebar, SidebarHeader, SidebarMenu, SidebarMenuItem, SidebarMenuButton, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarFooter, SidebarTrigger, useSidebar, 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, ArrowRight, Sparkles, Minus, Quote, Star, Twitter, Github, Linkedin, Mail, MessageSquare, ChevronDown, Send, Menu, UploadCloud, File, CheckCircle2, AlertCircle, Bell, Inbox, Activity, TrendingUp, TrendingDown, Sun, Moon, Palette, AlertTriangle, Rocket, Info, Layers, LayoutGrid, 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, Sun, Moon, Palette, AlertTriangle, Rocket, Info, Layers, LayoutGrid, ShieldCheck, Building2, MoreVerticalIcon, CreditCardIcon, BellIcon, 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,7 +13,7 @@ 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 = React32.createContext({
16
+ var OlwibaUIContext = React34.createContext({
17
17
  isMobile: false,
18
18
  mode: "default",
19
19
  setMode: () => {
@@ -22,17 +22,17 @@ var OlwibaUIContext = React32.createContext({
22
22
  function OlwibaUIProvider({ children, isMobile: isMobileProp, mode: initialMode = "default" }) {
23
23
  const detectedMobile = useIsMobile();
24
24
  const isMobile = isMobileProp ?? detectedMobile;
25
- const [mode, setMode] = React32.useState(initialMode);
25
+ const [mode, setMode] = React34.useState(initialMode);
26
26
  const variant = mode !== "default" ? mode : void 0;
27
27
  return /* @__PURE__ */ jsx(OlwibaUIContext.Provider, { value: { isMobile, mode, setMode }, children: /* @__PURE__ */ jsx(UIVariantProvider, { mode: variant, children }) });
28
28
  }
29
29
  function useOlwibaUI() {
30
- return React32.useContext(OlwibaUIContext);
30
+ return React34.useContext(OlwibaUIContext);
31
31
  }
32
32
  function useUIMode() {
33
- return React32.useContext(OlwibaUIContext).mode;
33
+ return React34.useContext(OlwibaUIContext).mode;
34
34
  }
35
- var Button = React32.forwardRef(
35
+ var Button = React34.forwardRef(
36
36
  ({ mode, ...props }, ref) => {
37
37
  const ctxMode = useUIMode();
38
38
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -40,7 +40,7 @@ var Button = React32.forwardRef(
40
40
  }
41
41
  );
42
42
  Button.displayName = "Button";
43
- var Card = React32.forwardRef(
43
+ var Card = React34.forwardRef(
44
44
  ({ mode, ...props }, ref) => {
45
45
  const ctxMode = useUIMode();
46
46
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -51,7 +51,7 @@ Card.displayName = "Card";
51
51
  function Badge(props) {
52
52
  return /* @__PURE__ */ jsx(Badge$1, { ...props });
53
53
  }
54
- var Input = React32.forwardRef(
54
+ var Input = React34.forwardRef(
55
55
  ({ mode, ...props }, ref) => {
56
56
  const ctxMode = useUIMode();
57
57
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -59,7 +59,7 @@ var Input = React32.forwardRef(
59
59
  }
60
60
  );
61
61
  Input.displayName = "Input";
62
- var Textarea = React32.forwardRef(
62
+ var Textarea = React34.forwardRef(
63
63
  ({ mode, ...props }, ref) => {
64
64
  const ctxMode = useUIMode();
65
65
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -67,13 +67,13 @@ var Textarea = React32.forwardRef(
67
67
  }
68
68
  );
69
69
  Textarea.displayName = "Textarea";
70
- var Checkbox = React32.forwardRef(({ mode, ...props }, ref) => {
70
+ var Checkbox = React34.forwardRef(({ mode, ...props }, ref) => {
71
71
  const ctxMode = useUIMode();
72
72
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
73
73
  return /* @__PURE__ */ jsx(Checkbox$1, { mode: resolvedMode, ...props, ref });
74
74
  });
75
75
  Checkbox.displayName = "Checkbox";
76
- var Switch = React32.forwardRef(({ mode: _mode, ...props }, ref) => {
76
+ var Switch = React34.forwardRef(({ mode: _mode, ...props }, ref) => {
77
77
  return /* @__PURE__ */ jsx(Switch$1, { ...props, ref });
78
78
  });
79
79
  Switch.displayName = "Switch";
@@ -530,7 +530,7 @@ function DefaultForm({
530
530
  const isForgotPassword = mode === "forgot-password";
531
531
  const isResetPassword = mode === "reset-password";
532
532
  const isVerify = mode === "verify";
533
- const [code, setCode] = React32.useState("");
533
+ const [code, setCode] = React34.useState("");
534
534
  const hasPrefill = !!(defaultEmail || defaultPassword);
535
535
  const prefillStyle = (active) => active ? { animation: "auth-prefill 1.6s ease-out 0.35s 1 both" } : void 0;
536
536
  const copy = authCopy[mode];
@@ -690,10 +690,10 @@ function DataTable({
690
690
  emptyMessage = "No results.",
691
691
  className
692
692
  }) {
693
- const [sorting, setSorting] = React32.useState([]);
694
- const [rowSelection, setRowSelection] = React32.useState({});
695
- const [globalFilter, setGlobalFilter] = React32.useState("");
696
- const allColumns = React32.useMemo(
693
+ const [sorting, setSorting] = React34.useState([]);
694
+ const [rowSelection, setRowSelection] = React34.useState({});
695
+ const [globalFilter, setGlobalFilter] = React34.useState("");
696
+ const allColumns = React34.useMemo(
697
697
  () => selectable ? [selectColumn, ...columns] : columns,
698
698
  [selectable, columns]
699
699
  );
@@ -715,7 +715,7 @@ function DataTable({
715
715
  initialState: pageSize > 0 ? { pagination: { pageSize } } : void 0,
716
716
  enableRowSelection: selectable
717
717
  });
718
- React32.useEffect(() => {
718
+ React34.useEffect(() => {
719
719
  if (!onSelectionChange) return;
720
720
  onSelectionChange(table.getSelectedRowModel().rows.map((r) => r.original));
721
721
  }, [rowSelection]);
@@ -795,8 +795,8 @@ function DataTable({
795
795
  ] });
796
796
  }
797
797
  function InviteDialog({ roles, onInvite, onClose }) {
798
- const [email, setEmail] = React32.useState("");
799
- const [role, setRole] = React32.useState(roles[roles.length - 1] ?? roles[0]);
798
+ const [email, setEmail] = React34.useState("");
799
+ const [role, setRole] = React34.useState(roles[roles.length - 1] ?? roles[0]);
800
800
  return /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsxs(
801
801
  "form",
802
802
  {
@@ -840,8 +840,8 @@ function TeamMembersPanel({
840
840
  title = "Team members",
841
841
  description = "Manage who has access to this workspace."
842
842
  }) {
843
- const [inviteOpen, setInviteOpen] = React32.useState(false);
844
- const columns = React32.useMemo(() => [
843
+ const [inviteOpen, setInviteOpen] = React34.useState(false);
844
+ const columns = React34.useMemo(() => [
845
845
  {
846
846
  accessorKey: "name",
847
847
  header: "Name",
@@ -910,7 +910,7 @@ function BillingPanel({
910
910
  onUpdatePaymentMethod,
911
911
  className
912
912
  }) {
913
- const invoiceColumns = React32.useMemo(() => [
913
+ const invoiceColumns = React34.useMemo(() => [
914
914
  { accessorKey: "date", header: "Date", enableSorting: false },
915
915
  { accessorKey: "amount", header: "Amount", enableSorting: false },
916
916
  {
@@ -989,9 +989,9 @@ function OnboardingWizard({
989
989
  completeLabel = "Finish",
990
990
  className
991
991
  }) {
992
- const [internalStep, setInternalStep] = React32.useState(0);
993
- const [error, setError] = React32.useState(null);
994
- const [pending, setPending] = React32.useState(false);
992
+ const [internalStep, setInternalStep] = React34.useState(0);
993
+ const [error, setError] = React34.useState(null);
994
+ const [pending, setPending] = React34.useState(false);
995
995
  const index = stepProp ?? internalStep;
996
996
  const current = steps[index];
997
997
  const isLast = index === steps.length - 1;
@@ -1308,6 +1308,101 @@ function UpgradePrompt({
1308
1308
  }
1309
1309
  );
1310
1310
  }
1311
+ function UpdateBanner({
1312
+ currentVersion,
1313
+ fetchVersion,
1314
+ intervalMs = 5 * 60 * 1e3,
1315
+ forceShow = false,
1316
+ onRefresh,
1317
+ message = /* @__PURE__ */ jsxs(Fragment, { children: [
1318
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: "App update available!" }),
1319
+ " Refresh to get the latest features and improvements."
1320
+ ] }),
1321
+ buttonLabel = "Refresh now",
1322
+ className
1323
+ }) {
1324
+ const [show, setShow] = React34.useState(forceShow);
1325
+ const [entered, setEntered] = React34.useState(false);
1326
+ const [refreshing, setRefreshing] = React34.useState(false);
1327
+ React34.useEffect(() => {
1328
+ if (forceShow) {
1329
+ setShow(true);
1330
+ return;
1331
+ }
1332
+ setShow(false);
1333
+ let cancelled = false;
1334
+ const check = async () => {
1335
+ try {
1336
+ const server = await fetchVersion();
1337
+ if (!cancelled && server.version && server.version !== currentVersion) {
1338
+ setShow(true);
1339
+ }
1340
+ } catch {
1341
+ }
1342
+ };
1343
+ void check();
1344
+ const id = setInterval(check, intervalMs);
1345
+ return () => {
1346
+ cancelled = true;
1347
+ clearInterval(id);
1348
+ };
1349
+ }, [currentVersion, fetchVersion, forceShow, intervalMs]);
1350
+ React34.useEffect(() => {
1351
+ if (!show) {
1352
+ setEntered(false);
1353
+ return;
1354
+ }
1355
+ const id = requestAnimationFrame(() => setEntered(true));
1356
+ return () => cancelAnimationFrame(id);
1357
+ }, [show]);
1358
+ const handleRefresh = () => {
1359
+ setRefreshing(true);
1360
+ setTimeout(() => {
1361
+ if (onRefresh) {
1362
+ onRefresh();
1363
+ setRefreshing(false);
1364
+ if (forceShow) setShow(false);
1365
+ } else {
1366
+ window.location.reload();
1367
+ }
1368
+ }, 400);
1369
+ };
1370
+ if (!show) return null;
1371
+ return /* @__PURE__ */ jsx("div", { className: "pointer-events-none fixed inset-x-0 top-4 z-50 flex justify-center px-4", children: /* @__PURE__ */ jsx(
1372
+ "div",
1373
+ {
1374
+ className: cn$1(
1375
+ "pointer-events-auto transition-all duration-500 ease-out",
1376
+ entered ? "translate-y-0 opacity-100" : "-translate-y-24 opacity-0"
1377
+ ),
1378
+ children: /* @__PURE__ */ jsx(
1379
+ Card$1,
1380
+ {
1381
+ className: cn$1(
1382
+ "max-w-3xl border-amber-300/60 bg-amber-50 dark:border-amber-700/60 dark:bg-amber-950",
1383
+ className
1384
+ ),
1385
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-6 p-4", children: [
1386
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1387
+ /* @__PURE__ */ jsx(Sparkles, { className: "size-5 shrink-0 text-amber-600 dark:text-amber-400", "aria-hidden": "true" }),
1388
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-amber-800 dark:text-amber-200", children: message })
1389
+ ] }),
1390
+ /* @__PURE__ */ jsx(
1391
+ Button$1,
1392
+ {
1393
+ onClick: handleRefresh,
1394
+ disabled: refreshing,
1395
+ size: "sm",
1396
+ className: "shrink-0 bg-amber-600 text-white hover:bg-amber-700 dark:bg-amber-600 dark:hover:bg-amber-700",
1397
+ children: refreshing ? /* @__PURE__ */ jsx(RefreshCw, { className: "size-4 animate-spin" }) : buttonLabel
1398
+ }
1399
+ )
1400
+ ] })
1401
+ }
1402
+ )
1403
+ }
1404
+ ) });
1405
+ }
1311
1406
  var translateMap = {
1312
1407
  up: "translate-y-6",
1313
1408
  down: "-translate-y-6",
@@ -1325,9 +1420,9 @@ function FadeIn({
1325
1420
  style,
1326
1421
  ...props
1327
1422
  }) {
1328
- const ref = React32.useRef(null);
1329
- const [visible, setVisible] = React32.useState(false);
1330
- React32.useEffect(() => {
1423
+ const ref = React34.useRef(null);
1424
+ const [visible, setVisible] = React34.useState(false);
1425
+ React34.useEffect(() => {
1331
1426
  const el = ref.current;
1332
1427
  if (!el) return;
1333
1428
  const observer = new IntersectionObserver(
@@ -1522,16 +1617,16 @@ function Carousel({
1522
1617
  className
1523
1618
  }) {
1524
1619
  const mode = useUIVariant();
1525
- const trackRef = React32.useRef(null);
1526
- const [canPrev, setCanPrev] = React32.useState(false);
1527
- const [canNext, setCanNext] = React32.useState(true);
1528
- const updateScrollState = React32.useCallback(() => {
1620
+ const trackRef = React34.useRef(null);
1621
+ const [canPrev, setCanPrev] = React34.useState(false);
1622
+ const [canNext, setCanNext] = React34.useState(true);
1623
+ const updateScrollState = React34.useCallback(() => {
1529
1624
  const track = trackRef.current;
1530
1625
  if (!track) return;
1531
1626
  setCanPrev(track.scrollLeft > 8);
1532
1627
  setCanNext(track.scrollLeft < track.scrollWidth - track.clientWidth - 8);
1533
1628
  }, []);
1534
- React32.useEffect(() => {
1629
+ React34.useEffect(() => {
1535
1630
  const track = trackRef.current;
1536
1631
  if (!track) return;
1537
1632
  updateScrollState();
@@ -1588,7 +1683,7 @@ function Carousel({
1588
1683
  role: "region",
1589
1684
  "aria-label": ariaLabel,
1590
1685
  className: "flex snap-x snap-mandatory gap-6 overflow-x-auto pb-4 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
1591
- children: React32.Children.map(
1686
+ children: React34.Children.map(
1592
1687
  children,
1593
1688
  (child) => child == null ? null : /* @__PURE__ */ jsx("div", { "data-carousel-item": true, className: cn$1("shrink-0 snap-start", itemClassName), children: child })
1594
1689
  )
@@ -1613,9 +1708,9 @@ function StaggerChildren({
1613
1708
  className,
1614
1709
  ...props
1615
1710
  }) {
1616
- const ref = React32.useRef(null);
1617
- const [visible, setVisible] = React32.useState(false);
1618
- React32.useEffect(() => {
1711
+ const ref = React34.useRef(null);
1712
+ const [visible, setVisible] = React34.useState(false);
1713
+ React34.useEffect(() => {
1619
1714
  const el = ref.current;
1620
1715
  if (!el) return;
1621
1716
  const observer = new IntersectionObserver(
@@ -1633,7 +1728,7 @@ function StaggerChildren({
1633
1728
  return () => observer.disconnect();
1634
1729
  }, [once]);
1635
1730
  const [tx, ty] = translateMap2[direction];
1636
- return /* @__PURE__ */ jsx("div", { ref, className: cn$1(className), ...props, children: React32.Children.map(children, (child, i) => /* @__PURE__ */ jsx(
1731
+ return /* @__PURE__ */ jsx("div", { ref, className: cn$1(className), ...props, children: React34.Children.map(children, (child, i) => /* @__PURE__ */ jsx(
1637
1732
  "div",
1638
1733
  {
1639
1734
  className: "h-full",
@@ -1709,11 +1804,56 @@ function GroupedFeaturesSection({
1709
1804
  ] }, group.label)) })
1710
1805
  ] }) }) });
1711
1806
  }
1807
+ function TimelineGroup({
1808
+ steps,
1809
+ startNumber,
1810
+ fadeIn
1811
+ }) {
1812
+ const fadePx = 48;
1813
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1814
+ fadeIn && /* @__PURE__ */ jsx(
1815
+ "div",
1816
+ {
1817
+ "aria-hidden": "true",
1818
+ className: "absolute left-[19px] w-1 bg-gradient-to-b from-transparent to-primary",
1819
+ style: { top: 0, height: fadePx }
1820
+ }
1821
+ ),
1822
+ /* @__PURE__ */ jsx(
1823
+ "div",
1824
+ {
1825
+ "aria-hidden": "true",
1826
+ className: "absolute left-[19px] w-1 bg-primary",
1827
+ style: {
1828
+ top: fadeIn ? fadePx : 20,
1829
+ height: fadeIn ? `calc(100% - ${fadePx}px)` : "calc(100% - 20px)"
1830
+ }
1831
+ }
1832
+ ),
1833
+ /* @__PURE__ */ jsx(
1834
+ "div",
1835
+ {
1836
+ "aria-hidden": "true",
1837
+ className: "absolute left-[19px] w-1 bg-gradient-to-b from-primary to-transparent",
1838
+ style: { top: "100%", height: fadePx }
1839
+ }
1840
+ ),
1841
+ /* @__PURE__ */ jsx("div", { className: "space-y-10", style: fadeIn ? { paddingTop: fadePx } : void 0, children: steps.map((step, i) => /* @__PURE__ */ jsx(FadeIn, { direction: "up", delay: i * 80, children: /* @__PURE__ */ jsxs("div", { className: "relative flex gap-5", children: [
1842
+ /* @__PURE__ */ jsx("div", { className: "relative z-10 flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full border-2 border-primary bg-primary text-lg font-bold text-primary-foreground", children: step.emoji ?? startNumber + i }),
1843
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 pt-1 pb-2", children: [
1844
+ /* @__PURE__ */ jsx("h3", { className: "mb-2 text-xl font-semibold text-foreground", children: step.title }),
1845
+ /* @__PURE__ */ jsx("div", { className: "text-sm leading-relaxed text-muted-foreground", children: step.description })
1846
+ ] })
1847
+ ] }) }, step.title)) })
1848
+ ] });
1849
+ }
1712
1850
  function StepsSection({
1713
1851
  badge = "How it works",
1714
1852
  title = "From zero to shipped",
1715
1853
  description,
1716
- steps
1854
+ steps,
1855
+ variant = "default",
1856
+ groups
1717
1857
  }) {
1718
1858
  const mode = useUIVariant();
1719
1859
  const sectionClasses = cn$1(
@@ -1722,11 +1862,27 @@ function StepsSection({
1722
1862
  mode === "playful" && "rounded-2xl border-primary/25 border",
1723
1863
  !mode && "rounded-2xl border"
1724
1864
  );
1865
+ if (variant === "timeline") {
1866
+ const resolvedGroups = groups ?? (steps ? [{ steps }] : []);
1867
+ let nextNumber = 1;
1868
+ 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: [
1869
+ /* @__PURE__ */ jsx(SectionTitle, { badge, title, description, className: "text-left [&>p]:mx-0" }),
1870
+ /* @__PURE__ */ jsx("div", { className: "mt-12", children: resolvedGroups.map((group, groupIndex) => {
1871
+ const startNumber = nextNumber;
1872
+ nextNumber += group.steps.length;
1873
+ return /* @__PURE__ */ jsxs(React34.Fragment, { children: [
1874
+ /* @__PURE__ */ jsx("div", { className: cn$1(groupIndex > 0 && "mt-10"), children: /* @__PURE__ */ jsx(TimelineGroup, { steps: group.steps, startNumber, fadeIn: groupIndex > 0 }) }),
1875
+ group.after && /* @__PURE__ */ jsx("div", { className: "mt-16", children: group.after })
1876
+ ] }, groupIndex);
1877
+ }) })
1878
+ ] }) }) });
1879
+ }
1880
+ const resolvedSteps = steps ?? [];
1725
1881
  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: [
1726
1882
  /* @__PURE__ */ jsx(SectionTitle, { badge, title, description }),
1727
1883
  /* @__PURE__ */ jsxs("div", { className: "mt-12", children: [
1728
- /* @__PURE__ */ jsx("div", { className: "hidden sm:grid", style: { gridTemplateColumns: `repeat(${steps.length}, 1fr)` }, children: steps.map((step, i) => /* @__PURE__ */ jsx(FadeIn, { direction: "up", delay: i * 80, children: /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col items-center text-center px-4", children: [
1729
- i < steps.length - 1 && /* @__PURE__ */ jsx(
1884
+ /* @__PURE__ */ jsx("div", { className: "hidden sm:grid", style: { gridTemplateColumns: `repeat(${resolvedSteps.length}, 1fr)` }, children: resolvedSteps.map((step, i) => /* @__PURE__ */ jsx(FadeIn, { direction: "up", delay: i * 80, children: /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col items-center text-center px-4", children: [
1885
+ i < resolvedSteps.length - 1 && /* @__PURE__ */ jsx(
1730
1886
  "div",
1731
1887
  {
1732
1888
  "aria-hidden": "true",
@@ -1735,10 +1891,10 @@ function StepsSection({
1735
1891
  ),
1736
1892
  /* @__PURE__ */ jsx("div", { className: "relative z-10 mb-3 flex h-12 w-12 items-center justify-center rounded-full bg-muted text-2xl", children: step.emoji ?? /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-primary", children: i + 1 }) }),
1737
1893
  /* @__PURE__ */ jsx("h3", { className: "font-semibold text-foreground", children: step.title }),
1738
- /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm leading-relaxed text-muted-foreground", children: step.description })
1894
+ /* @__PURE__ */ jsx("div", { className: "mt-2 text-sm leading-relaxed text-muted-foreground", children: step.description })
1739
1895
  ] }) }, step.title)) }),
1740
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0 sm:hidden", children: steps.map((step, i) => /* @__PURE__ */ jsx(FadeIn, { direction: "up", delay: i * 80, children: /* @__PURE__ */ jsxs("div", { className: "relative flex gap-4 pb-8 last:pb-0", children: [
1741
- i < steps.length - 1 && /* @__PURE__ */ jsx(
1896
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0 sm:hidden", children: resolvedSteps.map((step, i) => /* @__PURE__ */ jsx(FadeIn, { direction: "up", delay: i * 80, children: /* @__PURE__ */ jsxs("div", { className: "relative flex gap-4 pb-8 last:pb-0", children: [
1897
+ i < resolvedSteps.length - 1 && /* @__PURE__ */ jsx(
1742
1898
  "div",
1743
1899
  {
1744
1900
  "aria-hidden": "true",
@@ -1748,7 +1904,7 @@ function StepsSection({
1748
1904
  /* @__PURE__ */ jsx("div", { className: "relative z-10 flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-muted text-2xl", children: step.emoji ?? /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-primary", children: i + 1 }) }),
1749
1905
  /* @__PURE__ */ jsxs("div", { className: "pt-3", children: [
1750
1906
  /* @__PURE__ */ jsx("h3", { className: "font-semibold text-foreground", children: step.title }),
1751
- /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-sm leading-relaxed text-muted-foreground", children: step.description })
1907
+ /* @__PURE__ */ jsx("div", { className: "mt-1.5 text-sm leading-relaxed text-muted-foreground", children: step.description })
1752
1908
  ] })
1753
1909
  ] }) }, step.title)) })
1754
1910
  ] })
@@ -1884,9 +2040,9 @@ function FeatureMarqueeSection({
1884
2040
  ] });
1885
2041
  }
1886
2042
  function useIntersectionObserver(options) {
1887
- const ref = React32.useRef(null);
1888
- const [isIntersecting, setIsIntersecting] = React32.useState(false);
1889
- React32.useEffect(() => {
2043
+ const ref = React34.useRef(null);
2044
+ const [isIntersecting, setIsIntersecting] = React34.useState(false);
2045
+ React34.useEffect(() => {
1890
2046
  const el = ref.current;
1891
2047
  if (!el) return;
1892
2048
  const observer = new IntersectionObserver(([entry]) => {
@@ -1908,8 +2064,8 @@ function ShowcaseCta({
1908
2064
  sectionClasses
1909
2065
  }) {
1910
2066
  const [ref, intersecting] = useIntersectionObserver({ threshold: 0.15 });
1911
- const [visible, setVisible] = React32.useState(false);
1912
- React32.useEffect(() => {
2067
+ const [visible, setVisible] = React34.useState(false);
2068
+ React34.useEffect(() => {
1913
2069
  if (intersecting) setVisible(true);
1914
2070
  }, [intersecting]);
1915
2071
  return /* @__PURE__ */ jsxs(
@@ -2086,8 +2242,8 @@ function CountdownTimer({
2086
2242
  className,
2087
2243
  compact = false
2088
2244
  }) {
2089
- const [timeLeft, setTimeLeft] = React32.useState(() => getTimeLeft(deadline));
2090
- React32.useEffect(() => {
2245
+ const [timeLeft, setTimeLeft] = React34.useState(() => getTimeLeft(deadline));
2246
+ React34.useEffect(() => {
2091
2247
  setTimeLeft(getTimeLeft(deadline));
2092
2248
  const id = setInterval(() => setTimeLeft(getTimeLeft(deadline)), 1e3);
2093
2249
  return () => clearInterval(id);
@@ -2113,7 +2269,7 @@ function CountdownTimer({
2113
2269
  ];
2114
2270
  return /* @__PURE__ */ jsxs("div", { className: cn$1("flex items-center justify-center gap-2 text-sm", className), children: [
2115
2271
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label }),
2116
- /* @__PURE__ */ jsx("span", { className: "flex items-center gap-1 font-mono font-semibold tabular-nums", children: units.map(({ value, unit }, i) => /* @__PURE__ */ jsxs(React32.Fragment, { children: [
2272
+ /* @__PURE__ */ jsx("span", { className: "flex items-center gap-1 font-mono font-semibold tabular-nums", children: units.map(({ value, unit }, i) => /* @__PURE__ */ jsxs(React34.Fragment, { children: [
2117
2273
  /* @__PURE__ */ jsxs("span", { children: [
2118
2274
  String(value).padStart(2, "0"),
2119
2275
  /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: unit })
@@ -2138,7 +2294,7 @@ function PricingSection({
2138
2294
  highlightedBadgeLabel = "Founding member",
2139
2295
  renderPlanFooter
2140
2296
  }) {
2141
- const [annual, setAnnual] = React32.useState(false);
2297
+ const [annual, setAnnual] = React34.useState(false);
2142
2298
  const isOneTime = mode === "one-time";
2143
2299
  const uiMode = useUIVariant();
2144
2300
  const sectionClasses = cn$1(
@@ -2407,10 +2563,10 @@ function CountUp({
2407
2563
  className,
2408
2564
  ...props
2409
2565
  }) {
2410
- const ref = React32.useRef(null);
2411
- const [value, setValue] = React32.useState(from);
2412
- const hasStarted = React32.useRef(false);
2413
- React32.useEffect(() => {
2566
+ const ref = React34.useRef(null);
2567
+ const [value, setValue] = React34.useState(from);
2568
+ const hasStarted = React34.useRef(false);
2569
+ React34.useEffect(() => {
2414
2570
  const el = ref.current;
2415
2571
  if (!el) return;
2416
2572
  const observer = new IntersectionObserver(
@@ -2503,8 +2659,8 @@ function NewsletterSection({
2503
2659
  successDescription = defaults.successDescription,
2504
2660
  onSubscribe
2505
2661
  } = {}) {
2506
- const [email, setEmail] = React32.useState("");
2507
- const [submitted, setSubmitted] = React32.useState(false);
2662
+ const [email, setEmail] = React34.useState("");
2663
+ const [submitted, setSubmitted] = React34.useState(false);
2508
2664
  const mode = useUIVariant();
2509
2665
  const sectionClasses = cn$1(
2510
2666
  "overflow-hidden bg-card",
@@ -2595,7 +2751,7 @@ function ContactSection({
2595
2751
  sendAnotherLabel = defaults2.sendAnotherLabel,
2596
2752
  onSubmit
2597
2753
  } = {}) {
2598
- const [submitted, setSubmitted] = React32.useState(false);
2754
+ const [submitted, setSubmitted] = React34.useState(false);
2599
2755
  const mode = useUIVariant();
2600
2756
  const sectionClasses = cn$1(
2601
2757
  "overflow-hidden bg-card",
@@ -2893,7 +3049,7 @@ function Navbar({
2893
3049
  controls,
2894
3050
  renderLink = defaultRenderLink7
2895
3051
  }) {
2896
- const [open, setOpen] = React32.useState(false);
3052
+ const [open, setOpen] = React34.useState(false);
2897
3053
  const brandHref = brand.href ?? "/";
2898
3054
  const hasRightContent = controls?.length || cta?.primary || cta?.secondary;
2899
3055
  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: [
@@ -2910,7 +3066,7 @@ function Navbar({
2910
3066
  children: link.label
2911
3067
  }) }, link.label)) }),
2912
3068
  hasRightContent && /* @__PURE__ */ jsxs("div", { className: "hidden items-center justify-end gap-2 md:flex", children: [
2913
- controls?.map((control, i) => /* @__PURE__ */ jsx(React32.Fragment, { children: control }, i)),
3069
+ controls?.map((control, i) => /* @__PURE__ */ jsx(React34.Fragment, { children: control }, i)),
2914
3070
  (cta?.secondary || cta?.primary) && controls?.length ? /* @__PURE__ */ jsx("div", { className: "mx-1 h-4 w-px bg-border" }) : null,
2915
3071
  cta?.secondary && renderLink({
2916
3072
  href: cta.secondary.href,
@@ -2934,7 +3090,7 @@ function Navbar({
2934
3090
  /* @__PURE__ */ jsx("span", { children: brand.name })
2935
3091
  ] })
2936
3092
  }) }) }),
2937
- controls?.length ? /* @__PURE__ */ jsx("div", { className: "mb-4 flex w-full items-center justify-between gap-1", children: controls.map((control, i) => /* @__PURE__ */ jsx(React32.Fragment, { children: control }, i)) }) : null,
3093
+ controls?.length ? /* @__PURE__ */ jsx("div", { className: "mb-4 flex w-full items-center justify-between gap-1", children: controls.map((control, i) => /* @__PURE__ */ jsx(React34.Fragment, { children: control }, i)) }) : null,
2938
3094
  /* @__PURE__ */ jsx(Separator, {}),
2939
3095
  /* @__PURE__ */ jsx("nav", { className: "mt-4 flex flex-col gap-1", children: navLinks.map((link) => /* @__PURE__ */ jsx("span", { onClick: () => setOpen(false), children: renderLink({
2940
3096
  href: link.href,
@@ -3083,7 +3239,7 @@ function LogoStrip({
3083
3239
  ] });
3084
3240
  }
3085
3241
  function GridUnderlay({ variant, size = 24, className, ...props }) {
3086
- const id = React32.useId();
3242
+ const id = React34.useId();
3087
3243
  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: [
3088
3244
  /* @__PURE__ */ jsx("line", { x1: size / 2, y1: 0, x2: size / 2, y2: size, stroke: "currentColor", strokeWidth: 0.5 }),
3089
3245
  /* @__PURE__ */ jsx("line", { x1: 0, y1: size / 2, x2: size, y2: size / 2, stroke: "currentColor", strokeWidth: 0.5 })
@@ -3111,9 +3267,9 @@ function GlowUnderlay({
3111
3267
  style,
3112
3268
  ...props
3113
3269
  }) {
3114
- const [pos, setPos] = React32.useState({ x: "50%", y: "50%" });
3115
- const containerRef = React32.useRef(null);
3116
- React32.useEffect(() => {
3270
+ const [pos, setPos] = React34.useState({ x: "50%", y: "50%" });
3271
+ const containerRef = React34.useRef(null);
3272
+ React34.useEffect(() => {
3117
3273
  if (!followCursor) return;
3118
3274
  const handleMouseMove = (e) => {
3119
3275
  const el = containerRef.current;
@@ -3252,8 +3408,8 @@ function PageTransition({
3252
3408
  style,
3253
3409
  ...props
3254
3410
  }) {
3255
- const [mounted, setMounted] = React32.useState(false);
3256
- React32.useEffect(() => {
3411
+ const [mounted, setMounted] = React34.useState(false);
3412
+ React34.useEffect(() => {
3257
3413
  const id = requestAnimationFrame(() => setMounted(true));
3258
3414
  return () => cancelAnimationFrame(id);
3259
3415
  }, []);
@@ -3328,7 +3484,7 @@ function Sortable({
3328
3484
  if (oldIndex === -1 || newIndex === -1) return;
3329
3485
  onReorder(arrayMove(items, oldIndex, newIndex));
3330
3486
  };
3331
- const childArray = React32.Children.toArray(children);
3487
+ const childArray = React34.Children.toArray(children);
3332
3488
  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(
3333
3489
  (child, i) => items[i] === void 0 ? null : /* @__PURE__ */ jsx(SortableItem, { id: items[i], disabled, className: itemClassName, children: child }, items[i])
3334
3490
  ) }) }) });
@@ -3340,8 +3496,8 @@ function Spotlight({
3340
3496
  triggerClassName,
3341
3497
  shortcut = "\u2318K"
3342
3498
  }) {
3343
- const [open, setOpen] = React32.useState(false);
3344
- React32.useEffect(() => {
3499
+ const [open, setOpen] = React34.useState(false);
3500
+ React34.useEffect(() => {
3345
3501
  const down = (e) => {
3346
3502
  if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
3347
3503
  e.preventDefault();
@@ -3371,7 +3527,7 @@ function Spotlight({
3371
3527
  /* @__PURE__ */ jsx(CommandInput, { placeholder }),
3372
3528
  /* @__PURE__ */ jsxs(CommandList, { children: [
3373
3529
  /* @__PURE__ */ jsx(CommandEmpty, { children: "No results found." }),
3374
- groups.map((group, i) => /* @__PURE__ */ jsxs(React32.Fragment, { children: [
3530
+ groups.map((group, i) => /* @__PURE__ */ jsxs(React34.Fragment, { children: [
3375
3531
  i > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
3376
3532
  /* @__PURE__ */ jsx(CommandGroup, { heading: group.heading, children: group.items.map((item) => /* @__PURE__ */ jsxs(
3377
3533
  CommandItem,
@@ -3396,8 +3552,8 @@ function Spotlight({
3396
3552
  var BASE = 40;
3397
3553
  var MAGNIFY_RADIUS = 80;
3398
3554
  function Dock({ items, iconSize = BASE, magnification = 1.7, className, ...props }) {
3399
- const [mouseX, setMouseX] = React32.useState(null);
3400
- const containerRef = React32.useRef(null);
3555
+ const [mouseX, setMouseX] = React34.useState(null);
3556
+ const containerRef = React34.useRef(null);
3401
3557
  function getScale(index) {
3402
3558
  if (mouseX === null || !containerRef.current) return 1;
3403
3559
  const container = containerRef.current;
@@ -3496,7 +3652,7 @@ function ConfirmDialog({ isOpen, options, handleConfirm, handleCancel, destructi
3496
3652
  ] }) });
3497
3653
  }
3498
3654
  function RegisterHotkeys({ hotkeys }) {
3499
- React32.useEffect(() => {
3655
+ React34.useEffect(() => {
3500
3656
  const handleKeyDown = (event) => {
3501
3657
  for (const hotkey of hotkeys) {
3502
3658
  const matches = event.key.toLowerCase() === hotkey.key.toLowerCase() && !!event.ctrlKey === !!hotkey.ctrl && !!event.metaKey === !!hotkey.meta && !!event.shiftKey === !!hotkey.shift && !!event.altKey === !!hotkey.alt;
@@ -3513,10 +3669,10 @@ function RegisterHotkeys({ hotkeys }) {
3513
3669
  return null;
3514
3670
  }
3515
3671
  function useControlledOpen(defaultOpen = false) {
3516
- const [isOpen, setIsOpen] = React32.useState(defaultOpen);
3517
- const open = React32.useCallback(() => setIsOpen(true), []);
3518
- const close = React32.useCallback(() => setIsOpen(false), []);
3519
- const toggle = React32.useCallback(() => setIsOpen((prev) => !prev), []);
3672
+ const [isOpen, setIsOpen] = React34.useState(defaultOpen);
3673
+ const open = React34.useCallback(() => setIsOpen(true), []);
3674
+ const close = React34.useCallback(() => setIsOpen(false), []);
3675
+ const toggle = React34.useCallback(() => setIsOpen((prev) => !prev), []);
3520
3676
  return { isOpen, open, close, toggle, setIsOpen };
3521
3677
  }
3522
3678
  function CommandMenu({
@@ -3529,7 +3685,7 @@ function CommandMenu({
3529
3685
  }) {
3530
3686
  const internal = useControlledOpen(false);
3531
3687
  const isOpen = openProp ?? internal.isOpen;
3532
- const setOpen = React32.useCallback(
3688
+ const setOpen = React34.useCallback(
3533
3689
  (next) => {
3534
3690
  if (openProp === void 0) internal.setIsOpen(next);
3535
3691
  onOpenChange?.(next);
@@ -3554,7 +3710,7 @@ function CommandMenu({
3554
3710
  /* @__PURE__ */ jsx(CommandInput, { placeholder }),
3555
3711
  /* @__PURE__ */ jsxs(CommandList, { children: [
3556
3712
  /* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
3557
- groups.map((group, i) => /* @__PURE__ */ jsxs(React32.Fragment, { children: [
3713
+ groups.map((group, i) => /* @__PURE__ */ jsxs(React34.Fragment, { children: [
3558
3714
  i > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
3559
3715
  /* @__PURE__ */ jsx(CommandGroup, { heading: group.heading, children: group.items.map((item) => /* @__PURE__ */ jsxs(
3560
3716
  CommandItem,
@@ -3746,20 +3902,20 @@ function FileUpload({
3746
3902
  hint,
3747
3903
  className
3748
3904
  }) {
3749
- const [internalFiles, setInternalFiles] = React32.useState(defaultFiles ?? []);
3750
- const [isDragging, setIsDragging] = React32.useState(false);
3751
- const [validationError, setValidationError] = React32.useState(null);
3752
- const inputRef = React32.useRef(null);
3753
- const dragDepth = React32.useRef(0);
3905
+ const [internalFiles, setInternalFiles] = React34.useState(defaultFiles ?? []);
3906
+ const [isDragging, setIsDragging] = React34.useState(false);
3907
+ const [validationError, setValidationError] = React34.useState(null);
3908
+ const inputRef = React34.useRef(null);
3909
+ const dragDepth = React34.useRef(0);
3754
3910
  const files = filesProp ?? internalFiles;
3755
- const setFiles = React32.useCallback(
3911
+ const setFiles = React34.useCallback(
3756
3912
  (next) => {
3757
3913
  if (!filesProp) setInternalFiles(next);
3758
3914
  onFilesChange?.(next);
3759
3915
  },
3760
3916
  [filesProp, onFilesChange]
3761
3917
  );
3762
- const acceptList = React32.useMemo(
3918
+ const acceptList = React34.useMemo(
3763
3919
  () => accept?.split(",").map((a) => a.trim().toLowerCase()).filter(Boolean) ?? [],
3764
3920
  [accept]
3765
3921
  );
@@ -4426,7 +4582,7 @@ function PageHeader({
4426
4582
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1 pb-6", className), children: [
4427
4583
  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) => {
4428
4584
  const isLast = i === breadcrumbs.length - 1;
4429
- return /* @__PURE__ */ jsxs(React32.Fragment, { children: [
4585
+ return /* @__PURE__ */ jsxs(React34.Fragment, { children: [
4430
4586
  i > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5 shrink-0" }),
4431
4587
  isLast || !crumb.href ? /* @__PURE__ */ jsx("span", { className: cn(isLast && "text-foreground font-medium"), children: crumb.label }) : renderLink({
4432
4588
  href: crumb.href,
@@ -4462,7 +4618,7 @@ function PageHeader({
4462
4618
  ] });
4463
4619
  }
4464
4620
  function Suspensed({ children, fallback }) {
4465
- return /* @__PURE__ */ jsx(React32.Suspense, { fallback: fallback ?? /* @__PURE__ */ jsx(Spinner, {}), children });
4621
+ return /* @__PURE__ */ jsx(React34.Suspense, { fallback: fallback ?? /* @__PURE__ */ jsx(Spinner, {}), children });
4466
4622
  }
4467
4623
  function getInitialTheme() {
4468
4624
  if (typeof document === "undefined") return "dark";
@@ -4470,7 +4626,7 @@ function getInitialTheme() {
4470
4626
  return stored ?? (document.documentElement.classList.contains("dark") ? "dark" : "light");
4471
4627
  }
4472
4628
  function ThemeSwitchMinimal() {
4473
- const [theme, setThemeState] = React32.useState(getInitialTheme);
4629
+ const [theme, setThemeState] = React34.useState(getInitialTheme);
4474
4630
  const toggle = () => {
4475
4631
  const next = theme === "dark" ? "light" : "dark";
4476
4632
  setThemeState(next);
@@ -4596,9 +4752,9 @@ function getInitialColorName() {
4596
4752
  return localStorage.getItem(STORAGE_KEY) ?? "emerald";
4597
4753
  }
4598
4754
  function BrandColorSwitchMinimal() {
4599
- const [active, setActive] = React32.useState(getInitialColorName);
4600
- const [open, setOpen] = React32.useState(false);
4601
- React32.useEffect(() => {
4755
+ const [active, setActive] = React34.useState(getInitialColorName);
4756
+ const [open, setOpen] = React34.useState(false);
4757
+ React34.useEffect(() => {
4602
4758
  const saved = localStorage.getItem(STORAGE_KEY) ?? "emerald";
4603
4759
  const color = BRAND_COLORS.find((c) => c.name === saved);
4604
4760
  if (color) applyColor(color);
@@ -4659,7 +4815,7 @@ function BrandColorSwitchMinimal() {
4659
4815
  ] });
4660
4816
  }
4661
4817
  function ThemeColorUpdater({ colorTheme }) {
4662
- React32.useEffect(() => {
4818
+ React34.useEffect(() => {
4663
4819
  if (colorTheme) {
4664
4820
  document.documentElement.setAttribute("data-theme", colorTheme);
4665
4821
  } else {
@@ -4669,7 +4825,7 @@ function ThemeColorUpdater({ colorTheme }) {
4669
4825
  return null;
4670
4826
  }
4671
4827
  function VersionBanner({ version, message, className, onDismiss }) {
4672
- const [dismissed, setDismissed] = React32.useState(false);
4828
+ const [dismissed, setDismissed] = React34.useState(false);
4673
4829
  if (dismissed) return null;
4674
4830
  return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-4 bg-primary/10 px-4 py-2 text-sm", className), children: [
4675
4831
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
@@ -4926,29 +5082,29 @@ function useMounted() {
4926
5082
  return mounted;
4927
5083
  }
4928
5084
  function useConfirm() {
4929
- const [isOpen, setIsOpen] = React32.useState(false);
4930
- const [options, setOptions] = React32.useState({});
4931
- const resolveRef = React32.useRef(null);
4932
- const confirm = React32.useCallback((opts = {}) => {
5085
+ const [isOpen, setIsOpen] = React34.useState(false);
5086
+ const [options, setOptions] = React34.useState({});
5087
+ const resolveRef = React34.useRef(null);
5088
+ const confirm = React34.useCallback((opts = {}) => {
4933
5089
  setOptions(opts);
4934
5090
  setIsOpen(true);
4935
5091
  return new Promise((resolve) => {
4936
5092
  resolveRef.current = resolve;
4937
5093
  });
4938
5094
  }, []);
4939
- const handleConfirm = React32.useCallback(() => {
5095
+ const handleConfirm = React34.useCallback(() => {
4940
5096
  resolveRef.current?.(true);
4941
5097
  setIsOpen(false);
4942
5098
  }, []);
4943
- const handleCancel = React32.useCallback(() => {
5099
+ const handleCancel = React34.useCallback(() => {
4944
5100
  resolveRef.current?.(false);
4945
5101
  setIsOpen(false);
4946
5102
  }, []);
4947
5103
  return { confirm, isOpen, options, handleConfirm, handleCancel };
4948
5104
  }
4949
5105
  function useScrolledPast(threshold) {
4950
- const [scrolledPast, setScrolledPast] = React32.useState(false);
4951
- React32.useEffect(() => {
5106
+ const [scrolledPast, setScrolledPast] = React34.useState(false);
5107
+ React34.useEffect(() => {
4952
5108
  const handleScroll = () => {
4953
5109
  setScrolledPast(window.scrollY > threshold);
4954
5110
  };
@@ -4959,28 +5115,28 @@ function useScrolledPast(threshold) {
4959
5115
  return scrolledPast;
4960
5116
  }
4961
5117
  function useCopyToClipboard() {
4962
- const [copied, setCopied] = React32.useState(false);
4963
- const timeoutRef = React32.useRef(void 0);
4964
- const copy = React32.useCallback((text) => {
5118
+ const [copied, setCopied] = React34.useState(false);
5119
+ const timeoutRef = React34.useRef(void 0);
5120
+ const copy = React34.useCallback((text) => {
4965
5121
  navigator.clipboard.writeText(text).then(() => {
4966
5122
  setCopied(true);
4967
5123
  clearTimeout(timeoutRef.current);
4968
5124
  timeoutRef.current = setTimeout(() => setCopied(false), 2e3);
4969
5125
  });
4970
5126
  }, []);
4971
- React32.useEffect(() => () => clearTimeout(timeoutRef.current), []);
5127
+ React34.useEffect(() => () => clearTimeout(timeoutRef.current), []);
4972
5128
  return [copied, copy];
4973
5129
  }
4974
5130
  function useDebounce(value, delay) {
4975
- const [debounced, setDebounced] = React32.useState(value);
4976
- React32.useEffect(() => {
5131
+ const [debounced, setDebounced] = React34.useState(value);
5132
+ React34.useEffect(() => {
4977
5133
  const timer = setTimeout(() => setDebounced(value), delay);
4978
5134
  return () => clearTimeout(timer);
4979
5135
  }, [value, delay]);
4980
5136
  return debounced;
4981
5137
  }
4982
5138
  function useLocalStorage(key, initialValue) {
4983
- const [storedValue, setStoredValue] = React32.useState(() => {
5139
+ const [storedValue, setStoredValue] = React34.useState(() => {
4984
5140
  if (typeof window === "undefined") return initialValue;
4985
5141
  try {
4986
5142
  const item = window.localStorage.getItem(key);
@@ -4989,7 +5145,7 @@ function useLocalStorage(key, initialValue) {
4989
5145
  return initialValue;
4990
5146
  }
4991
5147
  });
4992
- const setValue = React32.useCallback(
5148
+ const setValue = React34.useCallback(
4993
5149
  (value) => {
4994
5150
  try {
4995
5151
  setStoredValue(value);
@@ -5004,11 +5160,11 @@ function useLocalStorage(key, initialValue) {
5004
5160
  return [storedValue, setValue];
5005
5161
  }
5006
5162
  function useMediaQuery(query) {
5007
- const [matches, setMatches] = React32.useState(() => {
5163
+ const [matches, setMatches] = React34.useState(() => {
5008
5164
  if (typeof window === "undefined") return false;
5009
5165
  return window.matchMedia(query).matches;
5010
5166
  });
5011
- React32.useEffect(() => {
5167
+ React34.useEffect(() => {
5012
5168
  if (typeof window === "undefined") return;
5013
5169
  const mql = window.matchMedia(query);
5014
5170
  setMatches(mql.matches);
@@ -5019,18 +5175,18 @@ function useMediaQuery(query) {
5019
5175
  return matches;
5020
5176
  }
5021
5177
  function usePagination(total, pageSize) {
5022
- const [page, setPage] = React32.useState(1);
5178
+ const [page, setPage] = React34.useState(1);
5023
5179
  const totalPages = Math.max(1, Math.ceil(total / pageSize));
5024
5180
  const offset = (page - 1) * pageSize;
5025
- const goTo = React32.useCallback(
5181
+ const goTo = React34.useCallback(
5026
5182
  (p) => setPage(Math.min(Math.max(1, p), totalPages)),
5027
5183
  [totalPages]
5028
5184
  );
5029
- const next = React32.useCallback(() => goTo(page + 1), [page, goTo]);
5030
- const prev = React32.useCallback(() => goTo(page - 1), [page, goTo]);
5185
+ const next = React34.useCallback(() => goTo(page + 1), [page, goTo]);
5186
+ const prev = React34.useCallback(() => goTo(page - 1), [page, goTo]);
5031
5187
  return { page, pageSize, totalPages, offset, hasPrev: page > 1, hasNext: page < totalPages, goTo, next, prev };
5032
5188
  }
5033
5189
 
5034
- export { ActivityFeed, AnimatedPill, AppContent, AppGrid, AppGridCell, AppScreen, AppShell, AuthSection, Badge, BillingPanel, BrandColorSwitchMinimal, Button, Card, Carousel, ChangelogCard, ChangelogList, Chart, Checkbox, CommandMenu, ComparisonSection, ConfirmDialog, ContactSection, ContextMenu, CountUp, CountdownTimer, CtaSection, DataTable, DevBanner, Dock, EmptyState, ErrorPage, FadeIn, FaqSection, FeatureCard, FeatureMarqueeSection, FeaturesSection, FileUpload, FlowBracket, FlowConnector, Footer, FullPageSpinner, GlassCard, Grid, GridItem, GroupedFeaturesSection, HeroSection, ImageCard, Input, LogoStrip, 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, UpgradePrompt, VersionBanner, marketingSectionSpacing, notify, useConfirm, useControlledOpen, useCopyToClipboard, useDebounce, useIntersectionObserver, useLocalStorage, useMediaQuery, useMounted, useOlwibaUI, usePagination, useScrolledPast, useUIMode };
5190
+ export { ActivityFeed, AnimatedPill, AppContent, AppGrid, AppGridCell, AppScreen, AppShell, AuthSection, Badge, BillingPanel, BrandColorSwitchMinimal, Button, Card, Carousel, ChangelogCard, ChangelogList, Chart, Checkbox, CommandMenu, ComparisonSection, ConfirmDialog, ContactSection, ContextMenu, CountUp, CountdownTimer, CtaSection, DataTable, DevBanner, Dock, EmptyState, ErrorPage, FadeIn, FaqSection, FeatureCard, FeatureMarqueeSection, FeaturesSection, FileUpload, FlowBracket, FlowConnector, Footer, FullPageSpinner, GlassCard, Grid, GridItem, GroupedFeaturesSection, HeroSection, ImageCard, Input, LogoStrip, 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, marketingSectionSpacing, notify, useConfirm, useControlledOpen, useCopyToClipboard, useDebounce, useIntersectionObserver, useLocalStorage, useMediaQuery, useMounted, useOlwibaUI, usePagination, useScrolledPast, useUIMode };
5035
5191
  //# sourceMappingURL=index.js.map
5036
5192
  //# sourceMappingURL=index.js.map