Skip to content

Commit 50639fa

Browse files
authored
impr(layouts): add basic support for thumb alpha keys (@zigotica) (monkeytypegame#6023)
1 parent 221e706 commit 50639fa

File tree

4 files changed

+227
-27
lines changed

4 files changed

+227
-27
lines changed

frontend/scripts/json-validation.cjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,9 @@ function validateOthers() {
236236
},
237237
row5: {
238238
type: "array",
239-
items: { type: "string", minLength: 1, maxLength: 1 },
239+
items: { type: "string", minLength: 1, maxLength: 2 },
240240
minItems: 1,
241-
maxItems: 1,
241+
maxItems: 2,
242242
},
243243
},
244244
required: ["row1", "row2", "row3", "row4", "row5"],
@@ -280,9 +280,9 @@ function validateOthers() {
280280
},
281281
row5: {
282282
type: "array",
283-
items: { type: "string", minLength: 1, maxLength: 1 },
283+
items: { type: "string", minLength: 1, maxLength: 2 },
284284
minItems: 1,
285-
maxItems: 1,
285+
maxItems: 2,
286286
},
287287
},
288288
required: ["row1", "row2", "row3", "row4", "row5"],

frontend/src/styles/keymap.scss

Lines changed: 90 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
.r5 {
102102
display: grid;
103103
grid-template-columns: 3.5fr 6fr 3.5fr;
104-
font-size: 0.5rem;
104+
font-size: 1rem;
105105
// &.matrixSpace {
106106
// // grid-template-columns: 6.75fr 1.9fr 6.75fr;
107107
// grid-template-columns: 6.9fr 4.6fr 6.9fr; // wider spacebar
@@ -110,6 +110,24 @@
110110
// // grid-template-columns: 6.75fr 1.9fr 6.75fr;
111111
// grid-template-columns: 4fr 7.5fr 4fr;
112112
// }
113+
.keySpace {
114+
// since we can potentially have alphas in r5,
115+
// we keep font-size: 1rem; for alphas to look the same as other rows,
116+
// but reduce it again to 0.5rem for space, so layout name fits.
117+
font-size: 0.5rem;
118+
}
119+
120+
&[data-row5-has-alpha="true"] {
121+
// space-alpha
122+
&[data-row5-grid="3-1"] {
123+
grid-template-columns: 4fr 4fr 1fr 4fr;
124+
}
125+
126+
// alpha-space
127+
&[data-row5-grid="1-3"] {
128+
grid-template-columns: 4fr 1fr 4fr 4fr;
129+
}
130+
}
113131
}
114132
&.matrix {
115133
.r1,
@@ -121,6 +139,18 @@
121139

122140
.r5 {
123141
grid-template-columns: 1fr 3fr 4fr 3fr 1fr;
142+
143+
&[data-row5-has-alpha="true"] {
144+
// space-alpha
145+
&[data-row5-grid="3-1"] {
146+
grid-template-columns: 1fr 2fr 3fr 1fr 5fr;
147+
}
148+
149+
// alpha-space
150+
&[data-row5-grid="1-3"] {
151+
grid-template-columns: 2fr 3fr 1fr 3fr 3fr;
152+
}
153+
}
124154
}
125155
}
126156
&.split {
@@ -152,6 +182,18 @@
152182
}
153183
.r5 {
154184
grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr;
185+
186+
&[data-row5-has-alpha="true"] {
187+
// space-alpha
188+
&[data-row5-grid="3-1"] {
189+
grid-template-columns: 5fr 3fr 1fr 1fr 6.5fr;
190+
}
191+
192+
// alpha-space
193+
&[data-row5-grid="1-3"] {
194+
grid-template-columns: 7fr 1fr 1fr 3fr 4.5fr;
195+
}
196+
}
155197
}
156198
.keySpace.right {
157199
opacity: 1;
@@ -180,6 +222,18 @@
180222

181223
.r5 {
182224
grid-template-columns: 1fr 2fr 3fr 1fr 3fr 2fr 1fr;
225+
226+
&[data-row5-has-alpha="true"] {
227+
// space-alpha
228+
&[data-row5-grid="3-1"] {
229+
grid-template-columns: 2fr 1fr 3fr 1fr 1fr 2fr 3fr;
230+
}
231+
232+
// alpha-space
233+
&[data-row5-grid="1-3"] {
234+
grid-template-columns: 4fr 1fr 1fr 1fr 3fr 1fr 2fr;
235+
}
236+
}
183237
}
184238
.keySpace.right {
185239
opacity: 1;
@@ -433,20 +487,42 @@
433487
}
434488
.r5 {
435489
grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr;
436-
}
437-
.keySpace.right {
438-
opacity: 1;
439-
}
440490

441-
div.keySpace {
442-
transform: rotate(10deg);
443-
margin-left: -5%;
444-
margin-top: 21%;
445-
}
446-
div.keySpace.right {
447-
transform: rotate(-10deg);
448-
margin-left: -33%;
449-
margin-top: 20%;
491+
// rotation/position of r5 keys moved under .r5 styles
492+
// and made generic to left/right to account for alphas
493+
div.keymapKey.left {
494+
transform: rotate(10deg);
495+
margin-left: -5%;
496+
margin-top: 21%;
497+
}
498+
div.keymapKey.right {
499+
opacity: 1;
500+
transform: rotate(-10deg);
501+
margin-left: -33%;
502+
margin-top: 20%;
503+
}
504+
505+
&[data-row5-has-alpha="true"] {
506+
// space-alpha
507+
&[data-row5-grid="3-1"] {
508+
grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr;
509+
510+
div.keymapKey.right {
511+
margin-left: -30%;
512+
margin-top: 25%;
513+
}
514+
}
515+
516+
// alpha-space
517+
&[data-row5-grid="1-3"] {
518+
grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr;
519+
520+
div.keymapKey.left {
521+
margin-left: 50%;
522+
margin-top: 25%;
523+
}
524+
}
525+
}
450526
}
451527
div#KeyBackslash.keymapKey {
452528
visibility: hidden;

frontend/src/ts/elements/keymap.ts

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ export async function refresh(
113113
if (Config.keymapMode === "off") return;
114114
if (ActivePage.get() !== "test") return;
115115
if (!layoutName) return;
116+
let r5_grid = "";
117+
let hasAlphas = false;
116118
try {
117119
let layouts;
118120
try {
@@ -153,6 +155,8 @@ export async function refresh(
153155
const isSteno =
154156
Config.keymapStyle === "steno" || Config.keymapStyle === "steno_matrix";
155157

158+
const isAlice = Config.keymapStyle === "alice";
159+
156160
if (isSteno) {
157161
lts = stenoKeys;
158162
}
@@ -203,19 +207,76 @@ export async function refresh(
203207

204208
if (row === "row5") {
205209
if (isSteno) continue;
206-
const layoutDisplay = layoutString.replace(/_/g, " ");
210+
let layoutDisplay = layoutString.replace(/_/g, " ");
207211
let letterStyle = "";
208212
if (Config.keymapLegendStyle === "blank") {
209213
letterStyle = `style="display: none;"`;
210214
}
215+
/* ROW 5 in alternate keymaps allow for alphas in thumb keys.
216+
* These keymaps MUST include two keys in row 5,
217+
* an alpha and a space, or a space and an alpha.
218+
* Alpha key is rendered with the regular alpha size.
219+
* Layout name is automatically added in the space key.
220+
* Visual keymap will be:
221+
* 1-3 for 1 alpha and 1 space
222+
* 3-1 for 1 space and 1 alpha
223+
* Together with the data-row5-has-alpha="true",
224+
* these two will be used to edit the CSS grid layout.
225+
* 3-3 for two spaces of size 3. This will not be used to edit CSS,
226+
* since it means a traditional layout, can keep current CSS grid.
227+
* It is just created for simplicity in the for loop below.
228+
* */
229+
// If only one space, add another
230+
if (rowKeys.length === 1 && rowKeys[0] === " ") {
231+
rowKeys[1] = rowKeys[0];
232+
}
233+
// If only one alpha, add one space and place it on the left
234+
if (rowKeys.length === 1 && rowKeys[0] !== " ") {
235+
rowKeys[1] = " ";
236+
rowKeys.reverse();
237+
}
238+
// If two alphas equal, replace one with a space on the left
239+
if (
240+
rowKeys.length > 1 &&
241+
rowKeys[0] !== " " &&
242+
rowKeys[0] === rowKeys[1]
243+
) {
244+
rowKeys[0] = " ";
245+
}
246+
const alphas = (v: string): boolean => v !== " ";
247+
hasAlphas = rowKeys.some(alphas);
248+
211249
rowElement += "<div></div>";
212-
rowElement += `<div class="keymapKey keySpace layoutIndicator left">
213-
<div class="letter" ${letterStyle}>${layoutDisplay}</div>
214-
</div>`;
215-
rowElement += `<div class="keymapSplitSpacer"></div>`;
216-
rowElement += `<div class="keymapKey keySpace right">
217-
<div class="letter"></div>
218-
</div>`;
250+
251+
for (let i = 0; i < rowKeys.length; i++) {
252+
const key = rowKeys[i] as string;
253+
let keyDisplay = key[0] as string;
254+
if (Config.keymapLegendStyle === "uppercase") {
255+
keyDisplay = keyDisplay.toUpperCase();
256+
}
257+
const keyVisualValue = key.replace('"', "&quot;");
258+
// these are used to keep grid layout but magically hide keys using opacity:
259+
let side = i < 1 ? "left" : "right";
260+
// we won't use this trick for alternate layouts, unless Alice (for rotation):
261+
if (hasAlphas && !isAlice) side = "";
262+
if (i === 1) {
263+
rowElement += `<div class="keymapSplitSpacer"></div>`;
264+
r5_grid += "-";
265+
}
266+
if (keyVisualValue === " ") {
267+
rowElement += `<div class="keymapKey keySpace layoutIndicator ${side}">
268+
<div class="letter" ${letterStyle}>${layoutDisplay}</div>
269+
</div>`;
270+
r5_grid += "3";
271+
// potential second space in next loop iterations will be empty:
272+
layoutDisplay = "";
273+
} else {
274+
rowElement += `<div class="keymapKey ${side}">
275+
<div class="letter">${keyDisplay}</div>
276+
</div>`;
277+
r5_grid += "1";
278+
}
279+
}
219280
} else {
220281
for (let i = 0; i < rowKeys.length; i++) {
221282
if (row === "row2" && i === 12) continue;
@@ -309,7 +370,15 @@ export async function refresh(
309370
}
310371
}
311372

312-
keymapElement += `<div class="row r${index + 1}">${rowElement}</div>`;
373+
if (row === "row5") {
374+
keymapElement += `<div
375+
class="row r${index + 1}"
376+
data-row5-grid="${r5_grid}"
377+
data-row5-has-alpha="${hasAlphas}"
378+
>${rowElement}</div>`;
379+
} else {
380+
keymapElement += `<div class="row r${index + 1}">${rowElement}</div>`;
381+
}
313382
}
314383
// );
315384

frontend/static/layouts/_list.json

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,5 +2112,60 @@
21122112
"row4": [",<", "/?", ".>", "hH", ";:", "jJ", "yY", "kK", "xX", "wW"],
21132113
"row5": [" "]
21142114
}
2115+
},
2116+
"anishtro": {
2117+
"keymapShowTopRow": false,
2118+
"type": "ansi",
2119+
"keys": {
2120+
"row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"],
2121+
"row2": ["qQ", "lL", "uU", "cC", "jJ", "kK", "pP", "mM", "wW", ";:", "[{", "]}", "\\|"],
2122+
"row3": ["aA", "nN", "iI", "sS", "vV", "bB", "hH", "tT", "rR", "oO", "'\""],
2123+
"row4": [",<", ".>", "yY", "gG", "xX", "zZ", "fF", "dD", "'\"", "-_"],
2124+
"row5": ["eE", " "]
2125+
}
2126+
},
2127+
"BEAKL_Zi": {
2128+
"keymapShowTopRow": false,
2129+
"type": "ansi",
2130+
"keys": {
2131+
"row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"],
2132+
"row2": ["zZ", "yY", "oO", "uU", ";:", "gG", "dD", "nN", "mM", "xX", "[{", "]}", "\\|"],
2133+
"row3": ["qQ", "hH", "eE", "aA", ".>", "cC", "tT", "rR", "sS", "wW", "'\""],
2134+
"row4": ["jJ", "-_", "'\"", "kK", ",<", "bB", "pP", "lL", "fF", "vV"],
2135+
"row5": ["iI", " "]
2136+
}
2137+
},
2138+
"MALTRON": {
2139+
"keymapShowTopRow": false,
2140+
"type": "ansi",
2141+
"keys": {
2142+
"row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"],
2143+
"row2": ["qQ", "pP", "yY", "cC", "bB", "vV", "mM", "uU", "zZ", "lL", "[{", "]}", "\\|"],
2144+
"row3": ["aA", "nN", "iI", "sS", "fF", "dD", "tT", "hH", "oO", "rR", "'\""],
2145+
"row4": [",<", ".>", "jJ", "gG", "'\"", "/?", "wW", "kK", "-_", "xX"],
2146+
"row5": ["eE", " "]
2147+
}
2148+
},
2149+
"PRSTEN": {
2150+
"keymapShowTopRow": false,
2151+
"type": "ansi",
2152+
"keys": {
2153+
"row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"],
2154+
"row2": ["`~", "wW", "cC", "dD", "fF", "qQ", "lL", "uU", "yY", ";:", "[{", "]}", "\\|"],
2155+
"row3": ["pP", "rR", "sS", "tT", "gG", "mM", "nN", "aA", "iI", "oO", "'\""],
2156+
"row4": ["xX", "hH", "vV", "bB", "[{", ",<", "jJ", "kK", "zZ", ".>"],
2157+
"row5": [" ", "eE"]
2158+
}
2159+
},
2160+
"RSTHD": {
2161+
"keymapShowTopRow": false,
2162+
"type": "ansi",
2163+
"keys": {
2164+
"row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"],
2165+
"row2": ["jJ", "cC", "yY", "fF", "kK", "zZ", "lL", ",<", "uU", "qQ", "[{", "]}", "\\|"],
2166+
"row3": ["rR", "sS", "tT", "hH", "dD", "mM", "nN", "aA", "iI", "oO", "'\""],
2167+
"row4": ["/?", "vV", "gG", "pP", "bB", "xX", "wW", ".>", ";:", "-_"],
2168+
"row5": ["eE", " "]
2169+
}
21152170
}
21162171
}

0 commit comments

Comments
 (0)