From 51f68656ad2814ec088b86d2774d3b62b3c4eb71 Mon Sep 17 00:00:00 2001 From: Atul Varma Date: Sat, 27 Mar 2021 08:29:42 -0400 Subject: [PATCH] Factor out vocabulary.ts. --- lib/creature-symbol-factory.tsx | 5 ++-- lib/pages/creature-page.tsx | 6 ++--- lib/pages/debug-page.tsx | 4 +-- lib/pages/mandala-page.tsx | 8 +++--- lib/pages/vocabulary-page.tsx | 2 +- lib/svg-symbol-widget.tsx | 47 --------------------------------- lib/svg-vocabulary.ts | 22 +++------------ lib/vocabulary-widget.tsx | 38 ++++++++++++++++++++++++++ lib/vocabulary.ts | 19 +++++++++++++ 9 files changed, 73 insertions(+), 78 deletions(-) delete mode 100644 lib/svg-symbol-widget.tsx create mode 100644 lib/vocabulary-widget.tsx create mode 100644 lib/vocabulary.ts diff --git a/lib/creature-symbol-factory.tsx b/lib/creature-symbol-factory.tsx index af98d29..15b4089 100644 --- a/lib/creature-symbol-factory.tsx +++ b/lib/creature-symbol-factory.tsx @@ -6,6 +6,7 @@ import { } from "./creature-symbol"; import { AttachmentPointType } from "./specs"; import { SvgSymbolData } from "./svg-symbol"; +import { Vocabulary } from "./vocabulary"; type AttachmentIndices = { left?: boolean; @@ -71,7 +72,7 @@ type SimpleCreatureSymbolFC = React.FC & { * render a ``. */ export function createCreatureSymbolFactory( - getSymbol: (name: string) => SvgSymbolData + vocabulary: Vocabulary ) { /** * Returns a React component that renders a ``, using the symbol @@ -80,7 +81,7 @@ export function createCreatureSymbolFactory( return function createCreatureSymbol( name: string ): React.FC { - const data = getSymbol(name); + const data = vocabulary.get(name); const Component: SimpleCreatureSymbolFC = (props) => { const symbol = getCreatureSymbol(data, props); return ; diff --git a/lib/pages/creature-page.tsx b/lib/pages/creature-page.tsx index 46a2504..4e365e6 100644 --- a/lib/pages/creature-page.tsx +++ b/lib/pages/creature-page.tsx @@ -25,7 +25,7 @@ import { NumericSlider } from "../numeric-slider"; import { DEFAULT_BG_COLOR } from "../colors"; /** Symbols that can be the "root" (i.e., main body) of a creature. */ -const ROOT_SYMBOLS = SvgVocabulary.filter( +const ROOT_SYMBOLS = SvgVocabulary.items.filter( (data) => data.meta?.always_be_nested !== true ); @@ -41,7 +41,7 @@ const ATTACHMENT_SYMBOLS: AttachmentSymbolMap = (() => { const result = {} as AttachmentSymbolMap; for (let type of ATTACHMENT_POINT_TYPES) { - result[type] = SvgVocabulary.filter((data) => { + result[type] = SvgVocabulary.items.filter((data) => { const { meta } = data; // If we have no metadata whatsoever, it can attach anywhere. @@ -66,7 +66,7 @@ const ATTACHMENT_SYMBOLS: AttachmentSymbolMap = (() => { })(); /** Symbols that can be nested within any part of a creature. */ -const NESTED_SYMBOLS = SvgVocabulary.filter( +const NESTED_SYMBOLS = SvgVocabulary.items.filter( // Since we don't currently support recursive nesting, ignore anything that // wants nested children. (data) => diff --git a/lib/pages/debug-page.tsx b/lib/pages/debug-page.tsx index 74b53e7..974844b 100644 --- a/lib/pages/debug-page.tsx +++ b/lib/pages/debug-page.tsx @@ -5,10 +5,10 @@ import { createCreatureSymbolFactory } from "../creature-symbol-factory"; import { HoverDebugHelper } from "../hover-debug-helper"; import { createSvgSymbolContext } from "../svg-symbol"; import { svgScale, SvgTransforms } from "../svg-transform"; -import { getSvgSymbol } from "../svg-vocabulary"; +import { SvgVocabulary } from "../svg-vocabulary"; import { SymbolContextWidget } from "../symbol-context-widget"; -const symbol = createCreatureSymbolFactory(getSvgSymbol); +const symbol = createCreatureSymbolFactory(SvgVocabulary); const Eye = symbol("eye"); diff --git a/lib/pages/mandala-page.tsx b/lib/pages/mandala-page.tsx index fd42d57..d152e5b 100644 --- a/lib/pages/mandala-page.tsx +++ b/lib/pages/mandala-page.tsx @@ -13,18 +13,18 @@ import { SvgSymbolContext, SvgSymbolData, } from "../svg-symbol"; -import { SvgSymbolWidget } from "../svg-symbol-widget"; +import { VocabularyWidget } from "../vocabulary-widget"; import { svgRotate, svgScale, SvgTransforms, svgTranslate, } from "../svg-transform"; -import { getSvgSymbol, SvgVocabulary } from "../svg-vocabulary"; +import { SvgVocabulary } from "../svg-vocabulary"; import { SymbolContextWidget } from "../symbol-context-widget"; import { range } from "../util"; -const EYE = getSvgSymbol("eye"); +const EYE = SvgVocabulary.get("eye"); const MandalaCircle: React.FC< { @@ -72,7 +72,7 @@ export const MandalaPage: React.FC<{}> = () => { {" "}

- = () => {

Mystic Symbolic Vocabulary

- {SvgVocabulary.map((symbolData) => ( + {SvgVocabulary.items.map((symbolData) => (
void; - choices: SvgSymbolData[]; -}; - -export const SvgSymbolWidget: React.FC = ({ - id, - label, - value, - onChange, - choices, -}) => { - id = id || slugify(label); - const symbolMap = useMemo( - () => new Map(choices.map((symbol) => [symbol.name, symbol])), - [choices] - ); - const handleChange = (value: string) => { - const symbol = symbolMap.get(value); - if (!symbol) throw new Error(`Unable to find "${value}"`); - onChange(symbol); - }; - - return ( - <> - - - - ); -}; diff --git a/lib/svg-vocabulary.ts b/lib/svg-vocabulary.ts index 94e6ae5..d744feb 100644 --- a/lib/svg-vocabulary.ts +++ b/lib/svg-vocabulary.ts @@ -1,23 +1,7 @@ import type { SvgSymbolData } from "./svg-symbol"; +import { Vocabulary } from "./vocabulary"; import _SvgVocabulary from "./_svg-vocabulary.json"; -export const SvgVocabulary: SvgSymbolData[] = _SvgVocabulary as any; - -/** - * Mapping from symbol names to symbol data, for quick and easy access. - */ -const SYMBOL_MAP = new Map( - SvgVocabulary.map((symbol) => [symbol.name, symbol]) +export const SvgVocabulary = new Vocabulary( + _SvgVocabulary as any ); - -/** - * Returns the data for the given symbol, throwing an error - * if it doesn't exist. - */ -export function getSvgSymbol(name: string): SvgSymbolData { - const symbol = SYMBOL_MAP.get(name); - if (!symbol) { - throw new Error(`Unable to find the symbol "${name}"!`); - } - return symbol; -} diff --git a/lib/vocabulary-widget.tsx b/lib/vocabulary-widget.tsx new file mode 100644 index 0000000..8a26de3 --- /dev/null +++ b/lib/vocabulary-widget.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { slugify } from "./util"; +import { Vocabulary, VocabularyType } from "./vocabulary"; + +export type VocabularyWidgetProps = { + id?: string; + label: string; + value: T; + onChange: (value: T) => void; + choices: Vocabulary; +}; + +export function VocabularyWidget({ + id, + label, + value, + onChange, + choices, +}: VocabularyWidgetProps) { + id = id || slugify(label); + + return ( + <> + + + + ); +} diff --git a/lib/vocabulary.ts b/lib/vocabulary.ts new file mode 100644 index 0000000..e27fb8b --- /dev/null +++ b/lib/vocabulary.ts @@ -0,0 +1,19 @@ +export type VocabularyType = { + name: string; +}; + +export class Vocabulary { + readonly itemMap: Map; + + constructor(readonly items: T[]) { + this.itemMap = new Map(items.map((item) => [item.name, item])); + } + + get(name: string): T { + const item = this.itemMap.get(name); + if (!item) { + throw new Error(`Unable to find the item "${name}"!`); + } + return item; + } +}