ColorInput: fix textual input

Fixes urbit/landscape#1060
This commit is contained in:
Liam Fitzgerald 2021-07-19 14:48:43 +10:00
parent ea9cef905a
commit 0e1f365bf5
No known key found for this signature in database
GPG Key ID: D390E12C61D1CFFB
2 changed files with 36 additions and 19 deletions

View File

@ -241,11 +241,13 @@ export function uxToHex(ux: string) {
export const hexToUx = (hex) => { export const hexToUx = (hex) => {
const ux = f.flow( const ux = f.flow(
f.reverse,
f.chunk(4), f.chunk(4),
// eslint-disable-next-line prefer-arrow-callback // eslint-disable-next-line prefer-arrow-callback
f.map(x => _.dropWhile(x, function(y: unknown) { f.map(x => _.dropWhile(x, function(y: unknown) {
return y === 0; return y === '0';
}).join('')), }).reverse().join('')),
f.reverse,
f.join('.') f.join('.')
)(hex.split('')); )(hex.split(''));
return `0x${ux}`; return `0x${ux}`;

View File

@ -7,8 +7,9 @@ import {
StatelessTextInput as Input StatelessTextInput as Input
} from '@tlon/indigo-react'; } from '@tlon/indigo-react';
import { useField } from 'formik'; import { useField } from 'formik';
import React, { FormEvent } from 'react'; import React, { FormEvent, useState, useEffect } from 'react';
import { hexToUx } from '~/logic/lib/util'; import { hexToUx } from '~/logic/lib/util';
import { uxToHex } from '@urbit/api/dist';
export type ColorInputProps = Parameters<typeof Col>[0] & { export type ColorInputProps = Parameters<typeof Col>[0] & {
id: string; id: string;
@ -17,24 +18,40 @@ export type ColorInputProps = Parameters<typeof Col>[0] & {
disabled?: boolean; disabled?: boolean;
}; };
const COLOR_REGEX = /^(\d|[a-f]|[A-F]){6}$/;
function padHex(hex: string) {
if(hex.length === 0) {
return '000000';
}
const repeat = 6 / hex.length;
if(Math.floor(repeat) === repeat) {
return hex.repeat(repeat);
}
if(hex.length < 6) {
return hex.slice(0,3).repeat(2);
}
return hex.slice(0,6);
}
export function ColorInput(props: ColorInputProps) { export function ColorInput(props: ColorInputProps) {
const { id, placeholder, label, caption, disabled, ...rest } = props; const { id, placeholder, label, caption, disabled, ...rest } = props;
const [{ value, onBlur }, meta, { setValue }] = useField(id); const [{ value, onBlur }, meta, { setValue, setTouched }] = useField(id);
const [field, setField] = useState('');
// const [error, setError] = useState<string | undefined>();
const hex = value.replace('#', '').replace('0x', '').replace('.', ''); useEffect(() => {
const padded = hex.padStart(6, '0'); const newValue = hexToUx(padHex(field));
setValue(newValue);
setTouched(true);
}, [field]);
const onChange = (e: FormEvent<HTMLInputElement>) => { const onChange = (e: FormEvent<HTMLInputElement>) => {
let { value: newValue } = e.target as HTMLInputElement; const { value: newValue } = e.target as HTMLInputElement;
newValue = newValue.replace('#', ''); setField(newValue);
const valid = newValue.match(/^(\d|[a-f]|[A-F]){0,6}$/);
if (!valid) {
return;
}
const result = hexToUx(newValue);
setValue(result);
}; };
const isValid = value.match(COLOR_REGEX);
const hex = uxToHex(value);
return ( return (
<Box display='flex' flexDirection='column' {...rest}> <Box display='flex' flexDirection='column' {...rest}>
@ -51,7 +68,7 @@ export function ColorInput(props: ColorInputProps) {
borderBottomRightRadius={0} borderBottomRightRadius={0}
onBlur={onBlur} onBlur={onBlur}
onChange={onChange} onChange={onChange}
value={hex} value={field}
disabled={disabled || false} disabled={disabled || false}
borderRight={0} borderRight={0}
placeholder={placeholder} placeholder={placeholder}
@ -64,14 +81,12 @@ export function ColorInput(props: ColorInputProps) {
borderColor='lightGray' borderColor='lightGray'
width='32px' width='32px'
alignSelf='stretch' alignSelf='stretch'
bg={`#${padded}`} bg={isValid ? `#${hex}` : 'transparent'}
> >
<Input <Input
width='100%' width='100%'
height='100%' height='100%'
alignSelf='stretch' alignSelf='stretch'
onChange={onChange}
value={padded}
disabled={disabled || false} disabled={disabled || false}
type='color' type='color'
opacity={0} opacity={0}