import/export theme

This commit is contained in:
Vinzenz Schroeter 2024-05-07 14:47:48 +02:00
parent e854f77bdc
commit d4d2b6397c
5 changed files with 56 additions and 17 deletions

View file

@ -34,7 +34,7 @@ export default function JoinForm({onDone}: {
<TextInput
value={name}
placeholder="player name"
onChange={e => setName(e.target.value)}
onChange={n => setName(n)}
onEnter={confirm}
/>
<Button

View file

@ -7,6 +7,7 @@ import Column from './components/Column.tsx';
import Button from './components/Button.tsx';
import Row from './components/Row.tsx';
import './MapChooser.css';
import Spacer from './components/Spacer.tsx';
function base64ToArrayBuffer(base64: string) {
const binaryString = atob(base64);
@ -57,7 +58,7 @@ function MapChooserDialog({mapNames, onClose, onConfirm}: {
readonly onClose: () => void;
}) {
const [chosenMap, setChosenMap] = useState<string>();
return <Dialog title='Choose a map' onClose={onClose}>
return <Dialog title="Choose a map" onClose={onClose}>
<Row className="MapChooser-Row overflow-scroll">
{mapNames.map(name => <MapPreview
key={name}
@ -67,7 +68,7 @@ function MapChooserDialog({mapNames, onClose, onConfirm}: {
/>)}
</Row>
<Row>
<div className="flex-grow"/>
<Spacer/>
<Button text="« cancel" onClick={onClose}/>
<Button text="√ confirm" disabled={!chosenMap} onClick={() => chosenMap && onConfirm(chosenMap)}/>
</Row>

View file

@ -1,27 +1,28 @@
import Button from './components/Button.tsx';
import {getRandomTheme, HSL, hslToString, useHslTheme} from './theme.tsx';
import Dialog from './components/Dialog.tsx';
import {useState} from 'react';
import {NumberInput, RangeInput} from './components/Input.tsx';
import {useMemo, useState} from 'react';
import {NumberInput, RangeInput, TextInput} from './components/Input.tsx';
import Row from './components/Row.tsx';
import Column from './components/Column.tsx';
import './ThemeChooser.css';
import Spacer from './components/Spacer.tsx';
function HslEditor({name, value, setValue}: {
name: string;
value: HSL;
setValue: (value: HSL) => void
}) {
const setH = (h: number) => setValue({...value, h});
const setS = (s: number) => setValue({...value, s});
const setL = (l: number) => setValue({...value, l});
const setH = (h: number) => setValue({...value, h});
const setS = (s: number) => setValue({...value, s});
const setL = (l: number) => setValue({...value, l});
return <Column>
<Row>
<div className="" style={{background: hslToString(value), border: '1px solid white', aspectRatio: '1'}}/>
<p>{name}</p>
</Row>
<div className='HslEditor-Inputs'>
<div className="HslEditor-Inputs">
<p>Hue</p>
<NumberInput value={Math.round(value.h)} onChange={setH}/>
<RangeInput value={Math.round(value.h)} min={0} max={360} onChange={setH}/>
@ -41,14 +42,43 @@ function ThemeChooserDialog({onClose}: {
onClose: () => void;
}) {
const {hslTheme, setHslTheme} = useHslTheme();
const [themeString, setThemeString] = useState<string>(JSON.stringify(hslTheme));
const [errorMsg, setErrorMsg] = useState<string>();
useMemo(() => {
setThemeString(JSON.stringify(hslTheme));
}, [hslTheme]);
return <Dialog title="Theme editor" onClose={onClose}>
<Row>
<Button
text="surprise me"
className='flex-grow'
text="? randomize"
onClick={() => setHslTheme(_ => getRandomTheme())}/>
<Spacer/>
</Row>
<Column className='overflow-scroll'>
<Row>
<TextInput
value={themeString}
onChange={setThemeString}
className="flex-grow"/>
<Button text="» import" onClick={() => {
try {
const theme = JSON.parse(themeString);
setHslTheme(old => ({...old, theme}));
} catch (e: any) {
setErrorMsg(e.message);
}
}}/>
{errorMsg &&
<Dialog
title="Error"
onClose={() => setErrorMsg(undefined)}
>
<p>{errorMsg}</p>
</Dialog>
}
</Row>
<Column className="overflow-scroll">
<HslEditor
name="background"
value={hslTheme.background}

View file

@ -1,8 +1,7 @@
import {ChangeEventHandler} from 'react';
import './Input.css';
export function TextInput({onChange, className, value, placeholder, onEnter}: {
onChange?: ChangeEventHandler<HTMLInputElement> | undefined;
onChange?: (value: string) => void;
className?: string;
value: string;
placeholder?: string;
@ -13,10 +12,15 @@ export function TextInput({onChange, className, value, placeholder, onEnter}: {
className={'Input ' + (className ?? '')}
value={value}
placeholder={placeholder}
onChange={onChange}
onChange={event => {
if (!onChange)
return;
onChange(event.target.value);
}}
onKeyUp={event => {
if (onEnter && event.key === 'Enter')
onEnter();
if (!onEnter || event.key !== 'Enter')
return;
onEnter();
}}
/>;
}

View file

@ -0,0 +1,4 @@
export default function Spacer() {
return <div className='flex-grow' />;
}