@pk-design/react-tailwind 1.10.3 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -86,7 +86,9 @@ const Toast = ({ id, title, message, type, variant = 'accent', action, icon, sho
86
86
  const enterFrom = isTop ? 'opacity-0 -translate-y-3 scale-95' : 'opacity-0 translate-y-3 scale-95';
87
87
  const leaveTo = isTop ? 'opacity-0 -translate-y-2 scale-95' : 'opacity-0 translate-y-2 scale-95';
88
88
  const renderedIcon = icon !== null && icon !== void 0 ? icon : (variant === 'filled' ? filledIconMap[type] : iconMap[type]);
89
- return (jsxRuntime.jsx(react.Transition, { appear: true, show: true, enter: "transform transition duration-300 ease-out", enterFrom: enterFrom, enterTo: "opacity-100 translate-y-0 scale-100", leave: "transition duration-200 ease-in", leaveFrom: "opacity-100 translate-y-0 scale-100", leaveTo: leaveTo, children: jsxRuntime.jsxs("div", { role: "status", id: id.toString(), className: buildClassname.buildClassName('relative overflow-hidden flex items-start gap-3 rounded-xl px-4 py-3.5 min-w-[280px] max-w-md transition-all', variantStyleMap[variant][type], className), children: [jsxRuntime.jsx("div", { className: "shrink-0 mt-0.5", children: variant === 'filled' ? (renderedIcon) : (jsxRuntime.jsx(TextContent.TextContent, { className: buildClassname.buildClassName(textColorMap[type]), children: renderedIcon })) }), jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [title && (jsxRuntime.jsx("div", { className: buildClassname.buildClassName('font-semibold text-sm leading-snug', variant === 'filled' ? 'text-white' : 'text-gray-900 dark:text-gray-100'), children: title })), jsxRuntime.jsx("div", { className: buildClassname.buildClassName('text-sm font-medium leading-relaxed', variant === 'filled' ? 'text-white/95' : 'text-gray-700 dark:text-gray-300'), children: message }), action && (jsxRuntime.jsx("div", { className: "mt-1.5", children: jsxRuntime.jsx("button", { type: "button", onClick: action.onClick, className: buildClassname.buildClassName('text-xs font-semibold underline underline-offset-2 transition-opacity focus:outline-none', variant === 'filled'
89
+ return (jsxRuntime.jsx(react.Transition, { appear: true, show: true, enter: "transform transition duration-300 ease-out", enterFrom: enterFrom, enterTo: "opacity-100 translate-y-0 scale-100", leave: "transition duration-200 ease-in", leaveFrom: "opacity-100 translate-y-0 scale-100", leaveTo: leaveTo, children: jsxRuntime.jsxs("div", { role: "status", id: id.toString(), className: buildClassname.buildClassName(
90
+ // Never wider than the viewport minus a 16px gutter each side.
91
+ 'relative overflow-hidden flex items-start gap-3 rounded-xl px-4 py-3.5 min-w-[min(280px,calc(100vw-2rem))] max-w-[min(28rem,calc(100vw-2rem))] transition-all', variantStyleMap[variant][type], className), children: [jsxRuntime.jsx("div", { className: "shrink-0 mt-0.5", children: variant === 'filled' ? (renderedIcon) : (jsxRuntime.jsx(TextContent.TextContent, { className: buildClassname.buildClassName(textColorMap[type]), children: renderedIcon })) }), jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [title && (jsxRuntime.jsx("div", { className: buildClassname.buildClassName('font-semibold text-sm leading-snug', variant === 'filled' ? 'text-white' : 'text-gray-900 dark:text-gray-100'), children: title })), jsxRuntime.jsx("div", { className: buildClassname.buildClassName('text-sm font-medium leading-relaxed', variant === 'filled' ? 'text-white/95' : 'text-gray-700 dark:text-gray-300'), children: message }), action && (jsxRuntime.jsx("div", { className: "mt-1.5", children: jsxRuntime.jsx("button", { type: "button", onClick: action.onClick, className: buildClassname.buildClassName('text-xs font-semibold underline underline-offset-2 transition-opacity focus:outline-none', variant === 'filled'
90
92
  ? 'text-white hover:opacity-85'
91
93
  : 'text-[var(--ui-primary)] hover:opacity-80'), children: action.label }) }))] }), jsxRuntime.jsx(Button.Button, { onClick: onClose, "aria-label": "Close toast", className: buildClassname.buildClassName('shrink-0 mt-0.5 opacity-60 hover:opacity-100 focus-visible:opacity-100 transition', variant === 'filled' && 'text-white hover:text-white focus-visible:outline-current'), iconOnly: true, size: "xs", variant: "plain", theme: variant === 'filled' ? 'primary' : 'secondary', children: jsxRuntime.jsx(X.default, { className: "size-4" }) }), showProgressBar && duration > 0 && (jsxRuntime.jsx("div", { className: "absolute bottom-0 left-0 right-0 h-1 bg-black/10 dark:bg-white/10 overflow-hidden", children: jsxRuntime.jsx("div", { className: buildClassname.buildClassName('h-full transition-all duration-75 ease-linear', variant === 'filled' ? 'bg-white/70' : progressBarColorMap[type]), style: { width: `${Math.max(0, progress)}%` } }) }))] }) }));
92
94
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.js","sources":["../../../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react'\nimport { Transition } from '@headlessui/react'\nimport XIcon from '../Icons/X.svg'\nimport CheckCircle from '../Icons/CircleCheck.svg'\nimport AlertCircle from '../Icons/CircleAlert.svg'\nimport Info from '../Icons/Info.svg'\nimport AlertTriangle from '../Icons/TriangleAlert.svg'\n\nimport { Button } from '../Button'\nimport { TextContent } from '../TextContent'\nimport { buildClassName } from '../../utils/build-classname'\n\nimport type { ToastProps, ToastType, ToastVariant } from './Toast.types'\n\n/**\n * Icons for each toast type\n */\nconst iconMap: Record<ToastType, React.ReactNode> = {\n success: <CheckCircle className=\"size-5 text-[var(--ui-success)]\" />,\n error: <AlertCircle className=\"size-5 text-[var(--ui-danger)]\" />,\n info: <Info className=\"size-5 text-[var(--ui-info)]\" />,\n warning: <AlertTriangle className=\"size-5 text-[var(--ui-warning)]\" />,\n}\n\nconst filledIconMap: Record<ToastType, React.ReactNode> = {\n success: <CheckCircle className=\"size-5 text-white\" />,\n error: <AlertCircle className=\"size-5 text-white\" />,\n info: <Info className=\"size-5 text-white\" />,\n warning: <AlertTriangle className=\"size-5 text-white\" />,\n}\n\nconst textColorMap: Record<ToastType, string> = {\n success: 'text-[var(--ui-success-text)]',\n error: 'text-[var(--ui-danger-text)]',\n info: 'text-[var(--ui-info-text)]',\n warning: 'text-[var(--ui-warning-text)]',\n}\n\nconst progressBarColorMap: Record<ToastType, string> = {\n success: 'bg-[var(--ui-success)]',\n error: 'bg-[var(--ui-danger)]',\n info: 'bg-[var(--ui-info)]',\n warning: 'bg-[var(--ui-warning)]',\n}\n\nconst variantStyleMap: Record<ToastVariant, Record<ToastType, string>> = {\n accent: {\n success:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-success)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n error:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-danger)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n info: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-info)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n warning:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-warning)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n },\n filled: {\n success: 'bg-[var(--ui-success)] text-white shadow-lg',\n error: 'bg-[var(--ui-danger)] text-white shadow-lg',\n info: 'bg-[var(--ui-info)] text-white shadow-lg',\n warning: 'bg-[var(--ui-warning)] text-white shadow-lg',\n },\n outlined: {\n success:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-success)] text-gray-900 dark:text-gray-100 shadow-md',\n error:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-danger)] text-gray-900 dark:text-gray-100 shadow-md',\n info: 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-info)] text-gray-900 dark:text-gray-100 shadow-md',\n warning:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-warning)] text-gray-900 dark:text-gray-100 shadow-md',\n },\n glass: {\n success:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-emerald-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n error:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-rose-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n info: 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-blue-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n warning:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-amber-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n },\n}\n\nexport const Toast: React.FC<ToastProps & { isTop?: boolean }> = ({\n id,\n title,\n message,\n type,\n variant = 'accent',\n action,\n icon,\n showProgressBar = true,\n duration = 4000,\n isPaused = false,\n onClose,\n className,\n isTop = true,\n}) => {\n const [progress, setProgress] = useState(100)\n\n useEffect(() => {\n if (!showProgressBar || !duration || isPaused) return\n\n const intervalTime = 50\n const step = (intervalTime / duration) * 100\n\n const timer = setInterval(() => {\n setProgress((prev) => {\n if (prev <= 0) {\n clearInterval(timer)\n return 0\n }\n return prev - step\n })\n }, intervalTime)\n\n return () => clearInterval(timer)\n }, [showProgressBar, duration, isPaused])\n\n const enterFrom = isTop ? 'opacity-0 -translate-y-3 scale-95' : 'opacity-0 translate-y-3 scale-95'\n const leaveTo = isTop ? 'opacity-0 -translate-y-2 scale-95' : 'opacity-0 translate-y-2 scale-95'\n\n const renderedIcon = icon ?? (variant === 'filled' ? filledIconMap[type] : iconMap[type])\n\n return (\n <Transition\n appear\n show\n enter=\"transform transition duration-300 ease-out\"\n enterFrom={enterFrom}\n enterTo=\"opacity-100 translate-y-0 scale-100\"\n leave=\"transition duration-200 ease-in\"\n leaveFrom=\"opacity-100 translate-y-0 scale-100\"\n leaveTo={leaveTo}\n >\n <div\n role=\"status\"\n id={id.toString()}\n className={buildClassName(\n 'relative overflow-hidden flex items-start gap-3 rounded-xl px-4 py-3.5 min-w-[280px] max-w-md transition-all',\n variantStyleMap[variant][type],\n className,\n )}\n >\n {/* Icon */}\n <div className=\"shrink-0 mt-0.5\">\n {variant === 'filled' ? (\n renderedIcon\n ) : (\n <TextContent className={buildClassName(textColorMap[type])}>{renderedIcon}</TextContent>\n )}\n </div>\n\n {/* Content Body */}\n <div className=\"flex-1 flex flex-col gap-0.5\">\n {title && (\n <div\n className={buildClassName(\n 'font-semibold text-sm leading-snug',\n variant === 'filled' ? 'text-white' : 'text-gray-900 dark:text-gray-100',\n )}\n >\n {title}\n </div>\n )}\n <div\n className={buildClassName(\n 'text-sm font-medium leading-relaxed',\n variant === 'filled' ? 'text-white/95' : 'text-gray-700 dark:text-gray-300',\n )}\n >\n {message}\n </div>\n\n {/* Action Button */}\n {action && (\n <div className=\"mt-1.5\">\n <button\n type=\"button\"\n onClick={action.onClick}\n className={buildClassName(\n 'text-xs font-semibold underline underline-offset-2 transition-opacity focus:outline-none',\n variant === 'filled'\n ? 'text-white hover:opacity-85'\n : 'text-[var(--ui-primary)] hover:opacity-80',\n )}\n >\n {action.label}\n </button>\n </div>\n )}\n </div>\n\n {/* Close button */}\n <Button\n onClick={onClose}\n aria-label=\"Close toast\"\n className={buildClassName(\n 'shrink-0 mt-0.5 opacity-60 hover:opacity-100 focus-visible:opacity-100 transition',\n variant === 'filled' && 'text-white hover:text-white focus-visible:outline-current',\n )}\n iconOnly\n size=\"xs\"\n variant=\"plain\"\n theme={variant === 'filled' ? 'primary' : 'secondary'}\n >\n <XIcon className=\"size-4\" />\n </Button>\n\n {/* Progress Bar Countdown */}\n {showProgressBar && duration > 0 && (\n <div className=\"absolute bottom-0 left-0 right-0 h-1 bg-black/10 dark:bg-white/10 overflow-hidden\">\n <div\n className={buildClassName(\n 'h-full transition-all duration-75 ease-linear',\n variant === 'filled' ? 'bg-white/70' : progressBarColorMap[type],\n )}\n style={{ width: `${Math.max(0, progress)}%` }}\n />\n </div>\n )}\n </div>\n </Transition>\n )\n}\n\nToast.displayName = 'Toast'\n"],"names":["_jsx","CheckCircle","AlertCircle","Info","AlertTriangle","useState","useEffect","Transition","_jsxs","buildClassName","TextContent","Button","XIcon"],"mappings":"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"}
1
+ {"version":3,"file":"Toast.js","sources":["../../../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react'\nimport { Transition } from '@headlessui/react'\nimport XIcon from '../Icons/X.svg'\nimport CheckCircle from '../Icons/CircleCheck.svg'\nimport AlertCircle from '../Icons/CircleAlert.svg'\nimport Info from '../Icons/Info.svg'\nimport AlertTriangle from '../Icons/TriangleAlert.svg'\n\nimport { Button } from '../Button'\nimport { TextContent } from '../TextContent'\nimport { buildClassName } from '../../utils/build-classname'\n\nimport type { ToastProps, ToastType, ToastVariant } from './Toast.types'\n\n/**\n * Icons for each toast type\n */\nconst iconMap: Record<ToastType, React.ReactNode> = {\n success: <CheckCircle className=\"size-5 text-[var(--ui-success)]\" />,\n error: <AlertCircle className=\"size-5 text-[var(--ui-danger)]\" />,\n info: <Info className=\"size-5 text-[var(--ui-info)]\" />,\n warning: <AlertTriangle className=\"size-5 text-[var(--ui-warning)]\" />,\n}\n\nconst filledIconMap: Record<ToastType, React.ReactNode> = {\n success: <CheckCircle className=\"size-5 text-white\" />,\n error: <AlertCircle className=\"size-5 text-white\" />,\n info: <Info className=\"size-5 text-white\" />,\n warning: <AlertTriangle className=\"size-5 text-white\" />,\n}\n\nconst textColorMap: Record<ToastType, string> = {\n success: 'text-[var(--ui-success-text)]',\n error: 'text-[var(--ui-danger-text)]',\n info: 'text-[var(--ui-info-text)]',\n warning: 'text-[var(--ui-warning-text)]',\n}\n\nconst progressBarColorMap: Record<ToastType, string> = {\n success: 'bg-[var(--ui-success)]',\n error: 'bg-[var(--ui-danger)]',\n info: 'bg-[var(--ui-info)]',\n warning: 'bg-[var(--ui-warning)]',\n}\n\nconst variantStyleMap: Record<ToastVariant, Record<ToastType, string>> = {\n accent: {\n success:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-success)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n error:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-danger)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n info: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-info)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n warning:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-warning)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n },\n filled: {\n success: 'bg-[var(--ui-success)] text-white shadow-lg',\n error: 'bg-[var(--ui-danger)] text-white shadow-lg',\n info: 'bg-[var(--ui-info)] text-white shadow-lg',\n warning: 'bg-[var(--ui-warning)] text-white shadow-lg',\n },\n outlined: {\n success:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-success)] text-gray-900 dark:text-gray-100 shadow-md',\n error:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-danger)] text-gray-900 dark:text-gray-100 shadow-md',\n info: 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-info)] text-gray-900 dark:text-gray-100 shadow-md',\n warning:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-warning)] text-gray-900 dark:text-gray-100 shadow-md',\n },\n glass: {\n success:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-emerald-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n error:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-rose-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n info: 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-blue-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n warning:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-amber-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n },\n}\n\nexport const Toast: React.FC<ToastProps & { isTop?: boolean }> = ({\n id,\n title,\n message,\n type,\n variant = 'accent',\n action,\n icon,\n showProgressBar = true,\n duration = 4000,\n isPaused = false,\n onClose,\n className,\n isTop = true,\n}) => {\n const [progress, setProgress] = useState(100)\n\n useEffect(() => {\n if (!showProgressBar || !duration || isPaused) return\n\n const intervalTime = 50\n const step = (intervalTime / duration) * 100\n\n const timer = setInterval(() => {\n setProgress((prev) => {\n if (prev <= 0) {\n clearInterval(timer)\n return 0\n }\n return prev - step\n })\n }, intervalTime)\n\n return () => clearInterval(timer)\n }, [showProgressBar, duration, isPaused])\n\n const enterFrom = isTop ? 'opacity-0 -translate-y-3 scale-95' : 'opacity-0 translate-y-3 scale-95'\n const leaveTo = isTop ? 'opacity-0 -translate-y-2 scale-95' : 'opacity-0 translate-y-2 scale-95'\n\n const renderedIcon = icon ?? (variant === 'filled' ? filledIconMap[type] : iconMap[type])\n\n return (\n <Transition\n appear\n show\n enter=\"transform transition duration-300 ease-out\"\n enterFrom={enterFrom}\n enterTo=\"opacity-100 translate-y-0 scale-100\"\n leave=\"transition duration-200 ease-in\"\n leaveFrom=\"opacity-100 translate-y-0 scale-100\"\n leaveTo={leaveTo}\n >\n <div\n role=\"status\"\n id={id.toString()}\n className={buildClassName(\n // Never wider than the viewport minus a 16px gutter each side.\n 'relative overflow-hidden flex items-start gap-3 rounded-xl px-4 py-3.5 min-w-[min(280px,calc(100vw-2rem))] max-w-[min(28rem,calc(100vw-2rem))] transition-all',\n variantStyleMap[variant][type],\n className,\n )}\n >\n {/* Icon */}\n <div className=\"shrink-0 mt-0.5\">\n {variant === 'filled' ? (\n renderedIcon\n ) : (\n <TextContent className={buildClassName(textColorMap[type])}>{renderedIcon}</TextContent>\n )}\n </div>\n\n {/* Content Body */}\n <div className=\"flex-1 flex flex-col gap-0.5\">\n {title && (\n <div\n className={buildClassName(\n 'font-semibold text-sm leading-snug',\n variant === 'filled' ? 'text-white' : 'text-gray-900 dark:text-gray-100',\n )}\n >\n {title}\n </div>\n )}\n <div\n className={buildClassName(\n 'text-sm font-medium leading-relaxed',\n variant === 'filled' ? 'text-white/95' : 'text-gray-700 dark:text-gray-300',\n )}\n >\n {message}\n </div>\n\n {/* Action Button */}\n {action && (\n <div className=\"mt-1.5\">\n <button\n type=\"button\"\n onClick={action.onClick}\n className={buildClassName(\n 'text-xs font-semibold underline underline-offset-2 transition-opacity focus:outline-none',\n variant === 'filled'\n ? 'text-white hover:opacity-85'\n : 'text-[var(--ui-primary)] hover:opacity-80',\n )}\n >\n {action.label}\n </button>\n </div>\n )}\n </div>\n\n {/* Close button */}\n <Button\n onClick={onClose}\n aria-label=\"Close toast\"\n className={buildClassName(\n 'shrink-0 mt-0.5 opacity-60 hover:opacity-100 focus-visible:opacity-100 transition',\n variant === 'filled' && 'text-white hover:text-white focus-visible:outline-current',\n )}\n iconOnly\n size=\"xs\"\n variant=\"plain\"\n theme={variant === 'filled' ? 'primary' : 'secondary'}\n >\n <XIcon className=\"size-4\" />\n </Button>\n\n {/* Progress Bar Countdown */}\n {showProgressBar && duration > 0 && (\n <div className=\"absolute bottom-0 left-0 right-0 h-1 bg-black/10 dark:bg-white/10 overflow-hidden\">\n <div\n className={buildClassName(\n 'h-full transition-all duration-75 ease-linear',\n variant === 'filled' ? 'bg-white/70' : progressBarColorMap[type],\n )}\n style={{ width: `${Math.max(0, progress)}%` }}\n />\n </div>\n )}\n </div>\n </Transition>\n )\n}\n\nToast.displayName = 'Toast'\n"],"names":["_jsx","CheckCircle","AlertCircle","Info","AlertTriangle","useState","useEffect","Transition","_jsxs","buildClassName","TextContent","Button","XIcon"],"mappings":"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"}
@@ -4,6 +4,7 @@ var jsxRuntime = require('react/jsx-runtime');
4
4
  var React = require('react');
5
5
  var Toast = require('./Toast.js');
6
6
  var buildClassname = require('../../utils/build-classname.js');
7
+ var useBreakpoint = require('../../hooks/use-breakpoint.js');
7
8
 
8
9
  const ToastContext = React.createContext(undefined);
9
10
  let toastCounter = 0;
@@ -17,11 +18,15 @@ const placementClass = {
17
18
  'top-right': 'top-20 right-6 items-end',
18
19
  'top-left': 'top-20 left-6 items-start',
19
20
  'top-center': 'top-20 left-1/2 -translate-x-1/2 items-center',
20
- 'bottom-right': 'bottom-6 right-6 items-end',
21
- 'bottom-left': 'bottom-6 left-6 items-start',
22
- 'bottom-center': 'bottom-6 left-1/2 -translate-x-1/2 items-center',
21
+ // Bottom placements clear the home indicator on notched phones (0 elsewhere).
22
+ 'bottom-right': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] right-6 items-end',
23
+ 'bottom-left': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-6 items-start',
24
+ 'bottom-center': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-1/2 -translate-x-1/2 items-center',
23
25
  };
24
- const ToastProvider = ({ children, placement = 'top-right', maxToasts = 5, className, }) => {
26
+ const ToastProvider = ({ children, placement: placementProp = 'top-right', maxToasts = 5, offset, className, }) => {
27
+ const placement = useBreakpoint.useResponsiveValue(placementProp);
28
+ const isTop = placement.startsWith('top');
29
+ const edgeOffset = isTop ? offset === null || offset === void 0 ? void 0 : offset.top : offset === null || offset === void 0 ? void 0 : offset.bottom;
25
30
  const [toasts, setToasts] = React.useState([]);
26
31
  const [pausedIds, setPausedIds] = React.useState(new Set());
27
32
  const metaRefs = React.useRef(new Map());
@@ -142,7 +147,7 @@ const ToastProvider = ({ children, placement = 'top-right', maxToasts = 5, class
142
147
  dismiss: (id) => closeToast(id),
143
148
  dismissAll: () => dismissAll(),
144
149
  }), [showToast, closeToast, dismissAll]);
145
- return (jsxRuntime.jsxs(ToastContext.Provider, { value: { showToast, closeToast, toast: toastHelpers }, children: [children, jsxRuntime.jsx("div", { className: buildClassname.buildClassName('fixed z-[9999] flex flex-col gap-3 pointer-events-none', placementClass[placement], className), children: toasts.map((toastItem) => (jsxRuntime.jsx("div", { className: "pointer-events-auto", onMouseEnter: () => handleMouseEnter(toastItem), onMouseLeave: () => handleMouseLeave(toastItem), children: jsxRuntime.jsx(Toast.Toast, { ...toastItem, isPaused: pausedIds.has(toastItem.id), isTop: placement.startsWith('top'), onClose: () => closeToast(toastItem.id) }) }, toastItem.id))) })] }));
150
+ return (jsxRuntime.jsxs(ToastContext.Provider, { value: { showToast, closeToast, toast: toastHelpers }, children: [children, jsxRuntime.jsx("div", { className: buildClassname.buildClassName('fixed z-[9999] flex flex-col gap-3 pointer-events-none', placementClass[placement], className), style: edgeOffset ? (isTop ? { top: edgeOffset } : { bottom: edgeOffset }) : undefined, "data-testid": "toast-container", "data-placement": placement, children: toasts.map((toastItem) => (jsxRuntime.jsx("div", { className: "pointer-events-auto", onMouseEnter: () => handleMouseEnter(toastItem), onMouseLeave: () => handleMouseLeave(toastItem), children: jsxRuntime.jsx(Toast.Toast, { ...toastItem, isPaused: pausedIds.has(toastItem.id), isTop: isTop, onClose: () => closeToast(toastItem.id) }) }, toastItem.id))) })] }));
146
151
  };
147
152
  ToastProvider.displayName = 'ToastProvider';
148
153
 
@@ -1 +1 @@
1
- {"version":3,"file":"ToastProvider.js","sources":["../../../../../src/components/Toast/ToastProvider.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n useRef,\n useCallback,\n useMemo,\n} from 'react'\nimport { Toast } from './Toast'\nimport type {\n IToast,\n ToastContextType,\n ToastOptions,\n ToastPlacement,\n ToastProviderProps,\n} from './Toast.types'\nimport { buildClassName } from '../../utils/build-classname'\n\nconst ToastContext = createContext<ToastContextType | undefined>(undefined)\nlet toastCounter = 0\n\nexport const useToast = (): ToastContextType => {\n const context = useContext(ToastContext)\n if (!context) throw new Error('useToast must be used within ToastProvider')\n return context\n}\n\nconst placementClass: Record<ToastPlacement, string> = {\n 'top-right': 'top-20 right-6 items-end',\n 'top-left': 'top-20 left-6 items-start',\n 'top-center': 'top-20 left-1/2 -translate-x-1/2 items-center',\n\n 'bottom-right': 'bottom-6 right-6 items-end',\n 'bottom-left': 'bottom-6 left-6 items-start',\n 'bottom-center': 'bottom-6 left-1/2 -translate-x-1/2 items-center',\n}\n\ninterface ToastMeta {\n timerId: any\n startTime: number\n remainingTime: number\n}\n\nexport const ToastProvider: React.FC<ToastProviderProps> = ({\n children,\n placement = 'top-right',\n maxToasts = 5,\n className,\n}) => {\n const [toasts, setToasts] = useState<IToast[]>([])\n const [pausedIds, setPausedIds] = useState<Set<number>>(new Set())\n const metaRefs = useRef<Map<number, ToastMeta>>(new Map())\n\n const clearTimer = (id: number) => {\n const meta = metaRefs.current.get(id)\n if (meta?.timerId) {\n clearTimeout(meta.timerId)\n meta.timerId = null\n }\n }\n\n const closeToast = useCallback((id: number) => {\n clearTimer(id)\n metaRefs.current.delete(id)\n setPausedIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n setToasts((prev) => prev.filter((t) => t.id !== id))\n }, [])\n\n const dismissAll = useCallback(() => {\n metaRefs.current.forEach((meta) => {\n if (meta.timerId) clearTimeout(meta.timerId)\n })\n metaRefs.current.clear()\n setPausedIds(new Set())\n setToasts([])\n }, [])\n\n const startAutoClose = useCallback(\n (toastId: number, delay: number) => {\n clearTimer(toastId)\n\n const timerId = setTimeout(() => {\n closeToast(toastId)\n }, delay)\n\n const meta = metaRefs.current.get(toastId)\n if (meta) {\n meta.timerId = timerId\n meta.startTime = Date.now()\n meta.remainingTime = delay\n } else {\n metaRefs.current.set(toastId, {\n timerId,\n startTime: Date.now(),\n remainingTime: delay,\n })\n }\n },\n [closeToast],\n )\n\n useEffect(() => {\n const refs = metaRefs.current\n return () =>\n refs.forEach((meta) => {\n if (meta.timerId) clearTimeout(meta.timerId)\n })\n }, [])\n\n const showToast = useCallback(\n (message: ReactNode, options?: ToastOptions): number => {\n const id = ++toastCounter\n\n const newToast: IToast = {\n id,\n title: options?.title,\n message,\n type: options?.type ?? 'info',\n variant: options?.variant ?? 'accent',\n duration: options?.duration ?? 4000,\n autoClose: options?.autoClose ?? true,\n pauseOnHover: options?.pauseOnHover ?? true,\n showProgressBar: options?.showProgressBar ?? options?.autoClose !== false,\n action: options?.action,\n icon: options?.icon,\n }\n\n setToasts((prev) => {\n const updated = [...prev, newToast]\n if (updated.length > maxToasts) updated.shift()\n return updated\n })\n\n if (newToast.autoClose) {\n startAutoClose(id, newToast.duration)\n }\n\n return id\n },\n [maxToasts, startAutoClose],\n )\n\n // Hover pauses timer and tracks exact remaining milliseconds\n const handleMouseEnter = (toast: IToast) => {\n if (!toast.pauseOnHover || !toast.autoClose) return\n\n const meta = metaRefs.current.get(toast.id)\n if (meta) {\n const elapsed = Date.now() - meta.startTime\n meta.remainingTime = Math.max(0, meta.remainingTime - elapsed)\n clearTimer(toast.id)\n setPausedIds((prev) => new Set(prev).add(toast.id))\n }\n }\n\n // Mouse leave resumes timer with exact remaining milliseconds\n const handleMouseLeave = (toast: IToast) => {\n if (!toast.pauseOnHover || !toast.autoClose) return\n\n setPausedIds((prev) => {\n const next = new Set(prev)\n next.delete(toast.id)\n return next\n })\n\n const meta = metaRefs.current.get(toast.id)\n if (meta && meta.remainingTime > 0) {\n startAutoClose(toast.id, meta.remainingTime)\n } else if (meta && meta.remainingTime <= 0) {\n closeToast(toast.id)\n }\n }\n\n const toastHelpers = useMemo(\n () => ({\n show: (message: ReactNode, options?: ToastOptions) => showToast(message, options),\n success: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'success' }),\n error: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'error' }),\n info: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'info' }),\n warning: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'warning' }),\n dismiss: (id: number) => closeToast(id),\n dismissAll: () => dismissAll(),\n }),\n [showToast, closeToast, dismissAll],\n )\n\n return (\n <ToastContext.Provider value={{ showToast, closeToast, toast: toastHelpers }}>\n {children}\n\n {/* Toast Container */}\n <div\n className={buildClassName(\n 'fixed z-[9999] flex flex-col gap-3 pointer-events-none',\n placementClass[placement],\n className,\n )}\n >\n {toasts.map((toastItem) => (\n <div\n key={toastItem.id}\n className=\"pointer-events-auto\"\n onMouseEnter={() => handleMouseEnter(toastItem)}\n onMouseLeave={() => handleMouseLeave(toastItem)}\n >\n <Toast\n {...toastItem}\n isPaused={pausedIds.has(toastItem.id)}\n isTop={placement.startsWith('top')}\n onClose={() => closeToast(toastItem.id)}\n />\n </div>\n ))}\n </div>\n </ToastContext.Provider>\n )\n}\n\nToastProvider.displayName = 'ToastProvider'\n"],"names":["createContext","useContext","useState","useRef","useCallback","useEffect","useMemo","_jsxs","_jsx","buildClassName","Toast"],"mappings":"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"}
1
+ {"version":3,"file":"ToastProvider.js","sources":["../../../../../src/components/Toast/ToastProvider.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n useRef,\n useCallback,\n useMemo,\n} from 'react'\nimport { Toast } from './Toast'\nimport type {\n IToast,\n ToastContextType,\n ToastOptions,\n ToastPlacement,\n ToastProviderProps,\n} from './Toast.types'\nimport { buildClassName } from '../../utils/build-classname'\nimport { useResponsiveValue } from '../../hooks/use-breakpoint'\n\nconst ToastContext = createContext<ToastContextType | undefined>(undefined)\nlet toastCounter = 0\n\nexport const useToast = (): ToastContextType => {\n const context = useContext(ToastContext)\n if (!context) throw new Error('useToast must be used within ToastProvider')\n return context\n}\n\nconst placementClass: Record<ToastPlacement, string> = {\n 'top-right': 'top-20 right-6 items-end',\n 'top-left': 'top-20 left-6 items-start',\n 'top-center': 'top-20 left-1/2 -translate-x-1/2 items-center',\n\n // Bottom placements clear the home indicator on notched phones (0 elsewhere).\n 'bottom-right': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] right-6 items-end',\n 'bottom-left': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-6 items-start',\n 'bottom-center':\n 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-1/2 -translate-x-1/2 items-center',\n}\n\ninterface ToastMeta {\n timerId: any\n startTime: number\n remainingTime: number\n}\n\nexport const ToastProvider: React.FC<ToastProviderProps> = ({\n children,\n placement: placementProp = 'top-right',\n maxToasts = 5,\n offset,\n className,\n}) => {\n const placement = useResponsiveValue(placementProp)\n const isTop = placement.startsWith('top')\n const edgeOffset = isTop ? offset?.top : offset?.bottom\n const [toasts, setToasts] = useState<IToast[]>([])\n const [pausedIds, setPausedIds] = useState<Set<number>>(new Set())\n const metaRefs = useRef<Map<number, ToastMeta>>(new Map())\n\n const clearTimer = (id: number) => {\n const meta = metaRefs.current.get(id)\n if (meta?.timerId) {\n clearTimeout(meta.timerId)\n meta.timerId = null\n }\n }\n\n const closeToast = useCallback((id: number) => {\n clearTimer(id)\n metaRefs.current.delete(id)\n setPausedIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n setToasts((prev) => prev.filter((t) => t.id !== id))\n }, [])\n\n const dismissAll = useCallback(() => {\n metaRefs.current.forEach((meta) => {\n if (meta.timerId) clearTimeout(meta.timerId)\n })\n metaRefs.current.clear()\n setPausedIds(new Set())\n setToasts([])\n }, [])\n\n const startAutoClose = useCallback(\n (toastId: number, delay: number) => {\n clearTimer(toastId)\n\n const timerId = setTimeout(() => {\n closeToast(toastId)\n }, delay)\n\n const meta = metaRefs.current.get(toastId)\n if (meta) {\n meta.timerId = timerId\n meta.startTime = Date.now()\n meta.remainingTime = delay\n } else {\n metaRefs.current.set(toastId, {\n timerId,\n startTime: Date.now(),\n remainingTime: delay,\n })\n }\n },\n [closeToast],\n )\n\n useEffect(() => {\n const refs = metaRefs.current\n return () =>\n refs.forEach((meta) => {\n if (meta.timerId) clearTimeout(meta.timerId)\n })\n }, [])\n\n const showToast = useCallback(\n (message: ReactNode, options?: ToastOptions): number => {\n const id = ++toastCounter\n\n const newToast: IToast = {\n id,\n title: options?.title,\n message,\n type: options?.type ?? 'info',\n variant: options?.variant ?? 'accent',\n duration: options?.duration ?? 4000,\n autoClose: options?.autoClose ?? true,\n pauseOnHover: options?.pauseOnHover ?? true,\n showProgressBar: options?.showProgressBar ?? options?.autoClose !== false,\n action: options?.action,\n icon: options?.icon,\n }\n\n setToasts((prev) => {\n const updated = [...prev, newToast]\n if (updated.length > maxToasts) updated.shift()\n return updated\n })\n\n if (newToast.autoClose) {\n startAutoClose(id, newToast.duration)\n }\n\n return id\n },\n [maxToasts, startAutoClose],\n )\n\n // Hover pauses timer and tracks exact remaining milliseconds\n const handleMouseEnter = (toast: IToast) => {\n if (!toast.pauseOnHover || !toast.autoClose) return\n\n const meta = metaRefs.current.get(toast.id)\n if (meta) {\n const elapsed = Date.now() - meta.startTime\n meta.remainingTime = Math.max(0, meta.remainingTime - elapsed)\n clearTimer(toast.id)\n setPausedIds((prev) => new Set(prev).add(toast.id))\n }\n }\n\n // Mouse leave resumes timer with exact remaining milliseconds\n const handleMouseLeave = (toast: IToast) => {\n if (!toast.pauseOnHover || !toast.autoClose) return\n\n setPausedIds((prev) => {\n const next = new Set(prev)\n next.delete(toast.id)\n return next\n })\n\n const meta = metaRefs.current.get(toast.id)\n if (meta && meta.remainingTime > 0) {\n startAutoClose(toast.id, meta.remainingTime)\n } else if (meta && meta.remainingTime <= 0) {\n closeToast(toast.id)\n }\n }\n\n const toastHelpers = useMemo(\n () => ({\n show: (message: ReactNode, options?: ToastOptions) => showToast(message, options),\n success: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'success' }),\n error: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'error' }),\n info: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'info' }),\n warning: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'warning' }),\n dismiss: (id: number) => closeToast(id),\n dismissAll: () => dismissAll(),\n }),\n [showToast, closeToast, dismissAll],\n )\n\n return (\n <ToastContext.Provider value={{ showToast, closeToast, toast: toastHelpers }}>\n {children}\n\n {/* Toast Container */}\n <div\n className={buildClassName(\n 'fixed z-[9999] flex flex-col gap-3 pointer-events-none',\n placementClass[placement],\n className,\n )}\n style={edgeOffset ? (isTop ? { top: edgeOffset } : { bottom: edgeOffset }) : undefined}\n data-testid=\"toast-container\"\n data-placement={placement}\n >\n {toasts.map((toastItem) => (\n <div\n key={toastItem.id}\n className=\"pointer-events-auto\"\n onMouseEnter={() => handleMouseEnter(toastItem)}\n onMouseLeave={() => handleMouseLeave(toastItem)}\n >\n <Toast\n {...toastItem}\n isPaused={pausedIds.has(toastItem.id)}\n isTop={isTop}\n onClose={() => closeToast(toastItem.id)}\n />\n </div>\n ))}\n </div>\n </ToastContext.Provider>\n )\n}\n\nToastProvider.displayName = 'ToastProvider'\n"],"names":["createContext","useContext","useResponsiveValue","useState","useRef","useCallback","useEffect","useMemo","_jsxs","_jsx","buildClassName","Toast"],"mappings":"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"}
@@ -84,7 +84,9 @@ const Toast = ({ id, title, message, type, variant = 'accent', action, icon, sho
84
84
  const enterFrom = isTop ? 'opacity-0 -translate-y-3 scale-95' : 'opacity-0 translate-y-3 scale-95';
85
85
  const leaveTo = isTop ? 'opacity-0 -translate-y-2 scale-95' : 'opacity-0 translate-y-2 scale-95';
86
86
  const renderedIcon = icon !== null && icon !== void 0 ? icon : (variant === 'filled' ? filledIconMap[type] : iconMap[type]);
87
- return (jsx(Transition, { appear: true, show: true, enter: "transform transition duration-300 ease-out", enterFrom: enterFrom, enterTo: "opacity-100 translate-y-0 scale-100", leave: "transition duration-200 ease-in", leaveFrom: "opacity-100 translate-y-0 scale-100", leaveTo: leaveTo, children: jsxs("div", { role: "status", id: id.toString(), className: buildClassName('relative overflow-hidden flex items-start gap-3 rounded-xl px-4 py-3.5 min-w-[280px] max-w-md transition-all', variantStyleMap[variant][type], className), children: [jsx("div", { className: "shrink-0 mt-0.5", children: variant === 'filled' ? (renderedIcon) : (jsx(TextContent, { className: buildClassName(textColorMap[type]), children: renderedIcon })) }), jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [title && (jsx("div", { className: buildClassName('font-semibold text-sm leading-snug', variant === 'filled' ? 'text-white' : 'text-gray-900 dark:text-gray-100'), children: title })), jsx("div", { className: buildClassName('text-sm font-medium leading-relaxed', variant === 'filled' ? 'text-white/95' : 'text-gray-700 dark:text-gray-300'), children: message }), action && (jsx("div", { className: "mt-1.5", children: jsx("button", { type: "button", onClick: action.onClick, className: buildClassName('text-xs font-semibold underline underline-offset-2 transition-opacity focus:outline-none', variant === 'filled'
87
+ return (jsx(Transition, { appear: true, show: true, enter: "transform transition duration-300 ease-out", enterFrom: enterFrom, enterTo: "opacity-100 translate-y-0 scale-100", leave: "transition duration-200 ease-in", leaveFrom: "opacity-100 translate-y-0 scale-100", leaveTo: leaveTo, children: jsxs("div", { role: "status", id: id.toString(), className: buildClassName(
88
+ // Never wider than the viewport minus a 16px gutter each side.
89
+ 'relative overflow-hidden flex items-start gap-3 rounded-xl px-4 py-3.5 min-w-[min(280px,calc(100vw-2rem))] max-w-[min(28rem,calc(100vw-2rem))] transition-all', variantStyleMap[variant][type], className), children: [jsx("div", { className: "shrink-0 mt-0.5", children: variant === 'filled' ? (renderedIcon) : (jsx(TextContent, { className: buildClassName(textColorMap[type]), children: renderedIcon })) }), jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [title && (jsx("div", { className: buildClassName('font-semibold text-sm leading-snug', variant === 'filled' ? 'text-white' : 'text-gray-900 dark:text-gray-100'), children: title })), jsx("div", { className: buildClassName('text-sm font-medium leading-relaxed', variant === 'filled' ? 'text-white/95' : 'text-gray-700 dark:text-gray-300'), children: message }), action && (jsx("div", { className: "mt-1.5", children: jsx("button", { type: "button", onClick: action.onClick, className: buildClassName('text-xs font-semibold underline underline-offset-2 transition-opacity focus:outline-none', variant === 'filled'
88
90
  ? 'text-white hover:opacity-85'
89
91
  : 'text-[var(--ui-primary)] hover:opacity-80'), children: action.label }) }))] }), jsx(Button, { onClick: onClose, "aria-label": "Close toast", className: buildClassName('shrink-0 mt-0.5 opacity-60 hover:opacity-100 focus-visible:opacity-100 transition', variant === 'filled' && 'text-white hover:text-white focus-visible:outline-current'), iconOnly: true, size: "xs", variant: "plain", theme: variant === 'filled' ? 'primary' : 'secondary', children: jsx(SvgX, { className: "size-4" }) }), showProgressBar && duration > 0 && (jsx("div", { className: "absolute bottom-0 left-0 right-0 h-1 bg-black/10 dark:bg-white/10 overflow-hidden", children: jsx("div", { className: buildClassName('h-full transition-all duration-75 ease-linear', variant === 'filled' ? 'bg-white/70' : progressBarColorMap[type]), style: { width: `${Math.max(0, progress)}%` } }) }))] }) }));
90
92
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.js","sources":["../../../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react'\nimport { Transition } from '@headlessui/react'\nimport XIcon from '../Icons/X.svg'\nimport CheckCircle from '../Icons/CircleCheck.svg'\nimport AlertCircle from '../Icons/CircleAlert.svg'\nimport Info from '../Icons/Info.svg'\nimport AlertTriangle from '../Icons/TriangleAlert.svg'\n\nimport { Button } from '../Button'\nimport { TextContent } from '../TextContent'\nimport { buildClassName } from '../../utils/build-classname'\n\nimport type { ToastProps, ToastType, ToastVariant } from './Toast.types'\n\n/**\n * Icons for each toast type\n */\nconst iconMap: Record<ToastType, React.ReactNode> = {\n success: <CheckCircle className=\"size-5 text-[var(--ui-success)]\" />,\n error: <AlertCircle className=\"size-5 text-[var(--ui-danger)]\" />,\n info: <Info className=\"size-5 text-[var(--ui-info)]\" />,\n warning: <AlertTriangle className=\"size-5 text-[var(--ui-warning)]\" />,\n}\n\nconst filledIconMap: Record<ToastType, React.ReactNode> = {\n success: <CheckCircle className=\"size-5 text-white\" />,\n error: <AlertCircle className=\"size-5 text-white\" />,\n info: <Info className=\"size-5 text-white\" />,\n warning: <AlertTriangle className=\"size-5 text-white\" />,\n}\n\nconst textColorMap: Record<ToastType, string> = {\n success: 'text-[var(--ui-success-text)]',\n error: 'text-[var(--ui-danger-text)]',\n info: 'text-[var(--ui-info-text)]',\n warning: 'text-[var(--ui-warning-text)]',\n}\n\nconst progressBarColorMap: Record<ToastType, string> = {\n success: 'bg-[var(--ui-success)]',\n error: 'bg-[var(--ui-danger)]',\n info: 'bg-[var(--ui-info)]',\n warning: 'bg-[var(--ui-warning)]',\n}\n\nconst variantStyleMap: Record<ToastVariant, Record<ToastType, string>> = {\n accent: {\n success:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-success)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n error:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-danger)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n info: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-info)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n warning:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-warning)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n },\n filled: {\n success: 'bg-[var(--ui-success)] text-white shadow-lg',\n error: 'bg-[var(--ui-danger)] text-white shadow-lg',\n info: 'bg-[var(--ui-info)] text-white shadow-lg',\n warning: 'bg-[var(--ui-warning)] text-white shadow-lg',\n },\n outlined: {\n success:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-success)] text-gray-900 dark:text-gray-100 shadow-md',\n error:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-danger)] text-gray-900 dark:text-gray-100 shadow-md',\n info: 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-info)] text-gray-900 dark:text-gray-100 shadow-md',\n warning:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-warning)] text-gray-900 dark:text-gray-100 shadow-md',\n },\n glass: {\n success:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-emerald-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n error:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-rose-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n info: 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-blue-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n warning:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-amber-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n },\n}\n\nexport const Toast: React.FC<ToastProps & { isTop?: boolean }> = ({\n id,\n title,\n message,\n type,\n variant = 'accent',\n action,\n icon,\n showProgressBar = true,\n duration = 4000,\n isPaused = false,\n onClose,\n className,\n isTop = true,\n}) => {\n const [progress, setProgress] = useState(100)\n\n useEffect(() => {\n if (!showProgressBar || !duration || isPaused) return\n\n const intervalTime = 50\n const step = (intervalTime / duration) * 100\n\n const timer = setInterval(() => {\n setProgress((prev) => {\n if (prev <= 0) {\n clearInterval(timer)\n return 0\n }\n return prev - step\n })\n }, intervalTime)\n\n return () => clearInterval(timer)\n }, [showProgressBar, duration, isPaused])\n\n const enterFrom = isTop ? 'opacity-0 -translate-y-3 scale-95' : 'opacity-0 translate-y-3 scale-95'\n const leaveTo = isTop ? 'opacity-0 -translate-y-2 scale-95' : 'opacity-0 translate-y-2 scale-95'\n\n const renderedIcon = icon ?? (variant === 'filled' ? filledIconMap[type] : iconMap[type])\n\n return (\n <Transition\n appear\n show\n enter=\"transform transition duration-300 ease-out\"\n enterFrom={enterFrom}\n enterTo=\"opacity-100 translate-y-0 scale-100\"\n leave=\"transition duration-200 ease-in\"\n leaveFrom=\"opacity-100 translate-y-0 scale-100\"\n leaveTo={leaveTo}\n >\n <div\n role=\"status\"\n id={id.toString()}\n className={buildClassName(\n 'relative overflow-hidden flex items-start gap-3 rounded-xl px-4 py-3.5 min-w-[280px] max-w-md transition-all',\n variantStyleMap[variant][type],\n className,\n )}\n >\n {/* Icon */}\n <div className=\"shrink-0 mt-0.5\">\n {variant === 'filled' ? (\n renderedIcon\n ) : (\n <TextContent className={buildClassName(textColorMap[type])}>{renderedIcon}</TextContent>\n )}\n </div>\n\n {/* Content Body */}\n <div className=\"flex-1 flex flex-col gap-0.5\">\n {title && (\n <div\n className={buildClassName(\n 'font-semibold text-sm leading-snug',\n variant === 'filled' ? 'text-white' : 'text-gray-900 dark:text-gray-100',\n )}\n >\n {title}\n </div>\n )}\n <div\n className={buildClassName(\n 'text-sm font-medium leading-relaxed',\n variant === 'filled' ? 'text-white/95' : 'text-gray-700 dark:text-gray-300',\n )}\n >\n {message}\n </div>\n\n {/* Action Button */}\n {action && (\n <div className=\"mt-1.5\">\n <button\n type=\"button\"\n onClick={action.onClick}\n className={buildClassName(\n 'text-xs font-semibold underline underline-offset-2 transition-opacity focus:outline-none',\n variant === 'filled'\n ? 'text-white hover:opacity-85'\n : 'text-[var(--ui-primary)] hover:opacity-80',\n )}\n >\n {action.label}\n </button>\n </div>\n )}\n </div>\n\n {/* Close button */}\n <Button\n onClick={onClose}\n aria-label=\"Close toast\"\n className={buildClassName(\n 'shrink-0 mt-0.5 opacity-60 hover:opacity-100 focus-visible:opacity-100 transition',\n variant === 'filled' && 'text-white hover:text-white focus-visible:outline-current',\n )}\n iconOnly\n size=\"xs\"\n variant=\"plain\"\n theme={variant === 'filled' ? 'primary' : 'secondary'}\n >\n <XIcon className=\"size-4\" />\n </Button>\n\n {/* Progress Bar Countdown */}\n {showProgressBar && duration > 0 && (\n <div className=\"absolute bottom-0 left-0 right-0 h-1 bg-black/10 dark:bg-white/10 overflow-hidden\">\n <div\n className={buildClassName(\n 'h-full transition-all duration-75 ease-linear',\n variant === 'filled' ? 'bg-white/70' : progressBarColorMap[type],\n )}\n style={{ width: `${Math.max(0, progress)}%` }}\n />\n </div>\n )}\n </div>\n </Transition>\n )\n}\n\nToast.displayName = 'Toast'\n"],"names":["_jsx","CheckCircle","AlertCircle","Info","AlertTriangle","_jsxs","XIcon"],"mappings":"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"}
1
+ {"version":3,"file":"Toast.js","sources":["../../../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react'\nimport { Transition } from '@headlessui/react'\nimport XIcon from '../Icons/X.svg'\nimport CheckCircle from '../Icons/CircleCheck.svg'\nimport AlertCircle from '../Icons/CircleAlert.svg'\nimport Info from '../Icons/Info.svg'\nimport AlertTriangle from '../Icons/TriangleAlert.svg'\n\nimport { Button } from '../Button'\nimport { TextContent } from '../TextContent'\nimport { buildClassName } from '../../utils/build-classname'\n\nimport type { ToastProps, ToastType, ToastVariant } from './Toast.types'\n\n/**\n * Icons for each toast type\n */\nconst iconMap: Record<ToastType, React.ReactNode> = {\n success: <CheckCircle className=\"size-5 text-[var(--ui-success)]\" />,\n error: <AlertCircle className=\"size-5 text-[var(--ui-danger)]\" />,\n info: <Info className=\"size-5 text-[var(--ui-info)]\" />,\n warning: <AlertTriangle className=\"size-5 text-[var(--ui-warning)]\" />,\n}\n\nconst filledIconMap: Record<ToastType, React.ReactNode> = {\n success: <CheckCircle className=\"size-5 text-white\" />,\n error: <AlertCircle className=\"size-5 text-white\" />,\n info: <Info className=\"size-5 text-white\" />,\n warning: <AlertTriangle className=\"size-5 text-white\" />,\n}\n\nconst textColorMap: Record<ToastType, string> = {\n success: 'text-[var(--ui-success-text)]',\n error: 'text-[var(--ui-danger-text)]',\n info: 'text-[var(--ui-info-text)]',\n warning: 'text-[var(--ui-warning-text)]',\n}\n\nconst progressBarColorMap: Record<ToastType, string> = {\n success: 'bg-[var(--ui-success)]',\n error: 'bg-[var(--ui-danger)]',\n info: 'bg-[var(--ui-info)]',\n warning: 'bg-[var(--ui-warning)]',\n}\n\nconst variantStyleMap: Record<ToastVariant, Record<ToastType, string>> = {\n accent: {\n success:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-success)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n error:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-danger)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n info: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-info)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n warning:\n 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-warning)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',\n },\n filled: {\n success: 'bg-[var(--ui-success)] text-white shadow-lg',\n error: 'bg-[var(--ui-danger)] text-white shadow-lg',\n info: 'bg-[var(--ui-info)] text-white shadow-lg',\n warning: 'bg-[var(--ui-warning)] text-white shadow-lg',\n },\n outlined: {\n success:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-success)] text-gray-900 dark:text-gray-100 shadow-md',\n error:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-danger)] text-gray-900 dark:text-gray-100 shadow-md',\n info: 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-info)] text-gray-900 dark:text-gray-100 shadow-md',\n warning:\n 'bg-white dark:bg-gray-900 border-2 border-[var(--ui-warning)] text-gray-900 dark:text-gray-100 shadow-md',\n },\n glass: {\n success:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-emerald-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n error:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-rose-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n info: 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-blue-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n warning:\n 'backdrop-blur-md bg-white/85 dark:bg-gray-900/85 border border-amber-500/30 text-gray-900 dark:text-gray-100 shadow-xl',\n },\n}\n\nexport const Toast: React.FC<ToastProps & { isTop?: boolean }> = ({\n id,\n title,\n message,\n type,\n variant = 'accent',\n action,\n icon,\n showProgressBar = true,\n duration = 4000,\n isPaused = false,\n onClose,\n className,\n isTop = true,\n}) => {\n const [progress, setProgress] = useState(100)\n\n useEffect(() => {\n if (!showProgressBar || !duration || isPaused) return\n\n const intervalTime = 50\n const step = (intervalTime / duration) * 100\n\n const timer = setInterval(() => {\n setProgress((prev) => {\n if (prev <= 0) {\n clearInterval(timer)\n return 0\n }\n return prev - step\n })\n }, intervalTime)\n\n return () => clearInterval(timer)\n }, [showProgressBar, duration, isPaused])\n\n const enterFrom = isTop ? 'opacity-0 -translate-y-3 scale-95' : 'opacity-0 translate-y-3 scale-95'\n const leaveTo = isTop ? 'opacity-0 -translate-y-2 scale-95' : 'opacity-0 translate-y-2 scale-95'\n\n const renderedIcon = icon ?? (variant === 'filled' ? filledIconMap[type] : iconMap[type])\n\n return (\n <Transition\n appear\n show\n enter=\"transform transition duration-300 ease-out\"\n enterFrom={enterFrom}\n enterTo=\"opacity-100 translate-y-0 scale-100\"\n leave=\"transition duration-200 ease-in\"\n leaveFrom=\"opacity-100 translate-y-0 scale-100\"\n leaveTo={leaveTo}\n >\n <div\n role=\"status\"\n id={id.toString()}\n className={buildClassName(\n // Never wider than the viewport minus a 16px gutter each side.\n 'relative overflow-hidden flex items-start gap-3 rounded-xl px-4 py-3.5 min-w-[min(280px,calc(100vw-2rem))] max-w-[min(28rem,calc(100vw-2rem))] transition-all',\n variantStyleMap[variant][type],\n className,\n )}\n >\n {/* Icon */}\n <div className=\"shrink-0 mt-0.5\">\n {variant === 'filled' ? (\n renderedIcon\n ) : (\n <TextContent className={buildClassName(textColorMap[type])}>{renderedIcon}</TextContent>\n )}\n </div>\n\n {/* Content Body */}\n <div className=\"flex-1 flex flex-col gap-0.5\">\n {title && (\n <div\n className={buildClassName(\n 'font-semibold text-sm leading-snug',\n variant === 'filled' ? 'text-white' : 'text-gray-900 dark:text-gray-100',\n )}\n >\n {title}\n </div>\n )}\n <div\n className={buildClassName(\n 'text-sm font-medium leading-relaxed',\n variant === 'filled' ? 'text-white/95' : 'text-gray-700 dark:text-gray-300',\n )}\n >\n {message}\n </div>\n\n {/* Action Button */}\n {action && (\n <div className=\"mt-1.5\">\n <button\n type=\"button\"\n onClick={action.onClick}\n className={buildClassName(\n 'text-xs font-semibold underline underline-offset-2 transition-opacity focus:outline-none',\n variant === 'filled'\n ? 'text-white hover:opacity-85'\n : 'text-[var(--ui-primary)] hover:opacity-80',\n )}\n >\n {action.label}\n </button>\n </div>\n )}\n </div>\n\n {/* Close button */}\n <Button\n onClick={onClose}\n aria-label=\"Close toast\"\n className={buildClassName(\n 'shrink-0 mt-0.5 opacity-60 hover:opacity-100 focus-visible:opacity-100 transition',\n variant === 'filled' && 'text-white hover:text-white focus-visible:outline-current',\n )}\n iconOnly\n size=\"xs\"\n variant=\"plain\"\n theme={variant === 'filled' ? 'primary' : 'secondary'}\n >\n <XIcon className=\"size-4\" />\n </Button>\n\n {/* Progress Bar Countdown */}\n {showProgressBar && duration > 0 && (\n <div className=\"absolute bottom-0 left-0 right-0 h-1 bg-black/10 dark:bg-white/10 overflow-hidden\">\n <div\n className={buildClassName(\n 'h-full transition-all duration-75 ease-linear',\n variant === 'filled' ? 'bg-white/70' : progressBarColorMap[type],\n )}\n style={{ width: `${Math.max(0, progress)}%` }}\n />\n </div>\n )}\n </div>\n </Transition>\n )\n}\n\nToast.displayName = 'Toast'\n"],"names":["_jsx","CheckCircle","AlertCircle","Info","AlertTriangle","_jsxs","XIcon"],"mappings":"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"}
@@ -2,6 +2,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { createContext, useContext, useState, useRef, useCallback, useEffect, useMemo } from 'react';
3
3
  import { Toast } from './Toast.js';
4
4
  import { buildClassName } from '../../utils/build-classname.js';
5
+ import { useResponsiveValue } from '../../hooks/use-breakpoint.js';
5
6
 
6
7
  const ToastContext = createContext(undefined);
7
8
  let toastCounter = 0;
@@ -15,11 +16,15 @@ const placementClass = {
15
16
  'top-right': 'top-20 right-6 items-end',
16
17
  'top-left': 'top-20 left-6 items-start',
17
18
  'top-center': 'top-20 left-1/2 -translate-x-1/2 items-center',
18
- 'bottom-right': 'bottom-6 right-6 items-end',
19
- 'bottom-left': 'bottom-6 left-6 items-start',
20
- 'bottom-center': 'bottom-6 left-1/2 -translate-x-1/2 items-center',
19
+ // Bottom placements clear the home indicator on notched phones (0 elsewhere).
20
+ 'bottom-right': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] right-6 items-end',
21
+ 'bottom-left': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-6 items-start',
22
+ 'bottom-center': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-1/2 -translate-x-1/2 items-center',
21
23
  };
22
- const ToastProvider = ({ children, placement = 'top-right', maxToasts = 5, className, }) => {
24
+ const ToastProvider = ({ children, placement: placementProp = 'top-right', maxToasts = 5, offset, className, }) => {
25
+ const placement = useResponsiveValue(placementProp);
26
+ const isTop = placement.startsWith('top');
27
+ const edgeOffset = isTop ? offset === null || offset === void 0 ? void 0 : offset.top : offset === null || offset === void 0 ? void 0 : offset.bottom;
23
28
  const [toasts, setToasts] = useState([]);
24
29
  const [pausedIds, setPausedIds] = useState(new Set());
25
30
  const metaRefs = useRef(new Map());
@@ -140,7 +145,7 @@ const ToastProvider = ({ children, placement = 'top-right', maxToasts = 5, class
140
145
  dismiss: (id) => closeToast(id),
141
146
  dismissAll: () => dismissAll(),
142
147
  }), [showToast, closeToast, dismissAll]);
143
- return (jsxs(ToastContext.Provider, { value: { showToast, closeToast, toast: toastHelpers }, children: [children, jsx("div", { className: buildClassName('fixed z-[9999] flex flex-col gap-3 pointer-events-none', placementClass[placement], className), children: toasts.map((toastItem) => (jsx("div", { className: "pointer-events-auto", onMouseEnter: () => handleMouseEnter(toastItem), onMouseLeave: () => handleMouseLeave(toastItem), children: jsx(Toast, { ...toastItem, isPaused: pausedIds.has(toastItem.id), isTop: placement.startsWith('top'), onClose: () => closeToast(toastItem.id) }) }, toastItem.id))) })] }));
148
+ return (jsxs(ToastContext.Provider, { value: { showToast, closeToast, toast: toastHelpers }, children: [children, jsx("div", { className: buildClassName('fixed z-[9999] flex flex-col gap-3 pointer-events-none', placementClass[placement], className), style: edgeOffset ? (isTop ? { top: edgeOffset } : { bottom: edgeOffset }) : undefined, "data-testid": "toast-container", "data-placement": placement, children: toasts.map((toastItem) => (jsx("div", { className: "pointer-events-auto", onMouseEnter: () => handleMouseEnter(toastItem), onMouseLeave: () => handleMouseLeave(toastItem), children: jsx(Toast, { ...toastItem, isPaused: pausedIds.has(toastItem.id), isTop: isTop, onClose: () => closeToast(toastItem.id) }) }, toastItem.id))) })] }));
144
149
  };
145
150
  ToastProvider.displayName = 'ToastProvider';
146
151
 
@@ -1 +1 @@
1
- {"version":3,"file":"ToastProvider.js","sources":["../../../../../src/components/Toast/ToastProvider.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n useRef,\n useCallback,\n useMemo,\n} from 'react'\nimport { Toast } from './Toast'\nimport type {\n IToast,\n ToastContextType,\n ToastOptions,\n ToastPlacement,\n ToastProviderProps,\n} from './Toast.types'\nimport { buildClassName } from '../../utils/build-classname'\n\nconst ToastContext = createContext<ToastContextType | undefined>(undefined)\nlet toastCounter = 0\n\nexport const useToast = (): ToastContextType => {\n const context = useContext(ToastContext)\n if (!context) throw new Error('useToast must be used within ToastProvider')\n return context\n}\n\nconst placementClass: Record<ToastPlacement, string> = {\n 'top-right': 'top-20 right-6 items-end',\n 'top-left': 'top-20 left-6 items-start',\n 'top-center': 'top-20 left-1/2 -translate-x-1/2 items-center',\n\n 'bottom-right': 'bottom-6 right-6 items-end',\n 'bottom-left': 'bottom-6 left-6 items-start',\n 'bottom-center': 'bottom-6 left-1/2 -translate-x-1/2 items-center',\n}\n\ninterface ToastMeta {\n timerId: any\n startTime: number\n remainingTime: number\n}\n\nexport const ToastProvider: React.FC<ToastProviderProps> = ({\n children,\n placement = 'top-right',\n maxToasts = 5,\n className,\n}) => {\n const [toasts, setToasts] = useState<IToast[]>([])\n const [pausedIds, setPausedIds] = useState<Set<number>>(new Set())\n const metaRefs = useRef<Map<number, ToastMeta>>(new Map())\n\n const clearTimer = (id: number) => {\n const meta = metaRefs.current.get(id)\n if (meta?.timerId) {\n clearTimeout(meta.timerId)\n meta.timerId = null\n }\n }\n\n const closeToast = useCallback((id: number) => {\n clearTimer(id)\n metaRefs.current.delete(id)\n setPausedIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n setToasts((prev) => prev.filter((t) => t.id !== id))\n }, [])\n\n const dismissAll = useCallback(() => {\n metaRefs.current.forEach((meta) => {\n if (meta.timerId) clearTimeout(meta.timerId)\n })\n metaRefs.current.clear()\n setPausedIds(new Set())\n setToasts([])\n }, [])\n\n const startAutoClose = useCallback(\n (toastId: number, delay: number) => {\n clearTimer(toastId)\n\n const timerId = setTimeout(() => {\n closeToast(toastId)\n }, delay)\n\n const meta = metaRefs.current.get(toastId)\n if (meta) {\n meta.timerId = timerId\n meta.startTime = Date.now()\n meta.remainingTime = delay\n } else {\n metaRefs.current.set(toastId, {\n timerId,\n startTime: Date.now(),\n remainingTime: delay,\n })\n }\n },\n [closeToast],\n )\n\n useEffect(() => {\n const refs = metaRefs.current\n return () =>\n refs.forEach((meta) => {\n if (meta.timerId) clearTimeout(meta.timerId)\n })\n }, [])\n\n const showToast = useCallback(\n (message: ReactNode, options?: ToastOptions): number => {\n const id = ++toastCounter\n\n const newToast: IToast = {\n id,\n title: options?.title,\n message,\n type: options?.type ?? 'info',\n variant: options?.variant ?? 'accent',\n duration: options?.duration ?? 4000,\n autoClose: options?.autoClose ?? true,\n pauseOnHover: options?.pauseOnHover ?? true,\n showProgressBar: options?.showProgressBar ?? options?.autoClose !== false,\n action: options?.action,\n icon: options?.icon,\n }\n\n setToasts((prev) => {\n const updated = [...prev, newToast]\n if (updated.length > maxToasts) updated.shift()\n return updated\n })\n\n if (newToast.autoClose) {\n startAutoClose(id, newToast.duration)\n }\n\n return id\n },\n [maxToasts, startAutoClose],\n )\n\n // Hover pauses timer and tracks exact remaining milliseconds\n const handleMouseEnter = (toast: IToast) => {\n if (!toast.pauseOnHover || !toast.autoClose) return\n\n const meta = metaRefs.current.get(toast.id)\n if (meta) {\n const elapsed = Date.now() - meta.startTime\n meta.remainingTime = Math.max(0, meta.remainingTime - elapsed)\n clearTimer(toast.id)\n setPausedIds((prev) => new Set(prev).add(toast.id))\n }\n }\n\n // Mouse leave resumes timer with exact remaining milliseconds\n const handleMouseLeave = (toast: IToast) => {\n if (!toast.pauseOnHover || !toast.autoClose) return\n\n setPausedIds((prev) => {\n const next = new Set(prev)\n next.delete(toast.id)\n return next\n })\n\n const meta = metaRefs.current.get(toast.id)\n if (meta && meta.remainingTime > 0) {\n startAutoClose(toast.id, meta.remainingTime)\n } else if (meta && meta.remainingTime <= 0) {\n closeToast(toast.id)\n }\n }\n\n const toastHelpers = useMemo(\n () => ({\n show: (message: ReactNode, options?: ToastOptions) => showToast(message, options),\n success: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'success' }),\n error: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'error' }),\n info: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'info' }),\n warning: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'warning' }),\n dismiss: (id: number) => closeToast(id),\n dismissAll: () => dismissAll(),\n }),\n [showToast, closeToast, dismissAll],\n )\n\n return (\n <ToastContext.Provider value={{ showToast, closeToast, toast: toastHelpers }}>\n {children}\n\n {/* Toast Container */}\n <div\n className={buildClassName(\n 'fixed z-[9999] flex flex-col gap-3 pointer-events-none',\n placementClass[placement],\n className,\n )}\n >\n {toasts.map((toastItem) => (\n <div\n key={toastItem.id}\n className=\"pointer-events-auto\"\n onMouseEnter={() => handleMouseEnter(toastItem)}\n onMouseLeave={() => handleMouseLeave(toastItem)}\n >\n <Toast\n {...toastItem}\n isPaused={pausedIds.has(toastItem.id)}\n isTop={placement.startsWith('top')}\n onClose={() => closeToast(toastItem.id)}\n />\n </div>\n ))}\n </div>\n </ToastContext.Provider>\n )\n}\n\nToastProvider.displayName = 'ToastProvider'\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"ToastProvider.js","sources":["../../../../../src/components/Toast/ToastProvider.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n useRef,\n useCallback,\n useMemo,\n} from 'react'\nimport { Toast } from './Toast'\nimport type {\n IToast,\n ToastContextType,\n ToastOptions,\n ToastPlacement,\n ToastProviderProps,\n} from './Toast.types'\nimport { buildClassName } from '../../utils/build-classname'\nimport { useResponsiveValue } from '../../hooks/use-breakpoint'\n\nconst ToastContext = createContext<ToastContextType | undefined>(undefined)\nlet toastCounter = 0\n\nexport const useToast = (): ToastContextType => {\n const context = useContext(ToastContext)\n if (!context) throw new Error('useToast must be used within ToastProvider')\n return context\n}\n\nconst placementClass: Record<ToastPlacement, string> = {\n 'top-right': 'top-20 right-6 items-end',\n 'top-left': 'top-20 left-6 items-start',\n 'top-center': 'top-20 left-1/2 -translate-x-1/2 items-center',\n\n // Bottom placements clear the home indicator on notched phones (0 elsewhere).\n 'bottom-right': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] right-6 items-end',\n 'bottom-left': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-6 items-start',\n 'bottom-center':\n 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-1/2 -translate-x-1/2 items-center',\n}\n\ninterface ToastMeta {\n timerId: any\n startTime: number\n remainingTime: number\n}\n\nexport const ToastProvider: React.FC<ToastProviderProps> = ({\n children,\n placement: placementProp = 'top-right',\n maxToasts = 5,\n offset,\n className,\n}) => {\n const placement = useResponsiveValue(placementProp)\n const isTop = placement.startsWith('top')\n const edgeOffset = isTop ? offset?.top : offset?.bottom\n const [toasts, setToasts] = useState<IToast[]>([])\n const [pausedIds, setPausedIds] = useState<Set<number>>(new Set())\n const metaRefs = useRef<Map<number, ToastMeta>>(new Map())\n\n const clearTimer = (id: number) => {\n const meta = metaRefs.current.get(id)\n if (meta?.timerId) {\n clearTimeout(meta.timerId)\n meta.timerId = null\n }\n }\n\n const closeToast = useCallback((id: number) => {\n clearTimer(id)\n metaRefs.current.delete(id)\n setPausedIds((prev) => {\n const next = new Set(prev)\n next.delete(id)\n return next\n })\n setToasts((prev) => prev.filter((t) => t.id !== id))\n }, [])\n\n const dismissAll = useCallback(() => {\n metaRefs.current.forEach((meta) => {\n if (meta.timerId) clearTimeout(meta.timerId)\n })\n metaRefs.current.clear()\n setPausedIds(new Set())\n setToasts([])\n }, [])\n\n const startAutoClose = useCallback(\n (toastId: number, delay: number) => {\n clearTimer(toastId)\n\n const timerId = setTimeout(() => {\n closeToast(toastId)\n }, delay)\n\n const meta = metaRefs.current.get(toastId)\n if (meta) {\n meta.timerId = timerId\n meta.startTime = Date.now()\n meta.remainingTime = delay\n } else {\n metaRefs.current.set(toastId, {\n timerId,\n startTime: Date.now(),\n remainingTime: delay,\n })\n }\n },\n [closeToast],\n )\n\n useEffect(() => {\n const refs = metaRefs.current\n return () =>\n refs.forEach((meta) => {\n if (meta.timerId) clearTimeout(meta.timerId)\n })\n }, [])\n\n const showToast = useCallback(\n (message: ReactNode, options?: ToastOptions): number => {\n const id = ++toastCounter\n\n const newToast: IToast = {\n id,\n title: options?.title,\n message,\n type: options?.type ?? 'info',\n variant: options?.variant ?? 'accent',\n duration: options?.duration ?? 4000,\n autoClose: options?.autoClose ?? true,\n pauseOnHover: options?.pauseOnHover ?? true,\n showProgressBar: options?.showProgressBar ?? options?.autoClose !== false,\n action: options?.action,\n icon: options?.icon,\n }\n\n setToasts((prev) => {\n const updated = [...prev, newToast]\n if (updated.length > maxToasts) updated.shift()\n return updated\n })\n\n if (newToast.autoClose) {\n startAutoClose(id, newToast.duration)\n }\n\n return id\n },\n [maxToasts, startAutoClose],\n )\n\n // Hover pauses timer and tracks exact remaining milliseconds\n const handleMouseEnter = (toast: IToast) => {\n if (!toast.pauseOnHover || !toast.autoClose) return\n\n const meta = metaRefs.current.get(toast.id)\n if (meta) {\n const elapsed = Date.now() - meta.startTime\n meta.remainingTime = Math.max(0, meta.remainingTime - elapsed)\n clearTimer(toast.id)\n setPausedIds((prev) => new Set(prev).add(toast.id))\n }\n }\n\n // Mouse leave resumes timer with exact remaining milliseconds\n const handleMouseLeave = (toast: IToast) => {\n if (!toast.pauseOnHover || !toast.autoClose) return\n\n setPausedIds((prev) => {\n const next = new Set(prev)\n next.delete(toast.id)\n return next\n })\n\n const meta = metaRefs.current.get(toast.id)\n if (meta && meta.remainingTime > 0) {\n startAutoClose(toast.id, meta.remainingTime)\n } else if (meta && meta.remainingTime <= 0) {\n closeToast(toast.id)\n }\n }\n\n const toastHelpers = useMemo(\n () => ({\n show: (message: ReactNode, options?: ToastOptions) => showToast(message, options),\n success: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'success' }),\n error: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'error' }),\n info: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'info' }),\n warning: (message: ReactNode, options?: ToastOptions) =>\n showToast(message, { ...options, type: 'warning' }),\n dismiss: (id: number) => closeToast(id),\n dismissAll: () => dismissAll(),\n }),\n [showToast, closeToast, dismissAll],\n )\n\n return (\n <ToastContext.Provider value={{ showToast, closeToast, toast: toastHelpers }}>\n {children}\n\n {/* Toast Container */}\n <div\n className={buildClassName(\n 'fixed z-[9999] flex flex-col gap-3 pointer-events-none',\n placementClass[placement],\n className,\n )}\n style={edgeOffset ? (isTop ? { top: edgeOffset } : { bottom: edgeOffset }) : undefined}\n data-testid=\"toast-container\"\n data-placement={placement}\n >\n {toasts.map((toastItem) => (\n <div\n key={toastItem.id}\n className=\"pointer-events-auto\"\n onMouseEnter={() => handleMouseEnter(toastItem)}\n onMouseLeave={() => handleMouseLeave(toastItem)}\n >\n <Toast\n {...toastItem}\n isPaused={pausedIds.has(toastItem.id)}\n isTop={isTop}\n onClose={() => closeToast(toastItem.id)}\n />\n </div>\n ))}\n </div>\n </ToastContext.Provider>\n )\n}\n\nToastProvider.displayName = 'ToastProvider'\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -4783,7 +4783,9 @@ const Toast = ({ id, title, message, type, variant = 'accent', action, icon, sho
4783
4783
  const enterFrom = isTop ? 'opacity-0 -translate-y-3 scale-95' : 'opacity-0 translate-y-3 scale-95';
4784
4784
  const leaveTo = isTop ? 'opacity-0 -translate-y-2 scale-95' : 'opacity-0 translate-y-2 scale-95';
4785
4785
  const renderedIcon = icon !== null && icon !== void 0 ? icon : (variant === 'filled' ? filledIconMap[type] : iconMap[type]);
4786
- return (jsxRuntime.jsx(react.Transition, { appear: true, show: true, enter: "transform transition duration-300 ease-out", enterFrom: enterFrom, enterTo: "opacity-100 translate-y-0 scale-100", leave: "transition duration-200 ease-in", leaveFrom: "opacity-100 translate-y-0 scale-100", leaveTo: leaveTo, children: jsxRuntime.jsxs("div", { role: "status", id: id.toString(), className: buildClassName('relative overflow-hidden flex items-start gap-3 rounded-xl px-4 py-3.5 min-w-[280px] max-w-md transition-all', variantStyleMap[variant][type], className), children: [jsxRuntime.jsx("div", { className: "shrink-0 mt-0.5", children: variant === 'filled' ? (renderedIcon) : (jsxRuntime.jsx(TextContent, { className: buildClassName(textColorMap[type]), children: renderedIcon })) }), jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [title && (jsxRuntime.jsx("div", { className: buildClassName('font-semibold text-sm leading-snug', variant === 'filled' ? 'text-white' : 'text-gray-900 dark:text-gray-100'), children: title })), jsxRuntime.jsx("div", { className: buildClassName('text-sm font-medium leading-relaxed', variant === 'filled' ? 'text-white/95' : 'text-gray-700 dark:text-gray-300'), children: message }), action && (jsxRuntime.jsx("div", { className: "mt-1.5", children: jsxRuntime.jsx("button", { type: "button", onClick: action.onClick, className: buildClassName('text-xs font-semibold underline underline-offset-2 transition-opacity focus:outline-none', variant === 'filled'
4786
+ return (jsxRuntime.jsx(react.Transition, { appear: true, show: true, enter: "transform transition duration-300 ease-out", enterFrom: enterFrom, enterTo: "opacity-100 translate-y-0 scale-100", leave: "transition duration-200 ease-in", leaveFrom: "opacity-100 translate-y-0 scale-100", leaveTo: leaveTo, children: jsxRuntime.jsxs("div", { role: "status", id: id.toString(), className: buildClassName(
4787
+ // Never wider than the viewport minus a 16px gutter each side.
4788
+ 'relative overflow-hidden flex items-start gap-3 rounded-xl px-4 py-3.5 min-w-[min(280px,calc(100vw-2rem))] max-w-[min(28rem,calc(100vw-2rem))] transition-all', variantStyleMap[variant][type], className), children: [jsxRuntime.jsx("div", { className: "shrink-0 mt-0.5", children: variant === 'filled' ? (renderedIcon) : (jsxRuntime.jsx(TextContent, { className: buildClassName(textColorMap[type]), children: renderedIcon })) }), jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [title && (jsxRuntime.jsx("div", { className: buildClassName('font-semibold text-sm leading-snug', variant === 'filled' ? 'text-white' : 'text-gray-900 dark:text-gray-100'), children: title })), jsxRuntime.jsx("div", { className: buildClassName('text-sm font-medium leading-relaxed', variant === 'filled' ? 'text-white/95' : 'text-gray-700 dark:text-gray-300'), children: message }), action && (jsxRuntime.jsx("div", { className: "mt-1.5", children: jsxRuntime.jsx("button", { type: "button", onClick: action.onClick, className: buildClassName('text-xs font-semibold underline underline-offset-2 transition-opacity focus:outline-none', variant === 'filled'
4787
4789
  ? 'text-white hover:opacity-85'
4788
4790
  : 'text-[var(--ui-primary)] hover:opacity-80'), children: action.label }) }))] }), jsxRuntime.jsx(Button, { onClick: onClose, "aria-label": "Close toast", className: buildClassName('shrink-0 mt-0.5 opacity-60 hover:opacity-100 focus-visible:opacity-100 transition', variant === 'filled' && 'text-white hover:text-white focus-visible:outline-current'), iconOnly: true, size: "xs", variant: "plain", theme: variant === 'filled' ? 'primary' : 'secondary', children: jsxRuntime.jsx(SvgX, { className: "size-4" }) }), showProgressBar && duration > 0 && (jsxRuntime.jsx("div", { className: "absolute bottom-0 left-0 right-0 h-1 bg-black/10 dark:bg-white/10 overflow-hidden", children: jsxRuntime.jsx("div", { className: buildClassName('h-full transition-all duration-75 ease-linear', variant === 'filled' ? 'bg-white/70' : progressBarColorMap[type]), style: { width: `${Math.max(0, progress)}%` } }) }))] }) }));
4789
4791
  };
@@ -4801,11 +4803,15 @@ const placementClass = {
4801
4803
  'top-right': 'top-20 right-6 items-end',
4802
4804
  'top-left': 'top-20 left-6 items-start',
4803
4805
  'top-center': 'top-20 left-1/2 -translate-x-1/2 items-center',
4804
- 'bottom-right': 'bottom-6 right-6 items-end',
4805
- 'bottom-left': 'bottom-6 left-6 items-start',
4806
- 'bottom-center': 'bottom-6 left-1/2 -translate-x-1/2 items-center',
4807
- };
4808
- const ToastProvider = ({ children, placement = 'top-right', maxToasts = 5, className, }) => {
4806
+ // Bottom placements clear the home indicator on notched phones (0 elsewhere).
4807
+ 'bottom-right': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] right-6 items-end',
4808
+ 'bottom-left': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-6 items-start',
4809
+ 'bottom-center': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-1/2 -translate-x-1/2 items-center',
4810
+ };
4811
+ const ToastProvider = ({ children, placement: placementProp = 'top-right', maxToasts = 5, offset, className, }) => {
4812
+ const placement = useResponsiveValue(placementProp);
4813
+ const isTop = placement.startsWith('top');
4814
+ const edgeOffset = isTop ? offset === null || offset === void 0 ? void 0 : offset.top : offset === null || offset === void 0 ? void 0 : offset.bottom;
4809
4815
  const [toasts, setToasts] = React.useState([]);
4810
4816
  const [pausedIds, setPausedIds] = React.useState(new Set());
4811
4817
  const metaRefs = React.useRef(new Map());
@@ -4926,7 +4932,7 @@ const ToastProvider = ({ children, placement = 'top-right', maxToasts = 5, class
4926
4932
  dismiss: (id) => closeToast(id),
4927
4933
  dismissAll: () => dismissAll(),
4928
4934
  }), [showToast, closeToast, dismissAll]);
4929
- return (jsxRuntime.jsxs(ToastContext.Provider, { value: { showToast, closeToast, toast: toastHelpers }, children: [children, jsxRuntime.jsx("div", { className: buildClassName('fixed z-[9999] flex flex-col gap-3 pointer-events-none', placementClass[placement], className), children: toasts.map((toastItem) => (jsxRuntime.jsx("div", { className: "pointer-events-auto", onMouseEnter: () => handleMouseEnter(toastItem), onMouseLeave: () => handleMouseLeave(toastItem), children: jsxRuntime.jsx(Toast, { ...toastItem, isPaused: pausedIds.has(toastItem.id), isTop: placement.startsWith('top'), onClose: () => closeToast(toastItem.id) }) }, toastItem.id))) })] }));
4935
+ return (jsxRuntime.jsxs(ToastContext.Provider, { value: { showToast, closeToast, toast: toastHelpers }, children: [children, jsxRuntime.jsx("div", { className: buildClassName('fixed z-[9999] flex flex-col gap-3 pointer-events-none', placementClass[placement], className), style: edgeOffset ? (isTop ? { top: edgeOffset } : { bottom: edgeOffset }) : undefined, "data-testid": "toast-container", "data-placement": placement, children: toasts.map((toastItem) => (jsxRuntime.jsx("div", { className: "pointer-events-auto", onMouseEnter: () => handleMouseEnter(toastItem), onMouseLeave: () => handleMouseLeave(toastItem), children: jsxRuntime.jsx(Toast, { ...toastItem, isPaused: pausedIds.has(toastItem.id), isTop: isTop, onClose: () => closeToast(toastItem.id) }) }, toastItem.id))) })] }));
4930
4936
  };
4931
4937
  ToastProvider.displayName = 'ToastProvider';
4932
4938