@lindle/linoardo 1.0.26 → 1.0.27

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.
@@ -0,0 +1,107 @@
1
+ import * as React from 'react';
2
+ import { twMerge } from 'tailwind-merge';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ // src/Containment/Menu/index.tsx
6
+ var placementClasses = {
7
+ "bottom-start": "left-0 top-full origin-top-left",
8
+ bottom: "left-1/2 top-full -translate-x-1/2 origin-top",
9
+ "bottom-end": "right-0 top-full origin-top-right",
10
+ "top-start": "left-0 bottom-full origin-bottom-left",
11
+ top: "left-1/2 bottom-full -translate-x-1/2 origin-bottom",
12
+ "top-end": "right-0 bottom-full origin-bottom-right"
13
+ };
14
+ var offsetClasses = {
15
+ top: "mb-2",
16
+ bottom: "mt-2"
17
+ };
18
+ var menuBaseClasses = "absolute z-50 min-w-[10rem] rounded-xl border border-gray-200/80 bg-white/95 p-2 text-sm text-gray-700 shadow-lg shadow-gray-900/10 ring-1 ring-black/5 backdrop-blur-md transition-all duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2";
19
+ var overlayBaseClasses = "fixed inset-0 z-40 bg-gray-900/30 backdrop-blur-[1px]";
20
+ var Menu = React.forwardRef((props, ref) => {
21
+ const {
22
+ activator,
23
+ children,
24
+ placement = "bottom-start",
25
+ open,
26
+ openOnHover = true,
27
+ openOnFocus = true,
28
+ matchActivatorWidth = false,
29
+ keepMounted = false,
30
+ scrim = false,
31
+ contentClassName,
32
+ contentProps,
33
+ overlayClassName,
34
+ className,
35
+ ...rest
36
+ } = props;
37
+ const hasContent = children !== void 0 && children !== null;
38
+ const isOpen = Boolean(open);
39
+ const shouldRenderContent = hasContent && (keepMounted || isOpen || openOnHover || openOnFocus);
40
+ const shouldRenderOverlay = scrim && hasContent && (isOpen || openOnHover || openOnFocus);
41
+ const verticalPlacement = placement.startsWith("top") ? "top" : "bottom";
42
+ const visibilityClasses = twMerge(
43
+ "pointer-events-none opacity-0 scale-95",
44
+ isOpen ? "pointer-events-auto opacity-100 scale-100" : void 0,
45
+ openOnHover ? "group-hover/menu:pointer-events-auto group-hover/menu:opacity-100 group-hover/menu:scale-100" : void 0,
46
+ openOnFocus ? "group-focus-within/menu:pointer-events-auto group-focus-within/menu:opacity-100 group-focus-within/menu:scale-100" : void 0
47
+ );
48
+ const overlayVisibilityClasses = twMerge(
49
+ "pointer-events-none opacity-0 transition-opacity duration-150",
50
+ openOnHover ? "group-hover/menu:opacity-100" : void 0,
51
+ openOnFocus ? "group-focus-within/menu:opacity-100" : void 0,
52
+ isOpen ? "pointer-events-auto opacity-100" : void 0
53
+ );
54
+ const {
55
+ className: contentExtraClassName,
56
+ style: contentStyle,
57
+ role: contentRole,
58
+ tabIndex: contentTabIndex,
59
+ ...restContentProps
60
+ } = contentProps ?? {};
61
+ const overlayNode = shouldRenderOverlay ? /* @__PURE__ */ jsx(
62
+ "div",
63
+ {
64
+ className: twMerge(overlayBaseClasses, overlayVisibilityClasses, overlayClassName),
65
+ "aria-hidden": true
66
+ }
67
+ ) : null;
68
+ return /* @__PURE__ */ jsxs(
69
+ "div",
70
+ {
71
+ ...rest,
72
+ ref,
73
+ className: twMerge("relative inline-flex min-w-0 group/menu", className),
74
+ "data-open": isOpen || void 0,
75
+ children: [
76
+ overlayNode,
77
+ /* @__PURE__ */ jsx("div", { className: "inline-flex w-full min-w-0", children: activator }),
78
+ shouldRenderContent ? /* @__PURE__ */ jsx(
79
+ "div",
80
+ {
81
+ ...restContentProps,
82
+ className: twMerge(
83
+ menuBaseClasses,
84
+ placementClasses[placement],
85
+ offsetClasses[verticalPlacement],
86
+ matchActivatorWidth ? "min-w-full" : void 0,
87
+ visibilityClasses,
88
+ contentClassName,
89
+ contentExtraClassName
90
+ ),
91
+ "data-state": isOpen ? "open" : "closed",
92
+ role: contentRole ?? "menu",
93
+ tabIndex: contentTabIndex ?? -1,
94
+ style: contentStyle,
95
+ children
96
+ }
97
+ ) : null
98
+ ]
99
+ }
100
+ );
101
+ });
102
+ Menu.displayName = "Menu";
103
+ var Menu_default = Menu;
104
+
105
+ export { Menu_default };
106
+ //# sourceMappingURL=chunk-DDQ7ICWD.js.map
107
+ //# sourceMappingURL=chunk-DDQ7ICWD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/Containment/Menu/index.tsx"],"names":[],"mappings":"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","file":"chunk-DDQ7ICWD.js","sourcesContent":["import * as React from 'react';\nimport { twMerge } from 'tailwind-merge';\n\nexport type MenuPlacement =\n | 'bottom-start'\n | 'bottom'\n | 'bottom-end'\n | 'top-start'\n | 'top'\n | 'top-end';\n\nexport interface MenuProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n activator: React.ReactNode;\n children: React.ReactNode;\n placement?: MenuPlacement;\n open?: boolean;\n openOnHover?: boolean;\n openOnFocus?: boolean;\n matchActivatorWidth?: boolean;\n keepMounted?: boolean;\n scrim?: boolean;\n contentClassName?: string;\n contentProps?: React.HTMLAttributes<HTMLDivElement>;\n overlayClassName?: string;\n}\n\nconst placementClasses: Record<MenuPlacement, string> = {\n 'bottom-start': 'left-0 top-full origin-top-left',\n bottom: 'left-1/2 top-full -translate-x-1/2 origin-top',\n 'bottom-end': 'right-0 top-full origin-top-right',\n 'top-start': 'left-0 bottom-full origin-bottom-left',\n top: 'left-1/2 bottom-full -translate-x-1/2 origin-bottom',\n 'top-end': 'right-0 bottom-full origin-bottom-right'\n};\n\nconst offsetClasses: Record<'top' | 'bottom', string> = {\n top: 'mb-2',\n bottom: 'mt-2'\n};\n\nconst menuBaseClasses =\n 'absolute z-50 min-w-[10rem] rounded-xl border border-gray-200/80 bg-white/95 p-2 text-sm text-gray-700 shadow-lg shadow-gray-900/10 ring-1 ring-black/5 backdrop-blur-md transition-all duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2';\n\nconst overlayBaseClasses = 'fixed inset-0 z-40 bg-gray-900/30 backdrop-blur-[1px]';\n\n/**\n * Contextual menu that opens relative to an activator with optional hover/focus behavior and scrim.\n */\nconst Menu = React.forwardRef<HTMLDivElement, MenuProps>((props, ref) => {\n const {\n activator,\n children,\n placement = 'bottom-start',\n open,\n openOnHover = true,\n openOnFocus = true,\n matchActivatorWidth = false,\n keepMounted = false,\n scrim = false,\n contentClassName,\n contentProps,\n overlayClassName,\n className,\n ...rest\n } = props;\n\n const hasContent = children !== undefined && children !== null;\n const isOpen = Boolean(open);\n const shouldRenderContent =\n hasContent && (keepMounted || isOpen || openOnHover || openOnFocus);\n const shouldRenderOverlay = scrim && hasContent && (isOpen || openOnHover || openOnFocus);\n const verticalPlacement = placement.startsWith('top') ? 'top' : 'bottom';\n\n const visibilityClasses = twMerge(\n 'pointer-events-none opacity-0 scale-95',\n isOpen ? 'pointer-events-auto opacity-100 scale-100' : undefined,\n openOnHover\n ? 'group-hover/menu:pointer-events-auto group-hover/menu:opacity-100 group-hover/menu:scale-100'\n : undefined,\n openOnFocus\n ? 'group-focus-within/menu:pointer-events-auto group-focus-within/menu:opacity-100 group-focus-within/menu:scale-100'\n : undefined\n );\n\n const overlayVisibilityClasses = twMerge(\n 'pointer-events-none opacity-0 transition-opacity duration-150',\n openOnHover ? 'group-hover/menu:opacity-100' : undefined,\n openOnFocus ? 'group-focus-within/menu:opacity-100' : undefined,\n isOpen ? 'pointer-events-auto opacity-100' : undefined\n );\n\n const {\n className: contentExtraClassName,\n style: contentStyle,\n role: contentRole,\n tabIndex: contentTabIndex,\n ...restContentProps\n } = contentProps ?? {};\n\n const overlayNode = shouldRenderOverlay ? (\n <div\n className={twMerge(overlayBaseClasses, overlayVisibilityClasses, overlayClassName)}\n aria-hidden\n />\n ) : null;\n\n return (\n <div\n {...rest}\n ref={ref}\n className={twMerge('relative inline-flex min-w-0 group/menu', className)}\n data-open={isOpen || undefined}\n >\n {overlayNode}\n <div className='inline-flex w-full min-w-0'>{activator}</div>\n {shouldRenderContent ? (\n <div\n {...restContentProps}\n className={twMerge(\n menuBaseClasses,\n placementClasses[placement],\n offsetClasses[verticalPlacement],\n matchActivatorWidth ? 'min-w-full' : undefined,\n visibilityClasses,\n contentClassName,\n contentExtraClassName\n )}\n data-state={isOpen ? 'open' : 'closed'}\n role={contentRole ?? 'menu'}\n tabIndex={contentTabIndex ?? -1}\n style={contentStyle}\n >\n {children}\n </div>\n ) : null}\n </div>\n );\n});\n\nMenu.displayName = 'Menu';\n\nexport default Menu;\n"]}
@@ -51,6 +51,37 @@ var typeTone = {
51
51
  iconText: "text-red-600"
52
52
  }
53
53
  };
54
+ var isBrowser = typeof window !== "undefined";
55
+ var autoCloseTimers = /* @__PURE__ */ new Map();
56
+ var clearAutoCloseTimer = (key) => {
57
+ const existing = autoCloseTimers.get(key);
58
+ if (!existing) return;
59
+ clearTimeout(existing.timeoutId);
60
+ autoCloseTimers.delete(key);
61
+ };
62
+ var scheduleAutoClose = (key, duration, onClose) => {
63
+ if (!isBrowser) return;
64
+ if (typeof duration !== "number" || !Number.isFinite(duration) || duration < 0 || !onClose) {
65
+ clearAutoCloseTimer(key);
66
+ return;
67
+ }
68
+ const existing = autoCloseTimers.get(key);
69
+ if (existing && existing.duration === duration && existing.onClose === onClose) return;
70
+ if (existing) clearAutoCloseTimer(key);
71
+ const timeoutId = setTimeout(() => {
72
+ autoCloseTimers.delete(key);
73
+ onClose();
74
+ }, duration);
75
+ autoCloseTimers.set(key, { timeoutId, duration, onClose });
76
+ };
77
+ var cleanupStaleTimers = (activeKeys) => {
78
+ if (!isBrowser) return;
79
+ for (const key of Array.from(autoCloseTimers.keys())) {
80
+ if (!activeKeys.has(key)) {
81
+ clearAutoCloseTimer(key);
82
+ }
83
+ }
84
+ };
54
85
  var resolveVariantClass = (variant, type) => {
55
86
  const tone = type ? typeTone[type] : void 0;
56
87
  switch (variant) {
@@ -107,6 +138,7 @@ var NotificationCard = ({ item }) => {
107
138
  icon,
108
139
  closeIcon,
109
140
  closable = true,
141
+ duration,
110
142
  btn,
111
143
  onClick,
112
144
  className,
@@ -183,16 +215,27 @@ var Notification = ({
183
215
  className,
184
216
  ...rest
185
217
  }) => {
186
- if (!items.length) return null;
218
+ if (!items.length) {
219
+ if (isBrowser) {
220
+ for (const key of Array.from(autoCloseTimers.keys())) {
221
+ clearAutoCloseTimer(key);
222
+ }
223
+ }
224
+ return null;
225
+ }
187
226
  const grouped = /* @__PURE__ */ new Map();
227
+ const activeKeys = /* @__PURE__ */ new Set();
188
228
  items.forEach((item) => {
189
229
  const resolvedKey = item.key ?? `notification-${item.message ?? Math.random()}`;
190
230
  const resolvedPlacement = item.placement ?? placement;
191
231
  const resolvedVariant = item.variant ?? variant;
232
+ activeKeys.add(resolvedKey);
233
+ scheduleAutoClose(resolvedKey, item.duration, item.onClose);
192
234
  const group = grouped.get(resolvedPlacement) ?? [];
193
235
  group.push({ ...item, key: resolvedKey, variant: resolvedVariant });
194
236
  grouped.set(resolvedPlacement, group);
195
237
  });
238
+ cleanupStaleTimers(activeKeys);
196
239
  return /* @__PURE__ */ jsx(Fragment, { children: Array.from(grouped.entries()).map(([groupPlacement, groupItems]) => /* @__PURE__ */ jsx(
197
240
  "div",
198
241
  {
@@ -212,5 +255,5 @@ var Notification = ({
212
255
  var Notification_default = Notification;
213
256
 
214
257
  export { Notification_default };
215
- //# sourceMappingURL=chunk-KI4DBZ2V.js.map
216
- //# sourceMappingURL=chunk-KI4DBZ2V.js.map
258
+ //# sourceMappingURL=chunk-S7VLFCLP.js.map
259
+ //# sourceMappingURL=chunk-S7VLFCLP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/Feedback/Notification/index.tsx"],"names":["normalized"],"mappings":"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","file":"chunk-S7VLFCLP.js","sourcesContent":["import * as React from 'react';\nimport { twMerge } from 'tailwind-merge';\nimport type {\n NotificationArgs,\n NotificationPlacement,\n NotificationProps,\n NotificationType,\n NotificationVariant\n} from './types.notification';\nimport type { PropIcon } from '../../global.types';\n\nconst placementClasses: Record<NotificationPlacement, string> = {\n topLeft: 'top-4 left-4 items-start',\n topRight: 'top-4 right-4 items-end',\n bottomLeft: 'bottom-4 left-4 items-start',\n bottomRight: 'bottom-4 right-4 items-end'\n};\n\nconst typeIconMap: Record<NotificationType, string> = {\n info: 'mdi-information-outline',\n success: 'mdi-check-circle-outline',\n warning: 'mdi-alert-outline',\n error: 'mdi-close-circle-outline'\n};\n\nconst typeAccentMap: Record<NotificationType, string> = {\n info: 'bg-sky-50 text-sky-600',\n success: 'bg-emerald-50 text-emerald-600',\n warning: 'bg-amber-50 text-amber-700',\n error: 'bg-red-50 text-red-600'\n};\n\nconst typeTone: Record<\n NotificationType,\n { bg: string; text: string; border: string; iconBg: string; iconText: string }\n> = {\n info: {\n bg: 'bg-sky-50',\n text: 'text-sky-900',\n border: 'border-sky-200',\n iconBg: 'bg-sky-100',\n iconText: 'text-sky-600'\n },\n success: {\n bg: 'bg-emerald-50',\n text: 'text-emerald-900',\n border: 'border-emerald-200',\n iconBg: 'bg-emerald-100',\n iconText: 'text-emerald-600'\n },\n warning: {\n bg: 'bg-amber-50',\n text: 'text-amber-900',\n border: 'border-amber-200',\n iconBg: 'bg-amber-100',\n iconText: 'text-amber-700'\n },\n error: {\n bg: 'bg-red-50',\n text: 'text-red-900',\n border: 'border-red-200',\n iconBg: 'bg-red-100',\n iconText: 'text-red-600'\n }\n};\n\nconst isBrowser = typeof window !== 'undefined';\n\ntype AutoCloseEntry = {\n timeoutId: ReturnType<typeof setTimeout>;\n duration: number;\n onClose: () => void;\n};\n\nconst autoCloseTimers = new Map<React.Key, AutoCloseEntry>();\n\nconst clearAutoCloseTimer = (key: React.Key) => {\n const existing = autoCloseTimers.get(key);\n if (!existing) return;\n clearTimeout(existing.timeoutId);\n autoCloseTimers.delete(key);\n};\n\nconst scheduleAutoClose = (\n key: React.Key,\n duration: number | null | undefined,\n onClose?: () => void\n) => {\n if (!isBrowser) return;\n if (typeof duration !== 'number' || !Number.isFinite(duration) || duration < 0 || !onClose) {\n clearAutoCloseTimer(key);\n return;\n }\n\n const existing = autoCloseTimers.get(key);\n if (existing && existing.duration === duration && existing.onClose === onClose) return;\n if (existing) clearAutoCloseTimer(key);\n\n const timeoutId = setTimeout(() => {\n autoCloseTimers.delete(key);\n onClose();\n }, duration);\n\n autoCloseTimers.set(key, { timeoutId, duration, onClose });\n};\n\nconst cleanupStaleTimers = (activeKeys: Set<React.Key>) => {\n if (!isBrowser) return;\n for (const key of Array.from(autoCloseTimers.keys())) {\n if (!activeKeys.has(key)) {\n clearAutoCloseTimer(key);\n }\n }\n};\n\nconst resolveVariantClass = (variant: NotificationVariant, type?: NotificationType) => {\n const tone = type ? typeTone[type] : undefined;\n switch (variant) {\n case 'filled':\n return twMerge(\n tone?.bg ?? 'bg-primary/10',\n tone?.text ?? 'text-primary',\n 'border border-transparent shadow-none'\n );\n case 'outline':\n return twMerge(\n 'bg-white/90',\n tone?.text ?? 'text-gray-900',\n tone?.border ?? 'border-primary/20',\n 'border-[1.5px]'\n );\n case 'ghost':\n return twMerge(\n 'bg-transparent shadow-none border border-transparent',\n tone?.text ?? 'text-gray-900'\n );\n case 'solid':\n default:\n return 'bg-white/95 text-gray-900 border border-gray-200';\n }\n};\n\nconst resolveIconClassName = (icon?: PropIcon | string) => {\n if (!icon) return undefined;\n if (typeof icon === 'string') {\n const trimmed = icon.trim();\n if (!trimmed) return undefined;\n if (trimmed.includes(' ')) return trimmed;\n const normalized = trimmed.startsWith('mdi-') ? trimmed : `mdi-${trimmed}`;\n return `mdi ${normalized}`;\n }\n const [library, iconName] = icon;\n const normalized = iconName?.startsWith('mdi-') ? iconName : `mdi-${iconName}`;\n return `mdi ${library} ${normalized}`.trim();\n};\n\nconst resolveIconNode = (icon?: React.ReactNode | PropIcon, fallbackClassName?: string) => {\n if (React.isValidElement(icon)) return icon;\n const iconClassName = resolveIconClassName(icon as PropIcon) ?? fallbackClassName;\n if (!iconClassName) return null;\n const hasBase = iconClassName.split(' ').some(token => token.trim() === 'mdi');\n const hasGlyph = iconClassName.includes('mdi-');\n const finalClassName = hasBase && hasGlyph ? iconClassName : `mdi ${iconClassName}`.trim();\n return <i className={finalClassName} aria-hidden />;\n};\n\nconst NotificationCard: React.FC<{\n item: NotificationArgs & { key: React.Key };\n}> = ({ item }) => {\n const {\n key,\n message,\n description,\n icon,\n closeIcon,\n closable = true,\n duration,\n btn,\n onClick,\n className,\n style,\n role = 'status',\n type,\n variant = 'solid',\n ...rest\n } = item;\n\n const hasMessage = message !== undefined && message !== null;\n const hasDescription = description !== undefined && description !== null;\n const hasContent = hasMessage || hasDescription;\n const accentClass = type ? typeAccentMap[type] : undefined;\n const iconNode = resolveIconNode(icon, type ? `mdi ${typeIconMap[type]}` : undefined);\n const closeIconNode = resolveIconNode(closeIcon, 'mdi mdi-close');\n const variantClass = resolveVariantClass(variant as NotificationVariant, type);\n const toneIconBg = type ? typeTone[type]?.iconBg : undefined;\n const toneIconText = type ? typeTone[type]?.iconText : undefined;\n\n return (\n <article\n {...rest}\n role={role}\n className={twMerge(\n 'pointer-events-auto flex w-88 max-w-[calc(100vw-2.5rem)] gap-3 rounded-2xl p-4 shadow-xl ring-1 ring-black/5 backdrop-blur-sm transition hover:-translate-y-0.5 hover:shadow-2xl focus:outline-none',\n 'dark:border-gray-800 dark:bg-gray-900/95 dark:text-gray-50 dark:ring-white/5',\n variantClass,\n className\n )}\n style={style}\n onClick={onClick}\n >\n {iconNode ? (\n <div\n className={twMerge(\n 'mt-0.5 flex h-10 w-10 shrink-0 items-center justify-center rounded-xl text-xl',\n toneIconBg ?? accentClass ?? 'bg-primary/10',\n toneIconText ?? 'text-primary'\n )}\n >\n {iconNode}\n </div>\n ) : null}\n <div className='min-w-0 flex-1 space-y-1'>\n {hasContent ? (\n <div className='space-y-1'>\n {hasMessage ? (\n <div className='text-[15px] font-semibold leading-5 text-gray-900 dark:text-white'>\n {message}\n </div>\n ) : null}\n {hasDescription ? (\n <div className='text-sm leading-6 text-gray-600 dark:text-gray-300'>\n {description}\n </div>\n ) : null}\n </div>\n ) : null}\n {btn ? <div className='pt-1 text-sm'>{btn}</div> : null}\n </div>\n {closable ? (\n <button\n type='button'\n aria-label='Zavřít upozornění'\n className='-mr-1 -mt-1 h-8 w-8 shrink-0 rounded-full text-gray-500 transition hover:bg-gray-100 hover:text-gray-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-white'\n onClick={event => {\n event.stopPropagation();\n item.onClose?.();\n }}\n >\n {closeIconNode}\n </button>\n ) : null}\n </article>\n );\n};\n\nconst Notification: React.FC<NotificationProps> = ({\n items = [],\n placement = 'topRight',\n variant = 'solid',\n gap = 12,\n containerClassName,\n className,\n ...rest\n}) => {\n if (!items.length) {\n if (isBrowser) {\n for (const key of Array.from(autoCloseTimers.keys())) {\n clearAutoCloseTimer(key);\n }\n }\n return null;\n }\n\n const grouped = new Map<NotificationPlacement, (NotificationArgs & { key: React.Key })[]>();\n const activeKeys = new Set<React.Key>();\n items.forEach(item => {\n const resolvedKey = item.key ?? `notification-${item.message ?? Math.random()}`;\n const resolvedPlacement = item.placement ?? placement;\n const resolvedVariant = item.variant ?? variant;\n activeKeys.add(resolvedKey);\n scheduleAutoClose(resolvedKey, item.duration, item.onClose);\n const group = grouped.get(resolvedPlacement) ?? [];\n group.push({ ...item, key: resolvedKey, variant: resolvedVariant });\n grouped.set(resolvedPlacement, group);\n });\n cleanupStaleTimers(activeKeys);\n\n return (\n <>\n {Array.from(grouped.entries()).map(([groupPlacement, groupItems]) => (\n <div\n key={groupPlacement}\n className={twMerge(\n 'pointer-events-none fixed z-70 flex w-full max-w-[24rem] flex-col',\n placementClasses[groupPlacement],\n containerClassName,\n className\n )}\n style={{ gap: `${gap}px` }}\n {...rest}\n >\n {groupItems.map(item => (\n <NotificationCard key={item.key} item={item} />\n ))}\n </div>\n ))}\n </>\n );\n};\n\nexport type {\n NotificationArgs,\n NotificationPlacement,\n NotificationProps,\n NotificationType,\n NotificationVariant\n} from './types.notification';\nexport default Notification;\n"]}
package/dist/index.cjs CHANGED
@@ -904,39 +904,23 @@ var Menu = React4__namespace.forwardRef((props, ref) => {
904
904
  className,
905
905
  ...rest
906
906
  } = props;
907
- const { onMouseEnter, onMouseLeave, onFocus, onBlur, ...restProps } = rest;
908
907
  const hasContent = children !== void 0 && children !== null;
909
- const isControlled = typeof open === "boolean";
910
- const [uncontrolledOpen, setUncontrolledOpen] = React4__namespace.useState(false);
911
- const closeTimer = React4__namespace.useRef(null);
912
- const visible = isControlled ? Boolean(open) : uncontrolledOpen;
913
- const shouldRenderContent = hasContent && (keepMounted || visible || !isControlled && (openOnHover || openOnFocus));
908
+ const isOpen = Boolean(open);
909
+ const shouldRenderContent = hasContent && (keepMounted || isOpen || openOnHover || openOnFocus);
910
+ const shouldRenderOverlay = scrim && hasContent && (isOpen || openOnHover || openOnFocus);
914
911
  const verticalPlacement = placement.startsWith("top") ? "top" : "bottom";
915
- const clearCloseTimer = () => {
916
- if (closeTimer.current !== null) {
917
- window.clearTimeout(closeTimer.current);
918
- closeTimer.current = null;
919
- }
920
- };
921
- const openMenu = () => {
922
- clearCloseTimer();
923
- if (!isControlled) {
924
- setUncontrolledOpen(true);
925
- }
926
- };
927
- const scheduleClose = () => {
928
- clearCloseTimer();
929
- if (!isControlled) {
930
- closeTimer.current = window.setTimeout(() => {
931
- setUncontrolledOpen(false);
932
- closeTimer.current = null;
933
- }, 120);
934
- }
935
- };
936
- React4__namespace.useEffect(() => {
937
- return () => clearCloseTimer();
938
- }, []);
939
- const visibilityClasses = visible ? "pointer-events-auto opacity-100 scale-100" : "pointer-events-none opacity-0 scale-95";
912
+ const visibilityClasses = tailwindMerge.twMerge(
913
+ "pointer-events-none opacity-0 scale-95",
914
+ isOpen ? "pointer-events-auto opacity-100 scale-100" : void 0,
915
+ openOnHover ? "group-hover/menu:pointer-events-auto group-hover/menu:opacity-100 group-hover/menu:scale-100" : void 0,
916
+ openOnFocus ? "group-focus-within/menu:pointer-events-auto group-focus-within/menu:opacity-100 group-focus-within/menu:scale-100" : void 0
917
+ );
918
+ const overlayVisibilityClasses = tailwindMerge.twMerge(
919
+ "pointer-events-none opacity-0 transition-opacity duration-150",
920
+ openOnHover ? "group-hover/menu:opacity-100" : void 0,
921
+ openOnFocus ? "group-focus-within/menu:opacity-100" : void 0,
922
+ isOpen ? "pointer-events-auto opacity-100" : void 0
923
+ );
940
924
  const {
941
925
  className: contentExtraClassName,
942
926
  style: contentStyle,
@@ -944,78 +928,46 @@ var Menu = React4__namespace.forwardRef((props, ref) => {
944
928
  tabIndex: contentTabIndex,
945
929
  ...restContentProps
946
930
  } = contentProps ?? {};
947
- const overlayNode = scrim && visible ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge(overlayBaseClasses, overlayClassName), "aria-hidden": true }) : null;
948
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
949
- overlayNode,
950
- /* @__PURE__ */ jsxRuntime.jsxs(
951
- "div",
952
- {
953
- ...restProps,
954
- ref,
955
- className: tailwindMerge.twMerge("relative inline-flex min-w-0 group/menu", className),
956
- "data-open": visible || void 0,
957
- onMouseEnter: (event) => {
958
- if (openOnHover) {
959
- openMenu();
960
- }
961
- onMouseEnter?.(event);
962
- },
963
- onMouseLeave: (event) => {
964
- if (openOnHover) {
965
- scheduleClose();
966
- }
967
- onMouseLeave?.(event);
968
- },
969
- onFocus: (event) => {
970
- if (openOnFocus) {
971
- openMenu();
972
- }
973
- onFocus?.(event);
974
- },
975
- onBlur: (event) => {
976
- if (openOnFocus) {
977
- scheduleClose();
931
+ const overlayNode = shouldRenderOverlay ? /* @__PURE__ */ jsxRuntime.jsx(
932
+ "div",
933
+ {
934
+ className: tailwindMerge.twMerge(overlayBaseClasses, overlayVisibilityClasses, overlayClassName),
935
+ "aria-hidden": true
936
+ }
937
+ ) : null;
938
+ return /* @__PURE__ */ jsxRuntime.jsxs(
939
+ "div",
940
+ {
941
+ ...rest,
942
+ ref,
943
+ className: tailwindMerge.twMerge("relative inline-flex min-w-0 group/menu", className),
944
+ "data-open": isOpen || void 0,
945
+ children: [
946
+ overlayNode,
947
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex w-full min-w-0", children: activator }),
948
+ shouldRenderContent ? /* @__PURE__ */ jsxRuntime.jsx(
949
+ "div",
950
+ {
951
+ ...restContentProps,
952
+ className: tailwindMerge.twMerge(
953
+ menuBaseClasses,
954
+ placementClasses[placement],
955
+ offsetClasses[verticalPlacement],
956
+ matchActivatorWidth ? "min-w-full" : void 0,
957
+ visibilityClasses,
958
+ contentClassName,
959
+ contentExtraClassName
960
+ ),
961
+ "data-state": isOpen ? "open" : "closed",
962
+ role: contentRole ?? "menu",
963
+ tabIndex: contentTabIndex ?? -1,
964
+ style: contentStyle,
965
+ children
978
966
  }
979
- onBlur?.(event);
980
- },
981
- children: [
982
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex w-full min-w-0", children: activator }),
983
- shouldRenderContent ? /* @__PURE__ */ jsxRuntime.jsx(
984
- "div",
985
- {
986
- ...restContentProps,
987
- className: tailwindMerge.twMerge(
988
- menuBaseClasses,
989
- placementClasses[placement],
990
- offsetClasses[verticalPlacement],
991
- matchActivatorWidth ? "min-w-full" : void 0,
992
- visibilityClasses,
993
- contentClassName,
994
- contentExtraClassName
995
- ),
996
- "data-state": visible ? "open" : "closed",
997
- role: contentRole ?? "menu",
998
- tabIndex: contentTabIndex ?? -1,
999
- style: contentStyle,
1000
- onMouseEnter: (event) => {
1001
- if (openOnHover) {
1002
- openMenu();
1003
- }
1004
- restContentProps?.onMouseEnter?.(event);
1005
- },
1006
- onMouseLeave: (event) => {
1007
- if (openOnHover) {
1008
- scheduleClose();
1009
- }
1010
- restContentProps?.onMouseLeave?.(event);
1011
- },
1012
- children
1013
- }
1014
- ) : null
1015
- ]
1016
- }
1017
- )
1018
- ] });
967
+ ) : null
968
+ ]
969
+ }
970
+ );
1019
971
  });
1020
972
  Menu.displayName = "Menu";
1021
973
  var Menu_default = Menu;
@@ -3455,6 +3407,37 @@ var typeTone = {
3455
3407
  iconText: "text-red-600"
3456
3408
  }
3457
3409
  };
3410
+ var isBrowser = typeof window !== "undefined";
3411
+ var autoCloseTimers = /* @__PURE__ */ new Map();
3412
+ var clearAutoCloseTimer = (key) => {
3413
+ const existing = autoCloseTimers.get(key);
3414
+ if (!existing) return;
3415
+ clearTimeout(existing.timeoutId);
3416
+ autoCloseTimers.delete(key);
3417
+ };
3418
+ var scheduleAutoClose = (key, duration, onClose) => {
3419
+ if (!isBrowser) return;
3420
+ if (typeof duration !== "number" || !Number.isFinite(duration) || duration < 0 || !onClose) {
3421
+ clearAutoCloseTimer(key);
3422
+ return;
3423
+ }
3424
+ const existing = autoCloseTimers.get(key);
3425
+ if (existing && existing.duration === duration && existing.onClose === onClose) return;
3426
+ if (existing) clearAutoCloseTimer(key);
3427
+ const timeoutId = setTimeout(() => {
3428
+ autoCloseTimers.delete(key);
3429
+ onClose();
3430
+ }, duration);
3431
+ autoCloseTimers.set(key, { timeoutId, duration, onClose });
3432
+ };
3433
+ var cleanupStaleTimers = (activeKeys) => {
3434
+ if (!isBrowser) return;
3435
+ for (const key of Array.from(autoCloseTimers.keys())) {
3436
+ if (!activeKeys.has(key)) {
3437
+ clearAutoCloseTimer(key);
3438
+ }
3439
+ }
3440
+ };
3458
3441
  var resolveVariantClass3 = (variant, type) => {
3459
3442
  const tone = type ? typeTone[type] : void 0;
3460
3443
  switch (variant) {
@@ -3511,6 +3494,7 @@ var NotificationCard = ({ item }) => {
3511
3494
  icon,
3512
3495
  closeIcon,
3513
3496
  closable = true,
3497
+ duration,
3514
3498
  btn,
3515
3499
  onClick,
3516
3500
  className,
@@ -3587,16 +3571,27 @@ var Notification = ({
3587
3571
  className,
3588
3572
  ...rest
3589
3573
  }) => {
3590
- if (!items.length) return null;
3574
+ if (!items.length) {
3575
+ if (isBrowser) {
3576
+ for (const key of Array.from(autoCloseTimers.keys())) {
3577
+ clearAutoCloseTimer(key);
3578
+ }
3579
+ }
3580
+ return null;
3581
+ }
3591
3582
  const grouped = /* @__PURE__ */ new Map();
3583
+ const activeKeys = /* @__PURE__ */ new Set();
3592
3584
  items.forEach((item) => {
3593
3585
  const resolvedKey = item.key ?? `notification-${item.message ?? Math.random()}`;
3594
3586
  const resolvedPlacement = item.placement ?? placement;
3595
3587
  const resolvedVariant = item.variant ?? variant;
3588
+ activeKeys.add(resolvedKey);
3589
+ scheduleAutoClose(resolvedKey, item.duration, item.onClose);
3596
3590
  const group = grouped.get(resolvedPlacement) ?? [];
3597
3591
  group.push({ ...item, key: resolvedKey, variant: resolvedVariant });
3598
3592
  grouped.set(resolvedPlacement, group);
3599
3593
  });
3594
+ cleanupStaleTimers(activeKeys);
3600
3595
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from(grouped.entries()).map(([groupPlacement, groupItems]) => /* @__PURE__ */ jsxRuntime.jsx(
3601
3596
  "div",
3602
3597
  {