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