calque/src/routes/(editor).tsx
2024-11-05 16:16:13 +01:00

81 lines
3.1 KiB
TypeScript

import { Link, Title } from "@solidjs/meta";
import { Component, createMemo, createSignal, ErrorBoundary, ParentProps, Show } from "solid-js";
import { BsTranslate } from "solid-icons/bs";
import { FilesProvider } from "~/features/file";
import { CommandPalette, CommandPaletteApi, Menu, MenuProvider } from "~/features/menu";
import { A, createAsync, useBeforeLeave } from "@solidjs/router";
import { createCommand, Modifier } from "~/features/command";
import { ColorScheme, ColorSchemePicker, getColorScheme } from "~/components/colorschemepicker";
import css from "./editor.module.css";
export default function Editor(props: ParentProps) {
const storedColorScheme = createAsync<keyof typeof ColorScheme>(() => getColorScheme(), { initialValue: 'Auto' });
const [commandPalette, setCommandPalette] = createSignal<CommandPaletteApi>();
const colorScheme = createMemo(() => ColorScheme[storedColorScheme()]);
const color = createMemo(() => ({
[ColorScheme.Auto]: undefined,
[ColorScheme.Light]: '#eee',
[ColorScheme.Dark]: '#333',
}[ColorScheme[storedColorScheme()]]));
const commands = [
createCommand('open command palette', () => {
commandPalette()?.show();
}, { key: 'p', modifier: Modifier.Control | Modifier.Shift }),
];
const transition = (done: () => void) => {
if (!document.startViewTransition) { return done() }
const transition = document.startViewTransition(done)
}
useBeforeLeave((e) => {
e.preventDefault()
transition(() => { e.retry(true) })
});
return <MenuProvider commands={commands}>
<Title>Calque</Title>
<meta id="theme-scheme" name="color-scheme" content={colorScheme()} />
<meta id="theme-color" name="theme-color" content={color()} />
<Show when={color() === undefined}>
<meta id="theme-auto-light" name="theme-color" media="(prefers-color-scheme: light)" content="#eee" />
<meta id="theme-auto-dark" name="theme-color" media="(prefers-color-scheme: dark)" content="#333" />
</Show>
<Link rel="icon" href="/images/favicon.dark.svg" media="screen and (prefers-color-scheme: dark)" />
<Link rel="icon" href="/images/favicon.light.svg" media="screen and (prefers-color-scheme: light)" />
<Link rel="manifest" href="/manifest.json" />
<main class={css.layout} inert={commandPalette()?.open()}>
<nav class={css.menu}>
<A class={css.logo} href="/"><BsTranslate /></A>
<Menu.Mount />
<section class={css.right}>
<ColorSchemePicker />
</section>
</nav>
<section>
<ErrorBoundary fallback={err => <ErrorComp error={err.message} />}>
<FilesProvider>
{props.children}
</FilesProvider>
</ErrorBoundary>
</section>
</main>
<CommandPalette api={setCommandPalette} />
</MenuProvider>
}
const ErrorComp: Component<{ error: string }> = (props) => {
return <div class={css.error}>{props.error}</div>
};