This commit is contained in:
Joshua Seigler 2024-04-07 02:36:46 -04:00
parent 63216d92cd
commit 26b3e5f2ad
2 changed files with 83 additions and 5 deletions

View file

@ -1,7 +1,7 @@
import { hydrate, prerender as ssr } from "preact-iso";
import "./style.css";
import { computed, effect, signal } from "@preact/signals";
import { computed, effect, signal, useSignal } from "@preact/signals";
const fonts: Record<string, { ligatures: string[]; lowercase: boolean }> = {
"AB-Equinox": {
@ -97,6 +97,7 @@ export function App() {
<main>
<div class="content">
<FontPicker />
<ReadingBox />
</div>
<aside class="reference">
<DualText>
@ -123,6 +124,46 @@ export function App() {
);
}
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
@ -142,14 +183,25 @@ function FontPicker() {
}
function DualText({ children }: { children: string }) {
const words = children.split(/\b/);
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)) {
if (ligatures.value.includes(nextTwoCharacters.toLowerCase())) {
letters.push(nextTwoCharacters);
i += 1;
} else {

View file

@ -153,6 +153,7 @@ h1 {
.dualtext-help > span {
position: relative;
min-width: 0;
transition: all 0.25s ease-in;
}
.dualtext-help > span::before {
content: attr(data-character);
@ -168,7 +169,7 @@ h1 {
margin: auto;
font-family: var(--font-standard);
font-style: italic;
font-size: 0.5em;
font-size: clamp(0.45rem, 0.25em, 1rem);
font-weight: 400;
color: var(--color-text-light);
}
@ -183,6 +184,31 @@ h1 {
main {
display: flex;
flex-direction: column;
max-width: 60rem;
width: 100%;
max-width: 40rem;
margin: 0 auto;
}
.readingbox {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.readingbox-text {
width: 100%;
display: flex;
flex-direction: column;
overflow: scroll;
}
.readingbox .dualtext-help {
pointer-events: all;
}
.readingbox .dualtext-help > span {
opacity: 0;
--color-text-light: var(--color-accent1);
}
.readingbox .dualtext-help > span:hover {
opacity: 1;
}