import { useCanvasOpen } from '@agent/components/Canvas'; import { useDraggable } from '@agent/hooks/useDraggable'; import { usePortal } from '@agent/hooks/usePortal'; import { useResizable } from '@agent/hooks/useResizable'; import { useGlobalStore } from '@agent/state/global'; import { usePositionStore } from '@agent/state/position'; import { createPortal, useCallback, useEffect, useState, } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { close, Icon } from '@wordpress/icons'; import { AnimatePresence, motion } from 'framer-motion'; // TODO: some of the bound checking isn't working that well. // For example, the user shrinks the height of the browser. // On reload this should at least put the window in bounds. // Maybe a resize observer would be useful. export const DragResizeLayout = ({ children }) => { const [el, setEl] = useState(null); const mountNode = usePortal('extendify-agent-mount'); const { open, setOpen } = useGlobalStore(); // So it will re-render the hooks when mounted const ref = useCallback( (node) => requestAnimationFrame(() => setEl(node)), [], ); useDraggable({ el, open, initialPosition: usePositionStore.getState(), onDragEnd: (x, y) => { usePositionStore.getState().setPosition(x, y); // External contract: no in-repo listener by design — emitted for // host-page/analytics consumers (mirrors the consumed :resize-end below). window.dispatchEvent( new CustomEvent('extendify-agent:drag-end', { detail: { x, y } }), ); }, }); useResizable({ el, open, initialSize: usePositionStore.getState(), onResizeEnd: (width, height) => { usePositionStore.setState({ width, height }); window.dispatchEvent( new CustomEvent('extendify-agent:resize-end', { detail: { width, height }, }), ); }, }); useEffect(() => { if (!el || !open) return; // If it's not intersecting, close it const observer = new IntersectionObserver((entries) => { if (!entries[0].isIntersecting) setOpen(false); }); observer.observe(el); return () => observer.disconnect(); }, [el, open, setOpen]); const canvasOpen = useCanvasOpen(); const closeAgent = () => { setOpen(false); // External contract: no in-repo listener by design — notifies // host-page/analytics consumers the user dismissed the agent. window.dispatchEvent(new CustomEvent('extendify-agent:closed-button')); }; if (!mountNode || !open) return null; return createPortal(
{window.extSharedData.partnerName}
{/* Only hidden: removing it shifts the drag handle to the edge. */}
{children}
, mountNode, ); }; const DragButton = (props) => { return (
); };