@embedpdf/plugin-interaction-manager 1.0.18 → 1.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/preact"),t=require("@embedpdf/plugin-interaction-manager"),n=require("preact/hooks"),o=require("preact/jsx-runtime"),r=require("@embedpdf/models"),i=()=>e.useCapability(t.InteractionManagerPlugin.id);function l(){const{provides:e}=i(),[t,o]=n.useState((()=>{const t=null==e?void 0:e.getActiveInteractionMode();return"page"===(null==t?void 0:t.scope)&&!!t.exclusive}));return n.useEffect((()=>{if(e)return e.onModeChange((()=>{const t=e.getActiveInteractionMode();o("page"===(null==t?void 0:t.scope)&&!!(null==t?void 0:t.exclusive))}))}),[e]),t}const c={pointerdown:"onPointerDown",pointerup:"onPointerUp",pointermove:"onPointerMove",pointerenter:"onPointerEnter",pointerleave:"onPointerLeave",pointercancel:"onPointerCancel",mousedown:"onMouseDown",mouseup:"onMouseUp",mousemove:"onMouseMove",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",mousecancel:"onMouseCancel",click:"onClick",dblclick:"onDoubleClick",touchstart:"onPointerDown",touchend:"onPointerUp",touchmove:"onPointerMove",touchcancel:"onPointerCancel"},s=["pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel"];function u(e,t,n,o){let r=e.getHandlersForScope(t);const i=()=>{var t;return!1!==(null==(t=e.getActiveInteractionMode())?void 0:t.wantsRawTouch)},l={};let u=i();const a=e=>{s.forEach((t=>{const o=l[t]??(l[t]=m);var r;n.addEventListener(t,o,(r=e,t.startsWith("touch")?{passive:!r}:{passive:!1}))}))},d=()=>{s.forEach((e=>{const t=l[e];t&&n.removeEventListener(e,t)}))};a(u);const p=e.onModeChange((()=>{if("global"===t.type){const t=e.getActiveInteractionMode();n.style.cursor="global"===(null==t?void 0:t.scope)?t.cursor??"auto":"auto"}r=e.getHandlersForScope(t);const o=i();o!==u&&(d(),a(o),u=o)})),g=e.onHandlerChange((()=>{r=e.getHandlersForScope(t)})),v=e.getActiveInteractionMode(),h=e.getCurrentCursor();n.style.cursor="global"===t.type&&"global"!==(null==v?void 0:v.scope)?"auto":h;const f=e.onCursorChange((o=>{var r;"global"===t.type&&"global"!==(null==(r=e.getActiveInteractionMode())?void 0:r.scope)||(n.style.cursor=o)})),y=(e,t)=>{if(o)return o(e,t);const n=t.getBoundingClientRect();return{x:e.clientX-n.left,y:e.clientY-n.top}};function m(t){var o;if(e.isPaused())return;const i=c[t.type];if(!i||!(null==r?void 0:r[i]))return;let l,s;if(t instanceof TouchEvent&&u&&("touchmove"===t.type||"touchcancel"===t.type)&&t.preventDefault(),t instanceof TouchEvent){const e="touchend"===t.type||"touchcancel"===t.type?t.changedTouches[0]:t.touches[0];if(!e)return;l=y(e,n),s={clientX:e.clientX,clientY:e.clientY,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,target:t.target,currentTarget:t.currentTarget,setPointerCapture:()=>{},releasePointerCapture:()=>{}}}else{const e=t;l=y(e,n),s={clientX:e.clientX,clientY:e.clientY,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey,target:e.target,currentTarget:e.currentTarget,setPointerCapture:()=>{var t,n;null==(n=null==(t=e.target)?void 0:t.setPointerCapture)||n.call(t,e.pointerId)},releasePointerCapture:()=>{var t,n;null==(n=null==(t=e.target)?void 0:t.releasePointerCapture)||n.call(t,e.pointerId)}}}null==(o=r[i])||o.call(r,l,s,e.getActiveMode())}return()=>{d(),p(),f(),g()}}exports.GlobalPointerProvider=({children:e,style:t,...r})=>{const l=n.useRef(null),{provides:c}=i();return n.useEffect((()=>{if(c&&l.current)return u(c,{type:"global"},l.current)}),[c]),o.jsx("div",{ref:l,style:{width:"100%",height:"100%",...t},...r,children:e})},exports.PagePointerProvider=({pageIndex:e,children:t,pageWidth:c,pageHeight:s,rotation:a,scale:d,convertEventToPoint:p,style:g,...v})=>{const h=n.useRef(null),{provides:f}=i(),y=l(),m=n.useCallback(((e,t)=>{const n=t.getBoundingClientRect(),o={x:e.clientX-n.left,y:e.clientY-n.top};return r.restorePosition({width:c,height:s},o,a,d)}),[c,s,a,d]);return n.useEffect((()=>{if(f&&h.current)return u(f,{type:"page",pageIndex:e},h.current,p||m)}),[f,e,p,m]),o.jsxs("div",{ref:h,style:{...g},...v,children:[t,y&&o.jsx("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:10}})]})},exports.useCursor=function(){const{provides:e}=i();return{setCursor:(t,n,o=0)=>{null==e||e.setCursor(t,n,o)},removeCursor:t=>{null==e||e.removeCursor(t)}}},exports.useInteractionManager=function(){const{provides:e}=i(),[o,r]=n.useState(t.initialState);return n.useEffect((()=>{if(e)return e.onStateChange((e=>{r(e)}))}),[e]),{provides:e,state:o}},exports.useInteractionManagerCapability=i,exports.useInteractionManagerPlugin=()=>e.usePlugin(t.InteractionManagerPlugin.id),exports.useIsPageExclusive=l,exports.usePointerHandlers=function({modeId:e,pageIndex:t}){const{provides:n}=i();return{register:(o,r)=>{const i=(null==r?void 0:r.modeId)??e,l=(null==r?void 0:r.pageIndex)??t;return i?null==n?void 0:n.registerHandlers({modeId:i,handlers:o,pageIndex:l}):null==n?void 0:n.registerAlways({scope:void 0!==l?{type:"page",pageIndex:l}:{type:"global"},handlers:o})}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/preact"),t=require("@embedpdf/plugin-interaction-manager"),n=require("preact/hooks"),o=require("preact/jsx-runtime"),r=require("@embedpdf/models"),i=()=>e.useCapability(t.InteractionManagerPlugin.id);function l(){const{provides:e}=i(),[t,o]=n.useState((()=>{const t=null==e?void 0:e.getActiveInteractionMode();return"page"===(null==t?void 0:t.scope)&&!!t.exclusive}));return n.useEffect((()=>{if(e)return e.onModeChange((()=>{const t=e.getActiveInteractionMode();o("page"===(null==t?void 0:t.scope)&&!!(null==t?void 0:t.exclusive))}))}),[e]),t}const c={pointerdown:"onPointerDown",pointerup:"onPointerUp",pointermove:"onPointerMove",pointerenter:"onPointerEnter",pointerleave:"onPointerLeave",pointercancel:"onPointerCancel",mousedown:"onMouseDown",mouseup:"onMouseUp",mousemove:"onMouseMove",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",mousecancel:"onMouseCancel",click:"onClick",dblclick:"onDoubleClick",touchstart:"onPointerDown",touchend:"onPointerUp",touchmove:"onPointerMove",touchcancel:"onPointerCancel"},u=["pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel"];function s(e){return"undefined"!=typeof TouchEvent&&e instanceof TouchEvent}function a(e,t,n,o){let r=e.getHandlersForScope(t);const i=()=>{var t;return!1!==(null==(t=e.getActiveInteractionMode())?void 0:t.wantsRawTouch)},l={};let a=i();const d=e=>{u.forEach((t=>{const o=l[t]??(l[t]=P);var r;n.addEventListener(t,o,(r=e,t.startsWith("touch")?{passive:!r}:{passive:!1}))}))},p=()=>{u.forEach((e=>{const t=l[e];t&&n.removeEventListener(e,t)}))};d(a);const g=e.onModeChange((()=>{if("global"===t.type){const t=e.getActiveInteractionMode();n.style.cursor="global"===(null==t?void 0:t.scope)?t.cursor??"auto":"auto"}r=e.getHandlersForScope(t);const o=i();o!==a&&(p(),d(o),a=o)})),v=e.onHandlerChange((()=>{r=e.getHandlersForScope(t)})),h=e.getActiveInteractionMode(),f=e.getCurrentCursor();n.style.cursor="global"===t.type&&"global"!==(null==h?void 0:h.scope)?"auto":f;const y=e.onCursorChange((o=>{var r;"global"===t.type&&"global"!==(null==(r=e.getActiveInteractionMode())?void 0:r.scope)||(n.style.cursor=o)})),m=(e,t)=>{if(o)return o(e,t);const n=t.getBoundingClientRect();return{x:e.clientX-n.left,y:e.clientY-n.top}};function P(t){var o;if(e.isPaused())return;const i=c[t.type];if(!i||!(null==r?void 0:r[i]))return;let l,u;if(s(t)&&a&&("touchmove"===t.type||"touchcancel"===t.type)&&t.preventDefault(),s(t)){const e="touchend"===t.type||"touchcancel"===t.type?t.changedTouches[0]:t.touches[0];if(!e)return;l=m(e,n),u={clientX:e.clientX,clientY:e.clientY,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,target:t.target,currentTarget:t.currentTarget,setPointerCapture:()=>{},releasePointerCapture:()=>{}}}else{const e=t;l=m(e,n),u={clientX:e.clientX,clientY:e.clientY,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey,target:e.target,currentTarget:e.currentTarget,setPointerCapture:()=>{var t,n;null==(n=null==(t=e.target)?void 0:t.setPointerCapture)||n.call(t,e.pointerId)},releasePointerCapture:()=>{var t,n;null==(n=null==(t=e.target)?void 0:t.releasePointerCapture)||n.call(t,e.pointerId)}}}null==(o=r[i])||o.call(r,l,u,e.getActiveMode())}return()=>{p(),g(),y(),v()}}exports.GlobalPointerProvider=({children:e,style:t,...r})=>{const l=n.useRef(null),{provides:c}=i();return n.useEffect((()=>{if(c&&l.current)return a(c,{type:"global"},l.current)}),[c]),o.jsx("div",{ref:l,style:{width:"100%",height:"100%",...t},...r,children:e})},exports.PagePointerProvider=({pageIndex:e,children:t,pageWidth:c,pageHeight:u,rotation:s,scale:d,convertEventToPoint:p,style:g,...v})=>{const h=n.useRef(null),{provides:f}=i(),y=l(),m=n.useCallback(((e,t)=>{const n=t.getBoundingClientRect(),o={x:e.clientX-n.left,y:e.clientY-n.top};return r.restorePosition({width:c,height:u},o,s,d)}),[c,u,s,d]);return n.useEffect((()=>{if(f&&h.current)return a(f,{type:"page",pageIndex:e},h.current,p||m)}),[f,e,p,m]),o.jsxs("div",{ref:h,style:{...g},...v,children:[t,y&&o.jsx("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:10}})]})},exports.useCursor=function(){const{provides:e}=i();return{setCursor:(t,n,o=0)=>{null==e||e.setCursor(t,n,o)},removeCursor:t=>{null==e||e.removeCursor(t)}}},exports.useInteractionManager=function(){const{provides:e}=i(),[o,r]=n.useState(t.initialState);return n.useEffect((()=>{if(e)return e.onStateChange((e=>{r(e)}))}),[e]),{provides:e,state:o}},exports.useInteractionManagerCapability=i,exports.useInteractionManagerPlugin=()=>e.usePlugin(t.InteractionManagerPlugin.id),exports.useIsPageExclusive=l,exports.usePointerHandlers=function({modeId:e,pageIndex:t}){const{provides:n}=i();return{register:(o,r)=>{const i=(null==r?void 0:r.modeId)??e,l=(null==r?void 0:r.pageIndex)??t;return i?null==n?void 0:n.registerHandlers({modeId:i,handlers:o,pageIndex:l}):null==n?void 0:n.registerAlways({scope:void 0!==l?{type:"page",pageIndex:l}:{type:"global"},handlers:o})}}};
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-interaction-manager.ts","../../src/shared/utils.ts","../../src/shared/components/global-pointer-provider.tsx","../../src/shared/components/page-pointer-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlers,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { useState, useEffect } from '@framework';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const [state, setState] = useState<InteractionManagerState>(initialState);\n\n useEffect(() => {\n if (!provides) return;\n return provides.onStateChange((state) => {\n setState(state);\n });\n }, [provides]);\n\n return {\n provides,\n state,\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n return finalModeId\n ? provides?.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides?.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n\n const [isPageExclusive, setIsPageExclusive] = useState<boolean>(() => {\n const m = cap?.getActiveInteractionMode();\n return m?.scope === 'page' && !!m.exclusive;\n });\n\n useEffect(() => {\n if (!cap) return;\n\n return cap.onModeChange(() => {\n const mode = cap.getActiveInteractionMode();\n setIsPageExclusive(mode?.scope === 'page' && !!mode?.exclusive);\n });\n }, [cap]);\n\n return isPageExclusive;\n}\n","import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n evt instanceof TouchEvent &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (evt instanceof TouchEvent) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { ReactNode, useEffect, useRef, HTMLAttributes, CSSProperties } from '@framework';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability } from '../hooks';\n\ninterface GlobalPointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n style?: CSSProperties;\n}\n\nexport const GlobalPointerProvider = ({\n children,\n style,\n ...props\n}: GlobalPointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(cap, { type: 'global' }, ref.current);\n }, [cap]);\n\n return (\n <div\n ref={ref}\n style={{\n width: '100%',\n height: '100%',\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n};\n","import {\n ReactNode,\n useEffect,\n useRef,\n useCallback,\n HTMLAttributes,\n CSSProperties,\n} from '@framework';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface PagePointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n style?: CSSProperties;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nexport const PagePointerProvider = ({\n pageIndex,\n children,\n pageWidth,\n pageHeight,\n rotation,\n scale,\n convertEventToPoint,\n style,\n ...props\n}: PagePointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = useIsPageExclusive();\n\n // Memoize the default conversion function\n const defaultConvertEventToPoint = useCallback(\n (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: pageWidth, height: pageHeight },\n displayPoint,\n rotation,\n scale,\n );\n },\n [pageWidth, pageHeight, rotation, scale],\n );\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(\n cap,\n { type: 'page', pageIndex },\n ref.current,\n convertEventToPoint || defaultConvertEventToPoint,\n );\n }, [cap, pageIndex, convertEventToPoint, defaultConvertEventToPoint]);\n\n return (\n <div\n ref={ref}\n style={{\n ...style,\n }}\n {...props}\n >\n {children}\n {isPageExclusive && (\n <div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }} />\n )}\n </div>\n );\n};\n"],"names":["useInteractionManagerCapability","useCapability","InteractionManagerPlugin","id","useIsPageExclusive","provides","cap","isPageExclusive","setIsPageExclusive","useState","m","getActiveInteractionMode","scope","exclusive","useEffect","onModeChange","mode","domEventMap","pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel","allEventTypes","createPointerProvider","element","convertEventToPoint","active","getHandlersForScope","wantsRawTouchNow","_a","wantsRawTouch","listeners","attachedWithRawTouch","addListeners","raw","forEach","type","fn","handleEvent","addEventListener","startsWith","passive","removeListeners","removeEventListener","stopMode","style","cursor","stopHandler","onHandlerChange","initialMode","initialCursor","getCurrentCursor","stopCursor","onCursorChange","c","toPos","e","host","r","getBoundingClientRect","x","clientX","left","y","clientY","top","evt","isPaused","handlerKey","pos","normEvt","TouchEvent","preventDefault","tp","changedTouches","touches","ctrlKey","shiftKey","altKey","metaKey","target","currentTarget","setPointerCapture","releasePointerCapture","pe","_b","call","pointerId","getActiveMode","children","props","ref","useRef","current","jsxRuntime","jsx","width","height","pageIndex","pageWidth","pageHeight","rotation","scale","defaultConvertEventToPoint","useCallback","event","rect","displayPoint","restorePosition","jsxs","position","right","bottom","zIndex","setCursor","token","prio","removeCursor","state","setState","initialState","onStateChange","usePlugin","modeId","register","handlers","options","finalModeId","finalPageIndex","registerHandlers","registerAlways"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-interaction-manager.ts","../../src/shared/utils.ts","../../src/shared/components/global-pointer-provider.tsx","../../src/shared/components/page-pointer-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlers,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { useState, useEffect } from '@framework';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const [state, setState] = useState<InteractionManagerState>(initialState);\n\n useEffect(() => {\n if (!provides) return;\n return provides.onStateChange((state) => {\n setState(state);\n });\n }, [provides]);\n\n return {\n provides,\n state,\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n return finalModeId\n ? provides?.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides?.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n\n const [isPageExclusive, setIsPageExclusive] = useState<boolean>(() => {\n const m = cap?.getActiveInteractionMode();\n return m?.scope === 'page' && !!m.exclusive;\n });\n\n useEffect(() => {\n if (!cap) return;\n\n return cap.onModeChange(() => {\n const mode = cap.getActiveInteractionMode();\n setIsPageExclusive(mode?.scope === 'page' && !!mode?.exclusive);\n });\n }, [cap]);\n\n return isPageExclusive;\n}\n","import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\nfunction isTouchEvent(evt: Event): evt is TouchEvent {\n return typeof TouchEvent !== 'undefined' && evt instanceof TouchEvent;\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n isTouchEvent(evt) &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (isTouchEvent(evt)) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { ReactNode, useEffect, useRef, HTMLAttributes, CSSProperties } from '@framework';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability } from '../hooks';\n\ninterface GlobalPointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n style?: CSSProperties;\n}\n\nexport const GlobalPointerProvider = ({\n children,\n style,\n ...props\n}: GlobalPointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(cap, { type: 'global' }, ref.current);\n }, [cap]);\n\n return (\n <div\n ref={ref}\n style={{\n width: '100%',\n height: '100%',\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n};\n","import {\n ReactNode,\n useEffect,\n useRef,\n useCallback,\n HTMLAttributes,\n CSSProperties,\n} from '@framework';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface PagePointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n style?: CSSProperties;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nexport const PagePointerProvider = ({\n pageIndex,\n children,\n pageWidth,\n pageHeight,\n rotation,\n scale,\n convertEventToPoint,\n style,\n ...props\n}: PagePointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = useIsPageExclusive();\n\n // Memoize the default conversion function\n const defaultConvertEventToPoint = useCallback(\n (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: pageWidth, height: pageHeight },\n displayPoint,\n rotation,\n scale,\n );\n },\n [pageWidth, pageHeight, rotation, scale],\n );\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(\n cap,\n { type: 'page', pageIndex },\n ref.current,\n convertEventToPoint || defaultConvertEventToPoint,\n );\n }, [cap, pageIndex, convertEventToPoint, defaultConvertEventToPoint]);\n\n return (\n <div\n ref={ref}\n style={{\n ...style,\n }}\n {...props}\n >\n {children}\n {isPageExclusive && (\n <div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }} />\n )}\n </div>\n );\n};\n"],"names":["useInteractionManagerCapability","useCapability","InteractionManagerPlugin","id","useIsPageExclusive","provides","cap","isPageExclusive","setIsPageExclusive","useState","m","getActiveInteractionMode","scope","exclusive","useEffect","onModeChange","mode","domEventMap","pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel","allEventTypes","isTouchEvent","evt","TouchEvent","createPointerProvider","element","convertEventToPoint","active","getHandlersForScope","wantsRawTouchNow","_a","wantsRawTouch","listeners","attachedWithRawTouch","addListeners","raw","forEach","type","fn","handleEvent","addEventListener","startsWith","passive","removeListeners","removeEventListener","stopMode","style","cursor","stopHandler","onHandlerChange","initialMode","initialCursor","getCurrentCursor","stopCursor","onCursorChange","c","toPos","e","host","r","getBoundingClientRect","x","clientX","left","y","clientY","top","isPaused","handlerKey","pos","normEvt","preventDefault","tp","changedTouches","touches","ctrlKey","shiftKey","altKey","metaKey","target","currentTarget","setPointerCapture","releasePointerCapture","pe","_b","call","pointerId","getActiveMode","children","props","ref","useRef","current","jsxRuntime","jsx","width","height","pageIndex","pageWidth","pageHeight","rotation","scale","defaultConvertEventToPoint","useCallback","event","rect","displayPoint","restorePosition","jsxs","position","right","bottom","zIndex","setCursor","token","prio","removeCursor","state","setState","initialState","onStateChange","usePlugin","modeId","register","handlers","options","finalModeId","finalPageIndex","registerHandlers","registerAlways"],"mappings":"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"}
@@ -104,6 +104,9 @@ const allEventTypes = [...pointerEventTypes, ...touchEventTypes];
104
104
  function listenerOpts(eventType, wantsRawTouch) {
105
105
  return eventType.startsWith("touch") ? { passive: !wantsRawTouch } : { passive: false };
106
106
  }
107
+ function isTouchEvent(evt) {
108
+ return typeof TouchEvent !== "undefined" && evt instanceof TouchEvent;
109
+ }
107
110
  function createPointerProvider(cap, scope, element, convertEventToPoint) {
108
111
  let active = cap.getHandlersForScope(scope);
109
112
  const wantsRawTouchNow = () => {
@@ -159,12 +162,12 @@ function createPointerProvider(cap, scope, element, convertEventToPoint) {
159
162
  if (cap.isPaused()) return;
160
163
  const handlerKey = domEventMap[evt.type];
161
164
  if (!handlerKey || !(active == null ? void 0 : active[handlerKey])) return;
162
- if (evt instanceof TouchEvent && attachedWithRawTouch && (evt.type === "touchmove" || evt.type === "touchcancel")) {
165
+ if (isTouchEvent(evt) && attachedWithRawTouch && (evt.type === "touchmove" || evt.type === "touchcancel")) {
163
166
  evt.preventDefault();
164
167
  }
165
168
  let pos;
166
169
  let normEvt;
167
- if (evt instanceof TouchEvent) {
170
+ if (isTouchEvent(evt)) {
168
171
  const tp = evt.type === "touchend" || evt.type === "touchcancel" ? evt.changedTouches[0] : evt.touches[0];
169
172
  if (!tp) return;
170
173
  pos = toPos(tp, element);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-interaction-manager.ts","../../src/shared/utils.ts","../../src/shared/components/global-pointer-provider.tsx","../../src/shared/components/page-pointer-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlers,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { useState, useEffect } from '@framework';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const [state, setState] = useState<InteractionManagerState>(initialState);\n\n useEffect(() => {\n if (!provides) return;\n return provides.onStateChange((state) => {\n setState(state);\n });\n }, [provides]);\n\n return {\n provides,\n state,\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n return finalModeId\n ? provides?.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides?.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n\n const [isPageExclusive, setIsPageExclusive] = useState<boolean>(() => {\n const m = cap?.getActiveInteractionMode();\n return m?.scope === 'page' && !!m.exclusive;\n });\n\n useEffect(() => {\n if (!cap) return;\n\n return cap.onModeChange(() => {\n const mode = cap.getActiveInteractionMode();\n setIsPageExclusive(mode?.scope === 'page' && !!mode?.exclusive);\n });\n }, [cap]);\n\n return isPageExclusive;\n}\n","import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n evt instanceof TouchEvent &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (evt instanceof TouchEvent) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { ReactNode, useEffect, useRef, HTMLAttributes, CSSProperties } from '@framework';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability } from '../hooks';\n\ninterface GlobalPointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n style?: CSSProperties;\n}\n\nexport const GlobalPointerProvider = ({\n children,\n style,\n ...props\n}: GlobalPointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(cap, { type: 'global' }, ref.current);\n }, [cap]);\n\n return (\n <div\n ref={ref}\n style={{\n width: '100%',\n height: '100%',\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n};\n","import {\n ReactNode,\n useEffect,\n useRef,\n useCallback,\n HTMLAttributes,\n CSSProperties,\n} from '@framework';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface PagePointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n style?: CSSProperties;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nexport const PagePointerProvider = ({\n pageIndex,\n children,\n pageWidth,\n pageHeight,\n rotation,\n scale,\n convertEventToPoint,\n style,\n ...props\n}: PagePointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = useIsPageExclusive();\n\n // Memoize the default conversion function\n const defaultConvertEventToPoint = useCallback(\n (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: pageWidth, height: pageHeight },\n displayPoint,\n rotation,\n scale,\n );\n },\n [pageWidth, pageHeight, rotation, scale],\n );\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(\n cap,\n { type: 'page', pageIndex },\n ref.current,\n convertEventToPoint || defaultConvertEventToPoint,\n );\n }, [cap, pageIndex, convertEventToPoint, defaultConvertEventToPoint]);\n\n return (\n <div\n ref={ref}\n style={{\n ...style,\n }}\n {...props}\n >\n {children}\n {isPageExclusive && (\n <div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }} />\n )}\n </div>\n );\n};\n"],"names":["state","_a"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-interaction-manager.ts","../../src/shared/utils.ts","../../src/shared/components/global-pointer-provider.tsx","../../src/shared/components/page-pointer-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlers,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { useState, useEffect } from '@framework';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const [state, setState] = useState<InteractionManagerState>(initialState);\n\n useEffect(() => {\n if (!provides) return;\n return provides.onStateChange((state) => {\n setState(state);\n });\n }, [provides]);\n\n return {\n provides,\n state,\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n return finalModeId\n ? provides?.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides?.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n\n const [isPageExclusive, setIsPageExclusive] = useState<boolean>(() => {\n const m = cap?.getActiveInteractionMode();\n return m?.scope === 'page' && !!m.exclusive;\n });\n\n useEffect(() => {\n if (!cap) return;\n\n return cap.onModeChange(() => {\n const mode = cap.getActiveInteractionMode();\n setIsPageExclusive(mode?.scope === 'page' && !!mode?.exclusive);\n });\n }, [cap]);\n\n return isPageExclusive;\n}\n","import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\nfunction isTouchEvent(evt: Event): evt is TouchEvent {\n return typeof TouchEvent !== 'undefined' && evt instanceof TouchEvent;\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n isTouchEvent(evt) &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (isTouchEvent(evt)) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { ReactNode, useEffect, useRef, HTMLAttributes, CSSProperties } from '@framework';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability } from '../hooks';\n\ninterface GlobalPointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n style?: CSSProperties;\n}\n\nexport const GlobalPointerProvider = ({\n children,\n style,\n ...props\n}: GlobalPointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(cap, { type: 'global' }, ref.current);\n }, [cap]);\n\n return (\n <div\n ref={ref}\n style={{\n width: '100%',\n height: '100%',\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n};\n","import {\n ReactNode,\n useEffect,\n useRef,\n useCallback,\n HTMLAttributes,\n CSSProperties,\n} from '@framework';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface PagePointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n style?: CSSProperties;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nexport const PagePointerProvider = ({\n pageIndex,\n children,\n pageWidth,\n pageHeight,\n rotation,\n scale,\n convertEventToPoint,\n style,\n ...props\n}: PagePointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = useIsPageExclusive();\n\n // Memoize the default conversion function\n const defaultConvertEventToPoint = useCallback(\n (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: pageWidth, height: pageHeight },\n displayPoint,\n rotation,\n scale,\n );\n },\n [pageWidth, pageHeight, rotation, scale],\n );\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(\n cap,\n { type: 'page', pageIndex },\n ref.current,\n convertEventToPoint || defaultConvertEventToPoint,\n );\n }, [cap, pageIndex, convertEventToPoint, defaultConvertEventToPoint]);\n\n return (\n <div\n ref={ref}\n style={{\n ...style,\n }}\n {...props}\n >\n {children}\n {isPageExclusive && (\n <div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }} />\n )}\n </div>\n );\n};\n"],"names":["state","_a"],"mappings":";;;;;AAUO,MAAM,8BAA8B,MACzC,UAAoC,yBAAyB,EAAE;AAC1D,MAAM,kCAAkC,MAC7C,cAAwC,yBAAyB,EAAE;AAE9D,SAAS,wBAAwB;AAChC,QAAA,EAAE,SAAS,IAAI,gCAAgC;AACrD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAkC,YAAY;AAExE,YAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACR,WAAA,SAAS,cAAc,CAACA,WAAU;AACvC,eAASA,MAAK;AAAA,IAAA,CACf;AAAA,EAAA,GACA,CAAC,QAAQ,CAAC;AAEN,SAAA;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,YAAY;AACpB,QAAA,EAAE,SAAS,IAAI,gCAAgC;AAC9C,SAAA;AAAA,IACL,WAAW,CAAC,OAAe,QAAgB,OAAO,MAAM;AAC5C,2CAAA,UAAU,OAAO,QAAQ;AAAA,IACrC;AAAA,IACA,cAAc,CAAC,UAAkB;AAC/B,2CAAU,aAAa;AAAA,IAAK;AAAA,EAEhC;AACF;AAOO,SAAS,mBAAmB,EAAE,QAAQ,aAAwC;AAC7E,QAAA,EAAE,SAAS,IAAI,gCAAgC;AAC9C,SAAA;AAAA,IACL,UAAU,CACR,UACA,YACG;AAEG,YAAA,eAAc,mCAAS,WAAU;AACjC,YAAA,kBAAiB,mCAAS,cAAa;AAEtC,aAAA,cACH,qCAAU,iBAAiB;AAAA,QACzB,QAAQ;AAAA,QACR;AAAA,QACA,WAAW;AAAA,MAAA,KAEb,qCAAU,eAAe;AAAA,QACvB,OACE,mBAAmB,SACf,EAAE,MAAM,QAAQ,WAAW,eAAe,IAC1C,EAAE,MAAM,SAAS;AAAA,QACvB;AAAA,MAAA;AAAA,IACD;AAAA,EAET;AACF;AAEO,SAAS,qBAAqB;AACnC,QAAM,EAAE,UAAU,IAAI,IAAI,gCAAgC;AAE1D,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAkB,MAAM;AAC9D,UAAA,IAAI,2BAAK;AACf,YAAO,uBAAG,WAAU,UAAU,CAAC,CAAC,EAAE;AAAA,EAAA,CACnC;AAED,YAAU,MAAM;AACd,QAAI,CAAC,IAAK;AAEH,WAAA,IAAI,aAAa,MAAM;AACtB,YAAA,OAAO,IAAI,yBAAyB;AAC1C,0BAAmB,6BAAM,WAAU,UAAU,CAAC,EAAC,6BAAM,UAAS;AAAA,IAAA,CAC/D;AAAA,EAAA,GACA,CAAC,GAAG,CAAC;AAED,SAAA;AACT;ACnFA,MAAM,cAAiC;AAAA,EACrC,aAAa;AAAA,EACb,WAAW;AAAA,EACX,aAAa;AAAA,EACb,cAAc;AAAA,EACd,cAAc;AAAA,EACd,eAAe;AAAA,EAEf,WAAW;AAAA,EACX,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EAEb,OAAO;AAAA,EACP,UAAU;AAAA;AAAA,EAGV,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AAAA,EACX,aAAa;AACf;AAEA,MAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,kBAAkB,CAAC,cAAc,YAAY,aAAa,aAAa;AAC7E,MAAM,gBAAgB,CAAC,GAAG,mBAAmB,GAAG,eAAe;AAK/D,SAAS,aAAa,WAAmB,eAAiD;AAEjF,SAAA,UAAU,WAAW,OAAO,IAAI,EAAE,SAAS,CAAC,cAAc,IAAI,EAAE,SAAS,MAAM;AACxF;AAEA,SAAS,aAAa,KAA+B;AAC5C,SAAA,OAAO,eAAe,eAAe,eAAe;AAC7D;AAKO,SAAS,sBACd,KACA,OACA,SACA,qBACA;AAEI,MAAA,SAAsC,IAAI,oBAAoB,KAAK;AAGvE,QAAM,mBAAmB,MAAM;;AAAA,sBAAI,+BAAJ,mBAAgC,mBAAkB;AAAA;AAGjF,QAAM,YAAkD,CAAC;AACzD,MAAI,uBAAuB,iBAAiB;AAEtC,QAAA,eAAe,CAAC,QAAiB;AACvB,kBAAA,QAAQ,CAAC,SAAS;AACxB,YAAA,KAAM,sCAAoB;AAChC,cAAQ,iBAAiB,MAAM,IAAI,aAAa,MAAM,GAAG,CAAC;AAAA,IAAA,CAC3D;AAAA,EACH;AACA,QAAM,kBAAkB,MAAM;AACd,kBAAA,QAAQ,CAAC,SAAS;AACxB,YAAA,KAAK,UAAU,IAAI;AACzB,UAAI,GAAI,SAAQ,oBAAoB,MAAM,EAAE;AAAA,IAAA,CAC7C;AAAA,EACH;AAGA,eAAa,oBAAoB;AAG3B,QAAA,WAAW,IAAI,aAAa,MAAM;AAElC,QAAA,MAAM,SAAS,UAAU;AACrB,YAAA,OAAO,IAAI,yBAAyB;AAC1C,cAAQ,MAAM,UAAS,6BAAM,WAAU,WAAY,KAAK,UAAU,SAAU;AAAA,IAAA;AAGrE,aAAA,IAAI,oBAAoB,KAAK;AAGtC,UAAM,MAAM,iBAAiB;AAC7B,QAAI,QAAQ,sBAAsB;AAChB,sBAAA;AAChB,mBAAa,GAAG;AACO,6BAAA;AAAA,IAAA;AAAA,EACzB,CACD;AAEK,QAAA,cAAc,IAAI,gBAAgB,MAAM;AACnC,aAAA,IAAI,oBAAoB,KAAK;AAAA,EAAA,CACvC;AAGK,QAAA,cAAc,IAAI,yBAAyB;AAC3C,QAAA,gBAAgB,IAAI,iBAAiB;AACnC,UAAA,MAAM,SACZ,MAAM,SAAS,aAAY,2CAAa,WAAU,WAAW,SAAS;AAExE,QAAM,aAAa,IAAI,eAAe,CAAC,MAAM;;AAC3C,QAAI,MAAM,SAAS,cAAY,SAAI,yBAAyB,MAA7B,mBAAgC,WAAU,SAAU;AACnF,YAAQ,MAAM,SAAS;AAAA,EAAA,CACxB;AAGK,QAAA,QAAQ,CAAC,GAAyC,SAAgC;AACtF,QAAI,oBAAqB,QAAO,oBAAoB,GAAmB,IAAI;AACrE,UAAA,IAAI,KAAK,sBAAsB;AAC9B,WAAA,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,EAAE,UAAU,EAAE,IAAI;AAAA,EACvD;AAGA,WAAS,YAAY,KAAY;;AAC3B,QAAA,IAAI,WAAY;AAEd,UAAA,aAAa,YAAY,IAAI,IAAI;AACvC,QAAI,CAAC,cAAc,EAAC,iCAAS,aAAa;AAIxC,QAAA,aAAa,GAAG,KAChB,yBACC,IAAI,SAAS,eAAe,IAAI,SAAS,gBAC1C;AACA,UAAI,eAAe;AAAA,IAAA;AAIjB,QAAA;AACA,QAAA;AAKA,QAAA,aAAa,GAAG,GAAG;AACrB,YAAM,KACJ,IAAI,SAAS,cAAc,IAAI,SAAS,gBACpC,IAAI,eAAe,CAAC,IACpB,IAAI,QAAQ,CAAC;AACnB,UAAI,CAAC,GAAI;AAEH,YAAA,MAAM,IAAI,OAAO;AACb,gBAAA;AAAA,QACR,SAAS,GAAG;AAAA,QACZ,SAAS,GAAG;AAAA,QACZ,SAAS,IAAI;AAAA,QACb,UAAU,IAAI;AAAA,QACd,QAAQ,IAAI;AAAA,QACZ,SAAS,IAAI;AAAA,QACb,QAAQ,IAAI;AAAA,QACZ,eAAe,IAAI;AAAA,QACnB,mBAAmB,MAAM;AAAA,QAAC;AAAA,QAC1B,uBAAuB,MAAM;AAAA,QAAA;AAAA,MAC/B;AAAA,IAAA,OACK;AACL,YAAM,KAAK;AACL,YAAA,MAAM,IAAI,OAAO;AACb,gBAAA;AAAA,QACR,SAAS,GAAG;AAAA,QACZ,SAAS,GAAG;AAAA,QACZ,SAAS,GAAG;AAAA,QACZ,UAAU,GAAG;AAAA,QACb,QAAQ,GAAG;AAAA,QACX,SAAS,GAAG;AAAA,QACZ,QAAQ,GAAG;AAAA,QACX,eAAe,GAAG;AAAA,QAClB,mBAAmB,MAAM;;AACtB,iBAAAC,MAAA,GAAG,WAAH,gBAAAA,IAA2B,sBAA3B,wBAAAA,KAA+C,GAAG;AAAA,QACrD;AAAA,QACA,uBAAuB,MAAM;;AAC1B,iBAAAA,MAAA,GAAG,WAAH,gBAAAA,IAA2B,0BAA3B,wBAAAA,KAAmD,GAAG;AAAA,QAAS;AAAA,MAEpE;AAAA,IAAA;AAGF,iBAAO,gBAAP,gCAAqB,KAAK,SAAS,IAAI;EAAe;AAIxD,SAAO,MAAM;AACK,oBAAA;AACP,aAAA;AACE,eAAA;AACC,gBAAA;AAAA,EACd;AACF;ACjNO,MAAM,wBAAwB,CAAC;AAAA,EACpC;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAkC;AAC1B,QAAA,MAAM,OAAuB,IAAI;AACvC,QAAM,EAAE,UAAU,IAAI,IAAI,gCAAgC;AAE1D,YAAU,MAAM;AACd,QAAI,CAAC,OAAO,CAAC,IAAI,QAAS;AAE1B,WAAO,sBAAsB,KAAK,EAAE,MAAM,SAAS,GAAG,IAAI,OAAO;AAAA,EAAA,GAChE,CAAC,GAAG,CAAC;AAGN,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,GAAG;AAAA,MACL;AAAA,MACC,GAAG;AAAA,MAEH;AAAA,IAAA;AAAA,EACH;AAEJ;ACbO,MAAM,sBAAsB,CAAC;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAgC;AACxB,QAAA,MAAM,OAAuB,IAAI;AACvC,QAAM,EAAE,UAAU,IAAI,IAAI,gCAAgC;AAC1D,QAAM,kBAAkB,mBAAmB;AAG3C,QAAM,6BAA6B;AAAA,IACjC,CAAC,OAAqB,YAAmC;AACjD,YAAA,OAAO,QAAQ,sBAAsB;AAC3C,YAAM,eAAe;AAAA,QACnB,GAAG,MAAM,UAAU,KAAK;AAAA,QACxB,GAAG,MAAM,UAAU,KAAK;AAAA,MAC1B;AACO,aAAA;AAAA,QACL,EAAE,OAAO,WAAW,QAAQ,WAAW;AAAA,QACvC;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,WAAW,YAAY,UAAU,KAAK;AAAA,EACzC;AAEA,YAAU,MAAM;AACd,QAAI,CAAC,OAAO,CAAC,IAAI,QAAS;AAEnB,WAAA;AAAA,MACL;AAAA,MACA,EAAE,MAAM,QAAQ,UAAU;AAAA,MAC1B,IAAI;AAAA,MACJ,uBAAuB;AAAA,IACzB;AAAA,KACC,CAAC,KAAK,WAAW,qBAAqB,0BAA0B,CAAC;AAGlE,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,GAAG;AAAA,MACL;AAAA,MACC,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA;AAAA,QACA,mBACE,oBAAA,OAAA,EAAI,OAAO,EAAE,UAAU,YAAY,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,KAAM,CAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAE5F;AAEJ;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/react"),t=require("@embedpdf/plugin-interaction-manager"),n=require("react"),o=require("react/jsx-runtime"),r=require("@embedpdf/models"),i=()=>e.useCapability(t.InteractionManagerPlugin.id);function l(){const{provides:e}=i(),[t,o]=n.useState((()=>{const t=null==e?void 0:e.getActiveInteractionMode();return"page"===(null==t?void 0:t.scope)&&!!t.exclusive}));return n.useEffect((()=>{if(e)return e.onModeChange((()=>{const t=e.getActiveInteractionMode();o("page"===(null==t?void 0:t.scope)&&!!(null==t?void 0:t.exclusive))}))}),[e]),t}const c={pointerdown:"onPointerDown",pointerup:"onPointerUp",pointermove:"onPointerMove",pointerenter:"onPointerEnter",pointerleave:"onPointerLeave",pointercancel:"onPointerCancel",mousedown:"onMouseDown",mouseup:"onMouseUp",mousemove:"onMouseMove",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",mousecancel:"onMouseCancel",click:"onClick",dblclick:"onDoubleClick",touchstart:"onPointerDown",touchend:"onPointerUp",touchmove:"onPointerMove",touchcancel:"onPointerCancel"},s=["pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel"];function u(e,t,n,o){let r=e.getHandlersForScope(t);const i=()=>{var t;return!1!==(null==(t=e.getActiveInteractionMode())?void 0:t.wantsRawTouch)},l={};let u=i();const a=e=>{s.forEach((t=>{const o=l[t]??(l[t]=m);var r;n.addEventListener(t,o,(r=e,t.startsWith("touch")?{passive:!r}:{passive:!1}))}))},d=()=>{s.forEach((e=>{const t=l[e];t&&n.removeEventListener(e,t)}))};a(u);const p=e.onModeChange((()=>{if("global"===t.type){const t=e.getActiveInteractionMode();n.style.cursor="global"===(null==t?void 0:t.scope)?t.cursor??"auto":"auto"}r=e.getHandlersForScope(t);const o=i();o!==u&&(d(),a(o),u=o)})),g=e.onHandlerChange((()=>{r=e.getHandlersForScope(t)})),v=e.getActiveInteractionMode(),h=e.getCurrentCursor();n.style.cursor="global"===t.type&&"global"!==(null==v?void 0:v.scope)?"auto":h;const f=e.onCursorChange((o=>{var r;"global"===t.type&&"global"!==(null==(r=e.getActiveInteractionMode())?void 0:r.scope)||(n.style.cursor=o)})),y=(e,t)=>{if(o)return o(e,t);const n=t.getBoundingClientRect();return{x:e.clientX-n.left,y:e.clientY-n.top}};function m(t){var o;if(e.isPaused())return;const i=c[t.type];if(!i||!(null==r?void 0:r[i]))return;let l,s;if(t instanceof TouchEvent&&u&&("touchmove"===t.type||"touchcancel"===t.type)&&t.preventDefault(),t instanceof TouchEvent){const e="touchend"===t.type||"touchcancel"===t.type?t.changedTouches[0]:t.touches[0];if(!e)return;l=y(e,n),s={clientX:e.clientX,clientY:e.clientY,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,target:t.target,currentTarget:t.currentTarget,setPointerCapture:()=>{},releasePointerCapture:()=>{}}}else{const e=t;l=y(e,n),s={clientX:e.clientX,clientY:e.clientY,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey,target:e.target,currentTarget:e.currentTarget,setPointerCapture:()=>{var t,n;null==(n=null==(t=e.target)?void 0:t.setPointerCapture)||n.call(t,e.pointerId)},releasePointerCapture:()=>{var t,n;null==(n=null==(t=e.target)?void 0:t.releasePointerCapture)||n.call(t,e.pointerId)}}}null==(o=r[i])||o.call(r,l,s,e.getActiveMode())}return()=>{d(),p(),f(),g()}}exports.GlobalPointerProvider=({children:e,style:t,...r})=>{const l=n.useRef(null),{provides:c}=i();return n.useEffect((()=>{if(c&&l.current)return u(c,{type:"global"},l.current)}),[c]),o.jsx("div",{ref:l,style:{width:"100%",height:"100%",...t},...r,children:e})},exports.PagePointerProvider=({pageIndex:e,children:t,pageWidth:c,pageHeight:s,rotation:a,scale:d,convertEventToPoint:p,style:g,...v})=>{const h=n.useRef(null),{provides:f}=i(),y=l(),m=n.useCallback(((e,t)=>{const n=t.getBoundingClientRect(),o={x:e.clientX-n.left,y:e.clientY-n.top};return r.restorePosition({width:c,height:s},o,a,d)}),[c,s,a,d]);return n.useEffect((()=>{if(f&&h.current)return u(f,{type:"page",pageIndex:e},h.current,p||m)}),[f,e,p,m]),o.jsxs("div",{ref:h,style:{...g},...v,children:[t,y&&o.jsx("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:10}})]})},exports.useCursor=function(){const{provides:e}=i();return{setCursor:(t,n,o=0)=>{null==e||e.setCursor(t,n,o)},removeCursor:t=>{null==e||e.removeCursor(t)}}},exports.useInteractionManager=function(){const{provides:e}=i(),[o,r]=n.useState(t.initialState);return n.useEffect((()=>{if(e)return e.onStateChange((e=>{r(e)}))}),[e]),{provides:e,state:o}},exports.useInteractionManagerCapability=i,exports.useInteractionManagerPlugin=()=>e.usePlugin(t.InteractionManagerPlugin.id),exports.useIsPageExclusive=l,exports.usePointerHandlers=function({modeId:e,pageIndex:t}){const{provides:n}=i();return{register:(o,r)=>{const i=(null==r?void 0:r.modeId)??e,l=(null==r?void 0:r.pageIndex)??t;return i?null==n?void 0:n.registerHandlers({modeId:i,handlers:o,pageIndex:l}):null==n?void 0:n.registerAlways({scope:void 0!==l?{type:"page",pageIndex:l}:{type:"global"},handlers:o})}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/react"),t=require("@embedpdf/plugin-interaction-manager"),n=require("react"),o=require("react/jsx-runtime"),r=require("@embedpdf/models"),i=()=>e.useCapability(t.InteractionManagerPlugin.id);function l(){const{provides:e}=i(),[t,o]=n.useState((()=>{const t=null==e?void 0:e.getActiveInteractionMode();return"page"===(null==t?void 0:t.scope)&&!!t.exclusive}));return n.useEffect((()=>{if(e)return e.onModeChange((()=>{const t=e.getActiveInteractionMode();o("page"===(null==t?void 0:t.scope)&&!!(null==t?void 0:t.exclusive))}))}),[e]),t}const c={pointerdown:"onPointerDown",pointerup:"onPointerUp",pointermove:"onPointerMove",pointerenter:"onPointerEnter",pointerleave:"onPointerLeave",pointercancel:"onPointerCancel",mousedown:"onMouseDown",mouseup:"onMouseUp",mousemove:"onMouseMove",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",mousecancel:"onMouseCancel",click:"onClick",dblclick:"onDoubleClick",touchstart:"onPointerDown",touchend:"onPointerUp",touchmove:"onPointerMove",touchcancel:"onPointerCancel"},u=["pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel"];function s(e){return"undefined"!=typeof TouchEvent&&e instanceof TouchEvent}function a(e,t,n,o){let r=e.getHandlersForScope(t);const i=()=>{var t;return!1!==(null==(t=e.getActiveInteractionMode())?void 0:t.wantsRawTouch)},l={};let a=i();const d=e=>{u.forEach((t=>{const o=l[t]??(l[t]=P);var r;n.addEventListener(t,o,(r=e,t.startsWith("touch")?{passive:!r}:{passive:!1}))}))},p=()=>{u.forEach((e=>{const t=l[e];t&&n.removeEventListener(e,t)}))};d(a);const g=e.onModeChange((()=>{if("global"===t.type){const t=e.getActiveInteractionMode();n.style.cursor="global"===(null==t?void 0:t.scope)?t.cursor??"auto":"auto"}r=e.getHandlersForScope(t);const o=i();o!==a&&(p(),d(o),a=o)})),v=e.onHandlerChange((()=>{r=e.getHandlersForScope(t)})),f=e.getActiveInteractionMode(),h=e.getCurrentCursor();n.style.cursor="global"===t.type&&"global"!==(null==f?void 0:f.scope)?"auto":h;const y=e.onCursorChange((o=>{var r;"global"===t.type&&"global"!==(null==(r=e.getActiveInteractionMode())?void 0:r.scope)||(n.style.cursor=o)})),m=(e,t)=>{if(o)return o(e,t);const n=t.getBoundingClientRect();return{x:e.clientX-n.left,y:e.clientY-n.top}};function P(t){var o;if(e.isPaused())return;const i=c[t.type];if(!i||!(null==r?void 0:r[i]))return;let l,u;if(s(t)&&a&&("touchmove"===t.type||"touchcancel"===t.type)&&t.preventDefault(),s(t)){const e="touchend"===t.type||"touchcancel"===t.type?t.changedTouches[0]:t.touches[0];if(!e)return;l=m(e,n),u={clientX:e.clientX,clientY:e.clientY,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,target:t.target,currentTarget:t.currentTarget,setPointerCapture:()=>{},releasePointerCapture:()=>{}}}else{const e=t;l=m(e,n),u={clientX:e.clientX,clientY:e.clientY,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey,target:e.target,currentTarget:e.currentTarget,setPointerCapture:()=>{var t,n;null==(n=null==(t=e.target)?void 0:t.setPointerCapture)||n.call(t,e.pointerId)},releasePointerCapture:()=>{var t,n;null==(n=null==(t=e.target)?void 0:t.releasePointerCapture)||n.call(t,e.pointerId)}}}null==(o=r[i])||o.call(r,l,u,e.getActiveMode())}return()=>{p(),g(),y(),v()}}exports.GlobalPointerProvider=({children:e,style:t,...r})=>{const l=n.useRef(null),{provides:c}=i();return n.useEffect((()=>{if(c&&l.current)return a(c,{type:"global"},l.current)}),[c]),o.jsx("div",{ref:l,style:{width:"100%",height:"100%",...t},...r,children:e})},exports.PagePointerProvider=({pageIndex:e,children:t,pageWidth:c,pageHeight:u,rotation:s,scale:d,convertEventToPoint:p,style:g,...v})=>{const f=n.useRef(null),{provides:h}=i(),y=l(),m=n.useCallback(((e,t)=>{const n=t.getBoundingClientRect(),o={x:e.clientX-n.left,y:e.clientY-n.top};return r.restorePosition({width:c,height:u},o,s,d)}),[c,u,s,d]);return n.useEffect((()=>{if(h&&f.current)return a(h,{type:"page",pageIndex:e},f.current,p||m)}),[h,e,p,m]),o.jsxs("div",{ref:f,style:{...g},...v,children:[t,y&&o.jsx("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:10}})]})},exports.useCursor=function(){const{provides:e}=i();return{setCursor:(t,n,o=0)=>{null==e||e.setCursor(t,n,o)},removeCursor:t=>{null==e||e.removeCursor(t)}}},exports.useInteractionManager=function(){const{provides:e}=i(),[o,r]=n.useState(t.initialState);return n.useEffect((()=>{if(e)return e.onStateChange((e=>{r(e)}))}),[e]),{provides:e,state:o}},exports.useInteractionManagerCapability=i,exports.useInteractionManagerPlugin=()=>e.usePlugin(t.InteractionManagerPlugin.id),exports.useIsPageExclusive=l,exports.usePointerHandlers=function({modeId:e,pageIndex:t}){const{provides:n}=i();return{register:(o,r)=>{const i=(null==r?void 0:r.modeId)??e,l=(null==r?void 0:r.pageIndex)??t;return i?null==n?void 0:n.registerHandlers({modeId:i,handlers:o,pageIndex:l}):null==n?void 0:n.registerAlways({scope:void 0!==l?{type:"page",pageIndex:l}:{type:"global"},handlers:o})}}};
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-interaction-manager.ts","../../src/shared/utils.ts","../../src/shared/components/global-pointer-provider.tsx","../../src/shared/components/page-pointer-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlers,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { useState, useEffect } from '@framework';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const [state, setState] = useState<InteractionManagerState>(initialState);\n\n useEffect(() => {\n if (!provides) return;\n return provides.onStateChange((state) => {\n setState(state);\n });\n }, [provides]);\n\n return {\n provides,\n state,\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n return finalModeId\n ? provides?.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides?.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n\n const [isPageExclusive, setIsPageExclusive] = useState<boolean>(() => {\n const m = cap?.getActiveInteractionMode();\n return m?.scope === 'page' && !!m.exclusive;\n });\n\n useEffect(() => {\n if (!cap) return;\n\n return cap.onModeChange(() => {\n const mode = cap.getActiveInteractionMode();\n setIsPageExclusive(mode?.scope === 'page' && !!mode?.exclusive);\n });\n }, [cap]);\n\n return isPageExclusive;\n}\n","import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n evt instanceof TouchEvent &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (evt instanceof TouchEvent) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { ReactNode, useEffect, useRef, HTMLAttributes, CSSProperties } from '@framework';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability } from '../hooks';\n\ninterface GlobalPointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n style?: CSSProperties;\n}\n\nexport const GlobalPointerProvider = ({\n children,\n style,\n ...props\n}: GlobalPointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(cap, { type: 'global' }, ref.current);\n }, [cap]);\n\n return (\n <div\n ref={ref}\n style={{\n width: '100%',\n height: '100%',\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n};\n","import {\n ReactNode,\n useEffect,\n useRef,\n useCallback,\n HTMLAttributes,\n CSSProperties,\n} from '@framework';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface PagePointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n style?: CSSProperties;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nexport const PagePointerProvider = ({\n pageIndex,\n children,\n pageWidth,\n pageHeight,\n rotation,\n scale,\n convertEventToPoint,\n style,\n ...props\n}: PagePointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = useIsPageExclusive();\n\n // Memoize the default conversion function\n const defaultConvertEventToPoint = useCallback(\n (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: pageWidth, height: pageHeight },\n displayPoint,\n rotation,\n scale,\n );\n },\n [pageWidth, pageHeight, rotation, scale],\n );\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(\n cap,\n { type: 'page', pageIndex },\n ref.current,\n convertEventToPoint || defaultConvertEventToPoint,\n );\n }, [cap, pageIndex, convertEventToPoint, defaultConvertEventToPoint]);\n\n return (\n <div\n ref={ref}\n style={{\n ...style,\n }}\n {...props}\n >\n {children}\n {isPageExclusive && (\n <div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }} />\n )}\n </div>\n );\n};\n"],"names":["useInteractionManagerCapability","useCapability","InteractionManagerPlugin","id","useIsPageExclusive","provides","cap","isPageExclusive","setIsPageExclusive","useState","m","getActiveInteractionMode","scope","exclusive","useEffect","onModeChange","mode","domEventMap","pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel","allEventTypes","createPointerProvider","element","convertEventToPoint","active","getHandlersForScope","wantsRawTouchNow","_a","wantsRawTouch","listeners","attachedWithRawTouch","addListeners","raw","forEach","type","fn","handleEvent","addEventListener","startsWith","passive","removeListeners","removeEventListener","stopMode","style","cursor","stopHandler","onHandlerChange","initialMode","initialCursor","getCurrentCursor","stopCursor","onCursorChange","c","toPos","e","host","r","getBoundingClientRect","x","clientX","left","y","clientY","top","evt","isPaused","handlerKey","pos","normEvt","TouchEvent","preventDefault","tp","changedTouches","touches","ctrlKey","shiftKey","altKey","metaKey","target","currentTarget","setPointerCapture","releasePointerCapture","pe","_b","call","pointerId","getActiveMode","children","props","ref","useRef","current","jsxRuntime","jsx","width","height","pageIndex","pageWidth","pageHeight","rotation","scale","defaultConvertEventToPoint","useCallback","event","rect","displayPoint","restorePosition","jsxs","position","right","bottom","zIndex","setCursor","token","prio","removeCursor","state","setState","initialState","onStateChange","usePlugin","modeId","register","handlers","options","finalModeId","finalPageIndex","registerHandlers","registerAlways"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-interaction-manager.ts","../../src/shared/utils.ts","../../src/shared/components/global-pointer-provider.tsx","../../src/shared/components/page-pointer-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlers,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { useState, useEffect } from '@framework';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const [state, setState] = useState<InteractionManagerState>(initialState);\n\n useEffect(() => {\n if (!provides) return;\n return provides.onStateChange((state) => {\n setState(state);\n });\n }, [provides]);\n\n return {\n provides,\n state,\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n return finalModeId\n ? provides?.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides?.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n\n const [isPageExclusive, setIsPageExclusive] = useState<boolean>(() => {\n const m = cap?.getActiveInteractionMode();\n return m?.scope === 'page' && !!m.exclusive;\n });\n\n useEffect(() => {\n if (!cap) return;\n\n return cap.onModeChange(() => {\n const mode = cap.getActiveInteractionMode();\n setIsPageExclusive(mode?.scope === 'page' && !!mode?.exclusive);\n });\n }, [cap]);\n\n return isPageExclusive;\n}\n","import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\nfunction isTouchEvent(evt: Event): evt is TouchEvent {\n return typeof TouchEvent !== 'undefined' && evt instanceof TouchEvent;\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n isTouchEvent(evt) &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (isTouchEvent(evt)) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { ReactNode, useEffect, useRef, HTMLAttributes, CSSProperties } from '@framework';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability } from '../hooks';\n\ninterface GlobalPointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n style?: CSSProperties;\n}\n\nexport const GlobalPointerProvider = ({\n children,\n style,\n ...props\n}: GlobalPointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(cap, { type: 'global' }, ref.current);\n }, [cap]);\n\n return (\n <div\n ref={ref}\n style={{\n width: '100%',\n height: '100%',\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n};\n","import {\n ReactNode,\n useEffect,\n useRef,\n useCallback,\n HTMLAttributes,\n CSSProperties,\n} from '@framework';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface PagePointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n style?: CSSProperties;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nexport const PagePointerProvider = ({\n pageIndex,\n children,\n pageWidth,\n pageHeight,\n rotation,\n scale,\n convertEventToPoint,\n style,\n ...props\n}: PagePointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = useIsPageExclusive();\n\n // Memoize the default conversion function\n const defaultConvertEventToPoint = useCallback(\n (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: pageWidth, height: pageHeight },\n displayPoint,\n rotation,\n scale,\n );\n },\n [pageWidth, pageHeight, rotation, scale],\n );\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(\n cap,\n { type: 'page', pageIndex },\n ref.current,\n convertEventToPoint || defaultConvertEventToPoint,\n );\n }, [cap, pageIndex, convertEventToPoint, defaultConvertEventToPoint]);\n\n return (\n <div\n ref={ref}\n style={{\n ...style,\n }}\n {...props}\n >\n {children}\n {isPageExclusive && (\n <div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }} />\n )}\n </div>\n );\n};\n"],"names":["useInteractionManagerCapability","useCapability","InteractionManagerPlugin","id","useIsPageExclusive","provides","cap","isPageExclusive","setIsPageExclusive","useState","m","getActiveInteractionMode","scope","exclusive","useEffect","onModeChange","mode","domEventMap","pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel","allEventTypes","isTouchEvent","evt","TouchEvent","createPointerProvider","element","convertEventToPoint","active","getHandlersForScope","wantsRawTouchNow","_a","wantsRawTouch","listeners","attachedWithRawTouch","addListeners","raw","forEach","type","fn","handleEvent","addEventListener","startsWith","passive","removeListeners","removeEventListener","stopMode","style","cursor","stopHandler","onHandlerChange","initialMode","initialCursor","getCurrentCursor","stopCursor","onCursorChange","c","toPos","e","host","r","getBoundingClientRect","x","clientX","left","y","clientY","top","isPaused","handlerKey","pos","normEvt","preventDefault","tp","changedTouches","touches","ctrlKey","shiftKey","altKey","metaKey","target","currentTarget","setPointerCapture","releasePointerCapture","pe","_b","call","pointerId","getActiveMode","children","props","ref","useRef","current","jsxRuntime","jsx","width","height","pageIndex","pageWidth","pageHeight","rotation","scale","defaultConvertEventToPoint","useCallback","event","rect","displayPoint","restorePosition","jsxs","position","right","bottom","zIndex","setCursor","token","prio","removeCursor","state","setState","initialState","onStateChange","usePlugin","modeId","register","handlers","options","finalModeId","finalPageIndex","registerHandlers","registerAlways"],"mappings":"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"}
@@ -104,6 +104,9 @@ const allEventTypes = [...pointerEventTypes, ...touchEventTypes];
104
104
  function listenerOpts(eventType, wantsRawTouch) {
105
105
  return eventType.startsWith("touch") ? { passive: !wantsRawTouch } : { passive: false };
106
106
  }
107
+ function isTouchEvent(evt) {
108
+ return typeof TouchEvent !== "undefined" && evt instanceof TouchEvent;
109
+ }
107
110
  function createPointerProvider(cap, scope, element, convertEventToPoint) {
108
111
  let active = cap.getHandlersForScope(scope);
109
112
  const wantsRawTouchNow = () => {
@@ -159,12 +162,12 @@ function createPointerProvider(cap, scope, element, convertEventToPoint) {
159
162
  if (cap.isPaused()) return;
160
163
  const handlerKey = domEventMap[evt.type];
161
164
  if (!handlerKey || !(active == null ? void 0 : active[handlerKey])) return;
162
- if (evt instanceof TouchEvent && attachedWithRawTouch && (evt.type === "touchmove" || evt.type === "touchcancel")) {
165
+ if (isTouchEvent(evt) && attachedWithRawTouch && (evt.type === "touchmove" || evt.type === "touchcancel")) {
163
166
  evt.preventDefault();
164
167
  }
165
168
  let pos;
166
169
  let normEvt;
167
- if (evt instanceof TouchEvent) {
170
+ if (isTouchEvent(evt)) {
168
171
  const tp = evt.type === "touchend" || evt.type === "touchcancel" ? evt.changedTouches[0] : evt.touches[0];
169
172
  if (!tp) return;
170
173
  pos = toPos(tp, element);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-interaction-manager.ts","../../src/shared/utils.ts","../../src/shared/components/global-pointer-provider.tsx","../../src/shared/components/page-pointer-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlers,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { useState, useEffect } from '@framework';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const [state, setState] = useState<InteractionManagerState>(initialState);\n\n useEffect(() => {\n if (!provides) return;\n return provides.onStateChange((state) => {\n setState(state);\n });\n }, [provides]);\n\n return {\n provides,\n state,\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n return finalModeId\n ? provides?.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides?.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n\n const [isPageExclusive, setIsPageExclusive] = useState<boolean>(() => {\n const m = cap?.getActiveInteractionMode();\n return m?.scope === 'page' && !!m.exclusive;\n });\n\n useEffect(() => {\n if (!cap) return;\n\n return cap.onModeChange(() => {\n const mode = cap.getActiveInteractionMode();\n setIsPageExclusive(mode?.scope === 'page' && !!mode?.exclusive);\n });\n }, [cap]);\n\n return isPageExclusive;\n}\n","import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n evt instanceof TouchEvent &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (evt instanceof TouchEvent) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { ReactNode, useEffect, useRef, HTMLAttributes, CSSProperties } from '@framework';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability } from '../hooks';\n\ninterface GlobalPointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n style?: CSSProperties;\n}\n\nexport const GlobalPointerProvider = ({\n children,\n style,\n ...props\n}: GlobalPointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(cap, { type: 'global' }, ref.current);\n }, [cap]);\n\n return (\n <div\n ref={ref}\n style={{\n width: '100%',\n height: '100%',\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n};\n","import {\n ReactNode,\n useEffect,\n useRef,\n useCallback,\n HTMLAttributes,\n CSSProperties,\n} from '@framework';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface PagePointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n style?: CSSProperties;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nexport const PagePointerProvider = ({\n pageIndex,\n children,\n pageWidth,\n pageHeight,\n rotation,\n scale,\n convertEventToPoint,\n style,\n ...props\n}: PagePointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = useIsPageExclusive();\n\n // Memoize the default conversion function\n const defaultConvertEventToPoint = useCallback(\n (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: pageWidth, height: pageHeight },\n displayPoint,\n rotation,\n scale,\n );\n },\n [pageWidth, pageHeight, rotation, scale],\n );\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(\n cap,\n { type: 'page', pageIndex },\n ref.current,\n convertEventToPoint || defaultConvertEventToPoint,\n );\n }, [cap, pageIndex, convertEventToPoint, defaultConvertEventToPoint]);\n\n return (\n <div\n ref={ref}\n style={{\n ...style,\n }}\n {...props}\n >\n {children}\n {isPageExclusive && (\n <div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }} />\n )}\n </div>\n );\n};\n"],"names":["state","_a"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-interaction-manager.ts","../../src/shared/utils.ts","../../src/shared/components/global-pointer-provider.tsx","../../src/shared/components/page-pointer-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlers,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { useState, useEffect } from '@framework';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const [state, setState] = useState<InteractionManagerState>(initialState);\n\n useEffect(() => {\n if (!provides) return;\n return provides.onStateChange((state) => {\n setState(state);\n });\n }, [provides]);\n\n return {\n provides,\n state,\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n return finalModeId\n ? provides?.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides?.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n\n const [isPageExclusive, setIsPageExclusive] = useState<boolean>(() => {\n const m = cap?.getActiveInteractionMode();\n return m?.scope === 'page' && !!m.exclusive;\n });\n\n useEffect(() => {\n if (!cap) return;\n\n return cap.onModeChange(() => {\n const mode = cap.getActiveInteractionMode();\n setIsPageExclusive(mode?.scope === 'page' && !!mode?.exclusive);\n });\n }, [cap]);\n\n return isPageExclusive;\n}\n","import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\nfunction isTouchEvent(evt: Event): evt is TouchEvent {\n return typeof TouchEvent !== 'undefined' && evt instanceof TouchEvent;\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n isTouchEvent(evt) &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (isTouchEvent(evt)) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { ReactNode, useEffect, useRef, HTMLAttributes, CSSProperties } from '@framework';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability } from '../hooks';\n\ninterface GlobalPointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n style?: CSSProperties;\n}\n\nexport const GlobalPointerProvider = ({\n children,\n style,\n ...props\n}: GlobalPointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(cap, { type: 'global' }, ref.current);\n }, [cap]);\n\n return (\n <div\n ref={ref}\n style={{\n width: '100%',\n height: '100%',\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n};\n","import {\n ReactNode,\n useEffect,\n useRef,\n useCallback,\n HTMLAttributes,\n CSSProperties,\n} from '@framework';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../utils';\n\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface PagePointerProviderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n style?: CSSProperties;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nexport const PagePointerProvider = ({\n pageIndex,\n children,\n pageWidth,\n pageHeight,\n rotation,\n scale,\n convertEventToPoint,\n style,\n ...props\n}: PagePointerProviderProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = useIsPageExclusive();\n\n // Memoize the default conversion function\n const defaultConvertEventToPoint = useCallback(\n (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: pageWidth, height: pageHeight },\n displayPoint,\n rotation,\n scale,\n );\n },\n [pageWidth, pageHeight, rotation, scale],\n );\n\n useEffect(() => {\n if (!cap || !ref.current) return;\n\n return createPointerProvider(\n cap,\n { type: 'page', pageIndex },\n ref.current,\n convertEventToPoint || defaultConvertEventToPoint,\n );\n }, [cap, pageIndex, convertEventToPoint, defaultConvertEventToPoint]);\n\n return (\n <div\n ref={ref}\n style={{\n ...style,\n }}\n {...props}\n >\n {children}\n {isPageExclusive && (\n <div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }} />\n )}\n </div>\n );\n};\n"],"names":["state","_a"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),t=require("@embedpdf/core/vue"),o=require("@embedpdf/plugin-interaction-manager"),n=require("@embedpdf/models"),r={pointerdown:"onPointerDown",pointerup:"onPointerUp",pointermove:"onPointerMove",pointerenter:"onPointerEnter",pointerleave:"onPointerLeave",pointercancel:"onPointerCancel",mousedown:"onMouseDown",mouseup:"onMouseUp",mousemove:"onMouseMove",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",mousecancel:"onMouseCancel",click:"onClick",dblclick:"onDoubleClick",touchstart:"onPointerDown",touchend:"onPointerUp",touchmove:"onPointerMove",touchcancel:"onPointerCancel"},l=["pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel"];function a(e,t,o,n){let a=e.getHandlersForScope(t);const i=()=>{var t;return!1!==(null==(t=e.getActiveInteractionMode())?void 0:t.wantsRawTouch)},c={};let u=i();const s=e=>{l.forEach((t=>{const n=c[t]??(c[t]=y);var r;o.addEventListener(t,n,(r=e,t.startsWith("touch")?{passive:!r}:{passive:!1}))}))},p=()=>{l.forEach((e=>{const t=c[e];t&&o.removeEventListener(e,t)}))};s(u);const v=e.onModeChange((()=>{if("global"===t.type){const t=e.getActiveInteractionMode();o.style.cursor="global"===(null==t?void 0:t.scope)?t.cursor??"auto":"auto"}a=e.getHandlersForScope(t);const n=i();n!==u&&(p(),s(n),u=n)})),d=e.onHandlerChange((()=>{a=e.getHandlersForScope(t)})),g=e.getActiveInteractionMode(),f=e.getCurrentCursor();o.style.cursor="global"===t.type&&"global"!==(null==g?void 0:g.scope)?"auto":f;const h=e.onCursorChange((n=>{var r;"global"===t.type&&"global"!==(null==(r=e.getActiveInteractionMode())?void 0:r.scope)||(o.style.cursor=n)})),m=(e,t)=>{if(n)return n(e,t);const o=t.getBoundingClientRect();return{x:e.clientX-o.left,y:e.clientY-o.top}};function y(t){var n;if(e.isPaused())return;const l=r[t.type];if(!l||!(null==a?void 0:a[l]))return;let i,c;if(t instanceof TouchEvent&&u&&("touchmove"===t.type||"touchcancel"===t.type)&&t.preventDefault(),t instanceof TouchEvent){const e="touchend"===t.type||"touchcancel"===t.type?t.changedTouches[0]:t.touches[0];if(!e)return;i=m(e,o),c={clientX:e.clientX,clientY:e.clientY,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,target:t.target,currentTarget:t.currentTarget,setPointerCapture:()=>{},releasePointerCapture:()=>{}}}else{const e=t;i=m(e,o),c={clientX:e.clientX,clientY:e.clientY,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey,target:e.target,currentTarget:e.currentTarget,setPointerCapture:()=>{var t,o;null==(o=null==(t=e.target)?void 0:t.setPointerCapture)||o.call(t,e.pointerId)},releasePointerCapture:()=>{var t,o;null==(o=null==(t=e.target)?void 0:t.releasePointerCapture)||o.call(t,e.pointerId)}}}null==(n=a[l])||n.call(a,i,c,e.getActiveMode())}return()=>{p(),v(),h(),d()}}const i=()=>t.useCapability(o.InteractionManagerPlugin.id);function c(){const{provides:t}=i(),o=e.ref(!1);return e.watchEffect((e=>{if(t.value){const n=t.value.getActiveInteractionMode();o.value="page"===(null==n?void 0:n.scope)&&!!(null==n?void 0:n.exclusive);e(t.value.onModeChange((()=>{if(!t.value)return;const e=t.value.getActiveInteractionMode();o.value="page"===(null==e?void 0:e.scope)&&!!(null==e?void 0:e.exclusive)})))}})),e.readonly(o)}const u=e.defineComponent({__name:"global-pointer-provider",setup(t){const o=e.ref(null),{provides:n}=i();return e.watchEffect((e=>{if(n.value&&o.value){e(a(n.value,{type:"global"},o.value))}})),(t,n)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"divRef",ref:o,style:{width:"100%",height:"100%"}},[e.renderSlot(t.$slots,"default")],512))}}),s={key:0,style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:10}},p=e.defineComponent({__name:"page-pointer-provider",props:{pageIndex:{},pageWidth:{},pageHeight:{},rotation:{},scale:{},convertEventToPoint:{type:Function}},setup(t){const o=t,r=e.ref(null),{provides:l}=i(),u=c(),p=e.computed((()=>(e,t)=>{const r=t.getBoundingClientRect(),l={x:e.clientX-r.left,y:e.clientY-r.top};return n.restorePosition({width:o.pageWidth,height:o.pageHeight},l,o.rotation,o.scale)}));return e.watchEffect((e=>{if(l.value&&r.value){e(a(l.value,{type:"page",pageIndex:o.pageIndex},r.value,o.convertEventToPoint||p.value))}})),(t,o)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"divRef",ref:r},[e.renderSlot(t.$slots,"default"),e.unref(u)?(e.openBlock(),e.createElementBlock("div",s)):e.createCommentVNode("",!0)],512))}});exports.GlobalPointerProvider=u,exports.PagePointerProvider=p,exports.useCursor=function(){const{provides:e}=i();return{setCursor:(t,o,n=0)=>{var r;null==(r=e.value)||r.setCursor(t,o,n)},removeCursor:t=>{var o;null==(o=e.value)||o.removeCursor(t)}}},exports.useInteractionManager=function(){const{provides:t}=i(),n=e.ref(o.initialState);return e.watchEffect((e=>{if(t.value){e(t.value.onStateChange((e=>{n.value=e})))}})),{provides:t,state:e.readonly(n)}},exports.useInteractionManagerCapability=i,exports.useInteractionManagerPlugin=()=>t.usePlugin(o.InteractionManagerPlugin.id),exports.useIsPageExclusive=c,exports.usePointerHandlers=function({modeId:e,pageIndex:t}){const{provides:o}=i();return{register:(n,r)=>{const l=(null==r?void 0:r.modeId)??e,a=(null==r?void 0:r.pageIndex)??t;if(o.value)return l?o.value.registerHandlers({modeId:l,handlers:n,pageIndex:a}):o.value.registerAlways({scope:void 0!==a?{type:"page",pageIndex:a}:{type:"global"},handlers:n})}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),t=require("@embedpdf/core/vue"),o=require("@embedpdf/plugin-interaction-manager"),n=require("@embedpdf/models"),r={pointerdown:"onPointerDown",pointerup:"onPointerUp",pointermove:"onPointerMove",pointerenter:"onPointerEnter",pointerleave:"onPointerLeave",pointercancel:"onPointerCancel",mousedown:"onMouseDown",mouseup:"onMouseUp",mousemove:"onMouseMove",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",mousecancel:"onMouseCancel",click:"onClick",dblclick:"onDoubleClick",touchstart:"onPointerDown",touchend:"onPointerUp",touchmove:"onPointerMove",touchcancel:"onPointerCancel"},l=["pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel"];function a(e){return"undefined"!=typeof TouchEvent&&e instanceof TouchEvent}function i(e,t,o,n){let i=e.getHandlersForScope(t);const u=()=>{var t;return!1!==(null==(t=e.getActiveInteractionMode())?void 0:t.wantsRawTouch)},c={};let s=u();const p=e=>{l.forEach((t=>{const n=c[t]??(c[t]=P);var r;o.addEventListener(t,n,(r=e,t.startsWith("touch")?{passive:!r}:{passive:!1}))}))},d=()=>{l.forEach((e=>{const t=c[e];t&&o.removeEventListener(e,t)}))};p(s);const v=e.onModeChange((()=>{if("global"===t.type){const t=e.getActiveInteractionMode();o.style.cursor="global"===(null==t?void 0:t.scope)?t.cursor??"auto":"auto"}i=e.getHandlersForScope(t);const n=u();n!==s&&(d(),p(n),s=n)})),g=e.onHandlerChange((()=>{i=e.getHandlersForScope(t)})),f=e.getActiveInteractionMode(),h=e.getCurrentCursor();o.style.cursor="global"===t.type&&"global"!==(null==f?void 0:f.scope)?"auto":h;const y=e.onCursorChange((n=>{var r;"global"===t.type&&"global"!==(null==(r=e.getActiveInteractionMode())?void 0:r.scope)||(o.style.cursor=n)})),m=(e,t)=>{if(n)return n(e,t);const o=t.getBoundingClientRect();return{x:e.clientX-o.left,y:e.clientY-o.top}};function P(t){var n;if(e.isPaused())return;const l=r[t.type];if(!l||!(null==i?void 0:i[l]))return;let u,c;if(a(t)&&s&&("touchmove"===t.type||"touchcancel"===t.type)&&t.preventDefault(),a(t)){const e="touchend"===t.type||"touchcancel"===t.type?t.changedTouches[0]:t.touches[0];if(!e)return;u=m(e,o),c={clientX:e.clientX,clientY:e.clientY,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,target:t.target,currentTarget:t.currentTarget,setPointerCapture:()=>{},releasePointerCapture:()=>{}}}else{const e=t;u=m(e,o),c={clientX:e.clientX,clientY:e.clientY,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey,target:e.target,currentTarget:e.currentTarget,setPointerCapture:()=>{var t,o;null==(o=null==(t=e.target)?void 0:t.setPointerCapture)||o.call(t,e.pointerId)},releasePointerCapture:()=>{var t,o;null==(o=null==(t=e.target)?void 0:t.releasePointerCapture)||o.call(t,e.pointerId)}}}null==(n=i[l])||n.call(i,u,c,e.getActiveMode())}return()=>{d(),v(),y(),g()}}const u=()=>t.useCapability(o.InteractionManagerPlugin.id);function c(){const{provides:t}=u(),o=e.ref(!1);return e.watchEffect((e=>{if(t.value){const n=t.value.getActiveInteractionMode();o.value="page"===(null==n?void 0:n.scope)&&!!(null==n?void 0:n.exclusive);e(t.value.onModeChange((()=>{if(!t.value)return;const e=t.value.getActiveInteractionMode();o.value="page"===(null==e?void 0:e.scope)&&!!(null==e?void 0:e.exclusive)})))}})),e.readonly(o)}const s=e.defineComponent({__name:"global-pointer-provider",setup(t){const o=e.ref(null),{provides:n}=u();return e.watchEffect((e=>{if(n.value&&o.value){e(i(n.value,{type:"global"},o.value))}})),(t,n)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"divRef",ref:o,style:{width:"100%",height:"100%"}},[e.renderSlot(t.$slots,"default")],512))}}),p={key:0,style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:10}},d=e.defineComponent({__name:"page-pointer-provider",props:{pageIndex:{},pageWidth:{},pageHeight:{},rotation:{},scale:{},convertEventToPoint:{type:Function}},setup(t){const o=t,r=e.ref(null),{provides:l}=u(),a=c(),s=e.computed((()=>(e,t)=>{const r=t.getBoundingClientRect(),l={x:e.clientX-r.left,y:e.clientY-r.top};return n.restorePosition({width:o.pageWidth,height:o.pageHeight},l,o.rotation,o.scale)}));return e.watchEffect((e=>{if(l.value&&r.value){e(i(l.value,{type:"page",pageIndex:o.pageIndex},r.value,o.convertEventToPoint||s.value))}})),(t,o)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"divRef",ref:r},[e.renderSlot(t.$slots,"default"),e.unref(a)?(e.openBlock(),e.createElementBlock("div",p)):e.createCommentVNode("",!0)],512))}});exports.GlobalPointerProvider=s,exports.PagePointerProvider=d,exports.useCursor=function(){const{provides:e}=u();return{setCursor:(t,o,n=0)=>{var r;null==(r=e.value)||r.setCursor(t,o,n)},removeCursor:t=>{var o;null==(o=e.value)||o.removeCursor(t)}}},exports.useInteractionManager=function(){const{provides:t}=u(),n=e.ref(o.initialState);return e.watchEffect((e=>{if(t.value){e(t.value.onStateChange((e=>{n.value=e})))}})),{provides:t,state:e.readonly(n)}},exports.useInteractionManagerCapability=u,exports.useInteractionManagerPlugin=()=>t.usePlugin(o.InteractionManagerPlugin.id),exports.useIsPageExclusive=c,exports.usePointerHandlers=function({modeId:e,pageIndex:t}){const{provides:o}=u();return{register:(n,r)=>{const l=(null==r?void 0:r.modeId)??e,a=(null==r?void 0:r.pageIndex)??t;if(o.value)return l?o.value.registerHandlers({modeId:l,handlers:n,pageIndex:a}):o.value.registerAlways({scope:void 0!==a?{type:"page",pageIndex:a}:{type:"global"},handlers:n})}}};
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/shared/utils.ts","../../src/vue/hooks/use-interaction-manager.ts","../../src/vue/components/global-pointer-provider.vue","../../src/vue/components/page-pointer-provider.vue"],"sourcesContent":["import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n evt instanceof TouchEvent &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (evt instanceof TouchEvent) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { ref, watchEffect, readonly } from 'vue';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const state = ref<InteractionManagerState>(initialState);\n\n watchEffect((onCleanup) => {\n if (provides.value) {\n // onStateChange is a BehaviorEmitter, so it emits the current state upon subscription\n const unsubscribe = provides.value.onStateChange((newState) => {\n state.value = newState;\n });\n onCleanup(unsubscribe);\n }\n });\n\n return {\n provides,\n state: readonly(state),\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides.value?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides.value?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n if (!provides.value) return;\n\n return finalModeId\n ? provides.value.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides.value.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = ref<boolean>(false);\n\n watchEffect((onCleanup) => {\n if (cap.value) {\n const mode = cap.value.getActiveInteractionMode();\n isPageExclusive.value = mode?.scope === 'page' && !!mode?.exclusive;\n\n const unsubscribe = cap.value.onModeChange(() => {\n if (!cap.value) return;\n const newMode = cap.value.getActiveInteractionMode();\n isPageExclusive.value = newMode?.scope === 'page' && !!newMode?.exclusive;\n });\n onCleanup(unsubscribe);\n }\n });\n\n return readonly(isPageExclusive);\n}\n","<script setup lang=\"ts\">\nimport { ref, watchEffect } from 'vue';\nimport { createPointerProvider } from '../../shared/utils';\nimport { useInteractionManagerCapability } from '../hooks';\n\nconst divRef = ref<HTMLDivElement | null>(null);\nconst { provides: cap } = useInteractionManagerCapability();\n\n// watchEffect automatically handles setup and teardown when capability or element is ready\nwatchEffect((onCleanup) => {\n if (cap.value && divRef.value) {\n const cleanup = createPointerProvider(cap.value, { type: 'global' }, divRef.value);\n onCleanup(cleanup);\n }\n});\n</script>\n\n<template>\n <div\n ref=\"divRef\"\n :style=\"{\n width: '100%',\n height: '100%',\n }\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, watchEffect, computed, StyleValue } from 'vue';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../../shared/utils';\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface Props {\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nconst props = defineProps<Props>();\n\nconst divRef = ref<HTMLDivElement | null>(null);\nconst { provides: cap } = useInteractionManagerCapability();\nconst isPageExclusive = useIsPageExclusive();\n\nconst defaultConvertEventToPoint = computed(() => {\n return (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: props.pageWidth, height: props.pageHeight },\n displayPoint,\n props.rotation,\n props.scale,\n );\n };\n});\n\nwatchEffect((onCleanup) => {\n if (cap.value && divRef.value) {\n const cleanup = createPointerProvider(\n cap.value,\n { type: 'page', pageIndex: props.pageIndex },\n divRef.value,\n props.convertEventToPoint || defaultConvertEventToPoint.value,\n );\n onCleanup(cleanup);\n }\n});\n</script>\n\n<template>\n <div ref=\"divRef\">\n <slot />\n <div\n v-if=\"isPageExclusive\"\n :style=\"{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }\"\n />\n </div>\n</template>\n"],"names":["domEventMap","pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel","allEventTypes","createPointerProvider","cap","scope","element","convertEventToPoint","active","getHandlersForScope","wantsRawTouchNow","_a","getActiveInteractionMode","wantsRawTouch","listeners","attachedWithRawTouch","addListeners","raw","forEach","type","fn","handleEvent","addEventListener","startsWith","passive","removeListeners","removeEventListener","stopMode","onModeChange","mode","style","cursor","stopHandler","onHandlerChange","initialMode","initialCursor","getCurrentCursor","stopCursor","onCursorChange","c","toPos","e","host","r","getBoundingClientRect","x","clientX","left","y","clientY","top","evt","isPaused","handlerKey","pos","normEvt","TouchEvent","preventDefault","tp","changedTouches","touches","ctrlKey","shiftKey","altKey","metaKey","target","currentTarget","setPointerCapture","releasePointerCapture","pe","_b","call","pointerId","getActiveMode","useInteractionManagerCapability","useCapability","InteractionManagerPlugin","id","useIsPageExclusive","provides","isPageExclusive","ref","readonly","vue$1","watchEffect","onCleanup","value","exclusive","newMode","divRef","_createElementBlock","createElementBlock","_renderSlot","_ctx","$slots","props","__props","defaultConvertEventToPoint","computed","event","rect","displayPoint","restorePosition","width","pageWidth","height","pageHeight","rotation","scale","pageIndex","_unref","_openBlock","_hoisted_1","setCursor","token","prio","removeCursor","state","initialState","onStateChange","newState","usePlugin","modeId","register","handlers","options","finalModeId","finalPageIndex","registerHandlers","registerAlways"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/shared/utils.ts","../../src/vue/hooks/use-interaction-manager.ts","../../src/vue/components/global-pointer-provider.vue","../../src/vue/components/page-pointer-provider.vue"],"sourcesContent":["import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\nfunction isTouchEvent(evt: Event): evt is TouchEvent {\n return typeof TouchEvent !== 'undefined' && evt instanceof TouchEvent;\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n isTouchEvent(evt) &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (isTouchEvent(evt)) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { ref, watchEffect, readonly } from 'vue';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const state = ref<InteractionManagerState>(initialState);\n\n watchEffect((onCleanup) => {\n if (provides.value) {\n // onStateChange is a BehaviorEmitter, so it emits the current state upon subscription\n const unsubscribe = provides.value.onStateChange((newState) => {\n state.value = newState;\n });\n onCleanup(unsubscribe);\n }\n });\n\n return {\n provides,\n state: readonly(state),\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides.value?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides.value?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n if (!provides.value) return;\n\n return finalModeId\n ? provides.value.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides.value.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = ref<boolean>(false);\n\n watchEffect((onCleanup) => {\n if (cap.value) {\n const mode = cap.value.getActiveInteractionMode();\n isPageExclusive.value = mode?.scope === 'page' && !!mode?.exclusive;\n\n const unsubscribe = cap.value.onModeChange(() => {\n if (!cap.value) return;\n const newMode = cap.value.getActiveInteractionMode();\n isPageExclusive.value = newMode?.scope === 'page' && !!newMode?.exclusive;\n });\n onCleanup(unsubscribe);\n }\n });\n\n return readonly(isPageExclusive);\n}\n","<script setup lang=\"ts\">\nimport { ref, watchEffect } from 'vue';\nimport { createPointerProvider } from '../../shared/utils';\nimport { useInteractionManagerCapability } from '../hooks';\n\nconst divRef = ref<HTMLDivElement | null>(null);\nconst { provides: cap } = useInteractionManagerCapability();\n\n// watchEffect automatically handles setup and teardown when capability or element is ready\nwatchEffect((onCleanup) => {\n if (cap.value && divRef.value) {\n const cleanup = createPointerProvider(cap.value, { type: 'global' }, divRef.value);\n onCleanup(cleanup);\n }\n});\n</script>\n\n<template>\n <div\n ref=\"divRef\"\n :style=\"{\n width: '100%',\n height: '100%',\n }\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, watchEffect, computed, StyleValue } from 'vue';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../../shared/utils';\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface Props {\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nconst props = defineProps<Props>();\n\nconst divRef = ref<HTMLDivElement | null>(null);\nconst { provides: cap } = useInteractionManagerCapability();\nconst isPageExclusive = useIsPageExclusive();\n\nconst defaultConvertEventToPoint = computed(() => {\n return (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: props.pageWidth, height: props.pageHeight },\n displayPoint,\n props.rotation,\n props.scale,\n );\n };\n});\n\nwatchEffect((onCleanup) => {\n if (cap.value && divRef.value) {\n const cleanup = createPointerProvider(\n cap.value,\n { type: 'page', pageIndex: props.pageIndex },\n divRef.value,\n props.convertEventToPoint || defaultConvertEventToPoint.value,\n );\n onCleanup(cleanup);\n }\n});\n</script>\n\n<template>\n <div ref=\"divRef\">\n <slot />\n <div\n v-if=\"isPageExclusive\"\n :style=\"{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }\"\n />\n </div>\n</template>\n"],"names":["domEventMap","pointerdown","pointerup","pointermove","pointerenter","pointerleave","pointercancel","mousedown","mouseup","mousemove","mouseenter","mouseleave","mousecancel","click","dblclick","touchstart","touchend","touchmove","touchcancel","allEventTypes","isTouchEvent","evt","TouchEvent","createPointerProvider","cap","scope","element","convertEventToPoint","active","getHandlersForScope","wantsRawTouchNow","_a","getActiveInteractionMode","wantsRawTouch","listeners","attachedWithRawTouch","addListeners","raw","forEach","type","fn","handleEvent","addEventListener","startsWith","passive","removeListeners","removeEventListener","stopMode","onModeChange","mode","style","cursor","stopHandler","onHandlerChange","initialMode","initialCursor","getCurrentCursor","stopCursor","onCursorChange","c","toPos","e","host","r","getBoundingClientRect","x","clientX","left","y","clientY","top","isPaused","handlerKey","pos","normEvt","preventDefault","tp","changedTouches","touches","ctrlKey","shiftKey","altKey","metaKey","target","currentTarget","setPointerCapture","releasePointerCapture","pe","_b","call","pointerId","getActiveMode","useInteractionManagerCapability","useCapability","InteractionManagerPlugin","id","useIsPageExclusive","provides","isPageExclusive","ref","readonly","vue$1","watchEffect","onCleanup","value","exclusive","newMode","divRef","_createElementBlock","createElementBlock","_renderSlot","_ctx","$slots","props","__props","defaultConvertEventToPoint","computed","event","rect","displayPoint","restorePosition","width","pageWidth","height","pageHeight","rotation","scale","pageIndex","_unref","_openBlock","_hoisted_1","setCursor","token","prio","removeCursor","state","initialState","onStateChange","newState","usePlugin","modeId","register","handlers","options","finalModeId","finalPageIndex","registerHandlers","registerAlways"],"mappings":"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"}
package/dist/vue/index.js CHANGED
@@ -44,6 +44,9 @@ const allEventTypes = [...pointerEventTypes, ...touchEventTypes];
44
44
  function listenerOpts(eventType, wantsRawTouch) {
45
45
  return eventType.startsWith("touch") ? { passive: !wantsRawTouch } : { passive: false };
46
46
  }
47
+ function isTouchEvent(evt) {
48
+ return typeof TouchEvent !== "undefined" && evt instanceof TouchEvent;
49
+ }
47
50
  function createPointerProvider(cap, scope, element, convertEventToPoint) {
48
51
  let active = cap.getHandlersForScope(scope);
49
52
  const wantsRawTouchNow = () => {
@@ -99,12 +102,12 @@ function createPointerProvider(cap, scope, element, convertEventToPoint) {
99
102
  if (cap.isPaused()) return;
100
103
  const handlerKey = domEventMap[evt.type];
101
104
  if (!handlerKey || !(active == null ? void 0 : active[handlerKey])) return;
102
- if (evt instanceof TouchEvent && attachedWithRawTouch && (evt.type === "touchmove" || evt.type === "touchcancel")) {
105
+ if (isTouchEvent(evt) && attachedWithRawTouch && (evt.type === "touchmove" || evt.type === "touchcancel")) {
103
106
  evt.preventDefault();
104
107
  }
105
108
  let pos;
106
109
  let normEvt;
107
- if (evt instanceof TouchEvent) {
110
+ if (isTouchEvent(evt)) {
108
111
  const tp = evt.type === "touchend" || evt.type === "touchcancel" ? evt.changedTouches[0] : evt.touches[0];
109
112
  if (!tp) return;
110
113
  pos = toPos(tp, element);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/shared/utils.ts","../../src/vue/hooks/use-interaction-manager.ts","../../src/vue/components/global-pointer-provider.vue","../../src/vue/components/page-pointer-provider.vue"],"sourcesContent":["import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n evt instanceof TouchEvent &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (evt instanceof TouchEvent) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { ref, watchEffect, readonly } from 'vue';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const state = ref<InteractionManagerState>(initialState);\n\n watchEffect((onCleanup) => {\n if (provides.value) {\n // onStateChange is a BehaviorEmitter, so it emits the current state upon subscription\n const unsubscribe = provides.value.onStateChange((newState) => {\n state.value = newState;\n });\n onCleanup(unsubscribe);\n }\n });\n\n return {\n provides,\n state: readonly(state),\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides.value?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides.value?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n if (!provides.value) return;\n\n return finalModeId\n ? provides.value.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides.value.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = ref<boolean>(false);\n\n watchEffect((onCleanup) => {\n if (cap.value) {\n const mode = cap.value.getActiveInteractionMode();\n isPageExclusive.value = mode?.scope === 'page' && !!mode?.exclusive;\n\n const unsubscribe = cap.value.onModeChange(() => {\n if (!cap.value) return;\n const newMode = cap.value.getActiveInteractionMode();\n isPageExclusive.value = newMode?.scope === 'page' && !!newMode?.exclusive;\n });\n onCleanup(unsubscribe);\n }\n });\n\n return readonly(isPageExclusive);\n}\n","<script setup lang=\"ts\">\nimport { ref, watchEffect } from 'vue';\nimport { createPointerProvider } from '../../shared/utils';\nimport { useInteractionManagerCapability } from '../hooks';\n\nconst divRef = ref<HTMLDivElement | null>(null);\nconst { provides: cap } = useInteractionManagerCapability();\n\n// watchEffect automatically handles setup and teardown when capability or element is ready\nwatchEffect((onCleanup) => {\n if (cap.value && divRef.value) {\n const cleanup = createPointerProvider(cap.value, { type: 'global' }, divRef.value);\n onCleanup(cleanup);\n }\n});\n</script>\n\n<template>\n <div\n ref=\"divRef\"\n :style=\"{\n width: '100%',\n height: '100%',\n }\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, watchEffect, computed, StyleValue } from 'vue';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../../shared/utils';\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface Props {\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nconst props = defineProps<Props>();\n\nconst divRef = ref<HTMLDivElement | null>(null);\nconst { provides: cap } = useInteractionManagerCapability();\nconst isPageExclusive = useIsPageExclusive();\n\nconst defaultConvertEventToPoint = computed(() => {\n return (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: props.pageWidth, height: props.pageHeight },\n displayPoint,\n props.rotation,\n props.scale,\n );\n };\n});\n\nwatchEffect((onCleanup) => {\n if (cap.value && divRef.value) {\n const cleanup = createPointerProvider(\n cap.value,\n { type: 'page', pageIndex: props.pageIndex },\n divRef.value,\n props.convertEventToPoint || defaultConvertEventToPoint.value,\n );\n onCleanup(cleanup);\n }\n});\n</script>\n\n<template>\n <div ref=\"divRef\">\n <slot />\n <div\n v-if=\"isPageExclusive\"\n :style=\"{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }\"\n />\n </div>\n</template>\n"],"names":["_a","_createElementBlock","_renderSlot","_unref","_openBlock"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/shared/utils.ts","../../src/vue/hooks/use-interaction-manager.ts","../../src/vue/components/global-pointer-provider.vue","../../src/vue/components/page-pointer-provider.vue"],"sourcesContent":["import { Position } from '@embedpdf/models';\nimport type {\n InteractionManagerCapability,\n InteractionScope,\n PointerEventHandlers,\n EmbedPdfPointerEvent,\n} from '@embedpdf/plugin-interaction-manager';\n\n/* -------------------------------------------------- */\n/* event → handler key lookup */\n/* -------------------------------------------------- */\ntype K = keyof PointerEventHandlers;\nconst domEventMap: Record<string, K> = {\n pointerdown: 'onPointerDown',\n pointerup: 'onPointerUp',\n pointermove: 'onPointerMove',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n pointercancel: 'onPointerCancel',\n\n mousedown: 'onMouseDown',\n mouseup: 'onMouseUp',\n mousemove: 'onMouseMove',\n mouseenter: 'onMouseEnter',\n mouseleave: 'onMouseLeave',\n mousecancel: 'onMouseCancel',\n\n click: 'onClick',\n dblclick: 'onDoubleClick',\n\n /* touch → pointer fallback for very old browsers */\n touchstart: 'onPointerDown',\n touchend: 'onPointerUp',\n touchmove: 'onPointerMove',\n touchcancel: 'onPointerCancel',\n};\n\nconst pointerEventTypes = [\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerenter',\n 'pointerleave',\n 'pointercancel',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseenter',\n 'mouseleave',\n 'mousecancel',\n 'click',\n 'dblclick',\n];\n\nconst touchEventTypes = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nconst allEventTypes = [...pointerEventTypes, ...touchEventTypes];\n\n/* -------------------------------------------------- */\n/* helper: decide listener options per event type */\n/* -------------------------------------------------- */\nfunction listenerOpts(eventType: string, wantsRawTouch: boolean): AddEventListenerOptions {\n // Only touch events are toggled; pointer/mouse stay non-passive\n return eventType.startsWith('touch') ? { passive: !wantsRawTouch } : { passive: false };\n}\n\nfunction isTouchEvent(evt: Event): evt is TouchEvent {\n return typeof TouchEvent !== 'undefined' && evt instanceof TouchEvent;\n}\n\n/* -------------------------------------------------- */\n/* createPointerProvider */\n/* -------------------------------------------------- */\nexport function createPointerProvider(\n cap: InteractionManagerCapability,\n scope: InteractionScope,\n element: HTMLElement,\n convertEventToPoint?: (evt: PointerEvent, host: HTMLElement) => Position,\n) {\n /* ---------- live handler set --------------------------------------------------- */\n let active: PointerEventHandlers | null = cap.getHandlersForScope(scope);\n\n /* ---------- helper to compute current wantsRawTouch (defaults to true) --------- */\n const wantsRawTouchNow = () => cap.getActiveInteractionMode()?.wantsRawTouch !== false; // default → true\n\n /* ---------- dynamic listener (re)attachment ------------------------------------ */\n const listeners: Record<string, (evt: Event) => void> = {};\n let attachedWithRawTouch = wantsRawTouchNow(); // remember current mode’s wish\n\n const addListeners = (raw: boolean) => {\n allEventTypes.forEach((type) => {\n const fn = (listeners[type] ??= handleEvent);\n element.addEventListener(type, fn, listenerOpts(type, raw));\n });\n };\n const removeListeners = () => {\n allEventTypes.forEach((type) => {\n const fn = listeners[type];\n if (fn) element.removeEventListener(type, fn);\n });\n };\n\n /* attach for the first time */\n addListeners(attachedWithRawTouch);\n\n /* ---------- mode & handler change hooks --------------------------------------- */\n const stopMode = cap.onModeChange(() => {\n /* cursor baseline update for global wrapper */\n if (scope.type === 'global') {\n const mode = cap.getActiveInteractionMode();\n element.style.cursor = mode?.scope === 'global' ? (mode.cursor ?? 'auto') : 'auto';\n }\n\n active = cap.getHandlersForScope(scope);\n\n /* re-attach listeners if wantsRawTouch toggled */\n const raw = wantsRawTouchNow();\n if (raw !== attachedWithRawTouch) {\n removeListeners();\n addListeners(raw);\n attachedWithRawTouch = raw;\n }\n });\n\n const stopHandler = cap.onHandlerChange(() => {\n active = cap.getHandlersForScope(scope);\n });\n\n /* ---------- cursor sync -------------------------------------------------------- */\n const initialMode = cap.getActiveInteractionMode();\n const initialCursor = cap.getCurrentCursor();\n element.style.cursor =\n scope.type === 'global' && initialMode?.scope !== 'global' ? 'auto' : initialCursor;\n\n const stopCursor = cap.onCursorChange((c) => {\n if (scope.type === 'global' && cap.getActiveInteractionMode()?.scope !== 'global') return;\n element.style.cursor = c;\n });\n\n /* ---------- point conversion --------------------------------------------------- */\n const toPos = (e: { clientX: number; clientY: number }, host: HTMLElement): Position => {\n if (convertEventToPoint) return convertEventToPoint(e as PointerEvent, host);\n const r = host.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n };\n\n /* ---------- central event handler --------------------------------------------- */\n function handleEvent(evt: Event) {\n if (cap.isPaused()) return;\n\n const handlerKey = domEventMap[evt.type];\n if (!handlerKey || !active?.[handlerKey]) return;\n\n /* preventDefault only when mode really wants raw touch */\n if (\n isTouchEvent(evt) &&\n attachedWithRawTouch &&\n (evt.type === 'touchmove' || evt.type === 'touchcancel')\n ) {\n evt.preventDefault();\n }\n\n // ----- normalise ----------------------------------------------------------------\n let pos!: Position;\n let normEvt!: EmbedPdfPointerEvent & {\n target: EventTarget | null;\n currentTarget: EventTarget | null;\n };\n\n if (isTouchEvent(evt)) {\n const tp =\n evt.type === 'touchend' || evt.type === 'touchcancel'\n ? evt.changedTouches[0]\n : evt.touches[0];\n if (!tp) return;\n\n pos = toPos(tp, element);\n normEvt = {\n clientX: tp.clientX,\n clientY: tp.clientY,\n ctrlKey: evt.ctrlKey,\n shiftKey: evt.shiftKey,\n altKey: evt.altKey,\n metaKey: evt.metaKey,\n target: evt.target,\n currentTarget: evt.currentTarget,\n setPointerCapture: () => {},\n releasePointerCapture: () => {},\n };\n } else {\n const pe = evt as PointerEvent;\n pos = toPos(pe, element);\n normEvt = {\n clientX: pe.clientX,\n clientY: pe.clientY,\n ctrlKey: pe.ctrlKey,\n shiftKey: pe.shiftKey,\n altKey: pe.altKey,\n metaKey: pe.metaKey,\n target: pe.target,\n currentTarget: pe.currentTarget,\n setPointerCapture: () => {\n (pe.target as HTMLElement)?.setPointerCapture?.(pe.pointerId);\n },\n releasePointerCapture: () => {\n (pe.target as HTMLElement)?.releasePointerCapture?.(pe.pointerId);\n },\n };\n }\n\n active[handlerKey]?.(pos, normEvt, cap.getActiveMode());\n }\n\n /* ---------- teardown ----------------------------------------------------------- */\n return () => {\n removeListeners();\n stopMode();\n stopCursor();\n stopHandler();\n };\n}\n","import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport {\n initialState,\n InteractionManagerPlugin,\n InteractionManagerState,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\nimport { ref, watchEffect, readonly } from 'vue';\n\nexport const useInteractionManagerPlugin = () =>\n usePlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id);\nexport const useInteractionManagerCapability = () =>\n useCapability<InteractionManagerPlugin>(InteractionManagerPlugin.id);\n\nexport function useInteractionManager() {\n const { provides } = useInteractionManagerCapability();\n const state = ref<InteractionManagerState>(initialState);\n\n watchEffect((onCleanup) => {\n if (provides.value) {\n // onStateChange is a BehaviorEmitter, so it emits the current state upon subscription\n const unsubscribe = provides.value.onStateChange((newState) => {\n state.value = newState;\n });\n onCleanup(unsubscribe);\n }\n });\n\n return {\n provides,\n state: readonly(state),\n };\n}\n\nexport function useCursor() {\n const { provides } = useInteractionManagerCapability();\n return {\n setCursor: (token: string, cursor: string, prio = 0) => {\n provides.value?.setCursor(token, cursor, prio);\n },\n removeCursor: (token: string) => {\n provides.value?.removeCursor(token);\n },\n };\n}\n\ninterface UsePointerHandlersOptions {\n modeId?: string | string[];\n pageIndex?: number;\n}\n\nexport function usePointerHandlers({ modeId, pageIndex }: UsePointerHandlersOptions) {\n const { provides } = useInteractionManagerCapability();\n return {\n register: (\n handlers: PointerEventHandlersWithLifecycle,\n options?: { modeId?: string | string[]; pageIndex?: number },\n ) => {\n // Use provided options or fall back to hook-level options\n const finalModeId = options?.modeId ?? modeId;\n const finalPageIndex = options?.pageIndex ?? pageIndex;\n\n if (!provides.value) return;\n\n return finalModeId\n ? provides.value.registerHandlers({\n modeId: finalModeId,\n handlers,\n pageIndex: finalPageIndex,\n })\n : provides.value.registerAlways({\n scope:\n finalPageIndex !== undefined\n ? { type: 'page', pageIndex: finalPageIndex }\n : { type: 'global' },\n handlers,\n });\n },\n };\n}\n\nexport function useIsPageExclusive() {\n const { provides: cap } = useInteractionManagerCapability();\n const isPageExclusive = ref<boolean>(false);\n\n watchEffect((onCleanup) => {\n if (cap.value) {\n const mode = cap.value.getActiveInteractionMode();\n isPageExclusive.value = mode?.scope === 'page' && !!mode?.exclusive;\n\n const unsubscribe = cap.value.onModeChange(() => {\n if (!cap.value) return;\n const newMode = cap.value.getActiveInteractionMode();\n isPageExclusive.value = newMode?.scope === 'page' && !!newMode?.exclusive;\n });\n onCleanup(unsubscribe);\n }\n });\n\n return readonly(isPageExclusive);\n}\n","<script setup lang=\"ts\">\nimport { ref, watchEffect } from 'vue';\nimport { createPointerProvider } from '../../shared/utils';\nimport { useInteractionManagerCapability } from '../hooks';\n\nconst divRef = ref<HTMLDivElement | null>(null);\nconst { provides: cap } = useInteractionManagerCapability();\n\n// watchEffect automatically handles setup and teardown when capability or element is ready\nwatchEffect((onCleanup) => {\n if (cap.value && divRef.value) {\n const cleanup = createPointerProvider(cap.value, { type: 'global' }, divRef.value);\n onCleanup(cleanup);\n }\n});\n</script>\n\n<template>\n <div\n ref=\"divRef\"\n :style=\"{\n width: '100%',\n height: '100%',\n }\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, watchEffect, computed, StyleValue } from 'vue';\nimport { Position, restorePosition } from '@embedpdf/models';\nimport { createPointerProvider } from '../../shared/utils';\nimport { useInteractionManagerCapability, useIsPageExclusive } from '../hooks';\n\ninterface Props {\n pageIndex: number;\n pageWidth: number;\n pageHeight: number;\n rotation: number;\n scale: number;\n convertEventToPoint?: (event: PointerEvent, element: HTMLElement) => Position;\n}\n\nconst props = defineProps<Props>();\n\nconst divRef = ref<HTMLDivElement | null>(null);\nconst { provides: cap } = useInteractionManagerCapability();\nconst isPageExclusive = useIsPageExclusive();\n\nconst defaultConvertEventToPoint = computed(() => {\n return (event: PointerEvent, element: HTMLElement): Position => {\n const rect = element.getBoundingClientRect();\n const displayPoint = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n };\n return restorePosition(\n { width: props.pageWidth, height: props.pageHeight },\n displayPoint,\n props.rotation,\n props.scale,\n );\n };\n});\n\nwatchEffect((onCleanup) => {\n if (cap.value && divRef.value) {\n const cleanup = createPointerProvider(\n cap.value,\n { type: 'page', pageIndex: props.pageIndex },\n divRef.value,\n props.convertEventToPoint || defaultConvertEventToPoint.value,\n );\n onCleanup(cleanup);\n }\n});\n</script>\n\n<template>\n <div ref=\"divRef\">\n <slot />\n <div\n v-if=\"isPageExclusive\"\n :style=\"{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 10 }\"\n />\n </div>\n</template>\n"],"names":["_a","_createElementBlock","_renderSlot","_unref","_openBlock"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-interaction-manager",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -28,20 +28,20 @@
28
28
  }
29
29
  },
30
30
  "dependencies": {
31
- "@embedpdf/models": "1.0.18"
31
+ "@embedpdf/models": "1.0.20"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/react": "^18.2.0",
35
35
  "typescript": "^5.0.0",
36
- "@embedpdf/build": "1.0.0",
37
- "@embedpdf/core": "1.0.18"
36
+ "@embedpdf/core": "1.0.20",
37
+ "@embedpdf/build": "1.0.0"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "react": ">=16.8.0",
41
41
  "react-dom": ">=16.8.0",
42
42
  "preact": "^10.26.4",
43
43
  "vue": ">=3.2.0",
44
- "@embedpdf/core": "1.0.18"
44
+ "@embedpdf/core": "1.0.20"
45
45
  },
46
46
  "files": [
47
47
  "dist",