mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
implement drag handles
This commit is contained in:
parent
fb668fd4e5
commit
c7f76d5ced
@ -88,6 +88,7 @@
|
|||||||
font: var(--fixed-font);
|
font: var(--fixed-font);
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
cursor: grab;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-frame-tech-close {
|
.block-frame-tech-close {
|
||||||
@ -128,6 +129,7 @@
|
|||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
border-radius: 0 0 4px 4px;
|
border-radius: 0 0 4px 4px;
|
||||||
|
cursor: grab;
|
||||||
|
|
||||||
.block-header-icon {
|
.block-header-icon {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
@ -145,9 +147,9 @@
|
|||||||
padding: 5px 5px 5px 5px;
|
padding: 5px 5px 5px 5px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
|
||||||
background-color: var(--highlight-bg-color);
|
background-color: var(--highlight-bg-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ const HoverTimeoutMs = 100;
|
|||||||
interface BlockProps {
|
interface BlockProps {
|
||||||
blockId: string;
|
blockId: string;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
|
dragHandleRef?: React.RefObject<HTMLDivElement>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBlockHeaderText(blockData: Block): string {
|
function getBlockHeaderText(blockData: Block): string {
|
||||||
@ -31,11 +32,17 @@ function getBlockHeaderText(blockData: Block): string {
|
|||||||
return `${blockData?.view} [${blockData.oid.substring(0, 8)}]`;
|
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));
|
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
|
||||||
|
|
||||||
return (
|
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>
|
<div className="block-header-text text-fixed">{getBlockHeaderText(blockData)}</div>
|
||||||
{onClose && (
|
{onClose && (
|
||||||
<div className="close-button" onClick={onClose}>
|
<div className="close-button" onClick={onClose}>
|
||||||
@ -57,9 +64,18 @@ interface BlockFrameProps {
|
|||||||
preview: boolean;
|
preview: boolean;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
blockRef?: React.RefObject<HTMLDivElement>;
|
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 [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
|
||||||
const isFocusedAtom = useBlockAtom<boolean>(blockId, "isFocused", () => {
|
const isFocusedAtom = useBlockAtom<boolean>(blockId, "isFocused", () => {
|
||||||
return jotai.atom((get) => {
|
return jotai.atom((get) => {
|
||||||
@ -82,7 +98,9 @@ const BlockFrame_Tech = ({ blockId, onClose, onClick, preview, blockRef, childre
|
|||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
ref={blockRef}
|
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}>
|
<div className="block-frame-tech-close" onClick={onClose}>
|
||||||
<i className="fa fa-solid fa-xmark fa-fw " />
|
<i className="fa fa-solid fa-xmark fa-fw " />
|
||||||
</div>
|
</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 localBlockRef = React.useRef<HTMLDivElement>(null);
|
||||||
const [showHeader, setShowHeader] = React.useState(preview ? true : false);
|
const [showHeader, setShowHeader] = React.useState(preview ? true : false);
|
||||||
const hoverState = React.useRef(hoverStateOff);
|
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)}
|
className={clsx("block-header-animation-wrap", showHeader ? "is-showing" : null)}
|
||||||
onMouseLeave={mouseLeaveHandler}
|
onMouseLeave={mouseLeaveHandler}
|
||||||
>
|
>
|
||||||
<FramelessBlockHeader blockId={blockId} onClose={onClose} />
|
<FramelessBlockHeader blockId={blockId} onClose={onClose} dragHandleRef={dragHandleRef} />
|
||||||
</div>
|
</div>
|
||||||
{preview ? <div className="block-frame-preview" /> : children}
|
{preview ? <div className="block-frame-preview" /> : children}
|
||||||
</div>
|
</div>
|
||||||
@ -184,7 +210,7 @@ function setBlockFocus(blockId: string) {
|
|||||||
WOS.setObjectValue(winData, globalStore.set, true);
|
WOS.setObjectValue(winData, globalStore.set, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Block = ({ blockId, onClose }: BlockProps) => {
|
const Block = ({ blockId, onClose, dragHandleRef }: BlockProps) => {
|
||||||
let blockElem: JSX.Element = null;
|
let blockElem: JSX.Element = null;
|
||||||
const focusElemRef = React.useRef<HTMLInputElement>(null);
|
const focusElemRef = React.useRef<HTMLInputElement>(null);
|
||||||
const blockRef = React.useRef<HTMLDivElement>(null);
|
const blockRef = React.useRef<HTMLDivElement>(null);
|
||||||
@ -222,6 +248,7 @@ const Block = ({ blockId, onClose }: BlockProps) => {
|
|||||||
preview={false}
|
preview={false}
|
||||||
onClick={() => setBlockClicked(true)}
|
onClick={() => setBlockClicked(true)}
|
||||||
blockRef={blockRef}
|
blockRef={blockRef}
|
||||||
|
dragHandleRef={dragHandleRef}
|
||||||
>
|
>
|
||||||
<div key="focuselem" className="block-focuselem">
|
<div key="focuselem" className="block-focuselem">
|
||||||
<input type="text" value="" ref={focusElemRef} onChange={() => {}} />
|
<input type="text" value="" ref={focusElemRef} onChange={() => {}} />
|
||||||
|
@ -20,13 +20,21 @@ const TabContent = ({ tabId }: { tabId: string }) => {
|
|||||||
const layoutStateAtom = useMemo(() => getLayoutStateAtomForTab(tabId, tabAtom), [tabAtom, tabId]);
|
const layoutStateAtom = useMemo(() => getLayoutStateAtomForTab(tabId, tabAtom), [tabAtom, tabId]);
|
||||||
const tabData = useAtomValue(tabAtom);
|
const tabData = useAtomValue(tabAtom);
|
||||||
|
|
||||||
const renderBlock = useCallback((tabData: TabLayoutData, ready: boolean, onClose: () => void) => {
|
const renderBlock = useCallback(
|
||||||
|
(
|
||||||
|
tabData: TabLayoutData,
|
||||||
|
ready: boolean,
|
||||||
|
onClose: () => void,
|
||||||
|
dragHandleRef: React.RefObject<HTMLDivElement>
|
||||||
|
) => {
|
||||||
// console.log("renderBlock", tabData);
|
// console.log("renderBlock", tabData);
|
||||||
if (!tabData.blockId || !ready) {
|
if (!tabData.blockId || !ready) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <Block blockId={tabData.blockId} onClose={onClose} />;
|
return <Block blockId={tabData.blockId} onClose={onClose} dragHandleRef={dragHandleRef} />;
|
||||||
}, []);
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const renderPreview = useCallback((tabData: TabLayoutData) => {
|
const renderPreview = useCallback((tabData: TabLayoutData) => {
|
||||||
console.log("renderPreview", tabData);
|
console.log("renderPreview", tabData);
|
||||||
|
@ -322,6 +322,7 @@ const DisplayNode = <T,>({
|
|||||||
ready,
|
ready,
|
||||||
}: DisplayNodeProps<T>) => {
|
}: DisplayNodeProps<T>) => {
|
||||||
const tileNodeRef = useRef<HTMLDivElement>(null);
|
const tileNodeRef = useRef<HTMLDivElement>(null);
|
||||||
|
const dragHandleRef = useRef<HTMLDivElement>(null);
|
||||||
const previewRef = useRef<HTMLDivElement>(null);
|
const previewRef = useRef<HTMLDivElement>(null);
|
||||||
const hasImagePreviewSetRef = useRef(false);
|
const hasImagePreviewSetRef = useRef(false);
|
||||||
|
|
||||||
@ -369,8 +370,10 @@ const DisplayNode = <T,>({
|
|||||||
|
|
||||||
// Register the tile item as a draggable component
|
// Register the tile item as a draggable component
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
drag(tileNodeRef);
|
if (dragHandleRef.current) {
|
||||||
}, [tileNodeRef]);
|
drag(dragHandleRef);
|
||||||
|
}
|
||||||
|
}, [ready]);
|
||||||
|
|
||||||
const onClose = useCallback(() => {
|
const onClose = useCallback(() => {
|
||||||
onLeafClose(layoutNode);
|
onLeafClose(layoutNode);
|
||||||
@ -380,7 +383,7 @@ const DisplayNode = <T,>({
|
|||||||
return (
|
return (
|
||||||
layoutNode.data && (
|
layoutNode.data && (
|
||||||
<div key="leaf" className="tile-leaf">
|
<div key="leaf" className="tile-leaf">
|
||||||
{renderContent(layoutNode.data, ready, onClose)}
|
{renderContent(layoutNode.data, ready, onClose, dragHandleRef)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -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 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;
|
export type PreviewRenderer<T> = (data: T) => React.ReactElement;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user