@olwiba/ui 0.2.23 → 0.2.25

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
@@ -2,7 +2,7 @@ import { cn } from './chunk-AMWLSHD6.js';
2
2
  export { MdxContent, cn } from './chunk-AMWLSHD6.js';
3
3
  import * as React21 from 'react';
4
4
  import { useRef, useEffect, useState, useCallback } 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, SidebarProvider, SidebarInset, 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, useSidebar, Sidebar, SidebarHeader, SidebarMenu, SidebarMenuItem, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarMenuButton, SidebarFooter, SidebarTrigger, CardHeader, CardTitle, CardDescription, CardContent, InputOTP, InputOTPGroup, InputOTPSlot, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose, ContextMenuSeparator, ContextMenuLabel, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent, ContextMenuItem, ContextMenuShortcut, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup } 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, SidebarProvider, SidebarInset, 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, Spinner, Popover, PopoverTrigger, PopoverContent, useSidebar, Sidebar, SidebarHeader, SidebarMenu, SidebarMenuItem, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarMenuButton, SidebarFooter, SidebarTrigger, CardHeader, CardTitle, CardDescription, CardContent, InputOTP, InputOTPGroup, InputOTPSlot, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose, ContextMenuSeparator, ContextMenuLabel, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent, ContextMenuItem, ContextMenuShortcut, 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
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, BirdIcon, MoreVerticalIcon, CreditCardIcon, BellIcon, SettingsIcon, LogOutIcon, ShieldCheck, Building2 } from 'lucide-react';
@@ -302,7 +302,7 @@ function NavUser({ user }) {
302
302
  children: [
303
303
  /* @__PURE__ */ jsxs(Avatar, { mode: avatarMode, size: "sm", children: [
304
304
  user.avatar && /* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
305
- /* @__PURE__ */ jsx(AvatarFallback, { className: "text-white", style: identityTint, children: /* @__PURE__ */ jsx(
305
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "text-white", style: identityTint, children: user.avatarFallback ?? /* @__PURE__ */ jsx(
306
306
  BirdIcon,
307
307
  {
308
308
  "aria-hidden": true,
@@ -329,7 +329,7 @@ function NavUser({ user }) {
329
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: [
330
330
  /* @__PURE__ */ jsxs(Avatar, { mode: avatarMode, size: "sm", children: [
331
331
  user.avatar && /* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
332
- /* @__PURE__ */ jsx(AvatarFallback, { className: "text-white", style: identityTint, children: /* @__PURE__ */ jsx(
332
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "text-white", style: identityTint, children: user.avatarFallback ?? /* @__PURE__ */ jsx(
333
333
  BirdIcon,
334
334
  {
335
335
  "aria-hidden": true,
@@ -379,7 +379,10 @@ function ShellSidebar({
379
379
  renderLink,
380
380
  collapsible,
381
381
  side,
382
- sidebarPosition
382
+ sidebarPosition,
383
+ sidebarContentKey,
384
+ sidebarContentClassName,
385
+ sidebarFooterStart
383
386
  }) {
384
387
  const fallbackLogo = typeof brand.name === "string" ? brand.name.slice(0, 1).toUpperCase() : null;
385
388
  const { isMobile, setOpenMobile } = useSidebar();
@@ -387,59 +390,83 @@ function ShellSidebar({
387
390
  if (isMobile) setOpenMobile(false);
388
391
  }, [isMobile, setOpenMobile]);
389
392
  return /* @__PURE__ */ jsxs(Sidebar, { side, collapsible, sidebarPosition, children: [
390
- /* @__PURE__ */ jsx(SidebarHeader, { className: "py-3", children: /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { onClickCapture: closeMobileMenu, children: /* @__PURE__ */ jsxs(
391
- "div",
393
+ /* @__PURE__ */ jsx(
394
+ SidebarHeader,
392
395
  {
393
- className: cn$1(
394
- "flex items-center gap-2 overflow-hidden rounded-md p-2 text-left",
395
- RAIL_SQUARE
396
- ),
397
- children: [
398
- brand.logo ? (
399
- // Neutral slot: the consumer's logo owns its own chrome
400
- // (background, radius). Sized to fill the collapsed icon rail.
401
- /* @__PURE__ */ jsx("span", { className: "flex size-8 shrink-0 items-center justify-center [&>svg]:size-5", children: brand.logo })
402
- ) : /* @__PURE__ */ jsx("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-primary text-sm font-semibold text-primary-foreground", children: fallbackLogo }),
403
- /* @__PURE__ */ jsx("span", { className: "min-w-0 whitespace-nowrap text-base font-semibold leading-none [text-box-edge:ex_alphabetic] [text-box-trim:trim-both] group-data-[collapsible=icon]:hidden", children: brand.name })
404
- ]
405
- }
406
- ) }) }) }),
407
- /* @__PURE__ */ jsx(SidebarContent, { children: /* @__PURE__ */ jsx(SidebarGroup, { children: /* @__PURE__ */ jsxs(SidebarGroupContent, { className: "flex flex-col gap-2", children: [
408
- action && /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { onClickCapture: closeMobileMenu, children: action.href ? /* @__PURE__ */ jsx(
409
- SidebarMenuButton,
410
- {
411
- asChild: true,
412
- tooltip: action.label,
413
- className: "min-w-8 bg-primary text-primary-foreground duration-200 ease-linear hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground",
414
- children: renderLink({
415
- href: action.href,
396
+ className: cn$1("py-3", sidebarContentClassName),
397
+ children: /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { onClickCapture: closeMobileMenu, children: /* @__PURE__ */ jsxs(
398
+ "div",
399
+ {
400
+ className: cn$1(
401
+ "flex items-center gap-2 overflow-hidden rounded-md p-2 text-left",
402
+ RAIL_SQUARE
403
+ ),
404
+ children: [
405
+ brand.logo ? (
406
+ // Neutral slot: the consumer's logo owns its own chrome
407
+ // (background, radius). Sized to fill the collapsed icon rail.
408
+ /* @__PURE__ */ jsx("span", { className: "flex size-8 shrink-0 items-center justify-center [&>svg]:size-5", children: brand.logo })
409
+ ) : /* @__PURE__ */ jsx("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-primary text-sm font-semibold text-primary-foreground", children: fallbackLogo }),
410
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 whitespace-nowrap text-base font-semibold leading-none [text-box-edge:ex_alphabetic] [text-box-trim:trim-both] group-data-[collapsible=icon]:hidden", children: brand.name })
411
+ ]
412
+ }
413
+ ) }) })
414
+ },
415
+ `${sidebarContentKey ?? "default"}-header`
416
+ ),
417
+ /* @__PURE__ */ jsx(
418
+ SidebarContent,
419
+ {
420
+ className: sidebarContentClassName,
421
+ children: /* @__PURE__ */ jsx(SidebarGroup, { children: /* @__PURE__ */ jsxs(SidebarGroupContent, { className: "flex flex-col gap-2", children: [
422
+ action && /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { onClickCapture: closeMobileMenu, children: action.href ? /* @__PURE__ */ jsx(
423
+ SidebarMenuButton,
424
+ {
425
+ asChild: true,
426
+ tooltip: action.label,
427
+ className: "min-w-8 bg-primary text-primary-foreground duration-200 ease-linear hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground",
428
+ children: renderLink({
429
+ href: action.href,
430
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [
431
+ action.icon && /* @__PURE__ */ jsx(action.icon, {}),
432
+ /* @__PURE__ */ jsx("span", { children: action.label })
433
+ ] })
434
+ })
435
+ }
436
+ ) : /* @__PURE__ */ jsxs(
437
+ SidebarMenuButton,
438
+ {
439
+ tooltip: action.label,
440
+ onClick: action.onClick,
441
+ className: "min-w-8 bg-primary text-primary-foreground duration-200 ease-linear hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground",
442
+ children: [
443
+ action.icon && /* @__PURE__ */ jsx(action.icon, {}),
444
+ /* @__PURE__ */ jsx("span", { children: action.label })
445
+ ]
446
+ }
447
+ ) }) }),
448
+ /* @__PURE__ */ jsx(SidebarMenu, { children: navItems.map((item) => /* @__PURE__ */ jsx(SidebarMenuItem, { onClickCapture: closeMobileMenu, children: /* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, tooltip: item.label, isActive: item.isActive, children: renderLink({
449
+ href: item.href,
416
450
  children: /* @__PURE__ */ jsxs(Fragment, { children: [
417
- action.icon && /* @__PURE__ */ jsx(action.icon, {}),
418
- /* @__PURE__ */ jsx("span", { children: action.label })
451
+ /* @__PURE__ */ jsx(item.icon, {}),
452
+ /* @__PURE__ */ jsx("span", { children: item.label })
419
453
  ] })
420
- })
421
- }
422
- ) : /* @__PURE__ */ jsxs(
423
- SidebarMenuButton,
424
- {
425
- tooltip: action.label,
426
- onClick: action.onClick,
427
- className: "min-w-8 bg-primary text-primary-foreground duration-200 ease-linear hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground",
428
- children: [
429
- action.icon && /* @__PURE__ */ jsx(action.icon, {}),
430
- /* @__PURE__ */ jsx("span", { children: action.label })
431
- ]
432
- }
433
- ) }) }),
434
- /* @__PURE__ */ jsx(SidebarMenu, { children: navItems.map((item) => /* @__PURE__ */ jsx(SidebarMenuItem, { onClickCapture: closeMobileMenu, children: /* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, tooltip: item.label, isActive: item.isActive, children: renderLink({
435
- href: item.href,
436
- children: /* @__PURE__ */ jsxs(Fragment, { children: [
437
- /* @__PURE__ */ jsx(item.icon, {}),
438
- /* @__PURE__ */ jsx("span", { children: item.label })
439
- ] })
440
- }) }) }, item.label)) })
441
- ] }) }) }),
442
- /* @__PURE__ */ jsx(SidebarFooter, { children: /* @__PURE__ */ jsx(NavUser, { user }) })
454
+ }) }) }, item.label)) })
455
+ ] }) })
456
+ },
457
+ `${sidebarContentKey ?? "default"}-content`
458
+ ),
459
+ /* @__PURE__ */ jsxs(
460
+ SidebarFooter,
461
+ {
462
+ className: sidebarContentClassName,
463
+ children: [
464
+ sidebarFooterStart,
465
+ /* @__PURE__ */ jsx(NavUser, { user })
466
+ ]
467
+ },
468
+ `${sidebarContentKey ?? "default"}-footer`
469
+ )
443
470
  ] });
444
471
  }
445
472
  function ShellHeader({
@@ -449,13 +476,19 @@ function ShellHeader({
449
476
  headerEnd,
450
477
  renderLink
451
478
  }) {
479
+ const { isMobile, setOpen, setOpenMobile } = useSidebar();
480
+ const expandSidebar = useCallback(() => {
481
+ if (isMobile) setOpenMobile(true);
482
+ else setOpen(true);
483
+ }, [isMobile, setOpen, setOpenMobile]);
484
+ const headerStartContent = typeof headerStart === "function" ? headerStart({ expandSidebar }) : headerStart;
452
485
  const source = breadcrumbs?.length ? breadcrumbs : pageTitle ? [pageTitle] : [];
453
486
  const trail = source.map(
454
487
  (crumb) => typeof crumb === "string" ? { label: crumb, href: void 0 } : crumb
455
488
  );
456
489
  return /* @__PURE__ */ jsx("header", { className: "flex h-12 shrink-0 items-center gap-2 border-b transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-1 px-4 lg:gap-2 lg:px-6", children: [
457
490
  /* @__PURE__ */ jsx(SidebarTrigger, { className: "-ml-1" }),
458
- headerStart && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: headerStart }),
491
+ headerStartContent && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: headerStartContent }),
459
492
  trail.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
460
493
  /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "mx-2 data-[orientation=vertical]:h-4" }),
461
494
  /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "flex min-w-0 items-center gap-1.5 text-sm", children: trail.map((crumb, index) => {
@@ -513,6 +546,9 @@ function AppShell({
513
546
  renderLink = defaultRenderLink,
514
547
  collapsible = "icon",
515
548
  sidebarPosition = "viewport",
549
+ sidebarContentKey,
550
+ sidebarContentClassName,
551
+ sidebarFooterStart,
516
552
  side = "left",
517
553
  contentClassName = "p-6",
518
554
  children
@@ -534,7 +570,10 @@ function AppShell({
534
570
  renderLink,
535
571
  collapsible,
536
572
  side,
537
- sidebarPosition
573
+ sidebarPosition,
574
+ sidebarContentKey,
575
+ sidebarContentClassName,
576
+ sidebarFooterStart
538
577
  }
539
578
  ),
540
579
  /* @__PURE__ */ jsxs(SidebarInset, { className: "overflow-y-auto", children: [
@@ -667,7 +706,7 @@ function AppFooter({ start, end, children, className, ...props }) {
667
706
  {
668
707
  ...props,
669
708
  className: cn(
670
- "border-t px-4 py-3 text-xs text-muted-foreground sm:px-6",
709
+ "border-t bg-background px-4 py-3 text-xs text-muted-foreground sm:px-6",
671
710
  className
672
711
  ),
673
712
  children: /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center justify-between gap-3", children: [
@@ -923,6 +962,7 @@ function DataTable({
923
962
  selectable = false,
924
963
  onSelectionChange,
925
964
  pageSize = 10,
965
+ pagination,
926
966
  toolbar,
927
967
  onRowClick,
928
968
  emptyMessage = "No results.",
@@ -949,8 +989,11 @@ function DataTable({
949
989
  },
950
990
  getCoreRowModel: getCoreRowModel(),
951
991
  getSortedRowModel: getSortedRowModel(),
952
- ...pageSize > 0 ? { getPaginationRowModel: getPaginationRowModel() } : {},
953
- initialState: pageSize > 0 ? { pagination: { pageSize } } : void 0,
992
+ // Server-paginated tables must not slice: `data` is already the page, and
993
+ // running the client model over it would paginate a single page again.
994
+ ...pageSize > 0 && !pagination ? { getPaginationRowModel: getPaginationRowModel() } : {},
995
+ ...pagination ? { manualPagination: true } : {},
996
+ initialState: pageSize > 0 && !pagination ? { pagination: { pageSize } } : void 0,
954
997
  enableRowSelection: selectable
955
998
  });
956
999
  React21.useEffect(() => {
@@ -958,6 +1001,12 @@ function DataTable({
958
1001
  onSelectionChange(table.getSelectedRowModel().rows.map((r) => r.original));
959
1002
  }, [rowSelection]);
960
1003
  const rows = table.getRowModel().rows;
1004
+ const canPrevious = pagination ? pagination.hasPrevious ?? pagination.pageIndex > 0 : table.getCanPreviousPage();
1005
+ const canNext = pagination ? pagination.hasNext ?? (pagination.pageCount !== void 0 && pagination.pageIndex < pagination.pageCount - 1) : table.getCanNextPage();
1006
+ const goPrevious = () => pagination ? pagination.onPageChange(pagination.pageIndex - 1) : table.previousPage();
1007
+ const goNext = () => pagination ? pagination.onPageChange(pagination.pageIndex + 1) : table.nextPage();
1008
+ const showPager = pagination ? canPrevious || canNext : pageSize > 0 && table.getPageCount() > 1;
1009
+ const pageLabel = pagination ? pagination.pageCount !== void 0 ? `Page ${pagination.pageIndex + 1} of ${pagination.pageCount}` : `Page ${pagination.pageIndex + 1}` : `Page ${table.getState().pagination.pageIndex + 1} of ${table.getPageCount()}`;
961
1010
  return /* @__PURE__ */ jsxs("div", { className: cn$1("space-y-4", className), children: [
962
1011
  (searchKey || toolbar) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
963
1012
  searchKey ? /* @__PURE__ */ jsxs("div", { className: "relative max-w-sm flex-1", children: [
@@ -1013,18 +1062,18 @@ function DataTable({
1013
1062
  row.id
1014
1063
  )) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: allColumns.length, className: "h-24 text-center text-muted-foreground", children: emptyMessage }) }) })
1015
1064
  ] }) }),
1016
- (selectable || pageSize > 0 && table.getPageCount() > 1) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1065
+ (selectable || showPager) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1017
1066
  /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
1018
1067
  selectable && `${table.getFilteredSelectedRowModel().rows.length} of ${table.getFilteredRowModel().rows.length} selected`,
1019
- selectable && pageSize > 0 && table.getPageCount() > 1 && " \xB7 ",
1020
- pageSize > 0 && table.getPageCount() > 1 && `Page ${table.getState().pagination.pageIndex + 1} of ${table.getPageCount()}`
1068
+ selectable && showPager && " \xB7 ",
1069
+ showPager && pageLabel
1021
1070
  ] }),
1022
- pageSize > 0 && table.getPageCount() > 1 && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1023
- /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: () => table.previousPage(), disabled: !table.getCanPreviousPage(), children: [
1071
+ showPager && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1072
+ /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: goPrevious, disabled: !canPrevious, children: [
1024
1073
  /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4" }),
1025
1074
  " Previous"
1026
1075
  ] }),
1027
- /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: () => table.nextPage(), disabled: !table.getCanNextPage(), children: [
1076
+ /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: goNext, disabled: !canNext, children: [
1028
1077
  "Next ",
1029
1078
  /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" })
1030
1079
  ] })
@@ -1314,19 +1363,55 @@ function OnboardingWizard({
1314
1363
  ] })
1315
1364
  ] });
1316
1365
  }
1317
- function EmptyState({ icon: Icon, title, description, action, className, ...props }) {
1366
+ function EmptyState({
1367
+ icon: Icon,
1368
+ title,
1369
+ description,
1370
+ eyebrow,
1371
+ action,
1372
+ secondaryAction,
1373
+ variant = "plain",
1374
+ compact = false,
1375
+ fill = false,
1376
+ className,
1377
+ ...props
1378
+ }) {
1379
+ const card = variant === "card";
1318
1380
  return /* @__PURE__ */ jsxs(
1319
1381
  "div",
1320
1382
  {
1321
- className: cn$1("flex flex-col items-center justify-center gap-3 py-12 text-center", className),
1383
+ className: cn$1(
1384
+ "relative flex flex-col items-center justify-center overflow-hidden text-center",
1385
+ !card && "gap-3 py-12",
1386
+ card && "min-h-72 rounded-xl border border-dashed bg-card/80 p-8 shadow-sm sm:p-10",
1387
+ card && compact && "min-h-0 p-5 sm:p-6",
1388
+ fill && "min-h-0 w-full flex-1",
1389
+ className
1390
+ ),
1322
1391
  ...props,
1323
1392
  children: [
1324
- Icon && /* @__PURE__ */ jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-2xl border bg-muted", children: /* @__PURE__ */ jsx(Icon, { className: "size-6 text-muted-foreground" }) }),
1325
- /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1326
- /* @__PURE__ */ jsx("h3", { className: "font-semibold", children: title }),
1327
- description && /* @__PURE__ */ jsx("p", { className: "max-w-xs text-sm text-muted-foreground", children: description })
1328
- ] }),
1329
- action
1393
+ card && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-10 top-0 h-24 rounded-full bg-primary/10 blur-3xl" }),
1394
+ /* @__PURE__ */ jsxs("div", { className: cn$1("relative flex flex-col items-center", card ? "gap-4" : "gap-3"), children: [
1395
+ Icon && /* @__PURE__ */ jsx(
1396
+ "div",
1397
+ {
1398
+ className: cn$1(
1399
+ "flex size-12 items-center justify-center rounded-2xl border",
1400
+ card ? "bg-background text-primary shadow-sm" : "bg-muted text-muted-foreground"
1401
+ ),
1402
+ children: /* @__PURE__ */ jsx(Icon, { className: card ? "size-5" : "size-6" })
1403
+ }
1404
+ ),
1405
+ /* @__PURE__ */ jsxs("div", { className: cn$1(card ? "max-w-md space-y-2" : "max-w-xs space-y-1"), children: [
1406
+ eyebrow && /* @__PURE__ */ jsx("p", { className: "text-xs font-medium uppercase tracking-[0.2em] text-muted-foreground", children: eyebrow }),
1407
+ /* @__PURE__ */ jsx("h3", { className: cn$1("font-semibold", card && "text-xl tracking-tight"), children: title }),
1408
+ description && /* @__PURE__ */ jsx("div", { className: cn$1("text-sm text-muted-foreground", card && "leading-6"), children: description })
1409
+ ] }),
1410
+ (action || secondaryAction) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3 sm:flex-row", children: [
1411
+ action,
1412
+ secondaryAction
1413
+ ] })
1414
+ ] })
1330
1415
  ]
1331
1416
  }
1332
1417
  );
@@ -4126,6 +4211,51 @@ function CommandMenu({
4126
4211
  ] })
4127
4212
  ] });
4128
4213
  }
4214
+ function LoadMore({
4215
+ hasNextPage,
4216
+ isFetchingNextPage,
4217
+ fetchNextPage,
4218
+ auto = true,
4219
+ label = "more",
4220
+ rootMargin = "400px",
4221
+ className,
4222
+ ...props
4223
+ }) {
4224
+ const sentinelRef = React21.useRef(null);
4225
+ const stateRef = React21.useRef({ hasNextPage, isFetchingNextPage, fetchNextPage });
4226
+ stateRef.current = { hasNextPage, isFetchingNextPage, fetchNextPage };
4227
+ React21.useEffect(() => {
4228
+ if (!auto) return;
4229
+ const node = sentinelRef.current;
4230
+ if (!node) return;
4231
+ const observer = new IntersectionObserver(
4232
+ ([entry]) => {
4233
+ if (!entry?.isIntersecting) return;
4234
+ const state = stateRef.current;
4235
+ if (state.hasNextPage && !state.isFetchingNextPage) void state.fetchNextPage();
4236
+ },
4237
+ { rootMargin }
4238
+ );
4239
+ observer.observe(node);
4240
+ return () => observer.disconnect();
4241
+ }, [auto, rootMargin]);
4242
+ if (!hasNextPage) return null;
4243
+ return /* @__PURE__ */ jsx("div", { ref: sentinelRef, className: cn$1("flex justify-center py-4", className), ...props, children: auto ? /* @__PURE__ */ jsx("span", { className: "flex h-9 items-center text-sm text-muted-foreground", "aria-live": "polite", children: isFetchingNextPage && /* @__PURE__ */ jsxs(Fragment, { children: [
4244
+ /* @__PURE__ */ jsx(Spinner, { className: "mr-2 size-4" }),
4245
+ " Loading more\u2026"
4246
+ ] }) }) : /* @__PURE__ */ jsx(
4247
+ Button$1,
4248
+ {
4249
+ variant: "outline",
4250
+ onClick: () => void fetchNextPage(),
4251
+ disabled: isFetchingNextPage,
4252
+ children: isFetchingNextPage ? /* @__PURE__ */ jsxs(Fragment, { children: [
4253
+ /* @__PURE__ */ jsx(Spinner, { className: "mr-2 size-4" }),
4254
+ " Loading\u2026"
4255
+ ] }) : `Load more ${label}`
4256
+ }
4257
+ ) });
4258
+ }
4129
4259
  function DataView({
4130
4260
  items,
4131
4261
  getRowId,
@@ -4208,6 +4338,9 @@ function Chart({
4208
4338
  height = 300,
4209
4339
  grid = true,
4210
4340
  legend,
4341
+ stacked = false,
4342
+ xTickFormatter,
4343
+ yDomain,
4211
4344
  valueFormatter = (v) => String(v),
4212
4345
  className
4213
4346
  }) {
@@ -4250,12 +4383,13 @@ function Chart({
4250
4383
  if (type === "bar") {
4251
4384
  chart = /* @__PURE__ */ jsxs(BarChart, { data, barCategoryGap: "25%", children: [
4252
4385
  gridEl,
4253
- /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, ...axisProps }),
4254
- /* @__PURE__ */ jsx(YAxis, { ...axisProps, width: 48, tickFormatter: valueFormatter }),
4386
+ /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, ...axisProps, tickFormatter: xTickFormatter }),
4387
+ /* @__PURE__ */ jsx(YAxis, { ...axisProps, width: 48, domain: yDomain, tickFormatter: valueFormatter }),
4255
4388
  tooltip,
4256
4389
  series.map((s, i) => /* @__PURE__ */ jsx(
4257
4390
  Bar,
4258
4391
  {
4392
+ stackId: stacked ? "stack" : void 0,
4259
4393
  dataKey: s.key,
4260
4394
  name: s.label ?? s.key,
4261
4395
  fill: seriesColor(s, i),
@@ -4268,8 +4402,8 @@ function Chart({
4268
4402
  } else if (type === "area") {
4269
4403
  chart = /* @__PURE__ */ jsxs(AreaChart, { data, children: [
4270
4404
  gridEl,
4271
- /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, ...axisProps }),
4272
- /* @__PURE__ */ jsx(YAxis, { ...axisProps, width: 48, tickFormatter: valueFormatter }),
4405
+ /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, ...axisProps, tickFormatter: xTickFormatter }),
4406
+ /* @__PURE__ */ jsx(YAxis, { ...axisProps, width: 48, domain: yDomain, tickFormatter: valueFormatter }),
4273
4407
  tooltip,
4274
4408
  series.map((s, i) => /* @__PURE__ */ jsx(
4275
4409
  Area,
@@ -4277,10 +4411,11 @@ function Chart({
4277
4411
  type: "monotone",
4278
4412
  dataKey: s.key,
4279
4413
  name: s.label ?? s.key,
4414
+ stackId: stacked ? "stack" : void 0,
4280
4415
  stroke: seriesColor(s, i),
4281
4416
  strokeWidth: 2,
4282
4417
  fill: seriesColor(s, i),
4283
- fillOpacity: 0.12,
4418
+ fillOpacity: stacked ? 0.35 : 0.12,
4284
4419
  dot: false,
4285
4420
  activeDot: { r: 4 }
4286
4421
  },
@@ -4290,8 +4425,8 @@ function Chart({
4290
4425
  } else {
4291
4426
  chart = /* @__PURE__ */ jsxs(LineChart, { data, children: [
4292
4427
  gridEl,
4293
- /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, ...axisProps }),
4294
- /* @__PURE__ */ jsx(YAxis, { ...axisProps, width: 48, tickFormatter: valueFormatter }),
4428
+ /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, ...axisProps, tickFormatter: xTickFormatter }),
4429
+ /* @__PURE__ */ jsx(YAxis, { ...axisProps, width: 48, domain: yDomain, tickFormatter: valueFormatter }),
4295
4430
  tooltip,
4296
4431
  series.map((s, i) => /* @__PURE__ */ jsx(
4297
4432
  Line,
@@ -4518,9 +4653,18 @@ function NotificationToast({
4518
4653
  ] })
4519
4654
  ] }) });
4520
4655
  }
4656
+ function defaultDuration(variant, hasAction) {
4657
+ if (variant === "error") return 1e4;
4658
+ if (variant === "warning") return 8e3;
4659
+ if (hasAction) return 8e3;
4660
+ return void 0;
4661
+ }
4521
4662
  function notify(options) {
4522
4663
  const { duration, ...toastProps } = options;
4523
- return toast.custom((id) => /* @__PURE__ */ jsx(NotificationToast, { ...toastProps, onDismiss: () => toast.dismiss(id) }), { duration });
4664
+ const resolved = duration ?? defaultDuration(toastProps.variant, Boolean(toastProps.action || toastProps.secondaryAction));
4665
+ return toast.custom((id) => /* @__PURE__ */ jsx(NotificationToast, { ...toastProps, onDismiss: () => toast.dismiss(id) }), {
4666
+ duration: resolved
4667
+ });
4524
4668
  }
4525
4669
  function NotificationsPopover({
4526
4670
  notifications,
@@ -5455,18 +5599,21 @@ function PostList({
5455
5599
  posts,
5456
5600
  renderLink,
5457
5601
  emptyMessage = "No posts published yet.",
5458
- columns = 3,
5602
+ columns,
5459
5603
  className
5460
5604
  }) {
5461
5605
  if (posts.length === 0) {
5462
5606
  return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground italic", children: emptyMessage });
5463
5607
  }
5608
+ const resolvedColumns = columns ?? (posts.length < 3 ? 2 : 3);
5609
+ const balancedShortListClassName = columns === void 0 ? posts.length === 1 ? "mx-auto w-full max-w-md sm:grid-cols-1" : posts.length === 2 ? "mx-auto w-full max-w-3xl" : void 0 : void 0;
5464
5610
  return /* @__PURE__ */ jsx(
5465
5611
  "div",
5466
5612
  {
5467
5613
  className: cn$1(
5468
5614
  "grid grid-cols-1 gap-x-8 gap-y-14 sm:grid-cols-2",
5469
- columns === 3 && "lg:grid-cols-3",
5615
+ resolvedColumns === 3 && "lg:grid-cols-3",
5616
+ balancedShortListClassName,
5470
5617
  className
5471
5618
  ),
5472
5619
  children: posts.map((post) => /* @__PURE__ */ jsx(PostCard, { ...post, renderLink }, post.slug))
@@ -5684,6 +5831,6 @@ function usePagination(total, pageSize) {
5684
5831
  return { page, pageSize, totalPages, offset, hasPrev: page > 1, hasNext: page < totalPages, goTo, next, prev };
5685
5832
  }
5686
5833
 
5687
- export { ActivityFeed, AnimatedPill, AnimatedSwap, AppContent, AppFooter, 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 };
5834
+ export { ActivityFeed, AnimatedPill, AnimatedSwap, AppContent, AppFooter, 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, LoadMore, 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 };
5688
5835
  //# sourceMappingURL=index.js.map
5689
5836
  //# sourceMappingURL=index.js.map