@@ -5,21 +5,215 @@
55 import Symbol from './Symbol.svelte';
66
77 import type { PartType, SymbolQuery } from 'types/sigil';
8− import { PART_TYPES } from 'types/sigil';
98
109 export let symbolQuery: SymbolQuery;
11− export let inputMode: PartType;
10+ // export let inputMode: PartType;
11+ export let inputComponents: string[] = [];
12+ export let unfocusSymbol: Function;
1213
14+ interface ModeDefs {
15+ [mode: string]: ModeDef
16+ }
17+ interface ModeDef {
18+ modes?: ModeDefs;
19+ displayParts?: string[];
20+ parts?: string[];
21+ }
22+
23+ const modeDefs: ModeDefs = {
24+ geon: {
25+ modes: {},
26+ displayParts: ['ghb'],
27+ },
28+ line: {
29+ modes: {
30+ mainFulls: {
31+ parts: ['lvf', 'lhf', 'lff', 'lbf'],
32+ },
33+ halvesFulls: {
34+ parts: ['lvfl', 'lvfr', 'lhft', 'lhfb', 'lfht', 'lfhb', 'lbht', 'lbhb'],
35+ },
36+ forwards: {
37+ parts: ['lff', 'lfft', 'lffb'],
38+ },
39+ backwards: {
40+ parts: ['lbf', 'lbft'],
41+ },
42+ weirds: {
43+ parts: ['lbhtf', 'lbrf', 'lfhm'],
44+ }
45+ },
46+ parts: ['lvf', 'lvfl', 'lvfr', 'lhf', 'lhft', 'lhfb', 'lff', 'lbf'],
47+ },
48+ arcCorner: {
49+ modes: {
50+ trFulls: {
51+ parts: ['atrf8', 'atrf6', 'atrf4', 'atrf2'],
52+ },
53+ trHalves: {
54+ parts: [/*'atra8',*/ 'atra6', 'atra4', 'atra2', 'atrb8', 'atrb6', 'atrb4', 'atrb2'],
55+ displayParts: ['atrb8', 'atrb6', 'atrb4', 'atrb2'],
56+ },
57+ tlFulls: {
58+ parts: ['atlf8', 'atlf6', 'atlf4', 'atlf2'],
59+ },
60+ tlHalves: {
61+ parts: ['atla8', 'atla6', 'atla4', 'atla2', 'atlb8', 'atlb6', 'atlb4', 'atlb2'],
62+ displayParts: ['atlb8', 'atlb6', 'atlb4', 'atlb2'],
63+ },
64+ blFulls: {
65+ parts: ['ablf8', 'ablf6', 'ablf4', 'ablf2'],
66+ },
67+ blHalves: {
68+ parts: ['ablb8', 'ablb6', 'ablb4', 'ablb2'],
69+ displayParts: ['ablb8', 'ablb6', 'ablb4', 'ablb2'],
70+ },
71+ brFulls: {
72+ parts: ['abrf8', 'abrf6', 'abrf4', 'abrf2'],
73+ },
74+ brHalves: {
75+ parts: ['abrb8', 'abrb6', 'abrb4', 'abrb2'],
76+ displayParts: ['abrb8', 'abrb6', 'abrb4', 'abrb2'],
77+ },
78+ },
79+ parts: ['ablf8', 'ablf6', 'ablf4', 'ablf2'],
80+ },
81+ arc: {
82+ modes: {
83+ rings: {
84+ parts: ['am081', 'am082', 'am083', 'am08s'],
85+ },
86+ diagonals: {
87+ parts: ['am741', 'am742', 'am743', 'am422', 'am423'],
88+ },
89+ topsBottoms: {
90+ parts: ['ab2', 'ab3', 'ab4', 'at1', 'at3', 'at4'],
91+ },
92+ leftsRights: {
93+ parts: ['al2', 'al3', 'al4', 'ar1', 'ar2', 'ar4'/*, 'arb2'*/],
94+ },
95+ rights: {
96+ parts: ['am642', 'am643'],
97+ },
98+ middles: {
99+ parts: ['am222', 'am223', 'am622', 'am623'],
100+ },
101+ middless: {
102+ parts: ['am142', 'am443'],
103+ },
104+ topRights: {
105+ parts: ['am021', 'am022', 'am023', 'am242', 'arb2'],
106+ },
107+ // weirds: {
108+ // parts: ['arb2'],
109+ // },
110+ },
111+ parts: ['am222', 'am223', 'ar4', 'ar2', 'ar1'],
112+ },
113+ circle: {
114+ parts: [
115+ 'cbr3mb', 'ctl3mb',
116+ 'cmmb',
117+ 'ct2mb', 'cl2mb', 'cb2mb', 'cr2mb',
118+ ],
119+ },
120+ donut: {
121+ parts: ['dbl', /*'dl',*/ 'dm', 'dtl', 'dtr'],
122+ },
123+ bezier: {
124+ parts: ['b1l1', 'b1l2', 'b1l3'],
125+ },
126+ };
127+ let modes: string[] = [];
128+ let modeDef: ModeDef = undefined;
129+ let subModeDefs: ModeDefs = modeDefs;
13130 let size = 48;
131+
132+
133+ $: {
134+ if (!symbolQuery.geon) {
135+ modes = ['geon'];
136+ }
137+ }
138+
139+ function pushMode(mode: string) {
140+ if (modeDef?.modes) {
141+ modes = [...modes, mode];
142+ } else {
143+ modes = [...modes.slice(0, -1), mode];
144+ }
145+ }
146+
147+ function popMode() {
148+ if (modes.length) {
149+ if (modeDef?.modes) {
150+ modes = modes.slice(0, -1);
151+ } else {
152+ modes = modes.slice(0, -2);
153+ }
154+ } else {
155+ unfocusSymbol();
156+ }
157+ }
158+
159+ $: {
160+ modeDef = undefined;
161+ subModeDefs = modeDefs;
162+ for (let mode of modes) {
163+ if (modeDef && modeDef.modes) {
164+ subModeDefs = modeDef.modes;
165+ }
166+ if (subModeDefs[mode]) {
167+ modeDef = subModeDefs[mode];
168+ } else {
169+ console.error(`Unknown mode: ${mode} of ${modes} in defs:`, subModeDefs);
170+ }
171+ }
172+
173+ if (modeDef && modeDef.modes) {
174+ subModeDefs = modeDef.modes;
175+ }
176+
177+ if (modeDef?.parts?.length && !modeDef.modes) {
178+ inputComponents = modeDef.parts;
179+ } else {
180+ inputComponents = [];
181+ }
182+ }
183+
184+ function clear() {
185+ if (modes.length) {
186+ symbolQuery = symbolQuery.clearPartType(modes[0] as PartType);
187+ } else {
188+ symbolQuery = symbolQuery.clear();
189+ }
190+ }
14191</script>
15192
16193<div class="grid grid-rows-2 grid-flow-col xs:grid-cols-2 xs:grid-flow-row place-content-center justify-center">
17− {#if inputMode === 'geon'}
18− <GeonSelector bind:symbolQuery bind:inputMode />
194+ <div
195+ class="aspect-square"
196+ on:click={popMode}
197+ >
198+ done
199+ </div>
200+ <div
201+ class="aspect-square"
202+ on:click={clear}
203+ >
204+ clear
205+ </div>
206+ {#if modes[0] === 'geon'}
207+ <GeonSelector bind:symbolQuery {popMode} />
19208 {:else}
20− {#each PART_TYPES as partType}
21− <SymbolInputModeSelectorButton {partType} focused={inputMode === partType}
22− on:click={() => inputMode = partType}
209+ <!-- {#each PART_TYPES as partType}
210+ <SymbolInputModeSelectorButton {partType} focused={modes[0] === partType}
211+ on:click={() => pushMode(partType)}
212+ />
213+ {/each} -->
214+ {#each Object.entries(subModeDefs) as [modeName, def]}
215+ <SymbolInputModeSelectorButton components={def.displayParts || def.parts} focused={modes.slice(-1)[0] === modeName}
216+ on:click={() => pushMode(modeName)}
23217 />
24218 {/each}
25219 {/if}