Skip to content

Commit

Permalink
refactor: FilesDropTarget -> TS (#30254)
Browse files Browse the repository at this point in the history
Co-authored-by: Aleksander Nicacio da Silva <[email protected]>
  • Loading branch information
MartinSchoeler and aleksandernsilva authored Sep 14, 2023
1 parent bec5a89 commit 7d1524f
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 113 deletions.
107 changes: 0 additions & 107 deletions packages/livechat/src/components/FilesDropTarget/index.js

This file was deleted.

122 changes: 122 additions & 0 deletions packages/livechat/src/components/FilesDropTarget/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import type { ComponentChildren, Ref } from 'preact';
import type { TargetedEvent } from 'preact/compat';
import { useState } from 'preact/hooks';
import type { JSXInternal } from 'preact/src/jsx';

import { createClassName } from '../../helpers/createClassName';
import styles from './styles.scss';

const escapeForRegExp = (string: string) => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

type FilesDropTargetProps = {
overlayed?: boolean;
overlayText?: string;
accept?: string;
multiple?: boolean;
className?: string;
style?: JSXInternal.CSSProperties;
children?: ComponentChildren;
inputRef?: Ref<HTMLInputElement>;
onUpload?: (files: File[]) => void;
};

export const FilesDropTarget = ({
overlayed,
overlayText,
accept,
multiple,
className,
style = {},
children,
inputRef,
onUpload,
}: FilesDropTargetProps) => {
const [dragLevel, setDragLevel] = useState(0);

const handleDragOver = (event: DragEvent) => {
event.preventDefault();
};

const handleDragEnter = (event: DragEvent) => {
event.preventDefault();
setDragLevel(dragLevel + 1);
};

const handleDragLeave = (event: DragEvent) => {
event.preventDefault();
setDragLevel(dragLevel - 1);
};

const handleDrop = (event: DragEvent) => {
event.preventDefault();

if (dragLevel === 0 || !event?.dataTransfer?.files?.length) {
return;
}

setDragLevel(0);

handleUpload(event?.dataTransfer?.files);
};

const handleInputChange = (event: TargetedEvent<HTMLInputElement>) => {
if (!event?.currentTarget?.files?.length) {
return;
}

handleUpload(event.currentTarget.files);
};

const handleUpload = (files: FileList) => {
if (!onUpload) {
return;
}

let filteredFiles = Array.from(files);

if (accept) {
const acceptMatchers = accept.split(',').map((acceptString) => {
if (acceptString.charAt(0) === '.') {
return ({ name }: { name: string }) => new RegExp(`${escapeForRegExp(acceptString)}$`, 'i').test(name);
}

const matchTypeOnly = /^(.+)\/\*$/i.exec(acceptString);
if (matchTypeOnly) {
return ({ type }: { type: string }) => new RegExp(`^${escapeForRegExp(matchTypeOnly[1])}/.*$`, 'i').test(type);
}

return ({ type }: { type: string }) => new RegExp(`^s${escapeForRegExp(acceptString)}$`, 'i').test(type);
});

filteredFiles = filteredFiles.filter((file) => acceptMatchers.some((acceptMatcher) => acceptMatcher(file)));
}

if (!multiple) {
filteredFiles = filteredFiles.slice(0, 1);
}

filteredFiles.length && onUpload(filteredFiles);
};

return (
<div
data-overlay-text={overlayText}
onDragOver={handleDragOver}
onDragEnter={handleDragEnter}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
className={createClassName(styles, 'drop', { overlayed, dragover: dragLevel > 0 }, [className])}
style={style}
>
<input
ref={inputRef}
type='file'
accept={accept}
multiple={multiple}
onChange={handleInputChange}
className={createClassName(styles, 'drop__input')}
/>
{children}
</div>
);
};
6 changes: 3 additions & 3 deletions packages/livechat/src/components/FilesDropTarget/stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ AcceptingMultipleFiles.args = {

export const TriggeringBrowseAction = Template.bind({});
TriggeringBrowseAction.storyName = 'triggering browse action';
const ref = createRef();
const inputRef = createRef();
TriggeringBrowseAction.args = {
children: (
<div
Expand All @@ -84,8 +84,8 @@ TriggeringBrowseAction.args = {
flexDirection: 'column',
}}
>
<Button onClick={() => ref.current.browse()}>Browse</Button>
<Button onClick={() => inputRef.current.browse()}>Browse</Button>
</div>
),
ref,
inputRef,
};
8 changes: 5 additions & 3 deletions packages/livechat/src/routes/Chat/component.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component } from 'preact';
import { Component, createRef } from 'preact';
import { Suspense, lazy } from 'preact/compat';
import { withTranslation } from 'react-i18next';

Expand Down Expand Up @@ -35,6 +35,8 @@ class Chat extends Component {
emojiPickerActive: false,
};

inputRef = createRef(null);

handleFilesDropTargetRef = (ref) => {
this.filesDropTarget = ref;
};
Expand All @@ -61,7 +63,7 @@ class Chat extends Component {

handleUploadClick = (event) => {
event.preventDefault();
this.filesDropTarget.browse();
this.inputRef?.current?.click();
};

handleSendClick = (event) => {
Expand Down Expand Up @@ -151,7 +153,7 @@ class Chat extends Component {
handleEmojiClick={this.handleEmojiClick}
{...props}
>
<FilesDropTarget ref={this.handleFilesDropTargetRef} overlayed overlayText={t('drop_here_to_upload_a_file')} onUpload={onUpload}>
<FilesDropTarget inputRef={this.inputRef} overlayed overlayText={t('drop_here_to_upload_a_file')} onUpload={onUpload}>
<Screen.Content nopadding>
{incomingCallAlert && !!incomingCallAlert.show && <CallNotification {...incomingCallAlert} dispatch={dispatch} />}
{incomingCallAlert?.show && ongoingCall && ongoingCall.callStatus === CallStatus.IN_PROGRESS_SAME_TAB ? (
Expand Down

0 comments on commit 7d1524f

Please sign in to comment.