aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
348 lines (345 loc) • 12.5 kB
JavaScript
'use client';
import { jsxs, jsx } from 'react/jsx-runtime';
import React, { useState, useCallback, useMemo } 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';
// Predefined color palettes
const predefinedPalettes = {
ocean: {
primary: "#0066cc",
secondary: "#00a3cc",
accent: "#00ffcc"
},
sunset: {
primary: "#ff6b35",
secondary: "#f7931e",
accent: "#ffb627"
},
forest: {
primary: "#2d5a27",
secondary: "#4a7c59",
accent: "#7fb069"
},
royal: {
primary: "#4a0e4e",
secondary: "#7b2cbf",
accent: "#c77dff"
},
minimal: {
primary: "#2c3e50",
secondary: "#34495e",
accent: "#ecf0f1"
}
};
const GlassColorSchemeGenerator = ({
initialScheme,
advanced = false,
generateCSS = true,
generateTailwind = false,
className = "",
onSchemeChange,
onExport
}) => {
const [baseColor, setBaseColor] = useState(initialScheme?.primary || "#0066cc");
const [palette, setPalette] = useState("ocean");
const [harmony, setHarmony] = useState("analogous");
// Generate color scheme based on base color and harmony
const generateScheme = useCallback((color, harmonyType) => {
// Convert hex to HSL
const hexToHsl = hex => {
const r = parseInt(hex.slice(1, 3), 16) / 255;
const g = parseInt(hex.slice(3, 5), 16) / 255;
const b = parseInt(hex.slice(5, 7), 16) / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h = 0,
s = 0,
l = (max + min) / 2;
if (max !== min) {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return [h * 360, s * 100, l * 100];
};
// Convert HSL to hex
const hslToHex = (h, s, l) => {
h /= 360;
s /= 100;
l /= 100;
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
};
let r, g, b;
if (s === 0) {
r = g = b = l;
} else {
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
const toHex = c => {
const hex = Math.round(c * 255).toString(16);
return hex.length === 1 ? "0" + hex : hex;
};
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
};
const [h, s, l] = hexToHsl(color);
let colors;
switch (harmonyType) {
case "analogous":
colors = {
primary: hslToHex(h, s, l),
secondary: hslToHex((h + 30) % 360, s, l),
accent: hslToHex((h - 30 + 360) % 360, s, l)
};
break;
case "complementary":
colors = {
primary: hslToHex(h, s, l),
secondary: hslToHex((h + 180) % 360, s, l),
accent: hslToHex((h + 180) % 360, s * 0.8, l * 1.2)
};
break;
case "triadic":
colors = {
primary: hslToHex(h, s, l),
secondary: hslToHex((h + 120) % 360, s, l),
accent: hslToHex((h + 240) % 360, s, l)
};
break;
case "monochromatic":
default:
colors = {
primary: hslToHex(h, s, l),
secondary: hslToHex(h, s * 0.6, l * 1.1),
accent: hslToHex(h, s * 0.4, l * 1.3)
};
break;
}
return {
...colors,
neutral: hslToHex(h, 10, 50),
success: "var(--glass-color-success)",
warning: "var(--glass-color-warning)",
error: "var(--glass-color-danger)",
info: "var(--glass-color-primary)",
background: hslToHex(h, 20, 5),
surface: hslToHex(h, 15, 10),
text: hslToHex(h, 10, 95)
};
}, []);
const colorScheme = useMemo(() => generateScheme(baseColor, harmony), [baseColor, harmony, generateScheme]);
// Update parent when scheme changes
React.useEffect(() => {
onSchemeChange?.(colorScheme);
}, [colorScheme, onSchemeChange]);
const handlePredefinedPalette = paletteName => {
const paletteColors = predefinedPalettes[paletteName];
setPalette(paletteName);
setBaseColor(paletteColors.primary);
};
const generateCSSVariables = scheme => {
return `:root {\n${Object.entries(scheme).map(([key, value]) => ` --color-${key}: ${value};`).join("\n")}\n}`;
};
const generateTailwindConfig = scheme => {
return `module.exports = {\n theme: {\n extend: {\n colors: {\n${Object.entries(scheme).map(([key, value]) => ` ${key}: '${value}',`).join("\n")}\n }\n }\n }\n}`;
};
const exportScheme = format => {
let content = "";
let filename = "";
switch (format) {
case "css":
content = generateCSSVariables(colorScheme);
filename = "color-scheme.css";
break;
case "json":
content = JSON.stringify(colorScheme, null, 2);
filename = "color-scheme.json";
break;
case "tailwind":
content = generateTailwindConfig(colorScheme);
filename = "tailwind.config.js";
break;
}
// Create download
const blob = new Blob([content], {
type: "text/plain"
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
onExport?.(colorScheme, format);
};
return jsxs("div", {
"data-glass-component": true,
className: `space-y-6 ${className}`,
children: [jsxs(OptimizedGlassCore, {
className: "glass-p-6",
intensity: "medium",
elevation: "level1",
children: [jsx("h3", {
className: 'glass-text-lg font-semibold text-primary mb-4',
children: "Base Color"
}), jsxs("div", {
className: 'glass-grid glass-grid-cols-1 md:grid-cols-2 glass-gap-6',
children: [jsxs("div", {
className: "glass-gap-4",
children: [jsxs("div", {
className: "glass-flex glass-items-center glass-gap-4",
children: [jsx("input", {
type: "color",
value: baseColor,
onChange: e => setBaseColor(e.target.value),
className: 'w-16 h-16 glass-radius-lg glass-border-2 glass-border-white/20 cursor-pointer'
}), jsxs("div", {
children: [jsx("label", {
className: 'block glass-text-sm text-primary/70 mb-1',
children: "Hex Color"
}), jsx("input", {
type: "text",
value: baseColor,
onChange: e => setBaseColor(e.target.value),
className: 'glass-px-3 glass-py-2 glass-surface-subtle/10 glass-border glass-border-white/20 glass-radius-md text-primary placeholder-white/50 focus:outline-none focus:border-white/40',
placeholder: "#0066cc"
})]
})]
}), jsxs("div", {
children: [jsx("label", {
className: 'block glass-text-sm text-primary/70 mb-2',
children: "Quick Palettes"
}), jsx("div", {
className: "glass-flex glass-flex-wrap glass-gap-2",
children: Object.entries(predefinedPalettes).map(([name, colors]) => jsx("button", {
onClick: e => handlePredefinedPalette(name),
className: `glass-px-3 glass-py-2 glass-radius-md glass-text-sm font-medium transition-colors ${palette === name ? "bg-white/20 glass-text-primary" : "bg-white/10 glass-text-primary/70 hover:bg-white/15"}`,
children: name.charAt(0).toUpperCase() + name.slice(1)
}, name))
})]
})]
}), jsx("div", {
className: "glass-gap-4",
children: jsxs("div", {
children: [jsx("label", {
className: 'block glass-text-sm text-primary/70 mb-2',
children: "Color Harmony"
}), jsx("div", {
className: "glass-grid glass-grid-cols-2 glass-gap-2",
children: [{
value: "analogous",
label: "Analogous"
}, {
value: "complementary",
label: "Complementary"
}, {
value: "triadic",
label: "Triadic"
}, {
value: "monochromatic",
label: "Monochromatic"
}].map(({
value,
label
}) => jsx("button", {
onClick: e => setHarmony(value),
className: `glass-px-3 glass-py-2 glass-radius-md glass-text-sm font-medium transition-colors ${harmony === value ? "bg-white/20 glass-text-primary" : "bg-white/10 glass-text-primary/70 hover:bg-white/15"}`,
children: label
}, value))
})]
})
})]
})]
}), jsxs(OptimizedGlassCore, {
className: "glass-p-6",
intensity: "medium",
elevation: "level1",
children: [jsx("h3", {
className: 'glass-text-lg font-semibold text-primary mb-4',
children: "Color Scheme Preview"
}), jsx("div", {
className: 'glass-grid glass-grid-cols-2 md:grid-cols-4 glass-gap-4',
children: Object.entries(colorScheme).map(([key, color]) => jsxs("div", {
className: "glass-gap-2",
children: [jsx("div", {
className: 'glass-w-full h-16 glass-radius-lg glass-border glass-border-white/20',
style: {
backgroundColor: color
}
}), jsxs("div", {
className: 'text-center',
children: [jsx("div", {
className: 'glass-text-xs text-primary/70 capitalize',
children: key
}), jsx("div", {
className: 'glass-text-xs text-primary/50 font-mono',
children: color
})]
})]
}, key))
})]
}), jsxs(OptimizedGlassCore, {
className: "glass-p-6",
intensity: "medium",
elevation: "level1",
children: [jsx("h3", {
className: 'glass-text-lg font-semibold text-primary mb-4',
children: "Export Options"
}), jsxs("div", {
className: "glass-flex glass-flex-wrap glass-gap-3",
children: [generateCSS && jsx("button", {
onClick: e => exportScheme("css"),
className: 'glass-px-4 glass-py-2 glass-surface-blue/20 glass-text-secondary glass-radius-md hover:glass-surface-blue/30 transition-colors',
children: "Export CSS Variables"
}), generateTailwind && jsx("button", {
onClick: e => exportScheme("tailwind"),
className: 'glass-px-4 glass-py-2 glass-surface-green/20 glass-text-secondary glass-radius-md hover:glass-surface-green/30 transition-colors',
children: "Export Tailwind Config"
}), jsx("button", {
onClick: e => exportScheme("json"),
className: 'glass-px-4 glass-py-2 glass-surface-primary/20 glass-text-secondary glass-radius-md hover:glass-surface-primary/30 transition-colors',
children: "Export JSON"
})]
}), generateCSS && jsxs("div", {
className: "glass-mt-4",
children: [jsx("label", {
className: 'block glass-text-sm text-primary/70 mb-2',
children: "CSS Variables Preview"
}), jsx("pre", {
className: 'glass-p-3 glass-surface-dark/20 glass-radius-md glass-text-xs text-primary/80 overflow-x-auto',
children: jsx("code", {
children: generateCSSVariables(colorScheme)
})
})]
})]
})]
});
};
export { GlassColorSchemeGenerator };
//# sourceMappingURL=GlassColorSchemeGenerator.js.map