Browse Source

Update event handling

Ensure event handling is flawless.
master
TheoryOfNekomata 1 year ago
parent
commit
1caa9c79bf
1 changed files with 57 additions and 37 deletions
  1. +57
    -37
      categories/blob/react/src/components/FileSelectBox/index.tsx

+ 57
- 37
categories/blob/react/src/components/FileSelectBox/index.tsx View File

@@ -83,30 +83,30 @@ export const FileSelectBoxDefaultPreviewComponent = React.forwardRef<
{!mini && (
<>
{typeof file?.type === 'string' && (
<div className="w-full whitespace-nowrap overflow-hidden text-ellipsis">{file?.type}</div>
<div className="w-full whitespace-nowrap overflow-hidden text-ellipsis">{file?.type}</div>
)}
{typeof file?.size === 'number' && (
<div
title={new Intl.NumberFormat(undefined, {
style: 'unit',
unit: 'byte',
unitDisplay: 'long',
}).format(file.size ?? 0)}
className="w-full whitespace-nowrap overflow-hidden text-ellipsis tabular-nums"
>
{new Intl.NumberFormat(undefined, {
style: 'unit',
unit: 'kilobyte',
unitDisplay: 'long',
}).format(file.size ?? 0)}
</div>
<div
title={new Intl.NumberFormat(undefined, {
style: 'unit',
unit: 'byte',
unitDisplay: 'long',
}).format(file.size ?? 0)}
className="w-full whitespace-nowrap overflow-hidden text-ellipsis tabular-nums"
>
{new Intl.NumberFormat(undefined, {
style: 'unit',
unit: 'kilobyte',
unitDisplay: 'long',
}).format(file.size ?? 0)}
</div>
)}
{typeof file?.lastModified === 'number' && (
<div className="w-full whitespace-nowrap overflow-hidden text-ellipsis">
<time dateTime={new Date(file.lastModified).toISOString()}>
{new Date(file.lastModified).toDateString()}
</time>
</div>
<div className="w-full whitespace-nowrap overflow-hidden text-ellipsis">
<time dateTime={new Date(file.lastModified).toISOString()}>
{new Date(file.lastModified).toDateString()}
</time>
</div>
)}
</>
)}
@@ -129,6 +129,7 @@ export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileS
placeholder,
previewComponent: FilePreviewComponent = FileSelectBoxDefaultPreviewComponent,
style,
onBlur,
...etcProps
},
forwardedRef,
@@ -181,18 +182,24 @@ export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileS
const labelId = React.useId();
const id = useFallbackId(idProp);

const cancelEvent = (e: React.DragEvent) => {
const cancelEvent: React.DragEventHandler<HTMLDivElement> = React.useCallback((e) => {
e.stopPropagation();
e.preventDefault();
};
}, []);

const filesCount = fileList?.length ?? 0;
const handleDrop: React.DragEventHandler<HTMLDivElement> = React.useCallback((e) => {
cancelEvent(e);
doSetFileList(e);
}, [cancelEvent, doSetFileList]);

const handleFileChange: React.ChangeEventHandler<FileSelectBoxDerivedElement> = (e) => {
const handleFileChange: React.ChangeEventHandler<
FileSelectBoxDerivedElement
> = React.useCallback((e) => {
const { currentTarget } = e;
if (clientSide && currentTarget.files && currentTarget.files.length > 0) {
setFileList(currentTarget.files);
setLastUpdated(Date.now());
setAboutToSelect(false);
onChange?.(e);
return;
}
@@ -205,26 +212,29 @@ export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileS
}
e.preventDefault();
e.currentTarget.files = fileList ?? null;
};
setAboutToSelect(false);
}, [clientSide, fileList, onChange]);

const handleKeyDown: React.KeyboardEventHandler<FileSelectBoxDerivedElement> = (e) => {
const handleKeyDown: React.KeyboardEventHandler<
FileSelectBoxDerivedElement
> = React.useCallback((e) => {
const { code } = e;
if (code === 'Backspace' || code === 'Delete') {
setDeleteKeyPressed(true);
} else if (code === 'Enter' || code === 'Space' || code === 'Return') {
setAboutToSelect(true);
}
};
}, []);

const handleKeyUp: React.KeyboardEventHandler<FileSelectBoxDerivedElement> = (e) => {
const handleKeyUp: React.KeyboardEventHandler<
FileSelectBoxDerivedElement
> = React.useCallback((e) => {
const { code } = e;
if (code === 'Backspace' || code === 'Delete') {
doSetFileList(e);
setDeleteKeyPressed(false);
} else if (code === 'Enter' || code === 'Space' || code === 'Return') {
setAboutToSelect(false);
}
};
}, [doSetFileList]);

const handleReselectMouseDown: React.MouseEventHandler<
HTMLButtonElement
@@ -253,6 +263,14 @@ export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileS
});
}, [defaultRef]);

const handleBlur: React.FocusEventHandler<
FileSelectBoxDerivedElement
> = React.useCallback((e) => {
setAboutToSelect(false);
setDeleteKeyPressed(false);
onBlur?.(e);
}, [onBlur]);

React.useEffect(() => {
const handleLabelMouseUp = () => {
setAboutToSelect(false);
@@ -265,6 +283,8 @@ export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileS
};
}, [defaultRef, aboutToSelect]);

const filesCount = fileList?.length ?? 0;

return (
<div
className={clsx(
@@ -276,10 +296,7 @@ export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileS
)}
onDragEnter={clientSide ? cancelEvent : undefined}
onDragOver={clientSide ? cancelEvent : undefined}
onDrop={clientSide ? (e) => {
cancelEvent(e);
doSetFileList(e);
} : undefined}
onDrop={clientSide ? handleDrop : undefined}
data-testid="root"
style={{
height: clientSide ? 64 : undefined,
@@ -307,8 +324,9 @@ export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileS
<button
type="button"
disabled={disabled}
tabIndex={-1}
className={clsx(
'flex items-center justify-center absolute top-0 left-0 w-full h-full cursor-pointer select-none',
'flex items-center focus:outline-0 justify-center absolute top-0 left-0 w-full h-full cursor-pointer select-none',
(fileList?.length ?? 0) > 0 && 'opacity-0',
)}
data-testid="clickArea"
@@ -324,6 +342,7 @@ export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileS
disabled={disabled}
ref={defaultRef}
type="file"
onBlur={handleBlur}
onKeyDown={clientSide ? handleKeyDown : undefined}
onKeyUp={clientSide ? handleKeyUp : undefined}
className={clsx(
@@ -411,8 +430,9 @@ export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileS
disabled={disabled}
onMouseDown={handleReselectMouseDown}
onMouseUp={handleReselectMouseUp}
tabIndex={-1}
className={clsx(
'flex w-full h-full bg-negative text-primary cursor-pointer items-center justify-center leading-none gap-4 select-none',
'flex w-full h-full focus:outline-0 bg-negative text-primary cursor-pointer items-center justify-center leading-none gap-4 select-none',
{
'group-focus-within:text-secondary group-focus-within:active:text-tertiary': !aboutToSelect,
'text-tertiary': aboutToSelect,


Loading…
Cancel
Save