implement drag handles

This commit is contained in:
sawka 2024-06-19 23:00:57 -07:00
parent fb668fd4e5
commit c7f76d5ced
5 changed files with 64 additions and 19 deletions

View File

@ -88,6 +88,7 @@
font: var(--fixed-font);
color: var(--secondary-text-color);
white-space: nowrap;
cursor: grab;
}
.block-frame-tech-close {
@ -128,6 +129,7 @@
-webkit-user-select: none;
cursor: default;
border-radius: 0 0 4px 4px;
cursor: grab;
.block-header-icon {
font-size: 20px;
@ -145,9 +147,9 @@
padding: 5px 5px 5px 5px;
margin-right: 5px;
border-radius: 4px;
cursor: pointer;
&:hover {
cursor: pointer;
background-color: var(--highlight-bg-color);
}
}

View File

@ -22,6 +22,7 @@ const HoverTimeoutMs = 100;
interface BlockProps {
blockId: string;
onClose?: () => void;
dragHandleRef?: React.RefObject<HTMLDivElement>;
}
function getBlockHeaderText(blockData: Block): string {
@ -31,11 +32,17 @@ function getBlockHeaderText(blockData: Block): string {
return `${blockData?.view} [${blockData.oid.substring(0, 8)}]`;
}
const FramelessBlockHeader = ({ blockId, onClose }: BlockProps) => {
interface FramelessBlockHeaderProps {
blockId: string;
onClose?: () => void;
dragHandleRef?: React.RefObject<HTMLDivElement>;
}
const FramelessBlockHeader = ({ blockId, onClose, dragHandleRef }: FramelessBlockHeaderProps) => {
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
return (
<div key="header" className="block-header">
<div key="header" className="block-header" ref={dragHandleRef}>
<div className="block-header-text text-fixed">{getBlockHeaderText(blockData)}</div>
{onClose && (
<div className="close-button" onClick={onClose}>
@ -57,9 +64,18 @@ interface BlockFrameProps {
preview: boolean;
children?: React.ReactNode;
blockRef?: React.RefObject<HTMLDivElement>;
dragHandleRef?: React.RefObject<HTMLDivElement>;
}
const BlockFrame_Tech = ({ blockId, onClose, onClick, preview, blockRef, children }: BlockFrameProps) => {
const BlockFrame_Tech = ({
blockId,
onClose,
onClick,
preview,
blockRef,
dragHandleRef,
children,
}: BlockFrameProps) => {
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
const isFocusedAtom = useBlockAtom<boolean>(blockId, "isFocused", () => {
return jotai.atom((get) => {
@ -82,7 +98,9 @@ const BlockFrame_Tech = ({ blockId, onClose, onClick, preview, blockRef, childre
onClick={onClick}
ref={blockRef}
>
<div className="block-frame-tech-header">{getBlockHeaderText(blockData)}</div>
<div className="block-frame-tech-header" ref={dragHandleRef}>
{getBlockHeaderText(blockData)}
</div>
<div className="block-frame-tech-close" onClick={onClose}>
<i className="fa fa-solid fa-xmark fa-fw " />
</div>
@ -91,7 +109,15 @@ const BlockFrame_Tech = ({ blockId, onClose, onClick, preview, blockRef, childre
);
};
const BlockFrame_Frameless = ({ blockId, onClose, onClick, preview, blockRef, children }: BlockFrameProps) => {
const BlockFrame_Frameless = ({
blockId,
onClose,
onClick,
preview,
blockRef,
dragHandleRef,
children,
}: BlockFrameProps) => {
const localBlockRef = React.useRef<HTMLDivElement>(null);
const [showHeader, setShowHeader] = React.useState(preview ? true : false);
const hoverState = React.useRef(hoverStateOff);
@ -150,7 +176,7 @@ const BlockFrame_Frameless = ({ blockId, onClose, onClick, preview, blockRef, ch
className={clsx("block-header-animation-wrap", showHeader ? "is-showing" : null)}
onMouseLeave={mouseLeaveHandler}
>
<FramelessBlockHeader blockId={blockId} onClose={onClose} />
<FramelessBlockHeader blockId={blockId} onClose={onClose} dragHandleRef={dragHandleRef} />
</div>
{preview ? <div className="block-frame-preview" /> : children}
</div>
@ -184,7 +210,7 @@ function setBlockFocus(blockId: string) {
WOS.setObjectValue(winData, globalStore.set, true);
}
const Block = ({ blockId, onClose }: BlockProps) => {
const Block = ({ blockId, onClose, dragHandleRef }: BlockProps) => {
let blockElem: JSX.Element = null;
const focusElemRef = React.useRef<HTMLInputElement>(null);
const blockRef = React.useRef<HTMLDivElement>(null);
@ -222,6 +248,7 @@ const Block = ({ blockId, onClose }: BlockProps) => {
preview={false}
onClick={() => setBlockClicked(true)}
blockRef={blockRef}
dragHandleRef={dragHandleRef}
>
<div key="focuselem" className="block-focuselem">
<input type="text" value="" ref={focusElemRef} onChange={() => {}} />

View File

@ -20,13 +20,21 @@ const TabContent = ({ tabId }: { tabId: string }) => {
const layoutStateAtom = useMemo(() => getLayoutStateAtomForTab(tabId, tabAtom), [tabAtom, tabId]);
const tabData = useAtomValue(tabAtom);
const renderBlock = useCallback((tabData: TabLayoutData, ready: boolean, onClose: () => void) => {
// console.log("renderBlock", tabData);
if (!tabData.blockId || !ready) {
return null;
}
return <Block blockId={tabData.blockId} onClose={onClose} />;
}, []);
const renderBlock = useCallback(
(
tabData: TabLayoutData,
ready: boolean,
onClose: () => void,
dragHandleRef: React.RefObject<HTMLDivElement>
) => {
// console.log("renderBlock", tabData);
if (!tabData.blockId || !ready) {
return null;
}
return <Block blockId={tabData.blockId} onClose={onClose} dragHandleRef={dragHandleRef} />;
},
[]
);
const renderPreview = useCallback((tabData: TabLayoutData) => {
console.log("renderPreview", tabData);

View File

@ -322,6 +322,7 @@ const DisplayNode = <T,>({
ready,
}: DisplayNodeProps<T>) => {
const tileNodeRef = useRef<HTMLDivElement>(null);
const dragHandleRef = useRef<HTMLDivElement>(null);
const previewRef = useRef<HTMLDivElement>(null);
const hasImagePreviewSetRef = useRef(false);
@ -369,8 +370,10 @@ const DisplayNode = <T,>({
// Register the tile item as a draggable component
useEffect(() => {
drag(tileNodeRef);
}, [tileNodeRef]);
if (dragHandleRef.current) {
drag(dragHandleRef);
}
}, [ready]);
const onClose = useCallback(() => {
onLeafClose(layoutNode);
@ -380,7 +383,7 @@ const DisplayNode = <T,>({
return (
layoutNode.data && (
<div key="leaf" className="tile-leaf">
{renderContent(layoutNode.data, ready, onClose)}
{renderContent(layoutNode.data, ready, onClose, dragHandleRef)}
</div>
)
);

View File

@ -158,7 +158,12 @@ export type WritableLayoutNodeAtom<T> = WritableAtom<LayoutNode<T>, [value: Layo
*/
export type WritableLayoutTreeStateAtom<T> = WritableAtom<LayoutTreeState<T>, [value: LayoutTreeState<T>], void>;
export type ContentRenderer<T> = (data: T, ready: boolean, onClose?: () => void) => React.ReactNode;
export type ContentRenderer<T> = (
data: T,
ready: boolean,
onClose: () => void,
dragHandleRef: React.RefObject<HTMLDivElement>
) => React.ReactNode;
export type PreviewRenderer<T> = (data: T) => React.ReactElement;