@pk-design/react-tailwind 1.10.3 → 1.11.1

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.
@@ -4448,9 +4448,13 @@ const SegmentedControl = forwardRef((props, ref) => {
4448
4448
  if (!isOptionDisabled) {
4449
4449
  onChange(option.value);
4450
4450
  }
4451
- }, onKeyDown: (e) => handleKeyDown(e, index), className: buildClassName('inline-flex items-center justify-center gap-1.5 transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary-ring)]', SIZE_OPTION_CLASS[size], fullWidth ? 'flex-1' : '', isOptionDisabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer', isSelected
4451
+ }, onKeyDown: (e) => handleKeyDown(e, index), className: buildClassName('inline-flex items-center justify-center gap-1.5 transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary-ring)]', SIZE_OPTION_CLASS[size],
4452
+ // Full width splits the row equally, so the width comes from the
4453
+ // row, not padding; tight side padding keeps labels on one line
4454
+ // on narrow screens.
4455
+ fullWidth ? 'min-w-0 flex-1 px-1.5' : '', isOptionDisabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer', isSelected
4452
4456
  ? 'bg-white text-[var(--ui-primary)] dark:bg-gray-700 dark:text-blue-400 shadow-xs font-semibold'
4453
- : 'text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100'), "data-testid": `segmented-option-${option.value}`, children: [option.icon && (jsx("span", { className: buildClassName('shrink-0 inline-flex items-center justify-center', SIZE_ICON_CLASS[size]), children: option.icon })), jsx("span", { children: option.label })] }, option.value));
4457
+ : 'text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100'), "data-testid": `segmented-option-${option.value}`, children: [option.icon && (jsx("span", { className: buildClassName('shrink-0 inline-flex items-center justify-center', SIZE_ICON_CLASS[size]), children: option.icon })), jsx("span", { className: "min-w-0 truncate", children: option.label })] }, option.value));
4454
4458
  }) }));
4455
4459
  });
4456
4460
  SegmentedControl.displayName = 'SegmentedControl';
@@ -4763,7 +4767,9 @@ const Toast = ({ id, title, message, type, variant = 'accent', action, icon, sho
4763
4767
  const enterFrom = isTop ? 'opacity-0 -translate-y-3 scale-95' : 'opacity-0 translate-y-3 scale-95';
4764
4768
  const leaveTo = isTop ? 'opacity-0 -translate-y-2 scale-95' : 'opacity-0 translate-y-2 scale-95';
4765
4769
  const renderedIcon = icon !== null && icon !== void 0 ? icon : (variant === 'filled' ? filledIconMap[type] : iconMap[type]);
4766
- 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'
4770
+ 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(
4771
+ // Never wider than the viewport minus a 16px gutter each side.
4772
+ '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'
4767
4773
  ? 'text-white hover:opacity-85'
4768
4774
  : '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)}%` } }) }))] }) }));
4769
4775
  };
@@ -4781,11 +4787,15 @@ const placementClass = {
4781
4787
  'top-right': 'top-20 right-6 items-end',
4782
4788
  'top-left': 'top-20 left-6 items-start',
4783
4789
  'top-center': 'top-20 left-1/2 -translate-x-1/2 items-center',
4784
- 'bottom-right': 'bottom-6 right-6 items-end',
4785
- 'bottom-left': 'bottom-6 left-6 items-start',
4786
- 'bottom-center': 'bottom-6 left-1/2 -translate-x-1/2 items-center',
4787
- };
4788
- const ToastProvider = ({ children, placement = 'top-right', maxToasts = 5, className, }) => {
4790
+ // Bottom placements clear the home indicator on notched phones (0 elsewhere).
4791
+ 'bottom-right': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] right-6 items-end',
4792
+ 'bottom-left': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-6 items-start',
4793
+ 'bottom-center': 'bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-1/2 -translate-x-1/2 items-center',
4794
+ };
4795
+ const ToastProvider = ({ children, placement: placementProp = 'top-right', maxToasts = 5, offset, className, }) => {
4796
+ const placement = useResponsiveValue(placementProp);
4797
+ const isTop = placement.startsWith('top');
4798
+ const edgeOffset = isTop ? offset === null || offset === void 0 ? void 0 : offset.top : offset === null || offset === void 0 ? void 0 : offset.bottom;
4789
4799
  const [toasts, setToasts] = useState([]);
4790
4800
  const [pausedIds, setPausedIds] = useState(new Set());
4791
4801
  const metaRefs = useRef(new Map());
@@ -4906,7 +4916,7 @@ const ToastProvider = ({ children, placement = 'top-right', maxToasts = 5, class
4906
4916
  dismiss: (id) => closeToast(id),
4907
4917
  dismissAll: () => dismissAll(),
4908
4918
  }), [showToast, closeToast, dismissAll]);
4909
- 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))) })] }));
4919
+ 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))) })] }));
4910
4920
  };
4911
4921
  ToastProvider.displayName = 'ToastProvider';
4912
4922