From c50ba5b2b47a7c3d929b67be09e6267bb5f4a1dd Mon Sep 17 00:00:00 2001 From: Triston Armstrong Date: Sat, 12 Oct 2024 13:20:52 -0400 Subject: [PATCH 1/2] feat(contextmenu): adds context menu support to the ap i can now create a context menu for anything --- bun.lockb | Bin 114724 -> 115127 bytes package.json | 1 + src/App.tsx | 1 + src/components/ContextMenuPortal.tsx | 44 ++++++++++++++ src/components/ImageCard.tsx | 82 ++++++++++++++++++++------- src/components/NoteCard.tsx | 39 +++++++++++++ 6 files changed, 145 insertions(+), 22 deletions(-) create mode 100644 src/components/ContextMenuPortal.tsx diff --git a/bun.lockb b/bun.lockb index dbb1abe2df37987ad8f701e3bb754fcfe37797d7..56b29729f01466dd2139be249306079413266702 100755 GIT binary patch delta 19976 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 TtA(3iNmonN=6T~)s}cVN2AoL_ diff --git a/package.json b/package.json index 728dbae..724a55b 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "commit": "cz" }, "dependencies": { + "@kaioken-core/hooks": "^0.0.8", "@tauri-apps/api": "^1", "caniuse-lite": "^1.0.30001667", "kaioken": "^0.32.1", diff --git a/src/App.tsx b/src/App.tsx index 4189a94..1094b82 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,6 +9,7 @@ export function App() { return ( +
) } diff --git a/src/components/ContextMenuPortal.tsx b/src/components/ContextMenuPortal.tsx new file mode 100644 index 0000000..2c57cab --- /dev/null +++ b/src/components/ContextMenuPortal.tsx @@ -0,0 +1,44 @@ +import { useClickOutside, useMouse } from "@kaioken-core/hooks"; +import { Portal, signal, useEffect, useRef } from "kaioken"; + +namespace ContextMenuPortal { + export interface Props { + children: JSX.Children + open: boolean + closeAction: (() => void) | null | undefined + } +} +export function ContextMenuPortal({ children, open, closeAction }: ContextMenuPortal.Props) { + const { mouse } = useMouse() + const pos = signal({ x: 0, y: 0 }) + const ref = useRef(null) + + useClickOutside(ref, () => { + closeAction?.() + }) + + useEffect(() => { + if (!open) return + pos.value = { x: mouse.x, y: mouse.y } + }, [open]) + + if (!open) return null + + return ( + document.querySelector("#context-menu-portal")!} + > +
+ {children} +
+
+ ) +} diff --git a/src/components/ImageCard.tsx b/src/components/ImageCard.tsx index bbecaaa..073ba02 100644 --- a/src/components/ImageCard.tsx +++ b/src/components/ImageCard.tsx @@ -5,6 +5,7 @@ import { LayerEnum } from "../utils/enums" import images, { ImageCardType } from "../signals/images" import { updateLocalStorage } from "../utils/localStorage" import { useThemeDetector } from "../utils/useThemeDetector" +import { ContextMenuPortal } from "./ContextMenuPortal" namespace ImageCard { export interface ImageCardProps { @@ -22,6 +23,7 @@ export function ImageCard({ key: itemKey, data: item }: ImageCard.ImageCardProps const offsetY = useRef(0) const initialResizeX = useRef(0) const initialResizeY = useRef(0) + const openContextMenu = signal(false) function debounceLSUpdate(time?: number) { debounce(() => { @@ -93,29 +95,65 @@ export function ImageCard({ key: itemKey, data: item }: ImageCard.ImageCardProps ImagesSignal.default.images.notify() } - return ( -
- + function _handleMouseClick(e: MouseEvent) { + e.preventDefault() + openContextMenu.value = !openContextMenu.value + } - -
+ function _handleContextClose() { + openContextMenu.value = false + } + + return ( + <> +
+ + + +
+ + +
+
+
+ {item.title} +
+
+ +
+ +
+
    +
  • + +
  • +
  • +
  • +
+
+
+
+ ) } diff --git a/src/components/NoteCard.tsx b/src/components/NoteCard.tsx index 1e1c82d..ff18c7b 100644 --- a/src/components/NoteCard.tsx +++ b/src/components/NoteCard.tsx @@ -9,6 +9,7 @@ import { ChangeEvent } from "tiny-markdown-editor" import { Divider } from "./Divider" import { ExportIcon } from "./icons/ExportIcon" import { createFileAndExport } from "../utils/createFileAndExport" +import { ContextMenuPortal } from "./ContextMenuPortal" namespace NoteCard { export interface NoteCardProps { @@ -26,6 +27,7 @@ export function NoteCard({ key: itemKey, data: item }: NoteCard.NoteCardProps) { const offsetY = useRef(0) const initialResizeX = useRef(0) const initialResizeY = useRef(0) + const openContextMenu = signal(false) const { debounce } = useDebounce() @@ -113,6 +115,15 @@ export function NoteCard({ key: itemKey, data: item }: NoteCard.NoteCardProps) { createFileAndExport("Note", item.contents, "text/markdown") } + function _handleMouseClick(e: MouseEvent) { + e.preventDefault() + openContextMenu.value = !openContextMenu.value + } + + function _handleContextClose() { + openContextMenu.value = false + } + const cardPositionStyle = { zIndex: `${focusedItem.value == itemKey ? LayerEnum.CARD_ELEVATED : LayerEnum.CARD}`, width: `${item.dimensions.w}px`, @@ -127,6 +138,7 @@ export function NoteCard({ key: itemKey, data: item }: NoteCard.NoteCardProps) { return (
+ + +
+
+
+ {item.title} +
+
+ +
+ +
+
    +
  • + +
  • +
  • + +
  • +
+
+
+
) From a2259f40ed8451f1f087e83baee5a6253da38b4a Mon Sep 17 00:00:00 2001 From: Triston Armstrong Date: Sat, 12 Oct 2024 13:31:15 -0400 Subject: [PATCH 2/2] feat(contextmenu): adds escape keyevent closing menu --- src/components/ContextMenuPortal.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/ContextMenuPortal.tsx b/src/components/ContextMenuPortal.tsx index 2c57cab..e57278a 100644 --- a/src/components/ContextMenuPortal.tsx +++ b/src/components/ContextMenuPortal.tsx @@ -1,4 +1,4 @@ -import { useClickOutside, useMouse } from "@kaioken-core/hooks"; +import { useClickOutside, useKeyStroke, useMouse } from "@kaioken-core/hooks"; import { Portal, signal, useEffect, useRef } from "kaioken"; namespace ContextMenuPortal { @@ -20,6 +20,14 @@ export function ContextMenuPortal({ children, open, closeAction }: ContextMenuPo useEffect(() => { if (!open) return pos.value = { x: mouse.x, y: mouse.y } + function _handleEscapeKey(e: KeyboardEvent) { + if (e.key !== "Escape") return + closeAction?.() + } + document.addEventListener("keydown", _handleEscapeKey) + return () => { + document.removeEventListener("keydown", _handleEscapeKey) + } }, [open]) if (!open) return null