import { listener } from "../../utils/event.ts"; import { installGlobalVar, useStage } from "./use-global-vars.ts"; import { nextTick, ref, watchEffect } from "vue"; export const useListener = < T extends HTMLElement, K extends keyof HTMLElementEventMap >( eventName: K, callback: ( this: T, ev: HTMLElementEventMap[K], stageDOM: HTMLDivElement ) => any, target?: HTMLElement | Window ) => { const stage = useStage(); return watchEffect((onCleanup) => { if (stage.value) { const $stage = stage.value!.getStage(); const dom = $stage.container() as any; onCleanup( listener(target || dom, eventName, function (ev) { callback.call(this, ev, dom); }) ); } }); }; export const useGlobalResize = installGlobalVar(() => { const stage = useStage(); const size = ref<{ width: number; height: number }>(); const setSize = () => { if (fix.value) return; const container = stage.value?.getStage().container(); if (container) { container.style.setProperty("display", "none"); } const dom = stage.value!.getNode().container().parentElement!; size.value = { width: dom.offsetWidth, height: dom.offsetHeight, }; if (container) { container.style.removeProperty("display"); } }; const stopWatch = watchEffect(() => { if (stage.value) { setSize(); nextTick(() => stopWatch()); } }); let unResize = listener(window, 'resize', setSize) const fix = ref(false); let unWatch: (() => void) | null = null; const setFixSize = (fixSize: { width: number; height: number } | null) => { if (fixSize) { size.value = { ...fixSize }; unWatch && unWatch(); unWatch = watchEffect(() => { const $stage = stage.value?.getStage(); if ($stage) { $stage.width(fixSize.width); $stage.height(fixSize.height); nextTick(() => unWatch && unWatch()); } }); } if (fix.value && !fixSize) { unResize = listener(window, 'resize', setSize) fix.value = false; nextTick(setSize) } else if (!fix.value && fixSize) { fix.value = true; unResize(); } }; return { var: { setFixSize: setFixSize, updateSize: setSize, size, fix, }, onDestroy: () => { fix || unResize(); unWatch && unWatch(); }, }; }, Symbol("resize")); export const useResize = () => useGlobalResize().size; export const usePreemptiveListener = installGlobalVar(() => { const cbs: Record void)[]> = {}; const eventDestorys: Record void> = {}; const stage = useStage(); const add = (eventName: string, cb: (ev: Event) => void) => { if (!cbs[eventName]) { cbs[eventName] = []; const $stage = stage.value!.getStage(); const dom = $stage.container() as any; eventDestorys[eventName] = listener(dom, eventName as any, (ev: any) => { console.log(cbs[eventName], cbs[eventName][0]); cbs[eventName][0].call(this, ev); }); } cbs[eventName].push(cb); }; const remove = (eventName: string, cb?: (ev: Event) => void) => { if (!cbs[eventName]) return; if (cb) { const index = cbs[eventName].indexOf(cb); if (index !== -1) { cbs[eventName].splice(index, 1); } if (cbs[eventName].length === 0) { delete cbs[eventName]; } } else { delete cbs[eventName]; } if (!cbs[eventName]) { eventDestorys[eventName](); } }; const on = ( eventName: T, callback: (this: HTMLDivElement, ev: HTMLElementEventMap[T]) => any ) => { const stopWatch = watchEffect((onCleanup) => { if (stage.value) { add(eventName, callback as any); onCleanup(() => { remove(eventName, callback as any); }); } }); return stopWatch; }; return on; }, Symbol("preemptiveListener"));