mirror of
https://github.com/seigler/aurebesh
synced 2025-07-25 08:46:12 +00:00
break components into files
This commit is contained in:
parent
df6c850b3f
commit
6e15a05126
10 changed files with 8714 additions and 8453 deletions
16503
package-lock.json
generated
16503
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -8,6 +8,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@preact/signals": "^1.2.3",
|
||||
"localforage": "^1.10.0",
|
||||
"preact": "^10.13.1",
|
||||
"preact-iso": "^2.6.2",
|
||||
"preact-render-to-string": "^6.4.1",
|
||||
|
|
42
src/components/DualText.tsx
Normal file
42
src/components/DualText.tsx
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { ligatures } from "./store";
|
||||
|
||||
export default function DualText({ children }: { children: string }) {
|
||||
const words: string[] = [];
|
||||
children.split(/\n/).forEach((line, index, lines) => {
|
||||
line.split(/\b(?=\w)/).forEach((word) => {
|
||||
words.push(word);
|
||||
});
|
||||
if (index < lines.length - 1) {
|
||||
words.push("\n");
|
||||
}
|
||||
});
|
||||
return (
|
||||
<span>
|
||||
{words.map((word) => {
|
||||
if (word === "\n") {
|
||||
return <br />;
|
||||
}
|
||||
const letters: string[] = [];
|
||||
for (let i = 0; i < word.length; i += 1) {
|
||||
const nextTwoCharacters = word.slice(i, i + 2);
|
||||
if (ligatures.value.includes(nextTwoCharacters.toLowerCase())) {
|
||||
letters.push(nextTwoCharacters);
|
||||
i += 1;
|
||||
} else {
|
||||
letters.push(nextTwoCharacters[0]);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<span class="dualtext-word">
|
||||
<span class="aurebesh">{word}</span>
|
||||
<div className="dualtext-help">
|
||||
{letters.map((character) => {
|
||||
return <span data-character={character} />;
|
||||
})}
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</span>
|
||||
);
|
||||
}
|
22
src/components/FontPicker.tsx
Normal file
22
src/components/FontPicker.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
import localforage from "localforage";
|
||||
import { fontNames, selectedFont } from "./store";
|
||||
|
||||
export default function FontPicker() {
|
||||
return (
|
||||
<select
|
||||
onChange={(event) => {
|
||||
const newValue = event.currentTarget.value;
|
||||
selectedFont.value = newValue;
|
||||
localforage.setItem("aurebesh-font", newValue);
|
||||
}}
|
||||
>
|
||||
{fontNames.map((font) => {
|
||||
return (
|
||||
<option value={font} selected={font === selectedFont.value}>
|
||||
{font}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
);
|
||||
}
|
202
src/components/Main.tsx
Normal file
202
src/components/Main.tsx
Normal file
|
@ -0,0 +1,202 @@
|
|||
import { computed, effect, signal } from "@preact/signals";
|
||||
import localforage from "localforage";
|
||||
import { useEffect } from "preact/hooks";
|
||||
import ReadingBox from "./ReadingBox";
|
||||
|
||||
const fonts: Record<string, { ligatures: string[]; lowercase: boolean }> = {
|
||||
"AB-Equinox": {
|
||||
ligatures: ["ch", "sh", "th", "ae", "eo", "kh", "ng", "oo"],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-Canon": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-CanonTech": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-Legends": {
|
||||
ligatures: ["ch", "sh", "th", "ae", "eo", "kh", "ng", "oo"],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-LegendsTech": {
|
||||
ligatures: ["ch", "sh", "th", "ae", "eo", "kh", "ng", "oo"],
|
||||
lowercase: false,
|
||||
},
|
||||
"Aurebesh_Rodian-Oblique": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"Aurebesh_Rodian-OblqOutline": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Aurebesh_Rodian: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"Aurebesh_Rodian-Outline": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshTypewriter-Light": {
|
||||
ligatures: [],
|
||||
lowercase: true,
|
||||
},
|
||||
"AurebeshTypewriter-Regular": {
|
||||
ligatures: [],
|
||||
lowercase: true,
|
||||
},
|
||||
Droidobesh: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
LaptiNekAF: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Maulobesh: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Nirvanabesh: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Skyhook: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
};
|
||||
|
||||
const fontNames = Object.keys(fonts);
|
||||
|
||||
const selectedFont = signal("AurebeshAF-Legends");
|
||||
effect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
document.documentElement.style.setProperty(
|
||||
"--font-aurebesh",
|
||||
selectedFont.value
|
||||
);
|
||||
}
|
||||
});
|
||||
const ligatures = computed(() => {
|
||||
return fonts[selectedFont.value].ligatures;
|
||||
});
|
||||
const lowercase = computed(() => {
|
||||
return fonts[selectedFont.value].lowercase;
|
||||
});
|
||||
|
||||
export default function Main() {
|
||||
useEffect(() => {
|
||||
localforage
|
||||
.getItem("aurebesh-font")
|
||||
.then((value) => {
|
||||
if (value != null) {
|
||||
selectedFont.value = `${value}`;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn("Couldn't fetch font preference: ", error);
|
||||
});
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<header>
|
||||
<h1>
|
||||
<DualText>Learn Aurebesh</DualText>
|
||||
</h1>
|
||||
</header>
|
||||
<main>
|
||||
<div class="content">
|
||||
<FontPicker />
|
||||
<ReadingBox />
|
||||
</div>
|
||||
<Reference />
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FontPicker() {
|
||||
return (
|
||||
<select
|
||||
onChange={(event) => {
|
||||
const newValue = event.currentTarget.value;
|
||||
selectedFont.value = newValue;
|
||||
localforage.setItem("aurebesh-font", newValue);
|
||||
}}
|
||||
>
|
||||
{fontNames.map((font) => {
|
||||
return (
|
||||
<option value={font} selected={font === selectedFont.value}>
|
||||
{font}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
);
|
||||
}
|
||||
|
||||
function DualText({ children }: { children: string }) {
|
||||
const words: string[] = [];
|
||||
children.split(/\n/).forEach((line, index, lines) => {
|
||||
line.split(/\b(?=\w)/).forEach((word) => {
|
||||
words.push(word);
|
||||
});
|
||||
if (index < lines.length - 1) {
|
||||
words.push("\n");
|
||||
}
|
||||
});
|
||||
return (
|
||||
<span>
|
||||
{words.map((word) => {
|
||||
if (word === "\n") {
|
||||
return <br />;
|
||||
}
|
||||
const letters: string[] = [];
|
||||
for (let i = 0; i < word.length; i += 1) {
|
||||
const nextTwoCharacters = word.slice(i, i + 2);
|
||||
if (ligatures.value.includes(nextTwoCharacters.toLowerCase())) {
|
||||
letters.push(nextTwoCharacters);
|
||||
i += 1;
|
||||
} else {
|
||||
letters.push(nextTwoCharacters[0]);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<span class="dualtext-word">
|
||||
<span class="aurebesh">{word}</span>
|
||||
<div className="dualtext-help">
|
||||
{letters.map((character) => {
|
||||
return <span data-character={character} />;
|
||||
})}
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function Reference() {
|
||||
return (
|
||||
<aside class="reference">
|
||||
<DualText>
|
||||
{lowercase.value ? "Aa Bb Cc Dd Ee Ff Gg Hh Ii" : "A B C D E F G H I"}
|
||||
</DualText>
|
||||
<DualText>
|
||||
{lowercase.value ? "Jj Kk Ll Mm Nn Oo Pp Qq Rr" : "J K L M N O P Q R"}
|
||||
</DualText>
|
||||
<DualText>
|
||||
{lowercase.value ? "Ss Tt Uu Vv Ww Xx Yy Zz" : "S T U V W X Y Z"}
|
||||
</DualText>
|
||||
<DualText>0 1 2 3 4 5 6 7 8 9</DualText>
|
||||
{ligatures.value.length > 0 && (
|
||||
<DualText>{ligatures.value.join(" ")}</DualText>
|
||||
)}
|
||||
<DualText>{`, . ? ! : ; ' " ( )`}</DualText>
|
||||
</aside>
|
||||
);
|
||||
}
|
58
src/components/ReadingBox.tsx
Normal file
58
src/components/ReadingBox.tsx
Normal file
|
@ -0,0 +1,58 @@
|
|||
import { useSignal } from "@preact/signals";
|
||||
import localforage from "localforage";
|
||||
import { useEffect } from "preact/hooks";
|
||||
import DualText from "./DualText";
|
||||
|
||||
export default function ReadingBox() {
|
||||
const isEditing = useSignal(false);
|
||||
const contents =
|
||||
useSignal(`It is a period of civil war. Rebel spaceships, striking from a hidden base, have won their first victory against the evil Galactic Empire.
|
||||
|
||||
During the battle, Rebel spies managed to steal secret plans to the Empire's ultimate weapon, the DEATH STAR, an armored space station with enough power to destroy an entire planet.
|
||||
|
||||
Pursued by the Empire's sinister agents, Princess Leia races home aboard her starship, custodian of the stolen plans that can save her people and restore freedom to the galaxy...`);
|
||||
useEffect(() => {
|
||||
localforage
|
||||
.getItem("aurebesh-text")
|
||||
.then((value) => {
|
||||
if (value != null) {
|
||||
contents.value = `${value}`;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn("Couldn't fetch stored text: ", error);
|
||||
});
|
||||
}, []);
|
||||
return (
|
||||
<div class="readingbox">
|
||||
<span>
|
||||
<label htmlFor="edit-toggle">Edit</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="edit-toggle"
|
||||
selected={isEditing}
|
||||
onChange={(event) => {
|
||||
isEditing.value = event.currentTarget.checked;
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
{isEditing.value ? (
|
||||
<textarea
|
||||
class="readingbox-textarea"
|
||||
id="reading-material"
|
||||
value={contents}
|
||||
onChange={(event) => {
|
||||
const newValue = event.currentTarget.value;
|
||||
contents.value = newValue;
|
||||
localforage.setItem("aurebesh-text", newValue);
|
||||
}}
|
||||
spellCheck={false}
|
||||
/>
|
||||
) : (
|
||||
<div class="readingbox-text aurebesh">
|
||||
<DualText>{contents.value}</DualText>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
23
src/components/Reference.tsx
Normal file
23
src/components/Reference.tsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import DualText from "./DualText";
|
||||
import { ligatures, lowercase } from "./store";
|
||||
|
||||
export default function Reference() {
|
||||
return (
|
||||
<aside class="reference">
|
||||
<DualText>
|
||||
{lowercase.value ? "Aa Bb Cc Dd Ee Ff Gg Hh Ii" : "A B C D E F G H I"}
|
||||
</DualText>
|
||||
<DualText>
|
||||
{lowercase.value ? "Jj Kk Ll Mm Nn Oo Pp Qq Rr" : "J K L M N O P Q R"}
|
||||
</DualText>
|
||||
<DualText>
|
||||
{lowercase.value ? "Ss Tt Uu Vv Ww Xx Yy Zz" : "S T U V W X Y Z"}
|
||||
</DualText>
|
||||
<DualText>0 1 2 3 4 5 6 7 8 9</DualText>
|
||||
{ligatures.value.length > 0 && (
|
||||
<DualText>{ligatures.value.join(" ")}</DualText>
|
||||
)}
|
||||
<DualText>{`, . ? ! : ; ' " ( )`}</DualText>
|
||||
</aside>
|
||||
);
|
||||
}
|
89
src/components/store.ts
Normal file
89
src/components/store.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
import { computed, effect, signal } from "@preact/signals";
|
||||
|
||||
export const fonts: Record<
|
||||
string,
|
||||
{ ligatures: string[]; lowercase: boolean }
|
||||
> = {
|
||||
"AB-Equinox": {
|
||||
ligatures: ["ch", "sh", "th", "ae", "eo", "kh", "ng", "oo"],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-Canon": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-CanonTech": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-Legends": {
|
||||
ligatures: ["ch", "sh", "th", "ae", "eo", "kh", "ng", "oo"],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-LegendsTech": {
|
||||
ligatures: ["ch", "sh", "th", "ae", "eo", "kh", "ng", "oo"],
|
||||
lowercase: false,
|
||||
},
|
||||
"Aurebesh_Rodian-Oblique": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"Aurebesh_Rodian-OblqOutline": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Aurebesh_Rodian: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"Aurebesh_Rodian-Outline": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshTypewriter-Light": {
|
||||
ligatures: [],
|
||||
lowercase: true,
|
||||
},
|
||||
"AurebeshTypewriter-Regular": {
|
||||
ligatures: [],
|
||||
lowercase: true,
|
||||
},
|
||||
Droidobesh: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
LaptiNekAF: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Maulobesh: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Nirvanabesh: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Skyhook: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const fontNames = Object.keys(fonts);
|
||||
|
||||
export const selectedFont = signal("AurebeshAF-Legends");
|
||||
effect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
document.documentElement.style.setProperty(
|
||||
"--font-aurebesh",
|
||||
selectedFont.value
|
||||
);
|
||||
}
|
||||
});
|
||||
export const ligatures = computed(() => {
|
||||
return fonts[selectedFont.value].ligatures;
|
||||
});
|
||||
export const lowercase = computed(() => {
|
||||
return fonts[selectedFont.value].lowercase;
|
||||
});
|
224
src/index.tsx
224
src/index.tsx
|
@ -1,230 +1,10 @@
|
|||
import { hydrate, prerender as ssr } from "preact-iso";
|
||||
|
||||
import "./style.css";
|
||||
import { computed, effect, signal, useSignal } from "@preact/signals";
|
||||
|
||||
const fonts: Record<string, { ligatures: string[]; lowercase: boolean }> = {
|
||||
"AB-Equinox": {
|
||||
ligatures: ["ch", "sh", "th", "ae", "eo", "kh", "ng", "oo"],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-Canon": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-CanonTech": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-Legends": {
|
||||
ligatures: ["ch", "sh", "th", "ae", "eo", "kh", "ng", "oo"],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshAF-LegendsTech": {
|
||||
ligatures: ["ch", "sh", "th", "ae", "eo", "kh", "ng", "oo"],
|
||||
lowercase: false,
|
||||
},
|
||||
"Aurebesh_Rodian-Oblique": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"Aurebesh_Rodian-OblqOutline": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Aurebesh_Rodian: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"Aurebesh_Rodian-Outline": {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
"AurebeshTypewriter-Light": {
|
||||
ligatures: [],
|
||||
lowercase: true,
|
||||
},
|
||||
"AurebeshTypewriter-Regular": {
|
||||
ligatures: [],
|
||||
lowercase: true,
|
||||
},
|
||||
Droidobesh: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
LaptiNekAF: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Maulobesh: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Nirvanabesh: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
Skyhook: {
|
||||
ligatures: [],
|
||||
lowercase: false,
|
||||
},
|
||||
};
|
||||
|
||||
const fontNames = Object.keys(fonts);
|
||||
|
||||
const selectedFont = signal("AurebeshAF-Legends");
|
||||
effect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
document.documentElement.style.setProperty(
|
||||
"--font-aurebesh",
|
||||
selectedFont.value
|
||||
);
|
||||
}
|
||||
});
|
||||
const ligatures = computed(() => {
|
||||
return fonts[selectedFont.value].ligatures;
|
||||
});
|
||||
const lowercase = computed(() => {
|
||||
return fonts[selectedFont.value].lowercase;
|
||||
});
|
||||
import Main from "./components/Main";
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<>
|
||||
<header>
|
||||
<h1>
|
||||
<DualText>Learn Aurebesh</DualText>
|
||||
</h1>
|
||||
</header>
|
||||
<main>
|
||||
<div class="content">
|
||||
<FontPicker />
|
||||
<ReadingBox />
|
||||
</div>
|
||||
<Reference />
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ReadingBox() {
|
||||
const isEditing = useSignal(false);
|
||||
const contents =
|
||||
useSignal(`It is a period of civil war. Rebel spaceships, striking from a hidden base, have won their first victory against the evil Galactic Empire.
|
||||
|
||||
During the battle, Rebel spies managed to steal secret plans to the Empire's ultimate weapon, the DEATH STAR, an armored space station with enough power to destroy an entire planet.
|
||||
|
||||
Pursued by the Empire's sinister agents, Princess Leia races home aboard her starship, custodian of the stolen plans that can save her people and restore freedom to the galaxy...`);
|
||||
return (
|
||||
<div class="readingbox">
|
||||
<span>
|
||||
<label htmlFor="edit-toggle">Edit</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="edit-toggle"
|
||||
selected={isEditing}
|
||||
onChange={(event) => {
|
||||
isEditing.value = event.currentTarget.checked;
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
{isEditing.value ? (
|
||||
<textarea
|
||||
class="readingbox-textarea"
|
||||
id="reading-material"
|
||||
value={contents}
|
||||
onChange={(event) => {
|
||||
contents.value = event.currentTarget.value;
|
||||
}}
|
||||
spellCheck={false}
|
||||
/>
|
||||
) : (
|
||||
<div class="readingbox-text aurebesh">
|
||||
<DualText>{contents.value}</DualText>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FontPicker() {
|
||||
return (
|
||||
<select
|
||||
onChange={(event) => {
|
||||
selectedFont.value = event.currentTarget.value;
|
||||
}}
|
||||
>
|
||||
{fontNames.map((font) => {
|
||||
return (
|
||||
<option value={font} selected={font === selectedFont.value}>
|
||||
{font}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
);
|
||||
}
|
||||
|
||||
function DualText({ children }: { children: string }) {
|
||||
const words: string[] = [];
|
||||
children.split(/\n/).forEach((line, index, lines) => {
|
||||
line.split(/\b(?=\w)/).forEach((word) => {
|
||||
words.push(word);
|
||||
});
|
||||
if (index < lines.length - 1) {
|
||||
words.push("\n");
|
||||
}
|
||||
});
|
||||
return (
|
||||
<span>
|
||||
{words.map((word) => {
|
||||
if (word === "\n") {
|
||||
return <br />;
|
||||
}
|
||||
const letters: string[] = [];
|
||||
for (let i = 0; i < word.length; i += 1) {
|
||||
const nextTwoCharacters = word.slice(i, i + 2);
|
||||
if (ligatures.value.includes(nextTwoCharacters.toLowerCase())) {
|
||||
letters.push(nextTwoCharacters);
|
||||
i += 1;
|
||||
} else {
|
||||
letters.push(nextTwoCharacters[0]);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<span class="dualtext-word">
|
||||
<span class="aurebesh">{word}</span>
|
||||
<div className="dualtext-help">
|
||||
{letters.map((character) => {
|
||||
return <span data-character={character} />;
|
||||
})}
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function Reference() {
|
||||
return (
|
||||
<aside class="reference">
|
||||
<DualText>
|
||||
{lowercase.value ? "Aa Bb Cc Dd Ee Ff Gg Hh Ii" : "A B C D E F G H I"}
|
||||
</DualText>
|
||||
<DualText>
|
||||
{lowercase.value ? "Jj Kk Ll Mm Nn Oo Pp Qq Rr" : "J K L M N O P Q R"}
|
||||
</DualText>
|
||||
<DualText>
|
||||
{lowercase.value ? "Ss Tt Uu Vv Ww Xx Yy Zz" : "S T U V W X Y Z"}
|
||||
</DualText>
|
||||
<DualText>0 1 2 3 4 5 6 7 8 9</DualText>
|
||||
{ligatures.value.length > 0 && (
|
||||
<DualText>{ligatures.value.join(" ")}</DualText>
|
||||
)}
|
||||
<DualText>{`, . ? ! : ; ' " ( )`}</DualText>
|
||||
</aside>
|
||||
);
|
||||
return <Main />;
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
--font-aurebesh: Droidobesh;
|
||||
--font-standard: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
|
||||
font-size: clamp(100%, 1rem + 2vw, 24px);
|
||||
font-size: clamp(100%, 1.5rem + 3vw, 350%);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
@ -172,6 +172,7 @@ h1 {
|
|||
min-width: 100%;
|
||||
font-family: var(--font-standard);
|
||||
font-size: clamp(0.75rem, 0.25em, 1rem);
|
||||
line-height: 1;
|
||||
font-weight: 400;
|
||||
color: var(--color-text-light);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue