From 2381a4f8e68e569e11dd25df54d405214dbde832 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Mon, 29 Jul 2019 22:10:45 -0700 Subject: [PATCH] Add support for file dropdown menu --- .../server/files/FileDropdownMenu.tsx | 92 +++++++++++++++++++ .../components/server/files/FileObjectRow.tsx | 10 +- tailwind.js | 14 +++ 3 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 resources/scripts/components/server/files/FileDropdownMenu.tsx diff --git a/resources/scripts/components/server/files/FileDropdownMenu.tsx b/resources/scripts/components/server/files/FileDropdownMenu.tsx new file mode 100644 index 00000000..ece264c8 --- /dev/null +++ b/resources/scripts/components/server/files/FileDropdownMenu.tsx @@ -0,0 +1,92 @@ +import React, { createRef, useEffect, useState } from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faEllipsisH } from '@fortawesome/free-solid-svg-icons/faEllipsisH'; +import { FileObject } from '@/api/server/files/loadDirectory'; +import { CSSTransition } from 'react-transition-group'; +import { faPencilAlt } from '@fortawesome/free-solid-svg-icons/faPencilAlt'; +import { faTrashAlt } from '@fortawesome/free-solid-svg-icons/faTrashAlt'; +import { faFileDownload } from '@fortawesome/free-solid-svg-icons/faFileDownload'; +import { faCopy } from '@fortawesome/free-solid-svg-icons/faCopy'; +import { faArrowsAltH } from '@fortawesome/free-solid-svg-icons/faArrowsAltH'; +import { faBalanceScaleLeft } from '@fortawesome/free-solid-svg-icons/faBalanceScaleLeft'; +import { faLevelUpAlt } from '@fortawesome/free-solid-svg-icons/faLevelUpAlt'; + +export default ({ file }: { file: FileObject }) => { + const menu = createRef(); + const [ visible, setVisible ] = useState(false); + const [posX, setPosX] = useState(0); + + const windowListener = (e: MouseEvent) => { + if (e.button === 2 || !visible || !menu.current) { + return; + } + + if (e.target === menu.current || menu.current.contains(e.target as Node)) { + return; + } + + if (e.target !== menu.current && !menu.current.contains(e.target as Node)) { + setVisible(false); + } + }; + + useEffect(() => { + visible + ? document.addEventListener('click', windowListener) + : document.removeEventListener('click', windowListener); + + if (visible && menu.current) { + menu.current.setAttribute( + 'style', `margin-top: -0.35rem; left: ${Math.round(posX - menu.current.clientWidth)}px` + ); + } + }, [ visible ]); + + useEffect(() => () => { + document.removeEventListener('click', windowListener); + }, []); + + return ( +
+
{ + e.preventDefault(); + if (!visible) { + setPosX(e.clientX); + } + setVisible(!visible); + }} + > + +
+ +
+
+ + Rename +
+
+ + Move +
+
+ + Copy +
+
+ + Download +
+
+ + Delete +
+
+
+
+ ); +}; diff --git a/resources/scripts/components/server/files/FileObjectRow.tsx b/resources/scripts/components/server/files/FileObjectRow.tsx index b284b56c..a23a6c96 100644 --- a/resources/scripts/components/server/files/FileObjectRow.tsx +++ b/resources/scripts/components/server/files/FileObjectRow.tsx @@ -6,9 +6,9 @@ import { bytesToHuman } from '@/helpers'; import differenceInHours from 'date-fns/difference_in_hours'; import format from 'date-fns/format'; import distanceInWordsToNow from 'date-fns/distance_in_words_to_now'; -import { faEllipsisH } from '@fortawesome/free-solid-svg-icons/faEllipsisH'; import React from 'react'; import { FileObject } from '@/api/server/files/loadDirectory'; +import FileDropdownMenu from '@/components/server/files/FileDropdownMenu'; export default ({ file, directory }: { file: FileObject; directory: string }) => { return ( @@ -16,7 +16,7 @@ export default ({ file, directory }: { file: FileObject; directory: string }) => key={file.name} href={file.isFile ? undefined : `#${directory}/${file.name}`} className={` - flex px-4 py-3 bg-neutral-700 text-neutral-300 rounded-sm mb-px text-sm + flex bg-neutral-700 text-neutral-300 rounded-sm mb-px text-sm hover:text-neutral-100 cursor-pointer items-center no-underline hover:bg-neutral-600 `} onClick={(e) => { @@ -25,7 +25,7 @@ export default ({ file, directory }: { file: FileObject; directory: string }) => } }} > -
+
{file.isFile ? : @@ -50,9 +50,7 @@ export default ({ file, directory }: { file: FileObject; directory: string }) => distanceInWordsToNow(file.modifiedAt, { includeSeconds: true }) }
-
- -
+ ); }; diff --git a/tailwind.js b/tailwind.js index 2f3314e5..98e27e62 100644 --- a/tailwind.js +++ b/tailwind.js @@ -531,6 +531,20 @@ module.exports = { minWidth: { '0': '0', + '1': '0.25rem', + '2': '0.5rem', + '3': '0.75rem', + '4': '1rem', + '6': '1.5rem', + '8': '2rem', + '10': '2.5rem', + '12': '3rem', + '16': '4rem', + '24': '6rem', + '32': '8rem', + '48': '12rem', + '64': '16rem', + '96': '24rem', 'full': '100%', },