aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
238 lines (235 loc) • 8.95 kB
JavaScript
'use client';
import { jsx, jsxs } from 'react/jsx-runtime';
import { useState } from 'react';
import { GlassCore } from '../../primitives/GlassCore.js';
import '../../primitives/glass/GlassAdvanced.js';
import '../../primitives/OptimizedGlassCore.js';
import '../../primitives/glass/OptimizedGlassAdvanced.js';
import '../../primitives/MotionNative.js';
import '../../primitives/motion/MotionFramer.js';
import { cn } from '../../lib/utilsComprehensive.js';
import { useDragDrop } from './GlassDragDropProvider.js';
const CategoryIcon = ({
category
}) => {
const icons = {
layout: "🏗️",
content: "📝",
media: "🎬",
interactive: "🎯",
advanced: "⚡"
};
return jsx("span", {
className: "glass-text-lg",
children: icons[category]
});
};
const ComponentItem = ({
component,
isDragging
}) => {
const {
onDragStart
} = useDragDrop();
const handleDragStart = e => {
e.dataTransfer.effectAllowed = "copy";
onDragStart(component, "component");
};
const handleMouseDown = () => {
onDragStart(component, "component");
};
return jsxs("div", {
"data-glass-component": true,
draggable: true,
onDragStart: handleDragStart,
onMouseDown: handleMouseDown,
className: cn("flex items-center gap-3 p-3 rounded-lg border border-gray-200 cursor-grab", "hover:border-blue-300 hover:bg-blue-50 transition-colors", "active:cursor-grabbing active:scale-95", isDragging && "opacity-50 scale-95"),
title: `Drag to add ${component.name}`,
children: [jsx("div", {
className: "glass-text-2xl",
children: component.icon
}), jsxs("div", {
className: 'glass-flex-1 min-glass-w-0',
children: [jsx("div", {
className: 'glass-text-sm font-medium glass-text-secondary truncate',
children: component.name
}), jsx("div", {
className: 'glass-text-xs glass-text-secondary capitalize',
children: component.category
})]
}), jsx("div", {
className: "glass-text-xs glass-text-secondary",
children: "\u22EF"
})]
});
};
const CategorySection = ({
category,
components,
isExpanded,
onToggle
}) => {
const categoryNames = {
layout: "Layout",
content: "Content",
media: "Media",
interactive: "Interactive",
advanced: "Advanced"
};
return jsxs("div", {
className: 'mb-4',
children: [jsxs("button", {
onClick: onToggle,
className: 'glass-flex glass-items-center glass-justify-between glass-w-full glass-p-2 glass-radius-lg hover:glass-surface-subtle transition-colors glass-focus glass-touch-target glass-focus glass-touch-target glass-contrast-guard',
children: [jsxs("div", {
className: "glass-flex glass-items-center glass-gap-2",
children: [jsx(CategoryIcon, {
category: category
}), jsx("span", {
className: 'glass-text-sm font-medium glass-text-secondary',
children: categoryNames[category]
}), jsxs("span", {
className: "glass-text-xs glass-text-secondary",
children: ["(", components.length, ")"]
})]
}), jsx("div", {
className: cn("text-gray-400 transition-transform", isExpanded ? "rotate-90" : "rotate-0"),
children: "\u25B6"
})]
}), isExpanded && jsx("div", {
className: 'mt-2 space-y-2 pl-4',
children: components.map(component => jsx(ComponentItem, {
component: component
}, component.id))
})]
});
};
const GlassComponentPalette = ({
className,
collapsed = false,
onToggleCollapse
}) => {
const {
componentLibrary,
dragDropState
} = useDragDrop();
const [expandedCategories, setExpandedCategories] = useState(new Set(["layout", "content"]));
const [searchQuery, setSearchQuery] = useState("");
const toggleCategory = category => {
setExpandedCategories(prev => {
const newSet = new Set(prev);
if (newSet.has(category)) {
newSet.delete(category);
} else {
newSet.add(category);
}
return newSet;
});
};
// Group components by category
const componentsByCategory = componentLibrary.reduce((acc, component) => {
if (!acc[component.category]) {
acc[component.category] = [];
}
acc[component.category].push(component);
return acc;
}, {});
// Filter components by search query
const filteredComponents = searchQuery ? componentLibrary.filter(component => component.name.toLowerCase().includes(searchQuery.toLowerCase()) || component.type.toLowerCase().includes(searchQuery.toLowerCase())) : null;
if (collapsed) {
return jsx("div", {
className: cn("w-12", className),
children: jsx(GlassCore, {
className: "glass-h-full glass-contrast-guard",
children: jsx("button", {
onClick: onToggleCollapse,
className: 'glass-flex glass-items-center glass-justify-center glass-w-full h-12 glass-text-secondary hover:glass-text-secondary transition-colors glass-focus glass-touch-target glass-focus glass-touch-target glass-contrast-guard',
title: "Expand Component Palette",
children: jsx("div", {
className: "glass-text-lg",
children: "\uD83D\uDCE6"
})
})
})
});
}
return jsx("div", {
className: cn("w-80 h-full flex flex-col", className),
children: jsxs(GlassCore, {
className: "glass-h-full glass-flex glass-flex-col glass-contrast-guard",
children: [jsxs("div", {
className: "glass-flex glass-items-center glass-justify-between glass-p-4 glass-border-b glass-border-subtle",
children: [jsx("h2", {
className: 'glass-text-lg font-semibold glass-text-secondary',
children: "Components"
}), jsx("button", {
onClick: onToggleCollapse,
className: 'glass-p-2 glass-text-secondary hover:glass-text-secondary transition-colors glass-focus glass-touch-target glass-focus glass-touch-target glass-contrast-guard',
title: "Collapse Palette",
children: "\u25C0"
})]
}), jsx("div", {
className: "glass-p-4 glass-border-b glass-border-subtle",
children: jsxs("div", {
className: 'relative',
children: [jsx("input", {
type: "text",
placeholder: "Search components...",
value: searchQuery,
onChange: e => setSearchQuery(e.target.value),
className: 'glass-w-full glass-px-3 glass-py-2 pl-10 glass-text-sm glass-border glass-border-subtle glass-radius-lg focus:outline-none focus:ring-2 focus:ring-blue-500'
}), jsx("div", {
className: 'absolute left-3 glass-top-1/2 transform -translate-y-1/2 glass-text-secondary',
children: "\uD83D\uDD0D"
}), searchQuery && jsx("button", {
onClick: () => setSearchQuery(""),
className: 'absolute right-3 glass-top-1/2 transform -translate-y-1/2 glass-text-secondary hover:glass-text-secondary glass-focus glass-touch-target',
children: "\u2715"
})]
})
}), jsx("div", {
className: 'glass-flex-1 overflow-y-auto glass-p-4',
children: searchQuery && filteredComponents ?
// Search Results
jsxs("div", {
className: 'space-y-2',
children: [jsxs("div", {
className: 'glass-text-sm glass-text-secondary mb-3',
children: [filteredComponents.length, " components found"]
}), filteredComponents.map(component => jsx(ComponentItem, {
component: component,
isDragging: dragDropState.draggedItem?.id === component.id
}, component.id)), filteredComponents.length === 0 && jsxs("div", {
className: 'text-center glass-py-8 glass-text-secondary',
children: [jsx("div", {
className: 'glass-text-2xl mb-2',
children: "\uD83D\uDD0D"
}), jsx("p", {
children: "No components found"
}), jsx("p", {
className: "glass-text-xs",
children: "Try a different search term"
})]
})]
}) :
// Categories
jsx("div", {
children: Object.entries(componentsByCategory).map(([category, components]) => jsx(CategorySection, {
category: category,
components: components,
isExpanded: expandedCategories.has(category),
onToggle: () => toggleCategory(category)
}, category))
})
}), jsx("div", {
className: "glass-p-4 glass-border-t glass-border-subtle glass-surface-subtle",
children: jsx("div", {
className: 'glass-text-xs glass-text-secondary text-center',
children: "\uD83D\uDCA1 Drag components onto the canvas to add them"
})
})]
})
});
};
export { GlassComponentPalette };
//# sourceMappingURL=GlassComponentPalette.js.map