@janovix/blocks 1.0.0-rc.3 → 1.0.0-rc.4
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.cjs +455 -0
- 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 +448 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -10,6 +10,8 @@ var SliderPrimitive = require('@radix-ui/react-slider');
|
|
|
10
10
|
var TogglePrimitive = require('@radix-ui/react-toggle');
|
|
11
11
|
var DialogPrimitive = require('@radix-ui/react-dialog');
|
|
12
12
|
var vaul = require('vaul');
|
|
13
|
+
var PopoverPrimitive = require('@radix-ui/react-popover');
|
|
14
|
+
var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
|
|
13
15
|
|
|
14
16
|
function _interopNamespace(e) {
|
|
15
17
|
if (e && e.__esModule) return e;
|
|
@@ -34,6 +36,8 @@ var ReactDOM__namespace = /*#__PURE__*/_interopNamespace(ReactDOM);
|
|
|
34
36
|
var SliderPrimitive__namespace = /*#__PURE__*/_interopNamespace(SliderPrimitive);
|
|
35
37
|
var TogglePrimitive__namespace = /*#__PURE__*/_interopNamespace(TogglePrimitive);
|
|
36
38
|
var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
|
|
39
|
+
var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
|
|
40
|
+
var ScrollAreaPrimitive__namespace = /*#__PURE__*/_interopNamespace(ScrollAreaPrimitive);
|
|
37
41
|
|
|
38
42
|
function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
|
|
39
43
|
return function handleEvent(event) {
|
|
@@ -10614,6 +10618,450 @@ function AvatarEditorDialog({
|
|
|
10614
10618
|
] }) })
|
|
10615
10619
|
] });
|
|
10616
10620
|
}
|
|
10621
|
+
function Popover({
|
|
10622
|
+
...props
|
|
10623
|
+
}) {
|
|
10624
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Root, { "data-slot": "popover", ...props });
|
|
10625
|
+
}
|
|
10626
|
+
function PopoverTrigger({
|
|
10627
|
+
...props
|
|
10628
|
+
}) {
|
|
10629
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Trigger, { "data-slot": "popover-trigger", ...props });
|
|
10630
|
+
}
|
|
10631
|
+
function PopoverContent({
|
|
10632
|
+
className,
|
|
10633
|
+
align = "center",
|
|
10634
|
+
sideOffset = 4,
|
|
10635
|
+
...props
|
|
10636
|
+
}) {
|
|
10637
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10638
|
+
PopoverPrimitive__namespace.Content,
|
|
10639
|
+
{
|
|
10640
|
+
"data-slot": "popover-content",
|
|
10641
|
+
align,
|
|
10642
|
+
sideOffset,
|
|
10643
|
+
className: cn(
|
|
10644
|
+
"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",
|
|
10645
|
+
className
|
|
10646
|
+
),
|
|
10647
|
+
...props
|
|
10648
|
+
}
|
|
10649
|
+
) });
|
|
10650
|
+
}
|
|
10651
|
+
function PopoverAnchor({
|
|
10652
|
+
...props
|
|
10653
|
+
}) {
|
|
10654
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Anchor, { "data-slot": "popover-anchor", ...props });
|
|
10655
|
+
}
|
|
10656
|
+
function ScrollArea({
|
|
10657
|
+
className,
|
|
10658
|
+
children,
|
|
10659
|
+
...props
|
|
10660
|
+
}) {
|
|
10661
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10662
|
+
ScrollAreaPrimitive__namespace.Root,
|
|
10663
|
+
{
|
|
10664
|
+
"data-slot": "scroll-area",
|
|
10665
|
+
className: cn("relative overflow-hidden", className),
|
|
10666
|
+
...props,
|
|
10667
|
+
children: [
|
|
10668
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10669
|
+
ScrollAreaPrimitive__namespace.Viewport,
|
|
10670
|
+
{
|
|
10671
|
+
"data-slot": "scroll-area-viewport",
|
|
10672
|
+
className: "h-full w-full rounded-[inherit]",
|
|
10673
|
+
children
|
|
10674
|
+
}
|
|
10675
|
+
),
|
|
10676
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollBar, {}),
|
|
10677
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollAreaPrimitive__namespace.Corner, {})
|
|
10678
|
+
]
|
|
10679
|
+
}
|
|
10680
|
+
);
|
|
10681
|
+
}
|
|
10682
|
+
function ScrollBar({
|
|
10683
|
+
className,
|
|
10684
|
+
orientation = "vertical",
|
|
10685
|
+
...props
|
|
10686
|
+
}) {
|
|
10687
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10688
|
+
ScrollAreaPrimitive__namespace.ScrollAreaScrollbar,
|
|
10689
|
+
{
|
|
10690
|
+
"data-slot": "scroll-bar",
|
|
10691
|
+
orientation,
|
|
10692
|
+
className: cn(
|
|
10693
|
+
"flex touch-none select-none transition-colors",
|
|
10694
|
+
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
|
|
10695
|
+
orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
|
10696
|
+
className
|
|
10697
|
+
),
|
|
10698
|
+
...props,
|
|
10699
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10700
|
+
ScrollAreaPrimitive__namespace.ScrollAreaThumb,
|
|
10701
|
+
{
|
|
10702
|
+
"data-slot": "scroll-thumb",
|
|
10703
|
+
className: "relative flex-1 rounded-full bg-border"
|
|
10704
|
+
}
|
|
10705
|
+
)
|
|
10706
|
+
}
|
|
10707
|
+
);
|
|
10708
|
+
}
|
|
10709
|
+
var sizeConfig = {
|
|
10710
|
+
sm: {
|
|
10711
|
+
button: "h-8 w-8",
|
|
10712
|
+
icon: "w-4 h-4",
|
|
10713
|
+
badge: "min-w-[16px] h-4 text-[10px] -top-1 -right-1",
|
|
10714
|
+
dot: "w-2.5 h-2.5 -top-0.5 -right-0.5"
|
|
10715
|
+
},
|
|
10716
|
+
md: {
|
|
10717
|
+
button: "h-9 w-9",
|
|
10718
|
+
icon: "w-5 h-5",
|
|
10719
|
+
badge: "min-w-[18px] h-[18px] text-[11px] -top-1 -right-1",
|
|
10720
|
+
dot: "w-3 h-3 -top-0.5 -right-0.5"
|
|
10721
|
+
},
|
|
10722
|
+
lg: {
|
|
10723
|
+
button: "h-10 w-10",
|
|
10724
|
+
icon: "w-6 h-6",
|
|
10725
|
+
badge: "min-w-[20px] h-5 text-xs -top-1.5 -right-1.5",
|
|
10726
|
+
dot: "w-3.5 h-3.5 -top-0.5 -right-0.5"
|
|
10727
|
+
}
|
|
10728
|
+
};
|
|
10729
|
+
var typeConfig = {
|
|
10730
|
+
info: {
|
|
10731
|
+
icon: lucideReact.Info,
|
|
10732
|
+
color: "text-blue-500",
|
|
10733
|
+
bg: "bg-blue-500/10"
|
|
10734
|
+
},
|
|
10735
|
+
success: {
|
|
10736
|
+
icon: lucideReact.CheckCircle,
|
|
10737
|
+
color: "text-green-500",
|
|
10738
|
+
bg: "bg-green-500/10"
|
|
10739
|
+
},
|
|
10740
|
+
warning: {
|
|
10741
|
+
icon: lucideReact.AlertTriangle,
|
|
10742
|
+
color: "text-amber-500",
|
|
10743
|
+
bg: "bg-amber-500/10"
|
|
10744
|
+
},
|
|
10745
|
+
error: {
|
|
10746
|
+
icon: lucideReact.XCircle,
|
|
10747
|
+
color: "text-red-500",
|
|
10748
|
+
bg: "bg-red-500/10"
|
|
10749
|
+
}
|
|
10750
|
+
};
|
|
10751
|
+
var dotColorConfig = {
|
|
10752
|
+
red: "bg-red-500",
|
|
10753
|
+
blue: "bg-blue-500",
|
|
10754
|
+
green: "bg-green-500",
|
|
10755
|
+
amber: "bg-amber-500",
|
|
10756
|
+
purple: "bg-purple-500",
|
|
10757
|
+
primary: "bg-primary"
|
|
10758
|
+
};
|
|
10759
|
+
var soundConfig = {
|
|
10760
|
+
chime: {
|
|
10761
|
+
frequencies: [880, 1100],
|
|
10762
|
+
durations: [0.1, 0.2],
|
|
10763
|
+
gain: 0.3
|
|
10764
|
+
},
|
|
10765
|
+
bell: {
|
|
10766
|
+
frequencies: [523, 659, 784],
|
|
10767
|
+
durations: [0.15, 0.15, 0.2],
|
|
10768
|
+
gain: 0.25
|
|
10769
|
+
},
|
|
10770
|
+
pop: {
|
|
10771
|
+
frequencies: [400, 600],
|
|
10772
|
+
durations: [0.05, 0.08],
|
|
10773
|
+
gain: 0.4
|
|
10774
|
+
},
|
|
10775
|
+
ding: {
|
|
10776
|
+
frequencies: [1200],
|
|
10777
|
+
durations: [0.15],
|
|
10778
|
+
gain: 0.2
|
|
10779
|
+
}
|
|
10780
|
+
};
|
|
10781
|
+
var pulseVariants = {
|
|
10782
|
+
ring: {
|
|
10783
|
+
animate: { scale: [1, 1.8], opacity: [0.6, 0] },
|
|
10784
|
+
transition: {
|
|
10785
|
+
duration: 1.2,
|
|
10786
|
+
repeat: Number.POSITIVE_INFINITY,
|
|
10787
|
+
ease: "easeOut"
|
|
10788
|
+
}
|
|
10789
|
+
},
|
|
10790
|
+
glow: {
|
|
10791
|
+
animate: { scale: [1, 1.3, 1], opacity: [0.8, 0.4, 0.8] },
|
|
10792
|
+
transition: {
|
|
10793
|
+
duration: 1.5,
|
|
10794
|
+
repeat: Number.POSITIVE_INFINITY,
|
|
10795
|
+
ease: "easeInOut"
|
|
10796
|
+
}
|
|
10797
|
+
},
|
|
10798
|
+
bounce: {
|
|
10799
|
+
animate: { scale: [1, 1.2, 1], y: [0, -2, 0] },
|
|
10800
|
+
transition: {
|
|
10801
|
+
duration: 0.6,
|
|
10802
|
+
repeat: Number.POSITIVE_INFINITY,
|
|
10803
|
+
ease: "easeInOut"
|
|
10804
|
+
}
|
|
10805
|
+
}
|
|
10806
|
+
};
|
|
10807
|
+
function formatTimeAgo(date) {
|
|
10808
|
+
const now = /* @__PURE__ */ new Date();
|
|
10809
|
+
const diffMs = now.getTime() - date.getTime();
|
|
10810
|
+
const diffSecs = Math.floor(diffMs / 1e3);
|
|
10811
|
+
const diffMins = Math.floor(diffSecs / 60);
|
|
10812
|
+
const diffHours = Math.floor(diffMins / 60);
|
|
10813
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
10814
|
+
if (diffSecs < 60) return "just now";
|
|
10815
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
10816
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
10817
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
10818
|
+
return date.toLocaleDateString();
|
|
10819
|
+
}
|
|
10820
|
+
function playNotificationSound(soundType = "chime", soundUrl) {
|
|
10821
|
+
if (typeof window === "undefined" || soundType === "none") return;
|
|
10822
|
+
if (soundUrl) {
|
|
10823
|
+
const audio = new Audio(soundUrl);
|
|
10824
|
+
audio.volume = 0.5;
|
|
10825
|
+
audio.play().catch(() => {
|
|
10826
|
+
});
|
|
10827
|
+
return;
|
|
10828
|
+
}
|
|
10829
|
+
const config = soundConfig[soundType];
|
|
10830
|
+
if (!config) return;
|
|
10831
|
+
try {
|
|
10832
|
+
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
10833
|
+
let currentTime = audioContext.currentTime;
|
|
10834
|
+
config.frequencies.forEach((freq, i) => {
|
|
10835
|
+
const oscillator = audioContext.createOscillator();
|
|
10836
|
+
const gainNode = audioContext.createGain();
|
|
10837
|
+
oscillator.connect(gainNode);
|
|
10838
|
+
gainNode.connect(audioContext.destination);
|
|
10839
|
+
oscillator.frequency.setValueAtTime(freq, currentTime);
|
|
10840
|
+
gainNode.gain.setValueAtTime(config.gain, currentTime);
|
|
10841
|
+
gainNode.gain.exponentialRampToValueAtTime(
|
|
10842
|
+
0.01,
|
|
10843
|
+
currentTime + config.durations[i]
|
|
10844
|
+
);
|
|
10845
|
+
oscillator.start(currentTime);
|
|
10846
|
+
oscillator.stop(currentTime + config.durations[i]);
|
|
10847
|
+
currentTime += config.durations[i] * 0.7;
|
|
10848
|
+
});
|
|
10849
|
+
} catch {
|
|
10850
|
+
}
|
|
10851
|
+
}
|
|
10852
|
+
function NotificationsWidget({
|
|
10853
|
+
notifications,
|
|
10854
|
+
onMarkAsRead,
|
|
10855
|
+
onMarkAllAsRead,
|
|
10856
|
+
onDismiss,
|
|
10857
|
+
onClearAll,
|
|
10858
|
+
onNotificationClick,
|
|
10859
|
+
size: size4 = "md",
|
|
10860
|
+
maxVisible = 5,
|
|
10861
|
+
playSound: _playSound = true,
|
|
10862
|
+
soundUrl,
|
|
10863
|
+
className,
|
|
10864
|
+
emptyMessage = "No notifications",
|
|
10865
|
+
title = "Notifications",
|
|
10866
|
+
dotColor = "red",
|
|
10867
|
+
showPulse = true,
|
|
10868
|
+
soundType = "chime",
|
|
10869
|
+
pulseStyle = "ring",
|
|
10870
|
+
soundCooldown = 2e3
|
|
10871
|
+
}) {
|
|
10872
|
+
const [isOpen, setIsOpen] = React32__namespace.useState(false);
|
|
10873
|
+
const [prevCount, setPrevCount] = React32__namespace.useState(0);
|
|
10874
|
+
const lastSoundPlayedRef = React32__namespace.useRef(0);
|
|
10875
|
+
const styles = sizeConfig[size4];
|
|
10876
|
+
const dotBgColor = dotColorConfig[dotColor];
|
|
10877
|
+
const unreadCount = notifications.filter((n) => !n.read).length;
|
|
10878
|
+
const visibleNotifications = notifications.slice(0, maxVisible);
|
|
10879
|
+
const hasMore = notifications.length > maxVisible;
|
|
10880
|
+
React32__namespace.useEffect(() => {
|
|
10881
|
+
if (soundType !== "none" && unreadCount > prevCount && prevCount > 0) {
|
|
10882
|
+
const now = Date.now();
|
|
10883
|
+
if (now - lastSoundPlayedRef.current >= soundCooldown) {
|
|
10884
|
+
playNotificationSound(soundType, soundUrl);
|
|
10885
|
+
lastSoundPlayedRef.current = now;
|
|
10886
|
+
}
|
|
10887
|
+
}
|
|
10888
|
+
setPrevCount(unreadCount);
|
|
10889
|
+
}, [unreadCount, prevCount, soundType, soundUrl, soundCooldown]);
|
|
10890
|
+
React32__namespace.useEffect(() => {
|
|
10891
|
+
if (isOpen && onMarkAsRead) {
|
|
10892
|
+
visibleNotifications.forEach((notification) => {
|
|
10893
|
+
if (!notification.read) {
|
|
10894
|
+
onMarkAsRead(notification.id);
|
|
10895
|
+
}
|
|
10896
|
+
});
|
|
10897
|
+
}
|
|
10898
|
+
}, [isOpen, onMarkAsRead, visibleNotifications]);
|
|
10899
|
+
const handleNotificationClick = (notification) => {
|
|
10900
|
+
if (notification.href) {
|
|
10901
|
+
onNotificationClick?.(notification);
|
|
10902
|
+
}
|
|
10903
|
+
};
|
|
10904
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
10905
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10906
|
+
react.motion.button,
|
|
10907
|
+
{
|
|
10908
|
+
className: cn(
|
|
10909
|
+
"relative inline-flex items-center justify-center rounded-lg",
|
|
10910
|
+
"bg-muted/50 border border-border/50 hover:bg-muted/70 transition-colors",
|
|
10911
|
+
styles.button,
|
|
10912
|
+
className
|
|
10913
|
+
),
|
|
10914
|
+
whileTap: { scale: 0.95 },
|
|
10915
|
+
"aria-label": `Notifications${unreadCount > 0 ? ` (${unreadCount} unread)` : ""}`,
|
|
10916
|
+
children: [
|
|
10917
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bell, { className: cn(styles.icon, "text-muted-foreground") }),
|
|
10918
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { children: unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10919
|
+
react.motion.div,
|
|
10920
|
+
{
|
|
10921
|
+
initial: { scale: 0, opacity: 0 },
|
|
10922
|
+
animate: { scale: 1, opacity: 1 },
|
|
10923
|
+
exit: { scale: 0, opacity: 0 },
|
|
10924
|
+
className: cn(
|
|
10925
|
+
"absolute flex items-center justify-center rounded-full",
|
|
10926
|
+
dotBgColor,
|
|
10927
|
+
"text-white font-medium",
|
|
10928
|
+
unreadCount > 9 ? styles.badge : styles.dot,
|
|
10929
|
+
unreadCount > 9 && "px-1"
|
|
10930
|
+
),
|
|
10931
|
+
children: unreadCount > 9 ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: unreadCount > 99 ? "99+" : unreadCount }) : null
|
|
10932
|
+
}
|
|
10933
|
+
) }),
|
|
10934
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { children: unreadCount > 0 && showPulse && pulseStyle !== "none" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10935
|
+
react.motion.div,
|
|
10936
|
+
{
|
|
10937
|
+
initial: { scale: 1, opacity: 0.5 },
|
|
10938
|
+
animate: pulseVariants[pulseStyle].animate,
|
|
10939
|
+
transition: pulseVariants[pulseStyle].transition,
|
|
10940
|
+
className: cn("absolute rounded-full", dotBgColor, styles.dot)
|
|
10941
|
+
}
|
|
10942
|
+
) })
|
|
10943
|
+
]
|
|
10944
|
+
}
|
|
10945
|
+
) }),
|
|
10946
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10947
|
+
PopoverContent,
|
|
10948
|
+
{
|
|
10949
|
+
side: "bottom",
|
|
10950
|
+
align: "end",
|
|
10951
|
+
className: "w-80 p-0 overflow-hidden",
|
|
10952
|
+
children: [
|
|
10953
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-border", children: [
|
|
10954
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
10955
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-sm", children: title }),
|
|
10956
|
+
unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-2 py-0.5 text-xs font-medium rounded-full bg-primary/10 text-primary", children: [
|
|
10957
|
+
unreadCount,
|
|
10958
|
+
" new"
|
|
10959
|
+
] })
|
|
10960
|
+
] }),
|
|
10961
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: unreadCount > 0 && onMarkAllAsRead && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10962
|
+
Button,
|
|
10963
|
+
{
|
|
10964
|
+
variant: "ghost",
|
|
10965
|
+
size: "sm",
|
|
10966
|
+
className: "h-7 px-2 text-xs",
|
|
10967
|
+
onClick: () => onMarkAllAsRead(),
|
|
10968
|
+
children: [
|
|
10969
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCheck, { className: "w-3.5 h-3.5 mr-1" }),
|
|
10970
|
+
"Mark all read"
|
|
10971
|
+
]
|
|
10972
|
+
}
|
|
10973
|
+
) })
|
|
10974
|
+
] }),
|
|
10975
|
+
notifications.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-8 px-4 text-center", children: [
|
|
10976
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-12 rounded-full bg-muted flex items-center justify-center mb-3", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bell, { className: "w-6 h-6 text-muted-foreground" }) }),
|
|
10977
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: emptyMessage })
|
|
10978
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10979
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "h-[320px]", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border", children: visibleNotifications.map((notification) => {
|
|
10980
|
+
const config = typeConfig[notification.type || "info"];
|
|
10981
|
+
const Icon = config.icon;
|
|
10982
|
+
const hasLink = !!notification.href;
|
|
10983
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10984
|
+
react.motion.div,
|
|
10985
|
+
{
|
|
10986
|
+
initial: { opacity: 0, y: -10 },
|
|
10987
|
+
animate: { opacity: 1, y: 0 },
|
|
10988
|
+
className: cn(
|
|
10989
|
+
"relative flex gap-3 px-4 py-3 transition-colors group",
|
|
10990
|
+
hasLink && "cursor-pointer hover:bg-muted/50",
|
|
10991
|
+
!hasLink && "cursor-default",
|
|
10992
|
+
!notification.read && "bg-primary/5"
|
|
10993
|
+
),
|
|
10994
|
+
onClick: () => handleNotificationClick(notification),
|
|
10995
|
+
children: [
|
|
10996
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10997
|
+
"div",
|
|
10998
|
+
{
|
|
10999
|
+
className: cn(
|
|
11000
|
+
"flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center",
|
|
11001
|
+
config.bg
|
|
11002
|
+
),
|
|
11003
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: cn("w-4 h-4", config.color) })
|
|
11004
|
+
}
|
|
11005
|
+
),
|
|
11006
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
11007
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-between gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11008
|
+
"p",
|
|
11009
|
+
{
|
|
11010
|
+
className: cn(
|
|
11011
|
+
"text-sm line-clamp-1",
|
|
11012
|
+
!notification.read ? "font-semibold" : "font-medium",
|
|
11013
|
+
hasLink && "group-hover:underline"
|
|
11014
|
+
),
|
|
11015
|
+
children: notification.title
|
|
11016
|
+
}
|
|
11017
|
+
) }),
|
|
11018
|
+
notification.message && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground line-clamp-2 mt-0.5", children: notification.message }),
|
|
11019
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-muted-foreground/70 mt-1", children: formatTimeAgo(notification.timestamp) })
|
|
11020
|
+
] }),
|
|
11021
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 flex items-start gap-1 opacity-0 group-hover:opacity-100 transition-opacity", children: onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11022
|
+
Button,
|
|
11023
|
+
{
|
|
11024
|
+
variant: "ghost",
|
|
11025
|
+
size: "icon",
|
|
11026
|
+
className: "h-6 w-6 text-muted-foreground hover:text-destructive",
|
|
11027
|
+
onClick: (e) => {
|
|
11028
|
+
e.stopPropagation();
|
|
11029
|
+
onDismiss(notification.id);
|
|
11030
|
+
},
|
|
11031
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3 h-3" })
|
|
11032
|
+
}
|
|
11033
|
+
) })
|
|
11034
|
+
]
|
|
11035
|
+
},
|
|
11036
|
+
notification.id
|
|
11037
|
+
);
|
|
11038
|
+
}) }) }),
|
|
11039
|
+
(hasMore || onClearAll) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-2 border-t border-border bg-muted/30", children: [
|
|
11040
|
+
hasMore && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
11041
|
+
"+",
|
|
11042
|
+
notifications.length - maxVisible,
|
|
11043
|
+
" more"
|
|
11044
|
+
] }),
|
|
11045
|
+
onClearAll && notifications.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11046
|
+
Button,
|
|
11047
|
+
{
|
|
11048
|
+
variant: "ghost",
|
|
11049
|
+
size: "sm",
|
|
11050
|
+
className: "h-7 px-2 text-xs text-muted-foreground hover:text-destructive",
|
|
11051
|
+
onClick: () => onClearAll(),
|
|
11052
|
+
children: [
|
|
11053
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-3 h-3 mr-1" }),
|
|
11054
|
+
"Clear all"
|
|
11055
|
+
]
|
|
11056
|
+
}
|
|
11057
|
+
)
|
|
11058
|
+
] })
|
|
11059
|
+
] })
|
|
11060
|
+
]
|
|
11061
|
+
}
|
|
11062
|
+
)
|
|
11063
|
+
] });
|
|
11064
|
+
}
|
|
10617
11065
|
|
|
10618
11066
|
exports.AvatarEditor = AvatarEditor;
|
|
10619
11067
|
exports.AvatarEditorDialog = AvatarEditorDialog;
|
|
@@ -10654,6 +11102,13 @@ exports.DropdownMenuSubContent = DropdownMenuSubContent2;
|
|
|
10654
11102
|
exports.DropdownMenuSubTrigger = DropdownMenuSubTrigger2;
|
|
10655
11103
|
exports.DropdownMenuTrigger = DropdownMenuTrigger2;
|
|
10656
11104
|
exports.LanguageSwitcher = LanguageSwitcher;
|
|
11105
|
+
exports.NotificationsWidget = NotificationsWidget;
|
|
11106
|
+
exports.Popover = Popover;
|
|
11107
|
+
exports.PopoverAnchor = PopoverAnchor;
|
|
11108
|
+
exports.PopoverContent = PopoverContent;
|
|
11109
|
+
exports.PopoverTrigger = PopoverTrigger;
|
|
11110
|
+
exports.ScrollArea = ScrollArea;
|
|
11111
|
+
exports.ScrollBar = ScrollBar;
|
|
10657
11112
|
exports.Slider = Slider;
|
|
10658
11113
|
exports.ThemeSwitcher = ThemeSwitcher;
|
|
10659
11114
|
exports.Toggle = Toggle;
|