Files
next-tjwater-frontend/src/features/workbench/components/scheduled-condition-workspace.tsx
T
jiang 7a304a91a8
Generic Container CI/CD / test-build-publish (push) Successful in 1m13s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 1m14s
feat(workbench): dock task and chart workspaces
2026-11-12 11:42:25 +08:00

38 lines
1.5 KiB
TypeScript

import { useLayoutEffect, useRef, useState, type ReactNode, type RefObject } from "react";
import { createPortal } from "react-dom";
/** Move the live panel without resetting filters, report state or pending input. */
export function ScheduledConditionWorkspace({
docked, dockTarget, hidden, children
}: {
docked: boolean;
dockTarget: RefObject<HTMLDivElement | null>;
hidden: boolean;
children: ReactNode;
}) {
const floating = useRef<HTMLDivElement>(null);
const restoreFocus = useRef(false);
const [host] = useState(() => {
const element = document.createElement("div");
element.className = "h-full min-h-0 min-w-0";
return element;
});
useLayoutEffect(() => {
const target = docked ? dockTarget.current : floating.current;
target?.append(host);
// Moving the host can drop keyboard focus. Restore the corresponding control.
if (restoreFocus.current && !hidden) host.querySelector<HTMLButtonElement>("[data-condition-dock-toggle]")?.focus({ preventScroll: true });
return () => {
restoreFocus.current = host.contains(document.activeElement);
host.remove();
};
}, [dockTarget, docked, hidden, host]);
return <>
<div ref={floating}
className="pointer-events-none absolute bottom-[calc(var(--workbench-timeline-height)+1.25rem)] right-16 top-24 z-50 hidden lg:block 2xl:[--workbench-condition-width:var(--workbench-condition-width-wide)]"
style={hidden || docked ? { display: "none" } : undefined} />
{createPortal(children, host)}
</>;
}