import { For, createSignal, onCleanup, onMount } from "solid-js"; import { createSortable, useDragDropContext } from "@thisbeyond/solid-dnd"; import type { DeckStore } from "../hooks/deckStore"; import type { LayerConfig } from "../types"; import alignLeftIcon from "./icons/align-left.png"; import alignCenterIcon from "./icons/align-center.png"; import alignRightIcon from "./icons/align-right.png"; export interface LayerRowProps { store: DeckStore; index: number; sortableId: string; layer: LayerConfig; hovered: boolean; onHoverChange: (idx: number | null) => void; openDropdown: string | null; setOpenDropdown: (val: string | null) => void; onUpdateOrientation: (o: "n" | "s" | "e" | "w") => void; onUpdateFontSize: (fs?: number) => void; onUpdateAlign: (a?: "l" | "c" | "r") => void; onSelect: () => void; onRemove: () => void; } const ORIENTATIONS = [ { value: "n" as const, label: "↑ 北" }, { value: "e" as const, label: "→ 东" }, { value: "s" as const, label: "↓ 南" }, { value: "w" as const, label: "← 西" }, ]; const ALIGNS = [ { value: "" as const, icon: alignCenterIcon }, { value: "l" as const, icon: alignLeftIcon }, { value: "c" as const, icon: alignCenterIcon }, { value: "r" as const, icon: alignRightIcon }, ]; const FONT_PRESETS = [3, 5, 8, 12] as const; function orientChar(v: string) { switch (v) { case "n": return "↑"; case "e": return "→"; case "s": return "↓"; case "w": return "←"; default: return "↑"; } } function alignSrc(v: string) { switch (v) { case "l": return alignLeftIcon; case "r": return alignRightIcon; default: return alignCenterIcon; } } export function LayerRow(props: LayerRowProps) { const sortable = createSortable(props.sortableId); const [dndState] = useDragDropContext()!; const [fontOpen, setFontOpen] = createSignal(false); let fontRef: HTMLDivElement | undefined; const selected = () => props.store.state.selectedLayer === props.index; onMount(() => { const h = (e: MouseEvent) => { if (fontRef && !fontRef.contains(e.target as Node)) setFontOpen(false); }; document.addEventListener("click", h); onCleanup(() => document.removeEventListener("click", h)); }); const toggleVisible = () => { const fn = props.store.state.activeSide === "front" ? props.store.actions.toggleFrontLayerVisible : props.store.actions.toggleBackLayerVisible; fn(props.index); }; return (
props.onHoverChange(props.index)} onMouseLeave={() => props.onHoverChange(null)} > {props.layer.prop || (props.layer.template ? "(模板)" : "")} props.setOpenDropdown( props.openDropdown === `orient-${props.index}` ? null : `orient-${props.index}`, ) } title="方向" > {(o) => ( )} } visible={props.layer.visible} open={props.openDropdown === `align-${props.index}`} onToggle={() => props.setOpenDropdown( props.openDropdown === `align-${props.index}` ? null : `align-${props.index}`, ) } title="对齐" > {(o) => ( )}
{fontOpen() && (
e.stopPropagation()} >
props.onUpdateFontSize( e.target.value ? Number(e.target.value) : undefined, ) } class="w-14 text-xs px-1.5 py-1 rounded border border-gray-300" step="0.1" min="0.1" /> mm
{(p) => ( )}
)}
); } function DropdownButton(props: { icon: import("solid-js").JSX.Element; visible: boolean; open: boolean; onToggle: () => void; title: string; children: import("solid-js").JSX.Element; }) { return (
{props.open && (
e.stopPropagation()} > {props.children}
)}
); }