From cedbe8638193dc981c7176ab8a23edd1700533b9 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Mon, 5 Sep 2022 10:54:54 +0800 Subject: [PATCH] new context menu --- .../explorer/ExplorerContextMenu.tsx | 268 +++++++----------- packages/ui/package.json | 2 + packages/ui/src/ContextMenu/index.tsx | 107 +++++++ packages/ui/src/index.ts | 1 + pnpm-lock.yaml | Bin 677477 -> 682966 bytes 5 files changed, 214 insertions(+), 164 deletions(-) create mode 100644 packages/ui/src/ContextMenu/index.tsx diff --git a/packages/interface/src/components/explorer/ExplorerContextMenu.tsx b/packages/interface/src/components/explorer/ExplorerContextMenu.tsx index a76c1c163..ff6c08cf9 100644 --- a/packages/interface/src/components/explorer/ExplorerContextMenu.tsx +++ b/packages/interface/src/components/explorer/ExplorerContextMenu.tsx @@ -1,182 +1,122 @@ import { explorerStore, useLibraryMutation, useLibraryQuery } from '@sd/client'; -import { ExplorerData } from '@sd/core'; import { - ArrowBendUpRight, - LockSimple, - Package, - Plus, - Share, - TagSimple, - Trash, - TrashSimple + ArrowBendUpRight, + FilePlus, + FileX, + LockSimple, + Package, + Plus, + Share, + TagSimple, + Trash, + TrashSimple, } from 'phosphor-react'; import React from 'react'; import { useSnapshot } from 'valtio'; -import { WithContextMenu } from '../layout/MenuOverlay'; +import { NewContextMenu as CM } from "@sd/ui" + +const AssignTagMenuItems = (props: { objectId: number }) => { + const tags = useLibraryQuery(['tags.getAll'], { suspense: true }); + const tagsForFile = useLibraryQuery(['tags.getForFile', props.objectId], { suspense: true }); + + const { mutate: assignTag } = useLibraryMutation('tags.assign'); + + return ( + <> + {tags.data?.map(tag => { + const active = !!tagsForFile.data?.find(t => t.id === tag.id) + + return { + e.preventDefault(); + if (props.objectId === null) return; + + assignTag({ + tag_id: tag.id, + file_id: props.objectId, + unassign: active + }); + }} + > +
+

{tag.name}

+ + })} + + ); +} interface Props { - children: React.ReactNode; + children: React.ReactNode; } export default function ExplorerContextMenu(props: Props) { - const store = useSnapshot(explorerStore); + const store = useSnapshot(explorerStore); - const { data: tags } = useLibraryQuery(['tags.getAll'], {}); + return ( +
+ + + - const { mutate: assignTag } = useLibraryMutation('tags.assign'); + - const { data: tagsForFile } = useLibraryQuery([ - 'tags.getForFile', - store.contextMenuObjectId || -1 - ]); - return ( -
- { - const active = !!tagsForFile?.find((t) => t.id === tag.id); - return { - label: tag.name || '', + + - // leftItem: t.id === tag.id)} />, - leftItem: ( -
-
-
- ), - onClick(e) { - e.preventDefault(); - if (store.contextMenuObjectId != null) - assignTag({ - tag_id: tag.id, - file_id: store.contextMenuObjectId, - unassign: active - }); - } - }; - }) || [] - ] - } - ], - [ - { - label: 'More actions...', - icon: Plus, + - children: [ - // [ - // { - // label: 'Move to library', - // icon: FilePlus, - // children: [libraries?.map((library) => ({ label: library.config.name })) || []] - // }, - // { - // label: 'Remove from library', - // icon: FileX - // } - // ], - [ - { - label: 'Encrypt', - icon: LockSimple - }, - { - label: 'Compress', - icon: Package - }, - { - label: 'Convert to', - icon: ArrowBendUpRight, + + - children: [ - [ - { - label: 'PNG' - }, - { - label: 'WebP' - } - ] - ] - } - // { - // label: 'Mint NFT', - // icon: TrashIcon - // } - ], - [ - { - label: 'Secure delete', - icon: TrashSimple - } - ] - ] - } - ], - [ - { - label: 'Delete', - icon: Trash, - danger: true - } - ] - ]} - > - {props.children} - -
- ); + + + { + e.preventDefault(); + + navigator.share?.({ + title: 'Spacedrive', + text: 'Check out this cool app', + url: 'https://spacedrive.com' + }); + }} /> + + + + {store.contextMenuObjectId && + + } + + + {/* {libraries.map(library => )} */} + + + + + + + + + + + + + + + + +
+ ); } diff --git a/packages/ui/package.json b/packages/ui/package.json index 1c32f3fba..cc0279996 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -21,11 +21,13 @@ "@heroicons/react": "^2.0.10", "@radix-ui/react-context-menu": "^1.0.0", "@tailwindcss/forms": "^0.5.2", + "class-variance-authority": "^0.2.3", "clsx": "^1.2.1", "phosphor-react": "^1.4.1", "postcss": "^8.4.14", "react": "^18.2.0", "react-dom": "^18.2.0", + "storybook": "^6.5.10", "tailwindcss": "^3.1.6" }, "devDependencies": { diff --git a/packages/ui/src/ContextMenu/index.tsx b/packages/ui/src/ContextMenu/index.tsx new file mode 100644 index 000000000..06b1e26da --- /dev/null +++ b/packages/ui/src/ContextMenu/index.tsx @@ -0,0 +1,107 @@ +import * as RadixCM from "@radix-ui/react-context-menu" +import clsx from "clsx"; +import { CaretRight, Icon } from "phosphor-react"; +import { HTMLAttributes, PropsWithChildren, Suspense, } from "react" +import React from 'react' +import { cva, VariantProps } from "class-variance-authority"; + +interface Props extends RadixCM.MenuContentProps { + trigger: React.ReactNode, +} + +const MENU_CLASSES = ` + flex flex-col + min-w-[11rem] p-2 space-y-1 + text-left text-sm dark:text-gray-100 text-gray-800 + bg-gray-50 border-gray-200 dark:bg-gray-950 + shadow-md shadow-gray-300 dark:shadow-gray-750 + select-none cursor-default rounded-lg +`; + +export const ContextMenu = ({ trigger, children, className, ...props }: PropsWithChildren) => { + return ( + + {trigger} + + + {children} + + + + ) +} + +export const Separator = () => + + +export const SubMenu = ({ label, icon, className, ...props }: RadixCM.MenuSubContentProps & ItemProps) => { + return ( + + + + + + + + + + + ) +} + +const ITEM_CLASSES = ` + flex flex-row items-center justify-start flex-1 + px-2 py-1 space-x-2 + cursor-default rounded + focus:outline-none +`; + +const itemStyles = cva([ITEM_CLASSES], { + variants: { + variant: { + default: 'hover:bg-primary focus:bg-primary', + danger: ` + text-red-600 dark:text-red-400 + hover:text-white focus:text-white + hover:bg-red-500 focus:bg-red-500 + ` + } + }, + defaultVariants: { + variant: 'default' + } +}) + +interface ItemProps extends VariantProps { + icon?: Icon, + rightArrow?: boolean, + label?: string, +} + +export const Item = ({ icon, label, rightArrow, children, variant, ...props }: ItemProps & RadixCM.MenuItemProps) => ( + + {children ? children : } + +) + +const DivItem = ({ variant, ...props }: ItemProps) => ( +
+ +
+) + + +const ItemInternals = ({ icon, label, rightArrow }: ItemProps) => { + const ItemIcon = icon; + return ( + <> + {ItemIcon && } + {label &&

{label}

} + + {rightArrow && <> +
+ + } + + ) +} diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index a305cff1c..ca98bd6fb 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -1,4 +1,5 @@ export * from './Button'; export * from './Dropdown'; export * from './ContextMenu'; +export * as NewContextMenu from "./ContextMenu/index" export * from './Input'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e66a95e5b2cad4a716d05cd703c2b4a5ee525397..81a2ed2f59e494f01a439c4f499716e2f6411873 100644 GIT binary patch delta 11189 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