diff --git a/src/components/md-deck/CardLayer.tsx b/src/components/md-deck/CardLayer.tsx index e85d731..0a8131d 100644 --- a/src/components/md-deck/CardLayer.tsx +++ b/src/components/md-deck/CardLayer.tsx @@ -1,15 +1,17 @@ -import {createMemo, For} from 'solid-js'; -import {parseMarkdown} from '../../markdown'; +import { createMemo, For, Show } from 'solid-js'; +import { parseMarkdown } from '../../markdown'; import { getLayerStyle } from './hooks/dimensions'; -import type { CardData, CardSide } from './types'; -import {DeckStore} from "./hooks/deckStore"; -import {processVariables} from "../utils/csv-loader"; -import {resolvePath} from "../utils/path"; +import type { CardData, CardSide, LayerConfig } from './types'; +import { DeckStore } from "./hooks/deckStore"; +import { processVariables } from "../utils/csv-loader"; +import { resolvePath } from "../utils/path"; +import type { LayerInteractionHandlers } from './hooks/useLayerInteraction'; export interface CardLayerProps { cardData: CardData; store: DeckStore; side?: CardSide; + interaction?: LayerInteractionHandlers; } export function CardLayer(props: CardLayerProps) { @@ -21,6 +23,8 @@ export function CardLayer(props: CardLayerProps) { ); const dimensions = () => props.store.state.dimensions!; const showBounds = () => props.store.state.isEditing; + const selectedLayer = () => props.store.state.selectedLayer; + const draggingState = () => props.store.state.draggingState; function renderLayerContent(content: string) { const iconPath = resolvePath(props.store.state.cards.sourcePath, props.cardData.iconPath ?? "./assets"); @@ -32,21 +36,67 @@ export function CardLayer(props: CardLayerProps) { if (align === 'r') return 'right'; return 'center'; }; + + const isLayerSelected = (layer: LayerConfig) => selectedLayer() === layer.prop; + + const getFrameBounds = (layer: LayerConfig) => { + const dims = dimensions(); + const orientation = layer.orientation || 'n'; + + if (orientation === 'e' || orientation === 'w') { + const left = (layer.y1 - 1) * dims.cellWidth; + const top = (layer.x1 - 1) * dims.cellHeight; + const width = (layer.y2 - layer.y1 + 1) * dims.cellWidth; + const height = (layer.x2 - layer.x1 + 1) * dims.cellHeight; + return { left, top, width, height }; + } + + const left = (layer.x1 - 1) * dims.cellWidth; + const top = (layer.y1 - 1) * dims.cellHeight; + const width = (layer.x2 - layer.x1 + 1) * dims.cellWidth; + const height = (layer.y2 - layer.y1 + 1) * dims.cellHeight; + return { left, top, width, height }; + }; + + const handleLayerClick = (layerProp: string, e: MouseEvent) => { + if (props.interaction) { + props.interaction.onLayerClick(layerProp, e); + } + }; + + const handleFrameMouseDown = ( + action: 'drag' | 'resize-corner' | 'resize-edge', + anchor?: 'nw' | 'ne' | 'sw' | 'se', + edge?: 'n' | 's' | 'e' | 'w', + e?: MouseEvent + ) => { + if (props.interaction) { + props.interaction.onFrameMouseDown(action, anchor, edge, e); + } + }; + return ( {(layer) => { + const bounds = () => getFrameBounds(layer); + const isSelected = () => isLayerSelected(layer); + return ( <>
handleLayerClick(layer.prop, e)} /> - {showBounds() && ( +
- )} + + +
+
handleFrameMouseDown('drag', undefined, undefined, e)} + /> + +
handleFrameMouseDown('resize-corner', 'nw', undefined, e)} + /> +
handleFrameMouseDown('resize-corner', 'ne', undefined, e)} + /> +
handleFrameMouseDown('resize-corner', 'sw', undefined, e)} + /> +
handleFrameMouseDown('resize-corner', 'se', undefined, e)} + /> +
handleFrameMouseDown('resize-edge', undefined, 'n', e)} + /> +
handleFrameMouseDown('resize-edge', undefined, 's', e)} + /> +
handleFrameMouseDown('resize-edge', undefined, 'w', e)} + /> +
handleFrameMouseDown('resize-edge', undefined, 'e', e)} + /> + + ); }} ); -} +} \ No newline at end of file diff --git a/src/components/md-deck/CardPreview.tsx b/src/components/md-deck/CardPreview.tsx index 53e0b02..9d5ad6c 100644 --- a/src/components/md-deck/CardPreview.tsx +++ b/src/components/md-deck/CardPreview.tsx @@ -1,58 +1,67 @@ -import { Show, For, createMemo } from 'solid-js'; -import { useCardSelection } from './hooks/useCardSelection'; -import { getSelectionBoxStyle } from './hooks/useCardSelection'; +import { Show, For, createMemo, onCleanup, onMount } from 'solid-js'; import { getShapeClipPath } from './hooks/shape-styles'; import { CardLayer } from './CardLayer'; import type { DeckStore } from './hooks/deckStore'; +import { useLayerInteraction } from './hooks/useLayerInteraction'; export interface CardPreviewProps { store: DeckStore; } -/** - * 卡牌预览组件 - */ export function CardPreview(props: CardPreviewProps) { const { store } = props; const currentCard = createMemo(() => store.state.cards[store.state.activeTab]); - const selectionStyle = createMemo(() => - getSelectionBoxStyle(store.state.selectStart, store.state.selectEnd, store.state.dimensions) - ); const shapeClipPath = createMemo(() => { const dims = store.state.dimensions; if (!dims) return 'none'; return getShapeClipPath(store.state.shape, dims.cardWidth, dims.cardHeight, store.state.cornerRadius); }); - const selection = useCardSelection(store); + const interaction = useLayerInteraction(store); let cardRef: HTMLDivElement | undefined; + const handleGlobalMouseMove = (e: MouseEvent) => { + if (cardRef && store.state.draggingState) { + interaction.onCardMouseMove(e, cardRef); + } + }; + + const handleGlobalMouseUp = () => { + if (store.state.draggingState) { + interaction.onCardMouseUp(); + } + }; + + onMount(() => { + document.addEventListener('mousemove', handleGlobalMouseMove); + document.addEventListener('mouseup', handleGlobalMouseUp); + }); + + onCleanup(() => { + document.removeEventListener('mousemove', handleGlobalMouseMove); + document.removeEventListener('mouseup', handleGlobalMouseUp); + }); + return (
selection.onMouseDown(e, cardRef!)} - onMouseMove={(e) => selection.onMouseMove(e, cardRef!)} - onMouseUp={selection.onMouseUp} - onMouseLeave={selection.onMouseLeave} + onClick={(e) => { + if (!store.state.draggingState && cardRef) { + interaction.onCardClick(e, cardRef); + } + }} > - -
- -
); -} +} \ No newline at end of file diff --git a/src/components/md-deck/editor-panel/LayerEditorPanel.tsx b/src/components/md-deck/editor-panel/LayerEditorPanel.tsx index 2577e06..1951473 100644 --- a/src/components/md-deck/editor-panel/LayerEditorPanel.tsx +++ b/src/components/md-deck/editor-panel/LayerEditorPanel.tsx @@ -80,9 +80,9 @@ function LayerEditorPanel(props: LayerEditorPanelProps) { toggleFn(layerProp); }; - const setEditingLayer = (layerProp: string) => { - store.actions.setEditingLayer( - store.state.editingLayer === layerProp ? null : layerProp + const selectLayer = (layerProp: string) => { + store.actions.setSelectedLayer( + store.state.selectedLayer === layerProp ? null : layerProp ); }; @@ -118,6 +118,8 @@ function LayerEditorPanel(props: LayerEditorPanelProps) {
toggleLayerVisible(layer.prop)} class="cursor-pointer" /> - {layer.prop} - - + {layer.prop} +