@olwiba/ui 0.2.22 → 0.2.24
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 +106 -10
- package/dist/index.js +341 -103
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/app/AppFooter.tsx +39 -0
- package/src/app/AppPageHero.tsx +73 -20
- package/src/app/AppShell.tsx +179 -32
- package/src/app/EmptyState.tsx +63 -12
- package/src/blog/PostList.tsx +19 -6
- package/src/components/LoadMore.tsx +80 -0
- package/src/index.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -2,10 +2,10 @@ 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, 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,
|
|
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
|
-
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,
|
|
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';
|
|
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';
|
|
@@ -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,71 +390,137 @@ 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(
|
|
391
|
-
|
|
393
|
+
/* @__PURE__ */ jsx(
|
|
394
|
+
SidebarHeader,
|
|
392
395
|
{
|
|
393
|
-
className: cn$1(
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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
|
-
|
|
418
|
-
/* @__PURE__ */ jsx("span", { children:
|
|
451
|
+
/* @__PURE__ */ jsx(item.icon, {}),
|
|
452
|
+
/* @__PURE__ */ jsx("span", { children: item.label })
|
|
419
453
|
] })
|
|
420
|
-
})
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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({
|
|
446
473
|
pageTitle,
|
|
474
|
+
breadcrumbs,
|
|
447
475
|
headerStart,
|
|
448
|
-
headerEnd
|
|
476
|
+
headerEnd,
|
|
477
|
+
renderLink
|
|
449
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;
|
|
485
|
+
const source = breadcrumbs?.length ? breadcrumbs : pageTitle ? [pageTitle] : [];
|
|
486
|
+
const trail = source.map(
|
|
487
|
+
(crumb) => typeof crumb === "string" ? { label: crumb, href: void 0 } : crumb
|
|
488
|
+
);
|
|
450
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: [
|
|
451
490
|
/* @__PURE__ */ jsx(SidebarTrigger, { className: "-ml-1" }),
|
|
452
|
-
|
|
453
|
-
/* @__PURE__ */
|
|
454
|
-
|
|
491
|
+
headerStartContent && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: headerStartContent }),
|
|
492
|
+
trail.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
493
|
+
/* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "mx-2 data-[orientation=vertical]:h-4" }),
|
|
494
|
+
/* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "flex min-w-0 items-center gap-1.5 text-sm", children: trail.map((crumb, index) => {
|
|
495
|
+
const isCurrent = index === trail.length - 1;
|
|
496
|
+
const isLink = !isCurrent && Boolean(crumb.href);
|
|
497
|
+
return /* @__PURE__ */ jsxs(
|
|
498
|
+
"span",
|
|
499
|
+
{
|
|
500
|
+
className: "flex min-w-0 items-center gap-1.5",
|
|
501
|
+
children: [
|
|
502
|
+
index > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "text-muted-foreground/60", children: "/" }),
|
|
503
|
+
isLink ? renderLink({
|
|
504
|
+
href: crumb.href,
|
|
505
|
+
className: "truncate rounded-sm text-muted-foreground transition-colors hover:text-foreground hover:underline underline-offset-4 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
506
|
+
children: crumb.label
|
|
507
|
+
}) : /* @__PURE__ */ jsx(
|
|
508
|
+
"span",
|
|
509
|
+
{
|
|
510
|
+
"aria-current": isCurrent ? "page" : void 0,
|
|
511
|
+
className: cn$1(
|
|
512
|
+
"truncate",
|
|
513
|
+
isCurrent ? "font-medium text-foreground" : "text-muted-foreground"
|
|
514
|
+
),
|
|
515
|
+
children: crumb.label
|
|
516
|
+
}
|
|
517
|
+
)
|
|
518
|
+
]
|
|
519
|
+
},
|
|
520
|
+
`${crumb.label}-${index}`
|
|
521
|
+
);
|
|
522
|
+
}) })
|
|
523
|
+
] }),
|
|
455
524
|
headerEnd && /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center gap-1", children: headerEnd })
|
|
456
525
|
] }) });
|
|
457
526
|
}
|
|
@@ -469,12 +538,17 @@ function AppShell({
|
|
|
469
538
|
navItems = [],
|
|
470
539
|
action,
|
|
471
540
|
user = defaultUser,
|
|
472
|
-
pageTitle
|
|
541
|
+
pageTitle,
|
|
542
|
+
breadcrumbs,
|
|
543
|
+
footer,
|
|
473
544
|
headerStart,
|
|
474
545
|
headerEnd,
|
|
475
546
|
renderLink = defaultRenderLink,
|
|
476
547
|
collapsible = "icon",
|
|
477
548
|
sidebarPosition = "viewport",
|
|
549
|
+
sidebarContentKey,
|
|
550
|
+
sidebarContentClassName,
|
|
551
|
+
sidebarFooterStart,
|
|
478
552
|
side = "left",
|
|
479
553
|
contentClassName = "p-6",
|
|
480
554
|
children
|
|
@@ -496,12 +570,25 @@ function AppShell({
|
|
|
496
570
|
renderLink,
|
|
497
571
|
collapsible,
|
|
498
572
|
side,
|
|
499
|
-
sidebarPosition
|
|
573
|
+
sidebarPosition,
|
|
574
|
+
sidebarContentKey,
|
|
575
|
+
sidebarContentClassName,
|
|
576
|
+
sidebarFooterStart
|
|
500
577
|
}
|
|
501
578
|
),
|
|
502
579
|
/* @__PURE__ */ jsxs(SidebarInset, { className: "overflow-y-auto", children: [
|
|
503
|
-
/* @__PURE__ */ jsx(
|
|
504
|
-
|
|
580
|
+
/* @__PURE__ */ jsx(
|
|
581
|
+
ShellHeader,
|
|
582
|
+
{
|
|
583
|
+
pageTitle,
|
|
584
|
+
breadcrumbs,
|
|
585
|
+
headerStart,
|
|
586
|
+
headerEnd,
|
|
587
|
+
renderLink
|
|
588
|
+
}
|
|
589
|
+
),
|
|
590
|
+
/* @__PURE__ */ jsx("div", { className: cn$1("flex min-h-0 grow shrink-0 flex-col", contentClassName), children }),
|
|
591
|
+
footer && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: footer })
|
|
505
592
|
] })
|
|
506
593
|
]
|
|
507
594
|
}
|
|
@@ -519,49 +606,116 @@ function AppPageHero({
|
|
|
519
606
|
action,
|
|
520
607
|
children,
|
|
521
608
|
compact = false,
|
|
609
|
+
surface = "card",
|
|
522
610
|
className
|
|
523
611
|
}) {
|
|
612
|
+
const isPlain = surface === "plain";
|
|
524
613
|
return /* @__PURE__ */ jsxs(
|
|
525
614
|
"section",
|
|
526
615
|
{
|
|
527
616
|
className: cn(
|
|
528
|
-
"relative
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
617
|
+
"relative",
|
|
618
|
+
!isPlain && [
|
|
619
|
+
"overflow-hidden border bg-card/80 shadow-sm",
|
|
620
|
+
// Compact is the page-pattern header: same surface and glow, less
|
|
621
|
+
// bulk, so it introduces a route without eating the fold above dense
|
|
622
|
+
// content.
|
|
623
|
+
compact ? "rounded-2xl p-4 sm:p-5" : "rounded-3xl p-5 sm:p-6",
|
|
624
|
+
// The glow blobs are decoration, and `::after` is the section's last
|
|
625
|
+
// child — so with everything on `z-index: auto` it paints above the
|
|
626
|
+
// header content and swallows clicks on whatever sits under it. At
|
|
627
|
+
// narrow widths the action row stacks below the copy, right into the
|
|
628
|
+
// bottom-left blob, which is how a visible button stops responding.
|
|
629
|
+
// pointer-events-none keeps them purely visual.
|
|
630
|
+
"before:pointer-events-none before:absolute before:-right-16 before:-top-16 before:rounded-full before:bg-primary/15 before:blur-3xl",
|
|
631
|
+
"after:pointer-events-none after:absolute after:left-10 after:rounded-full after:bg-primary/10 after:blur-3xl",
|
|
632
|
+
compact ? "before:size-32 after:-bottom-16 after:size-40" : "before:size-44 after:-bottom-20 after:size-52"
|
|
633
|
+
],
|
|
537
634
|
className
|
|
538
635
|
),
|
|
539
636
|
children: [
|
|
540
|
-
/* @__PURE__ */ jsxs(
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
637
|
+
/* @__PURE__ */ jsxs(
|
|
638
|
+
"div",
|
|
639
|
+
{
|
|
640
|
+
className: cn(
|
|
641
|
+
"relative flex flex-col sm:flex-row sm:items-start sm:justify-between",
|
|
642
|
+
compact ? "gap-3" : "gap-5"
|
|
643
|
+
),
|
|
644
|
+
children: [
|
|
645
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 items-start", compact ? "gap-3" : "gap-4"), children: [
|
|
646
|
+
Icon && /* @__PURE__ */ jsx(
|
|
647
|
+
"div",
|
|
648
|
+
{
|
|
649
|
+
className: cn(
|
|
650
|
+
"flex shrink-0 items-center justify-center border bg-background/70 text-primary shadow-sm",
|
|
651
|
+
compact ? "size-10 rounded-xl" : "size-12 rounded-2xl"
|
|
652
|
+
),
|
|
653
|
+
children: /* @__PURE__ */ jsx(Icon, { className: compact ? "size-4" : "size-5" })
|
|
654
|
+
}
|
|
655
|
+
),
|
|
656
|
+
/* @__PURE__ */ jsxs("div", { className: cn("min-w-0", compact ? "space-y-1" : "space-y-2"), children: [
|
|
657
|
+
eyebrow && /* @__PURE__ */ jsx(
|
|
658
|
+
"p",
|
|
659
|
+
{
|
|
660
|
+
className: cn(
|
|
661
|
+
"font-semibold uppercase text-primary/80",
|
|
662
|
+
compact ? "text-[11px] tracking-[0.18em]" : "text-xs tracking-[0.24em]"
|
|
663
|
+
),
|
|
664
|
+
children: eyebrow
|
|
665
|
+
}
|
|
551
666
|
),
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
667
|
+
/* @__PURE__ */ jsx(
|
|
668
|
+
"h1",
|
|
669
|
+
{
|
|
670
|
+
className: cn(
|
|
671
|
+
// Default leading puts ~4px of half-leading above the cap, so
|
|
672
|
+
// the title reads as sitting low against a top-aligned icon.
|
|
673
|
+
"font-semibold leading-tight tracking-tight",
|
|
674
|
+
compact ? "text-xl sm:text-2xl" : "text-3xl sm:text-4xl"
|
|
675
|
+
),
|
|
676
|
+
children: title
|
|
677
|
+
}
|
|
678
|
+
),
|
|
679
|
+
description && // A div, not a p: `description` is a ReactNode, and callers pass
|
|
680
|
+
// multiple paragraphs. Nesting <p> inside <p> is invalid HTML and
|
|
681
|
+
// the parser silently unnests it, which breaks hydration.
|
|
682
|
+
/* @__PURE__ */ jsx(
|
|
683
|
+
"div",
|
|
684
|
+
{
|
|
685
|
+
className: cn(
|
|
686
|
+
"max-w-2xl text-muted-foreground",
|
|
687
|
+
compact ? "text-sm leading-5" : "text-sm leading-6"
|
|
688
|
+
),
|
|
689
|
+
children: description
|
|
690
|
+
}
|
|
691
|
+
)
|
|
692
|
+
] })
|
|
693
|
+
] }),
|
|
694
|
+
action && /* @__PURE__ */ jsx("div", { className: cn("relative shrink-0", !compact && "sm:pt-1"), children: action })
|
|
695
|
+
]
|
|
696
|
+
}
|
|
697
|
+
),
|
|
698
|
+
children && /* @__PURE__ */ jsx("div", { className: cn("relative", compact ? "mt-4" : "mt-5"), children })
|
|
561
699
|
]
|
|
562
700
|
}
|
|
563
701
|
);
|
|
564
702
|
}
|
|
703
|
+
function AppFooter({ start, end, children, className, ...props }) {
|
|
704
|
+
return /* @__PURE__ */ jsx(
|
|
705
|
+
"footer",
|
|
706
|
+
{
|
|
707
|
+
...props,
|
|
708
|
+
className: cn(
|
|
709
|
+
"border-t bg-background px-4 py-3 text-xs text-muted-foreground sm:px-6",
|
|
710
|
+
className
|
|
711
|
+
),
|
|
712
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center justify-between gap-3", children: [
|
|
713
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 font-medium text-foreground", children: start ?? children }),
|
|
714
|
+
end && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: end })
|
|
715
|
+
] })
|
|
716
|
+
}
|
|
717
|
+
);
|
|
718
|
+
}
|
|
565
719
|
var defaultRenderLink2 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
|
|
566
720
|
function CenteredAuth({ children, brand, framed, className }) {
|
|
567
721
|
if (framed) {
|
|
@@ -1199,19 +1353,55 @@ function OnboardingWizard({
|
|
|
1199
1353
|
] })
|
|
1200
1354
|
] });
|
|
1201
1355
|
}
|
|
1202
|
-
function EmptyState({
|
|
1356
|
+
function EmptyState({
|
|
1357
|
+
icon: Icon,
|
|
1358
|
+
title,
|
|
1359
|
+
description,
|
|
1360
|
+
eyebrow,
|
|
1361
|
+
action,
|
|
1362
|
+
secondaryAction,
|
|
1363
|
+
variant = "plain",
|
|
1364
|
+
compact = false,
|
|
1365
|
+
fill = false,
|
|
1366
|
+
className,
|
|
1367
|
+
...props
|
|
1368
|
+
}) {
|
|
1369
|
+
const card = variant === "card";
|
|
1203
1370
|
return /* @__PURE__ */ jsxs(
|
|
1204
1371
|
"div",
|
|
1205
1372
|
{
|
|
1206
|
-
className: cn$1(
|
|
1373
|
+
className: cn$1(
|
|
1374
|
+
"relative flex flex-col items-center justify-center overflow-hidden text-center",
|
|
1375
|
+
!card && "gap-3 py-12",
|
|
1376
|
+
card && "min-h-72 rounded-xl border border-dashed bg-card/80 p-8 shadow-sm sm:p-10",
|
|
1377
|
+
card && compact && "min-h-0 p-5 sm:p-6",
|
|
1378
|
+
fill && "min-h-0 w-full flex-1",
|
|
1379
|
+
className
|
|
1380
|
+
),
|
|
1207
1381
|
...props,
|
|
1208
1382
|
children: [
|
|
1209
|
-
|
|
1210
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
1211
|
-
/* @__PURE__ */ jsx(
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1383
|
+
card && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-10 top-0 h-24 rounded-full bg-primary/10 blur-3xl" }),
|
|
1384
|
+
/* @__PURE__ */ jsxs("div", { className: cn$1("relative flex flex-col items-center", card ? "gap-4" : "gap-3"), children: [
|
|
1385
|
+
Icon && /* @__PURE__ */ jsx(
|
|
1386
|
+
"div",
|
|
1387
|
+
{
|
|
1388
|
+
className: cn$1(
|
|
1389
|
+
"flex size-12 items-center justify-center rounded-2xl border",
|
|
1390
|
+
card ? "bg-background text-primary shadow-sm" : "bg-muted text-muted-foreground"
|
|
1391
|
+
),
|
|
1392
|
+
children: /* @__PURE__ */ jsx(Icon, { className: card ? "size-5" : "size-6" })
|
|
1393
|
+
}
|
|
1394
|
+
),
|
|
1395
|
+
/* @__PURE__ */ jsxs("div", { className: cn$1(card ? "max-w-md space-y-2" : "max-w-xs space-y-1"), children: [
|
|
1396
|
+
eyebrow && /* @__PURE__ */ jsx("p", { className: "text-xs font-medium uppercase tracking-[0.2em] text-muted-foreground", children: eyebrow }),
|
|
1397
|
+
/* @__PURE__ */ jsx("h3", { className: cn$1("font-semibold", card && "text-xl tracking-tight"), children: title }),
|
|
1398
|
+
description && /* @__PURE__ */ jsx("div", { className: cn$1("text-sm text-muted-foreground", card && "leading-6"), children: description })
|
|
1399
|
+
] }),
|
|
1400
|
+
(action || secondaryAction) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3 sm:flex-row", children: [
|
|
1401
|
+
action,
|
|
1402
|
+
secondaryAction
|
|
1403
|
+
] })
|
|
1404
|
+
] })
|
|
1215
1405
|
]
|
|
1216
1406
|
}
|
|
1217
1407
|
);
|
|
@@ -4011,6 +4201,51 @@ function CommandMenu({
|
|
|
4011
4201
|
] })
|
|
4012
4202
|
] });
|
|
4013
4203
|
}
|
|
4204
|
+
function LoadMore({
|
|
4205
|
+
hasNextPage,
|
|
4206
|
+
isFetchingNextPage,
|
|
4207
|
+
fetchNextPage,
|
|
4208
|
+
auto = true,
|
|
4209
|
+
label = "more",
|
|
4210
|
+
rootMargin = "400px",
|
|
4211
|
+
className,
|
|
4212
|
+
...props
|
|
4213
|
+
}) {
|
|
4214
|
+
const sentinelRef = React21.useRef(null);
|
|
4215
|
+
const stateRef = React21.useRef({ hasNextPage, isFetchingNextPage, fetchNextPage });
|
|
4216
|
+
stateRef.current = { hasNextPage, isFetchingNextPage, fetchNextPage };
|
|
4217
|
+
React21.useEffect(() => {
|
|
4218
|
+
if (!auto) return;
|
|
4219
|
+
const node = sentinelRef.current;
|
|
4220
|
+
if (!node) return;
|
|
4221
|
+
const observer = new IntersectionObserver(
|
|
4222
|
+
([entry]) => {
|
|
4223
|
+
if (!entry?.isIntersecting) return;
|
|
4224
|
+
const state = stateRef.current;
|
|
4225
|
+
if (state.hasNextPage && !state.isFetchingNextPage) void state.fetchNextPage();
|
|
4226
|
+
},
|
|
4227
|
+
{ rootMargin }
|
|
4228
|
+
);
|
|
4229
|
+
observer.observe(node);
|
|
4230
|
+
return () => observer.disconnect();
|
|
4231
|
+
}, [auto, rootMargin]);
|
|
4232
|
+
if (!hasNextPage) return null;
|
|
4233
|
+
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: [
|
|
4234
|
+
/* @__PURE__ */ jsx(Spinner, { className: "mr-2 size-4" }),
|
|
4235
|
+
" Loading more\u2026"
|
|
4236
|
+
] }) }) : /* @__PURE__ */ jsx(
|
|
4237
|
+
Button$1,
|
|
4238
|
+
{
|
|
4239
|
+
variant: "outline",
|
|
4240
|
+
onClick: () => void fetchNextPage(),
|
|
4241
|
+
disabled: isFetchingNextPage,
|
|
4242
|
+
children: isFetchingNextPage ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4243
|
+
/* @__PURE__ */ jsx(Spinner, { className: "mr-2 size-4" }),
|
|
4244
|
+
" Loading\u2026"
|
|
4245
|
+
] }) : `Load more ${label}`
|
|
4246
|
+
}
|
|
4247
|
+
) });
|
|
4248
|
+
}
|
|
4014
4249
|
function DataView({
|
|
4015
4250
|
items,
|
|
4016
4251
|
getRowId,
|
|
@@ -5340,18 +5575,21 @@ function PostList({
|
|
|
5340
5575
|
posts,
|
|
5341
5576
|
renderLink,
|
|
5342
5577
|
emptyMessage = "No posts published yet.",
|
|
5343
|
-
columns
|
|
5578
|
+
columns,
|
|
5344
5579
|
className
|
|
5345
5580
|
}) {
|
|
5346
5581
|
if (posts.length === 0) {
|
|
5347
5582
|
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground italic", children: emptyMessage });
|
|
5348
5583
|
}
|
|
5584
|
+
const resolvedColumns = columns ?? (posts.length < 3 ? 2 : 3);
|
|
5585
|
+
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;
|
|
5349
5586
|
return /* @__PURE__ */ jsx(
|
|
5350
5587
|
"div",
|
|
5351
5588
|
{
|
|
5352
5589
|
className: cn$1(
|
|
5353
5590
|
"grid grid-cols-1 gap-x-8 gap-y-14 sm:grid-cols-2",
|
|
5354
|
-
|
|
5591
|
+
resolvedColumns === 3 && "lg:grid-cols-3",
|
|
5592
|
+
balancedShortListClassName,
|
|
5355
5593
|
className
|
|
5356
5594
|
),
|
|
5357
5595
|
children: posts.map((post) => /* @__PURE__ */ jsx(PostCard, { ...post, renderLink }, post.slug))
|
|
@@ -5569,6 +5807,6 @@ function usePagination(total, pageSize) {
|
|
|
5569
5807
|
return { page, pageSize, totalPages, offset, hasPrev: page > 1, hasNext: page < totalPages, goTo, next, prev };
|
|
5570
5808
|
}
|
|
5571
5809
|
|
|
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 };
|
|
5810
|
+
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 };
|
|
5573
5811
|
//# sourceMappingURL=index.js.map
|
|
5574
5812
|
//# sourceMappingURL=index.js.map
|