import { type Component, Show, createMemo } from 'solid-js';
import type { RGB } from '~/engine/types';
import { Tooltip } from './Tooltip';
import { PARAM_HELP } from './paramHelp';
interface Props {
label: string;
color: RGB;
name?: string;
onChange: (color: RGB) => void;
info?: string;
}
export const ColorRow: Component<Props> = (props) => {
const hex = createMemo(() => rgbToHex(props.color));
const helpText = createMemo(() => props.info ?? PARAM_HELP[props.label]);
const onPick = (e: Event) => {
const target = e.currentTarget as HTMLInputElement;
props.onChange(hexToRgb(target.value));
};
return (
<div style={{ display: 'flex', 'align-items': 'center', gap: '12px' }}>
<label
style={{
position: 'relative',
width: '32px',
height: '32px',
'border-radius': 'var(--radius-md)',
background: hex(),
border: '1px solid var(--border-strong)',
'box-shadow': `0 0 0 1px var(--surface-raised) inset, 0 0 12px -4px ${hex()}`,
'flex-shrink': '0',
cursor: 'pointer',
}}
>
<input
type="color"
value={hex()}
onInput={onPick}
style={{
position: 'absolute',
inset: '0',
width: '100%',
height: '100%',
opacity: '0',
cursor: 'pointer',
}}
/>
</label>
<div style={{ flex: '1', display: 'flex', 'flex-direction': 'column', gap: '2px' }}>
<span
style={{ 'font-family': 'var(--font-body)', 'font-size': '12.5px', 'font-weight': '500' }}
>
{props.label}
</span>
{props.name && (
<span
class="phys-mono"
style={{
'font-size': '10px',
color: 'var(--fg-tertiary)',
'letter-spacing': '0.06em',
'text-transform': 'uppercase',
}}
>
{props.name}
</span>
)}
</div>
<span class="phys-mono" style={{ 'font-size': '11px', color: 'var(--fg-secondary)' }}>
{hex()}
</span>
<Show when={helpText()}>
<Tooltip text={helpText() ?? ''} />
</Show>
</div>
);
};
function rgbToHex(rgb: RGB): string {
return `#${rgb
.map((c) =>
Math.round(c * 255)
.toString(16)
.padStart(2, '0'),
)
.join('')}`;
}
function hexToRgb(hex: string): RGB {
const n = Number.parseInt(hex.replace('#', ''), 16);
return [((n >> 16) & 255) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255];
}