@@ -14,87 +14,110 @@
1414 export let inputComponents: string[] = [];
1515 export let unfocusSymbol: Function = () => {};
1616
17− let modes: string[] = [];
17+ let mode: string = null;
18+ let subMode: string = null;
1819 let modeDef: ModeDef = undefined;
19− let subModeDefs: ModeDefs = MODE_DEFS;
20+ let unselectedSubModesExist: boolean = false;
21+ let modeDefs: ModeDefs = MODE_DEFS;
22+ let plausibleModeDefs: { name: string, def: ModeDef }[] = [];
2023
2124 function showGeonSelector() {
22− if (!symbolQuery.components.length && modes.length == 0) {
23− modes = ['geon'];
25+ if (!symbolQuery.components.length && !mode) {
26+ mode = 'geon';
27+ subMode = null;
2428 }
2529 }
2630
2731 $: symbolQuery.components, showGeonSelector();
2832
29− function pushMode(mode: string) {
30− if (modeDef?.modes) {
31− modes = [...modes, mode];
33+ function pushMode(newMode: string) {
34+ const subModes = modeDef?.modes;
35+ if (subModes || subMode) {
36+ subMode = newMode;
3237 } else {
33− modes = [...modes.slice(0, -1), mode];
38+ mode = newMode;
39+ subMode = null;
3440 }
3541 }
3642
3743 function popMode() {
38− if (modes.length) {
39− if (modeDef?.modes) {
40− modes = modes.slice(0, -1);
41− } else {
42− modes = modes.slice(0, -2);
43− }
44+ if (mode || subMode) {
45+ mode = null;
46+ subMode = null;
4447 } else {
4548 unfocusSymbol();
4649 }
4750 }
4851
4952 $: {
50− modeDef = undefined;
51− subModeDefs = MODE_DEFS;
52− for (let mode of modes) {
53− if (modeDef && modeDef.modes) {
54− subModeDefs = modeDef.modes;
53+ let modeResolved = false;
54+ let count = 0;
55+ while (!modeResolved && count < 5) {
56+ modeDef = undefined;
57+ modeDefs = MODE_DEFS;
58+ if (mode) {
59+ modeDef = MODE_DEFS[mode];
60+ }
61+ unselectedSubModesExist = !!modeDef?.modes;
62+ if (unselectedSubModesExist) {
63+ modeDefs = modeDef.modes;
64+ if (subMode) {
65+ if (modeDefs[subMode]) {
66+ modeDef = modeDefs[subMode];
67+ } else {
68+ console.error(`Unknown subMode: ${subMode} of ${mode} in defs:`, modeDefs);
69+ subMode = null;
70+ }
71+ }
5572 }
56− if (subModeDefs[mode]) {
57− modeDef = subModeDefs[mode];
73+ unselectedSubModesExist = !!modeDef?.modes;
74+ if (!isDefPlausible(modeDef) && mode !== 'geon') {
75+ if (subMode) {
76+ subMode = null;
77+ } else {
78+ mode = null;
79+ }
5880 } else {
59− console.error(`Unknown mode: ${mode} of ${modes} in defs:`, subModeDefs);
81+ plausibleModeDefs = getPlausibleModeDefs(modeDefs);
82+ if (unselectedSubModesExist) {
83+ subMode = plausibleModeDefs[0].name;
84+ } else {
85+ modeResolved = true;
86+ }
87+ }
88+ count++;
89+ if (count >= 5 && !modeResolved) {
90+ console.error("sigil input mode resulotion failed");
6091 }
6192 }
62−
63− if (modeDef && modeDef.modes) {
64− subModeDefs = modeDef.modes;
65− }
66−
67− if (modeDef?.parts?.length && !modeDef.modes) {
93+ inputComponents = [];
94+ if (modeDef?.parts?.length) {
6895 inputComponents = modeDef.parts;
6996 if (!$searchSettings.allowFictionalSigils) {
7097 inputComponents = symbolQuery.filterPlausibleParts(inputComponents);
7198 }
72− } else {
73− inputComponents = [];
7499 }
75100 }
76101
77− $: plausibleModes = Object.entries(subModeDefs).map(([modeName, def]) => {
102+ function isDefPlausible(def: ModeDef): boolean {
103+ if (!def) return true;
78104 const deepParts = getDeepParts(def);
79− const plausible = $searchSettings.allowFictionalSigils || symbolQuery.arePartsPlausible(deepParts);
80− if (!plausible && modeName !== 'geon') return null;
81− const parts = filterPartsByGeon(def.displayParts || def.parts, symbolQuery.geon);
82− return { parts, modeName };
83− }).filter(mode => mode !== null);
105+ return $searchSettings.allowFictionalSigils || symbolQuery.arePartsPlausible(deepParts);
106+ }
84107
85− $: {
86− const currentMode = modes.slice(-1)[0];
87− if (currentMode != 'geon') {
88− if (plausibleModes.length === 0) {
89− popMode();
90− } else if (plausibleModes.length >= 1) {
91− const leafMode = modeDef && !(modeDef.modes);
92− const plausibleModeNames = plausibleModes.map(({ modeName }) => modeName);
93− if ((modes.length == 1 && modeDef.modes) || (leafMode && !plausibleModeNames.includes(currentMode))) {
94− pushMode(plausibleModes[0].modeName);
95− }
96− }
97− }
108+ function getPlausibleModeDefs(modeDefs: ModeDefs) {
109+ return Object.entries(modeDefs).map(([modeName, def]) => {
110+ const plausible = isDefPlausible(def);
111+ if (!plausible && modeName !== 'geon') return null;
112+ const parts = filterPartsByGeon(def.displayParts || def.parts, symbolQuery.geon);
113+ return {
114+ name: modeName,
115+ def: {
116+ ...def,
117+ parts,
118+ },
119+ };
120+ }).filter(mode => mode !== null);
98121 }
99122
100123 function clear() {
@@ -116,17 +139,23 @@
116139</style>
117140
118141<div class="mx-auto flex justify-center xs:items-center xs:flex-col">
119− <SymbolInputNavButtons onDone={popMode} onClear={clear} />
142+ <SymbolInputNavButtons onDone={popMode} onClear={clear} hideClearButton={symbolQuery.components.length == 0} />
120143 <div class="max-w-[15rem] h-full grid grid-cols-custom gap-1 justify-center xs:max-w-[8rem]">
121− {#if modes[0] === 'geon'}
144+ {#if mode === 'geon'}
122145 <GeonSelector bind:symbolQuery {popMode} />
123146 {:else}
124− {#each plausibleModes as { modeName, parts }}
125− <SymbolInputModeSelectorButton components={parts} focused={modes.slice(-1)[0] === modeName}
126− on:click={() => pushMode(modeName)}
147+ {#each plausibleModeDefs as { name, def: { parts } }}
148+ <SymbolInputModeSelectorButton components={parts} focused={mode === name || subMode === name}
149+ on:click={() => pushMode(name)}
127150 />
128151 {/each}
129152 {/if}
130153 </div>
154+ <!-- <p class="break-all w-24">
155+ mode: {mode}
156+ </p>
157+ <p class="break-all w-24">
158+ sub: {subMode}
159+ </p> -->
131160</div>
132161