diff options
author | Sergi Meseguer <[email protected]> | 2024-11-19 00:45:06 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2024-11-19 00:45:06 +0100 |
commit | 50639faa1d9f6e9c47158767cdaf7a26c2509b9a (patch) | |
tree | 5b5012f6fd9f296c0807c9744adce868fab1466d | |
parent | 221e70650ac6ef85852071f80e11c45592a9caaa (diff) | |
download | monkeytype-50639faa1d9f6e9c47158767cdaf7a26c2509b9a.tar.gz monkeytype-50639faa1d9f6e9c47158767cdaf7a26c2509b9a.zip |
impr(layouts): add basic support for thumb alpha keys (@zigotica) (#6023)
-rw-r--r-- | frontend/scripts/json-validation.cjs | 8 | ||||
-rw-r--r-- | frontend/src/styles/keymap.scss | 104 | ||||
-rw-r--r-- | frontend/src/ts/elements/keymap.ts | 87 | ||||
-rw-r--r-- | frontend/static/layouts/_list.json | 55 |
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('"', """); + // 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", " "] + } } } |