@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/README.md +605 -28
- package/dist/index.cjs +474 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -1
- package/dist/index.d.ts +66 -1
- package/dist/index.js +467 -9
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
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
|
|
9633
|
+
if (imageSource) {
|
|
9632
9634
|
const img = new Image();
|
|
9633
|
-
|
|
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
|
-
|
|
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
|
-
}, [
|
|
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
|