mysticsymbolic.github.io/lib/browser-main.tsx

131 wiersze
2.9 KiB
TypeScript
Czysty Zwykły widok Historia

2021-02-04 00:53:01 +00:00
import React, { useState } from "react";
2021-02-04 00:11:34 +00:00
import ReactDOM from "react-dom";
2021-02-04 00:36:29 +00:00
import _SvgVocabulary from "./svg-vocabulary.json";
import type { SvgSymbolData, SvgSymbolElement } from "./vocabulary";
2021-02-04 00:36:29 +00:00
2021-02-04 00:11:34 +00:00
const APP_ID = "app";
const appEl = document.getElementById(APP_ID);
const SvgVocabulary: SvgSymbolData[] = _SvgVocabulary as any;
2021-02-04 00:36:29 +00:00
2021-02-06 15:57:41 +00:00
const STROKE_REPLACEMENT_COLOR = "#000000";
const FILL_REPLACEMENT_COLOR = "#ffffff";
2021-02-06 13:02:18 +00:00
2021-02-04 00:11:34 +00:00
if (!appEl) {
throw new Error(`Unable to find #${APP_ID}!`);
}
type SvgSymbolContext = {
2021-02-04 00:53:01 +00:00
stroke: string;
fill: string;
2021-02-04 00:36:29 +00:00
};
type SvgSymbolProps = {
data: SvgSymbolData;
scale?: number;
} & SvgSymbolContext;
2021-02-04 00:39:48 +00:00
const px = (value: number) => `${value}px`;
function reactifySvgSymbolElement(
ctx: SvgSymbolContext,
el: SvgSymbolElement,
key: number
): JSX.Element {
let { fill, stroke } = el.props;
2021-02-06 15:57:41 +00:00
if (fill === STROKE_REPLACEMENT_COLOR) {
2021-02-06 13:02:18 +00:00
// The fill represents a "shadow" area, so use our stroke color here.
fill = ctx.stroke;
2021-02-06 15:57:41 +00:00
} else if (fill === FILL_REPLACEMENT_COLOR) {
fill = ctx.fill;
}
if (stroke === STROKE_REPLACEMENT_COLOR) {
stroke = ctx.stroke;
}
return React.createElement(
el.tagName,
{
...el.props,
id: undefined,
fill,
stroke,
key,
},
el.children.map(reactifySvgSymbolElement.bind(null, ctx))
);
}
2021-02-04 00:36:29 +00:00
const SvgSymbol: React.FC<SvgSymbolProps> = (props) => {
const d = props.data;
2021-02-04 00:53:01 +00:00
const scale = props.scale || 1;
2021-02-04 00:36:29 +00:00
return (
<svg
2021-02-04 00:53:01 +00:00
viewBox={`0 0 ${d.width} ${d.height}`}
width={px(d.width * scale)}
height={px(d.height * scale)}
>
{props.data.layers.map(reactifySvgSymbolElement.bind(null, props))}
</svg>
2021-02-04 00:36:29 +00:00
);
};
2021-02-04 00:53:01 +00:00
const App: React.FC<{}> = () => {
const [stroke, setStroke] = useState("#000000");
const [fill, setFill] = useState("#ffffff");
return (
<>
<h1>Mythic Symbolic Vocabulary</h1>
<p>
<label htmlFor="stroke">Stroke: </label>
<input
type="color"
value={stroke}
onChange={(e) => setStroke(e.target.value)}
id="stroke"
2021-02-04 01:26:17 +00:00
/>{" "}
2021-02-04 00:53:01 +00:00
<label htmlFor="fill">Fill: </label>
<input
type="color"
value={fill}
onChange={(e) => setFill(e.target.value)}
id="fill"
/>
</p>
{SvgVocabulary.map((symbolData) => (
<div
key={symbolData.name}
2021-02-04 00:53:01 +00:00
style={{
display: "inline-block",
2021-02-04 01:23:24 +00:00
border: "1px solid black",
margin: "4px",
2021-02-04 00:53:01 +00:00
}}
>
2021-02-04 01:23:24 +00:00
<div
style={{
backgroundColor: "black",
color: "white",
padding: "4px",
}}
>
{symbolData.name}
</div>
2021-02-06 13:11:20 +00:00
<div className="checkerboard-bg">
<SvgSymbol
data={symbolData}
scale={0.25}
stroke={stroke}
fill={fill}
/>
</div>
2021-02-04 00:53:01 +00:00
</div>
))}
</>
);
};
2021-02-04 00:11:34 +00:00
ReactDOM.render(<App />, appEl);