aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSergi Meseguer <[email protected]>2024-11-19 00:45:06 +0100
committerGitHub <[email protected]>2024-11-19 00:45:06 +0100
commit50639faa1d9f6e9c47158767cdaf7a26c2509b9a (patch)
tree5b5012f6fd9f296c0807c9744adce868fab1466d
parent221e70650ac6ef85852071f80e11c45592a9caaa (diff)
downloadmonkeytype-50639faa1d9f6e9c47158767cdaf7a26c2509b9a.tar.gz
monkeytype-50639faa1d9f6e9c47158767cdaf7a26c2509b9a.zip
impr(layouts): add basic support for thumb alpha keys (@zigotica) (#6023)
-rw-r--r--frontend/scripts/json-validation.cjs8
-rw-r--r--frontend/src/styles/keymap.scss104
-rw-r--r--frontend/src/ts/elements/keymap.ts87
-rw-r--r--frontend/static/layouts/_list.json55
4 files changed, 227 insertions, 27 deletions
diff --git a/frontend/scripts/json-validation.cjs b/frontend/scripts/json-validation.cjs
index 2fd24b947..67ec3e375 100644
--- a/frontend/scripts/json-validation.cjs
+++ b/frontend/scripts/json-validation.cjs
@@ -236,9 +236,9 @@ function validateOthers() {
},
row5: {
type: "array",
- items: { type: "string", minLength: 1, maxLength: 1 },
+ items: { type: "string", minLength: 1, maxLength: 2 },
minItems: 1,
- maxItems: 1,
+ maxItems: 2,
},
},
required: ["row1", "row2", "row3", "row4", "row5"],
@@ -280,9 +280,9 @@ function validateOthers() {
},
row5: {
type: "array",
- items: { type: "string", minLength: 1, maxLength: 1 },
+ items: { type: "string", minLength: 1, maxLength: 2 },
minItems: 1,
- maxItems: 1,
+ maxItems: 2,
},
},
required: ["row1", "row2", "row3", "row4", "row5"],
diff --git a/frontend/src/styles/keymap.scss b/frontend/src/styles/keymap.scss
index d4148435a..078df6d6c 100644
--- a/frontend/src/styles/keymap.scss
+++ b/frontend/src/styles/keymap.scss
@@ -101,7 +101,7 @@
.r5 {
display: grid;
grid-template-columns: 3.5fr 6fr 3.5fr;
- font-size: 0.5rem;
+ font-size: 1rem;
// &.matrixSpace {
// // grid-template-columns: 6.75fr 1.9fr 6.75fr;
// grid-template-columns: 6.9fr 4.6fr 6.9fr; // wider spacebar
@@ -110,6 +110,24 @@
// // grid-template-columns: 6.75fr 1.9fr 6.75fr;
// grid-template-columns: 4fr 7.5fr 4fr;
// }
+ .keySpace {
+ // since we can potentially have alphas in r5,
+ // we keep font-size: 1rem; for alphas to look the same as other rows,
+ // but reduce it again to 0.5rem for space, so layout name fits.
+ font-size: 0.5rem;
+ }
+
+ &[data-row5-has-alpha="true"] {
+ // space-alpha
+ &[data-row5-grid="3-1"] {
+ grid-template-columns: 4fr 4fr 1fr 4fr;
+ }
+
+ // alpha-space
+ &[data-row5-grid="1-3"] {
+ grid-template-columns: 4fr 1fr 4fr 4fr;
+ }
+ }
}
&.matrix {
.r1,
@@ -121,6 +139,18 @@
.r5 {
grid-template-columns: 1fr 3fr 4fr 3fr 1fr;
+
+ &[data-row5-has-alpha="true"] {
+ // space-alpha
+ &[data-row5-grid="3-1"] {
+ grid-template-columns: 1fr 2fr 3fr 1fr 5fr;
+ }
+
+ // alpha-space
+ &[data-row5-grid="1-3"] {
+ grid-template-columns: 2fr 3fr 1fr 3fr 3fr;
+ }
+ }
}
}
&.split {
@@ -152,6 +182,18 @@
}
.r5 {
grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr;
+
+ &[data-row5-has-alpha="true"] {
+ // space-alpha
+ &[data-row5-grid="3-1"] {
+ grid-template-columns: 5fr 3fr 1fr 1fr 6.5fr;
+ }
+
+ // alpha-space
+ &[data-row5-grid="1-3"] {
+ grid-template-columns: 7fr 1fr 1fr 3fr 4.5fr;
+ }
+ }
}
.keySpace.right {
opacity: 1;
@@ -180,6 +222,18 @@
.r5 {
grid-template-columns: 1fr 2fr 3fr 1fr 3fr 2fr 1fr;
+
+ &[data-row5-has-alpha="true"] {
+ // space-alpha
+ &[data-row5-grid="3-1"] {
+ grid-template-columns: 2fr 1fr 3fr 1fr 1fr 2fr 3fr;
+ }
+
+ // alpha-space
+ &[data-row5-grid="1-3"] {
+ grid-template-columns: 4fr 1fr 1fr 1fr 3fr 1fr 2fr;
+ }
+ }
}
.keySpace.right {
opacity: 1;
@@ -433,20 +487,42 @@
}
.r5 {
grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr;
- }
- .keySpace.right {
- opacity: 1;
- }
- div.keySpace {
- transform: rotate(10deg);
- margin-left: -5%;
- margin-top: 21%;
- }
- div.keySpace.right {
- transform: rotate(-10deg);
- margin-left: -33%;
- margin-top: 20%;
+ // rotation/position of r5 keys moved under .r5 styles
+ // and made generic to left/right to account for alphas
+ div.keymapKey.left {
+ transform: rotate(10deg);
+ margin-left: -5%;
+ margin-top: 21%;
+ }
+ div.keymapKey.right {
+ opacity: 1;
+ transform: rotate(-10deg);
+ margin-left: -33%;
+ margin-top: 20%;
+ }
+
+ &[data-row5-has-alpha="true"] {
+ // space-alpha
+ &[data-row5-grid="3-1"] {
+ grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr;
+
+ div.keymapKey.right {
+ margin-left: -30%;
+ margin-top: 25%;
+ }
+ }
+
+ // alpha-space
+ &[data-row5-grid="1-3"] {
+ grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr;
+
+ div.keymapKey.left {
+ margin-left: 50%;
+ margin-top: 25%;
+ }
+ }
+ }
}
div#KeyBackslash.keymapKey {
visibility: hidden;
diff --git a/frontend/src/ts/elements/keymap.ts b/frontend/src/ts/elements/keymap.ts
index 1c2c11e7f..ed58159af 100644
--- a/frontend/src/ts/elements/keymap.ts
+++ b/frontend/src/ts/elements/keymap.ts
@@ -113,6 +113,8 @@ export async function refresh(
if (Config.keymapMode === "off") return;
if (ActivePage.get() !== "test") return;
if (!layoutName) return;
+ let r5_grid = "";
+ let hasAlphas = false;
try {
let layouts;
try {
@@ -153,6 +155,8 @@ export async function refresh(
const isSteno =
Config.keymapStyle === "steno" || Config.keymapStyle === "steno_matrix";
+ const isAlice = Config.keymapStyle === "alice";
+
if (isSteno) {
lts = stenoKeys;
}
@@ -203,19 +207,76 @@ export async function refresh(
if (row === "row5") {
if (isSteno) continue;
- const layoutDisplay = layoutString.replace(/_/g, " ");
+ let layoutDisplay = layoutString.replace(/_/g, " ");
let letterStyle = "";
if (Config.keymapLegendStyle === "blank") {
letterStyle = `style="display: none;"`;
}
+ /* ROW 5 in alternate keymaps allow for alphas in thumb keys.
+ * These keymaps MUST include two keys in row 5,
+ * an alpha and a space, or a space and an alpha.
+ * Alpha key is rendered with the regular alpha size.
+ * Layout name is automatically added in the space key.
+ * Visual keymap will be:
+ * 1-3 for 1 alpha and 1 space
+ * 3-1 for 1 space and 1 alpha
+ * Together with the data-row5-has-alpha="true",
+ * these two will be used to edit the CSS grid layout.
+ * 3-3 for two spaces of size 3. This will not be used to edit CSS,
+ * since it means a traditional layout, can keep current CSS grid.
+ * It is just created for simplicity in the for loop below.
+ * */
+ // If only one space, add another
+ if (rowKeys.length === 1 && rowKeys[0] === " ") {
+ rowKeys[1] = rowKeys[0];
+ }
+ // If only one alpha, add one space and place it on the left
+ if (rowKeys.length === 1 && rowKeys[0] !== " ") {
+ rowKeys[1] = " ";
+ rowKeys.reverse();
+ }
+ // If two alphas equal, replace one with a space on the left
+ if (
+ rowKeys.length > 1 &&
+ rowKeys[0] !== " " &&
+ rowKeys[0] === rowKeys[1]
+ ) {
+ rowKeys[0] = " ";
+ }
+ const alphas = (v: string): boolean => v !== " ";
+ hasAlphas = rowKeys.some(alphas);
+
rowElement += "<div></div>";
- rowElement += `<div class="keymapKey keySpace layoutIndicator left">
- <div class="letter" ${letterStyle}>${layoutDisplay}</div>
- </div>`;
- rowElement += `<div class="keymapSplitSpacer"></div>`;
- rowElement += `<div class="keymapKey keySpace right">
- <div class="letter"></div>
- </div>`;
+
+ for (let i = 0; i < rowKeys.length; i++) {
+ const key = rowKeys[i] as string;
+ let keyDisplay = key[0] as string;
+ if (Config.keymapLegendStyle === "uppercase") {
+ keyDisplay = keyDisplay.toUpperCase();
+ }
+ const keyVisualValue = key.replace('"', "&quot;");
+ // these are used to keep grid layout but magically hide keys using opacity:
+ let side = i < 1 ? "left" : "right";
+ // we won't use this trick for alternate layouts, unless Alice (for rotation):
+ if (hasAlphas && !isAlice) side = "";
+ if (i === 1) {
+ rowElement += `<div class="keymapSplitSpacer"></div>`;
+ r5_grid += "-";
+ }
+ if (keyVisualValue === " ") {
+ rowElement += `<div class="keymapKey keySpace layoutIndicator ${side}">
+ <div class="letter" ${letterStyle}>${layoutDisplay}</div>
+ </div>`;
+ r5_grid += "3";
+ // potential second space in next loop iterations will be empty:
+ layoutDisplay = "";
+ } else {
+ rowElement += `<div class="keymapKey ${side}">
+ <div class="letter">${keyDisplay}</div>
+ </div>`;
+ r5_grid += "1";
+ }
+ }
} else {
for (let i = 0; i < rowKeys.length; i++) {
if (row === "row2" && i === 12) continue;
@@ -309,7 +370,15 @@ export async function refresh(
}
}
- keymapElement += `<div class="row r${index + 1}">${rowElement}</div>`;
+ if (row === "row5") {
+ keymapElement += `<div
+ class="row r${index + 1}"
+ data-row5-grid="${r5_grid}"
+ data-row5-has-alpha="${hasAlphas}"
+ >${rowElement}</div>`;
+ } else {
+ keymapElement += `<div class="row r${index + 1}">${rowElement}</div>`;
+ }
}
// );
diff --git a/frontend/static/layouts/_list.json b/frontend/static/layouts/_list.json
index 67a0682ef..f26065dcc 100644
--- a/frontend/static/layouts/_list.json
+++ b/frontend/static/layouts/_list.json
@@ -2112,5 +2112,60 @@
"row4": [",<", "/?", ".>", "hH", ";:", "jJ", "yY", "kK", "xX", "wW"],
"row5": [" "]
}
+ },
+ "anishtro": {
+ "keymapShowTopRow": false,
+ "type": "ansi",
+ "keys": {
+ "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"],
+ "row2": ["qQ", "lL", "uU", "cC", "jJ", "kK", "pP", "mM", "wW", ";:", "[{", "]}", "\\|"],
+ "row3": ["aA", "nN", "iI", "sS", "vV", "bB", "hH", "tT", "rR", "oO", "'\""],
+ "row4": [",<", ".>", "yY", "gG", "xX", "zZ", "fF", "dD", "'\"", "-_"],
+ "row5": ["eE", " "]
+ }
+ },
+ "BEAKL_Zi": {
+ "keymapShowTopRow": false,
+ "type": "ansi",
+ "keys": {
+ "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"],
+ "row2": ["zZ", "yY", "oO", "uU", ";:", "gG", "dD", "nN", "mM", "xX", "[{", "]}", "\\|"],
+ "row3": ["qQ", "hH", "eE", "aA", ".>", "cC", "tT", "rR", "sS", "wW", "'\""],
+ "row4": ["jJ", "-_", "'\"", "kK", ",<", "bB", "pP", "lL", "fF", "vV"],
+ "row5": ["iI", " "]
+ }
+ },
+ "MALTRON": {
+ "keymapShowTopRow": false,
+ "type": "ansi",
+ "keys": {
+ "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"],
+ "row2": ["qQ", "pP", "yY", "cC", "bB", "vV", "mM", "uU", "zZ", "lL", "[{", "]}", "\\|"],
+ "row3": ["aA", "nN", "iI", "sS", "fF", "dD", "tT", "hH", "oO", "rR", "'\""],
+ "row4": [",<", ".>", "jJ", "gG", "'\"", "/?", "wW", "kK", "-_", "xX"],
+ "row5": ["eE", " "]
+ }
+ },
+ "PRSTEN": {
+ "keymapShowTopRow": false,
+ "type": "ansi",
+ "keys": {
+ "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"],
+ "row2": ["`~", "wW", "cC", "dD", "fF", "qQ", "lL", "uU", "yY", ";:", "[{", "]}", "\\|"],
+ "row3": ["pP", "rR", "sS", "tT", "gG", "mM", "nN", "aA", "iI", "oO", "'\""],
+ "row4": ["xX", "hH", "vV", "bB", "[{", ",<", "jJ", "kK", "zZ", ".>"],
+ "row5": [" ", "eE"]
+ }
+ },
+ "RSTHD": {
+ "keymapShowTopRow": false,
+ "type": "ansi",
+ "keys": {
+ "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"],
+ "row2": ["jJ", "cC", "yY", "fF", "kK", "zZ", "lL", ",<", "uU", "qQ", "[{", "]}", "\\|"],
+ "row3": ["rR", "sS", "tT", "hH", "dD", "mM", "nN", "aA", "iI", "oO", "'\""],
+ "row4": ["/?", "vV", "gG", "pP", "bB", "xX", "wW", ".>", ";:", "-_"],
+ "row5": ["eE", " "]
+ }
}
}