aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
291 lines (288 loc) • 11.9 kB
JavaScript
'use client';
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import { cn } from '../../lib/utilsComprehensive.js';
import { Palette, Settings, Check, Eye, Save, Sun, Moon, Monitor } from 'lucide-react';
import { useState, useCallback } from 'react';
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 { GlassButton } from '../button/GlassButton.js';
import '../button/GlassFab.js';
import '../button/GlassMagneticButton.js';
import { CardHeader, CardTitle, CardContent } from '../card/index.js';
import { GlassCard } from '../card/GlassCard.js';
/**
* GlassThemeSwitcher component
* Theme switching interface with preview and customization
*/
const GlassThemeSwitcher = ({
currentTheme = "light",
themes = [],
enableSystemTheme = true,
showPreview = true,
showCustomOption = false,
compact = false,
onThemeChange,
onCustomThemeSave,
className,
...props
}) => {
const customThemes = Array.isArray(themes) ? themes : [];
const [selectedTheme, setSelectedTheme] = useState(currentTheme);
const [showCustomizer, setShowCustomizer] = useState(false);
const [customColors, setCustomColors] = useState({
primary: "var(--glass-color-primary)",
secondary: "#64748b",
background: "var(--glass-white)",
text: "var(--glass-black)"
});
// System theme options
const systemThemes = [{
id: "light",
name: "Light",
icon: Sun,
preview: {
primary: "var(--glass-color-primary)",
secondary: "#64748b",
background: "var(--glass-white)",
text: "var(--glass-black)"
}
}, {
id: "dark",
name: "Dark",
icon: Moon,
preview: {
primary: "var(--glass-color-primary-light)",
secondary: "#94a3b8",
background: "#0f172a",
text: "var(--glass-white)"
}
}, ...(enableSystemTheme ? [{
id: "system",
name: "System",
icon: Monitor,
preview: {
primary: "#8b5cf6",
secondary: "#64748b",
background: "#f8fafc",
text: "#1e293b"
}
}] : [])];
// Handle theme selection
const handleThemeSelect = useCallback(themeId => {
setSelectedTheme(themeId);
onThemeChange?.(themeId);
}, [onThemeChange]);
// Handle custom color change
const handleCustomColorChange = useCallback((colorKey, value) => {
setCustomColors(prev => ({
...prev,
[colorKey]: value
}));
}, []);
// Save custom theme
const handleSaveCustomTheme = useCallback(() => {
onCustomThemeSave?.(customColors);
setShowCustomizer(false);
}, [customColors, onCustomThemeSave]);
// Get theme preview style
const getPreviewStyle = useCallback(preview => ({
backgroundColor: preview.background,
color: preview.text,
"--preview-primary": preview.primary,
"--preview-secondary": preview.secondary
}), []);
return jsx(MotionFramer, {
"data-glass-component": true,
preset: "fadeIn",
className: "glass-w-full",
children: jsxs(GlassCard, {
className: cn("overflow-hidden", className),
...props,
children: [jsx(CardHeader, {
className: 'pb-3',
children: jsxs("div", {
className: "glass-flex glass-items-center glass-justify-between",
children: [jsxs(CardTitle, {
className: 'text-primary glass-text-lg font-semibold glass-flex glass-items-center glass-gap-2',
children: [jsx(Palette, {
className: 'w-5 h-5'
}), "Theme"]
}), !compact && showCustomOption && jsx(GlassButton, {
variant: "ghost",
size: "sm",
onClick: e => setShowCustomizer(!showCustomizer),
className: "glass-p-2 glass-focus glass-touch-target glass-contrast-guard",
children: jsx(Settings, {
className: 'w-4 h-4'
})
})]
})
}), jsxs(CardContent, {
className: 'pt-0',
children: [jsx("div", {
className: cn("grid glass-gap-3 mb-6", compact ? "grid-cols-1" : "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3"),
children: systemThemes.map(theme => {
const IconComponent = theme.icon;
const isSelected = selectedTheme === theme.id;
return jsxs(MotionFramer, {
preset: "scaleIn",
className: cn("relative glass-p-4 glass-radius-lg cursor-pointer transition-all duration-200", "hover:scale-[1.02] hover:shadow-lg", "glass-focus glass-touch-target glass-contrast-guard", isSelected ? "ring-2 ring-primary bg-primary/20" : "ring-1 ring-white/10 bg-white/5 hover:ring-white/30"),
onClick: e => handleThemeSelect(theme.id),
children: [showPreview && jsx("div", {
className: 'glass-w-full h-16 glass-radius-md mb-3 ring-1 ring-white/10',
style: getPreviewStyle(theme.preview),
children: jsxs("div", {
className: "glass-p-2 glass-gap-1",
children: [jsx("div", {
className: 'h-2 glass-radius-md',
style: {
backgroundColor: "var(--preview-primary)"
}
}), jsx("div", {
className: 'h-1 glass-radius-md',
style: {
backgroundColor: "var(--preview-secondary)"
}
})]
})
}), jsxs("div", {
className: "glass-flex glass-items-center glass-justify-between",
children: [jsxs("div", {
className: "glass-flex glass-items-center glass-gap-2",
children: [jsx(IconComponent, {
className: 'w-4 h-4'
}), jsx("span", {
className: 'font-medium glass-text-sm',
children: theme.name
})]
}), isSelected && jsx(Check, {
className: 'w-4 h-4 text-primary'
})]
})]
}, theme.id);
})
}), customThemes.length > 0 && jsxs(Fragment, {
children: [jsx("div", {
className: 'mb-3',
children: jsx("h4", {
className: 'text-primary/80 glass-text-sm font-medium',
children: "Custom Themes"
})
}), jsx("div", {
className: cn("grid glass-gap-3", compact ? "grid-cols-1" : "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3"),
children: customThemes.map(theme => {
const isSelected = selectedTheme === theme.id;
return jsxs(MotionFramer, {
preset: "scaleIn",
className: cn("relative glass-p-4 glass-radius-lg cursor-pointer transition-all duration-200", "hover:scale-[1.02] hover:shadow-lg", "glass-focus glass-touch-target glass-contrast-guard", isSelected ? "ring-2 ring-primary bg-primary/20" : "ring-1 ring-white/10 bg-white/5 hover:ring-white/30"),
onClick: e => handleThemeSelect(theme.id),
children: [showPreview && jsx("div", {
className: 'glass-w-full h-16 glass-radius-md mb-3 glass-border glass-border-white/20',
style: getPreviewStyle(theme.preview),
children: jsxs("div", {
className: "glass-p-2 glass-gap-1",
children: [jsx("div", {
className: 'h-2 glass-radius-md',
style: {
backgroundColor: theme.preview.primary
}
}), jsx("div", {
className: 'h-1 glass-radius-md',
style: {
backgroundColor: theme.preview.secondary
}
})]
})
}), jsxs("div", {
className: "glass-flex glass-items-center glass-justify-between",
children: [jsx("span", {
className: 'font-medium glass-text-sm',
children: theme.name
}), isSelected && jsx(Check, {
className: 'w-4 h-4 text-primary'
})]
})]
}, theme.id);
})
})]
}), showCustomizer && jsx(MotionFramer, {
preset: "slideDown",
className: 'mt-6 glass-p-4 glass-surface-subtle/5 glass-radius-lg',
children: jsxs("div", {
className: "glass-gap-4",
children: [jsxs("h4", {
className: 'text-primary font-medium glass-flex glass-items-center glass-gap-2',
children: [jsx(Eye, {
className: 'w-4 h-4'
}), "Customize Theme"]
}), jsx("div", {
className: "glass-grid glass-grid-cols-2 glass-gap-4",
children: Object.entries(customColors).map(([key, value]) => jsxs("div", {
className: "glass-gap-2",
children: [jsx("label", {
className: 'text-primary/80 glass-text-sm capitalize',
children: key
}), jsxs("div", {
className: "glass-flex glass-gap-2",
children: [jsx("input", {
type: "color",
value: value,
onChange: e => handleCustomColorChange(key, e.target.value),
className: 'w-10 h-8 glass-radius-md ring-1 ring-white/10 cursor-pointer glass-focus glass-touch-target glass-contrast-guard'
}), jsx("input", {
type: "text",
value: value,
onChange: e => handleCustomColorChange(key, e.target.value),
className: 'glass-flex-1 glass-px-3 glass-py-1 glass-surface-subtle/10 ring-1 ring-white/10 glass-radius-md text-primary glass-text-sm focus:outline-none focus:ring-white/30 glass-focus glass-touch-target glass-contrast-guard'
})]
})]
}, key))
}), jsx("div", {
className: 'glass-w-full h-20 glass-radius-md ring-1 ring-white/10',
style: {
backgroundColor: customColors.background,
color: customColors.text
},
children: jsxs("div", {
className: "glass-p-3 glass-gap-2",
children: [jsx("div", {
className: 'h-3 glass-radius-md',
style: {
backgroundColor: customColors.primary
}
}), jsx("div", {
className: 'h-2 glass-radius-md',
style: {
backgroundColor: customColors.secondary
}
})]
})
}), jsxs("div", {
className: "glass-flex glass-gap-2",
children: [jsxs(GlassButton, {
variant: "primary",
size: "sm",
onClick: handleSaveCustomTheme,
className: "glass-flex glass-items-center glass-gap-2",
children: [jsx(Save, {
className: 'w-4 h-4'
}), "Save Theme"]
}), jsx(GlassButton, {
variant: "ghost",
size: "sm",
onClick: e => setShowCustomizer(false),
children: "Cancel"
})]
})]
})
})]
})]
})
});
};
export { GlassThemeSwitcher, GlassThemeSwitcher as default };
//# sourceMappingURL=GlassThemeSwitcher.js.map