Merge pull request #4965 from urbit/james/imageinput-fixes

imageinput: disable placeholder selection, hide placeholder on focus
This commit is contained in:
matildepark 2021-06-03 14:28:41 -04:00 committed by GitHub
commit 330e17e28d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,14 +1,11 @@
import {
BaseInput, Box,
Button,
Icon, Label, Row, StatelessTextInput as Input,
Text
} from '@tlon/indigo-react';
import { useField } from 'formik';
import React, { ReactElement, useCallback, useRef } from 'react';
import React, { ReactElement, useCallback, useRef, useState } from 'react';
import useStorage from '~/logic/lib/useStorage';
export type ImageInputProps = Parameters<typeof Box>[0] & {
@ -17,28 +14,50 @@ export type ImageInputProps = Parameters<typeof Box>[0] & {
placeholder?: string;
};
const prompt = (field, uploading, meta, clickUploadButton) => {
if (!field.value && !uploading && meta.error === undefined) {
const prompt = (
field,
focus,
uploading,
meta,
clickUploadButton,
canUpload
) => {
if (
!focus &&
!field.value &&
!uploading &&
meta.error === undefined
) {
return (
<Text
color='black'
fontWeight='500'
position='absolute'
left={2}
top={2}
display='flex'
height='100%'
alignItems='center'
lineHeight={1}
style={{ pointerEvents: 'none' }}
onSelect={e => e.preventDefault}
>
Paste a link here, or{' '}
<Text
fontWeight='500'
cursor='pointer'
color='blue'
style={{ pointerEvents: 'all' }}
onClick={clickUploadButton}
>
upload
</Text>{' '}
a file
Paste a link here
{canUpload ? (
<>
, or
<Text
fontWeight="500"
cursor="pointer"
color="blue"
style={{ pointerEvents: 'all' }}
mx='0.5ch'
onClick={clickUploadButton}
>
upload
</Text>
a file
</>
) : null}
</Text>
);
}
@ -46,9 +65,18 @@ const prompt = (field, uploading, meta, clickUploadButton) => {
};
const uploadingStatus = (uploading, meta) => {
if (uploading && meta.error === undefined) {
if (meta.error === undefined && uploading) {
return (
<Text position='absolute' left={2} top={2} gray>
<Text
position="absolute"
left={2}
display='flex'
height='100%'
alignItems='center'
lineHeight={1}
gray
onSelect={e => e.preventDefault}
>
Uploading...
</Text>
);
@ -56,21 +84,26 @@ const uploadingStatus = (uploading, meta) => {
return null;
};
const errorRetry = (meta, uploading, clickUploadButton) => {
if (meta.error !== undefined) {
const errorRetry = (meta, focus, uploading, clickUploadButton) => {
if (!focus && meta.error !== undefined) {
return (
<Text
position='absolute'
left={2}
top={2}
display='flex'
height='100%'
alignItems='center'
lineHeight={1}
color='red'
style={{ pointerEvents: 'none' }}
onSelect={e => e.preventDefault}
>
{meta.error}{', '}please{' '}
<Text
fontWeight='500'
cursor='pointer'
color='blue'
mx='0.5ch'
style={{ pointerEvents: 'all' }}
onClick={clickUploadButton}
>
@ -111,8 +144,22 @@ export function ImageInput(props: ImageInputProps): ReactElement {
const { id, label, caption } = props;
const { uploadDefault, canUpload, uploading } = useStorage();
const [field, meta, { setValue, setError }] = useField(id);
const [focus, setFocus] = useState(false);
const ref = useRef<HTMLInputElement | null>(null);
const clickUploadButton = useCallback(() => {
ref.current?.click();
}, [ref]);
const clearEvt = useCallback(() => {
setValue('');
}, []);
const handleBlur = (e) => {
field.onBlur(e);
setFocus(false);
};
const onImageUpload = useCallback(async () => {
const file = ref.current?.files?.item(0);
@ -121,20 +168,14 @@ export function ImageInput(props: ImageInputProps): ReactElement {
}
try {
const url = await uploadDefault(file);
setFocus(false);
setValue(url);
} catch (e) {
setFocus(false);
setError(e.message);
}
}, [ref.current, uploadDefault, canUpload, setValue]);
const clickUploadButton = useCallback(() => {
ref.current?.click();
}, [ref]);
const clearEvt = useCallback(() => {
setValue('');
}, []);
return (
<Box display="flex" flexDirection="column" {...props}>
<Label htmlFor={id}>{label}</Label>
@ -144,16 +185,18 @@ export function ImageInput(props: ImageInputProps): ReactElement {
</Label>
) : null}
<Row mt={2} alignItems="flex-end" position='relative' width='100%'>
{prompt(field, uploading, meta, clickUploadButton)}
{prompt(field, focus, uploading, meta, clickUploadButton, canUpload)}
{clearButton(field, uploading, clearEvt)}
{uploadingStatus(uploading, meta)}
{errorRetry(meta, uploading, clickUploadButton)}
{errorRetry(meta, focus, uploading, clickUploadButton)}
<Box background='white' borderRadius={2} width='100%'>
<Input
{...field}
width='100%'
type={'text'}
onFocus={() => setFocus(true)}
onBlur={e => handleBlur(e)}
hasError={meta.touched && meta.error !== undefined}
{...field}
/>
</Box>
{canUpload && (