mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-09-05 22:28:01 +08:00
refactor: move layout names to contracts (@fehmer) (#6495)
This commit is contained in:
parent
ab9cef010e
commit
b36bc9f39e
10 changed files with 257 additions and 250 deletions
|
@ -46,13 +46,16 @@ For iso the number of keys need to be exactly thirteen for `row1`, twelve for `r
|
|||
|
||||
|
||||
|
||||
In addition to the layout file you need to add your layout to the `frontend/src/ts/constants/layouts.ts` file. Just append your layout name (without the `.json`) at the __end__ of the array. Remember to add a comma like this:
|
||||
In addition to the layout file you need to add your layout to the `packages/contracts/src/schemas/layouts.ts` file. Just append your layout name (without the `.json`) at the __end__ of the `LayoutNameSchema`. Remember to add a comma like this:
|
||||
|
||||
```ts
|
||||
"ergopti",
|
||||
"sword",
|
||||
"YOUR_LAYOUT",
|
||||
];
|
||||
export const LayoutNameSchema = z.enum([
|
||||
"qwerty",
|
||||
"dvorak",
|
||||
"colemak",
|
||||
...
|
||||
"your_layout_name",
|
||||
]);
|
||||
```
|
||||
|
||||
### Committing Layouts
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { readdirSync } from "fs";
|
||||
import { LayoutsList } from "../../src/ts/constants/layouts";
|
||||
import { LayoutName } from "@monkeytype/contracts/schemas/layouts";
|
||||
|
||||
describe("layouts", () => {
|
||||
it("should not have duplicates", () => {
|
||||
|
@ -32,7 +33,7 @@ describe("layouts", () => {
|
|||
});
|
||||
|
||||
function listLayoutFiles() {
|
||||
return readdirSync(import.meta.dirname + "/../../static/layouts").map((it) =>
|
||||
it.substring(0, it.length - 5)
|
||||
return readdirSync(import.meta.dirname + "/../../static/layouts").map(
|
||||
(it) => it.substring(0, it.length - 5) as LayoutName
|
||||
);
|
||||
}
|
||||
|
|
|
@ -439,21 +439,15 @@ describe("Config", () => {
|
|||
});
|
||||
it("setKeymapLayout", () => {
|
||||
expect(Config.setKeymapLayout("overrideSync")).toBe(true);
|
||||
expect(Config.setKeymapLayout("override_sync")).toBe(true);
|
||||
expect(Config.setKeymapLayout("override sync")).toBe(false);
|
||||
expect(Config.setKeymapLayout("override-sync!")).toBe(false);
|
||||
expect(Config.setKeymapLayout(stringOfLength(50))).toBe(true);
|
||||
|
||||
expect(Config.setKeymapLayout(stringOfLength(51))).toBe(false);
|
||||
expect(Config.setKeymapLayout("override_sync" as any)).toBe(false);
|
||||
expect(Config.setKeymapLayout("override sync" as any)).toBe(false);
|
||||
expect(Config.setKeymapLayout("override-sync!" as any)).toBe(false);
|
||||
});
|
||||
it("setLayout", () => {
|
||||
expect(Config.setLayout("semimak")).toBe(true);
|
||||
expect(Config.setLayout("semi_mak")).toBe(true);
|
||||
expect(Config.setLayout(stringOfLength(50))).toBe(true);
|
||||
|
||||
expect(Config.setLayout("semi mak")).toBe(false);
|
||||
expect(Config.setLayout("semi-mak")).toBe(true);
|
||||
expect(Config.setLayout(stringOfLength(51))).toBe(false);
|
||||
expect(Config.setLayout("default")).toBe(true);
|
||||
expect(Config.setLayout("semi_mak" as any)).toBe(false);
|
||||
expect(Config.setLayout("overrideSync" as any)).toBe(false);
|
||||
});
|
||||
it("setFontSize", () => {
|
||||
expect(Config.setFontSize(1)).toBe(true);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { KeymapLayout } from "@monkeytype/contracts/schemas/configs";
|
||||
import * as UpdateConfig from "../../config";
|
||||
import { LayoutsList } from "../../constants/layouts";
|
||||
import * as TestLogic from "../../test/test-logic";
|
||||
|
@ -23,7 +24,7 @@ const subgroup: CommandsSubgroup = {
|
|||
display: layout.replace(/_/g, " "),
|
||||
configValue: layout,
|
||||
exec: (): void => {
|
||||
UpdateConfig.setKeymapLayout(layout);
|
||||
UpdateConfig.setKeymapLayout(layout as KeymapLayout);
|
||||
TestLogic.restart();
|
||||
},
|
||||
})),
|
||||
|
|
|
@ -31,6 +31,7 @@ import { migrateConfig } from "./utils/config";
|
|||
import { roundTo1 } from "@monkeytype/util/numbers";
|
||||
import { getDefaultConfig } from "./constants/default-config";
|
||||
import { LayoutsList } from "./constants/layouts";
|
||||
import { LayoutName } from "@monkeytype/contracts/schemas/layouts";
|
||||
|
||||
const configLS = new LocalStorageWithSchema({
|
||||
key: "config",
|
||||
|
@ -1884,7 +1885,7 @@ export function setCustomLayoutfluid(
|
|||
|
||||
const invalidLayouts = trimmed
|
||||
.split(/[# ]+/) //can be space or hash
|
||||
.filter((it) => !LayoutsList.includes(it));
|
||||
.filter((it) => !LayoutsList.includes(it as LayoutName));
|
||||
|
||||
if (invalidLayouts.length !== 0) {
|
||||
notifyInvalid(
|
||||
|
|
|
@ -1,214 +1,3 @@
|
|||
export const LayoutsList:string[] = [
|
||||
"qwerty",
|
||||
"dvorak",
|
||||
"colemak",
|
||||
"colemak_wide",
|
||||
"colemak_dh",
|
||||
"colemak_dh_iso",
|
||||
"colemak_dh_wide",
|
||||
"colemak_dh_iso_wide",
|
||||
"colemak_dhk",
|
||||
"colemak_dh_matrix",
|
||||
"colemak_dhk_iso",
|
||||
"colemak_dhv",
|
||||
"qwertz",
|
||||
"swiss_german",
|
||||
"swiss_french",
|
||||
"workman",
|
||||
"prog_workman",
|
||||
"turkish_q",
|
||||
"turkish_f",
|
||||
"turkish_e",
|
||||
"MTGAP_ASRT",
|
||||
"norman",
|
||||
"halmak",
|
||||
"QGMLWB",
|
||||
"QGMLWY",
|
||||
"qwpr",
|
||||
"uk_qwerty",
|
||||
"spanish_qwerty",
|
||||
"italian_qwerty",
|
||||
"latam_qwerty",
|
||||
"prog_dvorak",
|
||||
"prog_dvorak_prime",
|
||||
"german_dvorak",
|
||||
"german_dvorak_imp",
|
||||
"spanish_dvorak",
|
||||
"swedish_colemak",
|
||||
"swedish_dvorak",
|
||||
"dvorak_L",
|
||||
"dvorak_R",
|
||||
"dvorak_fr",
|
||||
"azerty",
|
||||
"bepo",
|
||||
"bepo_AFNOR",
|
||||
"alpha",
|
||||
"handsdown",
|
||||
"hungarian",
|
||||
"handsdown_alt",
|
||||
"handsdown_promethium",
|
||||
"typehack",
|
||||
"MTGAP",
|
||||
"MTGAP_full",
|
||||
"ina",
|
||||
"soul",
|
||||
"niro",
|
||||
"mongolian",
|
||||
"JCUKEN",
|
||||
"Diktor",
|
||||
"Diktor_VoronovMod",
|
||||
"Redaktor",
|
||||
"JUIYAF",
|
||||
"Zubachev",
|
||||
"ISRT",
|
||||
"ISRT_Angle",
|
||||
"colemak_Qix",
|
||||
"colemak_Qi",
|
||||
"colemaQ",
|
||||
"colemaQ_F",
|
||||
"engram",
|
||||
"engrammer",
|
||||
"semimak",
|
||||
"semimak_jq",
|
||||
"semimak_jqc",
|
||||
"canary",
|
||||
"canary_matrix",
|
||||
"japanese_hiragana",
|
||||
"boo",
|
||||
"boo_mangle",
|
||||
"APT",
|
||||
"APT_angle",
|
||||
"middlemak",
|
||||
"middlemak-nh",
|
||||
"hindi_inscript",
|
||||
"thai_kedmanee",
|
||||
"thai_pattachote",
|
||||
"thai_manoonchai",
|
||||
"persian_standard",
|
||||
"persian_farsi",
|
||||
"arabic_101",
|
||||
"arabic_102",
|
||||
"arabic_mac",
|
||||
"hebrew",
|
||||
"urdu_phonetic",
|
||||
"brasileiro_nativo",
|
||||
"Foalmak",
|
||||
"quartz",
|
||||
"arensito",
|
||||
"ARTS",
|
||||
"beakl_15",
|
||||
"beakl_19",
|
||||
"beakl_19_bis",
|
||||
"capewell_dvorak",
|
||||
"colman",
|
||||
"heart",
|
||||
"klauser",
|
||||
"oneproduct",
|
||||
"pine",
|
||||
"real",
|
||||
"rolll",
|
||||
"stndc",
|
||||
"three",
|
||||
"uciea",
|
||||
"asset",
|
||||
"dwarf",
|
||||
"flaw",
|
||||
"whorf",
|
||||
"whorf6",
|
||||
"whorfmax",
|
||||
"whorfmax_ortho",
|
||||
"sertain",
|
||||
"ctgap",
|
||||
"octa8",
|
||||
"polish_programmers",
|
||||
"bulgarian",
|
||||
"bulgarian_phonetic_traditional",
|
||||
"belarusian",
|
||||
"ukrainian",
|
||||
"russian",
|
||||
"neo",
|
||||
"bone",
|
||||
"AdNW",
|
||||
"mine",
|
||||
"noted",
|
||||
"koy",
|
||||
"3l",
|
||||
"korean",
|
||||
"ekverto_b",
|
||||
"nerps",
|
||||
"sturdy_angle_ansi",
|
||||
"sturdy_angle_iso",
|
||||
"sturdy_ortho",
|
||||
"ABNT2",
|
||||
"HiYou",
|
||||
"xenia",
|
||||
"xenia_alt",
|
||||
"burmese",
|
||||
"gallium",
|
||||
"gallium_angle",
|
||||
"gallium_v2",
|
||||
"gallium_v2_matrix",
|
||||
"maya",
|
||||
"gallaya_angle_ansi",
|
||||
"gallaya_angle_iso",
|
||||
"gallaya_matrix",
|
||||
"nila",
|
||||
"minimak_4k",
|
||||
"minimak_8k",
|
||||
"minimak_12k",
|
||||
"optimot",
|
||||
"norwegian_qwerty",
|
||||
"portuguese_pt_qwerty_iso",
|
||||
"portuguese_pt_qwerty_ansi",
|
||||
"swedish_qwerty",
|
||||
"danish_qwerty",
|
||||
"noctum",
|
||||
"graphite",
|
||||
"graphite_angle",
|
||||
"graphite_angle_vc",
|
||||
"graphite_angle_kp",
|
||||
"graphite_matrix",
|
||||
"macedonian",
|
||||
"UGJRMV",
|
||||
"pashto",
|
||||
"ORNATE",
|
||||
"estonian",
|
||||
"stronk",
|
||||
"dhorf",
|
||||
"recurva",
|
||||
"seht-drai",
|
||||
"ints",
|
||||
"rollla",
|
||||
"wreathy",
|
||||
"saiga",
|
||||
"saiga-e",
|
||||
"krai",
|
||||
"mir",
|
||||
"ergol",
|
||||
"cascade",
|
||||
"vylet",
|
||||
"hyperroll",
|
||||
"romak",
|
||||
"scythe",
|
||||
"inqwerted",
|
||||
"rain",
|
||||
"night",
|
||||
"whix2",
|
||||
"haruka",
|
||||
"kuntum",
|
||||
"anishtro",
|
||||
"Kuntem",
|
||||
"BEAKL_Zi",
|
||||
"snorkle",
|
||||
"MALTRON",
|
||||
"PRSTEN",
|
||||
"RSTHD",
|
||||
"dusk",
|
||||
"zenith",
|
||||
"focal",
|
||||
"panini",
|
||||
"panini_wide",
|
||||
"ergopti",
|
||||
"sword",
|
||||
"opy",
|
||||
];
|
||||
import { LayoutName, LayoutNameSchema } from "@monkeytype/contracts/schemas/layouts";
|
||||
|
||||
export const LayoutsList:LayoutName[] = LayoutNameSchema._def.values;
|
|
@ -23,6 +23,7 @@ import * as WeakSpot from "../weak-spot";
|
|||
import * as IPAddresses from "../../utils/ip-addresses";
|
||||
import * as TestState from "../test-state";
|
||||
import { WordGenError } from "../../utils/word-gen-error";
|
||||
import { KeymapLayout, Layout } from "@monkeytype/contracts/schemas/configs";
|
||||
|
||||
export type FunboxFunctions = {
|
||||
getWord?: (wordset?: Wordset, wordIndex?: number) => string;
|
||||
|
@ -345,8 +346,8 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
|
|||
applyConfig(): void {
|
||||
const layout = Config.customLayoutfluid.split("#")[0] ?? "qwerty";
|
||||
|
||||
UpdateConfig.setLayout(layout, true);
|
||||
UpdateConfig.setKeymapLayout(layout, true);
|
||||
UpdateConfig.setLayout(layout as Layout, true);
|
||||
UpdateConfig.setKeymapLayout(layout as KeymapLayout, true);
|
||||
},
|
||||
rememberSettings(): void {
|
||||
save("keymapMode", Config.keymapMode, UpdateConfig.setKeymapMode);
|
||||
|
@ -357,8 +358,8 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
|
|||
if (Config.mode !== "time") {
|
||||
// here I need to check if Config.customLayoutFluid exists because of my
|
||||
// scuffed solution of returning whenever value is undefined in the setCustomLayoutfluid function
|
||||
const layouts: string[] = Config.customLayoutfluid
|
||||
? Config.customLayoutfluid.split("#")
|
||||
const layouts: Layout[] = Config.customLayoutfluid
|
||||
? (Config.customLayoutfluid.split("#") as Layout[])
|
||||
: ["qwerty", "dvorak", "colemak"];
|
||||
const outOf: number = TestWords.words.length;
|
||||
const wordsPerLayout = Math.floor(outOf / layouts.length);
|
||||
|
@ -379,8 +380,8 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
|
|||
LayoutfluidFunboxTimer.hide();
|
||||
}
|
||||
if (mod === wordsPerLayout) {
|
||||
UpdateConfig.setLayout(layouts[index] as string);
|
||||
UpdateConfig.setKeymapLayout(layouts[index] as string);
|
||||
UpdateConfig.setLayout(layouts[index] as Layout);
|
||||
UpdateConfig.setKeymapLayout(layouts[index] as KeymapLayout);
|
||||
if (mod > 3) {
|
||||
LayoutfluidFunboxTimer.hide();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import * as TestState from "./test-state";
|
|||
import * as Time from "../states/time";
|
||||
import * as TimerEvent from "../observables/timer-event";
|
||||
import * as LayoutfluidFunboxTimer from "../test/funbox/layoutfluid-funbox-timer";
|
||||
import { KeymapLayout, Layout } from "@monkeytype/contracts/schemas/configs";
|
||||
|
||||
type TimerStats = {
|
||||
dateNow: number;
|
||||
|
@ -118,8 +119,8 @@ function layoutfluid(): void {
|
|||
|
||||
if (Config.layout !== layout && layout !== undefined) {
|
||||
LayoutfluidFunboxTimer.hide();
|
||||
UpdateConfig.setLayout(layout, true);
|
||||
UpdateConfig.setKeymapLayout(layout, true);
|
||||
UpdateConfig.setLayout(layout as Layout, true);
|
||||
UpdateConfig.setKeymapLayout(layout as KeymapLayout, true);
|
||||
}
|
||||
}
|
||||
if (timerDebug) console.timeEnd("layoutfluid");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { z, ZodSchema } from "zod";
|
||||
import { LanguageSchema, token } from "./util";
|
||||
import * as Shared from "./shared";
|
||||
import * as Layouts from "./layouts";
|
||||
|
||||
export const SmoothCaretSchema = z.enum(["off", "slow", "medium", "fast"]);
|
||||
export type SmoothCaret = z.infer<typeof SmoothCaretSchema>;
|
||||
|
@ -269,15 +270,11 @@ export const ThemeNameSchema = token().max(50);
|
|||
export type ThemeName = z.infer<typeof ThemeNameSchema>;
|
||||
|
||||
export const KeymapLayoutSchema = z
|
||||
.string()
|
||||
.max(50)
|
||||
.regex(/^[a-zA-Z0-9\-_]+$/gi);
|
||||
.literal("overrideSync")
|
||||
.or(Layouts.LayoutNameSchema);
|
||||
export type KeymapLayout = z.infer<typeof KeymapLayoutSchema>;
|
||||
|
||||
export const LayoutSchema = z
|
||||
.string()
|
||||
.max(50)
|
||||
.regex(/^[a-zA-Z0-9\-_]+$/gi);
|
||||
export const LayoutSchema = z.literal("default").or(Layouts.LayoutNameSchema);
|
||||
export type Layout = z.infer<typeof LayoutSchema>;
|
||||
|
||||
export const FontSizeSchema = z.number().positive();
|
||||
|
|
219
packages/contracts/src/schemas/layouts.ts
Normal file
219
packages/contracts/src/schemas/layouts.ts
Normal file
|
@ -0,0 +1,219 @@
|
|||
import { z } from "zod";
|
||||
|
||||
export const LayoutNameSchema = z.enum([
|
||||
"qwerty",
|
||||
"dvorak",
|
||||
"colemak",
|
||||
"colemak_wide",
|
||||
"colemak_dh",
|
||||
"colemak_dh_iso",
|
||||
"colemak_dh_wide",
|
||||
"colemak_dh_iso_wide",
|
||||
"colemak_dhk",
|
||||
"colemak_dh_matrix",
|
||||
"colemak_dhk_iso",
|
||||
"colemak_dhv",
|
||||
"qwertz",
|
||||
"swiss_german",
|
||||
"swiss_french",
|
||||
"workman",
|
||||
"prog_workman",
|
||||
"turkish_q",
|
||||
"turkish_f",
|
||||
"turkish_e",
|
||||
"MTGAP_ASRT",
|
||||
"norman",
|
||||
"halmak",
|
||||
"QGMLWB",
|
||||
"QGMLWY",
|
||||
"qwpr",
|
||||
"uk_qwerty",
|
||||
"spanish_qwerty",
|
||||
"italian_qwerty",
|
||||
"latam_qwerty",
|
||||
"prog_dvorak",
|
||||
"prog_dvorak_prime",
|
||||
"german_dvorak",
|
||||
"german_dvorak_imp",
|
||||
"spanish_dvorak",
|
||||
"swedish_colemak",
|
||||
"swedish_dvorak",
|
||||
"dvorak_L",
|
||||
"dvorak_R",
|
||||
"dvorak_fr",
|
||||
"azerty",
|
||||
"bepo",
|
||||
"bepo_AFNOR",
|
||||
"alpha",
|
||||
"handsdown",
|
||||
"hungarian",
|
||||
"handsdown_alt",
|
||||
"handsdown_promethium",
|
||||
"typehack",
|
||||
"MTGAP",
|
||||
"MTGAP_full",
|
||||
"ina",
|
||||
"soul",
|
||||
"niro",
|
||||
"mongolian",
|
||||
"JCUKEN",
|
||||
"Diktor",
|
||||
"Diktor_VoronovMod",
|
||||
"Redaktor",
|
||||
"JUIYAF",
|
||||
"Zubachev",
|
||||
"ISRT",
|
||||
"ISRT_Angle",
|
||||
"colemak_Qix",
|
||||
"colemak_Qi",
|
||||
"colemaQ",
|
||||
"colemaQ_F",
|
||||
"engram",
|
||||
"engrammer",
|
||||
"semimak",
|
||||
"semimak_jq",
|
||||
"semimak_jqc",
|
||||
"canary",
|
||||
"canary_matrix",
|
||||
"japanese_hiragana",
|
||||
"boo",
|
||||
"boo_mangle",
|
||||
"APT",
|
||||
"APT_angle",
|
||||
"middlemak",
|
||||
"middlemak-nh",
|
||||
"hindi_inscript",
|
||||
"thai_kedmanee",
|
||||
"thai_pattachote",
|
||||
"thai_manoonchai",
|
||||
"persian_standard",
|
||||
"persian_farsi",
|
||||
"arabic_101",
|
||||
"arabic_102",
|
||||
"arabic_mac",
|
||||
"hebrew",
|
||||
"urdu_phonetic",
|
||||
"brasileiro_nativo",
|
||||
"Foalmak",
|
||||
"quartz",
|
||||
"arensito",
|
||||
"ARTS",
|
||||
"beakl_15",
|
||||
"beakl_19",
|
||||
"beakl_19_bis",
|
||||
"capewell_dvorak",
|
||||
"colman",
|
||||
"heart",
|
||||
"klauser",
|
||||
"oneproduct",
|
||||
"pine",
|
||||
"real",
|
||||
"rolll",
|
||||
"stndc",
|
||||
"three",
|
||||
"uciea",
|
||||
"asset",
|
||||
"dwarf",
|
||||
"flaw",
|
||||
"whorf",
|
||||
"whorf6",
|
||||
"whorfmax",
|
||||
"whorfmax_ortho",
|
||||
"sertain",
|
||||
"ctgap",
|
||||
"octa8",
|
||||
"polish_programmers",
|
||||
"bulgarian",
|
||||
"bulgarian_phonetic_traditional",
|
||||
"belarusian",
|
||||
"ukrainian",
|
||||
"russian",
|
||||
"neo",
|
||||
"bone",
|
||||
"AdNW",
|
||||
"mine",
|
||||
"noted",
|
||||
"koy",
|
||||
"3l",
|
||||
"korean",
|
||||
"ekverto_b",
|
||||
"nerps",
|
||||
"sturdy_angle_ansi",
|
||||
"sturdy_angle_iso",
|
||||
"sturdy_ortho",
|
||||
"ABNT2",
|
||||
"HiYou",
|
||||
"xenia",
|
||||
"xenia_alt",
|
||||
"burmese",
|
||||
"gallium",
|
||||
"gallium_angle",
|
||||
"gallium_v2",
|
||||
"gallium_v2_matrix",
|
||||
"maya",
|
||||
"gallaya_angle_ansi",
|
||||
"gallaya_angle_iso",
|
||||
"gallaya_matrix",
|
||||
"nila",
|
||||
"minimak_4k",
|
||||
"minimak_8k",
|
||||
"minimak_12k",
|
||||
"optimot",
|
||||
"norwegian_qwerty",
|
||||
"portuguese_pt_qwerty_iso",
|
||||
"portuguese_pt_qwerty_ansi",
|
||||
"swedish_qwerty",
|
||||
"danish_qwerty",
|
||||
"noctum",
|
||||
"graphite",
|
||||
"graphite_angle",
|
||||
"graphite_angle_vc",
|
||||
"graphite_angle_kp",
|
||||
"graphite_matrix",
|
||||
"macedonian",
|
||||
"UGJRMV",
|
||||
"pashto",
|
||||
"ORNATE",
|
||||
"estonian",
|
||||
"stronk",
|
||||
"dhorf",
|
||||
"recurva",
|
||||
"seht-drai",
|
||||
"ints",
|
||||
"rollla",
|
||||
"wreathy",
|
||||
"saiga",
|
||||
"saiga-e",
|
||||
"krai",
|
||||
"mir",
|
||||
"ergol",
|
||||
"cascade",
|
||||
"vylet",
|
||||
"hyperroll",
|
||||
"romak",
|
||||
"scythe",
|
||||
"inqwerted",
|
||||
"rain",
|
||||
"night",
|
||||
"whix2",
|
||||
"haruka",
|
||||
"kuntum",
|
||||
"anishtro",
|
||||
"Kuntem",
|
||||
"BEAKL_Zi",
|
||||
"snorkle",
|
||||
"MALTRON",
|
||||
"PRSTEN",
|
||||
"RSTHD",
|
||||
"dusk",
|
||||
"zenith",
|
||||
"focal",
|
||||
"panini",
|
||||
"panini_wide",
|
||||
"ergopti",
|
||||
"sword",
|
||||
"opy",
|
||||
]
|
||||
);
|
||||
|
||||
export type LayoutName = z.infer<typeof LayoutNameSchema>;
|
Loading…
Add table
Reference in a new issue