ttrpg-tools/src/components/md-deck/CardLayer.tsx

60 lines
1.9 KiB
TypeScript
Raw Normal View History

2026-02-27 21:12:23 +08:00
import { For } from 'solid-js';
import { marked } from '../../markdown';
import { getLayerStyle } from './hooks/dimensions';
import type { LayerConfig, Dimensions, CardData } from './types';
export interface CardLayerProps {
layers: LayerConfig[];
dimensions: Dimensions;
cardData: CardData;
2026-02-27 22:37:11 +08:00
showBounds?: boolean;
2026-02-27 21:12:23 +08:00
}
/**
* body {{prop}} markdown
*/
function processBody(body: string, currentRow: CardData): string {
const processedBody = body.replace(/\{\{(\w+)\}\}/g, (_, key) => currentRow[key] || '');
return marked.parse(processedBody) as string;
}
/**
* layer
*/
function renderLayerContent(layer: { prop: string }, cardData: CardData): string {
const content = cardData[layer.prop] || '';
return processBody(content, cardData);
}
export function CardLayer(props: CardLayerProps) {
return (
<For each={props.layers}>
2026-02-27 22:56:06 +08:00
{(layer) => {
return (
<>
<article
class="absolute flex items-center justify-center text-center prose prose-sm"
2026-02-27 22:37:11 +08:00
style={{
2026-02-27 23:09:03 +08:00
...getLayerStyle(layer, props.dimensions),
2026-02-28 12:18:52 +08:00
'font-size': `${layer.fontSize || 3}mm`
2026-02-27 22:37:11 +08:00
}}
2026-02-27 22:56:06 +08:00
innerHTML={renderLayerContent(layer, props.cardData)}
2026-02-27 22:37:11 +08:00
/>
2026-02-27 22:56:06 +08:00
{props.showBounds && (
<div
class="absolute border-2 border-blue-500/50 pointer-events-none select-none"
style={{
left: `${(layer.x1 - 1) * props.dimensions.cellWidth}mm`,
top: `${(layer.y1 - 1) * props.dimensions.cellHeight}mm`,
width: `${(layer.x2 - layer.x1 + 1) * props.dimensions.cellWidth}mm`,
height: `${(layer.y2 - layer.y1 + 1) * props.dimensions.cellHeight}mm`
}}
/>
)}
</>
);
}}
2026-02-27 21:12:23 +08:00
</For>
);
}