This commit is contained in:
Joshua Seigler 2024-04-07 22:58:50 -04:00
parent 6e15a05126
commit 1c6067a2cb
6 changed files with 52 additions and 201 deletions

View file

@ -1,8 +1,8 @@
import { ligatures } from "./store";
export default function DualText({ children }: { children: string }) {
export default function DualText({ text }: { text: string }) {
const words: string[] = [];
children.split(/\n/).forEach((line, index, lines) => {
text.split(/\n/).forEach((line, index, lines) => {
line.split(/\b(?=\w)/).forEach((word) => {
words.push(word);
});
@ -10,6 +10,8 @@ export default function DualText({ children }: { children: string }) {
words.push("\n");
}
});
const currentLigatures = ligatures.value;
return (
<span>
{words.map((word) => {
@ -19,7 +21,7 @@ export default function DualText({ children }: { children: string }) {
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())) {
if (currentLigatures.includes(nextTwoCharacters.toLowerCase())) {
letters.push(nextTwoCharacters);
i += 1;
} else {
@ -27,8 +29,8 @@ export default function DualText({ children }: { children: string }) {
}
}
return (
<span class="dualtext-word">
<span class="aurebesh">{word}</span>
<span class="dualtext-word aurebesh">
{word}
<div className="dualtext-help">
{letters.map((character) => {
return <span data-character={character} />;

View file

@ -1,92 +1,10 @@
import { computed, effect, signal } from "@preact/signals";
import localforage from "localforage";
import { useEffect } from "preact/hooks";
import { selectedFont } from "./store";
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;
});
import Reference from "./Reference";
import FontPicker from "./FontPicker";
import DualText from "./DualText";
export default function Main() {
useEffect(() => {
@ -105,7 +23,7 @@ export default function Main() {
<>
<header>
<h1>
<DualText>Learn Aurebesh</DualText>
<DualText text="Learn Aurebesh" />
</h1>
</header>
<main>
@ -118,85 +36,3 @@ export default function 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>
);
}

View file

@ -36,7 +36,7 @@ Pursued by the Empire's sinister agents, Princess Leia races home aboard her sta
}}
/>
</span>
{isEditing.value ? (
{isEditing.value && (
<textarea
class="readingbox-textarea"
id="reading-material"
@ -48,11 +48,10 @@ Pursued by the Empire's sinister agents, Princess Leia races home aboard her sta
}}
spellCheck={false}
/>
) : (
<div class="readingbox-text aurebesh">
<DualText>{contents.value}</DualText>
</div>
)}
<div class="readingbox-text aurebesh">
<DualText text={contents.value} />
</div>
</div>
);
}

View file

@ -4,20 +4,18 @@ 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>
<DualText
text={
lowercase.value
? "Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm Nn Oo Pp Qq Rr Ss Tt Uu Vv Ww Xx Yy Zz"
: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
}
/>
<DualText text="0 1 2 3 4 5 6 7 8 9" />
{ligatures.value.length > 0 && (
<DualText>{ligatures.value.join(" ")}</DualText>
<DualText text={ligatures.value.join(" ")} />
)}
<DualText>{`, . ? ! : ; ' " ( )`}</DualText>
<DualText text={`, . ? ! : ; ' " ( )`} />
</aside>
);
}

View file

@ -72,7 +72,7 @@ export const fonts: Record<
export const fontNames = Object.keys(fonts);
export const selectedFont = signal("AurebeshAF-Legends");
export const selectedFont = signal("AurebeshAF-Canon");
effect(() => {
if (typeof window !== "undefined") {
document.documentElement.style.setProperty(

View file

@ -5,18 +5,22 @@
@font-face {
font-family: "AurebeshAF-Canon";
src: url(/fonts/AurebeshAF-Canon.otf) format("opentype");
size-adjust: 80%;
}
@font-face {
font-family: "AurebeshAF-CanonTech";
src: url(/fonts/AurebeshAF-CanonTech.otf) format("opentype");
size-adjust: 80%;
}
@font-face {
font-family: "AurebeshAF-Legends";
src: url(/fonts/AurebeshAF-Legends.otf) format("opentype");
size-adjust: 80%;
}
@font-face {
font-family: "AurebeshAF-LegendsTech";
src: url(/fonts/AurebeshAF-LegendsTech.otf) format("opentype");
size-adjust: 80%;
}
@font-face {
font-family: "Aurebesh_Rodian-Oblique";
@ -86,7 +90,7 @@
--font-aurebesh: Droidobesh;
--font-standard: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
font-size: clamp(100%, 1.5rem + 3vw, 350%);
font-size: clamp(100%, 0.5rem + 1vw, 150%);
box-sizing: border-box;
}
@ -108,6 +112,17 @@ body {
);
}
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
font-size: 100%;
line-height: 1.15;
margin: 0;
}
#app {
flex-grow: 1;
display: flex;
@ -121,10 +136,11 @@ body {
}
h1 {
font-size: clamp(1rem, 3rem, 9vw);
font-size: clamp(1rem, 1.75rem, 9vw);
}
.aurebesh {
font-size: 1.5em;
font-family: var(--font-aurebesh);
}
@ -153,7 +169,8 @@ h1 {
.dualtext-help > span {
position: relative;
min-width: 0;
transition: opacity 0.25s ease-in;
transition: opacity 0.1s ease-in;
transition-delay: 0.15s;
}
.dualtext-help > span::before {
content: attr(data-character);
@ -171,18 +188,17 @@ h1 {
padding: 0.1em 0.25em;
min-width: 100%;
font-family: var(--font-standard);
font-size: clamp(0.75rem, 0.25em, 1rem);
font-size: clamp(0.75rem, 0.4em, 1rem);
line-height: 1;
font-weight: 400;
color: var(--color-text-light);
}
.reference {
font-size: clamp(1rem, 1.5rem, 6vw);
display: flex;
flex-direction: column;
gap: 0.5rem;
padding-bottom: 1rem;
gap: 0.5em;
padding-bottom: 1em;
}
main {
@ -203,7 +219,6 @@ main {
width: 100%;
display: flex;
flex-direction: column;
overflow: scroll;
padding: 1em;
}
@ -232,5 +247,6 @@ main {
}
.readingbox .dualtext-help > span:hover {
opacity: 1;
outline: 1px solid var(--color-accent2);
box-shadow: 0 0 1em 0.2em var(--color-accent2);
border-radius: 0.25em;
}