UNPKG

go-captcha-svelte

Version:

GoCaptcha for Svelte, which implements click mode, slider mode, drag-drop mode and rotation mode.

180 lines (179 loc) 6.28 kB
/** * @Author Awen * @Date 2024/06/01 * @Email wengaolng@gmail.com **/ import { checkTargetFather } from "../helper/helper"; import { writable, get } from 'svelte/store'; export function useHandler(data, event, config, clearCbs) { let state = writable({ dragLeft: 0, thumbLeft: get(data).thumbX || 0, thumbTop: get(data).thumbY || 0 }); let isFreeze = false; let rootRef; let containerRef; let tileRef; let dragBlockRef; let dragBarRef; const unsubscribe = data.subscribe(() => { if (!isFreeze) { state.set({ ...get(state), thumbLeft: (get(data).thumbX || 0), thumbTop: (get(data).thumbY || 0) }); } }); const dragEvent = (e) => { if (!checkTargetFather(dragBarRef, e)) { return; } const touch = e.touches && e.touches[0]; const offsetLeft = dragBlockRef.offsetLeft; const width = containerRef.offsetWidth; const blockWidth = dragBlockRef.offsetWidth; const maxWidth = width - blockWidth; const tileWith = tileRef.offsetWidth; const tileOffsetLeft = tileRef.offsetLeft; const containerMaxWidth = width - tileWith; const tileMaxWith = width - (tileWith + tileOffsetLeft); const ratio = tileMaxWith / maxWidth; let isMoving = false; let tmpLeaveDragEvent = null; let startX = 0; let currentThumbX = 0; if (touch) { startX = touch.pageX - offsetLeft; } else { startX = e.clientX - offsetLeft; } const moveEvent = (e) => { isMoving = true; const mTouche = e.touches && e.touches[0]; const curState = get(state); let left = 0; if (mTouche) { left = mTouche.pageX - startX; } else { left = e.clientX - startX; } const ctX = tileOffsetLeft + (left * ratio); if (left >= maxWidth) { currentThumbX = containerMaxWidth; state.set({ ...curState, dragLeft: maxWidth, thumbLeft: currentThumbX }); return; } if (left <= 0) { currentThumbX = tileOffsetLeft; state.set({ ...curState, dragLeft: 0, thumbLeft: tileOffsetLeft }); return; } currentThumbX = ctX; state.set({ ...curState, thumbLeft: currentThumbX, dragLeft: left }); const ec = get(event); ec.move && ec.move(currentThumbX, curState.thumbTop || 0); e.cancelBubble = true; e.preventDefault(); }; const upEvent = (e) => { if (!checkTargetFather(dragBarRef, e)) { return; } clearEvent(); if (!isMoving) { return; } isMoving = false; if (currentThumbX < 0) { return; } const ec = get(event); ec.confirm && ec.confirm({ x: parseInt(currentThumbX.toString()), y: get(state).thumbTop || 0 }, () => { resetData(); }); e.cancelBubble = true; e.preventDefault(); }; const leaveDragBlockEvent = (e) => { tmpLeaveDragEvent = e; }; const enterDragBlockEvent = () => { tmpLeaveDragEvent = null; }; const leaveUpEvent = (_) => { if (!tmpLeaveDragEvent) { return; } upEvent(tmpLeaveDragEvent); clearEvent(); }; const scope = get(config).scope; const dragDom = scope ? rootRef : dragBarRef; const scopeDom = scope ? rootRef : document.body; const clearEvent = () => { scopeDom.removeEventListener("mousemove", moveEvent, false); // @ts-ignore scopeDom.removeEventListener("touchmove", moveEvent, { passive: false }); dragDom.removeEventListener("mouseup", upEvent, false); dragDom.removeEventListener("mouseenter", enterDragBlockEvent, false); dragDom.removeEventListener("mouseleave", leaveDragBlockEvent, false); dragDom.removeEventListener("touchend", upEvent, false); scopeDom.removeEventListener("mouseleave", upEvent, false); scopeDom.removeEventListener("mouseup", leaveUpEvent, false); isFreeze = false; }; isFreeze = true; scopeDom.addEventListener("mousemove", moveEvent, false); scopeDom.addEventListener("touchmove", moveEvent, { passive: false }); dragDom.addEventListener("mouseup", upEvent, false); dragDom.addEventListener("mouseenter", enterDragBlockEvent, false); dragDom.addEventListener("mouseleave", leaveDragBlockEvent, false); dragDom.addEventListener("touchend", upEvent, false); scopeDom.addEventListener("mouseleave", upEvent, false); scopeDom.addEventListener("mouseup", leaveUpEvent, false); }; const closeEvent = (e) => { close(); e.cancelBubble = true; e.preventDefault(); return false; }; const refreshEvent = (e) => { refresh(); e.cancelBubble = true; e.preventDefault(); return false; }; const resetData = () => { state.set({ dragLeft: 0, thumbLeft: get(data).thumbX || 0, thumbTop: (get(data).thumbY || 0) }); }; const clearData = () => { resetData(); clearCbs && clearCbs(); }; const close = () => { const ec = get(event); ec.close && ec.close(); resetData(); }; const refresh = () => { const ec = get(event); ec.refresh && ec.refresh(); resetData(); }; const initRefs = (root, container, tile, dragBlock, dragBar) => { rootRef = root; containerRef = container; tileRef = tile; dragBlockRef = dragBlock; dragBarRef = dragBar; }; return { state, initRefs, unsubscribe, dragEvent, closeEvent, refreshEvent, resetData, clearData, close, refresh, }; }