UNPKG

aura-glass

Version:

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

348 lines (345 loc) 11.7 kB
'use client'; import { jsxs, jsx } from 'react/jsx-runtime'; import { forwardRef, useState } from 'react'; import { GlassButton, IconButton } from '../../button/GlassButton.js'; import '../../button/GlassFab.js'; import '../../button/GlassMagneticButton.js'; import { cn } from '../../../lib/utilsComprehensive.js'; import { GlassCard } from '../../card/GlassCard.js'; import '../../data-display/GlassAccordion.js'; import '../../data-display/GlassAlert.js'; import '../../data-display/GlassAvatar.js'; import { GlassBadge } from '../../data-display/GlassBadge.js'; import '../../data-display/GlassBadgeLine.js'; import '../../data-display/GlassDataGrid.js'; import '../../data-display/GlassDataTable.js'; import '../../../primitives/GlassCore.js'; import '../../../primitives/glass/GlassAdvanced.js'; import '../../../primitives/OptimizedGlassCore.js'; import '../../../primitives/glass/OptimizedGlassAdvanced.js'; import '../../../primitives/MotionNative.js'; import { MotionFramer } from '../../../primitives/motion/MotionFramer.js'; import '../../data-display/GlassHeatmap.js'; import '../../data-display/GlassLoadingSkeleton.js'; import '../../data-display/GlassProgress.js'; import '../../data-display/GlassTimeline.js'; import 'lucide-react'; import '../../data-display/GlassSkeleton.js'; import '../../data-display/GlassNotificationCenter.js'; import '../../data-display/GlassAnimatedNumber.js'; import '../../layout/GlassBox.js'; import '../../layout/GlassContainer.js'; import '../../layout/GlassFlex.js'; import { GlassGrid, GlassGridItem } from '../../layout/GlassGrid.js'; import '../../layout/GlassMasonry.js'; import '../../layout/GlassScrollArea.js'; import '../../layout/GlassSplitPane.js'; import { VStack, HStack } from '../../layout/GlassStack.js'; import '../../layout/OptimizedGlassContainer.js'; import '../../layout/Box.js'; /** * GlassDetailView component * Comprehensive detail view with multiple layout options */ const GlassDetailView = /*#__PURE__*/forwardRef(({ title, subtitle, status, breadcrumb, actions = [], sections = [], tabs = [], activeTab, onTabChange, layout = "default", sidebar, loading = false, error, onBack, onShare, onPrint, className, children, ...props }, ref) => { const [expandedSections, setExpandedSections] = useState(new Set(sections.filter(s => s.defaultExpanded !== false).map(s => s.id))); const [currentTab, setCurrentTab] = useState(activeTab || tabs[0]?.id); // Toggle section expansion const toggleSection = sectionId => { const newExpanded = new Set(expandedSections); if (newExpanded.has(sectionId)) { newExpanded.delete(sectionId); } else { newExpanded.add(sectionId); } setExpandedSections(newExpanded); }; // Handle tab change const handleTabChange = tabId => { setCurrentTab(tabId); onTabChange?.(tabId); }; // Render field value const renderFieldValue = field => { if (field.render) { return field.render(field.value); } switch (field.type) { case "boolean": return jsx(GlassBadge, { "data-glass-component": true, variant: field.value ? "success" : "error", size: "xs", children: field.value ? "Yes" : "No" }); case "badge": return jsx(GlassBadge, { variant: "outline", size: "xs", children: field.value }); case "link": return jsx("a", { href: field.value, target: "_blank", rel: "noopener noreferrer", className: 'text-primary hover:underline glass-focus glass-touch-target glass-contrast-guard', children: field.value }); case "date": return new Date(field.value).toLocaleDateString(); case "number": return typeof field.value === "number" ? field.value.toLocaleString() : field.value; default: return field.value; } }; // Render field const renderField = field => { const widthClasses = { auto: "w-auto", full: "w-full", half: "w-1/2", third: "w-1/3", quarter: "w-1/4" }; return jsxs("div", { className: cn("glass-auto-gap glass-auto-gap-xs", widthClasses[field.width || "auto"]), children: [jsx("label", { className: 'glass-text-sm font-medium glass-text-secondary', children: field.label }), jsxs(HStack, { space: "sm", align: "center", children: [jsx("div", { className: 'glass-text-sm text-primary', children: renderFieldValue(field) }), field.copyable && jsx(IconButton, { icon: "\uD83D\uDCCB", variant: "ghost", size: "xs", onClick: e => navigator.clipboard?.writeText(String(field.value)), "aria-label": "Copy to clipboard", className: "glass-focus glass-touch-target" })] })] }, field.id); }; // Render section const renderSection = section => { const isExpanded = expandedSections.has(section.id); return jsx(MotionFramer, { type: "slide", direction: "down", children: jsxs(GlassCard, { variant: "default", children: [jsxs("div", { className: cn("flex items-center justify-between", section.collapsible && "cursor-pointer glass-focus glass-touch-target"), onClick: section.collapsible ? () => toggleSection(section.id) : undefined, children: [jsxs(VStack, { space: "xs", children: [jsx("h3", { className: 'glass-text-lg font-semibold text-primary', children: section.title }), section.description && jsx("p", { className: "glass-text-sm glass-text-secondary", children: section.description })] }), section.collapsible && jsx(GlassButton, { leftIcon: isExpanded ? "−" : "+", variant: "ghost", size: "sm", "aria-label": isExpanded ? "Collapse section" : "Expand section" })] }), (!section.collapsible || isExpanded) && jsx(MotionFramer, { type: "slide", direction: "down", className: 'mt-6', children: section.component ? section.component : section.fields ? jsx("div", { className: 'glass-grid glass-grid-cols-1 md:grid-cols-2 lg:grid-cols-3 glass-gap-6', children: section.fields.map(renderField) }) : null })] }) }, section.id); }; // Render tabs const renderTabs = () => { if (tabs.length === 0) return null; return jsxs(VStack, { space: "md", children: [jsx("div", { className: "glass-border-b glass-border-glass-border/20", children: jsx("nav", { className: 'glass-flex space-x-8', children: tabs.map(tab => jsxs(GlassButton, { onClick: e => handleTabChange(tab.id), className: cn("flex items-center glass-gap-2 glass-py-2 glass-px-1 border-b-2 transition-colors glass-focus glass-touch-target", currentTab === tab.id ? "border-primary text-primary font-medium" : "border-transparent glass-text-secondary hover:text-foreground"), children: [tab.icon, jsx("span", { children: tab.label }), tab.badge && jsx(GlassBadge, { variant: "outline", size: "xs", children: tab.badge })] }, tab.id)) }) }), jsx("div", { children: tabs.find(tab => tab.id === currentTab)?.content })] }); }; // Render header const renderHeader = () => jsxs(VStack, { space: "md", children: [breadcrumb && jsx("div", { className: "glass-text-sm glass-text-secondary", children: breadcrumb }), jsxs(HStack, { space: "md", align: "center", justify: "between", children: [jsxs(HStack, { space: "md", align: "center", children: [onBack && jsx(GlassButton, { leftIcon: "\u2190", variant: "ghost", size: "sm", onClick: onBack, "aria-label": "Go back", className: "glass-focus glass-touch-target" }), jsxs(VStack, { space: "xs", children: [jsxs(HStack, { space: "sm", align: "center", children: [jsx("h1", { className: 'glass-text-2xl font-bold text-primary', children: title }), status && jsx(GlassBadge, { variant: status.variant, size: "sm", children: status.label })] }), subtitle && jsx("p", { className: "glass-text-lg glass-text-secondary", children: subtitle })] })] }), jsxs(HStack, { space: "sm", align: "center", children: [onShare && jsx(GlassButton, { leftIcon: "\uD83D\uDCE4", variant: "ghost", size: "sm", onClick: onShare, "aria-label": "Share", className: "glass-focus glass-touch-target" }), onPrint && jsx(GlassButton, { leftIcon: "\uD83D\uDDA8\uFE0F", variant: "ghost", size: "sm", onClick: onPrint, "aria-label": "Print", className: "glass-focus glass-touch-target" }), actions.map(action => jsx(GlassButton, { variant: action.variant, size: "sm", leftIcon: action.icon, onClick: action.onClick, disabled: action.disabled, loading: action.loading, className: "glass-focus glass-touch-target", children: action.label }, action.id))] })] })] }); // Render content based on layout const renderContent = () => { if (loading) { return jsx("div", { className: 'glass-flex glass-items-center glass-justify-center h-64', children: jsx("div", { className: 'w-8 h-8 glass-border-2 glass-border-primary glass-border-t-transparent glass-radius-full animate-spin' }) }); } if (error) { return jsxs(GlassCard, { variant: "default", className: 'glass-p-8 text-center', children: [jsx("div", { className: 'text-destructive font-medium mb-2', children: "Error" }), jsx("div", { className: "glass-text-secondary", children: error })] }); } switch (layout) { case "sidebar": return jsxs(GlassGrid, { cols: 12, gap: "lg", children: [jsx(GlassGridItem, { colSpan: 8, children: jsxs(VStack, { space: "lg", children: [tabs.length > 0 ? renderTabs() : sections.map(renderSection), children] }) }), jsx(GlassGridItem, { colSpan: 4, children: sidebar })] }); case "tabs": return renderTabs(); case "accordion": return jsxs(VStack, { space: "md", children: [sections.map(section => ({ ...section, collapsible: true })).map(renderSection), children] }); default: return jsxs(VStack, { space: "lg", children: [sections.map(renderSection), tabs.length > 0 && renderTabs(), children] }); } }; return jsxs("div", { ref: ref, className: cn("w-full glass-auto-gap glass-auto-gap-3xl", className), ...props, children: [renderHeader(), renderContent()] }); }); GlassDetailView.displayName = "GlassDetailView"; export { GlassDetailView }; //# sourceMappingURL=GlassDetailView.js.map