Browse Source

refactor AttachmentsDropup

Yuki Takei 2 years ago
parent
commit
e2e50caba1

+ 14 - 7
packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.tsx

@@ -196,8 +196,15 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
     isDragAccept,
     isDragAccept,
     isDragReject,
     isDragReject,
     isUploading,
     isUploading,
-    open,
-  } = useFileDropzone({ onUpload, acceptedUploadFileType });
+  } = useFileDropzone({
+    acceptedUploadFileType,
+    onUpload,
+    // ignore mouse and key events
+    dropzoneOpts: {
+      noClick: true,
+      noKeyboard: true,
+    },
+  });
 
 
   const fileUploadState = useMemo(() => {
   const fileUploadState = useMemo(() => {
 
 
@@ -237,12 +244,12 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
         <input {...getInputProps()} />
         <input {...getInputProps()} />
         <FileDropzoneOverlay isEnabled={isDragActive} />
         <FileDropzoneOverlay isEnabled={isDragActive} />
         <CodeMirrorEditorContainer ref={containerRef} />
         <CodeMirrorEditorContainer ref={containerRef} />
-        <Toolbar
-          editorKey={editorKey}
-          acceptedUploadFileType={acceptedUploadFileType}
-          onAttachmentMenuItemClicked={open}
-        />
       </div>
       </div>
+      <Toolbar
+        editorKey={editorKey}
+        acceptedUploadFileType={acceptedUploadFileType}
+        onUpload={onUpload}
+      />
     </div>
     </div>
   );
   );
 };
 };

+ 25 - 24
packages/editor/src/components/CodeMirrorEditor/Toolbar/AttachmentsDropdownItem.tsx

@@ -1,37 +1,38 @@
+import { ReactNode } from 'react';
+
 import { AcceptedUploadFileType } from '@growi/core';
 import { AcceptedUploadFileType } from '@growi/core';
 import {
 import {
   DropdownItem,
   DropdownItem,
 } from 'reactstrap';
 } from 'reactstrap';
 
 
+import { useFileDropzone } from '../../../services';
+
 type Props = {
 type Props = {
-  onItemClicked: () => void,
   acceptedUploadFileType: AcceptedUploadFileType,
   acceptedUploadFileType: AcceptedUploadFileType,
+  children?: ReactNode,
+  onUpload?: (files: File[]) => void,
 }
 }
 
 
-export const AttachmentsButton = (props: Props): JSX.Element => {
+export const AttachmentsDropdownItem = (props: Props): JSX.Element => {
 
 
-  const { onItemClicked, acceptedUploadFileType } = props;
+  const {
+    acceptedUploadFileType,
+    children,
+    onUpload,
+  } = props;
 
 
-  if (acceptedUploadFileType === AcceptedUploadFileType.ALL) {
-    return (
-      <>
-        <DropdownItem className="d-flex gap-2 align-items-center" onClick={onItemClicked}>
-          <span className="material-symbols-outlined fs-5">attach_file</span>
-          Files
-        </DropdownItem>
-      </>
-    );
-  }
-  if (acceptedUploadFileType === AcceptedUploadFileType.IMAGE) {
-    return (
-      <>
-        <DropdownItem className="d-flex gap-2 align-items-center" onClick={onItemClicked}>
-          <span className="material-symbols-outlined fs-5">image</span>
-          Images
-        </DropdownItem>
-      </>
-    );
-  }
+  const {
+    getRootProps,
+    getInputProps,
+    open,
+  } = useFileDropzone({ onUpload, acceptedUploadFileType });
 
 
-  return <></>;
+  return (
+    <div {...getRootProps()} className="dropzone">
+      <input {...getInputProps()} />
+      <DropdownItem className="d-flex gap-2 align-items-center" onClick={open}>
+        {children}
+      </DropdownItem>
+    </div>
+  );
 };
 };

+ 19 - 11
packages/editor/src/components/CodeMirrorEditor/Toolbar/AttachmentsDropup.tsx

@@ -10,27 +10,20 @@ import {
 
 
 import type { GlobalCodeMirrorEditorKey } from '../../../consts';
 import type { GlobalCodeMirrorEditorKey } from '../../../consts';
 
 
-import { AttachmentsButton } from './AttachmentsButton';
+import { AttachmentsDropdownItem } from './AttachmentsDropdownItem';
 import { LinkEditButton } from './LinkEditButton';
 import { LinkEditButton } from './LinkEditButton';
 
 
 type Props = {
 type Props = {
   editorKey: string | GlobalCodeMirrorEditorKey,
   editorKey: string | GlobalCodeMirrorEditorKey,
   acceptedUploadFileType: AcceptedUploadFileType,
   acceptedUploadFileType: AcceptedUploadFileType,
-  onMenuItemClicked: () => void,
+  onUpload?: (files: File[]) => void,
 }
 }
 
 
 export const AttachmentsDropup = (props: Props): JSX.Element => {
 export const AttachmentsDropup = (props: Props): JSX.Element => {
-  const { onMenuItemClicked, acceptedUploadFileType, editorKey } = props;
+  const { acceptedUploadFileType, editorKey, onUpload } = props;
 
 
   const [isOpen, setOpen] = useState(false);
   const [isOpen, setOpen] = useState(false);
 
 
-  const itemClickedHandler = useCallback(() => {
-    onMenuItemClicked();
-
-    // Force close against react-dropzone's { noClick: true } option
-    setOpen(false);
-  }, [onMenuItemClicked]);
-
   return (
   return (
     <>
     <>
       <Dropdown isOpen={isOpen} toggle={() => setOpen(!isOpen)} direction="up" className="lh-1">
       <Dropdown isOpen={isOpen} toggle={() => setOpen(!isOpen)} direction="up" className="lh-1">
@@ -41,8 +34,23 @@ export const AttachmentsDropup = (props: Props): JSX.Element => {
           <DropdownItem className="mt-1" header>
           <DropdownItem className="mt-1" header>
             Attachments
             Attachments
           </DropdownItem>
           </DropdownItem>
+
           <DropdownItem divider />
           <DropdownItem divider />
-          <AttachmentsButton onItemClicked={itemClickedHandler} acceptedUploadFileType={acceptedUploadFileType} />
+
+          { acceptedUploadFileType === AcceptedUploadFileType.ALL && (
+            <AttachmentsDropdownItem acceptedUploadFileType={AcceptedUploadFileType.ALL} onUpload={onUpload}>
+              <span className="material-symbols-outlined fs-5">attach_file</span>
+              Files
+            </AttachmentsDropdownItem>
+          ) }
+
+          { acceptedUploadFileType !== AcceptedUploadFileType.NONE && (
+            <AttachmentsDropdownItem acceptedUploadFileType={AcceptedUploadFileType.IMAGE} onUpload={onUpload}>
+              <span className="material-symbols-outlined fs-5">image</span>
+              Images
+            </AttachmentsDropdownItem>
+          ) }
+
           <LinkEditButton editorKey={editorKey} />
           <LinkEditButton editorKey={editorKey} />
         </DropdownMenu>
         </DropdownMenu>
       </Dropdown>
       </Dropdown>

+ 3 - 3
packages/editor/src/components/CodeMirrorEditor/Toolbar/Toolbar.tsx

@@ -16,15 +16,15 @@ import styles from './Toolbar.module.scss';
 type Props = {
 type Props = {
   editorKey: string | GlobalCodeMirrorEditorKey,
   editorKey: string | GlobalCodeMirrorEditorKey,
   acceptedUploadFileType: AcceptedUploadFileType,
   acceptedUploadFileType: AcceptedUploadFileType,
-  onAttachmentMenuItemClicked: () => void,
+  onUpload?: (files: File[]) => void,
 }
 }
 
 
 export const Toolbar = memo((props: Props): JSX.Element => {
 export const Toolbar = memo((props: Props): JSX.Element => {
 
 
-  const { editorKey, onAttachmentMenuItemClicked, acceptedUploadFileType } = props;
+  const { editorKey, acceptedUploadFileType, onUpload } = props;
   return (
   return (
     <div className={`d-flex gap-2 p-2 codemirror-editor-toolbar ${styles['codemirror-editor-toolbar']}`}>
     <div className={`d-flex gap-2 p-2 codemirror-editor-toolbar ${styles['codemirror-editor-toolbar']}`}>
-      <AttachmentsDropup editorKey={editorKey} onMenuItemClicked={onAttachmentMenuItemClicked} acceptedUploadFileType={acceptedUploadFileType} />
+      <AttachmentsDropup editorKey={editorKey} onUpload={onUpload} acceptedUploadFileType={acceptedUploadFileType} />
       <TextFormatTools editorKey={editorKey} />
       <TextFormatTools editorKey={editorKey} />
       <EmojiButton
       <EmojiButton
         editorKey={editorKey}
         editorKey={editorKey}

+ 6 - 6
packages/editor/src/services/file-dropzone/use-file-dropzone/use-file-dropzone.ts

@@ -2,21 +2,22 @@ import { useCallback, useState } from 'react';
 
 
 import { AcceptedUploadFileType } from '@growi/core';
 import { AcceptedUploadFileType } from '@growi/core';
 import { useDropzone, Accept } from 'react-dropzone';
 import { useDropzone, Accept } from 'react-dropzone';
-import type { DropzoneState } from 'react-dropzone';
+import type { DropzoneOptions, DropzoneState } from 'react-dropzone';
 
 
 
 
 type FileDropzoneState = DropzoneState & {
 type FileDropzoneState = DropzoneState & {
   isUploading: boolean,
   isUploading: boolean,
 }
 }
 
 
-type DropzoneEditor = {
+type Props = {
   acceptedUploadFileType: AcceptedUploadFileType,
   acceptedUploadFileType: AcceptedUploadFileType,
+  dropzoneOpts?: DropzoneOptions,
   onUpload?: (files: File[]) => void,
   onUpload?: (files: File[]) => void,
 }
 }
 
 
-export const useFileDropzone = (props: DropzoneEditor): FileDropzoneState => {
+export const useFileDropzone = (props: Props): FileDropzoneState => {
 
 
-  const { onUpload, acceptedUploadFileType } = props;
+  const { acceptedUploadFileType, dropzoneOpts, onUpload } = props;
 
 
   const [isUploading, setIsUploading] = useState(false);
   const [isUploading, setIsUploading] = useState(false);
 
 
@@ -41,10 +42,9 @@ export const useFileDropzone = (props: DropzoneEditor): FileDropzoneState => {
     : undefined;
     : undefined;
 
 
   const dzState = useDropzone({
   const dzState = useDropzone({
-    noKeyboard: true,
-    noClick: true,
     onDrop: dropHandler,
     onDrop: dropHandler,
     accept,
     accept,
+    ...dropzoneOpts,
   });
   });
 
 
   return {
   return {