import { nanoid } from '$lib/@iioioo_utils/Services/nanoid'; import { dragDropMachine } from '$lib/@iioioo_utils/State/dragDrop.machine'; import { BehaviorSubject, filter } from 'rxjs'; import { interpret, Interpreter } from 'xstate'; import type { DragDropContext, DragDropState, DragDropEvent } from '../State/types/dragDrop.types'; let machine, service: Interpreter; export const currentPosition: BehaviorSubject<{dx: number, dy: number}> = new BehaviorSubject({dx:0,dy:0}); export const currentData: BehaviorSubject<{ itemBeingDragged: any, itemBelow: any }> = new BehaviorSubject({itemBeingDragged:null,itemBelow:null}); export const broadcast: BehaviorSubject<{ itemBeingDragged: any, itemBelow: any }> = new BehaviorSubject({itemBeingDragged:null,itemBelow:null}); export const listeners: BehaviorSubject = new BehaviorSubject([]); listeners.subscribe(list => { list.forEach(el => { el.addEventListener('mousedown', handleMousedown); el.addEventListener('mouseenter', handleMouseenter); el.addEventListener('mouseleave', handleMouseleave); }); }) function handleMousedown(event) { if(!event.target.dataset.dragging) return; event.stopPropagation(); const node = JSON.parse(event.target.dataset.dragging); service.send({ type: 'PICK', item: node, x: event.clientX, y: event.clientY }) window.addEventListener('mousemove', handleMousemove); window.addEventListener('mouseup', handleMouseup); } function handleMouseenter(event) { const node = JSON.parse(event.target.dataset.dragging); service.send({ type: 'ENTER', item: node }); } function handleMouseleave(event) { const node = JSON.parse(event.target.dataset.dragging); service.send({ type: 'LEAVE', item: node }) } function handleMousemove(event) { service.send({ type: 'MOVE', x: event.clientX, y: event.clientY }) } function handleMouseup() { service.send({ type: 'DROP' }); window.removeEventListener('mousemove', handleMousemove); window.removeEventListener('mouseup', handleMouseup); } export function addListeners() { const draggables = document.querySelectorAll('[data-dragging]'); const draggableArray = Array.from(draggables) const currentLength = listeners.getValue().length; draggableArray.length > currentLength && listeners.next( draggableArray ); } export function pannable(node) { // machine = dragDropMachine( nanoid(), broadcast ); machine = dragDropMachine( nanoid(), broadcast ); // Interpret the machine, and add a listener for whenever a transition occurs. service = interpret(machine).onTransition((state) => { if (state.changed) { node.dataset.state = state.toStrings().join(" "); const { dx, dy, itemBeingDragged, itemBelow } = state.context; currentPosition.next({ dx, dy }); currentData.next({ itemBeingDragged, itemBelow }); } }) as any; service.start(); addListeners(); return { destroy() { listeners.getValue().forEach(el => { el.addEventListener('mousedown', handleMousedown); el.addEventListener('mouseenter', handleMouseenter); el.addEventListener('mouseleave', handleMouseleave); }); service.stop(); } }; }