@olwiba/ui 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { cn } from './chunk-AMWLSHD6.js';
2
2
  export { MdxContent, cn } from './chunk-AMWLSHD6.js';
3
- import * as React25 from 'react';
3
+ import * as React26 from 'react';
4
4
  import { useState, useEffect } from 'react';
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, Separator, Accordion, AccordionItem, AccordionTrigger, AccordionContent, Label, Sheet, SheetTrigger, SheetContent, 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, Spinner, SidebarProvider, SidebarInset, CardHeader, CardTitle, CardDescription, CardContent, ContextMenuSeparator, ContextMenuLabel, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent, ContextMenuItem, ContextMenuShortcut, Sidebar, SidebarHeader, SidebarMenu, SidebarMenuItem, SidebarMenuButton, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarFooter, SidebarTrigger, useSidebar, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup, DropdownMenuItem } from '@olwiba/cn';
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, useUIVariant, Separator, Accordion, AccordionItem, AccordionTrigger, AccordionContent, Label, Sheet, SheetTrigger, SheetContent, 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, Spinner, SidebarProvider, SidebarInset, CardHeader, CardTitle, CardDescription, CardContent, ContextMenuSeparator, ContextMenuLabel, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent, ContextMenuItem, ContextMenuShortcut, Sidebar, SidebarHeader, SidebarMenu, SidebarMenuItem, SidebarMenuButton, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarFooter, SidebarTrigger, useSidebar, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup, DropdownMenuItem } from '@olwiba/cn';
6
6
  export { CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@olwiba/cn';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
- import { Compass, ArrowLeft, X, ArrowRight, Sparkles, Check, Minus, Quote, Star, Twitter, Github, Linkedin, Mail, Phone, MapPin, MessageSquare, Send, Menu, Search, TrendingUp, TrendingDown, ChevronRight, ChevronLeft, Sun, Moon, AlertTriangle, Loader2, Layers, LayoutGrid, ShieldCheck, Building2, MoreVerticalIcon, CreditCardIcon, BellIcon, LogOutIcon } from 'lucide-react';
8
+ import { Compass, ArrowLeft, X, ArrowRight, ChevronLeft, ChevronRight, Sparkles, Check, Minus, Quote, Star, Twitter, Github, Linkedin, Mail, Phone, MapPin, MessageSquare, Send, Menu, Search, TrendingUp, TrendingDown, Sun, Moon, AlertTriangle, Loader2, Layers, LayoutGrid, ShieldCheck, Building2, MoreVerticalIcon, CreditCardIcon, BellIcon, LogOutIcon } from 'lucide-react';
9
9
 
10
- var OlwibaUIContext = React25.createContext({
10
+ var OlwibaUIContext = React26.createContext({
11
11
  isMobile: false,
12
12
  mode: "default",
13
13
  setMode: () => {
@@ -16,17 +16,17 @@ var OlwibaUIContext = React25.createContext({
16
16
  function OlwibaUIProvider({ children, isMobile: isMobileProp, mode: initialMode = "default" }) {
17
17
  const detectedMobile = useIsMobile();
18
18
  const isMobile = isMobileProp ?? detectedMobile;
19
- const [mode, setMode] = React25.useState(initialMode);
19
+ const [mode, setMode] = React26.useState(initialMode);
20
20
  const variant = mode !== "default" ? mode : void 0;
21
21
  return /* @__PURE__ */ jsx(OlwibaUIContext.Provider, { value: { isMobile, mode, setMode }, children: /* @__PURE__ */ jsx(UIVariantProvider, { mode: variant, children }) });
22
22
  }
23
23
  function useOlwibaUI() {
24
- return React25.useContext(OlwibaUIContext);
24
+ return React26.useContext(OlwibaUIContext);
25
25
  }
26
26
  function useUIMode() {
27
- return React25.useContext(OlwibaUIContext).mode;
27
+ return React26.useContext(OlwibaUIContext).mode;
28
28
  }
29
- var Button = React25.forwardRef(
29
+ var Button = React26.forwardRef(
30
30
  ({ mode, ...props }, ref) => {
31
31
  const ctxMode = useUIMode();
32
32
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -34,7 +34,7 @@ var Button = React25.forwardRef(
34
34
  }
35
35
  );
36
36
  Button.displayName = "Button";
37
- var Card = React25.forwardRef(
37
+ var Card = React26.forwardRef(
38
38
  ({ mode, ...props }, ref) => {
39
39
  const ctxMode = useUIMode();
40
40
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -45,7 +45,7 @@ Card.displayName = "Card";
45
45
  function Badge(props) {
46
46
  return /* @__PURE__ */ jsx(Badge$1, { ...props });
47
47
  }
48
- var Input = React25.forwardRef(
48
+ var Input = React26.forwardRef(
49
49
  ({ mode, ...props }, ref) => {
50
50
  const ctxMode = useUIMode();
51
51
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -53,7 +53,7 @@ var Input = React25.forwardRef(
53
53
  }
54
54
  );
55
55
  Input.displayName = "Input";
56
- var Textarea = React25.forwardRef(
56
+ var Textarea = React26.forwardRef(
57
57
  ({ mode, ...props }, ref) => {
58
58
  const ctxMode = useUIMode();
59
59
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
@@ -61,13 +61,13 @@ var Textarea = React25.forwardRef(
61
61
  }
62
62
  );
63
63
  Textarea.displayName = "Textarea";
64
- var Checkbox = React25.forwardRef(({ mode, ...props }, ref) => {
64
+ var Checkbox = React26.forwardRef(({ mode, ...props }, ref) => {
65
65
  const ctxMode = useUIMode();
66
66
  const resolvedMode = mode ?? (ctxMode !== "default" ? ctxMode : void 0);
67
67
  return /* @__PURE__ */ jsx(Checkbox$1, { mode: resolvedMode, ...props, ref });
68
68
  });
69
69
  Checkbox.displayName = "Checkbox";
70
- var Switch = React25.forwardRef(({ mode: _mode, ...props }, ref) => {
70
+ var Switch = React26.forwardRef(({ mode: _mode, ...props }, ref) => {
71
71
  return /* @__PURE__ */ jsx(Switch$1, { ...props, ref });
72
72
  });
73
73
  Switch.displayName = "Switch";
@@ -757,9 +757,9 @@ function FadeIn({
757
757
  style,
758
758
  ...props
759
759
  }) {
760
- const ref = React25.useRef(null);
761
- const [visible, setVisible] = React25.useState(false);
762
- React25.useEffect(() => {
760
+ const ref = React26.useRef(null);
761
+ const [visible, setVisible] = React26.useState(false);
762
+ React26.useEffect(() => {
763
763
  const el = ref.current;
764
764
  if (!el) return;
765
765
  const observer = new IntersectionObserver(
@@ -892,17 +892,28 @@ function HeroSection({
892
892
  ] }) });
893
893
  }
894
894
  function FeatureCard({ icon: Icon, title, description, href, className, ...props }) {
895
- const content = /* @__PURE__ */ jsxs(
895
+ const mode = useUIVariant();
896
+ const cardInner = /* @__PURE__ */ jsxs(
896
897
  "div",
897
898
  {
898
899
  className: cn$1(
899
- "group relative flex flex-col gap-4 rounded-2xl border bg-card p-6 transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md",
900
+ "group relative flex h-full flex-col gap-4 border bg-card p-6 transition-all duration-200",
901
+ mode === "playful" ? "rounded-2xl rotate-[0.3deg]" : mode === "smooth" ? "rounded-3xl hover:-translate-y-0.5 hover:shadow-md" : "rounded-2xl hover:-translate-y-0.5 hover:shadow-md",
900
902
  href && "cursor-pointer",
901
- className
903
+ mode !== "playful" && className
902
904
  ),
903
- ...props,
905
+ ...mode !== "playful" ? props : {},
904
906
  children: [
905
- /* @__PURE__ */ jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-xl bg-primary/10 text-primary transition-colors group-hover:bg-primary group-hover:text-primary-foreground", children: /* @__PURE__ */ jsx(Icon, { className: "size-5" }) }),
907
+ /* @__PURE__ */ jsx(
908
+ "div",
909
+ {
910
+ className: cn$1(
911
+ "flex h-10 w-10 items-center justify-center bg-primary/10 text-primary transition-colors group-hover:bg-primary group-hover:text-primary-foreground",
912
+ mode === "smooth" ? "rounded-2xl" : "rounded-xl"
913
+ ),
914
+ children: /* @__PURE__ */ jsx(Icon, { className: "size-5" })
915
+ }
916
+ ),
906
917
  /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
907
918
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
908
919
  /* @__PURE__ */ jsx("h3", { className: "font-semibold leading-tight", children: title }),
@@ -913,8 +924,18 @@ function FeatureCard({ icon: Icon, title, description, href, className, ...props
913
924
  ]
914
925
  }
915
926
  );
927
+ const content = mode === "playful" ? /* @__PURE__ */ jsxs("div", { className: cn$1("group/playful relative h-full", className), ...props, children: [
928
+ /* @__PURE__ */ jsx(
929
+ "div",
930
+ {
931
+ "aria-hidden": "true",
932
+ className: "absolute inset-0 rounded-2xl bg-border transition-transform duration-200 translate-x-[5px] translate-y-[5px] -rotate-[0.5deg] group-hover/playful:-rotate-[1.5deg] group-hover/playful:translate-x-[6px] group-hover/playful:translate-y-[6px]"
933
+ }
934
+ ),
935
+ cardInner
936
+ ] }) : cardInner;
916
937
  if (href) {
917
- return /* @__PURE__ */ jsx("a", { href, className: "block", children: content });
938
+ return /* @__PURE__ */ jsx("a", { href, className: "block h-full", children: content });
918
939
  }
919
940
  return content;
920
941
  }
@@ -935,9 +956,9 @@ function StaggerChildren({
935
956
  className,
936
957
  ...props
937
958
  }) {
938
- const ref = React25.useRef(null);
939
- const [visible, setVisible] = React25.useState(false);
940
- React25.useEffect(() => {
959
+ const ref = React26.useRef(null);
960
+ const [visible, setVisible] = React26.useState(false);
961
+ React26.useEffect(() => {
941
962
  const el = ref.current;
942
963
  if (!el) return;
943
964
  const observer = new IntersectionObserver(
@@ -955,9 +976,10 @@ function StaggerChildren({
955
976
  return () => observer.disconnect();
956
977
  }, [once]);
957
978
  const [tx, ty] = translateMap2[direction];
958
- return /* @__PURE__ */ jsx("div", { ref, className: cn$1(className), ...props, children: React25.Children.map(children, (child, i) => /* @__PURE__ */ jsx(
979
+ return /* @__PURE__ */ jsx("div", { ref, className: cn$1(className), ...props, children: React26.Children.map(children, (child, i) => /* @__PURE__ */ jsx(
959
980
  "div",
960
981
  {
982
+ className: "h-full",
961
983
  style: {
962
984
  transition: `opacity ${duration}ms ease, transform ${duration}ms ease`,
963
985
  transitionDelay: `${delay + i * stagger}ms`,
@@ -974,7 +996,14 @@ function FeaturesSection({
974
996
  badge = "Features",
975
997
  features
976
998
  }) {
977
- return /* @__PURE__ */ jsx("section", { className: "overflow-hidden rounded-2xl border bg-card", 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: [
999
+ const mode = useUIVariant();
1000
+ const sectionClasses = cn$1(
1001
+ "overflow-hidden bg-card",
1002
+ mode === "smooth" && "rounded-3xl border",
1003
+ mode === "playful" && "rounded-2xl border-primary/25 border",
1004
+ !mode && "rounded-2xl border"
1005
+ );
1006
+ 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: [
978
1007
  /* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
979
1008
  /* @__PURE__ */ jsx(StaggerChildren, { className: "mt-12 grid gap-8 sm:grid-cols-2 lg:grid-cols-3", children: features.map((feature) => /* @__PURE__ */ jsx(
980
1009
  FeatureCard,
@@ -988,6 +1017,106 @@ function FeaturesSection({
988
1017
  )) })
989
1018
  ] }) }) });
990
1019
  }
1020
+ function CarouselSection({
1021
+ title = "Explore the platform",
1022
+ description,
1023
+ badge = "Features",
1024
+ features
1025
+ }) {
1026
+ const mode = useUIVariant();
1027
+ const trackRef = React26.useRef(null);
1028
+ const [canPrev, setCanPrev] = React26.useState(false);
1029
+ const [canNext, setCanNext] = React26.useState(true);
1030
+ const updateScrollState = React26.useCallback(() => {
1031
+ const track = trackRef.current;
1032
+ if (!track) return;
1033
+ setCanPrev(track.scrollLeft > 8);
1034
+ setCanNext(track.scrollLeft < track.scrollWidth - track.clientWidth - 8);
1035
+ }, []);
1036
+ React26.useEffect(() => {
1037
+ const track = trackRef.current;
1038
+ if (!track) return;
1039
+ updateScrollState();
1040
+ track.addEventListener("scroll", updateScrollState, { passive: true });
1041
+ const observer = new ResizeObserver(updateScrollState);
1042
+ observer.observe(track);
1043
+ return () => {
1044
+ track.removeEventListener("scroll", updateScrollState);
1045
+ observer.disconnect();
1046
+ };
1047
+ }, [updateScrollState]);
1048
+ const scrollByCard = (direction) => {
1049
+ const track = trackRef.current;
1050
+ if (!track) return;
1051
+ const card = track.querySelector("[data-carousel-item]");
1052
+ const step = card ? card.offsetWidth + 24 : track.clientWidth * 0.8;
1053
+ track.scrollBy({ left: direction * step, behavior: "smooth" });
1054
+ };
1055
+ const sectionClasses = cn$1(
1056
+ "overflow-hidden bg-card",
1057
+ mode === "smooth" && "rounded-3xl border",
1058
+ mode === "playful" && "rounded-2xl border-primary/25 border",
1059
+ !mode && "rounded-2xl border"
1060
+ );
1061
+ const controlClasses = cn$1(
1062
+ "flex size-9 items-center justify-center border bg-background text-foreground transition-colors",
1063
+ "hover:bg-muted disabled:opacity-40 disabled:hover:bg-background",
1064
+ mode === "smooth" ? "rounded-2xl" : "rounded-xl"
1065
+ );
1066
+ 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: [
1067
+ /* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
1068
+ /* @__PURE__ */ jsxs(FadeIn, { direction: "up", children: [
1069
+ /* @__PURE__ */ jsxs("div", { className: "mt-10 flex items-center justify-end gap-2", children: [
1070
+ /* @__PURE__ */ jsx(
1071
+ "button",
1072
+ {
1073
+ type: "button",
1074
+ "aria-label": "Previous",
1075
+ className: controlClasses,
1076
+ onClick: () => scrollByCard(-1),
1077
+ disabled: !canPrev,
1078
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4" })
1079
+ }
1080
+ ),
1081
+ /* @__PURE__ */ jsx(
1082
+ "button",
1083
+ {
1084
+ type: "button",
1085
+ "aria-label": "Next",
1086
+ className: controlClasses,
1087
+ onClick: () => scrollByCard(1),
1088
+ disabled: !canNext,
1089
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" })
1090
+ }
1091
+ )
1092
+ ] }),
1093
+ /* @__PURE__ */ jsx(
1094
+ "div",
1095
+ {
1096
+ ref: trackRef,
1097
+ className: "mt-4 flex snap-x snap-mandatory gap-6 overflow-x-auto pb-4 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
1098
+ children: features.map((feature) => /* @__PURE__ */ jsx(
1099
+ "div",
1100
+ {
1101
+ "data-carousel-item": true,
1102
+ className: "w-[280px] shrink-0 snap-start sm:w-[320px]",
1103
+ children: /* @__PURE__ */ jsx(
1104
+ FeatureCard,
1105
+ {
1106
+ icon: feature.icon,
1107
+ title: feature.title,
1108
+ description: feature.description,
1109
+ href: feature.href
1110
+ }
1111
+ )
1112
+ },
1113
+ feature.title
1114
+ ))
1115
+ }
1116
+ )
1117
+ ] })
1118
+ ] }) }) });
1119
+ }
991
1120
  var defaultRenderLink5 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
992
1121
  function CtaSection({
993
1122
  heading,
@@ -997,10 +1126,17 @@ function CtaSection({
997
1126
  footnote,
998
1127
  renderLink = defaultRenderLink5
999
1128
  }) {
1000
- return /* @__PURE__ */ jsx("section", { className: "overflow-hidden rounded-2xl border bg-card", children: /* @__PURE__ */ jsxs("div", { className: "relative px-6 py-16 sm:px-10 sm:py-24", children: [
1129
+ const mode = useUIVariant();
1130
+ const sectionClasses = cn$1(
1131
+ "overflow-hidden bg-card",
1132
+ mode === "smooth" && "rounded-3xl border",
1133
+ mode === "playful" && "rounded-2xl border-primary/25 border",
1134
+ !mode && "rounded-2xl border"
1135
+ );
1136
+ return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsxs("div", { className: "relative px-6 py-16 sm:px-10 sm:py-24", children: [
1001
1137
  /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-[radial-gradient(ellipse_at_center,hsl(var(--primary)/0.15),transparent_70%)]" }),
1002
1138
  /* @__PURE__ */ jsx(FadeIn, { direction: "up", children: /* @__PURE__ */ jsxs("div", { className: "relative mx-auto max-w-2xl text-center", children: [
1003
- /* @__PURE__ */ jsx("div", { className: "mb-4 inline-flex h-10 w-10 items-center justify-center rounded-2xl bg-primary/10 text-primary", children: /* @__PURE__ */ jsx(Sparkles, { className: "size-5" }) }),
1139
+ /* @__PURE__ */ jsx("div", { className: cn$1("mb-4 inline-flex h-10 w-10 items-center justify-center bg-primary/10 text-primary", mode === "smooth" ? "rounded-3xl" : "rounded-2xl"), children: /* @__PURE__ */ jsx(Sparkles, { className: "size-5" }) }),
1004
1140
  /* @__PURE__ */ jsx("h2", { className: "text-balance text-3xl font-semibold tracking-tight sm:text-4xl", children: heading }),
1005
1141
  /* @__PURE__ */ jsx("p", { className: "mx-auto mt-4 max-w-lg text-pretty text-muted-foreground", children: description }),
1006
1142
  /* @__PURE__ */ jsxs("div", { className: "mt-8 flex flex-wrap items-center justify-center gap-3", children: [
@@ -1033,15 +1169,17 @@ function PricingCard({
1033
1169
  className,
1034
1170
  ...props
1035
1171
  }) {
1036
- return /* @__PURE__ */ jsxs(
1172
+ const mode = useUIVariant();
1173
+ const cardInner = /* @__PURE__ */ jsxs(
1037
1174
  "div",
1038
1175
  {
1039
1176
  className: cn$1(
1040
- "relative flex flex-col rounded-2xl border p-6",
1177
+ "relative flex flex-col border p-6",
1178
+ mode === "playful" ? "rounded-2xl rotate-[0.3deg]" : mode === "smooth" ? "rounded-3xl" : "rounded-2xl",
1041
1179
  highlighted ? "border-primary bg-primary/5 shadow-sm" : "bg-card",
1042
- className
1180
+ mode !== "playful" && className
1043
1181
  ),
1044
- ...props,
1182
+ ...mode !== "playful" ? props : {},
1045
1183
  children: [
1046
1184
  badge && /* @__PURE__ */ jsx("div", { className: "absolute -top-3 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx(Badge$1, { children: badge }) }),
1047
1185
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
@@ -1072,6 +1210,22 @@ function PricingCard({
1072
1210
  ]
1073
1211
  }
1074
1212
  );
1213
+ if (mode === "playful") {
1214
+ return /* @__PURE__ */ jsxs("div", { className: cn$1("group/playful relative", className), ...props, children: [
1215
+ /* @__PURE__ */ jsx(
1216
+ "div",
1217
+ {
1218
+ "aria-hidden": "true",
1219
+ className: cn$1(
1220
+ "absolute inset-0 rounded-2xl transition-transform duration-200 translate-x-[5px] translate-y-[5px] -rotate-[0.5deg] group-hover/playful:-rotate-[1.5deg] group-hover/playful:translate-x-[6px] group-hover/playful:translate-y-[6px]",
1221
+ highlighted ? "bg-primary/20" : "bg-border"
1222
+ )
1223
+ }
1224
+ ),
1225
+ cardInner
1226
+ ] });
1227
+ }
1228
+ return cardInner;
1075
1229
  }
1076
1230
  var defaultRenderLink6 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
1077
1231
  function PricingSection({
@@ -1084,16 +1238,25 @@ function PricingSection({
1084
1238
  renderLink = defaultRenderLink6,
1085
1239
  footnote
1086
1240
  }) {
1087
- const [annual, setAnnual] = React25.useState(false);
1088
- return /* @__PURE__ */ jsx("section", { className: "overflow-hidden rounded-2xl border bg-card", 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: [
1241
+ const [annual, setAnnual] = React26.useState(false);
1242
+ const mode = useUIVariant();
1243
+ const sectionClasses = cn$1(
1244
+ "overflow-hidden bg-card",
1245
+ mode === "smooth" && "rounded-3xl border",
1246
+ mode === "playful" && "rounded-2xl border-primary/25 border",
1247
+ !mode && "rounded-2xl border"
1248
+ );
1249
+ 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: [
1089
1250
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
1090
1251
  badge && /* @__PURE__ */ jsx(Badge$1, { variant: "secondary", className: "mb-4", children: badge }),
1091
1252
  /* @__PURE__ */ jsx("h2", { className: "text-balance text-3xl font-semibold tracking-tight sm:text-4xl", children: title }),
1092
1253
  description && /* @__PURE__ */ jsx("p", { className: "mx-auto mt-4 max-w-xl text-pretty text-muted-foreground", children: description }),
1093
1254
  /* @__PURE__ */ jsxs("div", { className: "mt-6 inline-flex items-center gap-3 rounded-full border bg-muted p-1", children: [
1094
1255
  /* @__PURE__ */ jsx(
1095
- "button",
1256
+ Button$1,
1096
1257
  {
1258
+ variant: "ghost",
1259
+ size: "sm",
1097
1260
  onClick: () => setAnnual(false),
1098
1261
  className: cn$1(
1099
1262
  "rounded-full px-4 py-1.5 text-sm font-medium transition-colors",
@@ -1103,8 +1266,10 @@ function PricingSection({
1103
1266
  }
1104
1267
  ),
1105
1268
  /* @__PURE__ */ jsxs(
1106
- "button",
1269
+ Button$1,
1107
1270
  {
1271
+ variant: "ghost",
1272
+ size: "sm",
1108
1273
  onClick: () => setAnnual(true),
1109
1274
  className: cn$1(
1110
1275
  "flex items-center gap-2 rounded-full px-4 py-1.5 text-sm font-medium transition-colors",
@@ -1149,11 +1314,16 @@ function TestimonialCard({
1149
1314
  className,
1150
1315
  ...props
1151
1316
  }) {
1152
- return /* @__PURE__ */ jsxs(
1317
+ const mode = useUIVariant();
1318
+ const cardInner = /* @__PURE__ */ jsxs(
1153
1319
  "div",
1154
1320
  {
1155
- className: cn$1("flex flex-col gap-4 rounded-2xl border bg-card p-6", className),
1156
- ...props,
1321
+ className: cn$1(
1322
+ "flex flex-col gap-4 border bg-card p-6",
1323
+ mode === "playful" ? "rounded-2xl rotate-[0.3deg]" : mode === "smooth" ? "rounded-3xl" : "rounded-2xl",
1324
+ mode !== "playful" && className
1325
+ ),
1326
+ ...mode !== "playful" ? props : {},
1157
1327
  children: [
1158
1328
  /* @__PURE__ */ jsx(Quote, { className: "size-4 text-muted-foreground/40" }),
1159
1329
  rating != null && /* @__PURE__ */ jsx("div", { className: "flex gap-0.5", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx(
@@ -1168,9 +1338,9 @@ function TestimonialCard({
1168
1338
  )) }),
1169
1339
  /* @__PURE__ */ jsx("p", { className: "flex-1 text-sm leading-relaxed", children: quote }),
1170
1340
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1171
- /* @__PURE__ */ jsxs(Avatar, { className: "size-9 rounded-xl", children: [
1341
+ /* @__PURE__ */ jsxs(Avatar, { className: "size-9", children: [
1172
1342
  /* @__PURE__ */ jsx(AvatarImage, { src: avatar, alt: name }),
1173
- /* @__PURE__ */ jsx(AvatarFallback, { className: "rounded-xl text-xs", children: initials ?? name.slice(0, 2).toUpperCase() })
1343
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "text-xs", children: initials ?? name.slice(0, 2).toUpperCase() })
1174
1344
  ] }),
1175
1345
  /* @__PURE__ */ jsxs("div", { children: [
1176
1346
  /* @__PURE__ */ jsx("div", { className: "text-sm font-medium leading-tight", children: name }),
@@ -1183,6 +1353,19 @@ function TestimonialCard({
1183
1353
  ]
1184
1354
  }
1185
1355
  );
1356
+ if (mode === "playful") {
1357
+ return /* @__PURE__ */ jsxs("div", { className: cn$1("group/playful relative", className), ...props, children: [
1358
+ /* @__PURE__ */ jsx(
1359
+ "div",
1360
+ {
1361
+ "aria-hidden": "true",
1362
+ className: "absolute inset-0 rounded-2xl bg-border transition-transform duration-200 translate-x-[5px] translate-y-[5px] -rotate-[0.5deg] group-hover/playful:-rotate-[1.5deg] group-hover/playful:translate-x-[6px] group-hover/playful:translate-y-[6px]"
1363
+ }
1364
+ ),
1365
+ cardInner
1366
+ ] });
1367
+ }
1368
+ return cardInner;
1186
1369
  }
1187
1370
  function TestimonialsSection({
1188
1371
  title = "Trusted by teams shipping real products",
@@ -1190,7 +1373,14 @@ function TestimonialsSection({
1190
1373
  badge = "Testimonials",
1191
1374
  testimonials
1192
1375
  }) {
1193
- return /* @__PURE__ */ jsx("section", { className: "overflow-hidden rounded-2xl border bg-card", 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: [
1376
+ const mode = useUIVariant();
1377
+ const sectionClasses = cn$1(
1378
+ "overflow-hidden bg-card",
1379
+ mode === "smooth" && "rounded-3xl border",
1380
+ mode === "playful" && "rounded-2xl border-primary/25 border",
1381
+ !mode && "rounded-2xl border"
1382
+ );
1383
+ 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: [
1194
1384
  /* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
1195
1385
  /* @__PURE__ */ jsx(StaggerChildren, { className: "mt-12 columns-1 gap-4 sm:columns-2 lg:columns-3", children: testimonials.map((t) => /* @__PURE__ */ jsx(
1196
1386
  "div",
@@ -1296,7 +1486,14 @@ function FaqSection({
1296
1486
  badge = "FAQ",
1297
1487
  items
1298
1488
  }) {
1299
- return /* @__PURE__ */ jsx("section", { className: "overflow-hidden rounded-2xl border bg-card", 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: [
1489
+ const mode = useUIVariant();
1490
+ const sectionClasses = cn$1(
1491
+ "overflow-hidden bg-card",
1492
+ mode === "smooth" && "rounded-3xl border",
1493
+ mode === "playful" && "rounded-2xl border-primary/25 border",
1494
+ !mode && "rounded-2xl border"
1495
+ );
1496
+ 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: [
1300
1497
  /* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
1301
1498
  /* @__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: [
1302
1499
  /* @__PURE__ */ jsx(AccordionTrigger, { className: "text-left text-sm font-medium", children: item.question }),
@@ -1315,10 +1512,10 @@ function CountUp({
1315
1512
  className,
1316
1513
  ...props
1317
1514
  }) {
1318
- const ref = React25.useRef(null);
1319
- const [value, setValue] = React25.useState(from);
1320
- const hasStarted = React25.useRef(false);
1321
- React25.useEffect(() => {
1515
+ const ref = React26.useRef(null);
1516
+ const [value, setValue] = React26.useState(from);
1517
+ const hasStarted = React26.useRef(false);
1518
+ React26.useEffect(() => {
1322
1519
  const el = ref.current;
1323
1520
  if (!el) return;
1324
1521
  const observer = new IntersectionObserver(
@@ -1366,7 +1563,14 @@ function StatsSection({
1366
1563
  badge = "By the numbers",
1367
1564
  stats
1368
1565
  }) {
1369
- return /* @__PURE__ */ jsx("section", { className: "overflow-hidden rounded-2xl border bg-card", children: /* @__PURE__ */ jsxs("div", { className: "relative px-6 py-14 sm:px-10 sm:py-20", children: [
1566
+ const mode = useUIVariant();
1567
+ const sectionClasses = cn$1(
1568
+ "overflow-hidden bg-card",
1569
+ mode === "smooth" && "rounded-3xl border",
1570
+ mode === "playful" && "rounded-2xl border-primary/25 border",
1571
+ !mode && "rounded-2xl border"
1572
+ );
1573
+ return /* @__PURE__ */ jsx("section", { className: sectionClasses, children: /* @__PURE__ */ jsxs("div", { className: "relative px-6 py-14 sm:px-10 sm:py-20", children: [
1370
1574
  /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-[radial-gradient(ellipse_at_bottom,hsl(var(--primary)/0.08),transparent_60%)]" }),
1371
1575
  /* @__PURE__ */ jsxs("div", { className: "relative mx-auto max-w-4xl", children: [
1372
1576
  /* @__PURE__ */ jsx(SectionTitle, { title, description, badge }),
@@ -1404,8 +1608,8 @@ function NewsletterSection({
1404
1608
  successDescription = defaults.successDescription,
1405
1609
  onSubscribe
1406
1610
  } = {}) {
1407
- const [email, setEmail] = React25.useState("");
1408
- const [submitted, setSubmitted] = React25.useState(false);
1611
+ const [email, setEmail] = React26.useState("");
1612
+ const [submitted, setSubmitted] = React26.useState(false);
1409
1613
  async function handleSubmit(e) {
1410
1614
  e.preventDefault();
1411
1615
  if (!email) return;
@@ -1483,7 +1687,7 @@ function ContactSection({
1483
1687
  sendAnotherLabel = defaults2.sendAnotherLabel,
1484
1688
  onSubmit
1485
1689
  } = {}) {
1486
- const [submitted, setSubmitted] = React25.useState(false);
1690
+ const [submitted, setSubmitted] = React26.useState(false);
1487
1691
  async function handleSubmit(e) {
1488
1692
  e.preventDefault();
1489
1693
  await onSubmit?.(e);
@@ -1580,7 +1784,7 @@ function Navbar({
1580
1784
  controls,
1581
1785
  renderLink = defaultRenderLink7
1582
1786
  }) {
1583
- const [open, setOpen] = React25.useState(false);
1787
+ const [open, setOpen] = React26.useState(false);
1584
1788
  const brandHref = brand.href ?? "/";
1585
1789
  const hasRightContent = controls?.length || cta?.primary || cta?.secondary;
1586
1790
  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: [
@@ -1597,7 +1801,7 @@ function Navbar({
1597
1801
  children: link.label
1598
1802
  }) }, link.label)) }),
1599
1803
  hasRightContent && /* @__PURE__ */ jsxs("div", { className: "hidden items-center justify-end gap-2 md:flex", children: [
1600
- controls?.map((control, i) => /* @__PURE__ */ jsx(React25.Fragment, { children: control }, i)),
1804
+ controls?.map((control, i) => /* @__PURE__ */ jsx(React26.Fragment, { children: control }, i)),
1601
1805
  (cta?.secondary || cta?.primary) && controls?.length ? /* @__PURE__ */ jsx("div", { className: "mx-1 h-4 w-px bg-border" }) : null,
1602
1806
  cta?.secondary && renderLink({
1603
1807
  href: cta.secondary.href,
@@ -1623,7 +1827,7 @@ function Navbar({
1623
1827
  ] })
1624
1828
  }) }),
1625
1829
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1626
- controls?.map((control, i) => /* @__PURE__ */ jsx(React25.Fragment, { children: control }, i)),
1830
+ controls?.map((control, i) => /* @__PURE__ */ jsx(React26.Fragment, { children: control }, i)),
1627
1831
  /* @__PURE__ */ jsxs(Button$1, { variant: "ghost", size: "icon", onClick: () => setOpen(false), children: [
1628
1832
  /* @__PURE__ */ jsx(X, { className: "size-4" }),
1629
1833
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close menu" })
@@ -1768,7 +1972,7 @@ function LogoStrip({
1768
1972
  ] });
1769
1973
  }
1770
1974
  function GridUnderlay({ variant, size = 24, className, ...props }) {
1771
- const id = React25.useId();
1975
+ const id = React26.useId();
1772
1976
  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: [
1773
1977
  /* @__PURE__ */ jsx("line", { x1: size / 2, y1: 0, x2: size / 2, y2: size, stroke: "currentColor", strokeWidth: 0.5 }),
1774
1978
  /* @__PURE__ */ jsx("line", { x1: 0, y1: size / 2, x2: size, y2: size / 2, stroke: "currentColor", strokeWidth: 0.5 })
@@ -1796,9 +2000,9 @@ function GlowUnderlay({
1796
2000
  style,
1797
2001
  ...props
1798
2002
  }) {
1799
- const [pos, setPos] = React25.useState({ x: "50%", y: "50%" });
1800
- const containerRef = React25.useRef(null);
1801
- React25.useEffect(() => {
2003
+ const [pos, setPos] = React26.useState({ x: "50%", y: "50%" });
2004
+ const containerRef = React26.useRef(null);
2005
+ React26.useEffect(() => {
1802
2006
  if (!followCursor) return;
1803
2007
  const handleMouseMove = (e) => {
1804
2008
  const el = containerRef.current;
@@ -1890,8 +2094,8 @@ function PageTransition({
1890
2094
  style,
1891
2095
  ...props
1892
2096
  }) {
1893
- const [mounted, setMounted] = React25.useState(false);
1894
- React25.useEffect(() => {
2097
+ const [mounted, setMounted] = React26.useState(false);
2098
+ React26.useEffect(() => {
1895
2099
  const id = requestAnimationFrame(() => setMounted(true));
1896
2100
  return () => cancelAnimationFrame(id);
1897
2101
  }, []);
@@ -1918,8 +2122,8 @@ function Spotlight({
1918
2122
  triggerClassName,
1919
2123
  shortcut = "\u2318K"
1920
2124
  }) {
1921
- const [open, setOpen] = React25.useState(false);
1922
- React25.useEffect(() => {
2125
+ const [open, setOpen] = React26.useState(false);
2126
+ React26.useEffect(() => {
1923
2127
  const down = (e) => {
1924
2128
  if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
1925
2129
  e.preventDefault();
@@ -1949,7 +2153,7 @@ function Spotlight({
1949
2153
  /* @__PURE__ */ jsx(CommandInput, { placeholder }),
1950
2154
  /* @__PURE__ */ jsxs(CommandList, { children: [
1951
2155
  /* @__PURE__ */ jsx(CommandEmpty, { children: "No results found." }),
1952
- groups.map((group, i) => /* @__PURE__ */ jsxs(React25.Fragment, { children: [
2156
+ groups.map((group, i) => /* @__PURE__ */ jsxs(React26.Fragment, { children: [
1953
2157
  i > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
1954
2158
  /* @__PURE__ */ jsx(CommandGroup, { heading: group.heading, children: group.items.map((item) => /* @__PURE__ */ jsxs(
1955
2159
  CommandItem,
@@ -1974,8 +2178,8 @@ function Spotlight({
1974
2178
  var BASE = 40;
1975
2179
  var MAGNIFY_RADIUS = 80;
1976
2180
  function Dock({ items, iconSize = BASE, magnification = 1.7, className, ...props }) {
1977
- const [mouseX, setMouseX] = React25.useState(null);
1978
- const containerRef = React25.useRef(null);
2181
+ const [mouseX, setMouseX] = React26.useState(null);
2182
+ const containerRef = React26.useRef(null);
1979
2183
  function getScale(index) {
1980
2184
  if (mouseX === null || !containerRef.current) return 1;
1981
2185
  const container = containerRef.current;
@@ -2200,7 +2404,7 @@ function PageHeader({
2200
2404
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1 pb-6", className), children: [
2201
2405
  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) => {
2202
2406
  const isLast = i === breadcrumbs.length - 1;
2203
- return /* @__PURE__ */ jsxs(React25.Fragment, { children: [
2407
+ return /* @__PURE__ */ jsxs(React26.Fragment, { children: [
2204
2408
  i > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5 shrink-0" }),
2205
2409
  isLast || !crumb.href ? /* @__PURE__ */ jsx("span", { className: cn(isLast && "text-foreground font-medium"), children: crumb.label }) : renderLink({
2206
2410
  href: crumb.href,
@@ -2236,11 +2440,11 @@ function PageHeader({
2236
2440
  ] });
2237
2441
  }
2238
2442
  function Suspensed({ children, fallback }) {
2239
- return /* @__PURE__ */ jsx(React25.Suspense, { fallback: fallback ?? /* @__PURE__ */ jsx(Spinner, {}), children });
2443
+ return /* @__PURE__ */ jsx(React26.Suspense, { fallback: fallback ?? /* @__PURE__ */ jsx(Spinner, {}), children });
2240
2444
  }
2241
2445
  function ThemeSwitchMinimal() {
2242
- const [theme, setThemeState] = React25.useState("dark");
2243
- React25.useEffect(() => {
2446
+ const [theme, setThemeState] = React26.useState("dark");
2447
+ React26.useEffect(() => {
2244
2448
  const stored = localStorage.getItem("theme");
2245
2449
  const resolved = stored ?? (document.documentElement.classList.contains("dark") ? "dark" : "light");
2246
2450
  setThemeState(resolved);
@@ -2287,7 +2491,7 @@ function ModeSwitchMinimal() {
2287
2491
  ) });
2288
2492
  }
2289
2493
  function ThemeColorUpdater({ colorTheme }) {
2290
- React25.useEffect(() => {
2494
+ React26.useEffect(() => {
2291
2495
  if (colorTheme) {
2292
2496
  document.documentElement.setAttribute("data-theme", colorTheme);
2293
2497
  } else {
@@ -2297,7 +2501,7 @@ function ThemeColorUpdater({ colorTheme }) {
2297
2501
  return null;
2298
2502
  }
2299
2503
  function VersionBanner({ version, message, className, onDismiss }) {
2300
- const [dismissed, setDismissed] = React25.useState(false);
2504
+ const [dismissed, setDismissed] = React26.useState(false);
2301
2505
  if (dismissed) return null;
2302
2506
  return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-4 bg-primary/10 px-4 py-2 text-sm", className), children: [
2303
2507
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
@@ -2337,7 +2541,7 @@ function DevBanner({ environment = "development", className }) {
2337
2541
  );
2338
2542
  }
2339
2543
  function RegisterHotkeys({ hotkeys }) {
2340
- React25.useEffect(() => {
2544
+ React26.useEffect(() => {
2341
2545
  const handleKeyDown = (event) => {
2342
2546
  for (const hotkey of hotkeys) {
2343
2547
  const matches = event.key.toLowerCase() === hotkey.key.toLowerCase() && !!event.ctrlKey === !!hotkey.ctrl && !!event.metaKey === !!hotkey.meta && !!event.shiftKey === !!hotkey.shift && !!event.altKey === !!hotkey.alt;
@@ -2457,36 +2661,36 @@ function useMounted() {
2457
2661
  return mounted;
2458
2662
  }
2459
2663
  function useConfirm() {
2460
- const [isOpen, setIsOpen] = React25.useState(false);
2461
- const [options, setOptions] = React25.useState({});
2462
- const resolveRef = React25.useRef(null);
2463
- const confirm = React25.useCallback((opts = {}) => {
2664
+ const [isOpen, setIsOpen] = React26.useState(false);
2665
+ const [options, setOptions] = React26.useState({});
2666
+ const resolveRef = React26.useRef(null);
2667
+ const confirm = React26.useCallback((opts = {}) => {
2464
2668
  setOptions(opts);
2465
2669
  setIsOpen(true);
2466
2670
  return new Promise((resolve) => {
2467
2671
  resolveRef.current = resolve;
2468
2672
  });
2469
2673
  }, []);
2470
- const handleConfirm = React25.useCallback(() => {
2674
+ const handleConfirm = React26.useCallback(() => {
2471
2675
  resolveRef.current?.(true);
2472
2676
  setIsOpen(false);
2473
2677
  }, []);
2474
- const handleCancel = React25.useCallback(() => {
2678
+ const handleCancel = React26.useCallback(() => {
2475
2679
  resolveRef.current?.(false);
2476
2680
  setIsOpen(false);
2477
2681
  }, []);
2478
2682
  return { confirm, isOpen, options, handleConfirm, handleCancel };
2479
2683
  }
2480
2684
  function useControlledOpen(defaultOpen = false) {
2481
- const [isOpen, setIsOpen] = React25.useState(defaultOpen);
2482
- const open = React25.useCallback(() => setIsOpen(true), []);
2483
- const close = React25.useCallback(() => setIsOpen(false), []);
2484
- const toggle = React25.useCallback(() => setIsOpen((prev) => !prev), []);
2685
+ const [isOpen, setIsOpen] = React26.useState(defaultOpen);
2686
+ const open = React26.useCallback(() => setIsOpen(true), []);
2687
+ const close = React26.useCallback(() => setIsOpen(false), []);
2688
+ const toggle = React26.useCallback(() => setIsOpen((prev) => !prev), []);
2485
2689
  return { isOpen, open, close, toggle, setIsOpen };
2486
2690
  }
2487
2691
  function useScrolledPast(threshold) {
2488
- const [scrolledPast, setScrolledPast] = React25.useState(false);
2489
- React25.useEffect(() => {
2692
+ const [scrolledPast, setScrolledPast] = React26.useState(false);
2693
+ React26.useEffect(() => {
2490
2694
  const handleScroll = () => {
2491
2695
  setScrolledPast(window.scrollY > threshold);
2492
2696
  };
@@ -2497,30 +2701,30 @@ function useScrolledPast(threshold) {
2497
2701
  return scrolledPast;
2498
2702
  }
2499
2703
  function useCopyToClipboard() {
2500
- const [copied, setCopied] = React25.useState(false);
2501
- const timeoutRef = React25.useRef(void 0);
2502
- const copy = React25.useCallback((text) => {
2704
+ const [copied, setCopied] = React26.useState(false);
2705
+ const timeoutRef = React26.useRef(void 0);
2706
+ const copy = React26.useCallback((text) => {
2503
2707
  navigator.clipboard.writeText(text).then(() => {
2504
2708
  setCopied(true);
2505
2709
  clearTimeout(timeoutRef.current);
2506
2710
  timeoutRef.current = setTimeout(() => setCopied(false), 2e3);
2507
2711
  });
2508
2712
  }, []);
2509
- React25.useEffect(() => () => clearTimeout(timeoutRef.current), []);
2713
+ React26.useEffect(() => () => clearTimeout(timeoutRef.current), []);
2510
2714
  return [copied, copy];
2511
2715
  }
2512
2716
  function useDebounce(value, delay) {
2513
- const [debounced, setDebounced] = React25.useState(value);
2514
- React25.useEffect(() => {
2717
+ const [debounced, setDebounced] = React26.useState(value);
2718
+ React26.useEffect(() => {
2515
2719
  const timer = setTimeout(() => setDebounced(value), delay);
2516
2720
  return () => clearTimeout(timer);
2517
2721
  }, [value, delay]);
2518
2722
  return debounced;
2519
2723
  }
2520
2724
  function useIntersectionObserver(options) {
2521
- const ref = React25.useRef(null);
2522
- const [isIntersecting, setIsIntersecting] = React25.useState(false);
2523
- React25.useEffect(() => {
2725
+ const ref = React26.useRef(null);
2726
+ const [isIntersecting, setIsIntersecting] = React26.useState(false);
2727
+ React26.useEffect(() => {
2524
2728
  const el = ref.current;
2525
2729
  if (!el) return;
2526
2730
  const observer = new IntersectionObserver(([entry]) => {
@@ -2532,7 +2736,7 @@ function useIntersectionObserver(options) {
2532
2736
  return [ref, isIntersecting];
2533
2737
  }
2534
2738
  function useLocalStorage(key, initialValue) {
2535
- const [storedValue, setStoredValue] = React25.useState(() => {
2739
+ const [storedValue, setStoredValue] = React26.useState(() => {
2536
2740
  if (typeof window === "undefined") return initialValue;
2537
2741
  try {
2538
2742
  const item = window.localStorage.getItem(key);
@@ -2541,7 +2745,7 @@ function useLocalStorage(key, initialValue) {
2541
2745
  return initialValue;
2542
2746
  }
2543
2747
  });
2544
- const setValue = React25.useCallback(
2748
+ const setValue = React26.useCallback(
2545
2749
  (value) => {
2546
2750
  try {
2547
2751
  setStoredValue(value);
@@ -2556,11 +2760,11 @@ function useLocalStorage(key, initialValue) {
2556
2760
  return [storedValue, setValue];
2557
2761
  }
2558
2762
  function useMediaQuery(query) {
2559
- const [matches, setMatches] = React25.useState(() => {
2763
+ const [matches, setMatches] = React26.useState(() => {
2560
2764
  if (typeof window === "undefined") return false;
2561
2765
  return window.matchMedia(query).matches;
2562
2766
  });
2563
- React25.useEffect(() => {
2767
+ React26.useEffect(() => {
2564
2768
  if (typeof window === "undefined") return;
2565
2769
  const mql = window.matchMedia(query);
2566
2770
  setMatches(mql.matches);
@@ -2571,18 +2775,18 @@ function useMediaQuery(query) {
2571
2775
  return matches;
2572
2776
  }
2573
2777
  function usePagination(total, pageSize) {
2574
- const [page, setPage] = React25.useState(1);
2778
+ const [page, setPage] = React26.useState(1);
2575
2779
  const totalPages = Math.max(1, Math.ceil(total / pageSize));
2576
2780
  const offset = (page - 1) * pageSize;
2577
- const goTo = React25.useCallback(
2781
+ const goTo = React26.useCallback(
2578
2782
  (p) => setPage(Math.min(Math.max(1, p), totalPages)),
2579
2783
  [totalPages]
2580
2784
  );
2581
- const next = React25.useCallback(() => goTo(page + 1), [page, goTo]);
2582
- const prev = React25.useCallback(() => goTo(page - 1), [page, goTo]);
2785
+ const next = React26.useCallback(() => goTo(page + 1), [page, goTo]);
2786
+ const prev = React26.useCallback(() => goTo(page - 1), [page, goTo]);
2583
2787
  return { page, pageSize, totalPages, offset, hasPrev: page > 1, hasNext: page < totalPages, goTo, next, prev };
2584
2788
  }
2585
2789
 
2586
- export { AppContent, AppGrid, AppGridCell, AppScreen, AppShell, AuthSection, Badge, Button, Card, ChangelogCard, ChangelogList, Checkbox, ConfirmDialog, ContactSection, ContextMenu, CountUp, CtaSection, DevBanner, Dock, EmptyState, ErrorPage, FadeIn, FaqSection, FeatureCard, FeaturesSection, Footer, FullPageSpinner, GlassCard, Grid, GridItem, HeroSection, ImageCard, Input, LogoStrip, ModeSwitchMinimal, Navbar, NewsletterSection, OlwibaUIProvider, Overlay, PageHeader, PageTransition, PhoneFrame, PostCard, PostList, PricingCard, PricingSection, PublicPageFrame, RegisterHotkeys, RootErrorFallback, Section, SectionTitle, Spotlight, Stack, StaggerChildren, StatCard, StatsSection, Suspensed, Switch, TeamSection, TestimonialCard, TestimonialsSection, Textarea, ThemeColorUpdater, ThemeSwitchMinimal, Underlay, UpgradePrompt, VersionBanner, useConfirm, useControlledOpen, useCopyToClipboard, useDebounce, useIntersectionObserver, useLocalStorage, useMediaQuery, useMounted, useOlwibaUI, usePagination, useScrolledPast, useUIMode };
2790
+ export { AppContent, AppGrid, AppGridCell, AppScreen, AppShell, AuthSection, Badge, Button, Card, CarouselSection, ChangelogCard, ChangelogList, Checkbox, ConfirmDialog, ContactSection, ContextMenu, CountUp, CtaSection, DevBanner, Dock, EmptyState, ErrorPage, FadeIn, FaqSection, FeatureCard, FeaturesSection, Footer, FullPageSpinner, GlassCard, Grid, GridItem, HeroSection, ImageCard, Input, LogoStrip, ModeSwitchMinimal, Navbar, NewsletterSection, OlwibaUIProvider, Overlay, PageHeader, PageTransition, PhoneFrame, PostCard, PostList, PricingCard, PricingSection, PublicPageFrame, RegisterHotkeys, RootErrorFallback, Section, SectionTitle, Spotlight, Stack, StaggerChildren, StatCard, StatsSection, Suspensed, Switch, TeamSection, TestimonialCard, TestimonialsSection, Textarea, ThemeColorUpdater, ThemeSwitchMinimal, Underlay, UpgradePrompt, VersionBanner, useConfirm, useControlledOpen, useCopyToClipboard, useDebounce, useIntersectionObserver, useLocalStorage, useMediaQuery, useMounted, useOlwibaUI, usePagination, useScrolledPast, useUIMode };
2587
2791
  //# sourceMappingURL=index.js.map
2588
2792
  //# sourceMappingURL=index.js.map