diff --git a/bun.lockb b/bun.lockb index dbb1abe..56b2972 100755 Binary files a/bun.lockb and b/bun.lockb differ 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..e57278a --- /dev/null +++ b/src/components/ContextMenuPortal.tsx @@ -0,0 +1,52 @@ +import { useClickOutside, useKeyStroke, 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 } + function _handleEscapeKey(e: KeyboardEvent) { + if (e.key !== "Escape") return + closeAction?.() + } + document.addEventListener("keydown", _handleEscapeKey) + return () => { + document.removeEventListener("keydown", _handleEscapeKey) + } + }, [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} +
+
+ +
+ +
+
    +
  • + +
  • +
  • + +
  • +
+
+
+
)