feat(ui): add InputColor and custom theme

This commit is contained in:
2026-02-09 15:26:18 +01:00
parent 2e6466ceca
commit 64d75b9686
10 changed files with 234 additions and 59 deletions

View File

@@ -1,7 +1,14 @@
<script lang="ts">
import type { NodeInput } from '@nodarium/types';
import { InputCheckbox, InputNumber, InputSelect, InputShape, InputVec3 } from './index';
import {
InputCheckbox,
InputColor,
InputNumber,
InputSelect,
InputShape,
InputVec3
} from './index';
interface Props {
input: NodeInput;
@@ -21,8 +28,15 @@
/>
{:else if input.type === 'shape'}
<InputShape bind:value={value as number[]} />
{:else if input.type === 'color'}
<InputColor bind:value={value as number[]} />
{:else if input.type === 'integer'}
<InputNumber bind:value={value as number} min={input?.min} max={input?.max} step={1} />
<InputNumber
bind:value={value as number}
min={input?.min}
max={input?.max}
step={1}
/>
{:else if input.type === 'boolean'}
<InputCheckbox bind:value={value as boolean} {id} />
{:else if input.type === 'select'}

View File

@@ -140,12 +140,12 @@ html.theme-catppuccin {
}
html.theme-high-contrast {
--color-text: #ffffff;
--color-text: white;
--color-outline: white;
--color-layer-0: #000000;
--color-layer-0: black;
--color-layer-1: black;
--color-layer-2: #222222;
--color-layer-3: #ffffff;
--color-layer-2: #ababab;
--color-layer-3: white;
--color-connection: #fff;
}

View File

@@ -1,5 +1,6 @@
export { default as Input } from './Input.svelte';
export { default as InputCheckbox } from './inputs/InputCheckbox.svelte';
export { default as InputColor } from './inputs/InputColor.svelte';
export { default as InputNumber } from './inputs/InputNumber.svelte';
export { default as InputSelect } from './inputs/InputSelect.svelte';
export { default as InputShape } from './inputs/InputShape.svelte';

View File

@@ -0,0 +1,85 @@
<script lang="ts">
interface Props {
value?: [number, number, number];
id?: string;
}
let {
value = $bindable([255, 255, 255] as [number, number, number]),
id
}: Props = $props();
let hexValue = $derived(
`#${value.map((c) => c.toString(16).padStart(2, '0')).join('')}`
);
let rValue = $state(value[0]);
let gValue = $state(value[1]);
let bValue = $state(value[2]);
$effect(() => {
rValue = value[0];
gValue = value[1];
bValue = value[2];
});
function handleHexInput(e: Event) {
const target = e.target as HTMLInputElement;
let val = target.value.replace(/[^0-9a-fA-F]/g, '');
if (val.length > 6) val = val.slice(0, 6);
if (val.length === 3) {
val = val
.split('')
.map((c) => c + c)
.join('');
}
if (val.length === 6) {
value = [
parseInt(val.slice(0, 2), 16),
parseInt(val.slice(2, 4), 16),
parseInt(val.slice(4, 6), 16)
] as [number, number, number];
}
}
function handleHexBlur() {
rValue = value[0];
gValue = value[1];
bValue = value[2];
}
</script>
<div class="flex overflow-hidden rounded-sm border border-outline bg-layer-2 w-min">
<label
class="-ml-px w-8 shrink-0 overflow-hidden"
style={`background-color: ${hexValue}`}
>
<input
type="color"
bind:value={hexValue}
{id}
oninput={handleHexInput}
class="h-full w-8 cursor-pointer appearance-none p-0"
/>
</label>
<div class="flex items-center gap-1 px-2 py-1">
<span class="pointer-events-none text-text opacity-30">#</span>
<input
type="text"
value={hexValue.slice(1)}
{id}
oninput={handleHexInput}
onblur={handleHexBlur}
maxlength={6}
class="w-15 bg-transparent text-text outline-none"
/>
</div>
</div>
<style>
input[type="color"] {
margin-top: -1px;
margin-right: -1px;
height: calc(100% + 2px);
}
</style>