@embedpdf/utils 1.3.12 → 1.3.14
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.
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +7 -9
- package/dist/preact/index.js.map +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +7 -9
- package/dist/react/index.js.map +1 -1
- package/dist/vue/hooks/index.d.ts +2 -0
- package/dist/vue/hooks/use-double-press-props.d.ts +37 -0
- package/dist/vue/hooks/use-drag-resize.d.ts +18 -4
- package/dist/vue/hooks/use-interaction-handles.d.ts +34 -0
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.d.ts +1 -0
- package/dist/vue/index.js +275 -30
- package/dist/vue/index.js.map +1 -1
- package/dist/vue/utils/deep-to-raw.d.ts +1 -0
- package/dist/vue/utils/interaction-normalize.d.ts +11 -0
- package/package.json +2 -2
package/dist/preact/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("preact/jsx-runtime"),e=require("@embedpdf/utils"),i=require("preact"),n=require("preact/hooks"),s="onDblClick";class r{constructor(t,e){this.config=t,this.onUpdate=e,this.state="idle",this.startPoint=null,this.startElement=null,this.activeHandle=null,this.currentPosition=null,this.activeVertexIndex=null,this.startVertices=[],this.currentVertices=[],this.currentVertices=t.vertices||[]}updateConfig(t){this.config={...this.config,...t},this.currentVertices=t.vertices||[]}startDrag(t,e){this.state="dragging",this.startPoint={x:t,y:e},this.startElement={...this.config.element},this.currentPosition={...this.config.element},this.onUpdate({state:"start",transformData:{type:"move",changes:{rect:this.startElement}}})}startResize(t,e,i){this.state="resizing",this.activeHandle=t,this.startPoint={x:e,y:i},this.startElement={...this.config.element},this.currentPosition={...this.config.element},this.onUpdate({state:"start",transformData:{type:"resize",changes:{rect:this.startElement},metadata:{handle:this.activeHandle,maintainAspectRatio:this.config.maintainAspectRatio}}})}startVertexEdit(t,e,i){this.currentVertices=[...this.config.vertices??this.currentVertices],t<0||t>=this.currentVertices.length||(this.state="vertex-editing",this.activeVertexIndex=t,this.startPoint={x:e,y:i},this.startVertices=[...this.currentVertices],this.onUpdate({state:"start",transformData:{type:"vertex-edit",changes:{vertices:this.startVertices},metadata:{vertexIndex:t}}}))}move(t,e){if("idle"!==this.state&&this.startPoint)if("dragging"===this.state&&this.startElement){const i=this.calculateDelta(t,e),n=this.calculateDragPosition(i);this.currentPosition=n,this.onUpdate({state:"move",transformData:{type:"move",changes:{rect:n}}})}else if("resizing"===this.state&&this.activeHandle&&this.startElement){const i=this.calculateDelta(t,e),n=this.calculateResizePosition(i,this.activeHandle);this.currentPosition=n,this.onUpdate({state:"move",transformData:{type:"resize",changes:{rect:n},metadata:{handle:this.activeHandle,maintainAspectRatio:this.config.maintainAspectRatio}}})}else if("vertex-editing"===this.state&&null!==this.activeVertexIndex){const i=this.calculateVertexPosition(t,e);this.currentVertices=i,this.onUpdate({state:"move",transformData:{type:"vertex-edit",changes:{vertices:i},metadata:{vertexIndex:this.activeVertexIndex}}})}}end(){if("idle"===this.state)return;const t=this.state,e=this.activeHandle,i=this.activeVertexIndex;if("vertex-editing"===t)this.onUpdate({state:"end",transformData:{type:"vertex-edit",changes:{vertices:this.currentVertices},metadata:{vertexIndex:i||void 0}}});else{const i=this.getCurrentPosition();this.onUpdate({state:"end",transformData:{type:"dragging"===t?"move":"resize",changes:{rect:i},metadata:"dragging"===t?void 0:{handle:e||void 0,maintainAspectRatio:this.config.maintainAspectRatio}}})}this.reset()}cancel(){"idle"!==this.state&&("vertex-editing"===this.state?this.onUpdate({state:"end",transformData:{type:"vertex-edit",changes:{vertices:this.startVertices},metadata:{vertexIndex:this.activeVertexIndex||void 0}}}):this.startElement&&this.onUpdate({state:"end",transformData:{type:"dragging"===this.state?"move":"resize",changes:{rect:this.startElement},metadata:"dragging"===this.state?void 0:{handle:this.activeHandle||void 0,maintainAspectRatio:this.config.maintainAspectRatio}}}),this.reset())}reset(){this.state="idle",this.startPoint=null,this.startElement=null,this.activeHandle=null,this.currentPosition=null,this.activeVertexIndex=null,this.startVertices=[]}getCurrentPosition(){return this.currentPosition||this.config.element}calculateDelta(t,e){if(!this.startPoint)return{x:0,y:0};const i={x:t-this.startPoint.x,y:e-this.startPoint.y};return this.transformDelta(i)}transformDelta(t){const{pageRotation:e=0,scale:i=1}=this.config,n=e*Math.PI/2,s=Math.cos(n),r=Math.sin(n),a=t.x/i,o=t.y/i;return{x:s*a+r*o,y:-r*a+s*o}}clampPoint(t){var e;const i=null==(e=this.config.constraints)?void 0:e.boundingBox;return i?{x:Math.max(0,Math.min(t.x,i.width)),y:Math.max(0,Math.min(t.y,i.height))}:t}calculateVertexPosition(t,e){if(null===this.activeVertexIndex)return this.startVertices;const i=this.calculateDelta(t,e),n=[...this.startVertices],s=n[this.activeVertexIndex],r={x:s.x+i.x,y:s.y+i.y};return n[this.activeVertexIndex]=this.clampPoint(r),n}calculateDragPosition(t){if(!this.startElement)return this.config.element;const e={origin:{x:this.startElement.origin.x+t.x,y:this.startElement.origin.y+t.y},size:{width:this.startElement.size.width,height:this.startElement.size.height}};return this.applyConstraints(e)}calculateResizePosition(t,e){var i;if(!this.startElement)return this.config.element;let{origin:{x:n,y:s},size:{width:r,height:a}}=this.startElement;switch(e){case"se":r+=t.x,a+=t.y;break;case"sw":n+=t.x,r-=t.x,a+=t.y;break;case"ne":r+=t.x,s+=t.y,a-=t.y;break;case"nw":n+=t.x,r-=t.x,s+=t.y,a-=t.y;break;case"n":s+=t.y,a-=t.y;break;case"s":a+=t.y;break;case"e":r+=t.x;break;case"w":n+=t.x,r-=t.x}if(this.config.maintainAspectRatio&&this.startElement){const t=this.startElement.size.width/this.startElement.size.height;if(["n","s","e","w"].includes(e))if("n"===e||"s"===e){const e=a*t,i=e-r;r=e,n-=i/2}else{const i=r/t,o=i-a;a=i,"w"===e&&(n=this.startElement.origin.x+this.startElement.size.width-r),s-=o/2}else{Math.abs(r-this.startElement.size.width)>Math.abs(a-this.startElement.size.height)?a=r/t:r=a*t,e.includes("w")&&(n=this.startElement.origin.x+this.startElement.size.width-r),e.includes("n")&&(s=this.startElement.origin.y+this.startElement.size.height-a)}}const o=null==(i=this.config.constraints)?void 0:i.boundingBox;if(o)switch(e){case"e":r=Math.min(r,o.width-n);break;case"s":a=Math.min(a,o.height-s);break;case"se":r=Math.min(r,o.width-n),a=Math.min(a,o.height-s);break;case"w":n<0&&(r+=n,n=0);break;case"n":s<0&&(a+=s,s=0);break;case"sw":n<0&&(r+=n,n=0),a=Math.min(a,o.height-s);break;case"nw":n<0&&(r+=n,n=0),s<0&&(a+=s,s=0);break;case"ne":r=Math.min(r,o.width-n),s<0&&(a+=s,s=0)}return this.applyConstraints({origin:{x:n,y:s},size:{width:r,height:a}})}applyConstraints(t){const{constraints:e}=this.config;if(!e)return t;let{origin:{x:i,y:n},size:{width:s,height:r}}=t;return s=Math.max(e.minWidth||1,s),r=Math.max(e.minHeight||1,r),e.maxWidth&&(s=Math.min(e.maxWidth,s)),e.maxHeight&&(r=Math.min(e.maxHeight,r)),e.boundingBox&&(i=Math.max(0,Math.min(i,e.boundingBox.width-s)),n=Math.max(0,Math.min(n,e.boundingBox.height-r))),{origin:{x:i,y:n},size:{width:s,height:r}}}}function a(t,e){return"n"===t||"s"===t?"ns-resize":"e"===t||"w"===t?"ew-resize":e%2==0?{nw:"nwse-resize",ne:"nesw-resize",sw:"nesw-resize",se:"nwse-resize"}[t]:{nw:"nesw-resize",ne:"nwse-resize",sw:"nwse-resize",se:"nesw-resize"}[t]}function o(t,e,i){const n=-t/2;return"center"===i?n:"outside"===i?n-e:n+e}function c(t){const{onUpdate:e,enabled:i=!0,...s}=t,a=n.useRef(null),o=n.useRef(e);n.useEffect((()=>{o.current=e}),[e]),n.useEffect((()=>{a.current?a.current.updateConfig(s):a.current=new r(s,(t=>{var e;return null==(e=o.current)?void 0:e.call(o,t)}))}),[s.element,s.constraints,s.maintainAspectRatio,s.pageRotation,s.scale,s.vertices]);const c=n.useCallback((t=>{var e;i&&(t.preventDefault(),t.stopPropagation(),null==(e=a.current)||e.startDrag(t.clientX,t.clientY),t.currentTarget.setPointerCapture(t.pointerId))}),[i]),l=n.useCallback((t=>{var e;t.preventDefault(),t.stopPropagation(),null==(e=a.current)||e.move(t.clientX,t.clientY)}),[]),h=n.useCallback((t=>{var e,i,n;t.preventDefault(),t.stopPropagation(),null==(e=a.current)||e.end(),null==(n=(i=t.currentTarget).releasePointerCapture)||n.call(i,t.pointerId)}),[]),u=n.useCallback((t=>({onPointerDown:e=>{var n;i&&(e.preventDefault(),e.stopPropagation(),null==(n=a.current)||n.startResize(t,e.clientX,e.clientY),e.currentTarget.setPointerCapture(e.pointerId))},onPointerMove:l,onPointerUp:h,onPointerCancel:h})),[i,l,h]),d=n.useCallback((t=>({onPointerDown:e=>{var n;i&&(e.preventDefault(),e.stopPropagation(),null==(n=a.current)||n.startVertexEdit(t,e.clientX,e.clientY),e.currentTarget.setPointerCapture(e.pointerId))},onPointerMove:l,onPointerUp:h,onPointerCancel:h})),[i,l,h]);return{dragProps:i?{onPointerDown:c,onPointerMove:l,onPointerUp:h,onPointerCancel:h}:{},createResizeProps:u,createVertexProps:d}}exports.CounterRotate=function({children:s,...r}){const{rect:a,rotation:o}=r,{matrix:c,width:l,height:h}=e.getCounterRotation(a,o),u=n.useRef(null);n.useEffect((()=>{const t=u.current;if(!t)return;const e=t=>{t.stopPropagation(),t.preventDefault()},i=t=>{t.stopPropagation(),t.preventDefault()};return t.addEventListener("pointerdown",e,{capture:!0}),t.addEventListener("touchstart",i,{capture:!0}),()=>{t.removeEventListener("pointerdown",e,{capture:!0}),t.removeEventListener("touchstart",i,{capture:!0})}}),[]);const d={style:{position:"absolute",left:a.origin.x,top:a.origin.y,transform:c,transformOrigin:"0 0",width:l,height:h,pointerEvents:"none",zIndex:3},ref:t=>{u.current=t}};return t.jsx(i.Fragment,{children:s({menuWrapperProps:d,matrix:c,rect:{origin:{x:a.origin.x,y:a.origin.y},size:{width:l,height:h}}})})},exports.useDoublePressProps=function(t,{delay:e=300,tolerancePx:i=18}={}){const r=n.useRef({t:0,x:0,y:0}),a=n.useCallback((n=>{if(!t)return;if("mouse"===n.pointerType||!1===n.isPrimary)return;const s=performance.now(),a=n.clientX,o=n.clientY,c=s-r.current.t<=e,l=a-r.current.x,h=o-r.current.y;c&&l*l+h*h<=i*i&&(null==t||t(n)),r.current={t:s,x:a,y:o}}),[t,e,i]),o=n.useCallback((e=>{null==t||t(e)}),[t]);return t?{[s]:o,onPointerUpCapture:a}:{}},exports.useDragResize=c,exports.useInteractionHandles=function(t){const{controller:e,resizeUI:i,vertexUI:s,includeVertices:r=!1,handleAttrs:l,vertexAttrs:h}=t,{dragProps:u,createResizeProps:d,createVertexProps:g}=c(e);return{dragProps:u,resize:n.useMemo((()=>function(t,e={}){const{handleSize:i=8,spacing:n=1,offsetMode:s="outside",includeSides:r=!1,zIndex:c=3,rotationAwareCursor:l=!0}=e,h=(t.pageRotation??0)%4,u=t=>({[t]:o(i,n,s)});return[["nw",{...u("top"),...u("left")}],["ne",{...u("top"),...u("right")}],["sw",{...u("bottom"),...u("left")}],["se",{...u("bottom"),...u("right")}],...r?[["n",{...u("top"),left:`calc(50% - ${i/2}px)`}],["s",{...u("bottom"),left:`calc(50% - ${i/2}px)`}],["w",{...u("left"),top:`calc(50% - ${i/2}px)`}],["e",{...u("right"),top:`calc(50% - ${i/2}px)`}]]:[]].map((([t,e])=>({handle:t,style:{position:"absolute",width:i,height:i,borderRadius:"50%",zIndex:c,cursor:l?a(t,h):"default",touchAction:"none",...e},attrs:{"data-epdf-handle":t}})))}(e,i).map((t=>{var e;return{key:null==(e=t.attrs)?void 0:e["data-epdf-handle"],style:t.style,...d(t.handle),...t.attrs??{},...(null==l?void 0:l(t.handle))??{}}}))),[e.element.origin.x,e.element.origin.y,e.element.size.width,e.element.size.height,e.scale,e.pageRotation,e.maintainAspectRatio,null==i?void 0:i.handleSize,null==i?void 0:i.spacing,null==i?void 0:i.offsetMode,null==i?void 0:i.includeSides,null==i?void 0:i.zIndex,null==i?void 0:i.rotationAwareCursor,d,l]),vertices:n.useMemo((()=>{if(!r)return[];return function(t,e={},i){const{vertexSize:n=12,zIndex:s=4}=e,r=t.element,a=t.scale??1;return(i??t.vertices??[]).map(((t,e)=>({handle:"nw",style:{position:"absolute",left:(t.x-r.origin.x)*a-n/2,top:(t.y-r.origin.y)*a-n/2,width:n,height:n,borderRadius:"50%",cursor:"pointer",zIndex:s,touchAction:"none"},attrs:{"data-epdf-vertex":e}})))}(e,s,e.vertices).map(((t,e)=>({key:e,style:t.style,...g(e),...t.attrs??{},...(null==h?void 0:h(e))??{}})))}),[r,e.element.origin.x,e.element.origin.y,e.element.size.width,e.element.size.height,e.scale,e.vertices,null==s?void 0:s.vertexSize,null==s?void 0:s.zIndex,g,h])}};
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("preact/jsx-runtime"),e=require("@embedpdf/utils"),i=require("preact"),n=require("preact/hooks"),s="onDblClick";class r{constructor(t,e){this.config=t,this.onUpdate=e,this.state="idle",this.startPoint=null,this.startElement=null,this.activeHandle=null,this.currentPosition=null,this.activeVertexIndex=null,this.startVertices=[],this.currentVertices=[],this.currentVertices=t.vertices||[]}updateConfig(t){this.config={...this.config,...t},this.currentVertices=t.vertices||[]}startDrag(t,e){this.state="dragging",this.startPoint={x:t,y:e},this.startElement={...this.config.element},this.currentPosition={...this.config.element},this.onUpdate({state:"start",transformData:{type:"move",changes:{rect:this.startElement}}})}startResize(t,e,i){this.state="resizing",this.activeHandle=t,this.startPoint={x:e,y:i},this.startElement={...this.config.element},this.currentPosition={...this.config.element},this.onUpdate({state:"start",transformData:{type:"resize",changes:{rect:this.startElement},metadata:{handle:this.activeHandle,maintainAspectRatio:this.config.maintainAspectRatio}}})}startVertexEdit(t,e,i){this.currentVertices=[...this.config.vertices??this.currentVertices],t<0||t>=this.currentVertices.length||(this.state="vertex-editing",this.activeVertexIndex=t,this.startPoint={x:e,y:i},this.startVertices=[...this.currentVertices],this.onUpdate({state:"start",transformData:{type:"vertex-edit",changes:{vertices:this.startVertices},metadata:{vertexIndex:t}}}))}move(t,e){if("idle"!==this.state&&this.startPoint)if("dragging"===this.state&&this.startElement){const i=this.calculateDelta(t,e),n=this.calculateDragPosition(i);this.currentPosition=n,this.onUpdate({state:"move",transformData:{type:"move",changes:{rect:n}}})}else if("resizing"===this.state&&this.activeHandle&&this.startElement){const i=this.calculateDelta(t,e),n=this.calculateResizePosition(i,this.activeHandle);this.currentPosition=n,this.onUpdate({state:"move",transformData:{type:"resize",changes:{rect:n},metadata:{handle:this.activeHandle,maintainAspectRatio:this.config.maintainAspectRatio}}})}else if("vertex-editing"===this.state&&null!==this.activeVertexIndex){const i=this.calculateVertexPosition(t,e);this.currentVertices=i,this.onUpdate({state:"move",transformData:{type:"vertex-edit",changes:{vertices:i},metadata:{vertexIndex:this.activeVertexIndex}}})}}end(){if("idle"===this.state)return;const t=this.state,e=this.activeHandle,i=this.activeVertexIndex;if("vertex-editing"===t)this.onUpdate({state:"end",transformData:{type:"vertex-edit",changes:{vertices:this.currentVertices},metadata:{vertexIndex:i||void 0}}});else{const i=this.getCurrentPosition();this.onUpdate({state:"end",transformData:{type:"dragging"===t?"move":"resize",changes:{rect:i},metadata:"dragging"===t?void 0:{handle:e||void 0,maintainAspectRatio:this.config.maintainAspectRatio}}})}this.reset()}cancel(){"idle"!==this.state&&("vertex-editing"===this.state?this.onUpdate({state:"end",transformData:{type:"vertex-edit",changes:{vertices:this.startVertices},metadata:{vertexIndex:this.activeVertexIndex||void 0}}}):this.startElement&&this.onUpdate({state:"end",transformData:{type:"dragging"===this.state?"move":"resize",changes:{rect:this.startElement},metadata:"dragging"===this.state?void 0:{handle:this.activeHandle||void 0,maintainAspectRatio:this.config.maintainAspectRatio}}}),this.reset())}reset(){this.state="idle",this.startPoint=null,this.startElement=null,this.activeHandle=null,this.currentPosition=null,this.activeVertexIndex=null,this.startVertices=[]}getCurrentPosition(){return this.currentPosition||this.config.element}calculateDelta(t,e){if(!this.startPoint)return{x:0,y:0};const i={x:t-this.startPoint.x,y:e-this.startPoint.y};return this.transformDelta(i)}transformDelta(t){const{pageRotation:e=0,scale:i=1}=this.config,n=e*Math.PI/2,s=Math.cos(n),r=Math.sin(n),a=t.x/i,o=t.y/i;return{x:s*a+r*o,y:-r*a+s*o}}clampPoint(t){var e;const i=null==(e=this.config.constraints)?void 0:e.boundingBox;return i?{x:Math.max(0,Math.min(t.x,i.width)),y:Math.max(0,Math.min(t.y,i.height))}:t}calculateVertexPosition(t,e){if(null===this.activeVertexIndex)return this.startVertices;const i=this.calculateDelta(t,e),n=[...this.startVertices],s=n[this.activeVertexIndex],r={x:s.x+i.x,y:s.y+i.y};return n[this.activeVertexIndex]=this.clampPoint(r),n}calculateDragPosition(t){if(!this.startElement)return this.config.element;const e={origin:{x:this.startElement.origin.x+t.x,y:this.startElement.origin.y+t.y},size:{width:this.startElement.size.width,height:this.startElement.size.height}};return this.applyConstraints(e)}calculateResizePosition(t,e){var i;if(!this.startElement)return this.config.element;let{origin:{x:n,y:s},size:{width:r,height:a}}=this.startElement;switch(e){case"se":r+=t.x,a+=t.y;break;case"sw":n+=t.x,r-=t.x,a+=t.y;break;case"ne":r+=t.x,s+=t.y,a-=t.y;break;case"nw":n+=t.x,r-=t.x,s+=t.y,a-=t.y;break;case"n":s+=t.y,a-=t.y;break;case"s":a+=t.y;break;case"e":r+=t.x;break;case"w":n+=t.x,r-=t.x}if(this.config.maintainAspectRatio&&this.startElement){const t=this.startElement.size.width/this.startElement.size.height;if(["n","s","e","w"].includes(e))if("n"===e||"s"===e){const e=a*t,i=e-r;r=e,n-=i/2}else{const i=r/t,o=i-a;a=i,"w"===e&&(n=this.startElement.origin.x+this.startElement.size.width-r),s-=o/2}else{Math.abs(r-this.startElement.size.width)>Math.abs(a-this.startElement.size.height)?a=r/t:r=a*t,e.includes("w")&&(n=this.startElement.origin.x+this.startElement.size.width-r),e.includes("n")&&(s=this.startElement.origin.y+this.startElement.size.height-a)}}const o=null==(i=this.config.constraints)?void 0:i.boundingBox;if(o)switch(e){case"e":r=Math.min(r,o.width-n);break;case"s":a=Math.min(a,o.height-s);break;case"se":r=Math.min(r,o.width-n),a=Math.min(a,o.height-s);break;case"w":n<0&&(r+=n,n=0);break;case"n":s<0&&(a+=s,s=0);break;case"sw":n<0&&(r+=n,n=0),a=Math.min(a,o.height-s);break;case"nw":n<0&&(r+=n,n=0),s<0&&(a+=s,s=0);break;case"ne":r=Math.min(r,o.width-n),s<0&&(a+=s,s=0)}return this.applyConstraints({origin:{x:n,y:s},size:{width:r,height:a}})}applyConstraints(t){const{constraints:e}=this.config;if(!e)return t;let{origin:{x:i,y:n},size:{width:s,height:r}}=t;return s=Math.max(e.minWidth||1,s),r=Math.max(e.minHeight||1,r),e.maxWidth&&(s=Math.min(e.maxWidth,s)),e.maxHeight&&(r=Math.min(e.maxHeight,r)),e.boundingBox&&(i=Math.max(0,Math.min(i,e.boundingBox.width-s)),n=Math.max(0,Math.min(n,e.boundingBox.height-r))),{origin:{x:i,y:n},size:{width:s,height:r}}}}function a(t,e){return"n"===t||"s"===t?"ns-resize":"e"===t||"w"===t?"ew-resize":e%2==0?{nw:"nwse-resize",ne:"nesw-resize",sw:"nesw-resize",se:"nwse-resize"}[t]:{nw:"nesw-resize",ne:"nwse-resize",sw:"nwse-resize",se:"nesw-resize"}[t]}function o(t,e,i){const n=-t/2;return"center"===i?n:"outside"===i?n-e:n+e}function c(t){const{onUpdate:e,enabled:i=!0,...s}=t,a=n.useRef(null),o=n.useRef(e);n.useEffect((()=>{o.current=e}),[e]),n.useEffect((()=>{a.current?a.current.updateConfig(s):a.current=new r(s,(t=>{var e;return null==(e=o.current)?void 0:e.call(o,t)}))}),[s.element,s.constraints,s.maintainAspectRatio,s.pageRotation,s.scale,s.vertices]);const c=n.useCallback((t=>{var e;i&&(t.preventDefault(),t.stopPropagation(),null==(e=a.current)||e.startDrag(t.clientX,t.clientY),t.currentTarget.setPointerCapture(t.pointerId))}),[i]),l=n.useCallback((t=>{var e;t.preventDefault(),t.stopPropagation(),null==(e=a.current)||e.move(t.clientX,t.clientY)}),[]),h=n.useCallback((t=>{var e,i,n;t.preventDefault(),t.stopPropagation(),null==(e=a.current)||e.end(),null==(n=(i=t.currentTarget).releasePointerCapture)||n.call(i,t.pointerId)}),[]),u=n.useCallback((t=>({onPointerDown:e=>{var n;i&&(e.preventDefault(),e.stopPropagation(),null==(n=a.current)||n.startResize(t,e.clientX,e.clientY),e.currentTarget.setPointerCapture(e.pointerId))},onPointerMove:l,onPointerUp:h,onPointerCancel:h})),[i,l,h]),d=n.useCallback((t=>({onPointerDown:e=>{var n;i&&(e.preventDefault(),e.stopPropagation(),null==(n=a.current)||n.startVertexEdit(t,e.clientX,e.clientY),e.currentTarget.setPointerCapture(e.pointerId))},onPointerMove:l,onPointerUp:h,onPointerCancel:h})),[i,l,h]);return{dragProps:i?{onPointerDown:c,onPointerMove:l,onPointerUp:h,onPointerCancel:h}:{},createResizeProps:u,createVertexProps:d}}exports.CounterRotate=function({children:s,...r}){const{rect:a,rotation:o}=r,{matrix:c,width:l,height:h}=e.getCounterRotation(a,o),u=n.useRef(null);n.useEffect((()=>{const t=u.current;if(!t)return;const e=t=>{t.stopPropagation()},i=t=>{t.stopPropagation()};return t.addEventListener("pointerdown",e,{capture:!0}),t.addEventListener("touchstart",i,{capture:!0}),()=>{t.removeEventListener("pointerdown",e,{capture:!0}),t.removeEventListener("touchstart",i,{capture:!0})}}),[]);const d={style:{position:"absolute",left:a.origin.x,top:a.origin.y,transform:c,transformOrigin:"0 0",width:l,height:h,pointerEvents:"none",zIndex:3},ref:t=>{u.current=t}};return t.jsx(i.Fragment,{children:s({menuWrapperProps:d,matrix:c,rect:{origin:{x:a.origin.x,y:a.origin.y},size:{width:l,height:h}}})})},exports.useDoublePressProps=function(t,{delay:e=300,tolerancePx:i=18}={}){const r=n.useRef({t:0,x:0,y:0}),a=n.useCallback((n=>{if(!t)return;if("mouse"===n.pointerType||!1===n.isPrimary)return;const s=performance.now(),a=n.clientX,o=n.clientY,c=s-r.current.t<=e,l=a-r.current.x,h=o-r.current.y;c&&l*l+h*h<=i*i&&(null==t||t(n)),r.current={t:s,x:a,y:o}}),[t,e,i]),o=n.useCallback((e=>{null==t||t(e)}),[t]);return t?{[s]:o,onPointerUpCapture:a}:{}},exports.useDragResize=c,exports.useInteractionHandles=function(t){const{controller:e,resizeUI:i,vertexUI:s,includeVertices:r=!1,handleAttrs:l,vertexAttrs:h}=t,{dragProps:u,createResizeProps:d,createVertexProps:g}=c(e);return{dragProps:u,resize:n.useMemo((()=>function(t,e={}){const{handleSize:i=8,spacing:n=1,offsetMode:s="outside",includeSides:r=!1,zIndex:c=3,rotationAwareCursor:l=!0}=e,h=(t.pageRotation??0)%4,u=t=>({[t]:o(i,n,s)+"px"});return[["nw",{...u("top"),...u("left")}],["ne",{...u("top"),...u("right")}],["sw",{...u("bottom"),...u("left")}],["se",{...u("bottom"),...u("right")}],...r?[["n",{...u("top"),left:`calc(50% - ${i/2}px)`}],["s",{...u("bottom"),left:`calc(50% - ${i/2}px)`}],["w",{...u("left"),top:`calc(50% - ${i/2}px)`}],["e",{...u("right"),top:`calc(50% - ${i/2}px)`}]]:[]].map((([t,e])=>({handle:t,style:{position:"absolute",width:i+"px",height:i+"px",borderRadius:"50%",zIndex:c,cursor:l?a(t,h):"default",touchAction:"none",...e},attrs:{"data-epdf-handle":t}})))}(e,i).map((t=>{var e;return{key:null==(e=t.attrs)?void 0:e["data-epdf-handle"],style:t.style,...d(t.handle),...t.attrs??{},...(null==l?void 0:l(t.handle))??{}}}))),[e.element.origin.x,e.element.origin.y,e.element.size.width,e.element.size.height,e.scale,e.pageRotation,e.maintainAspectRatio,null==i?void 0:i.handleSize,null==i?void 0:i.spacing,null==i?void 0:i.offsetMode,null==i?void 0:i.includeSides,null==i?void 0:i.zIndex,null==i?void 0:i.rotationAwareCursor,d,l]),vertices:n.useMemo((()=>{if(!r)return[];return function(t,e={},i){const{vertexSize:n=12,zIndex:s=4}=e,r=t.element,a=t.scale??1;return(i??t.vertices??[]).map(((t,e)=>({handle:"nw",style:{position:"absolute",left:(t.x-r.origin.x)*a-n/2+"px",top:(t.y-r.origin.y)*a-n/2+"px",width:n+"px",height:n+"px",borderRadius:"50%",cursor:"pointer",zIndex:s,touchAction:"none"},attrs:{"data-epdf-vertex":e}})))}(e,s,e.vertices).map(((t,e)=>({key:e,style:t.style,...g(e),...t.attrs??{},...(null==h?void 0:h(e))??{}})))}),[r,e.element.origin.x,e.element.origin.y,e.element.size.width,e.element.size.height,e.scale,e.vertices,null==s?void 0:s.vertexSize,null==s?void 0:s.zIndex,g,h])}};
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../src/preact/adapter.ts","../../src/shared/plugin-interaction-primitives/drag-resize-controller.ts","../../src/shared/plugin-interaction-primitives/utils.ts","../../src/shared/hooks/use-drag-resize.ts","../../src/shared/components/counter-rotate-container.tsx","../../src/shared/hooks/use-double-press-props.ts","../../src/shared/hooks/use-interaction-handles.ts"],"sourcesContent":["import { createContext, JSX, Fragment, FunctionComponent } from 'preact';\nexport { useEffect, useRef, useState, useCallback, useMemo, useContext } from 'preact/hooks';\nexport type { ComponentChildren as ReactNode, JSX } from 'preact';\n\nexport { createContext, Fragment };\n\nexport type CSSProperties = import('preact').JSX.CSSProperties;\nexport type HTMLAttributes<T = any> = import('preact').JSX.HTMLAttributes<\n T extends EventTarget ? T : never\n>;\n\nexport type MouseEvent<T = Element> = JSX.TargetedMouseEvent<T extends EventTarget ? T : never>;\nexport type PointerEvent<T = Element> = JSX.TargetedPointerEvent<T extends EventTarget ? T : never>;\nexport type ChangeEvent<T = Element> = JSX.TargetedInputEvent<T extends EventTarget ? T : never>;\nexport type TouchEvent<T = Element> = JSX.TargetedTouchEvent<T extends EventTarget ? T : never>;\nexport type ComponentType = FunctionComponent;\n\nexport const dblClickProp = 'onDblClick' as const;\n","import { Position, Rect } from '@embedpdf/models';\n\nexport interface DragResizeConfig {\n element: Rect;\n vertices?: Position[];\n constraints?: {\n minWidth?: number;\n minHeight?: number;\n maxWidth?: number;\n maxHeight?: number;\n boundingBox?: { width: number; height: number }; // page bounds\n };\n maintainAspectRatio?: boolean;\n pageRotation?: number;\n scale?: number;\n}\n\nexport type InteractionState = 'idle' | 'dragging' | 'resizing' | 'vertex-editing';\nexport type ResizeHandle = 'nw' | 'ne' | 'sw' | 'se' | 'n' | 'e' | 's' | 'w';\n\nexport interface TransformData {\n type: 'move' | 'resize' | 'vertex-edit';\n changes: {\n rect?: Rect;\n vertices?: Position[];\n };\n metadata?: {\n handle?: ResizeHandle;\n vertexIndex?: number;\n maintainAspectRatio?: boolean;\n };\n}\n\nexport interface InteractionEvent {\n state: 'start' | 'move' | 'end';\n transformData?: TransformData;\n}\n\n/**\n * Pure geometric controller that manages drag/resize/vertex-edit logic.\n */\nexport class DragResizeController {\n private state: InteractionState = 'idle';\n private startPoint: Position | null = null;\n private startElement: Rect | null = null;\n private activeHandle: ResizeHandle | null = null;\n private currentPosition: Rect | null = null;\n\n // Vertex editing state - pure geometric\n private activeVertexIndex: number | null = null;\n private startVertices: Position[] = [];\n private currentVertices: Position[] = [];\n\n constructor(\n private config: DragResizeConfig,\n private onUpdate: (event: InteractionEvent) => void,\n ) {\n this.currentVertices = config.vertices || [];\n }\n\n updateConfig(config: Partial<DragResizeConfig>) {\n this.config = { ...this.config, ...config };\n this.currentVertices = config.vertices || [];\n }\n\n startDrag(clientX: number, clientY: number) {\n this.state = 'dragging';\n this.startPoint = { x: clientX, y: clientY };\n this.startElement = { ...this.config.element };\n this.currentPosition = { ...this.config.element };\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'move',\n changes: {\n rect: this.startElement,\n },\n },\n });\n }\n\n startResize(handle: ResizeHandle, clientX: number, clientY: number) {\n this.state = 'resizing';\n this.activeHandle = handle;\n this.startPoint = { x: clientX, y: clientY };\n this.startElement = { ...this.config.element };\n this.currentPosition = { ...this.config.element };\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'resize',\n changes: {\n rect: this.startElement,\n },\n metadata: {\n handle: this.activeHandle,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n startVertexEdit(vertexIndex: number, clientX: number, clientY: number) {\n // Refresh vertices from latest config before validating index\n this.currentVertices = [...(this.config.vertices ?? this.currentVertices)];\n if (vertexIndex < 0 || vertexIndex >= this.currentVertices.length) return;\n\n this.state = 'vertex-editing';\n this.activeVertexIndex = vertexIndex;\n this.startPoint = { x: clientX, y: clientY };\n this.startVertices = [...this.currentVertices];\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.startVertices,\n },\n metadata: {\n vertexIndex,\n },\n },\n });\n }\n\n move(clientX: number, clientY: number) {\n if (this.state === 'idle' || !this.startPoint) return;\n\n if (this.state === 'dragging' && this.startElement) {\n const delta = this.calculateDelta(clientX, clientY);\n const position = this.calculateDragPosition(delta);\n this.currentPosition = position;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'move',\n changes: {\n rect: position,\n },\n },\n });\n } else if (this.state === 'resizing' && this.activeHandle && this.startElement) {\n const delta = this.calculateDelta(clientX, clientY);\n const position = this.calculateResizePosition(delta, this.activeHandle);\n this.currentPosition = position;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'resize',\n changes: {\n rect: position,\n },\n metadata: {\n handle: this.activeHandle,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n } else if (this.state === 'vertex-editing' && this.activeVertexIndex !== null) {\n const vertices = this.calculateVertexPosition(clientX, clientY);\n this.currentVertices = vertices;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices,\n },\n metadata: {\n vertexIndex: this.activeVertexIndex,\n },\n },\n });\n }\n }\n\n end() {\n if (this.state === 'idle') return;\n\n const wasState = this.state;\n const handle = this.activeHandle;\n const vertexIndex = this.activeVertexIndex;\n\n if (wasState === 'vertex-editing') {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.currentVertices,\n },\n metadata: {\n vertexIndex: vertexIndex || undefined,\n },\n },\n });\n } else {\n const finalPosition = this.getCurrentPosition();\n this.onUpdate({\n state: 'end',\n transformData: {\n type: wasState === 'dragging' ? 'move' : 'resize',\n changes: {\n rect: finalPosition,\n },\n metadata:\n wasState === 'dragging'\n ? undefined\n : {\n handle: handle || undefined,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n this.reset();\n }\n\n cancel() {\n if (this.state === 'idle') return;\n\n if (this.state === 'vertex-editing') {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.startVertices,\n },\n metadata: {\n vertexIndex: this.activeVertexIndex || undefined,\n },\n },\n });\n } else if (this.startElement) {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: this.state === 'dragging' ? 'move' : 'resize',\n changes: {\n rect: this.startElement,\n },\n metadata:\n this.state === 'dragging'\n ? undefined\n : {\n handle: this.activeHandle || undefined,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n this.reset();\n }\n\n private reset() {\n this.state = 'idle';\n this.startPoint = null;\n this.startElement = null;\n this.activeHandle = null;\n this.currentPosition = null;\n this.activeVertexIndex = null;\n this.startVertices = [];\n }\n\n private getCurrentPosition() {\n return this.currentPosition || this.config.element;\n }\n\n private calculateDelta(clientX: number, clientY: number): Position {\n if (!this.startPoint) return { x: 0, y: 0 };\n\n const rawDelta: Position = {\n x: clientX - this.startPoint.x,\n y: clientY - this.startPoint.y,\n };\n\n return this.transformDelta(rawDelta);\n }\n\n private transformDelta(delta: Position): Position {\n const { pageRotation = 0, scale = 1 } = this.config;\n\n const rad = (pageRotation * Math.PI) / 2;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n\n const scaledX = delta.x / scale;\n const scaledY = delta.y / scale;\n\n return {\n x: cos * scaledX + sin * scaledY,\n y: -sin * scaledX + cos * scaledY,\n };\n }\n\n private clampPoint(p: Position): Position {\n const bbox = this.config.constraints?.boundingBox;\n if (!bbox) return p;\n return {\n x: Math.max(0, Math.min(p.x, bbox.width)),\n y: Math.max(0, Math.min(p.y, bbox.height)),\n };\n }\n\n private calculateVertexPosition(clientX: number, clientY: number): Position[] {\n if (this.activeVertexIndex === null) return this.startVertices;\n\n const delta = this.calculateDelta(clientX, clientY);\n const newVertices = [...this.startVertices];\n const currentVertex = newVertices[this.activeVertexIndex];\n\n const moved = {\n x: currentVertex.x + delta.x,\n y: currentVertex.y + delta.y,\n };\n newVertices[this.activeVertexIndex] = this.clampPoint(moved);\n\n return newVertices;\n }\n\n private calculateDragPosition(delta: Position): Rect {\n if (!this.startElement) return this.config.element;\n\n const position: Rect = {\n origin: {\n x: this.startElement.origin.x + delta.x,\n y: this.startElement.origin.y + delta.y,\n },\n size: {\n width: this.startElement.size.width,\n height: this.startElement.size.height,\n },\n };\n\n return this.applyConstraints(position);\n }\n\n private calculateResizePosition(delta: Position, handle: ResizeHandle): Rect {\n if (!this.startElement) return this.config.element;\n\n let {\n origin: { x, y },\n size: { width, height },\n } = this.startElement;\n\n switch (handle) {\n case 'se':\n width += delta.x;\n height += delta.y;\n break;\n case 'sw':\n x += delta.x;\n width -= delta.x;\n height += delta.y;\n break;\n case 'ne':\n width += delta.x;\n y += delta.y;\n height -= delta.y;\n break;\n case 'nw':\n x += delta.x;\n width -= delta.x;\n y += delta.y;\n height -= delta.y;\n break;\n case 'n':\n y += delta.y;\n height -= delta.y;\n break;\n case 's':\n height += delta.y;\n break;\n case 'e':\n width += delta.x;\n break;\n case 'w':\n x += delta.x;\n width -= delta.x;\n break;\n }\n\n // Maintain aspect ratio if needed\n if (this.config.maintainAspectRatio && this.startElement) {\n const aspectRatio = this.startElement.size.width / this.startElement.size.height;\n\n if (['n', 's', 'e', 'w'].includes(handle)) {\n if (handle === 'n' || handle === 's') {\n const newWidth = height * aspectRatio;\n const widthDiff = newWidth - width;\n width = newWidth;\n x -= widthDiff / 2;\n } else {\n const newHeight = width / aspectRatio;\n const heightDiff = newHeight - height;\n height = newHeight;\n if (handle === 'w') {\n x = this.startElement.origin.x + this.startElement.size.width - width;\n }\n y -= heightDiff / 2;\n }\n } else {\n const widthChange = Math.abs(width - this.startElement.size.width);\n const heightChange = Math.abs(height - this.startElement.size.height);\n if (widthChange > heightChange) {\n height = width / aspectRatio;\n } else {\n width = height * aspectRatio;\n }\n if (handle.includes('w')) {\n x = this.startElement.origin.x + this.startElement.size.width - width;\n }\n if (handle.includes('n')) {\n y = this.startElement.origin.y + this.startElement.size.height - height;\n }\n }\n }\n\n // Handle-aware bounding box clamping to avoid shifting opposite edge\n const bbox = this.config.constraints?.boundingBox;\n if (bbox) {\n switch (handle) {\n case 'e':\n width = Math.min(width, bbox.width - x);\n break;\n case 's':\n height = Math.min(height, bbox.height - y);\n break;\n case 'se':\n width = Math.min(width, bbox.width - x);\n height = Math.min(height, bbox.height - y);\n break;\n case 'w':\n if (x < 0) {\n width += x;\n x = 0;\n }\n break;\n case 'n':\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n case 'sw':\n if (x < 0) {\n width += x;\n x = 0;\n }\n height = Math.min(height, bbox.height - y);\n break;\n case 'nw':\n if (x < 0) {\n width += x;\n x = 0;\n }\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n case 'ne':\n width = Math.min(width, bbox.width - x);\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n }\n }\n\n return this.applyConstraints({ origin: { x, y }, size: { width, height } });\n }\n\n private applyConstraints(position: Rect): Rect {\n const { constraints } = this.config;\n if (!constraints) return position;\n\n let {\n origin: { x, y },\n size: { width, height },\n } = position;\n\n // Apply size constraints\n width = Math.max(constraints.minWidth || 1, width);\n height = Math.max(constraints.minHeight || 1, height);\n\n if (constraints.maxWidth) width = Math.min(constraints.maxWidth, width);\n if (constraints.maxHeight) height = Math.min(constraints.maxHeight, height);\n\n // Apply bounding box constraints\n if (constraints.boundingBox) {\n x = Math.max(0, Math.min(x, constraints.boundingBox.width - width));\n y = Math.max(0, Math.min(y, constraints.boundingBox.height - height));\n }\n\n return { origin: { x, y }, size: { width, height } };\n }\n}\n","import type { Position, Rect } from '@embedpdf/models';\nimport type { ResizeHandle, DragResizeConfig } from './drag-resize-controller';\n\nexport type QuarterTurns = 0 | 1 | 2 | 3;\n\nexport interface ResizeUI {\n handleSize?: number; // px (default 8)\n spacing?: number; // px distance from the box edge (default 1)\n offsetMode?: 'outside' | 'inside' | 'center'; // default 'outside'\n includeSides?: boolean; // default false\n zIndex?: number; // default 3\n rotationAwareCursor?: boolean; // default true\n}\n\nexport interface VertexUI {\n vertexSize?: number; // px (default 12)\n zIndex?: number; // default 4\n}\n\nexport interface HandleDescriptor {\n handle: ResizeHandle;\n style: Record<string, number | string>;\n attrs?: Record<string, any>;\n}\n\nfunction diagonalCursor(handle: ResizeHandle, rot: QuarterTurns): string {\n // Standard cursors; diagonals flip on odd quarter-turns\n const diag0: Record<'nw' | 'ne' | 'sw' | 'se', string> = {\n nw: 'nwse-resize',\n ne: 'nesw-resize',\n sw: 'nesw-resize',\n se: 'nwse-resize',\n };\n if (handle === 'n' || handle === 's') return 'ns-resize';\n if (handle === 'e' || handle === 'w') return 'ew-resize';\n if (rot % 2 === 0) return diag0[handle as 'nw' | 'ne' | 'sw' | 'se'];\n return { nw: 'nesw-resize', ne: 'nwse-resize', sw: 'nwse-resize', se: 'nesw-resize' }[\n handle as 'nw' | 'ne' | 'sw' | 'se'\n ]!;\n}\n\nfunction edgeOffset(k: number, spacing: number, mode: 'outside' | 'inside' | 'center') {\n // Base puts the handle centered on the edge\n const base = -k / 2;\n if (mode === 'center') return base;\n // outside moves further out (more negative), inside moves in (less negative)\n return mode === 'outside' ? base - spacing : base + spacing;\n}\n\nexport function describeResizeFromConfig(\n cfg: DragResizeConfig,\n ui: ResizeUI = {},\n): HandleDescriptor[] {\n const {\n handleSize = 8,\n spacing = 1,\n offsetMode = 'outside',\n includeSides = false,\n zIndex = 3,\n rotationAwareCursor = true,\n } = ui;\n\n const rotation = ((cfg.pageRotation ?? 0) % 4) as QuarterTurns;\n\n const off = (edge: 'top' | 'right' | 'bottom' | 'left') => ({\n [edge]: edgeOffset(handleSize, spacing, offsetMode),\n });\n\n const corners: Array<[ResizeHandle, Record<string, number | string>]> = [\n ['nw', { ...off('top'), ...off('left') }],\n ['ne', { ...off('top'), ...off('right') }],\n ['sw', { ...off('bottom'), ...off('left') }],\n ['se', { ...off('bottom'), ...off('right') }],\n ];\n const sides: Array<[ResizeHandle, Record<string, number | string>]> = includeSides\n ? [\n ['n', { ...off('top'), left: `calc(50% - ${handleSize / 2}px)` }],\n ['s', { ...off('bottom'), left: `calc(50% - ${handleSize / 2}px)` }],\n ['w', { ...off('left'), top: `calc(50% - ${handleSize / 2}px)` }],\n ['e', { ...off('right'), top: `calc(50% - ${handleSize / 2}px)` }],\n ]\n : [];\n\n const all = [...corners, ...sides];\n\n return all.map(([handle, pos]) => ({\n handle,\n style: {\n position: 'absolute',\n width: handleSize,\n height: handleSize,\n borderRadius: '50%',\n zIndex,\n cursor: rotationAwareCursor ? diagonalCursor(handle, rotation) : 'default',\n touchAction: 'none',\n ...(pos as any),\n },\n attrs: { 'data-epdf-handle': handle },\n }));\n}\n\nexport function describeVerticesFromConfig(\n cfg: DragResizeConfig,\n ui: VertexUI = {},\n liveVertices?: Position[],\n): HandleDescriptor[] {\n const { vertexSize = 12, zIndex = 4 } = ui;\n const rect: Rect = cfg.element;\n const scale = cfg.scale ?? 1;\n const verts = liveVertices ?? cfg.vertices ?? [];\n\n return verts.map((v, i) => {\n const left = (v.x - rect.origin.x) * scale - vertexSize / 2;\n const top = (v.y - rect.origin.y) * scale - vertexSize / 2;\n return {\n handle: 'nw', // not used; kept for type\n style: {\n position: 'absolute',\n left,\n top,\n width: vertexSize,\n height: vertexSize,\n borderRadius: '50%',\n cursor: 'pointer',\n zIndex,\n touchAction: 'none',\n },\n attrs: { 'data-epdf-vertex': i },\n };\n });\n}\n","import { useRef, useCallback, useEffect, PointerEvent } from '@framework';\nimport {\n DragResizeController,\n DragResizeConfig,\n InteractionEvent,\n ResizeHandle,\n} from '../plugin-interaction-primitives';\n\nexport interface UseDragResizeOptions extends DragResizeConfig {\n onUpdate?: (event: InteractionEvent) => void;\n enabled?: boolean;\n}\n\nexport interface ResizeHandleEventProps {\n onPointerDown: (e: PointerEvent) => void;\n onPointerMove: (e: PointerEvent) => void;\n onPointerUp: (e: PointerEvent) => void;\n onPointerCancel: (e: PointerEvent) => void;\n}\n\nexport function useDragResize(options: UseDragResizeOptions) {\n const { onUpdate, enabled = true, ...config } = options;\n const controllerRef = useRef<DragResizeController | null>(null);\n const onUpdateRef = useRef<typeof onUpdate>(onUpdate);\n\n useEffect(() => {\n onUpdateRef.current = onUpdate;\n }, [onUpdate]);\n\n // Initialize or update controller\n useEffect(() => {\n if (!controllerRef.current) {\n controllerRef.current = new DragResizeController(config, (event) =>\n onUpdateRef.current?.(event),\n );\n } else {\n controllerRef.current.updateConfig(config);\n }\n }, [\n config.element,\n config.constraints,\n config.maintainAspectRatio,\n config.pageRotation,\n config.scale,\n config.vertices,\n ]);\n\n const handleDragStart = useCallback(\n (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startDrag(e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n [enabled],\n );\n\n const handleMove = useCallback((e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.move(e.clientX, e.clientY);\n }, []);\n\n const handleEnd = useCallback((e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.end();\n (e.currentTarget as HTMLElement).releasePointerCapture?.(e.pointerId);\n }, []);\n\n const createResizeHandler = useCallback(\n (handle: ResizeHandle): ResizeHandleEventProps => ({\n onPointerDown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startResize(handle, e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }),\n [enabled, handleMove, handleEnd],\n );\n\n const createVertexHandler = useCallback(\n (vertexIndex: number): ResizeHandleEventProps => ({\n onPointerDown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startVertexEdit(vertexIndex, e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }),\n [enabled, handleMove, handleEnd],\n );\n\n return {\n dragProps: enabled\n ? {\n onPointerDown: handleDragStart,\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }\n : {},\n createResizeProps: createResizeHandler,\n createVertexProps: createVertexHandler,\n };\n}\n","import { Rect, Rotation } from '@embedpdf/models';\nimport { getCounterRotation } from '@embedpdf/utils';\nimport { ReactNode, CSSProperties, Fragment, useRef, useEffect } from '@framework';\n\ninterface CounterRotateProps {\n rect: Rect;\n rotation: Rotation;\n}\n\nexport interface MenuWrapperProps {\n style: CSSProperties;\n ref: (el: HTMLDivElement | null) => void;\n}\n\ninterface CounterRotateComponentProps extends CounterRotateProps {\n children: (props: {\n matrix: string;\n rect: Rect;\n menuWrapperProps: MenuWrapperProps;\n }) => ReactNode;\n}\n\nexport function CounterRotate({ children, ...props }: CounterRotateComponentProps) {\n const { rect, rotation } = props;\n const { matrix, width, height } = getCounterRotation(rect, rotation);\n const elementRef = useRef<HTMLDivElement | null>(null);\n\n // Use native event listeners with capture phase to prevent text selection\n useEffect(() => {\n const element = elementRef.current;\n if (!element) return;\n\n const handlePointerDown = (e: Event) => {\n e.stopPropagation();\n e.preventDefault();\n };\n\n const handleTouchStart = (e: Event) => {\n e.stopPropagation();\n e.preventDefault();\n };\n\n // Use capture phase to intercept before synthetic events\n element.addEventListener('pointerdown', handlePointerDown, { capture: true });\n element.addEventListener('touchstart', handleTouchStart, { capture: true });\n\n return () => {\n element.removeEventListener('pointerdown', handlePointerDown, { capture: true });\n element.removeEventListener('touchstart', handleTouchStart, { capture: true });\n };\n }, []);\n\n const menuWrapperStyle: CSSProperties = {\n position: 'absolute',\n left: rect.origin.x,\n top: rect.origin.y,\n transform: matrix,\n transformOrigin: '0 0',\n width: width,\n height: height,\n pointerEvents: 'none',\n zIndex: 3,\n };\n\n const menuWrapperProps: MenuWrapperProps = {\n style: menuWrapperStyle,\n ref: (el: HTMLDivElement | null) => {\n elementRef.current = el;\n },\n };\n\n return (\n <Fragment>\n {children({\n menuWrapperProps,\n matrix,\n rect: {\n origin: { x: rect.origin.x, y: rect.origin.y },\n size: { width: width, height: height },\n },\n })}\n </Fragment>\n );\n}\n","import { useRef, useCallback, dblClickProp } from '@framework';\nimport type { PointerEvent } from '@framework';\n\ntype DoublePressOptions = {\n delay?: number; // ms between taps\n tolerancePx?: number; // spatial tolerance\n};\n\ntype DoubleHandler<T extends Element> = ((e: PointerEvent<T> | MouseEvent) => void) | undefined;\n\ntype DoubleProps<K extends string> = Partial<Record<K, (e: any) => void>> & {\n onPointerUp?: (e: any) => void;\n};\n\nexport function useDoublePressProps<\n T extends Element = Element,\n K extends string = typeof dblClickProp,\n>(\n onDouble?: DoubleHandler<T>,\n { delay = 300, tolerancePx = 18 }: DoublePressOptions = {},\n): DoubleProps<K> {\n const last = useRef({ t: 0, x: 0, y: 0 });\n\n const handlePointerUp = useCallback(\n (e: any) => {\n if (!onDouble) return;\n\n // Ignore mouse (it will use native dblclick),\n // and ignore non-primary pointers (multi-touch, etc.)\n if (e.pointerType === 'mouse' || e.isPrimary === false) return;\n\n const now = performance.now();\n const x = e.clientX as number;\n const y = e.clientY as number;\n\n const withinTime = now - last.current.t <= delay;\n const dx = x - last.current.x;\n const dy = y - last.current.y;\n const withinDist = dx * dx + dy * dy <= tolerancePx * tolerancePx;\n\n if (withinTime && withinDist) onDouble?.(e as PointerEvent<T>);\n\n last.current = { t: now, x, y };\n },\n [onDouble, delay, tolerancePx],\n );\n\n const handleDouble = useCallback(\n (e: any) => {\n onDouble?.(e);\n },\n [onDouble],\n );\n\n return onDouble\n ? ({\n // Computed property uses the framework’s name ('onDoubleClick' or 'onDblClick')\n [dblClickProp]: handleDouble,\n onPointerUpCapture: handlePointerUp,\n } as DoubleProps<K>)\n : {};\n}\n","import { useMemo, PointerEvent } from '@framework';\nimport type { CSSProperties } from '@framework';\nimport { useDragResize, UseDragResizeOptions } from './use-drag-resize';\nimport {\n describeResizeFromConfig,\n describeVerticesFromConfig,\n type ResizeUI,\n type VertexUI,\n} from '../plugin-interaction-primitives/utils';\n\nexport type HandleElementProps = {\n key: string | number;\n style: CSSProperties;\n onPointerDown: (e: PointerEvent) => void;\n onPointerMove: (e: PointerEvent) => void;\n onPointerUp: (e: PointerEvent) => void;\n onPointerCancel: (e: PointerEvent) => void;\n} & Record<string, any>;\n\nexport function useInteractionHandles(opts: {\n controller: UseDragResizeOptions; // SINGLE config (rect/scale/rotation/vertices/…)\n resizeUI?: ResizeUI; // purely visual knobs\n vertexUI?: VertexUI; // purely visual knobs\n includeVertices?: boolean; // default false\n handleAttrs?: (\n h: 'nw' | 'ne' | 'sw' | 'se' | 'n' | 'e' | 's' | 'w',\n ) => Record<string, any> | void;\n vertexAttrs?: (i: number) => Record<string, any> | void;\n}) {\n const {\n controller,\n resizeUI,\n vertexUI,\n includeVertices = false,\n handleAttrs,\n vertexAttrs,\n } = opts;\n\n const { dragProps, createResizeProps, createVertexProps } = useDragResize(controller);\n\n // Resize handles: only uses data from the SAME controller config.\n const resize: HandleElementProps[] = useMemo(() => {\n const desc = describeResizeFromConfig(controller, resizeUI);\n return desc.map((d) => ({\n key: d.attrs?.['data-epdf-handle'] as string,\n style: d.style as CSSProperties,\n ...createResizeProps(d.handle),\n ...(d.attrs ?? {}),\n ...(handleAttrs?.(d.handle) ?? {}),\n }));\n // deps: controller geometry knobs + UI knobs + handler factory\n }, [\n controller.element.origin.x,\n controller.element.origin.y,\n controller.element.size.width,\n controller.element.size.height,\n controller.scale,\n controller.pageRotation,\n controller.maintainAspectRatio,\n resizeUI?.handleSize,\n resizeUI?.spacing,\n resizeUI?.offsetMode,\n resizeUI?.includeSides,\n resizeUI?.zIndex,\n resizeUI?.rotationAwareCursor,\n createResizeProps,\n handleAttrs,\n ]);\n\n // Vertex handles: same source; prefer live vertices if parent rerenders with updated cfg.vertices\n const vertices: HandleElementProps[] = useMemo(() => {\n if (!includeVertices) return [];\n const desc = describeVerticesFromConfig(controller, vertexUI, controller.vertices);\n return desc.map((d, i) => ({\n key: i,\n style: d.style as CSSProperties,\n ...createVertexProps(i),\n ...(d.attrs ?? {}),\n ...(vertexAttrs?.(i) ?? {}),\n }));\n }, [\n includeVertices,\n controller.element.origin.x,\n controller.element.origin.y,\n controller.element.size.width,\n controller.element.size.height,\n controller.scale,\n controller.vertices, // identity/content drives recalculation\n vertexUI?.vertexSize,\n vertexUI?.zIndex,\n createVertexProps,\n vertexAttrs,\n ]);\n\n return { dragProps, resize, vertices };\n}\n"],"names":["dblClickProp","DragResizeController","constructor","config","onUpdate","this","state","startPoint","startElement","activeHandle","currentPosition","activeVertexIndex","startVertices","currentVertices","vertices","updateConfig","startDrag","clientX","clientY","x","y","element","transformData","type","changes","rect","startResize","handle","metadata","maintainAspectRatio","startVertexEdit","vertexIndex","length","move","delta","calculateDelta","position","calculateDragPosition","calculateResizePosition","calculateVertexPosition","end","wasState","finalPosition","getCurrentPosition","reset","cancel","rawDelta","transformDelta","pageRotation","scale","rad","Math","PI","cos","sin","scaledX","scaledY","clampPoint","p","bbox","_a","constraints","boundingBox","max","min","width","height","newVertices","currentVertex","moved","origin","size","applyConstraints","aspectRatio","includes","newWidth","widthDiff","newHeight","heightDiff","abs","minWidth","minHeight","maxWidth","maxHeight","diagonalCursor","rot","nw","ne","sw","se","edgeOffset","k","spacing","mode","base","useDragResize","options","enabled","controllerRef","useRef","onUpdateRef","useEffect","current","event","call","handleDragStart","useCallback","e","preventDefault","stopPropagation","currentTarget","setPointerCapture","pointerId","handleMove","handleEnd","_c","_b","releasePointerCapture","createResizeHandler","onPointerDown","onPointerMove","onPointerUp","onPointerCancel","createVertexHandler","dragProps","createResizeProps","createVertexProps","children","props","rotation","matrix","getCounterRotation","elementRef","handlePointerDown","handleTouchStart","addEventListener","capture","removeEventListener","menuWrapperProps","style","left","top","transform","transformOrigin","pointerEvents","zIndex","ref","el","Fragment","onDouble","delay","tolerancePx","last","t","handlePointerUp","pointerType","isPrimary","now","performance","withinTime","dx","dy","handleDouble","onPointerUpCapture","opts","controller","resizeUI","vertexUI","includeVertices","handleAttrs","vertexAttrs","resize","useMemo","cfg","ui","handleSize","offsetMode","includeSides","rotationAwareCursor","off","edge","map","pos","borderRadius","cursor","touchAction","attrs","describeResizeFromConfig","d","key","liveVertices","vertexSize","v","i","describeVerticesFromConfig"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/preact/adapter.ts","../../src/shared/plugin-interaction-primitives/drag-resize-controller.ts","../../src/shared/plugin-interaction-primitives/utils.ts","../../src/shared/hooks/use-drag-resize.ts","../../src/shared/components/counter-rotate-container.tsx","../../src/shared/hooks/use-double-press-props.ts","../../src/shared/hooks/use-interaction-handles.ts"],"sourcesContent":["import { createContext, JSX, Fragment, FunctionComponent } from 'preact';\nexport { useEffect, useRef, useState, useCallback, useMemo, useContext } from 'preact/hooks';\nexport type { ComponentChildren as ReactNode, JSX } from 'preact';\n\nexport { createContext, Fragment };\n\nexport type CSSProperties = import('preact').JSX.CSSProperties;\nexport type HTMLAttributes<T = any> = import('preact').JSX.HTMLAttributes<\n T extends EventTarget ? T : never\n>;\n\nexport type MouseEvent<T = Element> = JSX.TargetedMouseEvent<T extends EventTarget ? T : never>;\nexport type PointerEvent<T = Element> = JSX.TargetedPointerEvent<T extends EventTarget ? T : never>;\nexport type ChangeEvent<T = Element> = JSX.TargetedInputEvent<T extends EventTarget ? T : never>;\nexport type TouchEvent<T = Element> = JSX.TargetedTouchEvent<T extends EventTarget ? T : never>;\nexport type ComponentType = FunctionComponent;\n\nexport const dblClickProp = 'onDblClick' as const;\n","import { Position, Rect } from '@embedpdf/models';\n\nexport interface DragResizeConfig {\n element: Rect;\n vertices?: Position[];\n constraints?: {\n minWidth?: number;\n minHeight?: number;\n maxWidth?: number;\n maxHeight?: number;\n boundingBox?: { width: number; height: number }; // page bounds\n };\n maintainAspectRatio?: boolean;\n pageRotation?: number;\n scale?: number;\n}\n\nexport type InteractionState = 'idle' | 'dragging' | 'resizing' | 'vertex-editing';\nexport type ResizeHandle = 'nw' | 'ne' | 'sw' | 'se' | 'n' | 'e' | 's' | 'w';\n\nexport interface TransformData {\n type: 'move' | 'resize' | 'vertex-edit';\n changes: {\n rect?: Rect;\n vertices?: Position[];\n };\n metadata?: {\n handle?: ResizeHandle;\n vertexIndex?: number;\n maintainAspectRatio?: boolean;\n };\n}\n\nexport interface InteractionEvent {\n state: 'start' | 'move' | 'end';\n transformData?: TransformData;\n}\n\n/**\n * Pure geometric controller that manages drag/resize/vertex-edit logic.\n */\nexport class DragResizeController {\n private state: InteractionState = 'idle';\n private startPoint: Position | null = null;\n private startElement: Rect | null = null;\n private activeHandle: ResizeHandle | null = null;\n private currentPosition: Rect | null = null;\n\n // Vertex editing state - pure geometric\n private activeVertexIndex: number | null = null;\n private startVertices: Position[] = [];\n private currentVertices: Position[] = [];\n\n constructor(\n private config: DragResizeConfig,\n private onUpdate: (event: InteractionEvent) => void,\n ) {\n this.currentVertices = config.vertices || [];\n }\n\n updateConfig(config: Partial<DragResizeConfig>) {\n this.config = { ...this.config, ...config };\n this.currentVertices = config.vertices || [];\n }\n\n startDrag(clientX: number, clientY: number) {\n this.state = 'dragging';\n this.startPoint = { x: clientX, y: clientY };\n this.startElement = { ...this.config.element };\n this.currentPosition = { ...this.config.element };\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'move',\n changes: {\n rect: this.startElement,\n },\n },\n });\n }\n\n startResize(handle: ResizeHandle, clientX: number, clientY: number) {\n this.state = 'resizing';\n this.activeHandle = handle;\n this.startPoint = { x: clientX, y: clientY };\n this.startElement = { ...this.config.element };\n this.currentPosition = { ...this.config.element };\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'resize',\n changes: {\n rect: this.startElement,\n },\n metadata: {\n handle: this.activeHandle,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n startVertexEdit(vertexIndex: number, clientX: number, clientY: number) {\n // Refresh vertices from latest config before validating index\n this.currentVertices = [...(this.config.vertices ?? this.currentVertices)];\n if (vertexIndex < 0 || vertexIndex >= this.currentVertices.length) return;\n\n this.state = 'vertex-editing';\n this.activeVertexIndex = vertexIndex;\n this.startPoint = { x: clientX, y: clientY };\n this.startVertices = [...this.currentVertices];\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.startVertices,\n },\n metadata: {\n vertexIndex,\n },\n },\n });\n }\n\n move(clientX: number, clientY: number) {\n if (this.state === 'idle' || !this.startPoint) return;\n\n if (this.state === 'dragging' && this.startElement) {\n const delta = this.calculateDelta(clientX, clientY);\n const position = this.calculateDragPosition(delta);\n this.currentPosition = position;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'move',\n changes: {\n rect: position,\n },\n },\n });\n } else if (this.state === 'resizing' && this.activeHandle && this.startElement) {\n const delta = this.calculateDelta(clientX, clientY);\n const position = this.calculateResizePosition(delta, this.activeHandle);\n this.currentPosition = position;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'resize',\n changes: {\n rect: position,\n },\n metadata: {\n handle: this.activeHandle,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n } else if (this.state === 'vertex-editing' && this.activeVertexIndex !== null) {\n const vertices = this.calculateVertexPosition(clientX, clientY);\n this.currentVertices = vertices;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices,\n },\n metadata: {\n vertexIndex: this.activeVertexIndex,\n },\n },\n });\n }\n }\n\n end() {\n if (this.state === 'idle') return;\n\n const wasState = this.state;\n const handle = this.activeHandle;\n const vertexIndex = this.activeVertexIndex;\n\n if (wasState === 'vertex-editing') {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.currentVertices,\n },\n metadata: {\n vertexIndex: vertexIndex || undefined,\n },\n },\n });\n } else {\n const finalPosition = this.getCurrentPosition();\n this.onUpdate({\n state: 'end',\n transformData: {\n type: wasState === 'dragging' ? 'move' : 'resize',\n changes: {\n rect: finalPosition,\n },\n metadata:\n wasState === 'dragging'\n ? undefined\n : {\n handle: handle || undefined,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n this.reset();\n }\n\n cancel() {\n if (this.state === 'idle') return;\n\n if (this.state === 'vertex-editing') {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.startVertices,\n },\n metadata: {\n vertexIndex: this.activeVertexIndex || undefined,\n },\n },\n });\n } else if (this.startElement) {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: this.state === 'dragging' ? 'move' : 'resize',\n changes: {\n rect: this.startElement,\n },\n metadata:\n this.state === 'dragging'\n ? undefined\n : {\n handle: this.activeHandle || undefined,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n this.reset();\n }\n\n private reset() {\n this.state = 'idle';\n this.startPoint = null;\n this.startElement = null;\n this.activeHandle = null;\n this.currentPosition = null;\n this.activeVertexIndex = null;\n this.startVertices = [];\n }\n\n private getCurrentPosition() {\n return this.currentPosition || this.config.element;\n }\n\n private calculateDelta(clientX: number, clientY: number): Position {\n if (!this.startPoint) return { x: 0, y: 0 };\n\n const rawDelta: Position = {\n x: clientX - this.startPoint.x,\n y: clientY - this.startPoint.y,\n };\n\n return this.transformDelta(rawDelta);\n }\n\n private transformDelta(delta: Position): Position {\n const { pageRotation = 0, scale = 1 } = this.config;\n\n const rad = (pageRotation * Math.PI) / 2;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n\n const scaledX = delta.x / scale;\n const scaledY = delta.y / scale;\n\n return {\n x: cos * scaledX + sin * scaledY,\n y: -sin * scaledX + cos * scaledY,\n };\n }\n\n private clampPoint(p: Position): Position {\n const bbox = this.config.constraints?.boundingBox;\n if (!bbox) return p;\n return {\n x: Math.max(0, Math.min(p.x, bbox.width)),\n y: Math.max(0, Math.min(p.y, bbox.height)),\n };\n }\n\n private calculateVertexPosition(clientX: number, clientY: number): Position[] {\n if (this.activeVertexIndex === null) return this.startVertices;\n\n const delta = this.calculateDelta(clientX, clientY);\n const newVertices = [...this.startVertices];\n const currentVertex = newVertices[this.activeVertexIndex];\n\n const moved = {\n x: currentVertex.x + delta.x,\n y: currentVertex.y + delta.y,\n };\n newVertices[this.activeVertexIndex] = this.clampPoint(moved);\n\n return newVertices;\n }\n\n private calculateDragPosition(delta: Position): Rect {\n if (!this.startElement) return this.config.element;\n\n const position: Rect = {\n origin: {\n x: this.startElement.origin.x + delta.x,\n y: this.startElement.origin.y + delta.y,\n },\n size: {\n width: this.startElement.size.width,\n height: this.startElement.size.height,\n },\n };\n\n return this.applyConstraints(position);\n }\n\n private calculateResizePosition(delta: Position, handle: ResizeHandle): Rect {\n if (!this.startElement) return this.config.element;\n\n let {\n origin: { x, y },\n size: { width, height },\n } = this.startElement;\n\n switch (handle) {\n case 'se':\n width += delta.x;\n height += delta.y;\n break;\n case 'sw':\n x += delta.x;\n width -= delta.x;\n height += delta.y;\n break;\n case 'ne':\n width += delta.x;\n y += delta.y;\n height -= delta.y;\n break;\n case 'nw':\n x += delta.x;\n width -= delta.x;\n y += delta.y;\n height -= delta.y;\n break;\n case 'n':\n y += delta.y;\n height -= delta.y;\n break;\n case 's':\n height += delta.y;\n break;\n case 'e':\n width += delta.x;\n break;\n case 'w':\n x += delta.x;\n width -= delta.x;\n break;\n }\n\n // Maintain aspect ratio if needed\n if (this.config.maintainAspectRatio && this.startElement) {\n const aspectRatio = this.startElement.size.width / this.startElement.size.height;\n\n if (['n', 's', 'e', 'w'].includes(handle)) {\n if (handle === 'n' || handle === 's') {\n const newWidth = height * aspectRatio;\n const widthDiff = newWidth - width;\n width = newWidth;\n x -= widthDiff / 2;\n } else {\n const newHeight = width / aspectRatio;\n const heightDiff = newHeight - height;\n height = newHeight;\n if (handle === 'w') {\n x = this.startElement.origin.x + this.startElement.size.width - width;\n }\n y -= heightDiff / 2;\n }\n } else {\n const widthChange = Math.abs(width - this.startElement.size.width);\n const heightChange = Math.abs(height - this.startElement.size.height);\n if (widthChange > heightChange) {\n height = width / aspectRatio;\n } else {\n width = height * aspectRatio;\n }\n if (handle.includes('w')) {\n x = this.startElement.origin.x + this.startElement.size.width - width;\n }\n if (handle.includes('n')) {\n y = this.startElement.origin.y + this.startElement.size.height - height;\n }\n }\n }\n\n // Handle-aware bounding box clamping to avoid shifting opposite edge\n const bbox = this.config.constraints?.boundingBox;\n if (bbox) {\n switch (handle) {\n case 'e':\n width = Math.min(width, bbox.width - x);\n break;\n case 's':\n height = Math.min(height, bbox.height - y);\n break;\n case 'se':\n width = Math.min(width, bbox.width - x);\n height = Math.min(height, bbox.height - y);\n break;\n case 'w':\n if (x < 0) {\n width += x;\n x = 0;\n }\n break;\n case 'n':\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n case 'sw':\n if (x < 0) {\n width += x;\n x = 0;\n }\n height = Math.min(height, bbox.height - y);\n break;\n case 'nw':\n if (x < 0) {\n width += x;\n x = 0;\n }\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n case 'ne':\n width = Math.min(width, bbox.width - x);\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n }\n }\n\n return this.applyConstraints({ origin: { x, y }, size: { width, height } });\n }\n\n private applyConstraints(position: Rect): Rect {\n const { constraints } = this.config;\n if (!constraints) return position;\n\n let {\n origin: { x, y },\n size: { width, height },\n } = position;\n\n // Apply size constraints\n width = Math.max(constraints.minWidth || 1, width);\n height = Math.max(constraints.minHeight || 1, height);\n\n if (constraints.maxWidth) width = Math.min(constraints.maxWidth, width);\n if (constraints.maxHeight) height = Math.min(constraints.maxHeight, height);\n\n // Apply bounding box constraints\n if (constraints.boundingBox) {\n x = Math.max(0, Math.min(x, constraints.boundingBox.width - width));\n y = Math.max(0, Math.min(y, constraints.boundingBox.height - height));\n }\n\n return { origin: { x, y }, size: { width, height } };\n }\n}\n","import type { Position, Rect } from '@embedpdf/models';\nimport type { ResizeHandle, DragResizeConfig } from './drag-resize-controller';\n\nexport type QuarterTurns = 0 | 1 | 2 | 3;\n\nexport interface ResizeUI {\n handleSize?: number; // px (default 8)\n spacing?: number; // px distance from the box edge (default 1)\n offsetMode?: 'outside' | 'inside' | 'center'; // default 'outside'\n includeSides?: boolean; // default false\n zIndex?: number; // default 3\n rotationAwareCursor?: boolean; // default true\n}\n\nexport interface VertexUI {\n vertexSize?: number; // px (default 12)\n zIndex?: number; // default 4\n}\n\nexport interface HandleDescriptor {\n handle: ResizeHandle;\n style: Record<string, number | string>;\n attrs?: Record<string, any>;\n}\n\nfunction diagonalCursor(handle: ResizeHandle, rot: QuarterTurns): string {\n // Standard cursors; diagonals flip on odd quarter-turns\n const diag0: Record<'nw' | 'ne' | 'sw' | 'se', string> = {\n nw: 'nwse-resize',\n ne: 'nesw-resize',\n sw: 'nesw-resize',\n se: 'nwse-resize',\n };\n if (handle === 'n' || handle === 's') return 'ns-resize';\n if (handle === 'e' || handle === 'w') return 'ew-resize';\n if (rot % 2 === 0) return diag0[handle as 'nw' | 'ne' | 'sw' | 'se'];\n return { nw: 'nesw-resize', ne: 'nwse-resize', sw: 'nwse-resize', se: 'nesw-resize' }[\n handle as 'nw' | 'ne' | 'sw' | 'se'\n ]!;\n}\n\nfunction edgeOffset(k: number, spacing: number, mode: 'outside' | 'inside' | 'center') {\n // Base puts the handle centered on the edge\n const base = -k / 2;\n if (mode === 'center') return base;\n // outside moves further out (more negative), inside moves in (less negative)\n return mode === 'outside' ? base - spacing : base + spacing;\n}\n\nexport function describeResizeFromConfig(\n cfg: DragResizeConfig,\n ui: ResizeUI = {},\n): HandleDescriptor[] {\n const {\n handleSize = 8,\n spacing = 1,\n offsetMode = 'outside',\n includeSides = false,\n zIndex = 3,\n rotationAwareCursor = true,\n } = ui;\n\n const rotation = ((cfg.pageRotation ?? 0) % 4) as QuarterTurns;\n\n const off = (edge: 'top' | 'right' | 'bottom' | 'left') => ({\n [edge]: edgeOffset(handleSize, spacing, offsetMode) + 'px',\n });\n\n const corners: Array<[ResizeHandle, Record<string, number | string>]> = [\n ['nw', { ...off('top'), ...off('left') }],\n ['ne', { ...off('top'), ...off('right') }],\n ['sw', { ...off('bottom'), ...off('left') }],\n ['se', { ...off('bottom'), ...off('right') }],\n ];\n const sides: Array<[ResizeHandle, Record<string, number | string>]> = includeSides\n ? [\n ['n', { ...off('top'), left: `calc(50% - ${handleSize / 2}px)` }],\n ['s', { ...off('bottom'), left: `calc(50% - ${handleSize / 2}px)` }],\n ['w', { ...off('left'), top: `calc(50% - ${handleSize / 2}px)` }],\n ['e', { ...off('right'), top: `calc(50% - ${handleSize / 2}px)` }],\n ]\n : [];\n\n const all = [...corners, ...sides];\n\n return all.map(([handle, pos]) => ({\n handle,\n style: {\n position: 'absolute',\n width: handleSize + 'px',\n height: handleSize + 'px',\n borderRadius: '50%',\n zIndex,\n cursor: rotationAwareCursor ? diagonalCursor(handle, rotation) : 'default',\n touchAction: 'none',\n ...(pos as any),\n },\n attrs: { 'data-epdf-handle': handle },\n }));\n}\n\nexport function describeVerticesFromConfig(\n cfg: DragResizeConfig,\n ui: VertexUI = {},\n liveVertices?: Position[],\n): HandleDescriptor[] {\n const { vertexSize = 12, zIndex = 4 } = ui;\n const rect: Rect = cfg.element;\n const scale = cfg.scale ?? 1;\n const verts = liveVertices ?? cfg.vertices ?? [];\n\n return verts.map((v, i) => {\n const left = (v.x - rect.origin.x) * scale - vertexSize / 2;\n const top = (v.y - rect.origin.y) * scale - vertexSize / 2;\n return {\n handle: 'nw', // not used; kept for type\n style: {\n position: 'absolute',\n left: left + 'px',\n top: top + 'px',\n width: vertexSize + 'px',\n height: vertexSize + 'px',\n borderRadius: '50%',\n cursor: 'pointer',\n zIndex,\n touchAction: 'none',\n },\n attrs: { 'data-epdf-vertex': i },\n };\n });\n}\n","import { useRef, useCallback, useEffect, PointerEvent } from '@framework';\nimport {\n DragResizeController,\n DragResizeConfig,\n InteractionEvent,\n ResizeHandle,\n} from '../plugin-interaction-primitives';\n\nexport interface UseDragResizeOptions extends DragResizeConfig {\n onUpdate?: (event: InteractionEvent) => void;\n enabled?: boolean;\n}\n\nexport interface ResizeHandleEventProps {\n onPointerDown: (e: PointerEvent) => void;\n onPointerMove: (e: PointerEvent) => void;\n onPointerUp: (e: PointerEvent) => void;\n onPointerCancel: (e: PointerEvent) => void;\n}\n\nexport function useDragResize(options: UseDragResizeOptions) {\n const { onUpdate, enabled = true, ...config } = options;\n const controllerRef = useRef<DragResizeController | null>(null);\n const onUpdateRef = useRef<typeof onUpdate>(onUpdate);\n\n useEffect(() => {\n onUpdateRef.current = onUpdate;\n }, [onUpdate]);\n\n // Initialize or update controller\n useEffect(() => {\n if (!controllerRef.current) {\n controllerRef.current = new DragResizeController(config, (event) =>\n onUpdateRef.current?.(event),\n );\n } else {\n controllerRef.current.updateConfig(config);\n }\n }, [\n config.element,\n config.constraints,\n config.maintainAspectRatio,\n config.pageRotation,\n config.scale,\n config.vertices,\n ]);\n\n const handleDragStart = useCallback(\n (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startDrag(e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n [enabled],\n );\n\n const handleMove = useCallback((e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.move(e.clientX, e.clientY);\n }, []);\n\n const handleEnd = useCallback((e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.end();\n (e.currentTarget as HTMLElement).releasePointerCapture?.(e.pointerId);\n }, []);\n\n const createResizeHandler = useCallback(\n (handle: ResizeHandle): ResizeHandleEventProps => ({\n onPointerDown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startResize(handle, e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }),\n [enabled, handleMove, handleEnd],\n );\n\n const createVertexHandler = useCallback(\n (vertexIndex: number): ResizeHandleEventProps => ({\n onPointerDown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startVertexEdit(vertexIndex, e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }),\n [enabled, handleMove, handleEnd],\n );\n\n return {\n dragProps: enabled\n ? {\n onPointerDown: handleDragStart,\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }\n : {},\n createResizeProps: createResizeHandler,\n createVertexProps: createVertexHandler,\n };\n}\n","import { Rect, Rotation } from '@embedpdf/models';\nimport { getCounterRotation } from '@embedpdf/utils';\nimport { ReactNode, CSSProperties, Fragment, useRef, useEffect } from '@framework';\n\ninterface CounterRotateProps {\n rect: Rect;\n rotation: Rotation;\n}\n\nexport interface MenuWrapperProps {\n style: CSSProperties;\n ref: (el: HTMLDivElement | null) => void;\n}\n\ninterface CounterRotateComponentProps extends CounterRotateProps {\n children: (props: {\n matrix: string;\n rect: Rect;\n menuWrapperProps: MenuWrapperProps;\n }) => ReactNode;\n}\n\nexport function CounterRotate({ children, ...props }: CounterRotateComponentProps) {\n const { rect, rotation } = props;\n const { matrix, width, height } = getCounterRotation(rect, rotation);\n const elementRef = useRef<HTMLDivElement | null>(null);\n\n // Use native event listeners with capture phase to prevent event propagation\n useEffect(() => {\n const element = elementRef.current;\n if (!element) return;\n\n const handlePointerDown = (e: Event) => {\n // Stop propagation to prevent underlying layers from receiving the event\n e.stopPropagation();\n // DO NOT use e.preventDefault() here - it breaks click events on mobile/tablet!\n // preventDefault() stops the browser from generating click events from touch,\n // which makes buttons inside this container non-functional on touch devices.\n };\n\n const handleTouchStart = (e: Event) => {\n // Stop propagation to prevent underlying layers from receiving the event\n e.stopPropagation();\n // DO NOT use e.preventDefault() here - it breaks click events on mobile/tablet!\n // preventDefault() stops the browser from generating click events from touch,\n // which makes buttons inside this container non-functional on touch devices.\n };\n\n // Use capture phase to intercept before synthetic events\n element.addEventListener('pointerdown', handlePointerDown, { capture: true });\n element.addEventListener('touchstart', handleTouchStart, { capture: true });\n\n return () => {\n element.removeEventListener('pointerdown', handlePointerDown, { capture: true });\n element.removeEventListener('touchstart', handleTouchStart, { capture: true });\n };\n }, []);\n\n const menuWrapperStyle: CSSProperties = {\n position: 'absolute',\n left: rect.origin.x,\n top: rect.origin.y,\n transform: matrix,\n transformOrigin: '0 0',\n width: width,\n height: height,\n pointerEvents: 'none',\n zIndex: 3,\n };\n\n const menuWrapperProps: MenuWrapperProps = {\n style: menuWrapperStyle,\n ref: (el: HTMLDivElement | null) => {\n elementRef.current = el;\n },\n };\n\n return (\n <Fragment>\n {children({\n menuWrapperProps,\n matrix,\n rect: {\n origin: { x: rect.origin.x, y: rect.origin.y },\n size: { width: width, height: height },\n },\n })}\n </Fragment>\n );\n}\n","import { useRef, useCallback, dblClickProp } from '@framework';\nimport type { PointerEvent } from '@framework';\n\ntype DoublePressOptions = {\n delay?: number; // ms between taps\n tolerancePx?: number; // spatial tolerance\n};\n\ntype DoubleHandler<T extends Element> = ((e: PointerEvent<T> | MouseEvent) => void) | undefined;\n\ntype DoubleProps<K extends string> = Partial<Record<K, (e: any) => void>> & {\n onPointerUp?: (e: any) => void;\n};\n\nexport function useDoublePressProps<\n T extends Element = Element,\n K extends string = typeof dblClickProp,\n>(\n onDouble?: DoubleHandler<T>,\n { delay = 300, tolerancePx = 18 }: DoublePressOptions = {},\n): DoubleProps<K> {\n const last = useRef({ t: 0, x: 0, y: 0 });\n\n const handlePointerUp = useCallback(\n (e: any) => {\n if (!onDouble) return;\n\n // Ignore mouse (it will use native dblclick),\n // and ignore non-primary pointers (multi-touch, etc.)\n if (e.pointerType === 'mouse' || e.isPrimary === false) return;\n\n const now = performance.now();\n const x = e.clientX as number;\n const y = e.clientY as number;\n\n const withinTime = now - last.current.t <= delay;\n const dx = x - last.current.x;\n const dy = y - last.current.y;\n const withinDist = dx * dx + dy * dy <= tolerancePx * tolerancePx;\n\n if (withinTime && withinDist) onDouble?.(e as PointerEvent<T>);\n\n last.current = { t: now, x, y };\n },\n [onDouble, delay, tolerancePx],\n );\n\n const handleDouble = useCallback(\n (e: any) => {\n onDouble?.(e);\n },\n [onDouble],\n );\n\n return onDouble\n ? ({\n // Computed property uses the framework’s name ('onDoubleClick' or 'onDblClick')\n [dblClickProp]: handleDouble,\n onPointerUpCapture: handlePointerUp,\n } as DoubleProps<K>)\n : {};\n}\n","import { useMemo, PointerEvent } from '@framework';\nimport type { CSSProperties } from '@framework';\nimport { useDragResize, UseDragResizeOptions } from './use-drag-resize';\nimport {\n describeResizeFromConfig,\n describeVerticesFromConfig,\n type ResizeUI,\n type VertexUI,\n} from '../plugin-interaction-primitives/utils';\n\nexport type HandleElementProps = {\n key: string | number;\n style: CSSProperties;\n onPointerDown: (e: PointerEvent) => void;\n onPointerMove: (e: PointerEvent) => void;\n onPointerUp: (e: PointerEvent) => void;\n onPointerCancel: (e: PointerEvent) => void;\n} & Record<string, any>;\n\nexport function useInteractionHandles(opts: {\n controller: UseDragResizeOptions; // SINGLE config (rect/scale/rotation/vertices/…)\n resizeUI?: ResizeUI; // purely visual knobs\n vertexUI?: VertexUI; // purely visual knobs\n includeVertices?: boolean; // default false\n handleAttrs?: (\n h: 'nw' | 'ne' | 'sw' | 'se' | 'n' | 'e' | 's' | 'w',\n ) => Record<string, any> | void;\n vertexAttrs?: (i: number) => Record<string, any> | void;\n}) {\n const {\n controller,\n resizeUI,\n vertexUI,\n includeVertices = false,\n handleAttrs,\n vertexAttrs,\n } = opts;\n\n const { dragProps, createResizeProps, createVertexProps } = useDragResize(controller);\n\n // Resize handles: only uses data from the SAME controller config.\n const resize: HandleElementProps[] = useMemo(() => {\n const desc = describeResizeFromConfig(controller, resizeUI);\n return desc.map((d) => ({\n key: d.attrs?.['data-epdf-handle'] as string,\n style: d.style as CSSProperties,\n ...createResizeProps(d.handle),\n ...(d.attrs ?? {}),\n ...(handleAttrs?.(d.handle) ?? {}),\n }));\n // deps: controller geometry knobs + UI knobs + handler factory\n }, [\n controller.element.origin.x,\n controller.element.origin.y,\n controller.element.size.width,\n controller.element.size.height,\n controller.scale,\n controller.pageRotation,\n controller.maintainAspectRatio,\n resizeUI?.handleSize,\n resizeUI?.spacing,\n resizeUI?.offsetMode,\n resizeUI?.includeSides,\n resizeUI?.zIndex,\n resizeUI?.rotationAwareCursor,\n createResizeProps,\n handleAttrs,\n ]);\n\n // Vertex handles: same source; prefer live vertices if parent rerenders with updated cfg.vertices\n const vertices: HandleElementProps[] = useMemo(() => {\n if (!includeVertices) return [];\n const desc = describeVerticesFromConfig(controller, vertexUI, controller.vertices);\n return desc.map((d, i) => ({\n key: i,\n style: d.style as CSSProperties,\n ...createVertexProps(i),\n ...(d.attrs ?? {}),\n ...(vertexAttrs?.(i) ?? {}),\n }));\n }, [\n includeVertices,\n controller.element.origin.x,\n controller.element.origin.y,\n controller.element.size.width,\n controller.element.size.height,\n controller.scale,\n controller.vertices, // identity/content drives recalculation\n vertexUI?.vertexSize,\n vertexUI?.zIndex,\n createVertexProps,\n vertexAttrs,\n ]);\n\n return { dragProps, resize, vertices };\n}\n"],"names":["dblClickProp","DragResizeController","constructor","config","onUpdate","this","state","startPoint","startElement","activeHandle","currentPosition","activeVertexIndex","startVertices","currentVertices","vertices","updateConfig","startDrag","clientX","clientY","x","y","element","transformData","type","changes","rect","startResize","handle","metadata","maintainAspectRatio","startVertexEdit","vertexIndex","length","move","delta","calculateDelta","position","calculateDragPosition","calculateResizePosition","calculateVertexPosition","end","wasState","finalPosition","getCurrentPosition","reset","cancel","rawDelta","transformDelta","pageRotation","scale","rad","Math","PI","cos","sin","scaledX","scaledY","clampPoint","p","bbox","_a","constraints","boundingBox","max","min","width","height","newVertices","currentVertex","moved","origin","size","applyConstraints","aspectRatio","includes","newWidth","widthDiff","newHeight","heightDiff","abs","minWidth","minHeight","maxWidth","maxHeight","diagonalCursor","rot","nw","ne","sw","se","edgeOffset","k","spacing","mode","base","useDragResize","options","enabled","controllerRef","useRef","onUpdateRef","useEffect","current","event","call","handleDragStart","useCallback","e","preventDefault","stopPropagation","currentTarget","setPointerCapture","pointerId","handleMove","handleEnd","_c","_b","releasePointerCapture","createResizeHandler","onPointerDown","onPointerMove","onPointerUp","onPointerCancel","createVertexHandler","dragProps","createResizeProps","createVertexProps","children","props","rotation","matrix","getCounterRotation","elementRef","handlePointerDown","handleTouchStart","addEventListener","capture","removeEventListener","menuWrapperProps","style","left","top","transform","transformOrigin","pointerEvents","zIndex","ref","el","Fragment","onDouble","delay","tolerancePx","last","t","handlePointerUp","pointerType","isPrimary","now","performance","withinTime","dx","dy","handleDouble","onPointerUpCapture","opts","controller","resizeUI","vertexUI","includeVertices","handleAttrs","vertexAttrs","resize","useMemo","cfg","ui","handleSize","offsetMode","includeSides","rotationAwareCursor","off","edge","map","pos","borderRadius","cursor","touchAction","attrs","describeResizeFromConfig","d","key","liveVertices","vertexSize","v","i","describeVerticesFromConfig"],"mappings":"iMAiBaA,EAAe,aCwBrB,MAAMC,EAYX,WAAAC,CACUC,EACAC,GADAC,KAAAF,OAAAA,EACAE,KAAAD,SAAAA,EAbVC,KAAQC,MAA0B,OAClCD,KAAQE,WAA8B,KACtCF,KAAQG,aAA4B,KACpCH,KAAQI,aAAoC,KAC5CJ,KAAQK,gBAA+B,KAGvCL,KAAQM,kBAAmC,KAC3CN,KAAQO,cAA4B,GACpCP,KAAQQ,gBAA8B,GAM/BR,KAAAQ,gBAAkBV,EAAOW,UAAY,EAAC,CAG7C,YAAAC,CAAaZ,GACXE,KAAKF,OAAS,IAAKE,KAAKF,UAAWA,GAC9BE,KAAAQ,gBAAkBV,EAAOW,UAAY,EAAC,CAG7C,SAAAE,CAAUC,EAAiBC,GACzBb,KAAKC,MAAQ,WACbD,KAAKE,WAAa,CAAEY,EAAGF,EAASG,EAAGF,GACnCb,KAAKG,aAAe,IAAKH,KAAKF,OAAOkB,SACrChB,KAAKK,gBAAkB,IAAKL,KAAKF,OAAOkB,SAExChB,KAAKD,SAAS,CACZE,MAAO,QACPgB,cAAe,CACbC,KAAM,OACNC,QAAS,CACPC,KAAMpB,KAAKG,gBAGhB,CAGH,WAAAkB,CAAYC,EAAsBV,EAAiBC,GACjDb,KAAKC,MAAQ,WACbD,KAAKI,aAAekB,EACpBtB,KAAKE,WAAa,CAAEY,EAAGF,EAASG,EAAGF,GACnCb,KAAKG,aAAe,IAAKH,KAAKF,OAAOkB,SACrChB,KAAKK,gBAAkB,IAAKL,KAAKF,OAAOkB,SAExChB,KAAKD,SAAS,CACZE,MAAO,QACPgB,cAAe,CACbC,KAAM,SACNC,QAAS,CACPC,KAAMpB,KAAKG,cAEboB,SAAU,CACRD,OAAQtB,KAAKI,aACboB,oBAAqBxB,KAAKF,OAAO0B,uBAGtC,CAGH,eAAAC,CAAgBC,EAAqBd,EAAiBC,GAEpDb,KAAKQ,gBAAkB,IAAKR,KAAKF,OAAOW,UAAYT,KAAKQ,iBACrDkB,EAAc,GAAKA,GAAe1B,KAAKQ,gBAAgBmB,SAE3D3B,KAAKC,MAAQ,iBACbD,KAAKM,kBAAoBoB,EACzB1B,KAAKE,WAAa,CAAEY,EAAGF,EAASG,EAAGF,GACnCb,KAAKO,cAAgB,IAAIP,KAAKQ,iBAE9BR,KAAKD,SAAS,CACZE,MAAO,QACPgB,cAAe,CACbC,KAAM,cACNC,QAAS,CACPV,SAAUT,KAAKO,eAEjBgB,SAAU,CACRG,kBAGL,CAGH,IAAAE,CAAKhB,EAAiBC,GACpB,GAAmB,SAAfb,KAAKC,OAAqBD,KAAKE,WAEnC,GAAmB,aAAfF,KAAKC,OAAwBD,KAAKG,aAAc,CAClD,MAAM0B,EAAQ7B,KAAK8B,eAAelB,EAASC,GACrCkB,EAAW/B,KAAKgC,sBAAsBH,GAC5C7B,KAAKK,gBAAkB0B,EAEvB/B,KAAKD,SAAS,CACZE,MAAO,OACPgB,cAAe,CACbC,KAAM,OACNC,QAAS,CACPC,KAAMW,KAGX,SACuB,aAAf/B,KAAKC,OAAwBD,KAAKI,cAAgBJ,KAAKG,aAAc,CAC9E,MAAM0B,EAAQ7B,KAAK8B,eAAelB,EAASC,GACrCkB,EAAW/B,KAAKiC,wBAAwBJ,EAAO7B,KAAKI,cAC1DJ,KAAKK,gBAAkB0B,EAEvB/B,KAAKD,SAAS,CACZE,MAAO,OACPgB,cAAe,CACbC,KAAM,SACNC,QAAS,CACPC,KAAMW,GAERR,SAAU,CACRD,OAAQtB,KAAKI,aACboB,oBAAqBxB,KAAKF,OAAO0B,uBAGtC,SACuB,mBAAfxB,KAAKC,OAAyD,OAA3BD,KAAKM,kBAA4B,CAC7E,MAAMG,EAAWT,KAAKkC,wBAAwBtB,EAASC,GACvDb,KAAKQ,gBAAkBC,EAEvBT,KAAKD,SAAS,CACZE,MAAO,OACPgB,cAAe,CACbC,KAAM,cACNC,QAAS,CACPV,YAEFc,SAAU,CACRG,YAAa1B,KAAKM,qBAGvB,CACH,CAGF,GAAA6B,GACM,GAAe,SAAfnC,KAAKC,MAAkB,OAE3B,MAAMmC,EAAWpC,KAAKC,MAChBqB,EAAStB,KAAKI,aACdsB,EAAc1B,KAAKM,kBAEzB,GAAiB,mBAAb8B,EACFpC,KAAKD,SAAS,CACZE,MAAO,MACPgB,cAAe,CACbC,KAAM,cACNC,QAAS,CACPV,SAAUT,KAAKQ,iBAEjBe,SAAU,CACRG,YAAaA,QAAe,UAI7B,CACC,MAAAW,EAAgBrC,KAAKsC,qBAC3BtC,KAAKD,SAAS,CACZE,MAAO,MACPgB,cAAe,CACbC,KAAmB,aAAbkB,EAA0B,OAAS,SACzCjB,QAAS,CACPC,KAAMiB,GAERd,SACe,aAAba,OACI,EACA,CACEd,OAAQA,QAAU,EAClBE,oBAAqBxB,KAAKF,OAAO0B,uBAG5C,CAGHxB,KAAKuC,OAAM,CAGb,MAAAC,GACqB,SAAfxC,KAAKC,QAEU,mBAAfD,KAAKC,MACPD,KAAKD,SAAS,CACZE,MAAO,MACPgB,cAAe,CACbC,KAAM,cACNC,QAAS,CACPV,SAAUT,KAAKO,eAEjBgB,SAAU,CACRG,YAAa1B,KAAKM,wBAAqB,MAIpCN,KAAKG,cACdH,KAAKD,SAAS,CACZE,MAAO,MACPgB,cAAe,CACbC,KAAqB,aAAflB,KAAKC,MAAuB,OAAS,SAC3CkB,QAAS,CACPC,KAAMpB,KAAKG,cAEboB,SACiB,aAAfvB,KAAKC,WACD,EACA,CACEqB,OAAQtB,KAAKI,mBAAgB,EAC7BoB,oBAAqBxB,KAAKF,OAAO0B,wBAM/CxB,KAAKuC,QAAM,CAGL,KAAAA,GACNvC,KAAKC,MAAQ,OACbD,KAAKE,WAAa,KAClBF,KAAKG,aAAe,KACpBH,KAAKI,aAAe,KACpBJ,KAAKK,gBAAkB,KACvBL,KAAKM,kBAAoB,KACzBN,KAAKO,cAAgB,EAAC,CAGhB,kBAAA+B,GACC,OAAAtC,KAAKK,iBAAmBL,KAAKF,OAAOkB,OAAA,CAGrC,cAAAc,CAAelB,EAAiBC,GAClC,IAACb,KAAKE,WAAY,MAAO,CAAEY,EAAG,EAAGC,EAAG,GAExC,MAAM0B,EAAqB,CACzB3B,EAAGF,EAAUZ,KAAKE,WAAWY,EAC7BC,EAAGF,EAAUb,KAAKE,WAAWa,GAGxB,OAAAf,KAAK0C,eAAeD,EAAQ,CAG7B,cAAAC,CAAeb,GACrB,MAAMc,aAAEA,EAAe,EAAAC,MAAGA,EAAQ,GAAM5C,KAAKF,OAEvC+C,EAAOF,EAAeG,KAAKC,GAAM,EACjCC,EAAMF,KAAKE,IAAIH,GACfI,EAAMH,KAAKG,IAAIJ,GAEfK,EAAUrB,EAAMf,EAAI8B,EACpBO,EAAUtB,EAAMd,EAAI6B,EAEnB,MAAA,CACL9B,EAAGkC,EAAME,EAAUD,EAAME,EACzBpC,GAAIkC,EAAMC,EAAUF,EAAMG,EAC5B,CAGM,UAAAC,CAAWC,SACX,MAAAC,EAAO,OAAAC,EAAAvD,KAAKF,OAAO0D,kBAAa,EAAAD,EAAAE,YAClC,OAACH,EACE,CACLxC,EAAGgC,KAAKY,IAAI,EAAGZ,KAAKa,IAAIN,EAAEvC,EAAGwC,EAAKM,QAClC7C,EAAG+B,KAAKY,IAAI,EAAGZ,KAAKa,IAAIN,EAAEtC,EAAGuC,EAAKO,UAHlBR,CAIlB,CAGM,uBAAAnB,CAAwBtB,EAAiBC,GAC/C,GAA+B,OAA3Bb,KAAKM,kBAA4B,OAAON,KAAKO,cAEjD,MAAMsB,EAAQ7B,KAAK8B,eAAelB,EAASC,GACrCiD,EAAc,IAAI9D,KAAKO,eACvBwD,EAAgBD,EAAY9D,KAAKM,mBAEjC0D,EAAQ,CACZlD,EAAGiD,EAAcjD,EAAIe,EAAMf,EAC3BC,EAAGgD,EAAchD,EAAIc,EAAMd,GAItB,OAFP+C,EAAY9D,KAAKM,mBAAqBN,KAAKoD,WAAWY,GAE/CF,CAAA,CAGD,qBAAA9B,CAAsBH,GAC5B,IAAK7B,KAAKG,aAAc,OAAOH,KAAKF,OAAOkB,QAE3C,MAAMe,EAAiB,CACrBkC,OAAQ,CACNnD,EAAGd,KAAKG,aAAa8D,OAAOnD,EAAIe,EAAMf,EACtCC,EAAGf,KAAKG,aAAa8D,OAAOlD,EAAIc,EAAMd,GAExCmD,KAAM,CACJN,MAAO5D,KAAKG,aAAa+D,KAAKN,MAC9BC,OAAQ7D,KAAKG,aAAa+D,KAAKL,SAI5B,OAAA7D,KAAKmE,iBAAiBpC,EAAQ,CAG/B,uBAAAE,CAAwBJ,EAAiBP,SAC/C,IAAKtB,KAAKG,aAAc,OAAOH,KAAKF,OAAOkB,QAEvC,IACFiD,QAAQnD,EAAEA,EAAAC,EAAGA,GACbmD,MAAMN,MAAEA,EAAAC,OAAOA,IACb7D,KAAKG,aAET,OAAQmB,GACN,IAAK,KACHsC,GAAS/B,EAAMf,EACf+C,GAAUhC,EAAMd,EAChB,MACF,IAAK,KACHD,GAAKe,EAAMf,EACX8C,GAAS/B,EAAMf,EACf+C,GAAUhC,EAAMd,EAChB,MACF,IAAK,KACH6C,GAAS/B,EAAMf,EACfC,GAAKc,EAAMd,EACX8C,GAAUhC,EAAMd,EAChB,MACF,IAAK,KACHD,GAAKe,EAAMf,EACX8C,GAAS/B,EAAMf,EACfC,GAAKc,EAAMd,EACX8C,GAAUhC,EAAMd,EAChB,MACF,IAAK,IACHA,GAAKc,EAAMd,EACX8C,GAAUhC,EAAMd,EAChB,MACF,IAAK,IACH8C,GAAUhC,EAAMd,EAChB,MACF,IAAK,IACH6C,GAAS/B,EAAMf,EACf,MACF,IAAK,IACHA,GAAKe,EAAMf,EACX8C,GAAS/B,EAAMf,EAKnB,GAAId,KAAKF,OAAO0B,qBAAuBxB,KAAKG,aAAc,CACxD,MAAMiE,EAAcpE,KAAKG,aAAa+D,KAAKN,MAAQ5D,KAAKG,aAAa+D,KAAKL,OAEtE,GAAA,CAAC,IAAK,IAAK,IAAK,KAAKQ,SAAS/C,GAC5B,GAAW,MAAXA,GAA6B,MAAXA,EAAgB,CACpC,MAAMgD,EAAWT,EAASO,EACpBG,EAAYD,EAAWV,EACrBA,EAAAU,EACRxD,GAAKyD,EAAY,CAAA,KACZ,CACL,MAAMC,EAAYZ,EAAQQ,EACpBK,EAAaD,EAAYX,EACtBA,EAAAW,EACM,MAAXlD,IACFR,EAAId,KAAKG,aAAa8D,OAAOnD,EAAId,KAAKG,aAAa+D,KAAKN,MAAQA,GAElE7C,GAAK0D,EAAa,CAAA,KAEf,CACe3B,KAAK4B,IAAId,EAAQ5D,KAAKG,aAAa+D,KAAKN,OACvCd,KAAK4B,IAAIb,EAAS7D,KAAKG,aAAa+D,KAAKL,QAE5DA,EAASD,EAAQQ,EAEjBR,EAAQC,EAASO,EAEf9C,EAAO+C,SAAS,OAClBvD,EAAId,KAAKG,aAAa8D,OAAOnD,EAAId,KAAKG,aAAa+D,KAAKN,MAAQA,GAE9DtC,EAAO+C,SAAS,OAClBtD,EAAIf,KAAKG,aAAa8D,OAAOlD,EAAIf,KAAKG,aAAa+D,KAAKL,OAASA,EACnE,CACF,CAII,MAAAP,EAAO,OAAAC,EAAAvD,KAAKF,OAAO0D,kBAAa,EAAAD,EAAAE,YACtC,GAAIH,EACF,OAAQhC,GACN,IAAK,IACHsC,EAAQd,KAAKa,IAAIC,EAAON,EAAKM,MAAQ9C,GACrC,MACF,IAAK,IACH+C,EAASf,KAAKa,IAAIE,EAAQP,EAAKO,OAAS9C,GACxC,MACF,IAAK,KACH6C,EAAQd,KAAKa,IAAIC,EAAON,EAAKM,MAAQ9C,GACrC+C,EAASf,KAAKa,IAAIE,EAAQP,EAAKO,OAAS9C,GACxC,MACF,IAAK,IACCD,EAAI,IACG8C,GAAA9C,EACLA,EAAA,GAEN,MACF,IAAK,IACCC,EAAI,IACI8C,GAAA9C,EACNA,EAAA,GAEN,MACF,IAAK,KACCD,EAAI,IACG8C,GAAA9C,EACLA,EAAA,GAEN+C,EAASf,KAAKa,IAAIE,EAAQP,EAAKO,OAAS9C,GACxC,MACF,IAAK,KACCD,EAAI,IACG8C,GAAA9C,EACLA,EAAA,GAEFC,EAAI,IACI8C,GAAA9C,EACNA,EAAA,GAEN,MACF,IAAK,KACH6C,EAAQd,KAAKa,IAAIC,EAAON,EAAKM,MAAQ9C,GACjCC,EAAI,IACI8C,GAAA9C,EACNA,EAAA,GAMZ,OAAOf,KAAKmE,iBAAiB,CAAEF,OAAQ,CAAEnD,IAAGC,KAAKmD,KAAM,CAAEN,QAAOC,WAAU,CAGpE,gBAAAM,CAAiBpC,GACjB,MAAAyB,YAAEA,GAAgBxD,KAAKF,OACzB,IAAC0D,EAAoB,OAAAzB,EAErB,IACFkC,QAAQnD,EAAEA,EAAAC,EAAGA,GACbmD,MAAMN,MAAEA,EAAAC,OAAOA,IACb9B,EAeG,OAZP6B,EAAQd,KAAKY,IAAIF,EAAYmB,UAAY,EAAGf,GAC5CC,EAASf,KAAKY,IAAIF,EAAYoB,WAAa,EAAGf,GAE1CL,EAAYqB,WAAUjB,EAAQd,KAAKa,IAAIH,EAAYqB,SAAUjB,IAC7DJ,EAAYsB,YAAWjB,EAASf,KAAKa,IAAIH,EAAYsB,UAAWjB,IAGhEL,EAAYC,cACV3C,EAAAgC,KAAKY,IAAI,EAAGZ,KAAKa,IAAI7C,EAAG0C,EAAYC,YAAYG,MAAQA,IACxD7C,EAAA+B,KAAKY,IAAI,EAAGZ,KAAKa,IAAI5C,EAAGyC,EAAYC,YAAYI,OAASA,KAGxD,CAAEI,OAAQ,CAAEnD,IAAGC,KAAKmD,KAAM,CAAEN,QAAOC,UAAS,EChevD,SAASkB,EAAezD,EAAsB0D,GAQ5C,MAAe,MAAX1D,GAA6B,MAAXA,EAAuB,YAC9B,MAAXA,GAA6B,MAAXA,EAAuB,YACzC0D,EAAM,GAAM,EARyC,CACvDC,GAAI,cACJC,GAAI,cACJC,GAAI,cACJC,GAAI,eAI0B9D,GACzB,CAAE2D,GAAI,cAAeC,GAAI,cAAeC,GAAI,cAAeC,GAAI,eACpE9D,EAEJ,CAEA,SAAS+D,EAAWC,EAAWC,EAAiBC,GAExC,MAAAC,GAAQH,EAAI,EACd,MAAS,WAATE,EAA0BC,EAEd,YAATD,EAAqBC,EAAOF,EAAUE,EAAOF,CACtD,CC3BO,SAASG,EAAcC,GAC5B,MAAM5F,SAAEA,EAAU6F,QAAAA,GAAU,KAAS9F,GAAW6F,EAC1CE,EAAgBC,SAAoC,MACpDC,EAAcD,SAAwB/F,GAE5CiG,EAAAA,WAAU,KACRD,EAAYE,QAAUlG,CAAA,GACrB,CAACA,IAGJiG,EAAAA,WAAU,KACHH,EAAcI,QAKHJ,EAAAI,QAAQvF,aAAaZ,GAJnC+F,EAAcI,QAAU,IAAIrG,EAAqBE,GAASoG,UACxD,OAAA,OAAA3C,EAAAwC,EAAYE,cAAU,EAAA1C,EAAA4C,KAAAJ,EAAAG,EAAA,GAGiB,GAE1C,CACDpG,EAAOkB,QACPlB,EAAO0D,YACP1D,EAAO0B,oBACP1B,EAAO6C,aACP7C,EAAO8C,MACP9C,EAAOW,WAGT,MAAM2F,EAAkBC,EAAAA,aACrBC,UACMV,IACLU,EAAEC,iBACFD,EAAEE,kBACF,OAAAjD,EAAAsC,EAAcI,UAAd1C,EAAuB5C,UAAU2F,EAAE1F,QAAS0F,EAAEzF,SAC3CyF,EAAAG,cAA8BC,kBAAkBJ,EAAEK,WAAS,GAEhE,CAACf,IAGGgB,EAAaP,eAAaC,UAC9BA,EAAEC,iBACFD,EAAEE,kBACF,OAAAjD,EAAAsC,EAAcI,UAAd1C,EAAuB3B,KAAK0E,EAAE1F,QAAS0F,EAAEzF,QAAA,GACxC,IAEGgG,EAAYR,eAAaC,cAC7BA,EAAEC,iBACFD,EAAEE,kBACF,OAAAjD,EAAAsC,EAAcI,UAAS1C,EAAApB,MACtB,OAAE2E,GAAAC,EAAAT,EAAAG,eAA8BO,wBAAhCF,EAAAX,KAAAY,EAAwDT,EAAEK,UAAA,GAC1D,IAEGM,EAAsBZ,EAAAA,aACzB/E,IAAkD,CACjD4F,cAAgBZ,UACTV,IACLU,EAAEC,iBACFD,EAAEE,kBACF,OAAAjD,EAAAsC,EAAcI,UAAS1C,EAAAlC,YAAYC,EAAQgF,EAAE1F,QAAS0F,EAAEzF,SACrDyF,EAAAG,cAA8BC,kBAAkBJ,EAAEK,WAAS,EAEhEQ,cAAeP,EACfQ,YAAaP,EACbQ,gBAAiBR,KAEnB,CAACjB,EAASgB,EAAYC,IAGlBS,EAAsBjB,EAAAA,aACzB3E,IAAiD,CAChDwF,cAAgBZ,UACTV,IACLU,EAAEC,iBACFD,EAAEE,kBACF,OAAAjD,EAAAsC,EAAcI,UAAS1C,EAAA9B,gBAAgBC,EAAa4E,EAAE1F,QAAS0F,EAAEzF,SAC9DyF,EAAAG,cAA8BC,kBAAkBJ,EAAEK,WAAS,EAEhEQ,cAAeP,EACfQ,YAAaP,EACbQ,gBAAiBR,KAEnB,CAACjB,EAASgB,EAAYC,IAGjB,MAAA,CACLU,UAAW3B,EACP,CACEsB,cAAed,EACfe,cAAeP,EACfQ,YAAaP,EACbQ,gBAAiBR,GAEnB,CAAC,EACLW,kBAAmBP,EACnBQ,kBAAmBH,EAEvB,uBC7FO,UAAuBI,SAAEA,KAAaC,IACrC,MAAAvG,KAAEA,EAAMwG,SAAAA,GAAaD,GACrBE,OAAEA,QAAQjE,EAAOC,OAAAA,GAAWiE,EAAAA,mBAAmB1G,EAAMwG,GACrDG,EAAajC,SAA8B,MAGjDE,EAAAA,WAAU,KACR,MAAMhF,EAAU+G,EAAW9B,QAC3B,IAAKjF,EAAS,OAER,MAAAgH,EAAqB1B,IAEzBA,EAAEE,iBAAgB,EAMdyB,EAAoB3B,IAExBA,EAAEE,iBAAgB,EAUpB,OAHAxF,EAAQkH,iBAAiB,cAAeF,EAAmB,CAAEG,SAAS,IACtEnH,EAAQkH,iBAAiB,aAAcD,EAAkB,CAAEE,SAAS,IAE7D,KACLnH,EAAQoH,oBAAoB,cAAeJ,EAAmB,CAAEG,SAAS,IACzEnH,EAAQoH,oBAAoB,aAAcH,EAAkB,CAAEE,SAAS,GAAM,CAC/E,GACC,IAEH,MAYME,EAAqC,CACzCC,MAbsC,CACtCvG,SAAU,WACVwG,KAAMnH,EAAK6C,OAAOnD,EAClB0H,IAAKpH,EAAK6C,OAAOlD,EACjB0H,UAAWZ,EACXa,gBAAiB,MACjB9E,QACAC,SACA8E,cAAe,OACfC,OAAQ,GAKRC,IAAMC,IACJf,EAAW9B,QAAU6C,CAAA,GAKvB,aAACC,EAAAA,UACErB,SAASA,EAAA,CACRW,mBACAR,SACAzG,KAAM,CACJ6C,OAAQ,CAAEnD,EAAGM,EAAK6C,OAAOnD,EAAGC,EAAGK,EAAK6C,OAAOlD,GAC3CmD,KAAM,CAAEN,QAAcC,cAKhC,8BC3EgB,SAIdmF,GACAC,MAAEA,EAAQ,gBAAKC,EAAc,IAA2B,IAElD,MAAAC,EAAOrD,SAAO,CAAEsD,EAAG,EAAGtI,EAAG,EAAGC,EAAG,IAE/BsI,EAAkBhD,EAAAA,aACrBC,IACC,IAAK0C,EAAU,OAIf,GAAsB,UAAlB1C,EAAEgD,cAA2C,IAAhBhD,EAAEiD,UAAqB,OAElD,MAAAC,EAAMC,YAAYD,MAClB1I,EAAIwF,EAAE1F,QACNG,EAAIuF,EAAEzF,QAEN6I,EAAaF,EAAML,EAAKlD,QAAQmD,GAAKH,EACrCU,EAAK7I,EAAIqI,EAAKlD,QAAQnF,EACtB8I,EAAK7I,EAAIoI,EAAKlD,QAAQlF,EAGxB2I,GAFeC,EAAKA,EAAKC,EAAKA,GAAMV,EAAcA,IAEb,MAAAF,GAAAA,EAAA1C,IAEzC6C,EAAKlD,QAAU,CAAEmD,EAAGI,EAAK1I,IAAGC,IAAE,GAEhC,CAACiI,EAAUC,EAAOC,IAGdW,EAAexD,EAAAA,aAClBC,IACY,MAAA0C,GAAAA,EAAA1C,EAAA,GAEb,CAAC0C,IAGH,OAAOA,EACF,CAECrJ,CAACA,GAAekK,EAChBC,mBAAoBT,GAEtB,CAAC,CACP,wDC1CO,SAA+BU,GAU9B,MAAAC,WACJA,EAAAC,SACAA,EAAAC,SACAA,EAAAC,gBACAA,GAAkB,EAAAC,YAClBA,EAAAC,YACAA,GACEN,GAEExC,UAAEA,EAAWC,kBAAAA,EAAAC,kBAAmBA,GAAsB/B,EAAcsE,GAwDnE,MAAA,CAAEzC,YAAW+C,OArDiBC,EAAAA,SAAQ,IJQxC,SACLC,EACAC,EAAe,IAET,MAAAC,WACJA,EAAa,EAAAnF,QACbA,EAAU,EAAAoF,WACVA,EAAa,UAAAC,aACbA,GAAe,EAAAhC,OACfA,EAAS,EAAAiC,oBACTA,GAAsB,GACpBJ,EAEE7C,GAAa4C,EAAI7H,cAAgB,GAAK,EAEtCmI,EAAOC,IAA+C,CAC1DA,CAACA,GAAO1F,EAAWqF,EAAYnF,EAASoF,GAAc,OAoBxD,MAFY,CAdV,CAAC,KAAM,IAAKG,EAAI,UAAWA,EAAI,UAC/B,CAAC,KAAM,IAAKA,EAAI,UAAWA,EAAI,WAC/B,CAAC,KAAM,IAAKA,EAAI,aAAcA,EAAI,UAClC,CAAC,KAAM,IAAKA,EAAI,aAAcA,EAAI,cAEkCF,EAClE,CACE,CAAC,IAAK,IAAKE,EAAI,OAAQvC,KAAM,cAAcmC,EAAa,SACxD,CAAC,IAAK,IAAKI,EAAI,UAAWvC,KAAM,cAAcmC,EAAa,SAC3D,CAAC,IAAK,IAAKI,EAAI,QAAStC,IAAK,cAAckC,EAAa,SACxD,CAAC,IAAK,IAAKI,EAAI,SAAUtC,IAAK,cAAckC,EAAa,UAE3D,IAIOM,KAAI,EAAE1J,EAAQ2J,MAAU,CACjC3J,SACAgH,MAAO,CACLvG,SAAU,WACV6B,MAAO8G,EAAa,KACpB7G,OAAQ6G,EAAa,KACrBQ,aAAc,MACdtC,SACAuC,OAAQN,EAAsB9F,EAAezD,EAAQsG,GAAY,UACjEwD,YAAa,UACTH,GAENI,MAAO,CAAE,mBAAoB/J,MAEjC,CIzDiBgK,CAAyBtB,EAAYC,GACtCe,KAAKO,UAAO,MAAA,CACtBC,IAAK,OAAAjI,EAAEgI,EAAAF,YAAQ,EAAA9H,EAAA,oBACf+E,MAAOiD,EAAEjD,SACNd,EAAkB+D,EAAEjK,WACnBiK,EAAEF,OAAS,CAAC,MACZ,MAAAjB,OAAA,EAAAA,EAAcmB,EAAEjK,UAAW,CAAA,EAAC,KAGjC,CACD0I,EAAWhJ,QAAQiD,OAAOnD,EAC1BkJ,EAAWhJ,QAAQiD,OAAOlD,EAC1BiJ,EAAWhJ,QAAQkD,KAAKN,MACxBoG,EAAWhJ,QAAQkD,KAAKL,OACxBmG,EAAWpH,MACXoH,EAAWrH,aACXqH,EAAWxI,oBACD,MAAVyI,OAAU,EAAAA,EAAAS,WACA,MAAVT,OAAU,EAAAA,EAAA1E,QACA,MAAV0E,OAAU,EAAAA,EAAAU,WACA,MAAVV,OAAU,EAAAA,EAAAW,aACA,MAAVX,OAAU,EAAAA,EAAArB,OACA,MAAVqB,OAAU,EAAAA,EAAAY,oBACVrD,EACA4C,IA4B0B3J,SAxBW8J,EAAAA,SAAQ,KACzC,IAACJ,EAAiB,MAAO,GAE7B,OJ4BG,SACLK,EACAC,EAAe,CAAA,EACfgB,GAEA,MAAMC,WAAEA,EAAa,GAAI9C,OAAAA,EAAS,GAAM6B,EAClCrJ,EAAaoJ,EAAIxJ,QACjB4B,EAAQ4H,EAAI5H,OAAS,EAG3B,OAFc6I,GAAgBjB,EAAI/J,UAAY,IAEjCuK,KAAI,CAACW,EAAGC,KAGZ,CACLtK,OAAQ,KACRgH,MAAO,CACLvG,SAAU,WACVwG,MANUoD,EAAE7K,EAAIM,EAAK6C,OAAOnD,GAAK8B,EAAQ8I,EAAa,EAMzC,KACblD,KANSmD,EAAE5K,EAAIK,EAAK6C,OAAOlD,GAAK6B,EAAQ8I,EAAa,EAM1C,KACX9H,MAAO8H,EAAa,KACpB7H,OAAQ6H,EAAa,KACrBR,aAAc,MACdC,OAAQ,UACRvC,SACAwC,YAAa,QAEfC,MAAO,CAAE,mBAAoBO,MAGnC,CI1DiBC,CAA2B7B,EAAYE,EAAUF,EAAWvJ,UAC7DuK,KAAI,CAACO,EAAGK,KAAO,CACzBJ,IAAKI,EACLtD,MAAOiD,EAAEjD,SACNb,EAAkBmE,MACjBL,EAAEF,OAAS,CAAC,MACE,MAAdhB,OAAc,EAAAA,EAAAuB,KAAM,CAAA,KACxB,GACD,CACDzB,EACAH,EAAWhJ,QAAQiD,OAAOnD,EAC1BkJ,EAAWhJ,QAAQiD,OAAOlD,EAC1BiJ,EAAWhJ,QAAQkD,KAAKN,MACxBoG,EAAWhJ,QAAQkD,KAAKL,OACxBmG,EAAWpH,MACXoH,EAAWvJ,SACD,MAAVyJ,OAAU,EAAAA,EAAAwB,WACA,MAAVxB,OAAU,EAAAA,EAAAtB,OACVnB,EACA4C,IAIJ"}
|
package/dist/preact/index.js
CHANGED
|
@@ -12,11 +12,9 @@ function CounterRotate({ children, ...props }) {
|
|
|
12
12
|
if (!element) return;
|
|
13
13
|
const handlePointerDown = (e) => {
|
|
14
14
|
e.stopPropagation();
|
|
15
|
-
e.preventDefault();
|
|
16
15
|
};
|
|
17
16
|
const handleTouchStart = (e) => {
|
|
18
17
|
e.stopPropagation();
|
|
19
|
-
e.preventDefault();
|
|
20
18
|
};
|
|
21
19
|
element.addEventListener("pointerdown", handlePointerDown, { capture: true });
|
|
22
20
|
element.addEventListener("touchstart", handleTouchStart, { capture: true });
|
|
@@ -483,7 +481,7 @@ function describeResizeFromConfig(cfg, ui = {}) {
|
|
|
483
481
|
} = ui;
|
|
484
482
|
const rotation = (cfg.pageRotation ?? 0) % 4;
|
|
485
483
|
const off = (edge) => ({
|
|
486
|
-
[edge]: edgeOffset(handleSize, spacing, offsetMode)
|
|
484
|
+
[edge]: edgeOffset(handleSize, spacing, offsetMode) + "px"
|
|
487
485
|
});
|
|
488
486
|
const corners = [
|
|
489
487
|
["nw", { ...off("top"), ...off("left") }],
|
|
@@ -502,8 +500,8 @@ function describeResizeFromConfig(cfg, ui = {}) {
|
|
|
502
500
|
handle,
|
|
503
501
|
style: {
|
|
504
502
|
position: "absolute",
|
|
505
|
-
width: handleSize,
|
|
506
|
-
height: handleSize,
|
|
503
|
+
width: handleSize + "px",
|
|
504
|
+
height: handleSize + "px",
|
|
507
505
|
borderRadius: "50%",
|
|
508
506
|
zIndex,
|
|
509
507
|
cursor: rotationAwareCursor ? diagonalCursor(handle, rotation) : "default",
|
|
@@ -526,10 +524,10 @@ function describeVerticesFromConfig(cfg, ui = {}, liveVertices) {
|
|
|
526
524
|
// not used; kept for type
|
|
527
525
|
style: {
|
|
528
526
|
position: "absolute",
|
|
529
|
-
left,
|
|
530
|
-
top,
|
|
531
|
-
width: vertexSize,
|
|
532
|
-
height: vertexSize,
|
|
527
|
+
left: left + "px",
|
|
528
|
+
top: top + "px",
|
|
529
|
+
width: vertexSize + "px",
|
|
530
|
+
height: vertexSize + "px",
|
|
533
531
|
borderRadius: "50%",
|
|
534
532
|
cursor: "pointer",
|
|
535
533
|
zIndex,
|
package/dist/preact/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/preact/adapter.ts","../../src/shared/components/counter-rotate-container.tsx","../../src/shared/plugin-interaction-primitives/drag-resize-controller.ts","../../src/shared/plugin-interaction-primitives/utils.ts","../../src/shared/hooks/use-drag-resize.ts","../../src/shared/hooks/use-interaction-handles.ts","../../src/shared/hooks/use-double-press-props.ts"],"sourcesContent":["import { createContext, JSX, Fragment, FunctionComponent } from 'preact';\nexport { useEffect, useRef, useState, useCallback, useMemo, useContext } from 'preact/hooks';\nexport type { ComponentChildren as ReactNode, JSX } from 'preact';\n\nexport { createContext, Fragment };\n\nexport type CSSProperties = import('preact').JSX.CSSProperties;\nexport type HTMLAttributes<T = any> = import('preact').JSX.HTMLAttributes<\n T extends EventTarget ? T : never\n>;\n\nexport type MouseEvent<T = Element> = JSX.TargetedMouseEvent<T extends EventTarget ? T : never>;\nexport type PointerEvent<T = Element> = JSX.TargetedPointerEvent<T extends EventTarget ? T : never>;\nexport type ChangeEvent<T = Element> = JSX.TargetedInputEvent<T extends EventTarget ? T : never>;\nexport type TouchEvent<T = Element> = JSX.TargetedTouchEvent<T extends EventTarget ? T : never>;\nexport type ComponentType = FunctionComponent;\n\nexport const dblClickProp = 'onDblClick' as const;\n","import { Rect, Rotation } from '@embedpdf/models';\nimport { getCounterRotation } from '@embedpdf/utils';\nimport { ReactNode, CSSProperties, Fragment, useRef, useEffect } from '@framework';\n\ninterface CounterRotateProps {\n rect: Rect;\n rotation: Rotation;\n}\n\nexport interface MenuWrapperProps {\n style: CSSProperties;\n ref: (el: HTMLDivElement | null) => void;\n}\n\ninterface CounterRotateComponentProps extends CounterRotateProps {\n children: (props: {\n matrix: string;\n rect: Rect;\n menuWrapperProps: MenuWrapperProps;\n }) => ReactNode;\n}\n\nexport function CounterRotate({ children, ...props }: CounterRotateComponentProps) {\n const { rect, rotation } = props;\n const { matrix, width, height } = getCounterRotation(rect, rotation);\n const elementRef = useRef<HTMLDivElement | null>(null);\n\n // Use native event listeners with capture phase to prevent text selection\n useEffect(() => {\n const element = elementRef.current;\n if (!element) return;\n\n const handlePointerDown = (e: Event) => {\n e.stopPropagation();\n e.preventDefault();\n };\n\n const handleTouchStart = (e: Event) => {\n e.stopPropagation();\n e.preventDefault();\n };\n\n // Use capture phase to intercept before synthetic events\n element.addEventListener('pointerdown', handlePointerDown, { capture: true });\n element.addEventListener('touchstart', handleTouchStart, { capture: true });\n\n return () => {\n element.removeEventListener('pointerdown', handlePointerDown, { capture: true });\n element.removeEventListener('touchstart', handleTouchStart, { capture: true });\n };\n }, []);\n\n const menuWrapperStyle: CSSProperties = {\n position: 'absolute',\n left: rect.origin.x,\n top: rect.origin.y,\n transform: matrix,\n transformOrigin: '0 0',\n width: width,\n height: height,\n pointerEvents: 'none',\n zIndex: 3,\n };\n\n const menuWrapperProps: MenuWrapperProps = {\n style: menuWrapperStyle,\n ref: (el: HTMLDivElement | null) => {\n elementRef.current = el;\n },\n };\n\n return (\n <Fragment>\n {children({\n menuWrapperProps,\n matrix,\n rect: {\n origin: { x: rect.origin.x, y: rect.origin.y },\n size: { width: width, height: height },\n },\n })}\n </Fragment>\n );\n}\n","import { Position, Rect } from '@embedpdf/models';\n\nexport interface DragResizeConfig {\n element: Rect;\n vertices?: Position[];\n constraints?: {\n minWidth?: number;\n minHeight?: number;\n maxWidth?: number;\n maxHeight?: number;\n boundingBox?: { width: number; height: number }; // page bounds\n };\n maintainAspectRatio?: boolean;\n pageRotation?: number;\n scale?: number;\n}\n\nexport type InteractionState = 'idle' | 'dragging' | 'resizing' | 'vertex-editing';\nexport type ResizeHandle = 'nw' | 'ne' | 'sw' | 'se' | 'n' | 'e' | 's' | 'w';\n\nexport interface TransformData {\n type: 'move' | 'resize' | 'vertex-edit';\n changes: {\n rect?: Rect;\n vertices?: Position[];\n };\n metadata?: {\n handle?: ResizeHandle;\n vertexIndex?: number;\n maintainAspectRatio?: boolean;\n };\n}\n\nexport interface InteractionEvent {\n state: 'start' | 'move' | 'end';\n transformData?: TransformData;\n}\n\n/**\n * Pure geometric controller that manages drag/resize/vertex-edit logic.\n */\nexport class DragResizeController {\n private state: InteractionState = 'idle';\n private startPoint: Position | null = null;\n private startElement: Rect | null = null;\n private activeHandle: ResizeHandle | null = null;\n private currentPosition: Rect | null = null;\n\n // Vertex editing state - pure geometric\n private activeVertexIndex: number | null = null;\n private startVertices: Position[] = [];\n private currentVertices: Position[] = [];\n\n constructor(\n private config: DragResizeConfig,\n private onUpdate: (event: InteractionEvent) => void,\n ) {\n this.currentVertices = config.vertices || [];\n }\n\n updateConfig(config: Partial<DragResizeConfig>) {\n this.config = { ...this.config, ...config };\n this.currentVertices = config.vertices || [];\n }\n\n startDrag(clientX: number, clientY: number) {\n this.state = 'dragging';\n this.startPoint = { x: clientX, y: clientY };\n this.startElement = { ...this.config.element };\n this.currentPosition = { ...this.config.element };\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'move',\n changes: {\n rect: this.startElement,\n },\n },\n });\n }\n\n startResize(handle: ResizeHandle, clientX: number, clientY: number) {\n this.state = 'resizing';\n this.activeHandle = handle;\n this.startPoint = { x: clientX, y: clientY };\n this.startElement = { ...this.config.element };\n this.currentPosition = { ...this.config.element };\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'resize',\n changes: {\n rect: this.startElement,\n },\n metadata: {\n handle: this.activeHandle,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n startVertexEdit(vertexIndex: number, clientX: number, clientY: number) {\n // Refresh vertices from latest config before validating index\n this.currentVertices = [...(this.config.vertices ?? this.currentVertices)];\n if (vertexIndex < 0 || vertexIndex >= this.currentVertices.length) return;\n\n this.state = 'vertex-editing';\n this.activeVertexIndex = vertexIndex;\n this.startPoint = { x: clientX, y: clientY };\n this.startVertices = [...this.currentVertices];\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.startVertices,\n },\n metadata: {\n vertexIndex,\n },\n },\n });\n }\n\n move(clientX: number, clientY: number) {\n if (this.state === 'idle' || !this.startPoint) return;\n\n if (this.state === 'dragging' && this.startElement) {\n const delta = this.calculateDelta(clientX, clientY);\n const position = this.calculateDragPosition(delta);\n this.currentPosition = position;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'move',\n changes: {\n rect: position,\n },\n },\n });\n } else if (this.state === 'resizing' && this.activeHandle && this.startElement) {\n const delta = this.calculateDelta(clientX, clientY);\n const position = this.calculateResizePosition(delta, this.activeHandle);\n this.currentPosition = position;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'resize',\n changes: {\n rect: position,\n },\n metadata: {\n handle: this.activeHandle,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n } else if (this.state === 'vertex-editing' && this.activeVertexIndex !== null) {\n const vertices = this.calculateVertexPosition(clientX, clientY);\n this.currentVertices = vertices;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices,\n },\n metadata: {\n vertexIndex: this.activeVertexIndex,\n },\n },\n });\n }\n }\n\n end() {\n if (this.state === 'idle') return;\n\n const wasState = this.state;\n const handle = this.activeHandle;\n const vertexIndex = this.activeVertexIndex;\n\n if (wasState === 'vertex-editing') {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.currentVertices,\n },\n metadata: {\n vertexIndex: vertexIndex || undefined,\n },\n },\n });\n } else {\n const finalPosition = this.getCurrentPosition();\n this.onUpdate({\n state: 'end',\n transformData: {\n type: wasState === 'dragging' ? 'move' : 'resize',\n changes: {\n rect: finalPosition,\n },\n metadata:\n wasState === 'dragging'\n ? undefined\n : {\n handle: handle || undefined,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n this.reset();\n }\n\n cancel() {\n if (this.state === 'idle') return;\n\n if (this.state === 'vertex-editing') {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.startVertices,\n },\n metadata: {\n vertexIndex: this.activeVertexIndex || undefined,\n },\n },\n });\n } else if (this.startElement) {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: this.state === 'dragging' ? 'move' : 'resize',\n changes: {\n rect: this.startElement,\n },\n metadata:\n this.state === 'dragging'\n ? undefined\n : {\n handle: this.activeHandle || undefined,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n this.reset();\n }\n\n private reset() {\n this.state = 'idle';\n this.startPoint = null;\n this.startElement = null;\n this.activeHandle = null;\n this.currentPosition = null;\n this.activeVertexIndex = null;\n this.startVertices = [];\n }\n\n private getCurrentPosition() {\n return this.currentPosition || this.config.element;\n }\n\n private calculateDelta(clientX: number, clientY: number): Position {\n if (!this.startPoint) return { x: 0, y: 0 };\n\n const rawDelta: Position = {\n x: clientX - this.startPoint.x,\n y: clientY - this.startPoint.y,\n };\n\n return this.transformDelta(rawDelta);\n }\n\n private transformDelta(delta: Position): Position {\n const { pageRotation = 0, scale = 1 } = this.config;\n\n const rad = (pageRotation * Math.PI) / 2;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n\n const scaledX = delta.x / scale;\n const scaledY = delta.y / scale;\n\n return {\n x: cos * scaledX + sin * scaledY,\n y: -sin * scaledX + cos * scaledY,\n };\n }\n\n private clampPoint(p: Position): Position {\n const bbox = this.config.constraints?.boundingBox;\n if (!bbox) return p;\n return {\n x: Math.max(0, Math.min(p.x, bbox.width)),\n y: Math.max(0, Math.min(p.y, bbox.height)),\n };\n }\n\n private calculateVertexPosition(clientX: number, clientY: number): Position[] {\n if (this.activeVertexIndex === null) return this.startVertices;\n\n const delta = this.calculateDelta(clientX, clientY);\n const newVertices = [...this.startVertices];\n const currentVertex = newVertices[this.activeVertexIndex];\n\n const moved = {\n x: currentVertex.x + delta.x,\n y: currentVertex.y + delta.y,\n };\n newVertices[this.activeVertexIndex] = this.clampPoint(moved);\n\n return newVertices;\n }\n\n private calculateDragPosition(delta: Position): Rect {\n if (!this.startElement) return this.config.element;\n\n const position: Rect = {\n origin: {\n x: this.startElement.origin.x + delta.x,\n y: this.startElement.origin.y + delta.y,\n },\n size: {\n width: this.startElement.size.width,\n height: this.startElement.size.height,\n },\n };\n\n return this.applyConstraints(position);\n }\n\n private calculateResizePosition(delta: Position, handle: ResizeHandle): Rect {\n if (!this.startElement) return this.config.element;\n\n let {\n origin: { x, y },\n size: { width, height },\n } = this.startElement;\n\n switch (handle) {\n case 'se':\n width += delta.x;\n height += delta.y;\n break;\n case 'sw':\n x += delta.x;\n width -= delta.x;\n height += delta.y;\n break;\n case 'ne':\n width += delta.x;\n y += delta.y;\n height -= delta.y;\n break;\n case 'nw':\n x += delta.x;\n width -= delta.x;\n y += delta.y;\n height -= delta.y;\n break;\n case 'n':\n y += delta.y;\n height -= delta.y;\n break;\n case 's':\n height += delta.y;\n break;\n case 'e':\n width += delta.x;\n break;\n case 'w':\n x += delta.x;\n width -= delta.x;\n break;\n }\n\n // Maintain aspect ratio if needed\n if (this.config.maintainAspectRatio && this.startElement) {\n const aspectRatio = this.startElement.size.width / this.startElement.size.height;\n\n if (['n', 's', 'e', 'w'].includes(handle)) {\n if (handle === 'n' || handle === 's') {\n const newWidth = height * aspectRatio;\n const widthDiff = newWidth - width;\n width = newWidth;\n x -= widthDiff / 2;\n } else {\n const newHeight = width / aspectRatio;\n const heightDiff = newHeight - height;\n height = newHeight;\n if (handle === 'w') {\n x = this.startElement.origin.x + this.startElement.size.width - width;\n }\n y -= heightDiff / 2;\n }\n } else {\n const widthChange = Math.abs(width - this.startElement.size.width);\n const heightChange = Math.abs(height - this.startElement.size.height);\n if (widthChange > heightChange) {\n height = width / aspectRatio;\n } else {\n width = height * aspectRatio;\n }\n if (handle.includes('w')) {\n x = this.startElement.origin.x + this.startElement.size.width - width;\n }\n if (handle.includes('n')) {\n y = this.startElement.origin.y + this.startElement.size.height - height;\n }\n }\n }\n\n // Handle-aware bounding box clamping to avoid shifting opposite edge\n const bbox = this.config.constraints?.boundingBox;\n if (bbox) {\n switch (handle) {\n case 'e':\n width = Math.min(width, bbox.width - x);\n break;\n case 's':\n height = Math.min(height, bbox.height - y);\n break;\n case 'se':\n width = Math.min(width, bbox.width - x);\n height = Math.min(height, bbox.height - y);\n break;\n case 'w':\n if (x < 0) {\n width += x;\n x = 0;\n }\n break;\n case 'n':\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n case 'sw':\n if (x < 0) {\n width += x;\n x = 0;\n }\n height = Math.min(height, bbox.height - y);\n break;\n case 'nw':\n if (x < 0) {\n width += x;\n x = 0;\n }\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n case 'ne':\n width = Math.min(width, bbox.width - x);\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n }\n }\n\n return this.applyConstraints({ origin: { x, y }, size: { width, height } });\n }\n\n private applyConstraints(position: Rect): Rect {\n const { constraints } = this.config;\n if (!constraints) return position;\n\n let {\n origin: { x, y },\n size: { width, height },\n } = position;\n\n // Apply size constraints\n width = Math.max(constraints.minWidth || 1, width);\n height = Math.max(constraints.minHeight || 1, height);\n\n if (constraints.maxWidth) width = Math.min(constraints.maxWidth, width);\n if (constraints.maxHeight) height = Math.min(constraints.maxHeight, height);\n\n // Apply bounding box constraints\n if (constraints.boundingBox) {\n x = Math.max(0, Math.min(x, constraints.boundingBox.width - width));\n y = Math.max(0, Math.min(y, constraints.boundingBox.height - height));\n }\n\n return { origin: { x, y }, size: { width, height } };\n }\n}\n","import type { Position, Rect } from '@embedpdf/models';\nimport type { ResizeHandle, DragResizeConfig } from './drag-resize-controller';\n\nexport type QuarterTurns = 0 | 1 | 2 | 3;\n\nexport interface ResizeUI {\n handleSize?: number; // px (default 8)\n spacing?: number; // px distance from the box edge (default 1)\n offsetMode?: 'outside' | 'inside' | 'center'; // default 'outside'\n includeSides?: boolean; // default false\n zIndex?: number; // default 3\n rotationAwareCursor?: boolean; // default true\n}\n\nexport interface VertexUI {\n vertexSize?: number; // px (default 12)\n zIndex?: number; // default 4\n}\n\nexport interface HandleDescriptor {\n handle: ResizeHandle;\n style: Record<string, number | string>;\n attrs?: Record<string, any>;\n}\n\nfunction diagonalCursor(handle: ResizeHandle, rot: QuarterTurns): string {\n // Standard cursors; diagonals flip on odd quarter-turns\n const diag0: Record<'nw' | 'ne' | 'sw' | 'se', string> = {\n nw: 'nwse-resize',\n ne: 'nesw-resize',\n sw: 'nesw-resize',\n se: 'nwse-resize',\n };\n if (handle === 'n' || handle === 's') return 'ns-resize';\n if (handle === 'e' || handle === 'w') return 'ew-resize';\n if (rot % 2 === 0) return diag0[handle as 'nw' | 'ne' | 'sw' | 'se'];\n return { nw: 'nesw-resize', ne: 'nwse-resize', sw: 'nwse-resize', se: 'nesw-resize' }[\n handle as 'nw' | 'ne' | 'sw' | 'se'\n ]!;\n}\n\nfunction edgeOffset(k: number, spacing: number, mode: 'outside' | 'inside' | 'center') {\n // Base puts the handle centered on the edge\n const base = -k / 2;\n if (mode === 'center') return base;\n // outside moves further out (more negative), inside moves in (less negative)\n return mode === 'outside' ? base - spacing : base + spacing;\n}\n\nexport function describeResizeFromConfig(\n cfg: DragResizeConfig,\n ui: ResizeUI = {},\n): HandleDescriptor[] {\n const {\n handleSize = 8,\n spacing = 1,\n offsetMode = 'outside',\n includeSides = false,\n zIndex = 3,\n rotationAwareCursor = true,\n } = ui;\n\n const rotation = ((cfg.pageRotation ?? 0) % 4) as QuarterTurns;\n\n const off = (edge: 'top' | 'right' | 'bottom' | 'left') => ({\n [edge]: edgeOffset(handleSize, spacing, offsetMode),\n });\n\n const corners: Array<[ResizeHandle, Record<string, number | string>]> = [\n ['nw', { ...off('top'), ...off('left') }],\n ['ne', { ...off('top'), ...off('right') }],\n ['sw', { ...off('bottom'), ...off('left') }],\n ['se', { ...off('bottom'), ...off('right') }],\n ];\n const sides: Array<[ResizeHandle, Record<string, number | string>]> = includeSides\n ? [\n ['n', { ...off('top'), left: `calc(50% - ${handleSize / 2}px)` }],\n ['s', { ...off('bottom'), left: `calc(50% - ${handleSize / 2}px)` }],\n ['w', { ...off('left'), top: `calc(50% - ${handleSize / 2}px)` }],\n ['e', { ...off('right'), top: `calc(50% - ${handleSize / 2}px)` }],\n ]\n : [];\n\n const all = [...corners, ...sides];\n\n return all.map(([handle, pos]) => ({\n handle,\n style: {\n position: 'absolute',\n width: handleSize,\n height: handleSize,\n borderRadius: '50%',\n zIndex,\n cursor: rotationAwareCursor ? diagonalCursor(handle, rotation) : 'default',\n touchAction: 'none',\n ...(pos as any),\n },\n attrs: { 'data-epdf-handle': handle },\n }));\n}\n\nexport function describeVerticesFromConfig(\n cfg: DragResizeConfig,\n ui: VertexUI = {},\n liveVertices?: Position[],\n): HandleDescriptor[] {\n const { vertexSize = 12, zIndex = 4 } = ui;\n const rect: Rect = cfg.element;\n const scale = cfg.scale ?? 1;\n const verts = liveVertices ?? cfg.vertices ?? [];\n\n return verts.map((v, i) => {\n const left = (v.x - rect.origin.x) * scale - vertexSize / 2;\n const top = (v.y - rect.origin.y) * scale - vertexSize / 2;\n return {\n handle: 'nw', // not used; kept for type\n style: {\n position: 'absolute',\n left,\n top,\n width: vertexSize,\n height: vertexSize,\n borderRadius: '50%',\n cursor: 'pointer',\n zIndex,\n touchAction: 'none',\n },\n attrs: { 'data-epdf-vertex': i },\n };\n });\n}\n","import { useRef, useCallback, useEffect, PointerEvent } from '@framework';\nimport {\n DragResizeController,\n DragResizeConfig,\n InteractionEvent,\n ResizeHandle,\n} from '../plugin-interaction-primitives';\n\nexport interface UseDragResizeOptions extends DragResizeConfig {\n onUpdate?: (event: InteractionEvent) => void;\n enabled?: boolean;\n}\n\nexport interface ResizeHandleEventProps {\n onPointerDown: (e: PointerEvent) => void;\n onPointerMove: (e: PointerEvent) => void;\n onPointerUp: (e: PointerEvent) => void;\n onPointerCancel: (e: PointerEvent) => void;\n}\n\nexport function useDragResize(options: UseDragResizeOptions) {\n const { onUpdate, enabled = true, ...config } = options;\n const controllerRef = useRef<DragResizeController | null>(null);\n const onUpdateRef = useRef<typeof onUpdate>(onUpdate);\n\n useEffect(() => {\n onUpdateRef.current = onUpdate;\n }, [onUpdate]);\n\n // Initialize or update controller\n useEffect(() => {\n if (!controllerRef.current) {\n controllerRef.current = new DragResizeController(config, (event) =>\n onUpdateRef.current?.(event),\n );\n } else {\n controllerRef.current.updateConfig(config);\n }\n }, [\n config.element,\n config.constraints,\n config.maintainAspectRatio,\n config.pageRotation,\n config.scale,\n config.vertices,\n ]);\n\n const handleDragStart = useCallback(\n (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startDrag(e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n [enabled],\n );\n\n const handleMove = useCallback((e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.move(e.clientX, e.clientY);\n }, []);\n\n const handleEnd = useCallback((e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.end();\n (e.currentTarget as HTMLElement).releasePointerCapture?.(e.pointerId);\n }, []);\n\n const createResizeHandler = useCallback(\n (handle: ResizeHandle): ResizeHandleEventProps => ({\n onPointerDown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startResize(handle, e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }),\n [enabled, handleMove, handleEnd],\n );\n\n const createVertexHandler = useCallback(\n (vertexIndex: number): ResizeHandleEventProps => ({\n onPointerDown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startVertexEdit(vertexIndex, e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }),\n [enabled, handleMove, handleEnd],\n );\n\n return {\n dragProps: enabled\n ? {\n onPointerDown: handleDragStart,\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }\n : {},\n createResizeProps: createResizeHandler,\n createVertexProps: createVertexHandler,\n };\n}\n","import { useMemo, PointerEvent } from '@framework';\nimport type { CSSProperties } from '@framework';\nimport { useDragResize, UseDragResizeOptions } from './use-drag-resize';\nimport {\n describeResizeFromConfig,\n describeVerticesFromConfig,\n type ResizeUI,\n type VertexUI,\n} from '../plugin-interaction-primitives/utils';\n\nexport type HandleElementProps = {\n key: string | number;\n style: CSSProperties;\n onPointerDown: (e: PointerEvent) => void;\n onPointerMove: (e: PointerEvent) => void;\n onPointerUp: (e: PointerEvent) => void;\n onPointerCancel: (e: PointerEvent) => void;\n} & Record<string, any>;\n\nexport function useInteractionHandles(opts: {\n controller: UseDragResizeOptions; // SINGLE config (rect/scale/rotation/vertices/…)\n resizeUI?: ResizeUI; // purely visual knobs\n vertexUI?: VertexUI; // purely visual knobs\n includeVertices?: boolean; // default false\n handleAttrs?: (\n h: 'nw' | 'ne' | 'sw' | 'se' | 'n' | 'e' | 's' | 'w',\n ) => Record<string, any> | void;\n vertexAttrs?: (i: number) => Record<string, any> | void;\n}) {\n const {\n controller,\n resizeUI,\n vertexUI,\n includeVertices = false,\n handleAttrs,\n vertexAttrs,\n } = opts;\n\n const { dragProps, createResizeProps, createVertexProps } = useDragResize(controller);\n\n // Resize handles: only uses data from the SAME controller config.\n const resize: HandleElementProps[] = useMemo(() => {\n const desc = describeResizeFromConfig(controller, resizeUI);\n return desc.map((d) => ({\n key: d.attrs?.['data-epdf-handle'] as string,\n style: d.style as CSSProperties,\n ...createResizeProps(d.handle),\n ...(d.attrs ?? {}),\n ...(handleAttrs?.(d.handle) ?? {}),\n }));\n // deps: controller geometry knobs + UI knobs + handler factory\n }, [\n controller.element.origin.x,\n controller.element.origin.y,\n controller.element.size.width,\n controller.element.size.height,\n controller.scale,\n controller.pageRotation,\n controller.maintainAspectRatio,\n resizeUI?.handleSize,\n resizeUI?.spacing,\n resizeUI?.offsetMode,\n resizeUI?.includeSides,\n resizeUI?.zIndex,\n resizeUI?.rotationAwareCursor,\n createResizeProps,\n handleAttrs,\n ]);\n\n // Vertex handles: same source; prefer live vertices if parent rerenders with updated cfg.vertices\n const vertices: HandleElementProps[] = useMemo(() => {\n if (!includeVertices) return [];\n const desc = describeVerticesFromConfig(controller, vertexUI, controller.vertices);\n return desc.map((d, i) => ({\n key: i,\n style: d.style as CSSProperties,\n ...createVertexProps(i),\n ...(d.attrs ?? {}),\n ...(vertexAttrs?.(i) ?? {}),\n }));\n }, [\n includeVertices,\n controller.element.origin.x,\n controller.element.origin.y,\n controller.element.size.width,\n controller.element.size.height,\n controller.scale,\n controller.vertices, // identity/content drives recalculation\n vertexUI?.vertexSize,\n vertexUI?.zIndex,\n createVertexProps,\n vertexAttrs,\n ]);\n\n return { dragProps, resize, vertices };\n}\n","import { useRef, useCallback, dblClickProp } from '@framework';\nimport type { PointerEvent } from '@framework';\n\ntype DoublePressOptions = {\n delay?: number; // ms between taps\n tolerancePx?: number; // spatial tolerance\n};\n\ntype DoubleHandler<T extends Element> = ((e: PointerEvent<T> | MouseEvent) => void) | undefined;\n\ntype DoubleProps<K extends string> = Partial<Record<K, (e: any) => void>> & {\n onPointerUp?: (e: any) => void;\n};\n\nexport function useDoublePressProps<\n T extends Element = Element,\n K extends string = typeof dblClickProp,\n>(\n onDouble?: DoubleHandler<T>,\n { delay = 300, tolerancePx = 18 }: DoublePressOptions = {},\n): DoubleProps<K> {\n const last = useRef({ t: 0, x: 0, y: 0 });\n\n const handlePointerUp = useCallback(\n (e: any) => {\n if (!onDouble) return;\n\n // Ignore mouse (it will use native dblclick),\n // and ignore non-primary pointers (multi-touch, etc.)\n if (e.pointerType === 'mouse' || e.isPrimary === false) return;\n\n const now = performance.now();\n const x = e.clientX as number;\n const y = e.clientY as number;\n\n const withinTime = now - last.current.t <= delay;\n const dx = x - last.current.x;\n const dy = y - last.current.y;\n const withinDist = dx * dx + dy * dy <= tolerancePx * tolerancePx;\n\n if (withinTime && withinDist) onDouble?.(e as PointerEvent<T>);\n\n last.current = { t: now, x, y };\n },\n [onDouble, delay, tolerancePx],\n );\n\n const handleDouble = useCallback(\n (e: any) => {\n onDouble?.(e);\n },\n [onDouble],\n );\n\n return onDouble\n ? ({\n // Computed property uses the framework’s name ('onDoubleClick' or 'onDblClick')\n [dblClickProp]: handleDouble,\n onPointerUpCapture: handlePointerUp,\n } as DoubleProps<K>)\n : {};\n}\n"],"names":[],"mappings":";;;;AAiBO,MAAM,eAAe;ACKrB,SAAS,cAAc,EAAE,UAAU,GAAG,SAAsC;AAC3E,QAAA,EAAE,MAAM,SAAA,IAAa;AAC3B,QAAM,EAAE,QAAQ,OAAO,OAAW,IAAA,mBAAmB,MAAM,QAAQ;AAC7D,QAAA,aAAa,OAA8B,IAAI;AAGrD,YAAU,MAAM;AACd,UAAM,UAAU,WAAW;AAC3B,QAAI,CAAC,QAAS;AAER,UAAA,oBAAoB,CAAC,MAAa;AACtC,QAAE,gBAAgB;AAClB,QAAE,eAAe;AAAA,IACnB;AAEM,UAAA,mBAAmB,CAAC,MAAa;AACrC,QAAE,gBAAgB;AAClB,QAAE,eAAe;AAAA,IACnB;AAGA,YAAQ,iBAAiB,eAAe,mBAAmB,EAAE,SAAS,MAAM;AAC5E,YAAQ,iBAAiB,cAAc,kBAAkB,EAAE,SAAS,MAAM;AAE1E,WAAO,MAAM;AACX,cAAQ,oBAAoB,eAAe,mBAAmB,EAAE,SAAS,MAAM;AAC/E,cAAQ,oBAAoB,cAAc,kBAAkB,EAAE,SAAS,MAAM;AAAA,IAC/E;AAAA,EACF,GAAG,EAAE;AAEL,QAAM,mBAAkC;AAAA,IACtC,UAAU;AAAA,IACV,MAAM,KAAK,OAAO;AAAA,IAClB,KAAK,KAAK,OAAO;AAAA,IACjB,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,QAAQ;AAAA,EACV;AAEA,QAAM,mBAAqC;AAAA,IACzC,OAAO;AAAA,IACP,KAAK,CAAC,OAA8B;AAClC,iBAAW,UAAU;AAAA,IAAA;AAAA,EAEzB;AAGE,SAAA,oBAAC,YACE,UAAS,SAAA;AAAA,IACR;AAAA,IACA;AAAA,IACA,MAAM;AAAA,MACJ,QAAQ,EAAE,GAAG,KAAK,OAAO,GAAG,GAAG,KAAK,OAAO,EAAE;AAAA,MAC7C,MAAM,EAAE,OAAc,OAAe;AAAA,IAAA;AAAA,EAExC,CAAA,GACH;AAEJ;AC1CO,MAAM,qBAAqB;AAAA,EAYhC,YACU,QACA,UACR;AAFQ,SAAA,SAAA;AACA,SAAA,WAAA;AAbV,SAAQ,QAA0B;AAClC,SAAQ,aAA8B;AACtC,SAAQ,eAA4B;AACpC,SAAQ,eAAoC;AAC5C,SAAQ,kBAA+B;AAGvC,SAAQ,oBAAmC;AAC3C,SAAQ,gBAA4B,CAAC;AACrC,SAAQ,kBAA8B,CAAC;AAMhC,SAAA,kBAAkB,OAAO,YAAY,CAAC;AAAA,EAAA;AAAA,EAG7C,aAAa,QAAmC;AAC9C,SAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,OAAO;AACrC,SAAA,kBAAkB,OAAO,YAAY,CAAC;AAAA,EAAA;AAAA,EAG7C,UAAU,SAAiB,SAAiB;AAC1C,SAAK,QAAQ;AACb,SAAK,aAAa,EAAE,GAAG,SAAS,GAAG,QAAQ;AAC3C,SAAK,eAAe,EAAE,GAAG,KAAK,OAAO,QAAQ;AAC7C,SAAK,kBAAkB,EAAE,GAAG,KAAK,OAAO,QAAQ;AAEhD,SAAK,SAAS;AAAA,MACZ,OAAO;AAAA,MACP,eAAe;AAAA,QACb,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM,KAAK;AAAA,QAAA;AAAA,MACb;AAAA,IACF,CACD;AAAA,EAAA;AAAA,EAGH,YAAY,QAAsB,SAAiB,SAAiB;AAClE,SAAK,QAAQ;AACb,SAAK,eAAe;AACpB,SAAK,aAAa,EAAE,GAAG,SAAS,GAAG,QAAQ;AAC3C,SAAK,eAAe,EAAE,GAAG,KAAK,OAAO,QAAQ;AAC7C,SAAK,kBAAkB,EAAE,GAAG,KAAK,OAAO,QAAQ;AAEhD,SAAK,SAAS;AAAA,MACZ,OAAO;AAAA,MACP,eAAe;AAAA,QACb,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM,KAAK;AAAA,QACb;AAAA,QACA,UAAU;AAAA,UACR,QAAQ,KAAK;AAAA,UACb,qBAAqB,KAAK,OAAO;AAAA,QAAA;AAAA,MACnC;AAAA,IACF,CACD;AAAA,EAAA;AAAA,EAGH,gBAAgB,aAAqB,SAAiB,SAAiB;AAErE,SAAK,kBAAkB,CAAC,GAAI,KAAK,OAAO,YAAY,KAAK,eAAgB;AACzE,QAAI,cAAc,KAAK,eAAe,KAAK,gBAAgB,OAAQ;AAEnE,SAAK,QAAQ;AACb,SAAK,oBAAoB;AACzB,SAAK,aAAa,EAAE,GAAG,SAAS,GAAG,QAAQ;AAC3C,SAAK,gBAAgB,CAAC,GAAG,KAAK,eAAe;AAE7C,SAAK,SAAS;AAAA,MACZ,OAAO;AAAA,MACP,eAAe;AAAA,QACb,MAAM;AAAA,QACN,SAAS;AAAA,UACP,UAAU,KAAK;AAAA,QACjB;AAAA,QACA,UAAU;AAAA,UACR;AAAA,QAAA;AAAA,MACF;AAAA,IACF,CACD;AAAA,EAAA;AAAA,EAGH,KAAK,SAAiB,SAAiB;AACrC,QAAI,KAAK,UAAU,UAAU,CAAC,KAAK,WAAY;AAE/C,QAAI,KAAK,UAAU,cAAc,KAAK,cAAc;AAClD,YAAM,QAAQ,KAAK,eAAe,SAAS,OAAO;AAC5C,YAAA,WAAW,KAAK,sBAAsB,KAAK;AACjD,WAAK,kBAAkB;AAEvB,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM;AAAA,UACN,SAAS;AAAA,YACP,MAAM;AAAA,UAAA;AAAA,QACR;AAAA,MACF,CACD;AAAA,IAAA,WACQ,KAAK,UAAU,cAAc,KAAK,gBAAgB,KAAK,cAAc;AAC9E,YAAM,QAAQ,KAAK,eAAe,SAAS,OAAO;AAClD,YAAM,WAAW,KAAK,wBAAwB,OAAO,KAAK,YAAY;AACtE,WAAK,kBAAkB;AAEvB,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM;AAAA,UACN,SAAS;AAAA,YACP,MAAM;AAAA,UACR;AAAA,UACA,UAAU;AAAA,YACR,QAAQ,KAAK;AAAA,YACb,qBAAqB,KAAK,OAAO;AAAA,UAAA;AAAA,QACnC;AAAA,MACF,CACD;AAAA,IAAA,WACQ,KAAK,UAAU,oBAAoB,KAAK,sBAAsB,MAAM;AAC7E,YAAM,WAAW,KAAK,wBAAwB,SAAS,OAAO;AAC9D,WAAK,kBAAkB;AAEvB,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM;AAAA,UACN,SAAS;AAAA,YACP;AAAA,UACF;AAAA,UACA,UAAU;AAAA,YACR,aAAa,KAAK;AAAA,UAAA;AAAA,QACpB;AAAA,MACF,CACD;AAAA,IAAA;AAAA,EACH;AAAA,EAGF,MAAM;AACA,QAAA,KAAK,UAAU,OAAQ;AAE3B,UAAM,WAAW,KAAK;AACtB,UAAM,SAAS,KAAK;AACpB,UAAM,cAAc,KAAK;AAEzB,QAAI,aAAa,kBAAkB;AACjC,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM;AAAA,UACN,SAAS;AAAA,YACP,UAAU,KAAK;AAAA,UACjB;AAAA,UACA,UAAU;AAAA,YACR,aAAa,eAAe;AAAA,UAAA;AAAA,QAC9B;AAAA,MACF,CACD;AAAA,IAAA,OACI;AACC,YAAA,gBAAgB,KAAK,mBAAmB;AAC9C,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM,aAAa,aAAa,SAAS;AAAA,UACzC,SAAS;AAAA,YACP,MAAM;AAAA,UACR;AAAA,UACA,UACE,aAAa,aACT,SACA;AAAA,YACE,QAAQ,UAAU;AAAA,YAClB,qBAAqB,KAAK,OAAO;AAAA,UAAA;AAAA,QACnC;AAAA,MACR,CACD;AAAA,IAAA;AAGH,SAAK,MAAM;AAAA,EAAA;AAAA,EAGb,SAAS;AACH,QAAA,KAAK,UAAU,OAAQ;AAEvB,QAAA,KAAK,UAAU,kBAAkB;AACnC,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM;AAAA,UACN,SAAS;AAAA,YACP,UAAU,KAAK;AAAA,UACjB;AAAA,UACA,UAAU;AAAA,YACR,aAAa,KAAK,qBAAqB;AAAA,UAAA;AAAA,QACzC;AAAA,MACF,CACD;AAAA,IAAA,WACQ,KAAK,cAAc;AAC5B,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM,KAAK,UAAU,aAAa,SAAS;AAAA,UAC3C,SAAS;AAAA,YACP,MAAM,KAAK;AAAA,UACb;AAAA,UACA,UACE,KAAK,UAAU,aACX,SACA;AAAA,YACE,QAAQ,KAAK,gBAAgB;AAAA,YAC7B,qBAAqB,KAAK,OAAO;AAAA,UAAA;AAAA,QACnC;AAAA,MACR,CACD;AAAA,IAAA;AAGH,SAAK,MAAM;AAAA,EAAA;AAAA,EAGL,QAAQ;AACd,SAAK,QAAQ;AACb,SAAK,aAAa;AAClB,SAAK,eAAe;AACpB,SAAK,eAAe;AACpB,SAAK,kBAAkB;AACvB,SAAK,oBAAoB;AACzB,SAAK,gBAAgB,CAAC;AAAA,EAAA;AAAA,EAGhB,qBAAqB;AACpB,WAAA,KAAK,mBAAmB,KAAK,OAAO;AAAA,EAAA;AAAA,EAGrC,eAAe,SAAiB,SAA2B;AAC7D,QAAA,CAAC,KAAK,WAAY,QAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAE1C,UAAM,WAAqB;AAAA,MACzB,GAAG,UAAU,KAAK,WAAW;AAAA,MAC7B,GAAG,UAAU,KAAK,WAAW;AAAA,IAC/B;AAEO,WAAA,KAAK,eAAe,QAAQ;AAAA,EAAA;AAAA,EAG7B,eAAe,OAA2B;AAChD,UAAM,EAAE,eAAe,GAAG,QAAQ,EAAA,IAAM,KAAK;AAEvC,UAAA,MAAO,eAAe,KAAK,KAAM;AACjC,UAAA,MAAM,KAAK,IAAI,GAAG;AAClB,UAAA,MAAM,KAAK,IAAI,GAAG;AAElB,UAAA,UAAU,MAAM,IAAI;AACpB,UAAA,UAAU,MAAM,IAAI;AAEnB,WAAA;AAAA,MACL,GAAG,MAAM,UAAU,MAAM;AAAA,MACzB,GAAG,CAAC,MAAM,UAAU,MAAM;AAAA,IAC5B;AAAA,EAAA;AAAA,EAGM,WAAW,GAAuB;;AAClC,UAAA,QAAO,UAAK,OAAO,gBAAZ,mBAAyB;AAClC,QAAA,CAAC,KAAa,QAAA;AACX,WAAA;AAAA,MACL,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC;AAAA,MACxC,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,IAC3C;AAAA,EAAA;AAAA,EAGM,wBAAwB,SAAiB,SAA6B;AAC5E,QAAI,KAAK,sBAAsB,KAAM,QAAO,KAAK;AAEjD,UAAM,QAAQ,KAAK,eAAe,SAAS,OAAO;AAClD,UAAM,cAAc,CAAC,GAAG,KAAK,aAAa;AACpC,UAAA,gBAAgB,YAAY,KAAK,iBAAiB;AAExD,UAAM,QAAQ;AAAA,MACZ,GAAG,cAAc,IAAI,MAAM;AAAA,MAC3B,GAAG,cAAc,IAAI,MAAM;AAAA,IAC7B;AACA,gBAAY,KAAK,iBAAiB,IAAI,KAAK,WAAW,KAAK;AAEpD,WAAA;AAAA,EAAA;AAAA,EAGD,sBAAsB,OAAuB;AACnD,QAAI,CAAC,KAAK,aAAc,QAAO,KAAK,OAAO;AAE3C,UAAM,WAAiB;AAAA,MACrB,QAAQ;AAAA,QACN,GAAG,KAAK,aAAa,OAAO,IAAI,MAAM;AAAA,QACtC,GAAG,KAAK,aAAa,OAAO,IAAI,MAAM;AAAA,MACxC;AAAA,MACA,MAAM;AAAA,QACJ,OAAO,KAAK,aAAa,KAAK;AAAA,QAC9B,QAAQ,KAAK,aAAa,KAAK;AAAA,MAAA;AAAA,IAEnC;AAEO,WAAA,KAAK,iBAAiB,QAAQ;AAAA,EAAA;AAAA,EAG/B,wBAAwB,OAAiB,QAA4B;;AAC3E,QAAI,CAAC,KAAK,aAAc,QAAO,KAAK,OAAO;AAEvC,QAAA;AAAA,MACF,QAAQ,EAAE,GAAG,EAAE;AAAA,MACf,MAAM,EAAE,OAAO,OAAO;AAAA,QACpB,KAAK;AAET,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,iBAAS,MAAM;AACf,kBAAU,MAAM;AAChB;AAAA,MACF,KAAK;AACH,aAAK,MAAM;AACX,iBAAS,MAAM;AACf,kBAAU,MAAM;AAChB;AAAA,MACF,KAAK;AACH,iBAAS,MAAM;AACf,aAAK,MAAM;AACX,kBAAU,MAAM;AAChB;AAAA,MACF,KAAK;AACH,aAAK,MAAM;AACX,iBAAS,MAAM;AACf,aAAK,MAAM;AACX,kBAAU,MAAM;AAChB;AAAA,MACF,KAAK;AACH,aAAK,MAAM;AACX,kBAAU,MAAM;AAChB;AAAA,MACF,KAAK;AACH,kBAAU,MAAM;AAChB;AAAA,MACF,KAAK;AACH,iBAAS,MAAM;AACf;AAAA,MACF,KAAK;AACH,aAAK,MAAM;AACX,iBAAS,MAAM;AACf;AAAA,IAAA;AAIJ,QAAI,KAAK,OAAO,uBAAuB,KAAK,cAAc;AACxD,YAAM,cAAc,KAAK,aAAa,KAAK,QAAQ,KAAK,aAAa,KAAK;AAEtE,UAAA,CAAC,KAAK,KAAK,KAAK,GAAG,EAAE,SAAS,MAAM,GAAG;AACrC,YAAA,WAAW,OAAO,WAAW,KAAK;AACpC,gBAAM,WAAW,SAAS;AAC1B,gBAAM,YAAY,WAAW;AACrB,kBAAA;AACR,eAAK,YAAY;AAAA,QAAA,OACZ;AACL,gBAAM,YAAY,QAAQ;AAC1B,gBAAM,aAAa,YAAY;AACtB,mBAAA;AACT,cAAI,WAAW,KAAK;AAClB,gBAAI,KAAK,aAAa,OAAO,IAAI,KAAK,aAAa,KAAK,QAAQ;AAAA,UAAA;AAElE,eAAK,aAAa;AAAA,QAAA;AAAA,MACpB,OACK;AACL,cAAM,cAAc,KAAK,IAAI,QAAQ,KAAK,aAAa,KAAK,KAAK;AACjE,cAAM,eAAe,KAAK,IAAI,SAAS,KAAK,aAAa,KAAK,MAAM;AACpE,YAAI,cAAc,cAAc;AAC9B,mBAAS,QAAQ;AAAA,QAAA,OACZ;AACL,kBAAQ,SAAS;AAAA,QAAA;AAEf,YAAA,OAAO,SAAS,GAAG,GAAG;AACxB,cAAI,KAAK,aAAa,OAAO,IAAI,KAAK,aAAa,KAAK,QAAQ;AAAA,QAAA;AAE9D,YAAA,OAAO,SAAS,GAAG,GAAG;AACxB,cAAI,KAAK,aAAa,OAAO,IAAI,KAAK,aAAa,KAAK,SAAS;AAAA,QAAA;AAAA,MACnE;AAAA,IACF;AAII,UAAA,QAAO,UAAK,OAAO,gBAAZ,mBAAyB;AACtC,QAAI,MAAM;AACR,cAAQ,QAAQ;AAAA,QACd,KAAK;AACH,kBAAQ,KAAK,IAAI,OAAO,KAAK,QAAQ,CAAC;AACtC;AAAA,QACF,KAAK;AACH,mBAAS,KAAK,IAAI,QAAQ,KAAK,SAAS,CAAC;AACzC;AAAA,QACF,KAAK;AACH,kBAAQ,KAAK,IAAI,OAAO,KAAK,QAAQ,CAAC;AACtC,mBAAS,KAAK,IAAI,QAAQ,KAAK,SAAS,CAAC;AACzC;AAAA,QACF,KAAK;AACH,cAAI,IAAI,GAAG;AACA,qBAAA;AACL,gBAAA;AAAA,UAAA;AAEN;AAAA,QACF,KAAK;AACH,cAAI,IAAI,GAAG;AACC,sBAAA;AACN,gBAAA;AAAA,UAAA;AAEN;AAAA,QACF,KAAK;AACH,cAAI,IAAI,GAAG;AACA,qBAAA;AACL,gBAAA;AAAA,UAAA;AAEN,mBAAS,KAAK,IAAI,QAAQ,KAAK,SAAS,CAAC;AACzC;AAAA,QACF,KAAK;AACH,cAAI,IAAI,GAAG;AACA,qBAAA;AACL,gBAAA;AAAA,UAAA;AAEN,cAAI,IAAI,GAAG;AACC,sBAAA;AACN,gBAAA;AAAA,UAAA;AAEN;AAAA,QACF,KAAK;AACH,kBAAQ,KAAK,IAAI,OAAO,KAAK,QAAQ,CAAC;AACtC,cAAI,IAAI,GAAG;AACC,sBAAA;AACN,gBAAA;AAAA,UAAA;AAEN;AAAA,MAAA;AAAA,IACJ;AAGF,WAAO,KAAK,iBAAiB,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,OAAO,UAAU;AAAA,EAAA;AAAA,EAGpE,iBAAiB,UAAsB;AACvC,UAAA,EAAE,gBAAgB,KAAK;AACzB,QAAA,CAAC,YAAoB,QAAA;AAErB,QAAA;AAAA,MACF,QAAQ,EAAE,GAAG,EAAE;AAAA,MACf,MAAM,EAAE,OAAO,OAAO;AAAA,IAAA,IACpB;AAGJ,YAAQ,KAAK,IAAI,YAAY,YAAY,GAAG,KAAK;AACjD,aAAS,KAAK,IAAI,YAAY,aAAa,GAAG,MAAM;AAEpD,QAAI,YAAY,SAAU,SAAQ,KAAK,IAAI,YAAY,UAAU,KAAK;AACtE,QAAI,YAAY,UAAW,UAAS,KAAK,IAAI,YAAY,WAAW,MAAM;AAG1E,QAAI,YAAY,aAAa;AACvB,UAAA,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,YAAY,YAAY,QAAQ,KAAK,CAAC;AAC9D,UAAA,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,YAAY,YAAY,SAAS,MAAM,CAAC;AAAA,IAAA;AAG/D,WAAA,EAAE,QAAQ,EAAE,GAAG,KAAK,MAAM,EAAE,OAAO,SAAS;AAAA,EAAA;AAEvD;ACleA,SAAS,eAAe,QAAsB,KAA2B;AAEvE,QAAM,QAAmD;AAAA,IACvD,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AACA,MAAI,WAAW,OAAO,WAAW,IAAY,QAAA;AAC7C,MAAI,WAAW,OAAO,WAAW,IAAY,QAAA;AAC7C,MAAI,MAAM,MAAM,EAAG,QAAO,MAAM,MAAmC;AAC5D,SAAA,EAAE,IAAI,eAAe,IAAI,eAAe,IAAI,eAAe,IAAI,cAAc,EAClF,MACF;AACF;AAEA,SAAS,WAAW,GAAW,SAAiB,MAAuC;AAE/E,QAAA,OAAO,CAAC,IAAI;AACd,MAAA,SAAS,SAAiB,QAAA;AAE9B,SAAO,SAAS,YAAY,OAAO,UAAU,OAAO;AACtD;AAEO,SAAS,yBACd,KACA,KAAe,IACK;AACd,QAAA;AAAA,IACJ,aAAa;AAAA,IACb,UAAU;AAAA,IACV,aAAa;AAAA,IACb,eAAe;AAAA,IACf,SAAS;AAAA,IACT,sBAAsB;AAAA,EAAA,IACpB;AAEE,QAAA,YAAa,IAAI,gBAAgB,KAAK;AAEtC,QAAA,MAAM,CAAC,UAA+C;AAAA,IAC1D,CAAC,IAAI,GAAG,WAAW,YAAY,SAAS,UAAU;AAAA,EAAA;AAGpD,QAAM,UAAkE;AAAA,IACtE,CAAC,MAAM,EAAE,GAAG,IAAI,KAAK,GAAG,GAAG,IAAI,MAAM,GAAG;AAAA,IACxC,CAAC,MAAM,EAAE,GAAG,IAAI,KAAK,GAAG,GAAG,IAAI,OAAO,GAAG;AAAA,IACzC,CAAC,MAAM,EAAE,GAAG,IAAI,QAAQ,GAAG,GAAG,IAAI,MAAM,GAAG;AAAA,IAC3C,CAAC,MAAM,EAAE,GAAG,IAAI,QAAQ,GAAG,GAAG,IAAI,OAAO,EAAG,CAAA;AAAA,EAC9C;AACA,QAAM,QAAgE,eAClE;AAAA,IACE,CAAC,KAAK,EAAE,GAAG,IAAI,KAAK,GAAG,MAAM,cAAc,aAAa,CAAC,MAAA,CAAO;AAAA,IAChE,CAAC,KAAK,EAAE,GAAG,IAAI,QAAQ,GAAG,MAAM,cAAc,aAAa,CAAC,MAAA,CAAO;AAAA,IACnE,CAAC,KAAK,EAAE,GAAG,IAAI,MAAM,GAAG,KAAK,cAAc,aAAa,CAAC,MAAA,CAAO;AAAA,IAChE,CAAC,KAAK,EAAE,GAAG,IAAI,OAAO,GAAG,KAAK,cAAc,aAAa,CAAC,MAAO,CAAA;AAAA,EAAA,IAEnE,CAAC;AAEL,QAAM,MAAM,CAAC,GAAG,SAAS,GAAG,KAAK;AAEjC,SAAO,IAAI,IAAI,CAAC,CAAC,QAAQ,GAAG,OAAO;AAAA,IACjC;AAAA,IACA,OAAO;AAAA,MACL,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,cAAc;AAAA,MACd;AAAA,MACA,QAAQ,sBAAsB,eAAe,QAAQ,QAAQ,IAAI;AAAA,MACjE,aAAa;AAAA,MACb,GAAI;AAAA,IACN;AAAA,IACA,OAAO,EAAE,oBAAoB,OAAO;AAAA,EAAA,EACpC;AACJ;AAEO,SAAS,2BACd,KACA,KAAe,CAAA,GACf,cACoB;AACpB,QAAM,EAAE,aAAa,IAAI,SAAS,EAAM,IAAA;AACxC,QAAM,OAAa,IAAI;AACjB,QAAA,QAAQ,IAAI,SAAS;AAC3B,QAAM,QAAQ,gBAAgB,IAAI,YAAY,CAAC;AAE/C,SAAO,MAAM,IAAI,CAAC,GAAG,MAAM;AACzB,UAAM,QAAQ,EAAE,IAAI,KAAK,OAAO,KAAK,QAAQ,aAAa;AAC1D,UAAM,OAAO,EAAE,IAAI,KAAK,OAAO,KAAK,QAAQ,aAAa;AAClD,WAAA;AAAA,MACL,QAAQ;AAAA;AAAA,MACR,OAAO;AAAA,QACL,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,QAAQ;AAAA,QACR;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA,OAAO,EAAE,oBAAoB,EAAE;AAAA,IACjC;AAAA,EAAA,CACD;AACH;AC9GO,SAAS,cAAc,SAA+B;AAC3D,QAAM,EAAE,UAAU,UAAU,MAAM,GAAG,OAAW,IAAA;AAC1C,QAAA,gBAAgB,OAAoC,IAAI;AACxD,QAAA,cAAc,OAAwB,QAAQ;AAEpD,YAAU,MAAM;AACd,gBAAY,UAAU;AAAA,EAAA,GACrB,CAAC,QAAQ,CAAC;AAGb,YAAU,MAAM;AACV,QAAA,CAAC,cAAc,SAAS;AAC1B,oBAAc,UAAU,IAAI;AAAA,QAAqB;AAAA,QAAQ,CAAC,UAAA;;AACxD,mCAAY,YAAZ,qCAAsB;AAAA;AAAA,MACxB;AAAA,IAAA,OACK;AACS,oBAAA,QAAQ,aAAa,MAAM;AAAA,IAAA;AAAA,EAC3C,GACC;AAAA,IACD,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,EAAA,CACR;AAED,QAAM,kBAAkB;AAAA,IACtB,CAAC,MAAoB;;AACnB,UAAI,CAAC,QAAS;AACd,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,0BAAc,YAAd,mBAAuB,UAAU,EAAE,SAAS,EAAE;AAC7C,QAAE,cAA8B,kBAAkB,EAAE,SAAS;AAAA,IAChE;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEM,QAAA,aAAa,YAAY,CAAC,MAAoB;;AAClD,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAClB,wBAAc,YAAd,mBAAuB,KAAK,EAAE,SAAS,EAAE;AAAA,EAC3C,GAAG,EAAE;AAEC,QAAA,YAAY,YAAY,CAAC,MAAoB;;AACjD,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAClB,wBAAc,YAAd,mBAAuB;AACtB,kBAAE,eAA8B,0BAAhC,4BAAwD,EAAE;AAAA,EAC7D,GAAG,EAAE;AAEL,QAAM,sBAAsB;AAAA,IAC1B,CAAC,YAAkD;AAAA,MACjD,eAAe,CAAC,MAAoB;;AAClC,YAAI,CAAC,QAAS;AACd,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB,4BAAc,YAAd,mBAAuB,YAAY,QAAQ,EAAE,SAAS,EAAE;AACvD,UAAE,cAA8B,kBAAkB,EAAE,SAAS;AAAA,MAChE;AAAA,MACA,eAAe;AAAA,MACf,aAAa;AAAA,MACb,iBAAiB;AAAA,IAAA;AAAA,IAEnB,CAAC,SAAS,YAAY,SAAS;AAAA,EACjC;AAEA,QAAM,sBAAsB;AAAA,IAC1B,CAAC,iBAAiD;AAAA,MAChD,eAAe,CAAC,MAAoB;;AAClC,YAAI,CAAC,QAAS;AACd,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB,4BAAc,YAAd,mBAAuB,gBAAgB,aAAa,EAAE,SAAS,EAAE;AAChE,UAAE,cAA8B,kBAAkB,EAAE,SAAS;AAAA,MAChE;AAAA,MACA,eAAe;AAAA,MACf,aAAa;AAAA,MACb,iBAAiB;AAAA,IAAA;AAAA,IAEnB,CAAC,SAAS,YAAY,SAAS;AAAA,EACjC;AAEO,SAAA;AAAA,IACL,WAAW,UACP;AAAA,MACE,eAAe;AAAA,MACf,eAAe;AAAA,MACf,aAAa;AAAA,MACb,iBAAiB;AAAA,IAAA,IAEnB,CAAC;AAAA,IACL,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,EACrB;AACF;AChGO,SAAS,sBAAsB,MASnC;AACK,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,EAAA,IACE;AAEJ,QAAM,EAAE,WAAW,mBAAmB,kBAAkB,IAAI,cAAc,UAAU;AAG9E,QAAA,SAA+B,QAAQ,MAAM;AAC3C,UAAA,OAAO,yBAAyB,YAAY,QAAQ;AACnD,WAAA,KAAK,IAAI,CAAC,MAAO;;AAAA;AAAA,QACtB,MAAK,OAAE,UAAF,mBAAU;AAAA,QACf,OAAO,EAAE;AAAA,QACT,GAAG,kBAAkB,EAAE,MAAM;AAAA,QAC7B,GAAI,EAAE,SAAS,CAAC;AAAA,QAChB,IAAI,2CAAc,EAAE,YAAW,CAAA;AAAA,MAAC;AAAA,KAChC;AAAA,EAAA,GAED;AAAA,IACD,WAAW,QAAQ,OAAO;AAAA,IAC1B,WAAW,QAAQ,OAAO;AAAA,IAC1B,WAAW,QAAQ,KAAK;AAAA,IACxB,WAAW,QAAQ,KAAK;AAAA,IACxB,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,qCAAU;AAAA,IACV,qCAAU;AAAA,IACV,qCAAU;AAAA,IACV,qCAAU;AAAA,IACV,qCAAU;AAAA,IACV,qCAAU;AAAA,IACV;AAAA,IACA;AAAA,EAAA,CACD;AAGK,QAAA,WAAiC,QAAQ,MAAM;AAC/C,QAAA,CAAC,gBAAiB,QAAO,CAAC;AAC9B,UAAM,OAAO,2BAA2B,YAAY,UAAU,WAAW,QAAQ;AACjF,WAAO,KAAK,IAAI,CAAC,GAAG,OAAO;AAAA,MACzB,KAAK;AAAA,MACL,OAAO,EAAE;AAAA,MACT,GAAG,kBAAkB,CAAC;AAAA,MACtB,GAAI,EAAE,SAAS,CAAC;AAAA,MAChB,IAAI,2CAAc,OAAM,CAAA;AAAA,IAAC,EACzB;AAAA,EAAA,GACD;AAAA,IACD;AAAA,IACA,WAAW,QAAQ,OAAO;AAAA,IAC1B,WAAW,QAAQ,OAAO;AAAA,IAC1B,WAAW,QAAQ,KAAK;AAAA,IACxB,WAAW,QAAQ,KAAK;AAAA,IACxB,WAAW;AAAA,IACX,WAAW;AAAA;AAAA,IACX,qCAAU;AAAA,IACV,qCAAU;AAAA,IACV;AAAA,IACA;AAAA,EAAA,CACD;AAEM,SAAA,EAAE,WAAW,QAAQ,SAAS;AACvC;ACjFgB,SAAA,oBAId,UACA,EAAE,QAAQ,KAAK,cAAc,GAA2B,IAAA,IACxC;AACV,QAAA,OAAO,OAAO,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG;AAExC,QAAM,kBAAkB;AAAA,IACtB,CAAC,MAAW;AACV,UAAI,CAAC,SAAU;AAIf,UAAI,EAAE,gBAAgB,WAAW,EAAE,cAAc,MAAO;AAElD,YAAA,MAAM,YAAY,IAAI;AAC5B,YAAM,IAAI,EAAE;AACZ,YAAM,IAAI,EAAE;AAEZ,YAAM,aAAa,MAAM,KAAK,QAAQ,KAAK;AACrC,YAAA,KAAK,IAAI,KAAK,QAAQ;AACtB,YAAA,KAAK,IAAI,KAAK,QAAQ;AAC5B,YAAM,aAAa,KAAK,KAAK,KAAK,MAAM,cAAc;AAElD,UAAA,cAAc,WAAY,sCAAW;AAEzC,WAAK,UAAU,EAAE,GAAG,KAAK,GAAG,EAAE;AAAA,IAChC;AAAA,IACA,CAAC,UAAU,OAAO,WAAW;AAAA,EAC/B;AAEA,QAAM,eAAe;AAAA,IACnB,CAAC,MAAW;AACV,2CAAW;AAAA,IACb;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,SAAO,WACF;AAAA;AAAA,IAEC,CAAC,YAAY,GAAG;AAAA,IAChB,oBAAoB;AAAA,EAAA,IAEtB,CAAC;AACP;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/preact/adapter.ts","../../src/shared/components/counter-rotate-container.tsx","../../src/shared/plugin-interaction-primitives/drag-resize-controller.ts","../../src/shared/plugin-interaction-primitives/utils.ts","../../src/shared/hooks/use-drag-resize.ts","../../src/shared/hooks/use-interaction-handles.ts","../../src/shared/hooks/use-double-press-props.ts"],"sourcesContent":["import { createContext, JSX, Fragment, FunctionComponent } from 'preact';\nexport { useEffect, useRef, useState, useCallback, useMemo, useContext } from 'preact/hooks';\nexport type { ComponentChildren as ReactNode, JSX } from 'preact';\n\nexport { createContext, Fragment };\n\nexport type CSSProperties = import('preact').JSX.CSSProperties;\nexport type HTMLAttributes<T = any> = import('preact').JSX.HTMLAttributes<\n T extends EventTarget ? T : never\n>;\n\nexport type MouseEvent<T = Element> = JSX.TargetedMouseEvent<T extends EventTarget ? T : never>;\nexport type PointerEvent<T = Element> = JSX.TargetedPointerEvent<T extends EventTarget ? T : never>;\nexport type ChangeEvent<T = Element> = JSX.TargetedInputEvent<T extends EventTarget ? T : never>;\nexport type TouchEvent<T = Element> = JSX.TargetedTouchEvent<T extends EventTarget ? T : never>;\nexport type ComponentType = FunctionComponent;\n\nexport const dblClickProp = 'onDblClick' as const;\n","import { Rect, Rotation } from '@embedpdf/models';\nimport { getCounterRotation } from '@embedpdf/utils';\nimport { ReactNode, CSSProperties, Fragment, useRef, useEffect } from '@framework';\n\ninterface CounterRotateProps {\n rect: Rect;\n rotation: Rotation;\n}\n\nexport interface MenuWrapperProps {\n style: CSSProperties;\n ref: (el: HTMLDivElement | null) => void;\n}\n\ninterface CounterRotateComponentProps extends CounterRotateProps {\n children: (props: {\n matrix: string;\n rect: Rect;\n menuWrapperProps: MenuWrapperProps;\n }) => ReactNode;\n}\n\nexport function CounterRotate({ children, ...props }: CounterRotateComponentProps) {\n const { rect, rotation } = props;\n const { matrix, width, height } = getCounterRotation(rect, rotation);\n const elementRef = useRef<HTMLDivElement | null>(null);\n\n // Use native event listeners with capture phase to prevent event propagation\n useEffect(() => {\n const element = elementRef.current;\n if (!element) return;\n\n const handlePointerDown = (e: Event) => {\n // Stop propagation to prevent underlying layers from receiving the event\n e.stopPropagation();\n // DO NOT use e.preventDefault() here - it breaks click events on mobile/tablet!\n // preventDefault() stops the browser from generating click events from touch,\n // which makes buttons inside this container non-functional on touch devices.\n };\n\n const handleTouchStart = (e: Event) => {\n // Stop propagation to prevent underlying layers from receiving the event\n e.stopPropagation();\n // DO NOT use e.preventDefault() here - it breaks click events on mobile/tablet!\n // preventDefault() stops the browser from generating click events from touch,\n // which makes buttons inside this container non-functional on touch devices.\n };\n\n // Use capture phase to intercept before synthetic events\n element.addEventListener('pointerdown', handlePointerDown, { capture: true });\n element.addEventListener('touchstart', handleTouchStart, { capture: true });\n\n return () => {\n element.removeEventListener('pointerdown', handlePointerDown, { capture: true });\n element.removeEventListener('touchstart', handleTouchStart, { capture: true });\n };\n }, []);\n\n const menuWrapperStyle: CSSProperties = {\n position: 'absolute',\n left: rect.origin.x,\n top: rect.origin.y,\n transform: matrix,\n transformOrigin: '0 0',\n width: width,\n height: height,\n pointerEvents: 'none',\n zIndex: 3,\n };\n\n const menuWrapperProps: MenuWrapperProps = {\n style: menuWrapperStyle,\n ref: (el: HTMLDivElement | null) => {\n elementRef.current = el;\n },\n };\n\n return (\n <Fragment>\n {children({\n menuWrapperProps,\n matrix,\n rect: {\n origin: { x: rect.origin.x, y: rect.origin.y },\n size: { width: width, height: height },\n },\n })}\n </Fragment>\n );\n}\n","import { Position, Rect } from '@embedpdf/models';\n\nexport interface DragResizeConfig {\n element: Rect;\n vertices?: Position[];\n constraints?: {\n minWidth?: number;\n minHeight?: number;\n maxWidth?: number;\n maxHeight?: number;\n boundingBox?: { width: number; height: number }; // page bounds\n };\n maintainAspectRatio?: boolean;\n pageRotation?: number;\n scale?: number;\n}\n\nexport type InteractionState = 'idle' | 'dragging' | 'resizing' | 'vertex-editing';\nexport type ResizeHandle = 'nw' | 'ne' | 'sw' | 'se' | 'n' | 'e' | 's' | 'w';\n\nexport interface TransformData {\n type: 'move' | 'resize' | 'vertex-edit';\n changes: {\n rect?: Rect;\n vertices?: Position[];\n };\n metadata?: {\n handle?: ResizeHandle;\n vertexIndex?: number;\n maintainAspectRatio?: boolean;\n };\n}\n\nexport interface InteractionEvent {\n state: 'start' | 'move' | 'end';\n transformData?: TransformData;\n}\n\n/**\n * Pure geometric controller that manages drag/resize/vertex-edit logic.\n */\nexport class DragResizeController {\n private state: InteractionState = 'idle';\n private startPoint: Position | null = null;\n private startElement: Rect | null = null;\n private activeHandle: ResizeHandle | null = null;\n private currentPosition: Rect | null = null;\n\n // Vertex editing state - pure geometric\n private activeVertexIndex: number | null = null;\n private startVertices: Position[] = [];\n private currentVertices: Position[] = [];\n\n constructor(\n private config: DragResizeConfig,\n private onUpdate: (event: InteractionEvent) => void,\n ) {\n this.currentVertices = config.vertices || [];\n }\n\n updateConfig(config: Partial<DragResizeConfig>) {\n this.config = { ...this.config, ...config };\n this.currentVertices = config.vertices || [];\n }\n\n startDrag(clientX: number, clientY: number) {\n this.state = 'dragging';\n this.startPoint = { x: clientX, y: clientY };\n this.startElement = { ...this.config.element };\n this.currentPosition = { ...this.config.element };\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'move',\n changes: {\n rect: this.startElement,\n },\n },\n });\n }\n\n startResize(handle: ResizeHandle, clientX: number, clientY: number) {\n this.state = 'resizing';\n this.activeHandle = handle;\n this.startPoint = { x: clientX, y: clientY };\n this.startElement = { ...this.config.element };\n this.currentPosition = { ...this.config.element };\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'resize',\n changes: {\n rect: this.startElement,\n },\n metadata: {\n handle: this.activeHandle,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n startVertexEdit(vertexIndex: number, clientX: number, clientY: number) {\n // Refresh vertices from latest config before validating index\n this.currentVertices = [...(this.config.vertices ?? this.currentVertices)];\n if (vertexIndex < 0 || vertexIndex >= this.currentVertices.length) return;\n\n this.state = 'vertex-editing';\n this.activeVertexIndex = vertexIndex;\n this.startPoint = { x: clientX, y: clientY };\n this.startVertices = [...this.currentVertices];\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.startVertices,\n },\n metadata: {\n vertexIndex,\n },\n },\n });\n }\n\n move(clientX: number, clientY: number) {\n if (this.state === 'idle' || !this.startPoint) return;\n\n if (this.state === 'dragging' && this.startElement) {\n const delta = this.calculateDelta(clientX, clientY);\n const position = this.calculateDragPosition(delta);\n this.currentPosition = position;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'move',\n changes: {\n rect: position,\n },\n },\n });\n } else if (this.state === 'resizing' && this.activeHandle && this.startElement) {\n const delta = this.calculateDelta(clientX, clientY);\n const position = this.calculateResizePosition(delta, this.activeHandle);\n this.currentPosition = position;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'resize',\n changes: {\n rect: position,\n },\n metadata: {\n handle: this.activeHandle,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n } else if (this.state === 'vertex-editing' && this.activeVertexIndex !== null) {\n const vertices = this.calculateVertexPosition(clientX, clientY);\n this.currentVertices = vertices;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices,\n },\n metadata: {\n vertexIndex: this.activeVertexIndex,\n },\n },\n });\n }\n }\n\n end() {\n if (this.state === 'idle') return;\n\n const wasState = this.state;\n const handle = this.activeHandle;\n const vertexIndex = this.activeVertexIndex;\n\n if (wasState === 'vertex-editing') {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.currentVertices,\n },\n metadata: {\n vertexIndex: vertexIndex || undefined,\n },\n },\n });\n } else {\n const finalPosition = this.getCurrentPosition();\n this.onUpdate({\n state: 'end',\n transformData: {\n type: wasState === 'dragging' ? 'move' : 'resize',\n changes: {\n rect: finalPosition,\n },\n metadata:\n wasState === 'dragging'\n ? undefined\n : {\n handle: handle || undefined,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n this.reset();\n }\n\n cancel() {\n if (this.state === 'idle') return;\n\n if (this.state === 'vertex-editing') {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: 'vertex-edit',\n changes: {\n vertices: this.startVertices,\n },\n metadata: {\n vertexIndex: this.activeVertexIndex || undefined,\n },\n },\n });\n } else if (this.startElement) {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: this.state === 'dragging' ? 'move' : 'resize',\n changes: {\n rect: this.startElement,\n },\n metadata:\n this.state === 'dragging'\n ? undefined\n : {\n handle: this.activeHandle || undefined,\n maintainAspectRatio: this.config.maintainAspectRatio,\n },\n },\n });\n }\n\n this.reset();\n }\n\n private reset() {\n this.state = 'idle';\n this.startPoint = null;\n this.startElement = null;\n this.activeHandle = null;\n this.currentPosition = null;\n this.activeVertexIndex = null;\n this.startVertices = [];\n }\n\n private getCurrentPosition() {\n return this.currentPosition || this.config.element;\n }\n\n private calculateDelta(clientX: number, clientY: number): Position {\n if (!this.startPoint) return { x: 0, y: 0 };\n\n const rawDelta: Position = {\n x: clientX - this.startPoint.x,\n y: clientY - this.startPoint.y,\n };\n\n return this.transformDelta(rawDelta);\n }\n\n private transformDelta(delta: Position): Position {\n const { pageRotation = 0, scale = 1 } = this.config;\n\n const rad = (pageRotation * Math.PI) / 2;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n\n const scaledX = delta.x / scale;\n const scaledY = delta.y / scale;\n\n return {\n x: cos * scaledX + sin * scaledY,\n y: -sin * scaledX + cos * scaledY,\n };\n }\n\n private clampPoint(p: Position): Position {\n const bbox = this.config.constraints?.boundingBox;\n if (!bbox) return p;\n return {\n x: Math.max(0, Math.min(p.x, bbox.width)),\n y: Math.max(0, Math.min(p.y, bbox.height)),\n };\n }\n\n private calculateVertexPosition(clientX: number, clientY: number): Position[] {\n if (this.activeVertexIndex === null) return this.startVertices;\n\n const delta = this.calculateDelta(clientX, clientY);\n const newVertices = [...this.startVertices];\n const currentVertex = newVertices[this.activeVertexIndex];\n\n const moved = {\n x: currentVertex.x + delta.x,\n y: currentVertex.y + delta.y,\n };\n newVertices[this.activeVertexIndex] = this.clampPoint(moved);\n\n return newVertices;\n }\n\n private calculateDragPosition(delta: Position): Rect {\n if (!this.startElement) return this.config.element;\n\n const position: Rect = {\n origin: {\n x: this.startElement.origin.x + delta.x,\n y: this.startElement.origin.y + delta.y,\n },\n size: {\n width: this.startElement.size.width,\n height: this.startElement.size.height,\n },\n };\n\n return this.applyConstraints(position);\n }\n\n private calculateResizePosition(delta: Position, handle: ResizeHandle): Rect {\n if (!this.startElement) return this.config.element;\n\n let {\n origin: { x, y },\n size: { width, height },\n } = this.startElement;\n\n switch (handle) {\n case 'se':\n width += delta.x;\n height += delta.y;\n break;\n case 'sw':\n x += delta.x;\n width -= delta.x;\n height += delta.y;\n break;\n case 'ne':\n width += delta.x;\n y += delta.y;\n height -= delta.y;\n break;\n case 'nw':\n x += delta.x;\n width -= delta.x;\n y += delta.y;\n height -= delta.y;\n break;\n case 'n':\n y += delta.y;\n height -= delta.y;\n break;\n case 's':\n height += delta.y;\n break;\n case 'e':\n width += delta.x;\n break;\n case 'w':\n x += delta.x;\n width -= delta.x;\n break;\n }\n\n // Maintain aspect ratio if needed\n if (this.config.maintainAspectRatio && this.startElement) {\n const aspectRatio = this.startElement.size.width / this.startElement.size.height;\n\n if (['n', 's', 'e', 'w'].includes(handle)) {\n if (handle === 'n' || handle === 's') {\n const newWidth = height * aspectRatio;\n const widthDiff = newWidth - width;\n width = newWidth;\n x -= widthDiff / 2;\n } else {\n const newHeight = width / aspectRatio;\n const heightDiff = newHeight - height;\n height = newHeight;\n if (handle === 'w') {\n x = this.startElement.origin.x + this.startElement.size.width - width;\n }\n y -= heightDiff / 2;\n }\n } else {\n const widthChange = Math.abs(width - this.startElement.size.width);\n const heightChange = Math.abs(height - this.startElement.size.height);\n if (widthChange > heightChange) {\n height = width / aspectRatio;\n } else {\n width = height * aspectRatio;\n }\n if (handle.includes('w')) {\n x = this.startElement.origin.x + this.startElement.size.width - width;\n }\n if (handle.includes('n')) {\n y = this.startElement.origin.y + this.startElement.size.height - height;\n }\n }\n }\n\n // Handle-aware bounding box clamping to avoid shifting opposite edge\n const bbox = this.config.constraints?.boundingBox;\n if (bbox) {\n switch (handle) {\n case 'e':\n width = Math.min(width, bbox.width - x);\n break;\n case 's':\n height = Math.min(height, bbox.height - y);\n break;\n case 'se':\n width = Math.min(width, bbox.width - x);\n height = Math.min(height, bbox.height - y);\n break;\n case 'w':\n if (x < 0) {\n width += x;\n x = 0;\n }\n break;\n case 'n':\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n case 'sw':\n if (x < 0) {\n width += x;\n x = 0;\n }\n height = Math.min(height, bbox.height - y);\n break;\n case 'nw':\n if (x < 0) {\n width += x;\n x = 0;\n }\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n case 'ne':\n width = Math.min(width, bbox.width - x);\n if (y < 0) {\n height += y;\n y = 0;\n }\n break;\n }\n }\n\n return this.applyConstraints({ origin: { x, y }, size: { width, height } });\n }\n\n private applyConstraints(position: Rect): Rect {\n const { constraints } = this.config;\n if (!constraints) return position;\n\n let {\n origin: { x, y },\n size: { width, height },\n } = position;\n\n // Apply size constraints\n width = Math.max(constraints.minWidth || 1, width);\n height = Math.max(constraints.minHeight || 1, height);\n\n if (constraints.maxWidth) width = Math.min(constraints.maxWidth, width);\n if (constraints.maxHeight) height = Math.min(constraints.maxHeight, height);\n\n // Apply bounding box constraints\n if (constraints.boundingBox) {\n x = Math.max(0, Math.min(x, constraints.boundingBox.width - width));\n y = Math.max(0, Math.min(y, constraints.boundingBox.height - height));\n }\n\n return { origin: { x, y }, size: { width, height } };\n }\n}\n","import type { Position, Rect } from '@embedpdf/models';\nimport type { ResizeHandle, DragResizeConfig } from './drag-resize-controller';\n\nexport type QuarterTurns = 0 | 1 | 2 | 3;\n\nexport interface ResizeUI {\n handleSize?: number; // px (default 8)\n spacing?: number; // px distance from the box edge (default 1)\n offsetMode?: 'outside' | 'inside' | 'center'; // default 'outside'\n includeSides?: boolean; // default false\n zIndex?: number; // default 3\n rotationAwareCursor?: boolean; // default true\n}\n\nexport interface VertexUI {\n vertexSize?: number; // px (default 12)\n zIndex?: number; // default 4\n}\n\nexport interface HandleDescriptor {\n handle: ResizeHandle;\n style: Record<string, number | string>;\n attrs?: Record<string, any>;\n}\n\nfunction diagonalCursor(handle: ResizeHandle, rot: QuarterTurns): string {\n // Standard cursors; diagonals flip on odd quarter-turns\n const diag0: Record<'nw' | 'ne' | 'sw' | 'se', string> = {\n nw: 'nwse-resize',\n ne: 'nesw-resize',\n sw: 'nesw-resize',\n se: 'nwse-resize',\n };\n if (handle === 'n' || handle === 's') return 'ns-resize';\n if (handle === 'e' || handle === 'w') return 'ew-resize';\n if (rot % 2 === 0) return diag0[handle as 'nw' | 'ne' | 'sw' | 'se'];\n return { nw: 'nesw-resize', ne: 'nwse-resize', sw: 'nwse-resize', se: 'nesw-resize' }[\n handle as 'nw' | 'ne' | 'sw' | 'se'\n ]!;\n}\n\nfunction edgeOffset(k: number, spacing: number, mode: 'outside' | 'inside' | 'center') {\n // Base puts the handle centered on the edge\n const base = -k / 2;\n if (mode === 'center') return base;\n // outside moves further out (more negative), inside moves in (less negative)\n return mode === 'outside' ? base - spacing : base + spacing;\n}\n\nexport function describeResizeFromConfig(\n cfg: DragResizeConfig,\n ui: ResizeUI = {},\n): HandleDescriptor[] {\n const {\n handleSize = 8,\n spacing = 1,\n offsetMode = 'outside',\n includeSides = false,\n zIndex = 3,\n rotationAwareCursor = true,\n } = ui;\n\n const rotation = ((cfg.pageRotation ?? 0) % 4) as QuarterTurns;\n\n const off = (edge: 'top' | 'right' | 'bottom' | 'left') => ({\n [edge]: edgeOffset(handleSize, spacing, offsetMode) + 'px',\n });\n\n const corners: Array<[ResizeHandle, Record<string, number | string>]> = [\n ['nw', { ...off('top'), ...off('left') }],\n ['ne', { ...off('top'), ...off('right') }],\n ['sw', { ...off('bottom'), ...off('left') }],\n ['se', { ...off('bottom'), ...off('right') }],\n ];\n const sides: Array<[ResizeHandle, Record<string, number | string>]> = includeSides\n ? [\n ['n', { ...off('top'), left: `calc(50% - ${handleSize / 2}px)` }],\n ['s', { ...off('bottom'), left: `calc(50% - ${handleSize / 2}px)` }],\n ['w', { ...off('left'), top: `calc(50% - ${handleSize / 2}px)` }],\n ['e', { ...off('right'), top: `calc(50% - ${handleSize / 2}px)` }],\n ]\n : [];\n\n const all = [...corners, ...sides];\n\n return all.map(([handle, pos]) => ({\n handle,\n style: {\n position: 'absolute',\n width: handleSize + 'px',\n height: handleSize + 'px',\n borderRadius: '50%',\n zIndex,\n cursor: rotationAwareCursor ? diagonalCursor(handle, rotation) : 'default',\n touchAction: 'none',\n ...(pos as any),\n },\n attrs: { 'data-epdf-handle': handle },\n }));\n}\n\nexport function describeVerticesFromConfig(\n cfg: DragResizeConfig,\n ui: VertexUI = {},\n liveVertices?: Position[],\n): HandleDescriptor[] {\n const { vertexSize = 12, zIndex = 4 } = ui;\n const rect: Rect = cfg.element;\n const scale = cfg.scale ?? 1;\n const verts = liveVertices ?? cfg.vertices ?? [];\n\n return verts.map((v, i) => {\n const left = (v.x - rect.origin.x) * scale - vertexSize / 2;\n const top = (v.y - rect.origin.y) * scale - vertexSize / 2;\n return {\n handle: 'nw', // not used; kept for type\n style: {\n position: 'absolute',\n left: left + 'px',\n top: top + 'px',\n width: vertexSize + 'px',\n height: vertexSize + 'px',\n borderRadius: '50%',\n cursor: 'pointer',\n zIndex,\n touchAction: 'none',\n },\n attrs: { 'data-epdf-vertex': i },\n };\n });\n}\n","import { useRef, useCallback, useEffect, PointerEvent } from '@framework';\nimport {\n DragResizeController,\n DragResizeConfig,\n InteractionEvent,\n ResizeHandle,\n} from '../plugin-interaction-primitives';\n\nexport interface UseDragResizeOptions extends DragResizeConfig {\n onUpdate?: (event: InteractionEvent) => void;\n enabled?: boolean;\n}\n\nexport interface ResizeHandleEventProps {\n onPointerDown: (e: PointerEvent) => void;\n onPointerMove: (e: PointerEvent) => void;\n onPointerUp: (e: PointerEvent) => void;\n onPointerCancel: (e: PointerEvent) => void;\n}\n\nexport function useDragResize(options: UseDragResizeOptions) {\n const { onUpdate, enabled = true, ...config } = options;\n const controllerRef = useRef<DragResizeController | null>(null);\n const onUpdateRef = useRef<typeof onUpdate>(onUpdate);\n\n useEffect(() => {\n onUpdateRef.current = onUpdate;\n }, [onUpdate]);\n\n // Initialize or update controller\n useEffect(() => {\n if (!controllerRef.current) {\n controllerRef.current = new DragResizeController(config, (event) =>\n onUpdateRef.current?.(event),\n );\n } else {\n controllerRef.current.updateConfig(config);\n }\n }, [\n config.element,\n config.constraints,\n config.maintainAspectRatio,\n config.pageRotation,\n config.scale,\n config.vertices,\n ]);\n\n const handleDragStart = useCallback(\n (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startDrag(e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n [enabled],\n );\n\n const handleMove = useCallback((e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.move(e.clientX, e.clientY);\n }, []);\n\n const handleEnd = useCallback((e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.end();\n (e.currentTarget as HTMLElement).releasePointerCapture?.(e.pointerId);\n }, []);\n\n const createResizeHandler = useCallback(\n (handle: ResizeHandle): ResizeHandleEventProps => ({\n onPointerDown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startResize(handle, e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }),\n [enabled, handleMove, handleEnd],\n );\n\n const createVertexHandler = useCallback(\n (vertexIndex: number): ResizeHandleEventProps => ({\n onPointerDown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controllerRef.current?.startVertexEdit(vertexIndex, e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }),\n [enabled, handleMove, handleEnd],\n );\n\n return {\n dragProps: enabled\n ? {\n onPointerDown: handleDragStart,\n onPointerMove: handleMove,\n onPointerUp: handleEnd,\n onPointerCancel: handleEnd,\n }\n : {},\n createResizeProps: createResizeHandler,\n createVertexProps: createVertexHandler,\n };\n}\n","import { useMemo, PointerEvent } from '@framework';\nimport type { CSSProperties } from '@framework';\nimport { useDragResize, UseDragResizeOptions } from './use-drag-resize';\nimport {\n describeResizeFromConfig,\n describeVerticesFromConfig,\n type ResizeUI,\n type VertexUI,\n} from '../plugin-interaction-primitives/utils';\n\nexport type HandleElementProps = {\n key: string | number;\n style: CSSProperties;\n onPointerDown: (e: PointerEvent) => void;\n onPointerMove: (e: PointerEvent) => void;\n onPointerUp: (e: PointerEvent) => void;\n onPointerCancel: (e: PointerEvent) => void;\n} & Record<string, any>;\n\nexport function useInteractionHandles(opts: {\n controller: UseDragResizeOptions; // SINGLE config (rect/scale/rotation/vertices/…)\n resizeUI?: ResizeUI; // purely visual knobs\n vertexUI?: VertexUI; // purely visual knobs\n includeVertices?: boolean; // default false\n handleAttrs?: (\n h: 'nw' | 'ne' | 'sw' | 'se' | 'n' | 'e' | 's' | 'w',\n ) => Record<string, any> | void;\n vertexAttrs?: (i: number) => Record<string, any> | void;\n}) {\n const {\n controller,\n resizeUI,\n vertexUI,\n includeVertices = false,\n handleAttrs,\n vertexAttrs,\n } = opts;\n\n const { dragProps, createResizeProps, createVertexProps } = useDragResize(controller);\n\n // Resize handles: only uses data from the SAME controller config.\n const resize: HandleElementProps[] = useMemo(() => {\n const desc = describeResizeFromConfig(controller, resizeUI);\n return desc.map((d) => ({\n key: d.attrs?.['data-epdf-handle'] as string,\n style: d.style as CSSProperties,\n ...createResizeProps(d.handle),\n ...(d.attrs ?? {}),\n ...(handleAttrs?.(d.handle) ?? {}),\n }));\n // deps: controller geometry knobs + UI knobs + handler factory\n }, [\n controller.element.origin.x,\n controller.element.origin.y,\n controller.element.size.width,\n controller.element.size.height,\n controller.scale,\n controller.pageRotation,\n controller.maintainAspectRatio,\n resizeUI?.handleSize,\n resizeUI?.spacing,\n resizeUI?.offsetMode,\n resizeUI?.includeSides,\n resizeUI?.zIndex,\n resizeUI?.rotationAwareCursor,\n createResizeProps,\n handleAttrs,\n ]);\n\n // Vertex handles: same source; prefer live vertices if parent rerenders with updated cfg.vertices\n const vertices: HandleElementProps[] = useMemo(() => {\n if (!includeVertices) return [];\n const desc = describeVerticesFromConfig(controller, vertexUI, controller.vertices);\n return desc.map((d, i) => ({\n key: i,\n style: d.style as CSSProperties,\n ...createVertexProps(i),\n ...(d.attrs ?? {}),\n ...(vertexAttrs?.(i) ?? {}),\n }));\n }, [\n includeVertices,\n controller.element.origin.x,\n controller.element.origin.y,\n controller.element.size.width,\n controller.element.size.height,\n controller.scale,\n controller.vertices, // identity/content drives recalculation\n vertexUI?.vertexSize,\n vertexUI?.zIndex,\n createVertexProps,\n vertexAttrs,\n ]);\n\n return { dragProps, resize, vertices };\n}\n","import { useRef, useCallback, dblClickProp } from '@framework';\nimport type { PointerEvent } from '@framework';\n\ntype DoublePressOptions = {\n delay?: number; // ms between taps\n tolerancePx?: number; // spatial tolerance\n};\n\ntype DoubleHandler<T extends Element> = ((e: PointerEvent<T> | MouseEvent) => void) | undefined;\n\ntype DoubleProps<K extends string> = Partial<Record<K, (e: any) => void>> & {\n onPointerUp?: (e: any) => void;\n};\n\nexport function useDoublePressProps<\n T extends Element = Element,\n K extends string = typeof dblClickProp,\n>(\n onDouble?: DoubleHandler<T>,\n { delay = 300, tolerancePx = 18 }: DoublePressOptions = {},\n): DoubleProps<K> {\n const last = useRef({ t: 0, x: 0, y: 0 });\n\n const handlePointerUp = useCallback(\n (e: any) => {\n if (!onDouble) return;\n\n // Ignore mouse (it will use native dblclick),\n // and ignore non-primary pointers (multi-touch, etc.)\n if (e.pointerType === 'mouse' || e.isPrimary === false) return;\n\n const now = performance.now();\n const x = e.clientX as number;\n const y = e.clientY as number;\n\n const withinTime = now - last.current.t <= delay;\n const dx = x - last.current.x;\n const dy = y - last.current.y;\n const withinDist = dx * dx + dy * dy <= tolerancePx * tolerancePx;\n\n if (withinTime && withinDist) onDouble?.(e as PointerEvent<T>);\n\n last.current = { t: now, x, y };\n },\n [onDouble, delay, tolerancePx],\n );\n\n const handleDouble = useCallback(\n (e: any) => {\n onDouble?.(e);\n },\n [onDouble],\n );\n\n return onDouble\n ? ({\n // Computed property uses the framework’s name ('onDoubleClick' or 'onDblClick')\n [dblClickProp]: handleDouble,\n onPointerUpCapture: handlePointerUp,\n } as DoubleProps<K>)\n : {};\n}\n"],"names":[],"mappings":"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"}
|