fix: solid-element

This commit is contained in:
hypercross 2026-02-26 00:47:26 +08:00
parent b5f5e853bd
commit 795c2c4389
7 changed files with 63 additions and 27 deletions

19
package-lock.json generated
View File

@ -14,6 +14,7 @@
"csv-parse": "^5.5.6", "csv-parse": "^5.5.6",
"marked": "^14.1.0", "marked": "^14.1.0",
"marked-directive": "^1.0.7", "marked-directive": "^1.0.7",
"solid-element": "^1.9.1",
"solid-js": "^1.9.3" "solid-js": "^1.9.3"
}, },
"bin": { "bin": {
@ -2356,6 +2357,12 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/component-register": {
"version": "0.8.8",
"resolved": "https://registry.npmjs.org/component-register/-/component-register-0.8.8.tgz",
"integrity": "sha512-djhwcxjY+X9dacaYUEOkOm7tda8uOEDiMDigWysu3xv54M8o6XDlsjR1qt5Y8QLGiKg51fqXFIR2HUTmt9ys0Q==",
"license": "MIT"
},
"node_modules/convert-source-map": { "node_modules/convert-source-map": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@ -3167,6 +3174,18 @@
"seroval": "^1.0" "seroval": "^1.0"
} }
}, },
"node_modules/solid-element": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/solid-element/-/solid-element-1.9.1.tgz",
"integrity": "sha512-baJy6Qz27oAUgkPlqOf3Y+7RsBiuVQrS51Nrh1ddDbrqrNPvJbIvehpUsTzLNFb2ZHIoHuNnDg330go/ZKcRdg==",
"license": "MIT",
"dependencies": {
"component-register": "^0.8.7"
},
"peerDependencies": {
"solid-js": "^1.9.3"
}
},
"node_modules/solid-js": { "node_modules/solid-js": {
"version": "1.9.11", "version": "1.9.11",
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.11.tgz", "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.11.tgz",

View File

@ -35,6 +35,7 @@
"csv-parse": "^5.5.6", "csv-parse": "^5.5.6",
"marked": "^14.1.0", "marked": "^14.1.0",
"marked-directive": "^1.0.7", "marked-directive": "^1.0.7",
"solid-element": "^1.9.1",
"solid-js": "^1.9.3" "solid-js": "^1.9.3"
}, },
"devDependencies": { "devDependencies": {

View File

@ -2,6 +2,9 @@ import { Component, createSignal, onMount } from 'solid-js';
import { useLocation } from '@solidjs/router'; import { useLocation } from '@solidjs/router';
import { parseMarkdown } from './markdown'; import { parseMarkdown } from './markdown';
// 导入组件以注册自定义元素
import './components';
const App: Component = () => { const App: Component = () => {
const location = useLocation(); const location = useLocation();
const [content, setContent] = createSignal(''); const [content, setContent] = createSignal('');

View File

@ -1,9 +1,5 @@
import { Component, createSignal, Show } from 'solid-js'; import { customElement, noShadowDOM } from 'solid-element';
import { createSignal } from 'solid-js';
export interface DiceProps {
formula: string;
key?: string;
}
function rollDice(formula: string): number { function rollDice(formula: string): number {
// 解析骰子公式例如2d6+d8 // 解析骰子公式例如2d6+d8
@ -30,10 +26,14 @@ function rollDice(formula: string): number {
return total; return total;
} }
export const Dice: Component<DiceProps> = (props) => { customElement('ttrpg-dice', { key: '' }, (props, { element }) => {
noShadowDOM();
const [result, setResult] = createSignal<number | null>(null); const [result, setResult] = createSignal<number | null>(null);
const [isRolled, setIsRolled] = createSignal(false); const [isRolled, setIsRolled] = createSignal(false);
// 从 element 的 textContent 获取骰子公式
const formula = element?.textContent?.trim() || '';
const handleClick = () => { const handleClick = () => {
if (isRolled()) { if (isRolled()) {
// 重置为公式 // 重置为公式
@ -41,18 +41,17 @@ export const Dice: Component<DiceProps> = (props) => {
setIsRolled(false); setIsRolled(false);
} else { } else {
// 掷骰子 // 掷骰子
const rollResult = rollDice(props.formula); const rollResult = rollDice(formula);
setResult(rollResult); setResult(rollResult);
setIsRolled(true); setIsRolled(true);
} }
}; };
const displayText = () => (isRolled() ? `${result()}` : props.formula); const displayText = () => (isRolled() ? `${result()}` : formula);
const queryParams = () => (props.key && isRolled() ? `?dice-${props.key}=${result()}` : '');
return ( return (
<a <a
href={queryParams()} href={props.key && isRolled() ? `?dice-${props.key}=${result()}` : '#'}
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
handleClick(); handleClick();
@ -63,4 +62,5 @@ export const Dice: Component<DiceProps> = (props) => {
<span>{displayText()}</span> <span>{displayText()}</span>
</a> </a>
); );
}; });

View File

@ -1,5 +1,8 @@
export { Dice } from './dice'; // 导入以注册自定义元素
export type { DiceProps } from './dice'; import './dice';
import './table';
export { Table } from './table'; // 导出类型
export type { DiceProps } from './dice';
export type { TableProps } from './table'; export type { TableProps } from './table';

View File

@ -1,21 +1,18 @@
import { Component, createSignal, For, Show } from 'solid-js'; import { customElement, noShadowDOM } from 'solid-element';
import { createSignal, For, Show } from 'solid-js';
import { parse } from 'csv-parse/sync'; import { parse } from 'csv-parse/sync';
export interface TableProps {
src: string;
roll?: boolean;
remix?: boolean;
}
interface TableRow { interface TableRow {
label: string; label: string;
body: string; body: string;
[key: string]: string; [key: string]: string;
} }
export const Table: Component<TableProps> = (props) => { customElement('ttrpg-table', { src: '', roll: false, remix: false }, (props, { element }) => {
noShadowDOM();
const [rows, setRows] = createSignal<TableRow[]>([]); const [rows, setRows] = createSignal<TableRow[]>([]);
const [activeTab, setActiveTab] = createSignal(0); const [activeTab, setActiveTab] = createSignal(0);
const [loaded, setLoaded] = createSignal(false);
// 解析 CSV 内容 // 解析 CSV 内容
const parseCSV = (content: string) => { const parseCSV = (content: string) => {
@ -24,6 +21,7 @@ export const Table: Component<TableProps> = (props) => {
skip_empty_lines: true, skip_empty_lines: true,
}); });
setRows(records as TableRow[]); setRows(records as TableRow[]);
setLoaded(true);
}; };
// 加载 CSV 文件 // 加载 CSV 文件
@ -34,11 +32,14 @@ export const Table: Component<TableProps> = (props) => {
parseCSV(content); parseCSV(content);
} catch (error) { } catch (error) {
console.error('Failed to load CSV:', error); console.error('Failed to load CSV:', error);
setLoaded(true);
} }
}; };
// 初始化加载 // 初始化加载
loadCSV(); if (!loaded()) {
loadCSV();
}
// 随机切换 tab // 随机切换 tab
const handleRoll = () => { const handleRoll = () => {
@ -80,12 +81,21 @@ export const Table: Component<TableProps> = (props) => {
</button> </button>
)} )}
</For> </For>
<Show when={props.roll}>
<button
onClick={handleRoll}
class="px-2 py-2 text-gray-500 hover:text-gray-700"
title="随机切换"
>
🎲
</button>
</Show>
</div> </div>
<div class="p-4 prose max-w-none"> <div class="p-4 prose max-w-none">
<Show when={rows().length > 0}> <Show when={loaded() && rows().length > 0}>
<div innerHTML={processBody(rows()[activeTab()].body, rows()[activeTab()])} /> <div innerHTML={processBody(rows()[activeTab()].body, rows()[activeTab()])} />
</Show> </Show>
</div> </div>
</div> </div>
); );
}; });

View File

@ -1,7 +1,7 @@
import { Marked } from 'marked'; import { Marked } from 'marked';
import { createDirectives } from 'marked-directive'; import { createDirectives } from 'marked-directive';
// 使用 marked-directive 来支持通过 @solidjs/element 添加的 UI 组件 // 使用 marked-directive 来支持指令语法
const marked = new Marked().use(createDirectives()); const marked = new Marked().use(createDirectives());
export function parseMarkdown(content: string): string { export function parseMarkdown(content: string): string {