@janovix/blocks 1.0.0-rc.3 → 1.0.0-rc.5

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,5 +1,5 @@
1
1
  import { useTheme } from 'next-themes';
2
- import { CheckIcon, CircleIcon, ChevronRightIcon, Monitor, Sun, Moon, Languages, Upload, Move, ZoomOut, ZoomIn, RotateCcw, RotateCw, Grid3X3, RefreshCw, X, XIcon, User, Pencil, Check, Loader2 } from 'lucide-react';
2
+ import { CheckIcon, CircleIcon, ChevronRightIcon, Monitor, Sun, Moon, Languages, Upload, Move, ZoomOut, ZoomIn, RotateCcw, RotateCw, Grid3X3, RefreshCw, X, XIcon, User, Pencil, Check, Loader2, Bell, CheckCheck, XCircle, AlertTriangle, CheckCircle, Info, Trash2 } from 'lucide-react';
3
3
  import { AnimatePresence, motion } from 'motion/react';
4
4
  import * as React32 from 'react';
5
5
  import React32__default, { useLayoutEffect, useState, useCallback, useEffect, useRef } from 'react';
@@ -10,6 +10,8 @@ import * as SliderPrimitive from '@radix-ui/react-slider';
10
10
  import * as TogglePrimitive from '@radix-ui/react-toggle';
11
11
  import * as DialogPrimitive from '@radix-ui/react-dialog';
12
12
  import { Drawer as Drawer$1 } from 'vaul';
13
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
14
+ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
13
15
 
14
16
  function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
15
17
  return function handleEvent(event) {
@@ -9628,9 +9630,11 @@ function AvatarEditor({
9628
9630
  const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
9629
9631
  const [showGrid, setShowGrid] = useState(initialShowGrid);
9630
9632
  useEffect(() => {
9631
- if (imageSource && !imageSource.startsWith("data:")) {
9633
+ if (imageSource) {
9632
9634
  const img = new Image();
9633
- img.crossOrigin = "anonymous";
9635
+ if (!imageSource.startsWith("data:")) {
9636
+ img.crossOrigin = "anonymous";
9637
+ }
9634
9638
  img.onload = () => {
9635
9639
  setImage(img);
9636
9640
  setImageLoaded(true);
@@ -9818,6 +9822,7 @@ function AvatarEditor({
9818
9822
  const handleTouchMove = useCallback(
9819
9823
  (e) => {
9820
9824
  if (!isDragging) return;
9825
+ e.preventDefault();
9821
9826
  const touch = e.touches[0];
9822
9827
  setPosition({
9823
9828
  x: touch.clientX - dragStart.x,
@@ -10400,14 +10405,13 @@ function DrawerDescription({
10400
10405
  function useMediaQuery(query) {
10401
10406
  const [matches, setMatches] = useState(false);
10402
10407
  useEffect(() => {
10408
+ if (typeof window === "undefined") return;
10403
10409
  const media = window.matchMedia(query);
10404
- if (media.matches !== matches) {
10405
- setMatches(media.matches);
10406
- }
10410
+ setMatches(media.matches);
10407
10411
  const listener = () => setMatches(media.matches);
10408
10412
  media.addEventListener("change", listener);
10409
10413
  return () => media.removeEventListener("change", listener);
10410
- }, [matches, query]);
10414
+ }, [query]);
10411
10415
  return matches;
10412
10416
  }
10413
10417
  function AvatarEditorDialog({
@@ -10430,7 +10434,15 @@ function AvatarEditorDialog({
10430
10434
  const [editedValue, setEditedValue] = useState(value ?? null);
10431
10435
  const [isSaving, setIsSaving] = useState(false);
10432
10436
  const [feedback, setFeedback] = useState(null);
10437
+ const [mobileEditorSize, setMobileEditorSize] = useState(editorSize);
10433
10438
  const isMobile = useMediaQuery("(max-width: 640px)");
10439
+ useEffect(() => {
10440
+ if (typeof window !== "undefined" && isMobile) {
10441
+ setMobileEditorSize(Math.min(editorSize + 40, window.innerWidth - 48));
10442
+ } else {
10443
+ setMobileEditorSize(editorSize);
10444
+ }
10445
+ }, [isMobile, editorSize]);
10434
10446
  const handleOpenChange = useCallback(
10435
10447
  (open) => {
10436
10448
  if (open) {
@@ -10505,7 +10517,6 @@ function AvatarEditorDialog({
10505
10517
  ]
10506
10518
  }
10507
10519
  );
10508
- const mobileEditorSize = isMobile ? Math.min(editorSize + 40, window.innerWidth - 48) : editorSize;
10509
10520
  const EditorContent = /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4", children: [
10510
10521
  /* @__PURE__ */ jsx(
10511
10522
  AvatarEditor,
@@ -10590,7 +10601,454 @@ function AvatarEditorDialog({
10590
10601
  ] }) })
10591
10602
  ] });
10592
10603
  }
10604
+ function Popover({
10605
+ ...props
10606
+ }) {
10607
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
10608
+ }
10609
+ function PopoverTrigger({
10610
+ ...props
10611
+ }) {
10612
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
10613
+ }
10614
+ function PopoverContent({
10615
+ className,
10616
+ align = "center",
10617
+ sideOffset = 4,
10618
+ ...props
10619
+ }) {
10620
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
10621
+ PopoverPrimitive.Content,
10622
+ {
10623
+ "data-slot": "popover-content",
10624
+ align,
10625
+ sideOffset,
10626
+ className: cn(
10627
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
10628
+ className
10629
+ ),
10630
+ ...props
10631
+ }
10632
+ ) });
10633
+ }
10634
+ function PopoverAnchor({
10635
+ ...props
10636
+ }) {
10637
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Anchor, { "data-slot": "popover-anchor", ...props });
10638
+ }
10639
+ function ScrollArea({
10640
+ className,
10641
+ children,
10642
+ ...props
10643
+ }) {
10644
+ return /* @__PURE__ */ jsxs(
10645
+ ScrollAreaPrimitive.Root,
10646
+ {
10647
+ "data-slot": "scroll-area",
10648
+ className: cn("relative overflow-hidden", className),
10649
+ ...props,
10650
+ children: [
10651
+ /* @__PURE__ */ jsx(
10652
+ ScrollAreaPrimitive.Viewport,
10653
+ {
10654
+ "data-slot": "scroll-area-viewport",
10655
+ className: "h-full w-full rounded-[inherit]",
10656
+ children
10657
+ }
10658
+ ),
10659
+ /* @__PURE__ */ jsx(ScrollBar, {}),
10660
+ /* @__PURE__ */ jsx(ScrollAreaPrimitive.Corner, {})
10661
+ ]
10662
+ }
10663
+ );
10664
+ }
10665
+ function ScrollBar({
10666
+ className,
10667
+ orientation = "vertical",
10668
+ ...props
10669
+ }) {
10670
+ return /* @__PURE__ */ jsx(
10671
+ ScrollAreaPrimitive.ScrollAreaScrollbar,
10672
+ {
10673
+ "data-slot": "scroll-bar",
10674
+ orientation,
10675
+ className: cn(
10676
+ "flex touch-none select-none transition-colors",
10677
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
10678
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]",
10679
+ className
10680
+ ),
10681
+ ...props,
10682
+ children: /* @__PURE__ */ jsx(
10683
+ ScrollAreaPrimitive.ScrollAreaThumb,
10684
+ {
10685
+ "data-slot": "scroll-thumb",
10686
+ className: "relative flex-1 rounded-full bg-border"
10687
+ }
10688
+ )
10689
+ }
10690
+ );
10691
+ }
10692
+ var sizeConfig = {
10693
+ sm: {
10694
+ button: "h-8 w-8",
10695
+ icon: "w-4 h-4",
10696
+ badge: "min-w-[16px] h-4 text-[10px] -top-1 -right-1",
10697
+ dot: "w-2.5 h-2.5 -top-0.5 -right-0.5"
10698
+ },
10699
+ md: {
10700
+ button: "h-9 w-9",
10701
+ icon: "w-5 h-5",
10702
+ badge: "min-w-[18px] h-[18px] text-[11px] -top-1 -right-1",
10703
+ dot: "w-3 h-3 -top-0.5 -right-0.5"
10704
+ },
10705
+ lg: {
10706
+ button: "h-10 w-10",
10707
+ icon: "w-6 h-6",
10708
+ badge: "min-w-[20px] h-5 text-xs -top-1.5 -right-1.5",
10709
+ dot: "w-3.5 h-3.5 -top-0.5 -right-0.5"
10710
+ }
10711
+ };
10712
+ var typeConfig = {
10713
+ info: {
10714
+ icon: Info,
10715
+ color: "text-blue-500",
10716
+ bg: "bg-blue-500/10"
10717
+ },
10718
+ success: {
10719
+ icon: CheckCircle,
10720
+ color: "text-green-500",
10721
+ bg: "bg-green-500/10"
10722
+ },
10723
+ warning: {
10724
+ icon: AlertTriangle,
10725
+ color: "text-amber-500",
10726
+ bg: "bg-amber-500/10"
10727
+ },
10728
+ error: {
10729
+ icon: XCircle,
10730
+ color: "text-red-500",
10731
+ bg: "bg-red-500/10"
10732
+ }
10733
+ };
10734
+ var dotColorConfig = {
10735
+ red: "bg-red-500",
10736
+ blue: "bg-blue-500",
10737
+ green: "bg-green-500",
10738
+ amber: "bg-amber-500",
10739
+ purple: "bg-purple-500",
10740
+ primary: "bg-primary"
10741
+ };
10742
+ var soundConfig = {
10743
+ chime: {
10744
+ frequencies: [880, 1100],
10745
+ durations: [0.1, 0.2],
10746
+ gain: 0.3
10747
+ },
10748
+ bell: {
10749
+ frequencies: [523, 659, 784],
10750
+ durations: [0.15, 0.15, 0.2],
10751
+ gain: 0.25
10752
+ },
10753
+ pop: {
10754
+ frequencies: [400, 600],
10755
+ durations: [0.05, 0.08],
10756
+ gain: 0.4
10757
+ },
10758
+ ding: {
10759
+ frequencies: [1200],
10760
+ durations: [0.15],
10761
+ gain: 0.2
10762
+ }
10763
+ };
10764
+ var pulseVariants = {
10765
+ ring: {
10766
+ animate: { scale: [1, 1.8], opacity: [0.6, 0] },
10767
+ transition: {
10768
+ duration: 1.2,
10769
+ repeat: Number.POSITIVE_INFINITY,
10770
+ ease: "easeOut"
10771
+ }
10772
+ },
10773
+ glow: {
10774
+ animate: { scale: [1, 1.3, 1], opacity: [0.8, 0.4, 0.8] },
10775
+ transition: {
10776
+ duration: 1.5,
10777
+ repeat: Number.POSITIVE_INFINITY,
10778
+ ease: "easeInOut"
10779
+ }
10780
+ },
10781
+ bounce: {
10782
+ animate: { scale: [1, 1.2, 1], y: [0, -2, 0] },
10783
+ transition: {
10784
+ duration: 0.6,
10785
+ repeat: Number.POSITIVE_INFINITY,
10786
+ ease: "easeInOut"
10787
+ }
10788
+ }
10789
+ };
10790
+ function formatTimeAgo(date) {
10791
+ const now = /* @__PURE__ */ new Date();
10792
+ const diffMs = now.getTime() - date.getTime();
10793
+ const diffSecs = Math.floor(diffMs / 1e3);
10794
+ const diffMins = Math.floor(diffSecs / 60);
10795
+ const diffHours = Math.floor(diffMins / 60);
10796
+ const diffDays = Math.floor(diffHours / 24);
10797
+ if (diffSecs < 60) return "just now";
10798
+ if (diffMins < 60) return `${diffMins}m ago`;
10799
+ if (diffHours < 24) return `${diffHours}h ago`;
10800
+ if (diffDays < 7) return `${diffDays}d ago`;
10801
+ return date.toLocaleDateString();
10802
+ }
10803
+ function playNotificationSound(soundType = "chime", soundUrl) {
10804
+ if (typeof window === "undefined" || soundType === "none") return;
10805
+ if (soundUrl) {
10806
+ const audio = new Audio(soundUrl);
10807
+ audio.volume = 0.5;
10808
+ audio.play().catch(() => {
10809
+ });
10810
+ return;
10811
+ }
10812
+ const config = soundConfig[soundType];
10813
+ if (!config) return;
10814
+ try {
10815
+ const audioContext = new (window.AudioContext || window.webkitAudioContext)();
10816
+ let currentTime = audioContext.currentTime;
10817
+ config.frequencies.forEach((freq, i) => {
10818
+ const oscillator = audioContext.createOscillator();
10819
+ const gainNode = audioContext.createGain();
10820
+ oscillator.connect(gainNode);
10821
+ gainNode.connect(audioContext.destination);
10822
+ oscillator.frequency.setValueAtTime(freq, currentTime);
10823
+ gainNode.gain.setValueAtTime(config.gain, currentTime);
10824
+ gainNode.gain.exponentialRampToValueAtTime(
10825
+ 0.01,
10826
+ currentTime + config.durations[i]
10827
+ );
10828
+ oscillator.start(currentTime);
10829
+ oscillator.stop(currentTime + config.durations[i]);
10830
+ currentTime += config.durations[i] * 0.7;
10831
+ });
10832
+ } catch {
10833
+ }
10834
+ }
10835
+ function NotificationsWidget({
10836
+ notifications,
10837
+ onMarkAsRead,
10838
+ onMarkAllAsRead,
10839
+ onDismiss,
10840
+ onClearAll,
10841
+ onNotificationClick,
10842
+ size: size4 = "md",
10843
+ maxVisible = 5,
10844
+ playSound = true,
10845
+ soundUrl,
10846
+ className,
10847
+ emptyMessage = "No notifications",
10848
+ title = "Notifications",
10849
+ dotColor = "red",
10850
+ showPulse = true,
10851
+ soundType = "chime",
10852
+ pulseStyle = "ring",
10853
+ soundCooldown = 2e3
10854
+ }) {
10855
+ const [isOpen, setIsOpen] = React32.useState(false);
10856
+ const [prevCount, setPrevCount] = React32.useState(0);
10857
+ const lastSoundPlayedRef = React32.useRef(0);
10858
+ const styles = sizeConfig[size4];
10859
+ const dotBgColor = dotColorConfig[dotColor];
10860
+ const unreadCount = notifications.filter((n) => !n.read).length;
10861
+ const visibleNotifications = React32.useMemo(
10862
+ () => notifications.slice(0, maxVisible),
10863
+ [notifications, maxVisible]
10864
+ );
10865
+ const hasMore = notifications.length > maxVisible;
10866
+ React32.useEffect(() => {
10867
+ if (playSound && soundType !== "none" && unreadCount > prevCount && prevCount > 0) {
10868
+ const now = Date.now();
10869
+ if (now - lastSoundPlayedRef.current >= soundCooldown) {
10870
+ playNotificationSound(soundType, soundUrl);
10871
+ lastSoundPlayedRef.current = now;
10872
+ }
10873
+ }
10874
+ setPrevCount(unreadCount);
10875
+ }, [unreadCount, prevCount, soundType, soundUrl, soundCooldown, playSound]);
10876
+ React32.useEffect(() => {
10877
+ if (isOpen && onMarkAsRead) {
10878
+ visibleNotifications.forEach((notification) => {
10879
+ if (!notification.read) {
10880
+ onMarkAsRead(notification.id);
10881
+ }
10882
+ });
10883
+ }
10884
+ }, [isOpen, onMarkAsRead, visibleNotifications]);
10885
+ const handleNotificationClick = (notification) => {
10886
+ if (notification.href) {
10887
+ onNotificationClick?.(notification);
10888
+ }
10889
+ };
10890
+ return /* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
10891
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
10892
+ motion.button,
10893
+ {
10894
+ className: cn(
10895
+ "relative inline-flex items-center justify-center rounded-lg",
10896
+ "bg-muted/50 border border-border/50 hover:bg-muted/70 transition-colors",
10897
+ styles.button,
10898
+ className
10899
+ ),
10900
+ whileTap: { scale: 0.95 },
10901
+ "aria-label": `Notifications${unreadCount > 0 ? ` (${unreadCount} unread)` : ""}`,
10902
+ children: [
10903
+ /* @__PURE__ */ jsx(Bell, { className: cn(styles.icon, "text-muted-foreground") }),
10904
+ /* @__PURE__ */ jsx(AnimatePresence, { children: unreadCount > 0 && /* @__PURE__ */ jsx(
10905
+ motion.div,
10906
+ {
10907
+ initial: { scale: 0, opacity: 0 },
10908
+ animate: { scale: 1, opacity: 1 },
10909
+ exit: { scale: 0, opacity: 0 },
10910
+ className: cn(
10911
+ "absolute flex items-center justify-center rounded-full",
10912
+ dotBgColor,
10913
+ "text-white font-medium",
10914
+ unreadCount > 9 ? styles.badge : styles.dot,
10915
+ unreadCount > 9 && "px-1"
10916
+ ),
10917
+ children: unreadCount > 9 ? /* @__PURE__ */ jsx("span", { children: unreadCount > 99 ? "99+" : unreadCount }) : null
10918
+ }
10919
+ ) }),
10920
+ /* @__PURE__ */ jsx(AnimatePresence, { children: unreadCount > 0 && showPulse && pulseStyle !== "none" && /* @__PURE__ */ jsx(
10921
+ motion.div,
10922
+ {
10923
+ initial: { scale: 1, opacity: 0.5 },
10924
+ animate: pulseVariants[pulseStyle].animate,
10925
+ transition: pulseVariants[pulseStyle].transition,
10926
+ className: cn("absolute rounded-full", dotBgColor, styles.dot)
10927
+ }
10928
+ ) })
10929
+ ]
10930
+ }
10931
+ ) }),
10932
+ /* @__PURE__ */ jsxs(
10933
+ PopoverContent,
10934
+ {
10935
+ side: "bottom",
10936
+ align: "end",
10937
+ className: "w-80 p-0 overflow-hidden",
10938
+ children: [
10939
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-border", children: [
10940
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10941
+ /* @__PURE__ */ jsx("h4", { className: "font-semibold text-sm", children: title }),
10942
+ unreadCount > 0 && /* @__PURE__ */ jsxs("span", { className: "px-2 py-0.5 text-xs font-medium rounded-full bg-primary/10 text-primary", children: [
10943
+ unreadCount,
10944
+ " new"
10945
+ ] })
10946
+ ] }),
10947
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: unreadCount > 0 && onMarkAllAsRead && /* @__PURE__ */ jsxs(
10948
+ Button,
10949
+ {
10950
+ variant: "ghost",
10951
+ size: "sm",
10952
+ className: "h-7 px-2 text-xs",
10953
+ onClick: () => onMarkAllAsRead(),
10954
+ children: [
10955
+ /* @__PURE__ */ jsx(CheckCheck, { className: "w-3.5 h-3.5 mr-1" }),
10956
+ "Mark all read"
10957
+ ]
10958
+ }
10959
+ ) })
10960
+ ] }),
10961
+ notifications.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-8 px-4 text-center", children: [
10962
+ /* @__PURE__ */ jsx("div", { className: "w-12 h-12 rounded-full bg-muted flex items-center justify-center mb-3", children: /* @__PURE__ */ jsx(Bell, { className: "w-6 h-6 text-muted-foreground" }) }),
10963
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: emptyMessage })
10964
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
10965
+ /* @__PURE__ */ jsx(ScrollArea, { className: "h-[320px]", children: /* @__PURE__ */ jsx("div", { className: "divide-y divide-border", children: visibleNotifications.map((notification) => {
10966
+ const config = typeConfig[notification.type || "info"];
10967
+ const Icon = config.icon;
10968
+ const hasLink = !!notification.href;
10969
+ return /* @__PURE__ */ jsxs(
10970
+ motion.div,
10971
+ {
10972
+ initial: { opacity: 0, y: -10 },
10973
+ animate: { opacity: 1, y: 0 },
10974
+ className: cn(
10975
+ "relative flex gap-3 px-4 py-3 transition-colors group",
10976
+ hasLink && "cursor-pointer hover:bg-muted/50",
10977
+ !hasLink && "cursor-default",
10978
+ !notification.read && "bg-primary/5"
10979
+ ),
10980
+ onClick: () => handleNotificationClick(notification),
10981
+ children: [
10982
+ /* @__PURE__ */ jsx(
10983
+ "div",
10984
+ {
10985
+ className: cn(
10986
+ "flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center",
10987
+ config.bg
10988
+ ),
10989
+ children: /* @__PURE__ */ jsx(Icon, { className: cn("w-4 h-4", config.color) })
10990
+ }
10991
+ ),
10992
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
10993
+ /* @__PURE__ */ jsx("div", { className: "flex items-start justify-between gap-2", children: /* @__PURE__ */ jsx(
10994
+ "p",
10995
+ {
10996
+ className: cn(
10997
+ "text-sm line-clamp-1",
10998
+ !notification.read ? "font-semibold" : "font-medium",
10999
+ hasLink && "group-hover:underline"
11000
+ ),
11001
+ children: notification.title
11002
+ }
11003
+ ) }),
11004
+ notification.message && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground line-clamp-2 mt-0.5", children: notification.message }),
11005
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground/70 mt-1", children: formatTimeAgo(notification.timestamp) })
11006
+ ] }),
11007
+ /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 flex items-start gap-1 opacity-0 group-hover:opacity-100 transition-opacity", children: onDismiss && /* @__PURE__ */ jsx(
11008
+ Button,
11009
+ {
11010
+ variant: "ghost",
11011
+ size: "icon",
11012
+ className: "h-6 w-6 text-muted-foreground hover:text-destructive",
11013
+ onClick: (e) => {
11014
+ e.stopPropagation();
11015
+ onDismiss(notification.id);
11016
+ },
11017
+ children: /* @__PURE__ */ jsx(X, { className: "w-3 h-3" })
11018
+ }
11019
+ ) })
11020
+ ]
11021
+ },
11022
+ notification.id
11023
+ );
11024
+ }) }) }),
11025
+ (hasMore || onClearAll) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2 border-t border-border bg-muted/30", children: [
11026
+ hasMore && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
11027
+ "+",
11028
+ notifications.length - maxVisible,
11029
+ " more"
11030
+ ] }),
11031
+ onClearAll && notifications.length > 0 && /* @__PURE__ */ jsxs(
11032
+ Button,
11033
+ {
11034
+ variant: "ghost",
11035
+ size: "sm",
11036
+ className: "h-7 px-2 text-xs text-muted-foreground hover:text-destructive",
11037
+ onClick: () => onClearAll(),
11038
+ children: [
11039
+ /* @__PURE__ */ jsx(Trash2, { className: "w-3 h-3 mr-1" }),
11040
+ "Clear all"
11041
+ ]
11042
+ }
11043
+ )
11044
+ ] })
11045
+ ] })
11046
+ ]
11047
+ }
11048
+ )
11049
+ ] });
11050
+ }
10593
11051
 
10594
- export { AvatarEditor, AvatarEditorDialog, Button, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu2 as DropdownMenu, DropdownMenuCheckboxItem2 as DropdownMenuCheckboxItem, DropdownMenuContent2 as DropdownMenuContent, DropdownMenuGroup2 as DropdownMenuGroup, DropdownMenuItem2 as DropdownMenuItem, DropdownMenuLabel2 as DropdownMenuLabel, DropdownMenuPortal2 as DropdownMenuPortal, DropdownMenuRadioGroup2 as DropdownMenuRadioGroup, DropdownMenuRadioItem2 as DropdownMenuRadioItem, DropdownMenuSeparator2 as DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub2 as DropdownMenuSub, DropdownMenuSubContent2 as DropdownMenuSubContent, DropdownMenuSubTrigger2 as DropdownMenuSubTrigger, DropdownMenuTrigger2 as DropdownMenuTrigger, LanguageSwitcher, Slider, ThemeSwitcher, Toggle, Tooltip2 as Tooltip, TooltipContent2 as TooltipContent, TooltipProvider2 as TooltipProvider, TooltipTrigger2 as TooltipTrigger, buttonVariants, cn, toggleVariants };
11052
+ export { AvatarEditor, AvatarEditorDialog, Button, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu2 as DropdownMenu, DropdownMenuCheckboxItem2 as DropdownMenuCheckboxItem, DropdownMenuContent2 as DropdownMenuContent, DropdownMenuGroup2 as DropdownMenuGroup, DropdownMenuItem2 as DropdownMenuItem, DropdownMenuLabel2 as DropdownMenuLabel, DropdownMenuPortal2 as DropdownMenuPortal, DropdownMenuRadioGroup2 as DropdownMenuRadioGroup, DropdownMenuRadioItem2 as DropdownMenuRadioItem, DropdownMenuSeparator2 as DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub2 as DropdownMenuSub, DropdownMenuSubContent2 as DropdownMenuSubContent, DropdownMenuSubTrigger2 as DropdownMenuSubTrigger, DropdownMenuTrigger2 as DropdownMenuTrigger, LanguageSwitcher, NotificationsWidget, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ScrollArea, ScrollBar, Slider, ThemeSwitcher, Toggle, Tooltip2 as Tooltip, TooltipContent2 as TooltipContent, TooltipProvider2 as TooltipProvider, TooltipTrigger2 as TooltipTrigger, buttonVariants, cn, toggleVariants };
10595
11053
  //# sourceMappingURL=index.js.map
10596
11054
  //# sourceMappingURL=index.js.map