From 52e04330bcb7c9687caebb26dc30d07697661d09 Mon Sep 17 00:00:00 2001 From: sawka Date: Wed, 19 Jun 2024 11:58:22 -0700 Subject: [PATCH] blocks now implement a focus of last resort and interact with the block focus field in window. --- frontend/app/block/block.less | 11 ++++++ frontend/app/block/block.tsx | 63 +++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/frontend/app/block/block.less b/frontend/app/block/block.less index 54af5a40..e3808e97 100644 --- a/frontend/app/block/block.less +++ b/frontend/app/block/block.less @@ -21,6 +21,17 @@ padding: 5px; } + .block-focuselem { + height: 0; + width: 0; + input { + width: 0; + height: 0; + opacity: 0; + pointer-events: none; + } + } + .block-header-animation-wrap { max-height: 0; transition: diff --git a/frontend/app/block/block.tsx b/frontend/app/block/block.tsx index c65ad096..8909f8c1 100644 --- a/frontend/app/block/block.tsx +++ b/frontend/app/block/block.tsx @@ -7,9 +7,10 @@ import { PreviewView } from "@/app/view/preview"; import { TerminalView } from "@/app/view/term/term"; import { ErrorBoundary } from "@/element/errorboundary"; import { CenteredDiv } from "@/element/quickelems"; -import { atoms, useBlockAtom } from "@/store/global"; +import { atoms, globalStore, useBlockAtom } from "@/store/global"; import * as WOS from "@/store/wos"; import clsx from "clsx"; +import { produce } from "immer"; import * as jotai from "jotai"; import * as React from "react"; @@ -52,11 +53,13 @@ const hoverStateOn = "on"; interface BlockFrameProps { blockId: string; onClose?: () => void; + onClick?: () => void; preview: boolean; children?: React.ReactNode; + blockRef?: React.RefObject; } -const BlockFrame_Tech = ({ blockId, onClose, preview, children }: BlockFrameProps) => { +const BlockFrame_Tech = ({ blockId, onClose, onClick, preview, blockRef, children }: BlockFrameProps) => { const [blockData] = WOS.useWaveObjectValue(WOS.makeORef("block", blockId)); const isFocusedAtom = useBlockAtom(blockId, "isFocused", () => { return jotai.atom((get) => { @@ -76,6 +79,8 @@ const BlockFrame_Tech = ({ blockId, onClose, preview, children }: BlockFrameProp isFocused ? "block-focused" : null, preview ? "block-preview" : null )} + onClick={onClick} + ref={blockRef} >
{getBlockHeaderText(blockData)}
@@ -86,16 +91,19 @@ const BlockFrame_Tech = ({ blockId, onClose, preview, children }: BlockFrameProp ); }; -const BlockFrame_Frameless = ({ blockId, onClose, preview, children }: BlockFrameProps) => { - const blockRef = React.useRef(null); +const BlockFrame_Frameless = ({ blockId, onClose, onClick, preview, blockRef, children }: BlockFrameProps) => { + const localBlockRef = React.useRef(null); const [showHeader, setShowHeader] = React.useState(preview ? true : false); const hoverState = React.useRef(hoverStateOff); + // this forward the lcal ref to the blockRef + React.useImperativeHandle(blockRef, () => localBlockRef.current); + React.useEffect(() => { if (preview) { return; } - const block = blockRef.current; + const block = localBlockRef.current; let hoverTimeout: NodeJS.Timeout = null; const handleMouseMove = (event) => { const rect = block.getBoundingClientRect(); @@ -132,7 +140,12 @@ const BlockFrame_Frameless = ({ blockId, onClose, preview, children }: BlockFram hoverState.current = hoverStateOff; }; return ( -
+
{ return ; }; +function setBlockFocus(blockId: string) { + let winData = globalStore.get(atoms.waveWindow); + if (winData.activeblockid === blockId) { + return; + } + winData = produce(winData, (draft) => { + draft.activeblockid = blockId; + }); + WOS.setObjectValue(winData, globalStore.set, true); +} + const Block = ({ blockId, onClose }: BlockProps) => { let blockElem: JSX.Element = null; + const focusElemRef = React.useRef(null); + const blockRef = React.useRef(null); + const [blockClicked, setBlockClicked] = React.useState(false); const [blockData, blockDataLoading] = WOS.useWaveObjectValue(WOS.makeORef("block", blockId)); + + React.useLayoutEffect(() => { + if (!blockClicked) { + return; + } + setBlockClicked(false); + const focusWithin = blockRef.current?.contains(document.activeElement); + if (!focusWithin) { + focusElemRef.current?.focus(); + } + setBlockFocus(blockId); + }, [blockClicked]); + if (!blockId || !blockData) return null; if (blockDataLoading) { blockElem = Loading...; @@ -176,7 +216,16 @@ const Block = ({ blockId, onClose }: BlockProps) => { blockElem = ; } return ( - + setBlockClicked(true)} + blockRef={blockRef} + > +
+ {}} /> +
Loading...}>{blockElem}