figmatic-print-builder/LayersPanel.jsx

163 lines
4.8 KiB
React
Raw Normal View History

2026-06-16 12:58:18 +05:30
import useEditorStore from "./useEditorStore";
import { Eye, EyeOff, Trash2 } from "lucide-react";
export default function LayersPanel() {
const elements = useEditorStore((state) => state.elements);
const selectedId = useEditorStore((state) => state.selectedId);
const setSelectedId = useEditorStore((state) => state.setSelectedId);
const deleteElement = useEditorStore((state) => state.deleteElement);
const showLayers = useEditorStore((state) => state.showLayers);
const toggleLayers = useEditorStore((state) => state.toggleLayers);
if (!showLayers) return null;
const getElementIcon = (type) => {
const icons = {
text: "T",
image: "🖼️",
qrcode: "⊡",
line: "─",
rectangle: "▭",
summary: "Σ",
table: "⊞",
};
return icons[type] || "•";
};
const getElementLabel = (element) => {
if (element.type === "text") return element.text.substring(0, 20);
if (element.type === "image") return element.src ? "Image" : "Empty Image";
return element.type.charAt(0).toUpperCase() + element.type.slice(1);
};
return (
<div style={styles.panel}>
<div style={styles.header}>
<h4 style={styles.title}>Layers</h4>
<button onClick={toggleLayers} style={styles.closeBtn}>
×
</button>
</div>
<div style={styles.layersList}>
{elements.length === 0 ? (
<div style={styles.emptyState}>No elements</div>
) : (
[...elements].reverse().map((element, index) => (
<div
key={element.id}
style={{
...styles.layerItem,
...(selectedId === element.id ? styles.layerItemSelected : {}),
}}
onClick={() => setSelectedId(element.id)}
>
<div style={styles.layerInfo}>
<span style={styles.layerIcon}>{getElementIcon(element.type)}</span>
<span style={styles.layerLabel}>{getElementLabel(element)}</span>
</div>
<button
onClick={(e) => {
e.stopPropagation();
deleteElement(element.id);
}}
style={styles.deleteBtn}
title="Delete"
>
<Trash2 size={14} />
</button>
</div>
))
)}
</div>
</div>
);
}
const styles = {
panel: {
width: 220,
background: "#fff",
borderRight: "1px solid #ddd",
display: "flex",
flexDirection: "column",
height: "100%",
},
header: {
padding: "12px 16px",
borderBottom: "1px solid #ddd",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
},
title: {
margin: 0,
fontSize: 14,
fontWeight: 600,
},
closeBtn: {
background: "none",
border: "none",
fontSize: 24,
cursor: "pointer",
padding: 0,
lineHeight: 1,
color: "#666",
},
layersList: {
flex: 1,
overflowY: "auto",
padding: 8,
},
emptyState: {
textAlign: "center",
color: "#999",
fontSize: 13,
marginTop: 20,
},
layerItem: {
padding: "8px 12px",
marginBottom: 4,
borderRadius: 4,
cursor: "pointer",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
transition: "all 0.2s",
border: "1px solid transparent",
},
layerItemSelected: {
background: "#e3f2fd",
border: "1px solid #2196f3",
},
layerInfo: {
display: "flex",
alignItems: "center",
gap: 8,
flex: 1,
overflow: "hidden",
},
layerIcon: {
fontSize: 16,
width: 20,
textAlign: "center",
},
layerLabel: {
fontSize: 13,
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
},
deleteBtn: {
background: "none",
border: "none",
cursor: "pointer",
padding: 4,
display: "flex",
alignItems: "center",
color: "#666",
opacity: 0.6,
transition: "opacity 0.2s",
},
};