@olwiba/ui 0.2.2 → 0.2.4
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 +18 -5
- package/dist/index.js +185 -122
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/marketing/PricingSection.tsx +9 -3
- package/src/marketing/StepsSection.tsx +105 -8
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cn } from './chunk-AMWLSHD6.js';
|
|
2
2
|
export { MdxContent, cn } from './chunk-AMWLSHD6.js';
|
|
3
|
-
import * as
|
|
3
|
+
import * as React33 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';
|
|
@@ -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 = React33.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] = React33.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 React33.useContext(OlwibaUIContext);
|
|
31
31
|
}
|
|
32
32
|
function useUIMode() {
|
|
33
|
-
return
|
|
33
|
+
return React33.useContext(OlwibaUIContext).mode;
|
|
34
34
|
}
|
|
35
|
-
var Button =
|
|
35
|
+
var Button = React33.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 = React33.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 = React33.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 = React33.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 = React33.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 = React33.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] = React33.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] = React33.useState([]);
|
|
694
|
+
const [rowSelection, setRowSelection] = React33.useState({});
|
|
695
|
+
const [globalFilter, setGlobalFilter] = React33.useState("");
|
|
696
|
+
const allColumns = React33.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
|
+
React33.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] = React33.useState("");
|
|
799
|
+
const [role, setRole] = React33.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] = React33.useState(false);
|
|
844
|
+
const columns = React33.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 = React33.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] = React33.useState(0);
|
|
993
|
+
const [error, setError] = React33.useState(null);
|
|
994
|
+
const [pending, setPending] = React33.useState(false);
|
|
995
995
|
const index = stepProp ?? internalStep;
|
|
996
996
|
const current = steps[index];
|
|
997
997
|
const isLast = index === steps.length - 1;
|
|
@@ -1325,9 +1325,9 @@ function FadeIn({
|
|
|
1325
1325
|
style,
|
|
1326
1326
|
...props
|
|
1327
1327
|
}) {
|
|
1328
|
-
const ref =
|
|
1329
|
-
const [visible, setVisible] =
|
|
1330
|
-
|
|
1328
|
+
const ref = React33.useRef(null);
|
|
1329
|
+
const [visible, setVisible] = React33.useState(false);
|
|
1330
|
+
React33.useEffect(() => {
|
|
1331
1331
|
const el = ref.current;
|
|
1332
1332
|
if (!el) return;
|
|
1333
1333
|
const observer = new IntersectionObserver(
|
|
@@ -1522,16 +1522,16 @@ function Carousel({
|
|
|
1522
1522
|
className
|
|
1523
1523
|
}) {
|
|
1524
1524
|
const mode = useUIVariant();
|
|
1525
|
-
const trackRef =
|
|
1526
|
-
const [canPrev, setCanPrev] =
|
|
1527
|
-
const [canNext, setCanNext] =
|
|
1528
|
-
const updateScrollState =
|
|
1525
|
+
const trackRef = React33.useRef(null);
|
|
1526
|
+
const [canPrev, setCanPrev] = React33.useState(false);
|
|
1527
|
+
const [canNext, setCanNext] = React33.useState(true);
|
|
1528
|
+
const updateScrollState = React33.useCallback(() => {
|
|
1529
1529
|
const track = trackRef.current;
|
|
1530
1530
|
if (!track) return;
|
|
1531
1531
|
setCanPrev(track.scrollLeft > 8);
|
|
1532
1532
|
setCanNext(track.scrollLeft < track.scrollWidth - track.clientWidth - 8);
|
|
1533
1533
|
}, []);
|
|
1534
|
-
|
|
1534
|
+
React33.useEffect(() => {
|
|
1535
1535
|
const track = trackRef.current;
|
|
1536
1536
|
if (!track) return;
|
|
1537
1537
|
updateScrollState();
|
|
@@ -1588,7 +1588,7 @@ function Carousel({
|
|
|
1588
1588
|
role: "region",
|
|
1589
1589
|
"aria-label": ariaLabel,
|
|
1590
1590
|
className: "flex snap-x snap-mandatory gap-6 overflow-x-auto pb-4 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
1591
|
-
children:
|
|
1591
|
+
children: React33.Children.map(
|
|
1592
1592
|
children,
|
|
1593
1593
|
(child) => child == null ? null : /* @__PURE__ */ jsx("div", { "data-carousel-item": true, className: cn$1("shrink-0 snap-start", itemClassName), children: child })
|
|
1594
1594
|
)
|
|
@@ -1613,9 +1613,9 @@ function StaggerChildren({
|
|
|
1613
1613
|
className,
|
|
1614
1614
|
...props
|
|
1615
1615
|
}) {
|
|
1616
|
-
const ref =
|
|
1617
|
-
const [visible, setVisible] =
|
|
1618
|
-
|
|
1616
|
+
const ref = React33.useRef(null);
|
|
1617
|
+
const [visible, setVisible] = React33.useState(false);
|
|
1618
|
+
React33.useEffect(() => {
|
|
1619
1619
|
const el = ref.current;
|
|
1620
1620
|
if (!el) return;
|
|
1621
1621
|
const observer = new IntersectionObserver(
|
|
@@ -1633,7 +1633,7 @@ function StaggerChildren({
|
|
|
1633
1633
|
return () => observer.disconnect();
|
|
1634
1634
|
}, [once]);
|
|
1635
1635
|
const [tx, ty] = translateMap2[direction];
|
|
1636
|
-
return /* @__PURE__ */ jsx("div", { ref, className: cn$1(className), ...props, children:
|
|
1636
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn$1(className), ...props, children: React33.Children.map(children, (child, i) => /* @__PURE__ */ jsx(
|
|
1637
1637
|
"div",
|
|
1638
1638
|
{
|
|
1639
1639
|
className: "h-full",
|
|
@@ -1709,11 +1709,56 @@ function GroupedFeaturesSection({
|
|
|
1709
1709
|
] }, group.label)) })
|
|
1710
1710
|
] }) }) });
|
|
1711
1711
|
}
|
|
1712
|
+
function TimelineGroup({
|
|
1713
|
+
steps,
|
|
1714
|
+
startNumber,
|
|
1715
|
+
fadeIn
|
|
1716
|
+
}) {
|
|
1717
|
+
const fadePx = 48;
|
|
1718
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
1719
|
+
fadeIn && /* @__PURE__ */ jsx(
|
|
1720
|
+
"div",
|
|
1721
|
+
{
|
|
1722
|
+
"aria-hidden": "true",
|
|
1723
|
+
className: "absolute left-[19px] w-1 bg-gradient-to-b from-transparent to-primary",
|
|
1724
|
+
style: { top: 0, height: fadePx }
|
|
1725
|
+
}
|
|
1726
|
+
),
|
|
1727
|
+
/* @__PURE__ */ jsx(
|
|
1728
|
+
"div",
|
|
1729
|
+
{
|
|
1730
|
+
"aria-hidden": "true",
|
|
1731
|
+
className: "absolute left-[19px] w-1 bg-primary",
|
|
1732
|
+
style: {
|
|
1733
|
+
top: fadeIn ? fadePx : 20,
|
|
1734
|
+
height: fadeIn ? `calc(100% - ${fadePx}px)` : "calc(100% - 20px)"
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
),
|
|
1738
|
+
/* @__PURE__ */ jsx(
|
|
1739
|
+
"div",
|
|
1740
|
+
{
|
|
1741
|
+
"aria-hidden": "true",
|
|
1742
|
+
className: "absolute left-[19px] w-1 bg-gradient-to-b from-primary to-transparent",
|
|
1743
|
+
style: { top: "100%", height: fadePx }
|
|
1744
|
+
}
|
|
1745
|
+
),
|
|
1746
|
+
/* @__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: [
|
|
1747
|
+
/* @__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 }),
|
|
1748
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 pt-1 pb-2", children: [
|
|
1749
|
+
/* @__PURE__ */ jsx("h3", { className: "mb-2 text-xl font-semibold text-foreground", children: step.title }),
|
|
1750
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm leading-relaxed text-muted-foreground", children: step.description })
|
|
1751
|
+
] })
|
|
1752
|
+
] }) }, step.title)) })
|
|
1753
|
+
] });
|
|
1754
|
+
}
|
|
1712
1755
|
function StepsSection({
|
|
1713
1756
|
badge = "How it works",
|
|
1714
1757
|
title = "From zero to shipped",
|
|
1715
1758
|
description,
|
|
1716
|
-
steps
|
|
1759
|
+
steps,
|
|
1760
|
+
variant = "default",
|
|
1761
|
+
groups
|
|
1717
1762
|
}) {
|
|
1718
1763
|
const mode = useUIVariant();
|
|
1719
1764
|
const sectionClasses = cn$1(
|
|
@@ -1722,11 +1767,27 @@ function StepsSection({
|
|
|
1722
1767
|
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
1723
1768
|
!mode && "rounded-2xl border"
|
|
1724
1769
|
);
|
|
1770
|
+
if (variant === "timeline") {
|
|
1771
|
+
const resolvedGroups = groups ?? (steps ? [{ steps }] : []);
|
|
1772
|
+
let nextNumber = 1;
|
|
1773
|
+
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: [
|
|
1774
|
+
/* @__PURE__ */ jsx(SectionTitle, { badge, title, description, className: "text-left [&>p]:mx-0" }),
|
|
1775
|
+
/* @__PURE__ */ jsx("div", { className: "mt-12", children: resolvedGroups.map((group, groupIndex) => {
|
|
1776
|
+
const startNumber = nextNumber;
|
|
1777
|
+
nextNumber += group.steps.length;
|
|
1778
|
+
return /* @__PURE__ */ jsxs(React33.Fragment, { children: [
|
|
1779
|
+
/* @__PURE__ */ jsx("div", { className: cn$1(groupIndex > 0 && "mt-10"), children: /* @__PURE__ */ jsx(TimelineGroup, { steps: group.steps, startNumber, fadeIn: groupIndex > 0 }) }),
|
|
1780
|
+
group.after && /* @__PURE__ */ jsx("div", { className: "mt-16", children: group.after })
|
|
1781
|
+
] }, groupIndex);
|
|
1782
|
+
}) })
|
|
1783
|
+
] }) }) });
|
|
1784
|
+
}
|
|
1785
|
+
const resolvedSteps = steps ?? [];
|
|
1725
1786
|
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
1787
|
/* @__PURE__ */ jsx(SectionTitle, { badge, title, description }),
|
|
1727
1788
|
/* @__PURE__ */ jsxs("div", { className: "mt-12", children: [
|
|
1728
|
-
/* @__PURE__ */ jsx("div", { className: "hidden sm:grid", style: { gridTemplateColumns: `repeat(${
|
|
1729
|
-
i <
|
|
1789
|
+
/* @__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: [
|
|
1790
|
+
i < resolvedSteps.length - 1 && /* @__PURE__ */ jsx(
|
|
1730
1791
|
"div",
|
|
1731
1792
|
{
|
|
1732
1793
|
"aria-hidden": "true",
|
|
@@ -1735,10 +1796,10 @@ function StepsSection({
|
|
|
1735
1796
|
),
|
|
1736
1797
|
/* @__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
1798
|
/* @__PURE__ */ jsx("h3", { className: "font-semibold text-foreground", children: step.title }),
|
|
1738
|
-
/* @__PURE__ */ jsx("
|
|
1799
|
+
/* @__PURE__ */ jsx("div", { className: "mt-2 text-sm leading-relaxed text-muted-foreground", children: step.description })
|
|
1739
1800
|
] }) }, step.title)) }),
|
|
1740
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0 sm:hidden", children:
|
|
1741
|
-
i <
|
|
1801
|
+
/* @__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: [
|
|
1802
|
+
i < resolvedSteps.length - 1 && /* @__PURE__ */ jsx(
|
|
1742
1803
|
"div",
|
|
1743
1804
|
{
|
|
1744
1805
|
"aria-hidden": "true",
|
|
@@ -1748,7 +1809,7 @@ function StepsSection({
|
|
|
1748
1809
|
/* @__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
1810
|
/* @__PURE__ */ jsxs("div", { className: "pt-3", children: [
|
|
1750
1811
|
/* @__PURE__ */ jsx("h3", { className: "font-semibold text-foreground", children: step.title }),
|
|
1751
|
-
/* @__PURE__ */ jsx("
|
|
1812
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1.5 text-sm leading-relaxed text-muted-foreground", children: step.description })
|
|
1752
1813
|
] })
|
|
1753
1814
|
] }) }, step.title)) })
|
|
1754
1815
|
] })
|
|
@@ -1884,9 +1945,9 @@ function FeatureMarqueeSection({
|
|
|
1884
1945
|
] });
|
|
1885
1946
|
}
|
|
1886
1947
|
function useIntersectionObserver(options) {
|
|
1887
|
-
const ref =
|
|
1888
|
-
const [isIntersecting, setIsIntersecting] =
|
|
1889
|
-
|
|
1948
|
+
const ref = React33.useRef(null);
|
|
1949
|
+
const [isIntersecting, setIsIntersecting] = React33.useState(false);
|
|
1950
|
+
React33.useEffect(() => {
|
|
1890
1951
|
const el = ref.current;
|
|
1891
1952
|
if (!el) return;
|
|
1892
1953
|
const observer = new IntersectionObserver(([entry]) => {
|
|
@@ -1908,8 +1969,8 @@ function ShowcaseCta({
|
|
|
1908
1969
|
sectionClasses
|
|
1909
1970
|
}) {
|
|
1910
1971
|
const [ref, intersecting] = useIntersectionObserver({ threshold: 0.15 });
|
|
1911
|
-
const [visible, setVisible] =
|
|
1912
|
-
|
|
1972
|
+
const [visible, setVisible] = React33.useState(false);
|
|
1973
|
+
React33.useEffect(() => {
|
|
1913
1974
|
if (intersecting) setVisible(true);
|
|
1914
1975
|
}, [intersecting]);
|
|
1915
1976
|
return /* @__PURE__ */ jsxs(
|
|
@@ -2086,8 +2147,8 @@ function CountdownTimer({
|
|
|
2086
2147
|
className,
|
|
2087
2148
|
compact = false
|
|
2088
2149
|
}) {
|
|
2089
|
-
const [timeLeft, setTimeLeft] =
|
|
2090
|
-
|
|
2150
|
+
const [timeLeft, setTimeLeft] = React33.useState(() => getTimeLeft(deadline));
|
|
2151
|
+
React33.useEffect(() => {
|
|
2091
2152
|
setTimeLeft(getTimeLeft(deadline));
|
|
2092
2153
|
const id = setInterval(() => setTimeLeft(getTimeLeft(deadline)), 1e3);
|
|
2093
2154
|
return () => clearInterval(id);
|
|
@@ -2113,7 +2174,7 @@ function CountdownTimer({
|
|
|
2113
2174
|
];
|
|
2114
2175
|
return /* @__PURE__ */ jsxs("div", { className: cn$1("flex items-center justify-center gap-2 text-sm", className), children: [
|
|
2115
2176
|
/* @__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(
|
|
2177
|
+
/* @__PURE__ */ jsx("span", { className: "flex items-center gap-1 font-mono font-semibold tabular-nums", children: units.map(({ value, unit }, i) => /* @__PURE__ */ jsxs(React33.Fragment, { children: [
|
|
2117
2178
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
2118
2179
|
String(value).padStart(2, "0"),
|
|
2119
2180
|
/* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: unit })
|
|
@@ -2134,9 +2195,11 @@ function PricingSection({
|
|
|
2134
2195
|
footnote,
|
|
2135
2196
|
mode = "subscription",
|
|
2136
2197
|
foundingDeadline,
|
|
2198
|
+
currency = "$",
|
|
2199
|
+
highlightedBadgeLabel = "Founding member",
|
|
2137
2200
|
renderPlanFooter
|
|
2138
2201
|
}) {
|
|
2139
|
-
const [annual, setAnnual] =
|
|
2202
|
+
const [annual, setAnnual] = React33.useState(false);
|
|
2140
2203
|
const isOneTime = mode === "one-time";
|
|
2141
2204
|
const uiMode = useUIVariant();
|
|
2142
2205
|
const sectionClasses = cn$1(
|
|
@@ -2184,9 +2247,9 @@ function PricingSection({
|
|
|
2184
2247
|
] }),
|
|
2185
2248
|
/* @__PURE__ */ jsx(StaggerChildren, { className: "mt-10 grid gap-4 lg:grid-cols-3", children: plans.map((plan) => {
|
|
2186
2249
|
const rawPrice = isOneTime ? plan.monthly : annual ? plan.annual : plan.monthly;
|
|
2187
|
-
const price = plan.priceDisplay ??
|
|
2250
|
+
const price = plan.priceDisplay ?? `${currency}${rawPrice}`;
|
|
2188
2251
|
const period = plan.periodDisplay ?? (isOneTime ? "one-time" : rawPrice > 0 ? "/mo" : "");
|
|
2189
|
-
const badge2 = plan.highlighted && foundingDeadline ? /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full border bg-secondary px-2.5 py-0.5 text-xs font-semibold text-secondary-foreground", children: /* @__PURE__ */ jsx(CountdownTimer, { deadline: foundingDeadline, compact: true }) }) : plan.highlighted ?
|
|
2252
|
+
const badge2 = plan.highlighted && foundingDeadline ? /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full border bg-secondary px-2.5 py-0.5 text-xs font-semibold text-secondary-foreground", children: /* @__PURE__ */ jsx(CountdownTimer, { deadline: foundingDeadline, compact: true }) }) : plan.highlighted && highlightedBadgeLabel ? highlightedBadgeLabel : void 0;
|
|
2190
2253
|
return /* @__PURE__ */ jsx(
|
|
2191
2254
|
PricingCard,
|
|
2192
2255
|
{
|
|
@@ -2405,10 +2468,10 @@ function CountUp({
|
|
|
2405
2468
|
className,
|
|
2406
2469
|
...props
|
|
2407
2470
|
}) {
|
|
2408
|
-
const ref =
|
|
2409
|
-
const [value, setValue] =
|
|
2410
|
-
const hasStarted =
|
|
2411
|
-
|
|
2471
|
+
const ref = React33.useRef(null);
|
|
2472
|
+
const [value, setValue] = React33.useState(from);
|
|
2473
|
+
const hasStarted = React33.useRef(false);
|
|
2474
|
+
React33.useEffect(() => {
|
|
2412
2475
|
const el = ref.current;
|
|
2413
2476
|
if (!el) return;
|
|
2414
2477
|
const observer = new IntersectionObserver(
|
|
@@ -2501,8 +2564,8 @@ function NewsletterSection({
|
|
|
2501
2564
|
successDescription = defaults.successDescription,
|
|
2502
2565
|
onSubscribe
|
|
2503
2566
|
} = {}) {
|
|
2504
|
-
const [email, setEmail] =
|
|
2505
|
-
const [submitted, setSubmitted] =
|
|
2567
|
+
const [email, setEmail] = React33.useState("");
|
|
2568
|
+
const [submitted, setSubmitted] = React33.useState(false);
|
|
2506
2569
|
const mode = useUIVariant();
|
|
2507
2570
|
const sectionClasses = cn$1(
|
|
2508
2571
|
"overflow-hidden bg-card",
|
|
@@ -2593,7 +2656,7 @@ function ContactSection({
|
|
|
2593
2656
|
sendAnotherLabel = defaults2.sendAnotherLabel,
|
|
2594
2657
|
onSubmit
|
|
2595
2658
|
} = {}) {
|
|
2596
|
-
const [submitted, setSubmitted] =
|
|
2659
|
+
const [submitted, setSubmitted] = React33.useState(false);
|
|
2597
2660
|
const mode = useUIVariant();
|
|
2598
2661
|
const sectionClasses = cn$1(
|
|
2599
2662
|
"overflow-hidden bg-card",
|
|
@@ -2891,7 +2954,7 @@ function Navbar({
|
|
|
2891
2954
|
controls,
|
|
2892
2955
|
renderLink = defaultRenderLink7
|
|
2893
2956
|
}) {
|
|
2894
|
-
const [open, setOpen] =
|
|
2957
|
+
const [open, setOpen] = React33.useState(false);
|
|
2895
2958
|
const brandHref = brand.href ?? "/";
|
|
2896
2959
|
const hasRightContent = controls?.length || cta?.primary || cta?.secondary;
|
|
2897
2960
|
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: [
|
|
@@ -2908,7 +2971,7 @@ function Navbar({
|
|
|
2908
2971
|
children: link.label
|
|
2909
2972
|
}) }, link.label)) }),
|
|
2910
2973
|
hasRightContent && /* @__PURE__ */ jsxs("div", { className: "hidden items-center justify-end gap-2 md:flex", children: [
|
|
2911
|
-
controls?.map((control, i) => /* @__PURE__ */ jsx(
|
|
2974
|
+
controls?.map((control, i) => /* @__PURE__ */ jsx(React33.Fragment, { children: control }, i)),
|
|
2912
2975
|
(cta?.secondary || cta?.primary) && controls?.length ? /* @__PURE__ */ jsx("div", { className: "mx-1 h-4 w-px bg-border" }) : null,
|
|
2913
2976
|
cta?.secondary && renderLink({
|
|
2914
2977
|
href: cta.secondary.href,
|
|
@@ -2932,7 +2995,7 @@ function Navbar({
|
|
|
2932
2995
|
/* @__PURE__ */ jsx("span", { children: brand.name })
|
|
2933
2996
|
] })
|
|
2934
2997
|
}) }) }),
|
|
2935
|
-
controls?.length ? /* @__PURE__ */ jsx("div", { className: "mb-4 flex w-full items-center justify-between gap-1", children: controls.map((control, i) => /* @__PURE__ */ jsx(
|
|
2998
|
+
controls?.length ? /* @__PURE__ */ jsx("div", { className: "mb-4 flex w-full items-center justify-between gap-1", children: controls.map((control, i) => /* @__PURE__ */ jsx(React33.Fragment, { children: control }, i)) }) : null,
|
|
2936
2999
|
/* @__PURE__ */ jsx(Separator, {}),
|
|
2937
3000
|
/* @__PURE__ */ jsx("nav", { className: "mt-4 flex flex-col gap-1", children: navLinks.map((link) => /* @__PURE__ */ jsx("span", { onClick: () => setOpen(false), children: renderLink({
|
|
2938
3001
|
href: link.href,
|
|
@@ -3081,7 +3144,7 @@ function LogoStrip({
|
|
|
3081
3144
|
] });
|
|
3082
3145
|
}
|
|
3083
3146
|
function GridUnderlay({ variant, size = 24, className, ...props }) {
|
|
3084
|
-
const id =
|
|
3147
|
+
const id = React33.useId();
|
|
3085
3148
|
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: [
|
|
3086
3149
|
/* @__PURE__ */ jsx("line", { x1: size / 2, y1: 0, x2: size / 2, y2: size, stroke: "currentColor", strokeWidth: 0.5 }),
|
|
3087
3150
|
/* @__PURE__ */ jsx("line", { x1: 0, y1: size / 2, x2: size, y2: size / 2, stroke: "currentColor", strokeWidth: 0.5 })
|
|
@@ -3109,9 +3172,9 @@ function GlowUnderlay({
|
|
|
3109
3172
|
style,
|
|
3110
3173
|
...props
|
|
3111
3174
|
}) {
|
|
3112
|
-
const [pos, setPos] =
|
|
3113
|
-
const containerRef =
|
|
3114
|
-
|
|
3175
|
+
const [pos, setPos] = React33.useState({ x: "50%", y: "50%" });
|
|
3176
|
+
const containerRef = React33.useRef(null);
|
|
3177
|
+
React33.useEffect(() => {
|
|
3115
3178
|
if (!followCursor) return;
|
|
3116
3179
|
const handleMouseMove = (e) => {
|
|
3117
3180
|
const el = containerRef.current;
|
|
@@ -3250,8 +3313,8 @@ function PageTransition({
|
|
|
3250
3313
|
style,
|
|
3251
3314
|
...props
|
|
3252
3315
|
}) {
|
|
3253
|
-
const [mounted, setMounted] =
|
|
3254
|
-
|
|
3316
|
+
const [mounted, setMounted] = React33.useState(false);
|
|
3317
|
+
React33.useEffect(() => {
|
|
3255
3318
|
const id = requestAnimationFrame(() => setMounted(true));
|
|
3256
3319
|
return () => cancelAnimationFrame(id);
|
|
3257
3320
|
}, []);
|
|
@@ -3326,7 +3389,7 @@ function Sortable({
|
|
|
3326
3389
|
if (oldIndex === -1 || newIndex === -1) return;
|
|
3327
3390
|
onReorder(arrayMove(items, oldIndex, newIndex));
|
|
3328
3391
|
};
|
|
3329
|
-
const childArray =
|
|
3392
|
+
const childArray = React33.Children.toArray(children);
|
|
3330
3393
|
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(
|
|
3331
3394
|
(child, i) => items[i] === void 0 ? null : /* @__PURE__ */ jsx(SortableItem, { id: items[i], disabled, className: itemClassName, children: child }, items[i])
|
|
3332
3395
|
) }) }) });
|
|
@@ -3338,8 +3401,8 @@ function Spotlight({
|
|
|
3338
3401
|
triggerClassName,
|
|
3339
3402
|
shortcut = "\u2318K"
|
|
3340
3403
|
}) {
|
|
3341
|
-
const [open, setOpen] =
|
|
3342
|
-
|
|
3404
|
+
const [open, setOpen] = React33.useState(false);
|
|
3405
|
+
React33.useEffect(() => {
|
|
3343
3406
|
const down = (e) => {
|
|
3344
3407
|
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
|
3345
3408
|
e.preventDefault();
|
|
@@ -3369,7 +3432,7 @@ function Spotlight({
|
|
|
3369
3432
|
/* @__PURE__ */ jsx(CommandInput, { placeholder }),
|
|
3370
3433
|
/* @__PURE__ */ jsxs(CommandList, { children: [
|
|
3371
3434
|
/* @__PURE__ */ jsx(CommandEmpty, { children: "No results found." }),
|
|
3372
|
-
groups.map((group, i) => /* @__PURE__ */ jsxs(
|
|
3435
|
+
groups.map((group, i) => /* @__PURE__ */ jsxs(React33.Fragment, { children: [
|
|
3373
3436
|
i > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
|
|
3374
3437
|
/* @__PURE__ */ jsx(CommandGroup, { heading: group.heading, children: group.items.map((item) => /* @__PURE__ */ jsxs(
|
|
3375
3438
|
CommandItem,
|
|
@@ -3394,8 +3457,8 @@ function Spotlight({
|
|
|
3394
3457
|
var BASE = 40;
|
|
3395
3458
|
var MAGNIFY_RADIUS = 80;
|
|
3396
3459
|
function Dock({ items, iconSize = BASE, magnification = 1.7, className, ...props }) {
|
|
3397
|
-
const [mouseX, setMouseX] =
|
|
3398
|
-
const containerRef =
|
|
3460
|
+
const [mouseX, setMouseX] = React33.useState(null);
|
|
3461
|
+
const containerRef = React33.useRef(null);
|
|
3399
3462
|
function getScale(index) {
|
|
3400
3463
|
if (mouseX === null || !containerRef.current) return 1;
|
|
3401
3464
|
const container = containerRef.current;
|
|
@@ -3494,7 +3557,7 @@ function ConfirmDialog({ isOpen, options, handleConfirm, handleCancel, destructi
|
|
|
3494
3557
|
] }) });
|
|
3495
3558
|
}
|
|
3496
3559
|
function RegisterHotkeys({ hotkeys }) {
|
|
3497
|
-
|
|
3560
|
+
React33.useEffect(() => {
|
|
3498
3561
|
const handleKeyDown = (event) => {
|
|
3499
3562
|
for (const hotkey of hotkeys) {
|
|
3500
3563
|
const matches = event.key.toLowerCase() === hotkey.key.toLowerCase() && !!event.ctrlKey === !!hotkey.ctrl && !!event.metaKey === !!hotkey.meta && !!event.shiftKey === !!hotkey.shift && !!event.altKey === !!hotkey.alt;
|
|
@@ -3511,10 +3574,10 @@ function RegisterHotkeys({ hotkeys }) {
|
|
|
3511
3574
|
return null;
|
|
3512
3575
|
}
|
|
3513
3576
|
function useControlledOpen(defaultOpen = false) {
|
|
3514
|
-
const [isOpen, setIsOpen] =
|
|
3515
|
-
const open =
|
|
3516
|
-
const close =
|
|
3517
|
-
const toggle =
|
|
3577
|
+
const [isOpen, setIsOpen] = React33.useState(defaultOpen);
|
|
3578
|
+
const open = React33.useCallback(() => setIsOpen(true), []);
|
|
3579
|
+
const close = React33.useCallback(() => setIsOpen(false), []);
|
|
3580
|
+
const toggle = React33.useCallback(() => setIsOpen((prev) => !prev), []);
|
|
3518
3581
|
return { isOpen, open, close, toggle, setIsOpen };
|
|
3519
3582
|
}
|
|
3520
3583
|
function CommandMenu({
|
|
@@ -3527,7 +3590,7 @@ function CommandMenu({
|
|
|
3527
3590
|
}) {
|
|
3528
3591
|
const internal = useControlledOpen(false);
|
|
3529
3592
|
const isOpen = openProp ?? internal.isOpen;
|
|
3530
|
-
const setOpen =
|
|
3593
|
+
const setOpen = React33.useCallback(
|
|
3531
3594
|
(next) => {
|
|
3532
3595
|
if (openProp === void 0) internal.setIsOpen(next);
|
|
3533
3596
|
onOpenChange?.(next);
|
|
@@ -3552,7 +3615,7 @@ function CommandMenu({
|
|
|
3552
3615
|
/* @__PURE__ */ jsx(CommandInput, { placeholder }),
|
|
3553
3616
|
/* @__PURE__ */ jsxs(CommandList, { children: [
|
|
3554
3617
|
/* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
|
|
3555
|
-
groups.map((group, i) => /* @__PURE__ */ jsxs(
|
|
3618
|
+
groups.map((group, i) => /* @__PURE__ */ jsxs(React33.Fragment, { children: [
|
|
3556
3619
|
i > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
|
|
3557
3620
|
/* @__PURE__ */ jsx(CommandGroup, { heading: group.heading, children: group.items.map((item) => /* @__PURE__ */ jsxs(
|
|
3558
3621
|
CommandItem,
|
|
@@ -3744,20 +3807,20 @@ function FileUpload({
|
|
|
3744
3807
|
hint,
|
|
3745
3808
|
className
|
|
3746
3809
|
}) {
|
|
3747
|
-
const [internalFiles, setInternalFiles] =
|
|
3748
|
-
const [isDragging, setIsDragging] =
|
|
3749
|
-
const [validationError, setValidationError] =
|
|
3750
|
-
const inputRef =
|
|
3751
|
-
const dragDepth =
|
|
3810
|
+
const [internalFiles, setInternalFiles] = React33.useState(defaultFiles ?? []);
|
|
3811
|
+
const [isDragging, setIsDragging] = React33.useState(false);
|
|
3812
|
+
const [validationError, setValidationError] = React33.useState(null);
|
|
3813
|
+
const inputRef = React33.useRef(null);
|
|
3814
|
+
const dragDepth = React33.useRef(0);
|
|
3752
3815
|
const files = filesProp ?? internalFiles;
|
|
3753
|
-
const setFiles =
|
|
3816
|
+
const setFiles = React33.useCallback(
|
|
3754
3817
|
(next) => {
|
|
3755
3818
|
if (!filesProp) setInternalFiles(next);
|
|
3756
3819
|
onFilesChange?.(next);
|
|
3757
3820
|
},
|
|
3758
3821
|
[filesProp, onFilesChange]
|
|
3759
3822
|
);
|
|
3760
|
-
const acceptList =
|
|
3823
|
+
const acceptList = React33.useMemo(
|
|
3761
3824
|
() => accept?.split(",").map((a) => a.trim().toLowerCase()).filter(Boolean) ?? [],
|
|
3762
3825
|
[accept]
|
|
3763
3826
|
);
|
|
@@ -4424,7 +4487,7 @@ function PageHeader({
|
|
|
4424
4487
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1 pb-6", className), children: [
|
|
4425
4488
|
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) => {
|
|
4426
4489
|
const isLast = i === breadcrumbs.length - 1;
|
|
4427
|
-
return /* @__PURE__ */ jsxs(
|
|
4490
|
+
return /* @__PURE__ */ jsxs(React33.Fragment, { children: [
|
|
4428
4491
|
i > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5 shrink-0" }),
|
|
4429
4492
|
isLast || !crumb.href ? /* @__PURE__ */ jsx("span", { className: cn(isLast && "text-foreground font-medium"), children: crumb.label }) : renderLink({
|
|
4430
4493
|
href: crumb.href,
|
|
@@ -4460,7 +4523,7 @@ function PageHeader({
|
|
|
4460
4523
|
] });
|
|
4461
4524
|
}
|
|
4462
4525
|
function Suspensed({ children, fallback }) {
|
|
4463
|
-
return /* @__PURE__ */ jsx(
|
|
4526
|
+
return /* @__PURE__ */ jsx(React33.Suspense, { fallback: fallback ?? /* @__PURE__ */ jsx(Spinner, {}), children });
|
|
4464
4527
|
}
|
|
4465
4528
|
function getInitialTheme() {
|
|
4466
4529
|
if (typeof document === "undefined") return "dark";
|
|
@@ -4468,7 +4531,7 @@ function getInitialTheme() {
|
|
|
4468
4531
|
return stored ?? (document.documentElement.classList.contains("dark") ? "dark" : "light");
|
|
4469
4532
|
}
|
|
4470
4533
|
function ThemeSwitchMinimal() {
|
|
4471
|
-
const [theme, setThemeState] =
|
|
4534
|
+
const [theme, setThemeState] = React33.useState(getInitialTheme);
|
|
4472
4535
|
const toggle = () => {
|
|
4473
4536
|
const next = theme === "dark" ? "light" : "dark";
|
|
4474
4537
|
setThemeState(next);
|
|
@@ -4594,9 +4657,9 @@ function getInitialColorName() {
|
|
|
4594
4657
|
return localStorage.getItem(STORAGE_KEY) ?? "emerald";
|
|
4595
4658
|
}
|
|
4596
4659
|
function BrandColorSwitchMinimal() {
|
|
4597
|
-
const [active, setActive] =
|
|
4598
|
-
const [open, setOpen] =
|
|
4599
|
-
|
|
4660
|
+
const [active, setActive] = React33.useState(getInitialColorName);
|
|
4661
|
+
const [open, setOpen] = React33.useState(false);
|
|
4662
|
+
React33.useEffect(() => {
|
|
4600
4663
|
const saved = localStorage.getItem(STORAGE_KEY) ?? "emerald";
|
|
4601
4664
|
const color = BRAND_COLORS.find((c) => c.name === saved);
|
|
4602
4665
|
if (color) applyColor(color);
|
|
@@ -4657,7 +4720,7 @@ function BrandColorSwitchMinimal() {
|
|
|
4657
4720
|
] });
|
|
4658
4721
|
}
|
|
4659
4722
|
function ThemeColorUpdater({ colorTheme }) {
|
|
4660
|
-
|
|
4723
|
+
React33.useEffect(() => {
|
|
4661
4724
|
if (colorTheme) {
|
|
4662
4725
|
document.documentElement.setAttribute("data-theme", colorTheme);
|
|
4663
4726
|
} else {
|
|
@@ -4667,7 +4730,7 @@ function ThemeColorUpdater({ colorTheme }) {
|
|
|
4667
4730
|
return null;
|
|
4668
4731
|
}
|
|
4669
4732
|
function VersionBanner({ version, message, className, onDismiss }) {
|
|
4670
|
-
const [dismissed, setDismissed] =
|
|
4733
|
+
const [dismissed, setDismissed] = React33.useState(false);
|
|
4671
4734
|
if (dismissed) return null;
|
|
4672
4735
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-4 bg-primary/10 px-4 py-2 text-sm", className), children: [
|
|
4673
4736
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -4924,29 +4987,29 @@ function useMounted() {
|
|
|
4924
4987
|
return mounted;
|
|
4925
4988
|
}
|
|
4926
4989
|
function useConfirm() {
|
|
4927
|
-
const [isOpen, setIsOpen] =
|
|
4928
|
-
const [options, setOptions] =
|
|
4929
|
-
const resolveRef =
|
|
4930
|
-
const confirm =
|
|
4990
|
+
const [isOpen, setIsOpen] = React33.useState(false);
|
|
4991
|
+
const [options, setOptions] = React33.useState({});
|
|
4992
|
+
const resolveRef = React33.useRef(null);
|
|
4993
|
+
const confirm = React33.useCallback((opts = {}) => {
|
|
4931
4994
|
setOptions(opts);
|
|
4932
4995
|
setIsOpen(true);
|
|
4933
4996
|
return new Promise((resolve) => {
|
|
4934
4997
|
resolveRef.current = resolve;
|
|
4935
4998
|
});
|
|
4936
4999
|
}, []);
|
|
4937
|
-
const handleConfirm =
|
|
5000
|
+
const handleConfirm = React33.useCallback(() => {
|
|
4938
5001
|
resolveRef.current?.(true);
|
|
4939
5002
|
setIsOpen(false);
|
|
4940
5003
|
}, []);
|
|
4941
|
-
const handleCancel =
|
|
5004
|
+
const handleCancel = React33.useCallback(() => {
|
|
4942
5005
|
resolveRef.current?.(false);
|
|
4943
5006
|
setIsOpen(false);
|
|
4944
5007
|
}, []);
|
|
4945
5008
|
return { confirm, isOpen, options, handleConfirm, handleCancel };
|
|
4946
5009
|
}
|
|
4947
5010
|
function useScrolledPast(threshold) {
|
|
4948
|
-
const [scrolledPast, setScrolledPast] =
|
|
4949
|
-
|
|
5011
|
+
const [scrolledPast, setScrolledPast] = React33.useState(false);
|
|
5012
|
+
React33.useEffect(() => {
|
|
4950
5013
|
const handleScroll = () => {
|
|
4951
5014
|
setScrolledPast(window.scrollY > threshold);
|
|
4952
5015
|
};
|
|
@@ -4957,28 +5020,28 @@ function useScrolledPast(threshold) {
|
|
|
4957
5020
|
return scrolledPast;
|
|
4958
5021
|
}
|
|
4959
5022
|
function useCopyToClipboard() {
|
|
4960
|
-
const [copied, setCopied] =
|
|
4961
|
-
const timeoutRef =
|
|
4962
|
-
const copy =
|
|
5023
|
+
const [copied, setCopied] = React33.useState(false);
|
|
5024
|
+
const timeoutRef = React33.useRef(void 0);
|
|
5025
|
+
const copy = React33.useCallback((text) => {
|
|
4963
5026
|
navigator.clipboard.writeText(text).then(() => {
|
|
4964
5027
|
setCopied(true);
|
|
4965
5028
|
clearTimeout(timeoutRef.current);
|
|
4966
5029
|
timeoutRef.current = setTimeout(() => setCopied(false), 2e3);
|
|
4967
5030
|
});
|
|
4968
5031
|
}, []);
|
|
4969
|
-
|
|
5032
|
+
React33.useEffect(() => () => clearTimeout(timeoutRef.current), []);
|
|
4970
5033
|
return [copied, copy];
|
|
4971
5034
|
}
|
|
4972
5035
|
function useDebounce(value, delay) {
|
|
4973
|
-
const [debounced, setDebounced] =
|
|
4974
|
-
|
|
5036
|
+
const [debounced, setDebounced] = React33.useState(value);
|
|
5037
|
+
React33.useEffect(() => {
|
|
4975
5038
|
const timer = setTimeout(() => setDebounced(value), delay);
|
|
4976
5039
|
return () => clearTimeout(timer);
|
|
4977
5040
|
}, [value, delay]);
|
|
4978
5041
|
return debounced;
|
|
4979
5042
|
}
|
|
4980
5043
|
function useLocalStorage(key, initialValue) {
|
|
4981
|
-
const [storedValue, setStoredValue] =
|
|
5044
|
+
const [storedValue, setStoredValue] = React33.useState(() => {
|
|
4982
5045
|
if (typeof window === "undefined") return initialValue;
|
|
4983
5046
|
try {
|
|
4984
5047
|
const item = window.localStorage.getItem(key);
|
|
@@ -4987,7 +5050,7 @@ function useLocalStorage(key, initialValue) {
|
|
|
4987
5050
|
return initialValue;
|
|
4988
5051
|
}
|
|
4989
5052
|
});
|
|
4990
|
-
const setValue =
|
|
5053
|
+
const setValue = React33.useCallback(
|
|
4991
5054
|
(value) => {
|
|
4992
5055
|
try {
|
|
4993
5056
|
setStoredValue(value);
|
|
@@ -5002,11 +5065,11 @@ function useLocalStorage(key, initialValue) {
|
|
|
5002
5065
|
return [storedValue, setValue];
|
|
5003
5066
|
}
|
|
5004
5067
|
function useMediaQuery(query) {
|
|
5005
|
-
const [matches, setMatches] =
|
|
5068
|
+
const [matches, setMatches] = React33.useState(() => {
|
|
5006
5069
|
if (typeof window === "undefined") return false;
|
|
5007
5070
|
return window.matchMedia(query).matches;
|
|
5008
5071
|
});
|
|
5009
|
-
|
|
5072
|
+
React33.useEffect(() => {
|
|
5010
5073
|
if (typeof window === "undefined") return;
|
|
5011
5074
|
const mql = window.matchMedia(query);
|
|
5012
5075
|
setMatches(mql.matches);
|
|
@@ -5017,15 +5080,15 @@ function useMediaQuery(query) {
|
|
|
5017
5080
|
return matches;
|
|
5018
5081
|
}
|
|
5019
5082
|
function usePagination(total, pageSize) {
|
|
5020
|
-
const [page, setPage] =
|
|
5083
|
+
const [page, setPage] = React33.useState(1);
|
|
5021
5084
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
5022
5085
|
const offset = (page - 1) * pageSize;
|
|
5023
|
-
const goTo =
|
|
5086
|
+
const goTo = React33.useCallback(
|
|
5024
5087
|
(p) => setPage(Math.min(Math.max(1, p), totalPages)),
|
|
5025
5088
|
[totalPages]
|
|
5026
5089
|
);
|
|
5027
|
-
const next =
|
|
5028
|
-
const prev =
|
|
5090
|
+
const next = React33.useCallback(() => goTo(page + 1), [page, goTo]);
|
|
5091
|
+
const prev = React33.useCallback(() => goTo(page - 1), [page, goTo]);
|
|
5029
5092
|
return { page, pageSize, totalPages, offset, hasPrev: page > 1, hasNext: page < totalPages, goTo, next, prev };
|
|
5030
5093
|
}
|
|
5031
5094
|
|