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) => {
const ux = f.flow(
f.reverse,
f.chunk(4),
// eslint-disable-next-line prefer-arrow-callback
f.map(x => _.dropWhile(x, function(y: unknown) {
return y === 0;
}).join('')),
return y === '0';
}).reverse().join('')),
f.reverse,
f.join('.')
)(hex.split(''));
return `0x${ux}`;

View File

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