@lessly/ui 0.14.1 → 0.15.0

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 CHANGED
@@ -1352,6 +1352,15 @@ interface NotificationProduct {
1352
1352
  }
1353
1353
  declare const severityLabels: Record<NotificationSeverity, string>;
1354
1354
  declare function severityBadgeVariant(severity: NotificationSeverity): 'destructive' | 'warning' | 'secondary';
1355
+ /** Per-severity dwell in seconds. `Infinity` means the toast stays until dismissed. */
1356
+ type NotificationToastDwell = Record<NotificationSeverity, number>;
1357
+ /**
1358
+ * Toasts peek, then tuck away — the record behind the bell is the durable copy, so
1359
+ * nothing is lost when a card leaves. Critical is the exception: it stays in the
1360
+ * corner until it is handled, because for an incident the persistent toast IS the
1361
+ * escalation. Timing lives in the toaster; this is only the default table.
1362
+ */
1363
+ declare const TOAST_DWELL: NotificationToastDwell;
1355
1364
  /**
1356
1365
  * Reads a stamp as a relative age. `now` is injectable so the components stay
1357
1366
  * testable and consumers can substitute an absolute or localized formatter; the
@@ -1428,4 +1437,40 @@ interface NotificationSettingsProps {
1428
1437
  }
1429
1438
  declare const NotificationSettings: React$1.ForwardRefExoticComponent<NotificationSettingsProps & React$1.RefAttributes<HTMLDivElement>>;
1430
1439
 
1431
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, type AppShellProps, AppSidebar, type AppSidebarProps, AspectRatio, AuthenticatedLayout, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, type ButtonProps, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, type CarouselContextProps, CarouselItem, CarouselNext, type CarouselOptions, type CarouselPlugin, CarouselPrevious, type CarouselProps, Checkbox, Code, CodeBlock, type CodeBlockProps, type CodeLang, type CodeProps, Col, type ColProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ConfirmDialog, type ConfirmDialogProps, type ConnectionAuth, ConnectionCard, type ConnectionCardProps, type ConnectionScope, type ConnectionStatus, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, type CopyButtonProps, type CreateProductSubmit, CreateProductWindow, type CreateProductWindowOrganization, type CreateProductWindowProduct, type CreateProductWindowProps, DatePicker, type DatePickerProps, type DeltaDirection, type DeltaTone, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DocsLink, type DocsLinkProps, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExtensionIcon, type ExtensionIconProps, ExtensionLink, type ExtensionLinkProps, type ExtensionLinkUiMode, FeedbackButton, type FeedbackButtonLabels, type FeedbackButtonProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Grid, GridOverlay, type GridOverlayProps, type GridProps, HoverCard, HoverCardContent, HoverCardTrigger, InlineError, type InlineErrorProps, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Label, MenuDivider, MenuPopup, type MenuPopupProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, type NavItem, type NavLinkComponent, NavRow, type NavRowProps, type NavRowVariant, NavSectionLabel, type NavSectionLabelProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, type NotifClass, type NotificationAction, NotificationBell, type NotificationBellProps, NotificationCenter, type NotificationCenterProps, type NotificationClass, type NotificationDeepLink, type NotificationItem, type NotificationMute, type NotificationPreferences, type NotificationProduct, NotificationSettings, type NotificationSettingsProps, type NotificationSeverity, type NotificationSubscription, type NotificationThreshold, OrgProductSwitcher, type OrgProductSwitcherAction, type OrgProductSwitcherItem, type OrgProductSwitcherProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, RequestRow, type RequestRowProps, type RequestState, type RequestSurface, type ResolvedTheme, type Responsive, ScrollArea, ScrollBar, SectionIntro, type SectionIntroProps, SegmentChip, type SegmentChipProps, Select, type SelectOption, type SelectProps, Separator, type Severity, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarBackHeader, type SidebarBackHeaderProps, SidebarNav, SidebarNavLink, type SidebarNavLinkProps, type SidebarNavProps, SidebarProductHeader, type SidebarProductHeaderProps, SignInScreen, type SignInScreenProps, type SignInScreenState, Skeleton, Slider, StatCard, type StatCardProps, StatusDot, type StatusDotProps, Switch, type SwitchProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, type TextareaProps, type Theme, ThemeToggle, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UseSidebarOptions, type UseSidebarResult, UserMenu, type UserMenuItem, type UserMenuProps, type UserMenuUser, alertVariants, badgeVariants, buttonVariants, cn, formatRelativeAge, isKnownExtensionIcon, isNotificationSettled, navigationMenuTriggerStyle, segmentChipVariants, severityBadgeVariant, severityLabels, statusDotVariants, toggleVariants, useCarousel, useFormField, useIsMobile, useSidebar, useTheme };
1440
+ interface NotificationToastProps {
1441
+ item: NotificationItem;
1442
+ /** Provenance shown once per run of same-source cards. Default `true`. */
1443
+ showSource?: boolean;
1444
+ /** A short state line under the body, e.g. "Awaiting your decision — expires in 20s." */
1445
+ note?: React$1.ReactNode;
1446
+ onItemClick?(item: NotificationItem): void;
1447
+ onAction?(action: NotificationAction, item: NotificationItem): void;
1448
+ onDismiss?(item: NotificationItem): void;
1449
+ /** Accessible label for the close button. Default `"Dismiss"`. */
1450
+ dismissLabel?: string;
1451
+ className?: string;
1452
+ }
1453
+ declare const NotificationToast: React$1.ForwardRefExoticComponent<NotificationToastProps & React$1.RefAttributes<HTMLDivElement>>;
1454
+
1455
+ type NotificationToasterPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
1456
+ interface NotificationToasterProps {
1457
+ /** The live queue. The consumer decides what becomes a toast at all. */
1458
+ items: NotificationItem[];
1459
+ /** Per-severity dwell in seconds, merged over `TOAST_DWELL`. `Infinity` never hides. */
1460
+ dwell?: Partial<NotificationToastDwell>;
1461
+ /** Most cards on screen at once. Default `4`. */
1462
+ max?: number;
1463
+ position?: NotificationToasterPosition;
1464
+ /** Freeze every countdown while the pointer is over the stack. Default `true`. */
1465
+ pauseOnHover?: boolean;
1466
+ /** Fires on auto-hide and on the close button alike — the item leaves the same way. */
1467
+ onDismiss?(id: string): void;
1468
+ onItemClick?(item: NotificationItem): void;
1469
+ onAction?(action: NotificationAction, item: NotificationItem): void;
1470
+ /** Per-item state line, e.g. a TTL countdown the consumer already tracks. */
1471
+ renderNote?(item: NotificationItem): React$1.ReactNode;
1472
+ className?: string;
1473
+ }
1474
+ declare const NotificationToaster: React$1.ForwardRefExoticComponent<NotificationToasterProps & React$1.RefAttributes<HTMLDivElement>>;
1475
+
1476
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, type AppShellProps, AppSidebar, type AppSidebarProps, AspectRatio, AuthenticatedLayout, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, type ButtonProps, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, type CarouselContextProps, CarouselItem, CarouselNext, type CarouselOptions, type CarouselPlugin, CarouselPrevious, type CarouselProps, Checkbox, Code, CodeBlock, type CodeBlockProps, type CodeLang, type CodeProps, Col, type ColProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ConfirmDialog, type ConfirmDialogProps, type ConnectionAuth, ConnectionCard, type ConnectionCardProps, type ConnectionScope, type ConnectionStatus, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, type CopyButtonProps, type CreateProductSubmit, CreateProductWindow, type CreateProductWindowOrganization, type CreateProductWindowProduct, type CreateProductWindowProps, DatePicker, type DatePickerProps, type DeltaDirection, type DeltaTone, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DocsLink, type DocsLinkProps, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExtensionIcon, type ExtensionIconProps, ExtensionLink, type ExtensionLinkProps, type ExtensionLinkUiMode, FeedbackButton, type FeedbackButtonLabels, type FeedbackButtonProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Grid, GridOverlay, type GridOverlayProps, type GridProps, HoverCard, HoverCardContent, HoverCardTrigger, InlineError, type InlineErrorProps, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Label, MenuDivider, MenuPopup, type MenuPopupProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, type NavItem, type NavLinkComponent, NavRow, type NavRowProps, type NavRowVariant, NavSectionLabel, type NavSectionLabelProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, type NotifClass, type NotificationAction, NotificationBell, type NotificationBellProps, NotificationCenter, type NotificationCenterProps, type NotificationClass, type NotificationDeepLink, type NotificationItem, type NotificationMute, type NotificationPreferences, type NotificationProduct, NotificationSettings, type NotificationSettingsProps, type NotificationSeverity, type NotificationSubscription, type NotificationThreshold, NotificationToast, type NotificationToastDwell, type NotificationToastProps, NotificationToaster, type NotificationToasterPosition, type NotificationToasterProps, OrgProductSwitcher, type OrgProductSwitcherAction, type OrgProductSwitcherItem, type OrgProductSwitcherProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, RequestRow, type RequestRowProps, type RequestState, type RequestSurface, type ResolvedTheme, type Responsive, ScrollArea, ScrollBar, SectionIntro, type SectionIntroProps, SegmentChip, type SegmentChipProps, Select, type SelectOption, type SelectProps, Separator, type Severity, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarBackHeader, type SidebarBackHeaderProps, SidebarNav, SidebarNavLink, type SidebarNavLinkProps, type SidebarNavProps, SidebarProductHeader, type SidebarProductHeaderProps, SignInScreen, type SignInScreenProps, type SignInScreenState, Skeleton, Slider, StatCard, type StatCardProps, StatusDot, type StatusDotProps, Switch, type SwitchProps, TOAST_DWELL, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, type TextareaProps, type Theme, ThemeToggle, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UseSidebarOptions, type UseSidebarResult, UserMenu, type UserMenuItem, type UserMenuProps, type UserMenuUser, alertVariants, badgeVariants, buttonVariants, cn, formatRelativeAge, isKnownExtensionIcon, isNotificationSettled, navigationMenuTriggerStyle, segmentChipVariants, severityBadgeVariant, severityLabels, statusDotVariants, toggleVariants, useCarousel, useFormField, useIsMobile, useSidebar, useTheme };
package/dist/index.js CHANGED
@@ -4285,6 +4285,11 @@ var severityBadgeVariants = {
4285
4285
  function severityBadgeVariant(severity) {
4286
4286
  return severityBadgeVariants[severity];
4287
4287
  }
4288
+ var TOAST_DWELL = {
4289
+ fyi: 6,
4290
+ important: 8,
4291
+ critical: Infinity
4292
+ };
4288
4293
  function formatRelativeAge(createdAt, now = /* @__PURE__ */ new Date()) {
4289
4294
  const then = createdAt instanceof Date ? createdAt : new Date(createdAt);
4290
4295
  const seconds = Math.max(0, Math.floor((now.getTime() - then.getTime()) / 1e3));
@@ -4871,6 +4876,184 @@ var NotificationSettings = React63.forwardRef(
4871
4876
  }
4872
4877
  );
4873
4878
  NotificationSettings.displayName = "NotificationSettings";
4879
+
4880
+ // src/components/notification-toast.tsx
4881
+ import * as React64 from "react";
4882
+ import { X as X3 } from "lucide-react";
4883
+ import { jsx as jsx77, jsxs as jsxs44 } from "react/jsx-runtime";
4884
+ var chipBase2 = "rounded-lg px-2.5 py-1 text-sm font-medium transition-colors";
4885
+ var chipPrimary = "bg-bg-brand text-text-on-brand hover:bg-bg-brand-hover";
4886
+ var chipDestructive = "bg-bg-elevated text-text-danger hover:bg-bg-surface";
4887
+ var linkAction = "text-sm font-semibold text-text-brand transition-colors hover:text-text-primary";
4888
+ var NotificationToast = React64.forwardRef(
4889
+ ({
4890
+ item,
4891
+ showSource = true,
4892
+ note,
4893
+ onItemClick,
4894
+ onAction,
4895
+ onDismiss,
4896
+ dismissLabel = "Dismiss",
4897
+ className
4898
+ }, ref) => {
4899
+ const actions = item.actions ?? [];
4900
+ return /* @__PURE__ */ jsxs44(
4901
+ "div",
4902
+ {
4903
+ ref,
4904
+ role: "status",
4905
+ "aria-live": item.severity === "critical" ? "assertive" : "polite",
4906
+ className: cn(
4907
+ "rounded-2xl border border-border-subtle bg-bg-elevated p-4 shadow-(--menu-shadow)",
4908
+ className
4909
+ ),
4910
+ children: [
4911
+ /* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2", children: [
4912
+ showSource && /* @__PURE__ */ jsx77("span", { className: "text-xs font-semibold uppercase tracking-[0.09em] text-text-secondary", children: item.source }),
4913
+ /* @__PURE__ */ jsx77(Badge, { variant: severityBadgeVariant(item.severity), children: severityLabels[item.severity] }),
4914
+ onDismiss && /* @__PURE__ */ jsx77(
4915
+ "button",
4916
+ {
4917
+ type: "button",
4918
+ "aria-label": dismissLabel,
4919
+ onClick: () => onDismiss(item),
4920
+ className: "-mr-1 ml-auto flex size-5 shrink-0 items-center justify-center rounded text-text-tertiary transition-colors hover:bg-bg-surface hover:text-text-primary",
4921
+ children: /* @__PURE__ */ jsx77(X3, { className: "size-3.5", "aria-hidden": "true" })
4922
+ }
4923
+ )
4924
+ ] }),
4925
+ onItemClick ? /* @__PURE__ */ jsx77(
4926
+ "button",
4927
+ {
4928
+ type: "button",
4929
+ onClick: () => onItemClick(item),
4930
+ className: "mt-1 block text-left text-sm font-semibold leading-snug text-text-primary underline-offset-2 hover:underline",
4931
+ children: item.title
4932
+ }
4933
+ ) : /* @__PURE__ */ jsx77("p", { className: "mt-1 text-sm font-semibold leading-snug text-text-primary", children: item.title }),
4934
+ item.body && /* @__PURE__ */ jsx77("p", { className: "mt-0.5 text-sm leading-snug text-text-secondary", children: item.body }),
4935
+ note && /* @__PURE__ */ jsx77("p", { className: "mt-1.5 text-xs font-medium text-text-warning", children: note }),
4936
+ actions.length > 0 && /* @__PURE__ */ jsx77("div", { className: "mt-2.5 flex flex-wrap items-center gap-2", children: actions.map((action) => {
4937
+ const variant = action.variant ?? "link";
4938
+ return /* @__PURE__ */ jsx77(
4939
+ "button",
4940
+ {
4941
+ type: "button",
4942
+ onClick: () => onAction?.(action, item),
4943
+ className: variant === "primary" ? cn(chipBase2, chipPrimary) : variant === "destructive" ? cn(chipBase2, chipDestructive) : linkAction,
4944
+ children: action.label
4945
+ },
4946
+ action.id
4947
+ );
4948
+ }) })
4949
+ ]
4950
+ }
4951
+ );
4952
+ }
4953
+ );
4954
+ NotificationToast.displayName = "NotificationToast";
4955
+
4956
+ // src/components/notification-toaster.tsx
4957
+ import * as React65 from "react";
4958
+ import { jsx as jsx78 } from "react/jsx-runtime";
4959
+ var positions = {
4960
+ "bottom-right": "bottom-6 right-6 flex-col",
4961
+ "bottom-left": "bottom-6 left-6 flex-col",
4962
+ "top-right": "top-6 right-6 flex-col-reverse",
4963
+ "top-left": "top-6 left-6 flex-col-reverse"
4964
+ };
4965
+ var NotificationToaster = React65.forwardRef(
4966
+ ({
4967
+ items,
4968
+ dwell,
4969
+ max = 4,
4970
+ position = "bottom-right",
4971
+ pauseOnHover = true,
4972
+ onDismiss,
4973
+ onItemClick,
4974
+ onAction,
4975
+ renderNote,
4976
+ className
4977
+ }, ref) => {
4978
+ const shown = items.slice(0, max);
4979
+ const [paused, setPaused] = React65.useState(false);
4980
+ const onDismissRef = React65.useRef(onDismiss);
4981
+ onDismissRef.current = onDismiss;
4982
+ const fyiDwell = dwell?.fyi;
4983
+ const importantDwell = dwell?.important;
4984
+ const criticalDwell = dwell?.critical;
4985
+ const remaining = React65.useRef(/* @__PURE__ */ new Map());
4986
+ const liveIds = shown.map((item) => `${item.id}:${item.severity}`).join(" ");
4987
+ React65.useEffect(() => {
4988
+ const owedById = remaining.current;
4989
+ const dwellSeconds = {
4990
+ fyi: fyiDwell ?? TOAST_DWELL.fyi,
4991
+ important: importantDwell ?? TOAST_DWELL.important,
4992
+ critical: criticalDwell ?? TOAST_DWELL.critical
4993
+ };
4994
+ const live = liveIds === "" ? [] : liveIds.split(" ");
4995
+ const ids = new Set(live.map((entry) => entry.slice(0, entry.lastIndexOf(":"))));
4996
+ for (const id of owedById.keys()) {
4997
+ if (!ids.has(id)) owedById.delete(id);
4998
+ }
4999
+ for (const entry of live) {
5000
+ const at = entry.lastIndexOf(":");
5001
+ const id = entry.slice(0, at);
5002
+ const severity = entry.slice(at + 1);
5003
+ if (!owedById.has(id)) {
5004
+ owedById.set(id, dwellSeconds[severity] * 1e3);
5005
+ }
5006
+ }
5007
+ if (paused) return;
5008
+ const startedAt = Date.now();
5009
+ const timers = [];
5010
+ for (const [id, owed] of owedById) {
5011
+ if (!Number.isFinite(owed)) continue;
5012
+ timers.push(
5013
+ setTimeout(() => {
5014
+ owedById.delete(id);
5015
+ onDismissRef.current?.(id);
5016
+ }, owed)
5017
+ );
5018
+ }
5019
+ return () => {
5020
+ timers.forEach(clearTimeout);
5021
+ const elapsed = Date.now() - startedAt;
5022
+ for (const [id, owed] of owedById) {
5023
+ if (Number.isFinite(owed)) owedById.set(id, Math.max(0, owed - elapsed));
5024
+ }
5025
+ };
5026
+ }, [liveIds, paused, fyiDwell, importantDwell, criticalDwell]);
5027
+ if (shown.length === 0) return null;
5028
+ return /* @__PURE__ */ jsx78(
5029
+ "div",
5030
+ {
5031
+ ref,
5032
+ role: "region",
5033
+ "aria-label": "Notifications",
5034
+ onMouseEnter: pauseOnHover ? () => setPaused(true) : void 0,
5035
+ onMouseLeave: pauseOnHover ? () => setPaused(false) : void 0,
5036
+ className: cn(
5037
+ "pointer-events-none fixed z-50 flex w-[350px] gap-3",
5038
+ positions[position],
5039
+ className
5040
+ ),
5041
+ children: shown.map((item, i) => /* @__PURE__ */ jsx78("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx78(
5042
+ NotificationToast,
5043
+ {
5044
+ item,
5045
+ showSource: i === 0 || shown[i - 1].source !== item.source,
5046
+ note: renderNote?.(item),
5047
+ onItemClick,
5048
+ onAction,
5049
+ onDismiss: onDismiss ? () => onDismiss(item.id) : void 0
5050
+ }
5051
+ ) }, item.id))
5052
+ }
5053
+ );
5054
+ }
5055
+ );
5056
+ NotificationToaster.displayName = "NotificationToaster";
4874
5057
  export {
4875
5058
  Accordion,
4876
5059
  AccordionContent,
@@ -5044,6 +5227,8 @@ export {
5044
5227
  NotificationBell,
5045
5228
  NotificationCenter,
5046
5229
  NotificationSettings,
5230
+ NotificationToast,
5231
+ NotificationToaster,
5047
5232
  OrgProductSwitcher,
5048
5233
  Pagination,
5049
5234
  PaginationContent,
@@ -5086,6 +5271,7 @@ export {
5086
5271
  StatCard,
5087
5272
  StatusDot,
5088
5273
  Switch,
5274
+ TOAST_DWELL,
5089
5275
  Table,
5090
5276
  TableBody,
5091
5277
  TableCaption,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lessly/ui",
3
- "version": "0.14.1",
3
+ "version": "0.15.0",
4
4
  "description": "Lessly design system — shared UI primitives, tokens, and theme",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.30.3",