@olwiba/ui 0.2.19 → 0.2.20
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 +99 -15
- package/dist/index.js +207 -250
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +6 -0
- package/src/marketing/ComparisonSection.tsx +6 -8
- package/src/marketing/ContactSection.tsx +6 -8
- package/src/marketing/CtaSection.tsx +7 -7
- package/src/marketing/FaqSection.tsx +6 -8
- package/src/marketing/FeatureMarqueeSection.tsx +6 -9
- package/src/marketing/FeaturesSection.tsx +6 -8
- package/src/marketing/GroupedFeaturesSection.tsx +5 -8
- package/src/marketing/NewsletterSection.tsx +6 -8
- package/src/marketing/PricingSection.tsx +12 -8
- package/src/marketing/QualificationSection.tsx +6 -8
- package/src/marketing/StatsSection.tsx +6 -8
- package/src/marketing/StepsSection.tsx +6 -8
- package/src/marketing/TeamSection.tsx +6 -8
- package/src/marketing/TechStackSection.tsx +6 -6
- package/src/marketing/TestimonialsSection.tsx +5 -8
- package/src/marketing/section-surface.tsx +88 -0
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 React21 from 'react';
|
|
4
4
|
import { useRef, useEffect, useState, useCallback } from 'react';
|
|
5
5
|
import { Button as Button$1, Card as Card$1, Input as Input$1, Textarea as Textarea$1, Checkbox as Checkbox$1, Switch as Switch$1, useIsMobile, UIVariantProvider, Badge as Badge$1, cn as cn$1, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Avatar, AvatarImage, AvatarFallback, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, Dialog, DialogTrigger, Progress, useUIVariant, Separator, Accordion, AccordionItem, AccordionTrigger, AccordionContent, Label, Sheet, SheetTrigger, SheetContent, StatusIndicator, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandSeparator, CommandGroup, CommandItem, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, ContextMenu as ContextMenu$1, ContextMenuTrigger, ContextMenuContent, AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, CommandShortcut, Popover, PopoverTrigger, PopoverContent, Spinner, SidebarProvider, SidebarInset, CardHeader, CardTitle, CardDescription, CardContent, InputOTP, InputOTPGroup, InputOTPSlot, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose, ContextMenuSeparator, ContextMenuLabel, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent, ContextMenuItem, ContextMenuShortcut, useSidebar, Sidebar, SidebarHeader, SidebarMenu, SidebarMenuItem, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarMenuButton, SidebarFooter, SidebarTrigger, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup } from '@olwiba/cn';
|
|
6
6
|
export { CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Enchanted } from '@olwiba/cn';
|
|
@@ -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 = React21.createContext({
|
|
17
17
|
isMobile: false,
|
|
18
18
|
mode: "default",
|
|
19
19
|
setMode: () => {
|
|
@@ -22,17 +22,17 @@ var OlwibaUIContext = React20.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] = React21.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 React21.useContext(OlwibaUIContext);
|
|
31
31
|
}
|
|
32
32
|
function useUIMode() {
|
|
33
|
-
return
|
|
33
|
+
return React21.useContext(OlwibaUIContext).mode;
|
|
34
34
|
}
|
|
35
|
-
var Button =
|
|
35
|
+
var Button = React21.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 = React20.forwardRef(
|
|
|
40
40
|
}
|
|
41
41
|
);
|
|
42
42
|
Button.displayName = "Button";
|
|
43
|
-
var Card =
|
|
43
|
+
var Card = React21.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 = React21.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 = React20.forwardRef(
|
|
|
59
59
|
}
|
|
60
60
|
);
|
|
61
61
|
Input.displayName = "Input";
|
|
62
|
-
var Textarea =
|
|
62
|
+
var Textarea = React21.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 = React20.forwardRef(
|
|
|
67
67
|
}
|
|
68
68
|
);
|
|
69
69
|
Textarea.displayName = "Textarea";
|
|
70
|
-
var Checkbox =
|
|
70
|
+
var Checkbox = React21.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 = React21.forwardRef(({ mode: _mode, ...props }, ref) => {
|
|
77
77
|
return /* @__PURE__ */ jsx(Switch$1, { ...props, ref });
|
|
78
78
|
});
|
|
79
79
|
Switch.displayName = "Switch";
|
|
@@ -626,7 +626,7 @@ function DefaultForm({
|
|
|
626
626
|
const isForgotPassword = mode === "forgot-password";
|
|
627
627
|
const isResetPassword = mode === "reset-password";
|
|
628
628
|
const isVerify = mode === "verify";
|
|
629
|
-
const [code, setCode] =
|
|
629
|
+
const [code, setCode] = React21.useState("");
|
|
630
630
|
const hasPrefill = !!(defaultEmail || defaultPassword);
|
|
631
631
|
const prefillStyle = (active) => active ? { animation: "auth-prefill 1.6s ease-out 0.35s 1 both" } : void 0;
|
|
632
632
|
const copy = authCopy[mode];
|
|
@@ -787,10 +787,10 @@ function DataTable({
|
|
|
787
787
|
emptyMessage = "No results.",
|
|
788
788
|
className
|
|
789
789
|
}) {
|
|
790
|
-
const [sorting, setSorting] =
|
|
791
|
-
const [rowSelection, setRowSelection] =
|
|
792
|
-
const [globalFilter, setGlobalFilter] =
|
|
793
|
-
const allColumns =
|
|
790
|
+
const [sorting, setSorting] = React21.useState([]);
|
|
791
|
+
const [rowSelection, setRowSelection] = React21.useState({});
|
|
792
|
+
const [globalFilter, setGlobalFilter] = React21.useState("");
|
|
793
|
+
const allColumns = React21.useMemo(
|
|
794
794
|
() => selectable ? [selectColumn, ...columns] : columns,
|
|
795
795
|
[selectable, columns]
|
|
796
796
|
);
|
|
@@ -812,7 +812,7 @@ function DataTable({
|
|
|
812
812
|
initialState: pageSize > 0 ? { pagination: { pageSize } } : void 0,
|
|
813
813
|
enableRowSelection: selectable
|
|
814
814
|
});
|
|
815
|
-
|
|
815
|
+
React21.useEffect(() => {
|
|
816
816
|
if (!onSelectionChange) return;
|
|
817
817
|
onSelectionChange(table.getSelectedRowModel().rows.map((r) => r.original));
|
|
818
818
|
}, [rowSelection]);
|
|
@@ -892,8 +892,8 @@ function DataTable({
|
|
|
892
892
|
] });
|
|
893
893
|
}
|
|
894
894
|
function InviteDialog({ roles, onInvite, onClose }) {
|
|
895
|
-
const [email, setEmail] =
|
|
896
|
-
const [role, setRole] =
|
|
895
|
+
const [email, setEmail] = React21.useState("");
|
|
896
|
+
const [role, setRole] = React21.useState(roles[roles.length - 1] ?? roles[0]);
|
|
897
897
|
return /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsxs(
|
|
898
898
|
"form",
|
|
899
899
|
{
|
|
@@ -937,8 +937,8 @@ function TeamMembersPanel({
|
|
|
937
937
|
title = "Team members",
|
|
938
938
|
description = "Manage who has access to this workspace."
|
|
939
939
|
}) {
|
|
940
|
-
const [inviteOpen, setInviteOpen] =
|
|
941
|
-
const columns =
|
|
940
|
+
const [inviteOpen, setInviteOpen] = React21.useState(false);
|
|
941
|
+
const columns = React21.useMemo(() => [
|
|
942
942
|
{
|
|
943
943
|
accessorKey: "name",
|
|
944
944
|
header: "Name",
|
|
@@ -1007,7 +1007,7 @@ function BillingPanel({
|
|
|
1007
1007
|
onUpdatePaymentMethod,
|
|
1008
1008
|
className
|
|
1009
1009
|
}) {
|
|
1010
|
-
const invoiceColumns =
|
|
1010
|
+
const invoiceColumns = React21.useMemo(() => [
|
|
1011
1011
|
{ accessorKey: "date", header: "Date", enableSorting: false },
|
|
1012
1012
|
{ accessorKey: "amount", header: "Amount", enableSorting: false },
|
|
1013
1013
|
{
|
|
@@ -1086,9 +1086,9 @@ function OnboardingWizard({
|
|
|
1086
1086
|
completeLabel = "Finish",
|
|
1087
1087
|
className
|
|
1088
1088
|
}) {
|
|
1089
|
-
const [internalStep, setInternalStep] =
|
|
1090
|
-
const [error, setError] =
|
|
1091
|
-
const [pending, setPending] =
|
|
1089
|
+
const [internalStep, setInternalStep] = React21.useState(0);
|
|
1090
|
+
const [error, setError] = React21.useState(null);
|
|
1091
|
+
const [pending, setPending] = React21.useState(false);
|
|
1092
1092
|
const index = stepProp ?? internalStep;
|
|
1093
1093
|
const current = steps[index];
|
|
1094
1094
|
const isLast = index === steps.length - 1;
|
|
@@ -1418,10 +1418,10 @@ function UpdateBanner({
|
|
|
1418
1418
|
buttonLabel = "Refresh now",
|
|
1419
1419
|
className
|
|
1420
1420
|
}) {
|
|
1421
|
-
const [show, setShow] =
|
|
1422
|
-
const [entered, setEntered] =
|
|
1423
|
-
const [refreshing, setRefreshing] =
|
|
1424
|
-
|
|
1421
|
+
const [show, setShow] = React21.useState(forceShow);
|
|
1422
|
+
const [entered, setEntered] = React21.useState(false);
|
|
1423
|
+
const [refreshing, setRefreshing] = React21.useState(false);
|
|
1424
|
+
React21.useEffect(() => {
|
|
1425
1425
|
if (forceShow) {
|
|
1426
1426
|
setShow(true);
|
|
1427
1427
|
return;
|
|
@@ -1444,7 +1444,7 @@ function UpdateBanner({
|
|
|
1444
1444
|
clearInterval(id);
|
|
1445
1445
|
};
|
|
1446
1446
|
}, [currentVersion, fetchVersion, forceShow, intervalMs]);
|
|
1447
|
-
|
|
1447
|
+
React21.useEffect(() => {
|
|
1448
1448
|
if (!show) {
|
|
1449
1449
|
setEntered(false);
|
|
1450
1450
|
return;
|
|
@@ -1517,9 +1517,9 @@ function FadeIn({
|
|
|
1517
1517
|
style,
|
|
1518
1518
|
...props
|
|
1519
1519
|
}) {
|
|
1520
|
-
const ref =
|
|
1521
|
-
const [visible, setVisible] =
|
|
1522
|
-
|
|
1520
|
+
const ref = React21.useRef(null);
|
|
1521
|
+
const [visible, setVisible] = React21.useState(false);
|
|
1522
|
+
React21.useEffect(() => {
|
|
1523
1523
|
const el = ref.current;
|
|
1524
1524
|
if (!el) return;
|
|
1525
1525
|
const observer = new IntersectionObserver(
|
|
@@ -1564,6 +1564,36 @@ var marketingSectionSpacing = {
|
|
|
1564
1564
|
standard: "px-6 py-14 sm:px-10 sm:py-20",
|
|
1565
1565
|
hero: "px-6 pb-14 pt-10 sm:px-10 sm:py-20"
|
|
1566
1566
|
};
|
|
1567
|
+
var MarketingSurfaceContext = React21.createContext(void 0);
|
|
1568
|
+
function MarketingSurfaceProvider({
|
|
1569
|
+
surface,
|
|
1570
|
+
children
|
|
1571
|
+
}) {
|
|
1572
|
+
return /* @__PURE__ */ jsx(MarketingSurfaceContext.Provider, { value: surface, children });
|
|
1573
|
+
}
|
|
1574
|
+
function useMarketingSurface() {
|
|
1575
|
+
return React21.useContext(MarketingSurfaceContext);
|
|
1576
|
+
}
|
|
1577
|
+
function useSectionSurface(override) {
|
|
1578
|
+
const mode = useUIVariant();
|
|
1579
|
+
const contextSurface = useMarketingSurface();
|
|
1580
|
+
const surface = override ?? contextSurface ?? "card";
|
|
1581
|
+
if (surface === "plain") return "overflow-hidden";
|
|
1582
|
+
if (surface === "soft") {
|
|
1583
|
+
return cn$1(
|
|
1584
|
+
"overflow-hidden border backdrop-blur-md",
|
|
1585
|
+
mode === "smooth" && "rounded-[2rem] border-border/40 bg-card/40",
|
|
1586
|
+
mode === "playful" && "rounded-3xl border-primary/20 bg-card/50",
|
|
1587
|
+
!mode && "rounded-3xl border-border/50 bg-card/45"
|
|
1588
|
+
);
|
|
1589
|
+
}
|
|
1590
|
+
return cn$1(
|
|
1591
|
+
"overflow-hidden bg-card",
|
|
1592
|
+
mode === "smooth" && "rounded-3xl border",
|
|
1593
|
+
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
1594
|
+
!mode && "rounded-2xl border"
|
|
1595
|
+
);
|
|
1596
|
+
}
|
|
1567
1597
|
var sizes = {
|
|
1568
1598
|
sm: { outer: "w-44", height: "h-80", notch: "w-16 h-4", border: "rounded-[2rem]", screen: "rounded-[1.75rem]" },
|
|
1569
1599
|
md: { outer: "w-56", height: "h-[26rem]", notch: "w-20 h-5", border: "rounded-[2.5rem]", screen: "rounded-[2.25rem]" },
|
|
@@ -1724,16 +1754,16 @@ function Carousel({
|
|
|
1724
1754
|
className
|
|
1725
1755
|
}) {
|
|
1726
1756
|
const mode = useUIVariant();
|
|
1727
|
-
const trackRef =
|
|
1728
|
-
const [canPrev, setCanPrev] =
|
|
1729
|
-
const [canNext, setCanNext] =
|
|
1730
|
-
const updateScrollState =
|
|
1757
|
+
const trackRef = React21.useRef(null);
|
|
1758
|
+
const [canPrev, setCanPrev] = React21.useState(false);
|
|
1759
|
+
const [canNext, setCanNext] = React21.useState(true);
|
|
1760
|
+
const updateScrollState = React21.useCallback(() => {
|
|
1731
1761
|
const track = trackRef.current;
|
|
1732
1762
|
if (!track) return;
|
|
1733
1763
|
setCanPrev(track.scrollLeft > 8);
|
|
1734
1764
|
setCanNext(track.scrollLeft < track.scrollWidth - track.clientWidth - 8);
|
|
1735
1765
|
}, []);
|
|
1736
|
-
|
|
1766
|
+
React21.useEffect(() => {
|
|
1737
1767
|
const track = trackRef.current;
|
|
1738
1768
|
if (!track) return;
|
|
1739
1769
|
updateScrollState();
|
|
@@ -1790,7 +1820,7 @@ function Carousel({
|
|
|
1790
1820
|
role: "region",
|
|
1791
1821
|
"aria-label": ariaLabel,
|
|
1792
1822
|
className: "flex snap-x snap-mandatory gap-6 overflow-x-auto pb-4 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
1793
|
-
children:
|
|
1823
|
+
children: React21.Children.map(
|
|
1794
1824
|
children,
|
|
1795
1825
|
(child) => child == null ? null : /* @__PURE__ */ jsx("div", { "data-carousel-item": true, className: cn$1("shrink-0 snap-start", itemClassName), children: child })
|
|
1796
1826
|
)
|
|
@@ -1815,9 +1845,9 @@ function StaggerChildren({
|
|
|
1815
1845
|
className,
|
|
1816
1846
|
...props
|
|
1817
1847
|
}) {
|
|
1818
|
-
const ref =
|
|
1819
|
-
const [visible, setVisible] =
|
|
1820
|
-
|
|
1848
|
+
const ref = React21.useRef(null);
|
|
1849
|
+
const [visible, setVisible] = React21.useState(false);
|
|
1850
|
+
React21.useEffect(() => {
|
|
1821
1851
|
const el = ref.current;
|
|
1822
1852
|
if (!el) return;
|
|
1823
1853
|
const observer = new IntersectionObserver(
|
|
@@ -1835,7 +1865,7 @@ function StaggerChildren({
|
|
|
1835
1865
|
return () => observer.disconnect();
|
|
1836
1866
|
}, [once]);
|
|
1837
1867
|
const [tx, ty] = translateMap2[direction];
|
|
1838
|
-
return /* @__PURE__ */ jsx("div", { ref, className: cn$1(className), ...props, children:
|
|
1868
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn$1(className), ...props, children: React21.Children.map(children, (child, i) => /* @__PURE__ */ jsx(
|
|
1839
1869
|
"div",
|
|
1840
1870
|
{
|
|
1841
1871
|
className: "h-full",
|
|
@@ -1854,15 +1884,10 @@ function FeaturesSection({
|
|
|
1854
1884
|
description = "A complete system of components, blocks, and hooks designed to work together - and get out of your way.",
|
|
1855
1885
|
badge = "Features",
|
|
1856
1886
|
features,
|
|
1857
|
-
layout = "grid"
|
|
1887
|
+
layout = "grid",
|
|
1888
|
+
surface
|
|
1858
1889
|
}) {
|
|
1859
|
-
const
|
|
1860
|
-
const sectionClasses = cn$1(
|
|
1861
|
-
"overflow-hidden bg-card",
|
|
1862
|
-
mode === "smooth" && "rounded-3xl border",
|
|
1863
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
1864
|
-
!mode && "rounded-2xl border"
|
|
1865
|
-
);
|
|
1890
|
+
const sectionClasses = useSectionSurface(surface);
|
|
1866
1891
|
const cards = features.map((feature) => /* @__PURE__ */ jsx(
|
|
1867
1892
|
FeatureCard,
|
|
1868
1893
|
{
|
|
@@ -1882,15 +1907,10 @@ function GroupedFeaturesSection({
|
|
|
1882
1907
|
badge = "Features",
|
|
1883
1908
|
title = "Everything you need to ship",
|
|
1884
1909
|
description,
|
|
1885
|
-
groups
|
|
1910
|
+
groups,
|
|
1911
|
+
surface
|
|
1886
1912
|
}) {
|
|
1887
|
-
const
|
|
1888
|
-
const sectionClasses = cn$1(
|
|
1889
|
-
"overflow-hidden bg-card",
|
|
1890
|
-
mode === "smooth" && "rounded-3xl border",
|
|
1891
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
1892
|
-
!mode && "rounded-2xl border"
|
|
1893
|
-
);
|
|
1913
|
+
const sectionClasses = useSectionSurface(surface);
|
|
1894
1914
|
return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
|
|
1895
1915
|
/* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
|
|
1896
1916
|
/* @__PURE__ */ jsx("div", { className: "mt-14 space-y-14", children: groups.map((group, i) => /* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -1960,15 +1980,10 @@ function StepsSection({
|
|
|
1960
1980
|
description,
|
|
1961
1981
|
steps,
|
|
1962
1982
|
variant = "default",
|
|
1963
|
-
groups
|
|
1983
|
+
groups,
|
|
1984
|
+
surface
|
|
1964
1985
|
}) {
|
|
1965
|
-
const
|
|
1966
|
-
const sectionClasses = cn$1(
|
|
1967
|
-
"overflow-hidden bg-card",
|
|
1968
|
-
mode === "smooth" && "rounded-3xl border",
|
|
1969
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
1970
|
-
!mode && "rounded-2xl border"
|
|
1971
|
-
);
|
|
1986
|
+
const sectionClasses = useSectionSurface(surface);
|
|
1972
1987
|
if (variant === "timeline") {
|
|
1973
1988
|
const resolvedGroups = groups ?? (steps ? [{ steps }] : []);
|
|
1974
1989
|
let nextNumber = 1;
|
|
@@ -1977,7 +1992,7 @@ function StepsSection({
|
|
|
1977
1992
|
/* @__PURE__ */ jsx("div", { className: "mt-12", children: resolvedGroups.map((group, groupIndex) => {
|
|
1978
1993
|
const startNumber = nextNumber;
|
|
1979
1994
|
nextNumber += group.steps.length;
|
|
1980
|
-
return /* @__PURE__ */ jsxs(
|
|
1995
|
+
return /* @__PURE__ */ jsxs(React21.Fragment, { children: [
|
|
1981
1996
|
/* @__PURE__ */ jsx("div", { className: cn$1(groupIndex > 0 && "mt-10"), children: /* @__PURE__ */ jsx(TimelineGroup, { steps: group.steps, startNumber, fadeIn: groupIndex > 0 }) }),
|
|
1982
1997
|
group.after && /* @__PURE__ */ jsx("div", { className: "mt-16", children: group.after })
|
|
1983
1998
|
] }, groupIndex);
|
|
@@ -2021,15 +2036,11 @@ function TechStackSection({
|
|
|
2021
2036
|
badge = "Built on",
|
|
2022
2037
|
title = "The stack",
|
|
2023
2038
|
description,
|
|
2024
|
-
items
|
|
2039
|
+
items,
|
|
2040
|
+
surface
|
|
2025
2041
|
}) {
|
|
2026
2042
|
const mode = useUIVariant();
|
|
2027
|
-
const sectionClasses =
|
|
2028
|
-
"overflow-hidden bg-card",
|
|
2029
|
-
mode === "smooth" && "rounded-3xl border",
|
|
2030
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
2031
|
-
!mode && "rounded-2xl border"
|
|
2032
|
-
);
|
|
2043
|
+
const sectionClasses = useSectionSurface(surface);
|
|
2033
2044
|
return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
|
|
2034
2045
|
/* @__PURE__ */ jsx(SectionTitle, { badge, title, description }),
|
|
2035
2046
|
/* @__PURE__ */ jsx(StaggerChildren, { className: "mt-12 grid gap-4 sm:grid-cols-2 lg:grid-cols-4", children: items.map((item) => {
|
|
@@ -2077,16 +2088,11 @@ function FeatureMarqueeSection({
|
|
|
2077
2088
|
description,
|
|
2078
2089
|
rows,
|
|
2079
2090
|
speed = "normal",
|
|
2080
|
-
pauseOnHover = true
|
|
2091
|
+
pauseOnHover = true,
|
|
2092
|
+
surface
|
|
2081
2093
|
}) {
|
|
2082
|
-
const mode = useUIVariant();
|
|
2083
2094
|
const duration = speedDuration[speed];
|
|
2084
|
-
const sectionClasses =
|
|
2085
|
-
"overflow-hidden bg-card",
|
|
2086
|
-
mode === "smooth" && "rounded-3xl border",
|
|
2087
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
2088
|
-
!mode && "rounded-2xl border"
|
|
2089
|
-
);
|
|
2095
|
+
const sectionClasses = useSectionSurface(surface);
|
|
2090
2096
|
return /* @__PURE__ */ jsxs("section", { className: sectionClasses, children: [
|
|
2091
2097
|
/* @__PURE__ */ jsxs("div", { className: "py-14 sm:py-20", children: [
|
|
2092
2098
|
(title || badge || description) && /* @__PURE__ */ jsx(FadeIn, { direction: "up", children: /* @__PURE__ */ jsx("div", { className: "mx-auto mb-10 max-w-4xl px-6 sm:px-10", children: /* @__PURE__ */ jsx(SectionTitle, { title: title ?? "", description, badge }) }) }),
|
|
@@ -2147,9 +2153,9 @@ function FeatureMarqueeSection({
|
|
|
2147
2153
|
] });
|
|
2148
2154
|
}
|
|
2149
2155
|
function useIntersectionObserver(options) {
|
|
2150
|
-
const ref =
|
|
2151
|
-
const [isIntersecting, setIsIntersecting] =
|
|
2152
|
-
|
|
2156
|
+
const ref = React21.useRef(null);
|
|
2157
|
+
const [isIntersecting, setIsIntersecting] = React21.useState(false);
|
|
2158
|
+
React21.useEffect(() => {
|
|
2153
2159
|
const el = ref.current;
|
|
2154
2160
|
if (!el) return;
|
|
2155
2161
|
const observer = new IntersectionObserver(([entry]) => {
|
|
@@ -2171,8 +2177,8 @@ function ShowcaseCta({
|
|
|
2171
2177
|
sectionClasses
|
|
2172
2178
|
}) {
|
|
2173
2179
|
const [ref, intersecting] = useIntersectionObserver({ threshold: 0.15 });
|
|
2174
|
-
const [visible, setVisible] =
|
|
2175
|
-
|
|
2180
|
+
const [visible, setVisible] = React21.useState(false);
|
|
2181
|
+
React21.useEffect(() => {
|
|
2176
2182
|
if (intersecting) setVisible(true);
|
|
2177
2183
|
}, [intersecting]);
|
|
2178
2184
|
return /* @__PURE__ */ jsxs(
|
|
@@ -2221,15 +2227,11 @@ function CtaSection(props) {
|
|
|
2221
2227
|
secondaryCta,
|
|
2222
2228
|
footnote,
|
|
2223
2229
|
variant = "default",
|
|
2224
|
-
renderLink = defaultRenderLink5
|
|
2230
|
+
renderLink = defaultRenderLink5,
|
|
2231
|
+
surface
|
|
2225
2232
|
} = props;
|
|
2226
2233
|
const mode = useUIVariant();
|
|
2227
|
-
const sectionClasses =
|
|
2228
|
-
"overflow-hidden bg-card",
|
|
2229
|
-
mode === "smooth" && "rounded-3xl border",
|
|
2230
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
2231
|
-
!mode && "rounded-2xl border"
|
|
2232
|
-
);
|
|
2234
|
+
const sectionClasses = useSectionSurface(surface);
|
|
2233
2235
|
if (variant === "showcase") {
|
|
2234
2236
|
return /* @__PURE__ */ jsx(ShowcaseCta, { ...props, sectionClasses });
|
|
2235
2237
|
}
|
|
@@ -2313,25 +2315,25 @@ function AnimatedSwap({
|
|
|
2313
2315
|
const ms = duration ?? spec?.duration ?? 0;
|
|
2314
2316
|
const reduced = usePrefersReducedMotion();
|
|
2315
2317
|
const animated = spec !== null && !reduced;
|
|
2316
|
-
const previous =
|
|
2317
|
-
const seenKey =
|
|
2318
|
-
const [swap, setSwap] =
|
|
2318
|
+
const previous = React21.useRef(children);
|
|
2319
|
+
const seenKey = React21.useRef(swapKey);
|
|
2320
|
+
const [swap, setSwap] = React21.useState(null);
|
|
2319
2321
|
if (seenKey.current !== swapKey) {
|
|
2320
2322
|
const out = previous.current;
|
|
2321
2323
|
seenKey.current = swapKey;
|
|
2322
2324
|
if (animated) setSwap({ key: swapKey, out, running: false });
|
|
2323
2325
|
}
|
|
2324
|
-
|
|
2326
|
+
React21.useEffect(() => {
|
|
2325
2327
|
previous.current = children;
|
|
2326
2328
|
});
|
|
2327
|
-
|
|
2329
|
+
React21.useEffect(() => {
|
|
2328
2330
|
if (!swap || swap.running) return;
|
|
2329
2331
|
const raf = requestAnimationFrame(() => {
|
|
2330
2332
|
setSwap((s) => s && s.key === swap.key ? { ...s, running: true } : s);
|
|
2331
2333
|
});
|
|
2332
2334
|
return () => cancelAnimationFrame(raf);
|
|
2333
2335
|
}, [swap]);
|
|
2334
|
-
|
|
2336
|
+
React21.useEffect(() => {
|
|
2335
2337
|
if (!swap?.running) return;
|
|
2336
2338
|
const done = setTimeout(() => {
|
|
2337
2339
|
setSwap((s) => s && s.key === swap.key ? null : s);
|
|
@@ -2361,8 +2363,8 @@ function AnimatedSwap({
|
|
|
2361
2363
|
);
|
|
2362
2364
|
}
|
|
2363
2365
|
function usePrefersReducedMotion() {
|
|
2364
|
-
const [reduced, setReduced] =
|
|
2365
|
-
|
|
2366
|
+
const [reduced, setReduced] = React21.useState(false);
|
|
2367
|
+
React21.useEffect(() => {
|
|
2366
2368
|
const query = window.matchMedia?.("(prefers-reduced-motion: reduce)");
|
|
2367
2369
|
if (!query) return;
|
|
2368
2370
|
setReduced(query.matches);
|
|
@@ -2474,8 +2476,8 @@ function CountdownTimer({
|
|
|
2474
2476
|
className,
|
|
2475
2477
|
compact = false
|
|
2476
2478
|
}) {
|
|
2477
|
-
const [timeLeft, setTimeLeft] =
|
|
2478
|
-
|
|
2479
|
+
const [timeLeft, setTimeLeft] = React21.useState(() => getTimeLeft(deadline));
|
|
2480
|
+
React21.useEffect(() => {
|
|
2479
2481
|
setTimeLeft(getTimeLeft(deadline));
|
|
2480
2482
|
const id = setInterval(() => setTimeLeft(getTimeLeft(deadline)), 1e3);
|
|
2481
2483
|
return () => clearInterval(id);
|
|
@@ -2501,7 +2503,7 @@ function CountdownTimer({
|
|
|
2501
2503
|
];
|
|
2502
2504
|
return /* @__PURE__ */ jsxs("div", { className: cn$1("flex items-center justify-center gap-2 text-sm", className), children: [
|
|
2503
2505
|
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label }),
|
|
2504
|
-
/* @__PURE__ */ jsx("span", { className: "flex items-center gap-1 font-mono font-semibold tabular-nums", children: units.map(({ value, unit }, i) => /* @__PURE__ */ jsxs(
|
|
2506
|
+
/* @__PURE__ */ jsx("span", { className: "flex items-center gap-1 font-mono font-semibold tabular-nums", children: units.map(({ value, unit }, i) => /* @__PURE__ */ jsxs(React21.Fragment, { children: [
|
|
2505
2507
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
2506
2508
|
String(value).padStart(2, "0"),
|
|
2507
2509
|
/* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: unit })
|
|
@@ -2555,26 +2557,21 @@ function PricingSection({
|
|
|
2555
2557
|
defaultCadence,
|
|
2556
2558
|
onSelectPlan,
|
|
2557
2559
|
pendingPlanName,
|
|
2558
|
-
priceEffect
|
|
2560
|
+
priceEffect,
|
|
2561
|
+
surface
|
|
2559
2562
|
}) {
|
|
2560
|
-
const [annual, setAnnual] =
|
|
2563
|
+
const [annual, setAnnual] = React21.useState(false);
|
|
2561
2564
|
const isOneTime = mode === "one-time";
|
|
2562
2565
|
const useCadences = !!cadences?.length;
|
|
2563
2566
|
const initialCadence = (defaultCadence && cadences?.some((c) => c.key === defaultCadence) ? defaultCadence : null) ?? cadences?.[0]?.key ?? "";
|
|
2564
|
-
const [activeCadence, setActiveCadence] =
|
|
2567
|
+
const [activeCadence, setActiveCadence] = React21.useState(initialCadence);
|
|
2565
2568
|
const cadence = cadences?.find((c) => c.key === activeCadence);
|
|
2566
|
-
const saveBadges =
|
|
2569
|
+
const saveBadges = React21.useMemo(
|
|
2567
2570
|
() => useCadences ? computeSaveBadges(plans, cadences, initialCadence) : {},
|
|
2568
2571
|
[useCadences, plans, cadences, initialCadence]
|
|
2569
2572
|
);
|
|
2570
2573
|
const showToggle = useCadences ? cadences.length > 1 : !isOneTime;
|
|
2571
|
-
const
|
|
2572
|
-
const sectionClasses = cn$1(
|
|
2573
|
-
"overflow-hidden bg-card",
|
|
2574
|
-
uiMode === "smooth" && "rounded-3xl border",
|
|
2575
|
-
uiMode === "playful" && "rounded-2xl border-primary/25 border",
|
|
2576
|
-
!uiMode && "rounded-2xl border"
|
|
2577
|
-
);
|
|
2574
|
+
const sectionClasses = useSectionSurface(surface);
|
|
2578
2575
|
return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-5xl", children: [
|
|
2579
2576
|
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
2580
2577
|
badge && (typeof badge === "string" ? /* @__PURE__ */ jsx(Badge$1, { variant: "secondary", className: "mb-4", children: badge }) : /* @__PURE__ */ jsx("div", { className: "mb-4", children: badge })),
|
|
@@ -2729,15 +2726,10 @@ function TestimonialsSection({
|
|
|
2729
2726
|
title = "Trusted by teams shipping real products",
|
|
2730
2727
|
description = "Here's what engineers and product teams say after using Olwiba in production.",
|
|
2731
2728
|
badge = "Testimonials",
|
|
2732
|
-
testimonials
|
|
2729
|
+
testimonials,
|
|
2730
|
+
surface
|
|
2733
2731
|
}) {
|
|
2734
|
-
const
|
|
2735
|
-
const sectionClasses = cn$1(
|
|
2736
|
-
"overflow-hidden bg-card",
|
|
2737
|
-
mode === "smooth" && "rounded-3xl border",
|
|
2738
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
2739
|
-
!mode && "rounded-2xl border"
|
|
2740
|
-
);
|
|
2732
|
+
const sectionClasses = useSectionSurface(surface);
|
|
2741
2733
|
return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-5xl", children: [
|
|
2742
2734
|
/* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
|
|
2743
2735
|
/* @__PURE__ */ jsx(StaggerChildren, { className: "mt-12 columns-1 gap-4 sm:columns-2 lg:columns-3", children: testimonials.map((t) => /* @__PURE__ */ jsx(
|
|
@@ -2791,15 +2783,10 @@ function TeamSection({
|
|
|
2791
2783
|
members = defaultTeam,
|
|
2792
2784
|
badge = "Team",
|
|
2793
2785
|
title = "The people behind Olwiba",
|
|
2794
|
-
description = "A small team with deep experience in design systems, open source, and developer tooling."
|
|
2786
|
+
description = "A small team with deep experience in design systems, open source, and developer tooling.",
|
|
2787
|
+
surface
|
|
2795
2788
|
}) {
|
|
2796
|
-
const
|
|
2797
|
-
const sectionClasses = cn$1(
|
|
2798
|
-
"overflow-hidden bg-card",
|
|
2799
|
-
mode === "smooth" && "rounded-3xl border",
|
|
2800
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
2801
|
-
!mode && "rounded-2xl border"
|
|
2802
|
-
);
|
|
2789
|
+
const sectionClasses = useSectionSurface(surface);
|
|
2803
2790
|
return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-5xl", children: [
|
|
2804
2791
|
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
2805
2792
|
/* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "mb-4", children: badge }),
|
|
@@ -2830,15 +2817,10 @@ function FaqSection({
|
|
|
2830
2817
|
title = "Frequently asked questions",
|
|
2831
2818
|
description = "Everything you need to know before getting started.",
|
|
2832
2819
|
badge = "FAQ",
|
|
2833
|
-
items
|
|
2820
|
+
items,
|
|
2821
|
+
surface
|
|
2834
2822
|
}) {
|
|
2835
|
-
const
|
|
2836
|
-
const sectionClasses = cn$1(
|
|
2837
|
-
"overflow-hidden bg-card",
|
|
2838
|
-
mode === "smooth" && "rounded-3xl border",
|
|
2839
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
2840
|
-
!mode && "rounded-2xl border"
|
|
2841
|
-
);
|
|
2823
|
+
const sectionClasses = useSectionSurface(surface);
|
|
2842
2824
|
return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-3xl", children: [
|
|
2843
2825
|
/* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
|
|
2844
2826
|
/* @__PURE__ */ jsx(FadeIn, { direction: "up", children: /* @__PURE__ */ jsx(Accordion, { type: "single", collapsible: true, className: "mt-10 w-full", children: items.map((item, i) => /* @__PURE__ */ jsxs(AccordionItem, { value: `item-${i}`, children: [
|
|
@@ -2858,10 +2840,10 @@ function CountUp({
|
|
|
2858
2840
|
className,
|
|
2859
2841
|
...props
|
|
2860
2842
|
}) {
|
|
2861
|
-
const ref =
|
|
2862
|
-
const [value, setValue] =
|
|
2863
|
-
const hasStarted =
|
|
2864
|
-
|
|
2843
|
+
const ref = React21.useRef(null);
|
|
2844
|
+
const [value, setValue] = React21.useState(from);
|
|
2845
|
+
const hasStarted = React21.useRef(false);
|
|
2846
|
+
React21.useEffect(() => {
|
|
2865
2847
|
const el = ref.current;
|
|
2866
2848
|
if (!el) return;
|
|
2867
2849
|
const observer = new IntersectionObserver(
|
|
@@ -2907,15 +2889,10 @@ function StatsSection({
|
|
|
2907
2889
|
title = "Built for scale, used in production",
|
|
2908
2890
|
description,
|
|
2909
2891
|
badge = "By the numbers",
|
|
2910
|
-
stats
|
|
2892
|
+
stats,
|
|
2893
|
+
surface
|
|
2911
2894
|
}) {
|
|
2912
|
-
const
|
|
2913
|
-
const sectionClasses = cn$1(
|
|
2914
|
-
"overflow-hidden bg-card",
|
|
2915
|
-
mode === "smooth" && "rounded-3xl border",
|
|
2916
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
2917
|
-
!mode && "rounded-2xl border"
|
|
2918
|
-
);
|
|
2895
|
+
const sectionClasses = useSectionSurface(surface);
|
|
2919
2896
|
return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsxs("div", { className: "relative px-6 py-14 sm:px-10 sm:py-20", children: [
|
|
2920
2897
|
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-[radial-gradient(ellipse_at_bottom,hsl(var(--primary)/0.08),transparent_60%)]" }),
|
|
2921
2898
|
/* @__PURE__ */ jsxs("div", { className: "relative mx-auto max-w-4xl", children: [
|
|
@@ -2952,17 +2929,12 @@ function NewsletterSection({
|
|
|
2952
2929
|
privacyLabel = defaults.privacyLabel,
|
|
2953
2930
|
successTitle = defaults.successTitle,
|
|
2954
2931
|
successDescription = defaults.successDescription,
|
|
2955
|
-
onSubscribe
|
|
2932
|
+
onSubscribe,
|
|
2933
|
+
surface
|
|
2956
2934
|
} = {}) {
|
|
2957
|
-
const [email, setEmail] =
|
|
2958
|
-
const [submitted, setSubmitted] =
|
|
2959
|
-
const
|
|
2960
|
-
const sectionClasses = cn$1(
|
|
2961
|
-
"overflow-hidden bg-card",
|
|
2962
|
-
mode === "smooth" && "rounded-3xl border",
|
|
2963
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
2964
|
-
!mode && "rounded-2xl border"
|
|
2965
|
-
);
|
|
2935
|
+
const [email, setEmail] = React21.useState("");
|
|
2936
|
+
const [submitted, setSubmitted] = React21.useState(false);
|
|
2937
|
+
const sectionClasses = useSectionSurface(surface);
|
|
2966
2938
|
async function handleSubmit(e) {
|
|
2967
2939
|
e.preventDefault();
|
|
2968
2940
|
if (!email) return;
|
|
@@ -3044,16 +3016,11 @@ function ContactSection({
|
|
|
3044
3016
|
successTitle = defaults2.successTitle,
|
|
3045
3017
|
successDescription = defaults2.successDescription,
|
|
3046
3018
|
sendAnotherLabel = defaults2.sendAnotherLabel,
|
|
3047
|
-
onSubmit
|
|
3019
|
+
onSubmit,
|
|
3020
|
+
surface
|
|
3048
3021
|
} = {}) {
|
|
3049
|
-
const [submitted, setSubmitted] =
|
|
3050
|
-
const
|
|
3051
|
-
const sectionClasses = cn$1(
|
|
3052
|
-
"overflow-hidden bg-card",
|
|
3053
|
-
mode === "smooth" && "rounded-3xl border",
|
|
3054
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
3055
|
-
!mode && "rounded-2xl border"
|
|
3056
|
-
);
|
|
3022
|
+
const [submitted, setSubmitted] = React21.useState(false);
|
|
3023
|
+
const sectionClasses = useSectionSurface(surface);
|
|
3057
3024
|
async function handleSubmit(e) {
|
|
3058
3025
|
e.preventDefault();
|
|
3059
3026
|
await onSubmit?.(e);
|
|
@@ -3237,15 +3204,10 @@ function ComparisonSection({
|
|
|
3237
3204
|
badge = "The math",
|
|
3238
3205
|
title = "The math is simple",
|
|
3239
3206
|
description,
|
|
3240
|
-
columns
|
|
3207
|
+
columns,
|
|
3208
|
+
surface
|
|
3241
3209
|
}) {
|
|
3242
|
-
const
|
|
3243
|
-
const sectionClasses = cn$1(
|
|
3244
|
-
"overflow-hidden bg-card",
|
|
3245
|
-
mode === "smooth" && "rounded-3xl border",
|
|
3246
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
3247
|
-
!mode && "rounded-2xl border"
|
|
3248
|
-
);
|
|
3210
|
+
const sectionClasses = useSectionSurface(surface);
|
|
3249
3211
|
return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
|
|
3250
3212
|
/* @__PURE__ */ jsx(SectionTitle, { badge, title, description }),
|
|
3251
3213
|
/* @__PURE__ */ jsx(StaggerChildren, { className: "mt-12 grid gap-4 sm:grid-cols-3", children: columns.map((col) => /* @__PURE__ */ jsxs(
|
|
@@ -3293,15 +3255,10 @@ function QualificationSection({
|
|
|
3293
3255
|
badge = "Who it is for",
|
|
3294
3256
|
title = "Is this for you?",
|
|
3295
3257
|
description,
|
|
3296
|
-
columns
|
|
3258
|
+
columns,
|
|
3259
|
+
surface
|
|
3297
3260
|
}) {
|
|
3298
|
-
const
|
|
3299
|
-
const sectionClasses = cn$1(
|
|
3300
|
-
"overflow-hidden bg-card",
|
|
3301
|
-
mode === "smooth" && "rounded-3xl border",
|
|
3302
|
-
mode === "playful" && "rounded-2xl border-primary/25 border",
|
|
3303
|
-
!mode && "rounded-2xl border"
|
|
3304
|
-
);
|
|
3261
|
+
const sectionClasses = useSectionSurface(surface);
|
|
3305
3262
|
return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsx("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
|
|
3306
3263
|
/* @__PURE__ */ jsx(SectionTitle, { badge, title, description }),
|
|
3307
3264
|
/* @__PURE__ */ jsx(FadeIn, { direction: "up", className: "mt-12 grid gap-6 sm:grid-cols-2", children: columns.map((col) => {
|
|
@@ -3344,10 +3301,10 @@ function Navbar({
|
|
|
3344
3301
|
controls,
|
|
3345
3302
|
renderLink = defaultRenderLink7
|
|
3346
3303
|
}) {
|
|
3347
|
-
const [open, setOpen] =
|
|
3304
|
+
const [open, setOpen] = React21.useState(false);
|
|
3348
3305
|
const brandHref = brand.href ?? "/";
|
|
3349
3306
|
const hasRightContent = controls?.length || cta?.primary || cta?.secondary;
|
|
3350
|
-
const closeMobileMenu =
|
|
3307
|
+
const closeMobileMenu = React21.useCallback(() => setOpen(false), []);
|
|
3351
3308
|
return /* @__PURE__ */ jsx("section", { className: "overflow-hidden rounded-2xl border bg-card", children: /* @__PURE__ */ jsxs("nav", { className: "grid h-16 grid-cols-[1fr_auto_1fr] items-center px-6", children: [
|
|
3352
3309
|
renderLink({
|
|
3353
3310
|
href: brandHref,
|
|
@@ -3362,7 +3319,7 @@ function Navbar({
|
|
|
3362
3319
|
children: link.label
|
|
3363
3320
|
}) }, link.label)) }),
|
|
3364
3321
|
hasRightContent && /* @__PURE__ */ jsxs("div", { className: "hidden items-center justify-end gap-2 md:flex", children: [
|
|
3365
|
-
controls?.map((control, i) => /* @__PURE__ */ jsx(
|
|
3322
|
+
controls?.map((control, i) => /* @__PURE__ */ jsx(React21.Fragment, { children: control }, i)),
|
|
3366
3323
|
(cta?.secondary || cta?.primary) && controls?.length ? /* @__PURE__ */ jsx("div", { className: "mx-1 h-4 w-px bg-border" }) : null,
|
|
3367
3324
|
cta?.secondary && renderLink({
|
|
3368
3325
|
href: cta.secondary.href,
|
|
@@ -3375,7 +3332,7 @@ function Navbar({
|
|
|
3375
3332
|
] }),
|
|
3376
3333
|
/* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
|
|
3377
3334
|
/* @__PURE__ */ jsxs("div", { className: "col-start-3 flex items-center justify-end gap-1 md:hidden", children: [
|
|
3378
|
-
controls?.map((control, i) => /* @__PURE__ */ jsx(
|
|
3335
|
+
controls?.map((control, i) => /* @__PURE__ */ jsx(React21.Fragment, { children: control }, i)),
|
|
3379
3336
|
/* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button$1, { variant: "ghost", size: "icon", children: [
|
|
3380
3337
|
/* @__PURE__ */ jsx(Menu, { className: "size-5" }),
|
|
3381
3338
|
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Open menu" })
|
|
@@ -3537,7 +3494,7 @@ function LogoStrip({
|
|
|
3537
3494
|
] });
|
|
3538
3495
|
}
|
|
3539
3496
|
function GridUnderlay({ variant, size = 24, className, ...props }) {
|
|
3540
|
-
const id =
|
|
3497
|
+
const id = React21.useId();
|
|
3541
3498
|
const pattern = variant === "dots" ? /* @__PURE__ */ jsx("circle", { cx: size / 2, cy: size / 2, r: 1, fill: "currentColor" }) : variant === "lines" ? /* @__PURE__ */ jsx("path", { d: `M ${size} 0 L 0 0 0 ${size}`, fill: "none", stroke: "currentColor", strokeWidth: 0.5 }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3542
3499
|
/* @__PURE__ */ jsx("line", { x1: size / 2, y1: 0, x2: size / 2, y2: size, stroke: "currentColor", strokeWidth: 0.5 }),
|
|
3543
3500
|
/* @__PURE__ */ jsx("line", { x1: 0, y1: size / 2, x2: size, y2: size / 2, stroke: "currentColor", strokeWidth: 0.5 })
|
|
@@ -3565,9 +3522,9 @@ function GlowUnderlay({
|
|
|
3565
3522
|
style,
|
|
3566
3523
|
...props
|
|
3567
3524
|
}) {
|
|
3568
|
-
const [pos, setPos] =
|
|
3569
|
-
const containerRef =
|
|
3570
|
-
|
|
3525
|
+
const [pos, setPos] = React21.useState({ x: "50%", y: "50%" });
|
|
3526
|
+
const containerRef = React21.useRef(null);
|
|
3527
|
+
React21.useEffect(() => {
|
|
3571
3528
|
if (!followCursor) return;
|
|
3572
3529
|
const handleMouseMove = (e) => {
|
|
3573
3530
|
const el = containerRef.current;
|
|
@@ -3706,8 +3663,8 @@ function PageTransition({
|
|
|
3706
3663
|
style,
|
|
3707
3664
|
...props
|
|
3708
3665
|
}) {
|
|
3709
|
-
const [mounted, setMounted] =
|
|
3710
|
-
|
|
3666
|
+
const [mounted, setMounted] = React21.useState(false);
|
|
3667
|
+
React21.useEffect(() => {
|
|
3711
3668
|
const id = requestAnimationFrame(() => setMounted(true));
|
|
3712
3669
|
return () => cancelAnimationFrame(id);
|
|
3713
3670
|
}, []);
|
|
@@ -3782,7 +3739,7 @@ function Sortable({
|
|
|
3782
3739
|
if (oldIndex === -1 || newIndex === -1) return;
|
|
3783
3740
|
onReorder(arrayMove(items, oldIndex, newIndex));
|
|
3784
3741
|
};
|
|
3785
|
-
const childArray =
|
|
3742
|
+
const childArray = React21.Children.toArray(children);
|
|
3786
3743
|
return /* @__PURE__ */ jsx(DndContext, { sensors, collisionDetection: closestCenter, onDragEnd: handleDragEnd, children: /* @__PURE__ */ jsx(SortableContext, { items, strategy: strategies[direction], children: /* @__PURE__ */ jsx("div", { className: cn$1(containerClasses[direction], className), children: childArray.map(
|
|
3787
3744
|
(child, i) => items[i] === void 0 ? null : /* @__PURE__ */ jsx(SortableItem, { id: items[i], disabled, className: itemClassName, children: child }, items[i])
|
|
3788
3745
|
) }) }) });
|
|
@@ -3794,8 +3751,8 @@ function Spotlight({
|
|
|
3794
3751
|
triggerClassName,
|
|
3795
3752
|
shortcut = "\u2318K"
|
|
3796
3753
|
}) {
|
|
3797
|
-
const [open, setOpen] =
|
|
3798
|
-
|
|
3754
|
+
const [open, setOpen] = React21.useState(false);
|
|
3755
|
+
React21.useEffect(() => {
|
|
3799
3756
|
const down = (e) => {
|
|
3800
3757
|
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
|
3801
3758
|
e.preventDefault();
|
|
@@ -3825,7 +3782,7 @@ function Spotlight({
|
|
|
3825
3782
|
/* @__PURE__ */ jsx(CommandInput, { placeholder }),
|
|
3826
3783
|
/* @__PURE__ */ jsxs(CommandList, { children: [
|
|
3827
3784
|
/* @__PURE__ */ jsx(CommandEmpty, { children: "No results found." }),
|
|
3828
|
-
groups.map((group, i) => /* @__PURE__ */ jsxs(
|
|
3785
|
+
groups.map((group, i) => /* @__PURE__ */ jsxs(React21.Fragment, { children: [
|
|
3829
3786
|
i > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
|
|
3830
3787
|
/* @__PURE__ */ jsx(CommandGroup, { heading: group.heading, children: group.items.map((item) => /* @__PURE__ */ jsxs(
|
|
3831
3788
|
CommandItem,
|
|
@@ -3850,8 +3807,8 @@ function Spotlight({
|
|
|
3850
3807
|
var BASE = 40;
|
|
3851
3808
|
var MAGNIFY_RADIUS = 80;
|
|
3852
3809
|
function Dock({ items, iconSize = BASE, magnification = 1.7, className, ...props }) {
|
|
3853
|
-
const [mouseX, setMouseX] =
|
|
3854
|
-
const containerRef =
|
|
3810
|
+
const [mouseX, setMouseX] = React21.useState(null);
|
|
3811
|
+
const containerRef = React21.useRef(null);
|
|
3855
3812
|
function getScale(index) {
|
|
3856
3813
|
if (mouseX === null || !containerRef.current) return 1;
|
|
3857
3814
|
const container = containerRef.current;
|
|
@@ -3950,7 +3907,7 @@ function ConfirmDialog({ isOpen, options, handleConfirm, handleCancel, destructi
|
|
|
3950
3907
|
] }) });
|
|
3951
3908
|
}
|
|
3952
3909
|
function RegisterHotkeys({ hotkeys }) {
|
|
3953
|
-
|
|
3910
|
+
React21.useEffect(() => {
|
|
3954
3911
|
const handleKeyDown = (event) => {
|
|
3955
3912
|
for (const hotkey of hotkeys) {
|
|
3956
3913
|
const matches = event.key.toLowerCase() === hotkey.key.toLowerCase() && !!event.ctrlKey === !!hotkey.ctrl && !!event.metaKey === !!hotkey.meta && !!event.shiftKey === !!hotkey.shift && !!event.altKey === !!hotkey.alt;
|
|
@@ -3967,10 +3924,10 @@ function RegisterHotkeys({ hotkeys }) {
|
|
|
3967
3924
|
return null;
|
|
3968
3925
|
}
|
|
3969
3926
|
function useControlledOpen(defaultOpen = false) {
|
|
3970
|
-
const [isOpen, setIsOpen] =
|
|
3971
|
-
const open =
|
|
3972
|
-
const close =
|
|
3973
|
-
const toggle =
|
|
3927
|
+
const [isOpen, setIsOpen] = React21.useState(defaultOpen);
|
|
3928
|
+
const open = React21.useCallback(() => setIsOpen(true), []);
|
|
3929
|
+
const close = React21.useCallback(() => setIsOpen(false), []);
|
|
3930
|
+
const toggle = React21.useCallback(() => setIsOpen((prev) => !prev), []);
|
|
3974
3931
|
return { isOpen, open, close, toggle, setIsOpen };
|
|
3975
3932
|
}
|
|
3976
3933
|
function CommandMenu({
|
|
@@ -3983,7 +3940,7 @@ function CommandMenu({
|
|
|
3983
3940
|
}) {
|
|
3984
3941
|
const internal = useControlledOpen(false);
|
|
3985
3942
|
const isOpen = openProp ?? internal.isOpen;
|
|
3986
|
-
const setOpen =
|
|
3943
|
+
const setOpen = React21.useCallback(
|
|
3987
3944
|
(next) => {
|
|
3988
3945
|
if (openProp === void 0) internal.setIsOpen(next);
|
|
3989
3946
|
onOpenChange?.(next);
|
|
@@ -4008,7 +3965,7 @@ function CommandMenu({
|
|
|
4008
3965
|
/* @__PURE__ */ jsx(CommandInput, { placeholder }),
|
|
4009
3966
|
/* @__PURE__ */ jsxs(CommandList, { children: [
|
|
4010
3967
|
/* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
|
|
4011
|
-
groups.map((group, i) => /* @__PURE__ */ jsxs(
|
|
3968
|
+
groups.map((group, i) => /* @__PURE__ */ jsxs(React21.Fragment, { children: [
|
|
4012
3969
|
i > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
|
|
4013
3970
|
/* @__PURE__ */ jsx(CommandGroup, { heading: group.heading, children: group.items.map((item) => /* @__PURE__ */ jsxs(
|
|
4014
3971
|
CommandItem,
|
|
@@ -4063,7 +4020,7 @@ function DataView({
|
|
|
4063
4020
|
}
|
|
4064
4021
|
);
|
|
4065
4022
|
}
|
|
4066
|
-
return /* @__PURE__ */ jsx(AppGrid, { columns: gridColumns, gap, className: cn$1(className), children: items.map((item) => /* @__PURE__ */ jsx(
|
|
4023
|
+
return /* @__PURE__ */ jsx(AppGrid, { columns: gridColumns, gap, className: cn$1(className), children: items.map((item) => /* @__PURE__ */ jsx(React21.Fragment, { children: renderCard(item) }, getRowId(item))) });
|
|
4067
4024
|
}
|
|
4068
4025
|
var TOKEN_COLORS = ["var(--chart-1)", "var(--chart-2)", "var(--chart-3)", "var(--chart-4)", "var(--chart-5)"];
|
|
4069
4026
|
var seriesColor = (s, i) => s.color ?? TOKEN_COLORS[i % TOKEN_COLORS.length];
|
|
@@ -4237,20 +4194,20 @@ function FileUpload({
|
|
|
4237
4194
|
hint,
|
|
4238
4195
|
className
|
|
4239
4196
|
}) {
|
|
4240
|
-
const [internalFiles, setInternalFiles] =
|
|
4241
|
-
const [isDragging, setIsDragging] =
|
|
4242
|
-
const [validationError, setValidationError] =
|
|
4243
|
-
const inputRef =
|
|
4244
|
-
const dragDepth =
|
|
4197
|
+
const [internalFiles, setInternalFiles] = React21.useState(defaultFiles ?? []);
|
|
4198
|
+
const [isDragging, setIsDragging] = React21.useState(false);
|
|
4199
|
+
const [validationError, setValidationError] = React21.useState(null);
|
|
4200
|
+
const inputRef = React21.useRef(null);
|
|
4201
|
+
const dragDepth = React21.useRef(0);
|
|
4245
4202
|
const files = filesProp ?? internalFiles;
|
|
4246
|
-
const setFiles =
|
|
4203
|
+
const setFiles = React21.useCallback(
|
|
4247
4204
|
(next) => {
|
|
4248
4205
|
if (!filesProp) setInternalFiles(next);
|
|
4249
4206
|
onFilesChange?.(next);
|
|
4250
4207
|
},
|
|
4251
4208
|
[filesProp, onFilesChange]
|
|
4252
4209
|
);
|
|
4253
|
-
const acceptList =
|
|
4210
|
+
const acceptList = React21.useMemo(
|
|
4254
4211
|
() => accept?.split(",").map((a) => a.trim().toLowerCase()).filter(Boolean) ?? [],
|
|
4255
4212
|
[accept]
|
|
4256
4213
|
);
|
|
@@ -4974,7 +4931,7 @@ function PageHeader({
|
|
|
4974
4931
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1 pb-6", className), children: [
|
|
4975
4932
|
breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-2 flex items-center gap-1 text-sm text-muted-foreground", children: breadcrumbs.map((crumb, i) => {
|
|
4976
4933
|
const isLast = i === breadcrumbs.length - 1;
|
|
4977
|
-
return /* @__PURE__ */ jsxs(
|
|
4934
|
+
return /* @__PURE__ */ jsxs(React21.Fragment, { children: [
|
|
4978
4935
|
i > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5 shrink-0" }),
|
|
4979
4936
|
isLast || !crumb.href ? /* @__PURE__ */ jsx("span", { className: cn(isLast && "text-foreground font-medium"), children: crumb.label }) : renderLink({
|
|
4980
4937
|
href: crumb.href,
|
|
@@ -5010,7 +4967,7 @@ function PageHeader({
|
|
|
5010
4967
|
] });
|
|
5011
4968
|
}
|
|
5012
4969
|
function Suspensed({ children, fallback }) {
|
|
5013
|
-
return /* @__PURE__ */ jsx(
|
|
4970
|
+
return /* @__PURE__ */ jsx(React21.Suspense, { fallback: fallback ?? /* @__PURE__ */ jsx(Spinner, {}), children });
|
|
5014
4971
|
}
|
|
5015
4972
|
function getInitialTheme() {
|
|
5016
4973
|
if (typeof document === "undefined") return "dark";
|
|
@@ -5018,7 +4975,7 @@ function getInitialTheme() {
|
|
|
5018
4975
|
return stored ?? (document.documentElement.classList.contains("dark") ? "dark" : "light");
|
|
5019
4976
|
}
|
|
5020
4977
|
function ThemeSwitchMinimal() {
|
|
5021
|
-
const [theme, setThemeState] =
|
|
4978
|
+
const [theme, setThemeState] = React21.useState(getInitialTheme);
|
|
5022
4979
|
const toggle = () => {
|
|
5023
4980
|
const next = theme === "dark" ? "light" : "dark";
|
|
5024
4981
|
setThemeState(next);
|
|
@@ -5144,9 +5101,9 @@ function getInitialColorName() {
|
|
|
5144
5101
|
return localStorage.getItem(STORAGE_KEY) ?? "emerald";
|
|
5145
5102
|
}
|
|
5146
5103
|
function BrandColorSwitchMinimal() {
|
|
5147
|
-
const [active, setActive] =
|
|
5148
|
-
const [open, setOpen] =
|
|
5149
|
-
|
|
5104
|
+
const [active, setActive] = React21.useState(getInitialColorName);
|
|
5105
|
+
const [open, setOpen] = React21.useState(false);
|
|
5106
|
+
React21.useEffect(() => {
|
|
5150
5107
|
const saved = localStorage.getItem(STORAGE_KEY) ?? "emerald";
|
|
5151
5108
|
const color = BRAND_COLORS.find((c) => c.name === saved);
|
|
5152
5109
|
if (color) applyColor(color);
|
|
@@ -5207,7 +5164,7 @@ function BrandColorSwitchMinimal() {
|
|
|
5207
5164
|
] });
|
|
5208
5165
|
}
|
|
5209
5166
|
function ThemeColorUpdater({ colorTheme }) {
|
|
5210
|
-
|
|
5167
|
+
React21.useEffect(() => {
|
|
5211
5168
|
if (colorTheme) {
|
|
5212
5169
|
document.documentElement.setAttribute("data-theme", colorTheme);
|
|
5213
5170
|
} else {
|
|
@@ -5217,7 +5174,7 @@ function ThemeColorUpdater({ colorTheme }) {
|
|
|
5217
5174
|
return null;
|
|
5218
5175
|
}
|
|
5219
5176
|
function VersionBanner({ version, message, className, onDismiss }) {
|
|
5220
|
-
const [dismissed, setDismissed] =
|
|
5177
|
+
const [dismissed, setDismissed] = React21.useState(false);
|
|
5221
5178
|
if (dismissed) return null;
|
|
5222
5179
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-4 bg-primary/10 px-4 py-2 text-sm", className), children: [
|
|
5223
5180
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -5474,29 +5431,29 @@ function useMounted() {
|
|
|
5474
5431
|
return mounted;
|
|
5475
5432
|
}
|
|
5476
5433
|
function useConfirm() {
|
|
5477
|
-
const [isOpen, setIsOpen] =
|
|
5478
|
-
const [options, setOptions] =
|
|
5479
|
-
const resolveRef =
|
|
5480
|
-
const confirm =
|
|
5434
|
+
const [isOpen, setIsOpen] = React21.useState(false);
|
|
5435
|
+
const [options, setOptions] = React21.useState({});
|
|
5436
|
+
const resolveRef = React21.useRef(null);
|
|
5437
|
+
const confirm = React21.useCallback((opts = {}) => {
|
|
5481
5438
|
setOptions(opts);
|
|
5482
5439
|
setIsOpen(true);
|
|
5483
5440
|
return new Promise((resolve) => {
|
|
5484
5441
|
resolveRef.current = resolve;
|
|
5485
5442
|
});
|
|
5486
5443
|
}, []);
|
|
5487
|
-
const handleConfirm =
|
|
5444
|
+
const handleConfirm = React21.useCallback(() => {
|
|
5488
5445
|
resolveRef.current?.(true);
|
|
5489
5446
|
setIsOpen(false);
|
|
5490
5447
|
}, []);
|
|
5491
|
-
const handleCancel =
|
|
5448
|
+
const handleCancel = React21.useCallback(() => {
|
|
5492
5449
|
resolveRef.current?.(false);
|
|
5493
5450
|
setIsOpen(false);
|
|
5494
5451
|
}, []);
|
|
5495
5452
|
return { confirm, isOpen, options, handleConfirm, handleCancel };
|
|
5496
5453
|
}
|
|
5497
5454
|
function useScrolledPast(threshold) {
|
|
5498
|
-
const [scrolledPast, setScrolledPast] =
|
|
5499
|
-
|
|
5455
|
+
const [scrolledPast, setScrolledPast] = React21.useState(false);
|
|
5456
|
+
React21.useEffect(() => {
|
|
5500
5457
|
const handleScroll = () => {
|
|
5501
5458
|
setScrolledPast(window.scrollY > threshold);
|
|
5502
5459
|
};
|
|
@@ -5507,28 +5464,28 @@ function useScrolledPast(threshold) {
|
|
|
5507
5464
|
return scrolledPast;
|
|
5508
5465
|
}
|
|
5509
5466
|
function useCopyToClipboard() {
|
|
5510
|
-
const [copied, setCopied] =
|
|
5511
|
-
const timeoutRef =
|
|
5512
|
-
const copy =
|
|
5467
|
+
const [copied, setCopied] = React21.useState(false);
|
|
5468
|
+
const timeoutRef = React21.useRef(void 0);
|
|
5469
|
+
const copy = React21.useCallback((text) => {
|
|
5513
5470
|
navigator.clipboard.writeText(text).then(() => {
|
|
5514
5471
|
setCopied(true);
|
|
5515
5472
|
clearTimeout(timeoutRef.current);
|
|
5516
5473
|
timeoutRef.current = setTimeout(() => setCopied(false), 2e3);
|
|
5517
5474
|
});
|
|
5518
5475
|
}, []);
|
|
5519
|
-
|
|
5476
|
+
React21.useEffect(() => () => clearTimeout(timeoutRef.current), []);
|
|
5520
5477
|
return [copied, copy];
|
|
5521
5478
|
}
|
|
5522
5479
|
function useDebounce(value, delay) {
|
|
5523
|
-
const [debounced, setDebounced] =
|
|
5524
|
-
|
|
5480
|
+
const [debounced, setDebounced] = React21.useState(value);
|
|
5481
|
+
React21.useEffect(() => {
|
|
5525
5482
|
const timer = setTimeout(() => setDebounced(value), delay);
|
|
5526
5483
|
return () => clearTimeout(timer);
|
|
5527
5484
|
}, [value, delay]);
|
|
5528
5485
|
return debounced;
|
|
5529
5486
|
}
|
|
5530
5487
|
function useLocalStorage(key, initialValue) {
|
|
5531
|
-
const [storedValue, setStoredValue] =
|
|
5488
|
+
const [storedValue, setStoredValue] = React21.useState(() => {
|
|
5532
5489
|
if (typeof window === "undefined") return initialValue;
|
|
5533
5490
|
try {
|
|
5534
5491
|
const item = window.localStorage.getItem(key);
|
|
@@ -5537,7 +5494,7 @@ function useLocalStorage(key, initialValue) {
|
|
|
5537
5494
|
return initialValue;
|
|
5538
5495
|
}
|
|
5539
5496
|
});
|
|
5540
|
-
const setValue =
|
|
5497
|
+
const setValue = React21.useCallback(
|
|
5541
5498
|
(value) => {
|
|
5542
5499
|
try {
|
|
5543
5500
|
setStoredValue(value);
|
|
@@ -5559,11 +5516,11 @@ function useViewMode(key = "view-mode", fallback = "cards") {
|
|
|
5559
5516
|
return { view: mounted ? stored : fallback, setView: setStored, ready: mounted };
|
|
5560
5517
|
}
|
|
5561
5518
|
function useMediaQuery(query) {
|
|
5562
|
-
const [matches, setMatches] =
|
|
5519
|
+
const [matches, setMatches] = React21.useState(() => {
|
|
5563
5520
|
if (typeof window === "undefined") return false;
|
|
5564
5521
|
return window.matchMedia(query).matches;
|
|
5565
5522
|
});
|
|
5566
|
-
|
|
5523
|
+
React21.useEffect(() => {
|
|
5567
5524
|
if (typeof window === "undefined") return;
|
|
5568
5525
|
const mql = window.matchMedia(query);
|
|
5569
5526
|
setMatches(mql.matches);
|
|
@@ -5574,18 +5531,18 @@ function useMediaQuery(query) {
|
|
|
5574
5531
|
return matches;
|
|
5575
5532
|
}
|
|
5576
5533
|
function usePagination(total, pageSize) {
|
|
5577
|
-
const [page, setPage] =
|
|
5534
|
+
const [page, setPage] = React21.useState(1);
|
|
5578
5535
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
5579
5536
|
const offset = (page - 1) * pageSize;
|
|
5580
|
-
const goTo =
|
|
5537
|
+
const goTo = React21.useCallback(
|
|
5581
5538
|
(p) => setPage(Math.min(Math.max(1, p), totalPages)),
|
|
5582
5539
|
[totalPages]
|
|
5583
5540
|
);
|
|
5584
|
-
const next =
|
|
5585
|
-
const prev =
|
|
5541
|
+
const next = React21.useCallback(() => goTo(page + 1), [page, goTo]);
|
|
5542
|
+
const prev = React21.useCallback(() => goTo(page - 1), [page, goTo]);
|
|
5586
5543
|
return { page, pageSize, totalPages, offset, hasPrev: page > 1, hasNext: page < totalPages, goTo, next, prev };
|
|
5587
5544
|
}
|
|
5588
5545
|
|
|
5589
|
-
export { ActivityFeed, AnimatedPill, AnimatedSwap, AppContent, AppGrid, AppGridCell, AppPageHero, AppScreen, AppShell, AuthSection, Badge, BillingPanel, BrandColorSwitchMinimal, Button, Card, Carousel, ChangelogCard, ChangelogList, Chart, Checkbox, CommandMenu, ComparisonSection, ConfirmDialog, ContactSection, ContextMenu, CountUp, CountdownTimer, CtaSection, DataTable, DataView, DevBanner, Dock, EmptyState, ErrorPage, FadeIn, FaqSection, FeatureCard, FeatureMarqueeSection, FeaturesSection, FileUpload, FlowBracket, FlowConnector, Footer, FullPageSpinner, GlassCard, Grid, GridItem, GroupedFeaturesSection, HeroSection, ImageCard, Input, LogoStrip, MediaCard, ModeSwitchMinimal, Navbar, NewsletterSection, NotificationToast, NotificationsPopover, OlwibaUIProvider, OnboardingWizard, Overlay, PageHeader, PageTransition, PhoneFrame, PostCard, PostList, PricingCard, PricingSection, PublicPageFrame, QualificationSection, RegisterHotkeys, RootErrorFallback, Section, SectionTitle, SettingsSection, Sortable, Spotlight, Stack, StaggerChildren, StatCard, StatsSection, StepsSection, Suspensed, Switch, TeamMembersPanel, TeamSection, TechStackSection, TestimonialCard, TestimonialsSection, Textarea, ThemeColorUpdater, ThemeSwitchMinimal, Underlay, UpdateBanner, UpgradePrompt, VersionBanner, ViewToggle, marketingSectionSpacing, notify, useConfirm, useControlledOpen, useCopyToClipboard, useDebounce, useIntersectionObserver, useLocalStorage, useMediaQuery, useMounted, useOlwibaUI, usePagination, useScrolledPast, useUIMode, useViewMode };
|
|
5546
|
+
export { ActivityFeed, AnimatedPill, AnimatedSwap, AppContent, AppGrid, AppGridCell, AppPageHero, AppScreen, AppShell, AuthSection, Badge, BillingPanel, BrandColorSwitchMinimal, Button, Card, Carousel, ChangelogCard, ChangelogList, Chart, Checkbox, CommandMenu, ComparisonSection, ConfirmDialog, ContactSection, ContextMenu, CountUp, CountdownTimer, CtaSection, DataTable, DataView, DevBanner, Dock, EmptyState, ErrorPage, FadeIn, FaqSection, FeatureCard, FeatureMarqueeSection, FeaturesSection, FileUpload, FlowBracket, FlowConnector, Footer, FullPageSpinner, GlassCard, Grid, GridItem, GroupedFeaturesSection, HeroSection, ImageCard, Input, LogoStrip, MarketingSurfaceProvider, MediaCard, ModeSwitchMinimal, Navbar, NewsletterSection, NotificationToast, NotificationsPopover, OlwibaUIProvider, OnboardingWizard, Overlay, PageHeader, PageTransition, PhoneFrame, PostCard, PostList, PricingCard, PricingSection, PublicPageFrame, QualificationSection, RegisterHotkeys, RootErrorFallback, Section, SectionTitle, SettingsSection, Sortable, Spotlight, Stack, StaggerChildren, StatCard, StatsSection, StepsSection, Suspensed, Switch, TeamMembersPanel, TeamSection, TechStackSection, TestimonialCard, TestimonialsSection, Textarea, ThemeColorUpdater, ThemeSwitchMinimal, Underlay, UpdateBanner, UpgradePrompt, VersionBanner, ViewToggle, marketingSectionSpacing, notify, useConfirm, useControlledOpen, useCopyToClipboard, useDebounce, useIntersectionObserver, useLocalStorage, useMarketingSurface, useMediaQuery, useMounted, useOlwibaUI, usePagination, useScrolledPast, useSectionSurface, useUIMode, useViewMode };
|
|
5590
5547
|
//# sourceMappingURL=index.js.map
|
|
5591
5548
|
//# sourceMappingURL=index.js.map
|