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 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(