UNPKG

aura-glass

Version:

A comprehensive glassmorphism design system for React applications with 142+ production-ready components

151 lines (148 loc) 5.93 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { cn } from '../../lib/utilsComprehensive.js'; import React, { forwardRef, useRef, useEffect, useCallback } from 'react'; import '../../primitives/GlassCore.js'; import '../../primitives/glass/GlassAdvanced.js'; import { OptimizedGlassCore } from '../../primitives/OptimizedGlassCore.js'; import '../../primitives/glass/OptimizedGlassAdvanced.js'; import '../../primitives/MotionNative.js'; import '../../primitives/motion/MotionFramer.js'; import { createPortal } from 'react-dom'; const GlassActionSheet = /*#__PURE__*/forwardRef(({ open, onClose, title, message, actions, showCancel = true, cancelText = "Cancel", elevation = "level4", closeOnBackdrop = true, animationDuration = 300, className, ...props }, ref) => { const [isVisible, setIsVisible] = React.useState(false); const [isAnimating, setIsAnimating] = React.useState(false); const sheetRef = useRef(null); const startYRef = useRef(0); const currentYRef = useRef(0); useEffect(() => { if (open) { setIsVisible(true); setTimeout(() => setIsAnimating(true), 10); } else { setIsAnimating(false); setTimeout(() => setIsVisible(false), animationDuration); } }, [open, animationDuration]); useEffect(() => { if (!isVisible) return; const handleEscape = e => { if (e.key === "Escape") { onClose(); } }; document.addEventListener("keydown", handleEscape); document.body.style.overflow = "hidden"; return () => { document.removeEventListener("keydown", handleEscape); document.body.style.overflow = ""; }; }, [isVisible, onClose]); const handleBackdropClick = useCallback(() => { if (closeOnBackdrop) { onClose(); } }, [closeOnBackdrop, onClose]); const handleActionClick = useCallback(action => { if (action.disabled) return; action.onAction(); onClose(); }, [onClose]); const handleTouchStart = useCallback(e => { startYRef.current = e.touches[0].clientY; currentYRef.current = 0; }, []); const handleTouchMove = useCallback(e => { const deltaY = e.touches[0].clientY - startYRef.current; if (deltaY > 0) { currentYRef.current = deltaY; if (sheetRef.current) { sheetRef.current.style.transform = `translateY(${deltaY}px)`; } } }, []); const handleTouchEnd = useCallback(() => { if (currentYRef.current > 100) { onClose(); } else if (sheetRef.current) { sheetRef.current.style.transform = ""; } currentYRef.current = 0; }, [onClose]); if (!isVisible) return null; const content = jsx("div", { className: cn("fixed inset-0 z-50 flex items-end justify-center", "transition-colors duration-300", isAnimating ? "bg-black/40" : "bg-black/0"), onClick: handleBackdropClick, role: "presentation", children: jsxs("div", { ref: sheetRef, onClick: e => e.stopPropagation(), onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, className: cn("w-full max-w-2xl mx-auto glass-p-4 pb-safe", "transition-transform duration-300 ease-out", isAnimating ? "translate-y-0" : "translate-y-full"), role: "dialog", "aria-modal": "true", "aria-labelledby": title ? "action-sheet-title" : undefined, "aria-describedby": message ? "action-sheet-message" : undefined, children: [jsxs(OptimizedGlassCore, { ref: ref, elevation: elevation, className: cn("overflow-hidden glass-radius-2xl", className), ...props, children: [(title || message) && jsxs("div", { className: 'glass-p-4 text-center glass-border-b glass-border-subtle', children: [title && jsx("h3", { id: "action-sheet-title", className: 'glass-text-lg font-semibold glass-text-primary mb-1', children: title }), message && jsx("p", { id: "action-sheet-message", className: "glass-text-sm glass-text-secondary", children: message })] }), jsx("div", { className: 'max-h-96 overflow-y-auto', children: actions.map((action, index) => jsxs("button", { onClick: () => handleActionClick(action), disabled: action.disabled, className: cn("w-full glass-p-4 flex items-center justify-center gap-3", "glass-text-base font-medium", "transition-all duration-200", "border-b glass-border-subtle last:border-b-0", "hover:bg-white/5 active:bg-white/10", "disabled:opacity-50 disabled:cursor-not-allowed", action.variant === "destructive" && "text-red-500", action.variant === "primary" && "text-blue-500 font-semibold", action.variant === "default" && "glass-text-primary", !action.disabled && "glass-focus glass-touch-target glass-contrast-guard"), type: "button", children: [action.icon && jsx("span", { className: "glass-flex-shrink-0", children: action.icon }), jsx("span", { children: action.label })] }, index)) })] }), showCancel && jsx(OptimizedGlassCore, { elevation: elevation, className: 'mt-2 overflow-hidden glass-radius-2xl', children: jsx("button", { onClick: onClose, className: cn("w-full glass-p-4 flex items-center justify-center", "glass-text-base font-semibold glass-text-primary", "transition-all duration-200", "hover:bg-white/5 active:bg-white/10", "glass-focus glass-touch-target glass-contrast-guard"), type: "button", children: cancelText }) })] }) }); return /*#__PURE__*/createPortal(content, document.body); }); GlassActionSheet.displayName = "GlassActionSheet"; export { GlassActionSheet, GlassActionSheet as default }; //# sourceMappingURL=GlassActionSheet.js.map