@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.d.ts +35 -4
- package/dist/index.js +278 -122
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/app/UpdateBanner.tsx +130 -0
- package/src/index.ts +3 -1
- package/src/marketing/StepsSection.tsx +105 -8
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
|
|
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,
|
|
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 =
|
|
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] =
|
|
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
|
|
30
|
+
return React34.useContext(OlwibaUIContext);
|
|
31
31
|
}
|
|
32
32
|
function useUIMode() {
|
|
33
|
-
return
|
|
33
|
+
return React34.useContext(OlwibaUIContext).mode;
|
|
34
34
|
}
|
|
35
|
-
var Button =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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] =
|
|
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] =
|
|
694
|
-
const [rowSelection, setRowSelection] =
|
|
695
|
-
const [globalFilter, setGlobalFilter] =
|
|
696
|
-
const allColumns =
|
|
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
|
-
|
|
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] =
|
|
799
|
-
const [role, setRole] =
|
|
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] =
|
|
844
|
-
const columns =
|
|
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 =
|
|
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] =
|
|
993
|
-
const [error, setError] =
|
|
994
|
-
const [pending, setPending] =
|
|
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 =
|
|
1329
|
-
const [visible, setVisible] =
|
|
1330
|
-
|
|
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 =
|
|
1526
|
-
const [canPrev, setCanPrev] =
|
|
1527
|
-
const [canNext, setCanNext] =
|
|
1528
|
-
const updateScrollState =
|
|
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
|
-
|
|
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:
|
|
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 =
|
|
1617
|
-
const [visible, setVisible] =
|
|
1618
|
-
|
|
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:
|
|
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(${
|
|
1729
|
-
i <
|
|
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("
|
|
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:
|
|
1741
|
-
i <
|
|
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("
|
|
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 =
|
|
1888
|
-
const [isIntersecting, setIsIntersecting] =
|
|
1889
|
-
|
|
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] =
|
|
1912
|
-
|
|
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] =
|
|
2090
|
-
|
|
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(
|
|
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] =
|
|
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 =
|
|
2411
|
-
const [value, setValue] =
|
|
2412
|
-
const hasStarted =
|
|
2413
|
-
|
|
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] =
|
|
2507
|
-
const [submitted, setSubmitted] =
|
|
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] =
|
|
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] =
|
|
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(
|
|
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(
|
|
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 =
|
|
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] =
|
|
3115
|
-
const containerRef =
|
|
3116
|
-
|
|
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] =
|
|
3256
|
-
|
|
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 =
|
|
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] =
|
|
3344
|
-
|
|
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(
|
|
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] =
|
|
3400
|
-
const containerRef =
|
|
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
|
-
|
|
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] =
|
|
3517
|
-
const open =
|
|
3518
|
-
const close =
|
|
3519
|
-
const toggle =
|
|
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 =
|
|
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(
|
|
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] =
|
|
3750
|
-
const [isDragging, setIsDragging] =
|
|
3751
|
-
const [validationError, setValidationError] =
|
|
3752
|
-
const inputRef =
|
|
3753
|
-
const dragDepth =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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] =
|
|
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] =
|
|
4600
|
-
const [open, setOpen] =
|
|
4601
|
-
|
|
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
|
-
|
|
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] =
|
|
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] =
|
|
4930
|
-
const [options, setOptions] =
|
|
4931
|
-
const resolveRef =
|
|
4932
|
-
const confirm =
|
|
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 =
|
|
5095
|
+
const handleConfirm = React34.useCallback(() => {
|
|
4940
5096
|
resolveRef.current?.(true);
|
|
4941
5097
|
setIsOpen(false);
|
|
4942
5098
|
}, []);
|
|
4943
|
-
const handleCancel =
|
|
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] =
|
|
4951
|
-
|
|
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] =
|
|
4963
|
-
const timeoutRef =
|
|
4964
|
-
const copy =
|
|
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
|
-
|
|
5127
|
+
React34.useEffect(() => () => clearTimeout(timeoutRef.current), []);
|
|
4972
5128
|
return [copied, copy];
|
|
4973
5129
|
}
|
|
4974
5130
|
function useDebounce(value, delay) {
|
|
4975
|
-
const [debounced, setDebounced] =
|
|
4976
|
-
|
|
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] =
|
|
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 =
|
|
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] =
|
|
5163
|
+
const [matches, setMatches] = React34.useState(() => {
|
|
5008
5164
|
if (typeof window === "undefined") return false;
|
|
5009
5165
|
return window.matchMedia(query).matches;
|
|
5010
5166
|
});
|
|
5011
|
-
|
|
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] =
|
|
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 =
|
|
5181
|
+
const goTo = React34.useCallback(
|
|
5026
5182
|
(p) => setPage(Math.min(Math.max(1, p), totalPages)),
|
|
5027
5183
|
[totalPages]
|
|
5028
5184
|
);
|
|
5029
|
-
const next =
|
|
5030
|
-
const prev =
|
|
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
|