diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..30a9902 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# Rider 忽略的文件 +/projectSettingsUpdater.xml +/modules.xml +/.idea.ttrpg-tools.iml +/contentModel.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/components/card-preview.tsx b/src/components/card-preview.tsx new file mode 100644 index 0000000..17c6a39 --- /dev/null +++ b/src/components/card-preview.tsx @@ -0,0 +1,114 @@ +import { Show, For } from 'solid-js'; +import { marked } from '../markdown'; +import type { CardData, LayerConfig, Dimensions } from './types'; +import { getLayerStyle } from './utils/dimensions'; +import { getSelectionBoxStyle } from './hooks/use-selection'; + +export interface CardPreviewProps { + cards: CardData[]; + activeTab: number; + layerConfigs: LayerConfig[]; + dimensions: Dimensions; + isEditing: boolean; + isFixed: boolean; + editingLayer: string | null; + isSelecting: boolean; + selectStart: { x: number; y: number } | null; + selectEnd: { x: number; y: number } | null; + onMouseDown: (e: MouseEvent) => void; + onMouseMove: (e: MouseEvent) => void; + onMouseUp: () => void; + onMouseLeave: () => void; +} + +/** + * 渲染 layer 内容 + */ +function renderLayer(layer: { prop: string }, cardData: CardData): string { + const content = cardData[layer.prop] || ''; + return marked.parse(content) as string; +} + +export function CardPreview(props: CardPreviewProps) { + const currentCard = () => props.cards[props.activeTab]; + const visibleLayers = () => props.layerConfigs.filter(l => l.visible); + const selectionStyle = () => + getSelectionBoxStyle(props.selectStart, props.selectEnd, props.dimensions); + + return ( +
+ +
+ {/* 框选遮罩 */} + +
+ + + {/* 网格区域容器 */} +
+ {/* 编辑模式下的网格线 */} + +
+ + {(_, i) => ( +
+ )} + + + {(_, i) => ( +
+ )} + +
+ + + {/* 渲染每个 layer */} + + {(layer) => { + const style = getLayerStyle(layer, props.dimensions); + const isEditingThis = props.editingLayer === layer.prop; + + return ( +
+ ); + }} + +
+
+ +
+ ); +} diff --git a/src/components/editor-panel.tsx b/src/components/editor-panel.tsx new file mode 100644 index 0000000..8e55a07 --- /dev/null +++ b/src/components/editor-panel.tsx @@ -0,0 +1,139 @@ +import { Show, For } from 'solid-js'; +import type { CardData, LayerConfig } from './types'; + +export interface DataEditorPanelProps { + cards: CardData[]; + activeTab: number; + updateCardData: (key: string, value: string) => void; +} + +export interface PropertiesEditorPanelProps { + localSize: string; + localGrid: string; + localBleed: string; + localPadding: string; + layerConfigs: LayerConfig[]; + editingLayer: string | null; + onSizeChange: (value: string) => void; + onGridChange: (value: string) => void; + onBleedChange: (value: string) => void; + onPaddingChange: (value: string) => void; + onToggleLayerVisible: (prop: string) => void; + onStartEditingLayer: (prop: string) => void; + onCopyCode: () => void; +} + +/** + * 左侧:CSV 数据编辑面板 + */ +export function DataEditorPanel(props: DataEditorPanelProps) { + return ( +
+

卡牌数据

+
+ + {(key) => ( +
+ +