fix: solid-element
This commit is contained in:
parent
b5f5e853bd
commit
795c2c4389
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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": {
|
||||||
|
|
|
||||||
|
|
@ -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('');
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化加载
|
// 初始化加载
|
||||||
|
if (!loaded()) {
|
||||||
loadCSV();
|
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>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue