@embedpdf/utils 2.4.1 → 2.6.0

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.
Files changed (47) hide show
  1. package/dist/preact/index.cjs +1 -1
  2. package/dist/preact/index.cjs.map +1 -1
  3. package/dist/preact/index.js +834 -317
  4. package/dist/preact/index.js.map +1 -1
  5. package/dist/react/index.cjs +1 -1
  6. package/dist/react/index.cjs.map +1 -1
  7. package/dist/react/index.js +834 -317
  8. package/dist/react/index.js.map +1 -1
  9. package/dist/shared/hooks/use-drag-resize.d.ts +4 -0
  10. package/dist/shared/hooks/use-interaction-handles.d.ts +18 -2
  11. package/dist/shared/plugin-interaction-primitives/drag-resize-controller.d.ts +49 -23
  12. package/dist/shared/plugin-interaction-primitives/index.d.ts +1 -0
  13. package/dist/shared/plugin-interaction-primitives/resize-geometry.d.ts +72 -0
  14. package/dist/shared/plugin-interaction-primitives/utils.d.ts +33 -0
  15. package/dist/shared-preact/hooks/use-drag-resize.d.ts +4 -0
  16. package/dist/shared-preact/hooks/use-interaction-handles.d.ts +18 -2
  17. package/dist/shared-preact/plugin-interaction-primitives/drag-resize-controller.d.ts +49 -23
  18. package/dist/shared-preact/plugin-interaction-primitives/index.d.ts +1 -0
  19. package/dist/shared-preact/plugin-interaction-primitives/resize-geometry.d.ts +72 -0
  20. package/dist/shared-preact/plugin-interaction-primitives/utils.d.ts +33 -0
  21. package/dist/shared-react/hooks/use-drag-resize.d.ts +4 -0
  22. package/dist/shared-react/hooks/use-interaction-handles.d.ts +18 -2
  23. package/dist/shared-react/plugin-interaction-primitives/drag-resize-controller.d.ts +49 -23
  24. package/dist/shared-react/plugin-interaction-primitives/index.d.ts +1 -0
  25. package/dist/shared-react/plugin-interaction-primitives/resize-geometry.d.ts +72 -0
  26. package/dist/shared-react/plugin-interaction-primitives/utils.d.ts +33 -0
  27. package/dist/shared-svelte/plugin-interaction-primitives/drag-resize-controller.d.ts +49 -23
  28. package/dist/shared-svelte/plugin-interaction-primitives/index.d.ts +1 -0
  29. package/dist/shared-svelte/plugin-interaction-primitives/resize-geometry.d.ts +72 -0
  30. package/dist/shared-svelte/plugin-interaction-primitives/utils.d.ts +33 -0
  31. package/dist/shared-vue/plugin-interaction-primitives/drag-resize-controller.d.ts +49 -23
  32. package/dist/shared-vue/plugin-interaction-primitives/index.d.ts +1 -0
  33. package/dist/shared-vue/plugin-interaction-primitives/resize-geometry.d.ts +72 -0
  34. package/dist/shared-vue/plugin-interaction-primitives/utils.d.ts +33 -0
  35. package/dist/svelte/hooks/use-drag-resize.svelte.d.ts +1 -0
  36. package/dist/svelte/hooks/use-interaction-handles.svelte.d.ts +16 -2
  37. package/dist/svelte/index.cjs +1 -1
  38. package/dist/svelte/index.cjs.map +1 -1
  39. package/dist/svelte/index.js +680 -288
  40. package/dist/svelte/index.js.map +1 -1
  41. package/dist/vue/hooks/use-drag-resize.d.ts +9 -0
  42. package/dist/vue/hooks/use-interaction-handles.d.ts +17 -2
  43. package/dist/vue/index.cjs +1 -1
  44. package/dist/vue/index.cjs.map +1 -1
  45. package/dist/vue/index.js +716 -292
  46. package/dist/vue/index.js.map +1 -1
  47. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/shared/plugin-interaction-primitives/drag-resize-controller.ts","../../src/shared/plugin-interaction-primitives/utils.ts","../../src/svelte/hooks/use-drag-resize.svelte.ts","../../src/svelte/utils/styles-to-string.ts","../../src/svelte/hooks/use-interaction-handles.svelte.ts","../../src/svelte/actions/doublePress.ts","../../src/svelte/components/CounterRotateContainer.svelte","../../src/svelte/utils/deep-to-raw.ts"],"sourcesContent":["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/** Anchor describes which edges stay fixed when resizing. */\ntype Anchor = {\n x: 'left' | 'right' | 'center';\n y: 'top' | 'bottom' | 'center';\n};\n\n/**\n * Derive anchor from handle.\n * - 'e' means we're dragging east → left edge is anchored\n * - 'nw' means we're dragging north-west → bottom-right corner is anchored\n */\nfunction getAnchor(handle: ResizeHandle): Anchor {\n return {\n x: handle.includes('e') ? 'left' : handle.includes('w') ? 'right' : 'center',\n y: handle.includes('s') ? 'top' : handle.includes('n') ? 'bottom' : 'center',\n };\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 /**\n * Calculate the new rect after a resize operation.\n * Pipeline: applyDelta → enforceAspectRatio → clampToBounds → applyConstraints\n */\n private calculateResizePosition(delta: Position, handle: ResizeHandle): Rect {\n if (!this.startElement) return this.config.element;\n\n const anchor = getAnchor(handle);\n const aspectRatio = this.startElement.size.width / this.startElement.size.height || 1;\n\n // Step 1: Apply delta to get raw resize\n let rect = this.applyResizeDelta(delta, anchor);\n\n // Step 2: Enforce aspect ratio if enabled\n if (this.config.maintainAspectRatio) {\n rect = this.enforceAspectRatio(rect, anchor, aspectRatio);\n }\n\n // Step 3: Clamp to bounding box\n rect = this.clampToBounds(rect, anchor, aspectRatio);\n\n // Step 4: Apply min/max constraints\n return this.applyConstraints(rect);\n }\n\n /**\n * Apply the mouse delta to produce a raw (unconstrained) resized rect.\n */\n private applyResizeDelta(delta: Position, anchor: Anchor): Rect {\n const start = this.startElement!;\n let x = start.origin.x;\n let y = start.origin.y;\n let width = start.size.width;\n let height = start.size.height;\n\n // Horizontal: if anchor is left, right edge moves; if anchor is right, left edge moves\n if (anchor.x === 'left') {\n width += delta.x;\n } else if (anchor.x === 'right') {\n x += delta.x;\n width -= delta.x;\n }\n // anchor.x === 'center' means no horizontal resize from this handle\n\n // Vertical: if anchor is top, bottom edge moves; if anchor is bottom, top edge moves\n if (anchor.y === 'top') {\n height += delta.y;\n } else if (anchor.y === 'bottom') {\n y += delta.y;\n height -= delta.y;\n }\n\n return { origin: { x, y }, size: { width, height } };\n }\n\n /**\n * Enforce aspect ratio while respecting the anchor.\n * For edge handles (center anchor on one axis), the rect expands symmetrically on that axis.\n * For corner handles, the anchor corner stays fixed.\n */\n private enforceAspectRatio(rect: Rect, anchor: Anchor, aspectRatio: number): Rect {\n const start = this.startElement!;\n let { x, y } = rect.origin;\n let { width, height } = rect.size;\n\n const isEdgeHandle = anchor.x === 'center' || anchor.y === 'center';\n\n if (isEdgeHandle) {\n // Edge handle: one dimension drives, the other follows, centered on the non-moving axis\n if (anchor.y === 'center') {\n // Horizontal edge (e/w): width is primary\n height = width / aspectRatio;\n // Center vertically relative to original\n y = start.origin.y + (start.size.height - height) / 2;\n } else {\n // Vertical edge (n/s): height is primary\n width = height * aspectRatio;\n // Center horizontally relative to original\n x = start.origin.x + (start.size.width - width) / 2;\n }\n } else {\n // Corner handle: pick the dominant axis based on which changed more\n const dw = Math.abs(width - start.size.width);\n const dh = Math.abs(height - start.size.height);\n\n if (dw >= dh) {\n height = width / aspectRatio;\n } else {\n width = height * aspectRatio;\n }\n }\n\n // Reposition based on anchor\n if (anchor.x === 'right') {\n x = start.origin.x + start.size.width - width;\n }\n if (anchor.y === 'bottom') {\n y = start.origin.y + start.size.height - height;\n }\n\n return { origin: { x, y }, size: { width, height } };\n }\n\n /**\n * Clamp rect to bounding box while respecting anchor and aspect ratio.\n */\n private clampToBounds(rect: Rect, anchor: Anchor, aspectRatio: number): Rect {\n const bbox = this.config.constraints?.boundingBox;\n if (!bbox) return rect;\n\n const start = this.startElement!;\n let { x, y } = rect.origin;\n let { width, height } = rect.size;\n\n // Ensure positive dimensions\n width = Math.max(1, width);\n height = Math.max(1, height);\n\n // Calculate anchor points (the edges/corners that must stay fixed)\n const anchorX = anchor.x === 'left' ? start.origin.x : start.origin.x + start.size.width;\n const anchorY = anchor.y === 'top' ? start.origin.y : start.origin.y + start.size.height;\n\n // Calculate max available space from anchor\n const maxW =\n anchor.x === 'left'\n ? bbox.width - anchorX\n : anchor.x === 'right'\n ? anchorX\n : Math.min(start.origin.x, bbox.width - start.origin.x - start.size.width) * 2 +\n start.size.width;\n\n const maxH =\n anchor.y === 'top'\n ? bbox.height - anchorY\n : anchor.y === 'bottom'\n ? anchorY\n : Math.min(start.origin.y, bbox.height - start.origin.y - start.size.height) * 2 +\n start.size.height;\n\n if (this.config.maintainAspectRatio) {\n // Find the scaling factor that fits both constraints\n const scaleW = width > maxW ? maxW / width : 1;\n const scaleH = height > maxH ? maxH / height : 1;\n const scale = Math.min(scaleW, scaleH);\n\n if (scale < 1) {\n width *= scale;\n height *= scale;\n }\n } else {\n // Clamp independently\n width = Math.min(width, maxW);\n height = Math.min(height, maxH);\n }\n\n // Recompute position based on anchor\n if (anchor.x === 'left') {\n x = anchorX;\n } else if (anchor.x === 'right') {\n x = anchorX - width;\n } else {\n x = start.origin.x + (start.size.width - width) / 2;\n }\n\n if (anchor.y === 'top') {\n y = anchorY;\n } else if (anchor.y === 'bottom') {\n y = anchorY - height;\n } else {\n y = start.origin.y + (start.size.height - height) / 2;\n }\n\n // Final clamp to ensure we're within bounds (handles center anchor edge cases)\n x = Math.max(0, Math.min(x, bbox.width - width));\n y = Math.max(0, Math.min(y, bbox.height - height));\n\n return { 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 const minW = constraints.minWidth ?? 1;\n const minH = constraints.minHeight ?? 1;\n const maxW = constraints.maxWidth;\n const maxH = constraints.maxHeight;\n\n if (this.config.maintainAspectRatio && width > 0 && height > 0) {\n const ratio = width / height;\n\n // Enforce mins (scale up)\n if (width < minW) {\n width = minW;\n height = width / ratio;\n }\n if (height < minH) {\n height = minH;\n width = height * ratio;\n }\n\n // Enforce maxes (scale down)\n if (maxW !== undefined && width > maxW) {\n width = maxW;\n height = width / ratio;\n }\n if (maxH !== undefined && height > maxH) {\n height = maxH;\n width = height * ratio;\n }\n } else {\n width = Math.max(minW, width);\n height = Math.max(minH, height);\n if (maxW !== undefined) width = Math.min(maxW, width);\n if (maxH !== undefined) height = Math.min(maxH, height);\n }\n\n // Clamp position to bounding box\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 {\n type DragResizeConfig,\n DragResizeController,\n type InteractionEvent,\n type ResizeHandle,\n} from '../../shared/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(getOptions: () => UseDragResizeOptions) {\n // Use getter function to maintain reactivity\n const config = $derived.by(() => {\n const opts = getOptions();\n const { onUpdate, enabled, ...rest } = opts;\n return rest;\n });\n\n const enabled = $derived(getOptions().enabled ?? true);\n const onUpdate = $derived(getOptions().onUpdate);\n\n let controller = $state<DragResizeController | null>(null);\n\n // Initialize or update controller\n $effect(() => {\n if (!controller) {\n controller = new DragResizeController(config, (event) => onUpdate?.(event));\n } else {\n controller.updateConfig(config);\n }\n });\n\n const handleDragStart = (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controller?.startDrag(e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n };\n\n const handleMove = (e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controller?.move(e.clientX, e.clientY);\n };\n\n const handleEnd = (e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controller?.end();\n (e.currentTarget as HTMLElement).releasePointerCapture?.(e.pointerId);\n };\n\n const createResizeHandler = (handle: ResizeHandle): ResizeHandleEventProps => ({\n onpointerdown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controller?.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\n const createVertexHandler = (vertexIndex: number): ResizeHandleEventProps => ({\n onpointerdown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controller?.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\n const dragProps = $derived(\n enabled\n ? {\n onpointerdown: handleDragStart,\n onpointermove: handleMove,\n onpointerup: handleEnd,\n onpointercancel: handleEnd,\n }\n : {},\n );\n\n return {\n get dragProps() {\n return dragProps;\n },\n createResizeProps: createResizeHandler,\n createVertexProps: createVertexHandler,\n };\n}\n","/**\n * Converts a style object with camelCase properties to a CSS string with kebab-case properties.\n *\n * This is useful in Svelte 5 where spreading style objects doesn't work with the `style:` directive.\n * Instead, you can convert the entire style object to a string and apply it to the `style` attribute.\n *\n * @param style - An object containing CSS properties in camelCase format with string or number values\n * @returns A CSS string with kebab-case properties suitable for the HTML style attribute\n *\n * @example\n * ```ts\n * const styles = {\n * position: 'absolute',\n * zIndex: 10,\n * borderRadius: '50%',\n * backgroundColor: '#007ACC'\n * };\n *\n * const cssString = stylesToString(styles);\n * // Returns: \"position: absolute; z-index: 10; border-radius: 50%; background-color: #007ACC\"\n * ```\n *\n * @example\n * Usage in Svelte templates:\n * ```svelte\n * <div style=\"{stylesToString(myStyles)}; color: red;\"></div>\n * ```\n */\nexport function stylesToString(style: Record<string, string | number>): string {\n return Object.entries(style)\n .map(([key, value]) => {\n const cssKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);\n return `${cssKey}: ${value}`;\n })\n .join('; ');\n}\n","import { useDragResize, type UseDragResizeOptions } from './use-drag-resize.svelte';\nimport {\n describeResizeFromConfig,\n describeVerticesFromConfig,\n type ResizeUI,\n type VertexUI,\n} from '../../shared/plugin-interaction-primitives';\nimport { stylesToString } from '../utils/styles-to-string';\n\nexport type HandleElementProps = {\n key: string | number;\n style: string;\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(\n getOpts: () => {\n controller: UseDragResizeOptions;\n resizeUI?: ResizeUI;\n vertexUI?: VertexUI;\n includeVertices?: boolean;\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) {\n // Use getter function and $derived to maintain reactivity\n const controller = $derived(getOpts().controller);\n const resizeUI = $derived(getOpts().resizeUI);\n const vertexUI = $derived(getOpts().vertexUI);\n const includeVertices = $derived(getOpts().includeVertices ?? false);\n const handleAttrs = $derived(getOpts().handleAttrs);\n const vertexAttrs = $derived(getOpts().vertexAttrs);\n\n const dragResize = useDragResize(() => controller);\n\n // Resize handles: computed from controller config\n const resize = $derived.by((): HandleElementProps[] => {\n const desc = describeResizeFromConfig(controller, resizeUI);\n return desc.map((d) => ({\n key: d.attrs?.['data-epdf-handle'] as string,\n style: stylesToString(d.style),\n ...dragResize.createResizeProps(d.handle),\n ...(d.attrs ?? {}),\n ...(handleAttrs?.(d.handle) ?? {}),\n }));\n });\n\n // Vertex handles: computed from controller config and vertices\n const vertices = $derived.by((): HandleElementProps[] => {\n if (!includeVertices) return [];\n const desc = describeVerticesFromConfig(controller, vertexUI, controller.vertices);\n return desc.map((d, i) => ({\n key: i,\n style: stylesToString(d.style),\n ...dragResize.createVertexProps(i),\n ...(d.attrs ?? {}),\n ...(vertexAttrs?.(i) ?? {}),\n }));\n });\n\n // Return getters to maintain reactivity when accessed from outside\n return {\n get dragProps() {\n return dragResize.dragProps;\n },\n get resize() {\n return resize;\n },\n get vertices() {\n return vertices;\n },\n };\n}\n","export type DoublePressOptions = {\n delay?: number; // ms between taps\n tolerancePx?: number; // spatial tolerance\n onDouble?: (e: PointerEvent | MouseEvent) => void;\n};\n\nexport function doublePress<T extends Element = Element>(\n node: T,\n options: DoublePressOptions = {},\n) {\n let { onDouble, delay = 300, tolerancePx = 18 } = options;\n\n // last pointerup (time & position)\n const last = { t: 0, x: 0, y: 0 };\n\n const handlePointerUp = (e: Event) => {\n const ev = e as PointerEvent;\n if (!onDouble) return;\n\n // ignore mouse (mouse uses native dblclick)\n // ignore non-primary pointers (multi-touch, etc.)\n if (ev.pointerType === 'mouse' || ev.isPrimary === false) return;\n\n const now = performance.now();\n const x = ev.clientX;\n const y = ev.clientY;\n\n const withinTime = now - last.t <= delay;\n const dx = x - last.x;\n const dy = y - last.y;\n const withinDist = dx * dx + dy * dy <= tolerancePx * tolerancePx;\n\n if (withinTime && withinDist) onDouble?.(ev);\n\n last.t = now;\n last.x = x;\n last.y = y;\n };\n\n const handleDblClick = (e: Event) => {\n onDouble?.(e as MouseEvent);\n };\n\n node.addEventListener('pointerup', handlePointerUp, { capture: true });\n node.addEventListener('dblclick', handleDblClick);\n\n return {\n update(next?: DoublePressOptions) {\n if (!next) return;\n onDouble = next.onDouble;\n // use nullish coalescing so 0 isn't swallowed accidentally (even though 0 isn't useful here)\n delay = next.delay ?? delay;\n tolerancePx = next.tolerancePx ?? tolerancePx;\n },\n destroy() {\n node.removeEventListener('pointerup', handlePointerUp, { capture: true } as any);\n node.removeEventListener('dblclick', handleDblClick);\n },\n };\n}\n","<script lang=\"ts\">\n import type { Snippet } from 'svelte';\n import type { Action } from 'svelte/action';\n import { getCounterRotation } from '@embedpdf/utils';\n import type { Rect, Rotation } from '@embedpdf/models';\n import type { MenuWrapperProps } from './types';\n\n interface CounterRotateProps {\n rect: Rect;\n rotation: Rotation;\n }\n\n interface CounterRotateChildrenProps {\n matrix: string;\n rect: Rect;\n menuWrapperProps: MenuWrapperProps;\n }\n\n interface Props extends CounterRotateProps {\n children?: Snippet<[CounterRotateChildrenProps]>;\n }\n\n let { rect, rotation, children }: Props = $props();\n const counterRotation = $derived(getCounterRotation(rect, rotation));\n\n // Svelte action for capture-phase event handling\n // This is the idiomatic way to attach lifecycle-managed behavior to DOM elements\n const menuWrapperAction: Action<HTMLElement> = (node) => {\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 };\n\n // Use capture phase to intercept before synthetic events\n node.addEventListener('pointerdown', handlePointerDown, { capture: true });\n node.addEventListener('touchstart', handleTouchStart, { capture: true });\n\n return {\n destroy() {\n node.removeEventListener('pointerdown', handlePointerDown, { capture: true });\n node.removeEventListener('touchstart', handleTouchStart, { capture: true });\n },\n };\n };\n\n const menuWrapperStyle = $derived(\n `position: absolute; ` +\n `left: ${rect.origin.x}px; ` +\n `top: ${rect.origin.y}px; ` +\n `transform: ${counterRotation.matrix}; ` +\n `transform-origin: 0 0; ` +\n `width: ${counterRotation.width}px; ` +\n `height: ${counterRotation.height}px; ` +\n `pointer-events: none; ` +\n `z-index: 3`,\n );\n\n const menuWrapperProps: MenuWrapperProps = $derived({\n style: menuWrapperStyle,\n action: menuWrapperAction,\n });\n</script>\n\n{#if children}\n {@render children({\n menuWrapperProps,\n matrix: counterRotation.matrix,\n rect: {\n origin: { x: rect.origin.x, y: rect.origin.y },\n size: { width: counterRotation.width, height: counterRotation.height },\n },\n })}\n{/if}\n","/**\n * Converts Svelte proxy objects to plain JavaScript objects.\n * This is useful when passing data to Web Workers or other contexts\n * that cannot handle Svelte's reactive proxies.\n *\n * Inspired by the Vue implementation, this recursively traverses the object\n * and handles primitives, arrays, and plain objects while stripping reactive proxies.\n */\nexport function deepToRaw<T extends Record<string, any>>(sourceObj: T): T {\n const objectIterator = (input: any): any => {\n // Handle null and undefined\n if (input === null || input === undefined) {\n return input;\n }\n\n // Handle primitives (string, number, boolean, bigint, symbol)\n if (typeof input !== 'object') {\n return input;\n }\n\n // Handle Arrays\n if (Array.isArray(input)) {\n return input.map((item) => objectIterator(item));\n }\n\n // Handle Date objects\n if (input instanceof Date) {\n return new Date(input.getTime());\n }\n\n // Handle RegExp\n if (input instanceof RegExp) {\n return new RegExp(input.source, input.flags);\n }\n\n // Handle plain objects (including Svelte proxies)\n // For Svelte proxies, we recursively extract plain values\n if (Object.prototype.toString.call(input) === '[object Object]') {\n return Object.keys(input).reduce((acc, key) => {\n // Skip non-enumerable properties and functions\n const value = input[key];\n if (typeof value !== 'function') {\n acc[key as keyof typeof acc] = objectIterator(value);\n }\n return acc;\n }, {} as T);\n }\n\n // For other object types (Map, Set, etc.), use JSON roundtrip as fallback\n // This will convert them to plain objects/arrays\n try {\n return JSON.parse(JSON.stringify(input));\n } catch {\n // If JSON serialization fails, return undefined\n return undefined;\n }\n };\n\n return objectIterator(sourceObj);\n}\n"],"names":["onUpdate","enabled"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/shared/plugin-interaction-primitives/utils.ts","../../src/shared/plugin-interaction-primitives/resize-geometry.ts","../../src/shared/plugin-interaction-primitives/drag-resize-controller.ts","../../src/svelte/hooks/use-drag-resize.svelte.ts","../../src/svelte/utils/styles-to-string.ts","../../src/svelte/hooks/use-interaction-handles.svelte.ts","../../src/svelte/actions/doublePress.ts","../../src/svelte/components/CounterRotateContainer.svelte","../../src/svelte/utils/deep-to-raw.ts"],"sourcesContent":["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 RotationUI {\n /** Handle size in px (default 32) */\n handleSize?: number;\n /** Screen-pixel gap between bounding box edge and handle center (default 30) */\n margin?: number;\n /** z-index of the rotation handle (default 5) */\n zIndex?: number;\n /** Whether to show the connector line from center to handle (default true) */\n showConnector?: boolean;\n /** Connector line width in px (default 1) */\n connectorWidth?: number;\n}\n\n/** Screen-pixel gap between the rect edge and the rotation handle center (default orbit margin). */\nexport const ROTATION_HANDLE_MARGIN = 35;\n\nexport interface HandleDescriptor {\n handle: ResizeHandle;\n style: Record<string, number | string>;\n attrs?: Record<string, any>;\n}\n\nexport interface RotationHandleDescriptor {\n /** Style for the rotation handle itself */\n handleStyle: Record<string, number | string>;\n /** Style for the connector line (if shown) */\n connectorStyle: Record<string, number | string>;\n /** Orbit radius in screen pixels used to position the handle. */\n radius: number;\n /** Attributes for the handle element */\n attrs?: Record<string, any>;\n}\n\n/**\n * Base angle (degrees, clockwise from north) for each resize handle.\n * Used to compute the effective angle after page + annotation rotation.\n */\nconst HANDLE_BASE_ANGLE: Record<ResizeHandle, number> = {\n n: 0,\n ne: 45,\n e: 90,\n se: 135,\n s: 180,\n sw: 225,\n w: 270,\n nw: 315,\n};\n\n/**\n * Cursor names mapped to 45-degree sectors.\n * Sector 0 = north (337.5..22.5), sector 1 = NE (22.5..67.5), etc.\n */\nconst SECTOR_CURSORS: string[] = [\n 'ns-resize', // 0: north\n 'nesw-resize', // 1: NE\n 'ew-resize', // 2: east\n 'nwse-resize', // 3: SE\n 'ns-resize', // 4: south\n 'nesw-resize', // 5: SW\n 'ew-resize', // 6: west\n 'nwse-resize', // 7: NW\n];\n\nfunction diagonalCursor(\n handle: ResizeHandle,\n pageQuarterTurns: QuarterTurns,\n annotationRotation: number = 0,\n): string {\n const pageAngle = pageQuarterTurns * 90;\n const totalAngle = HANDLE_BASE_ANGLE[handle] + pageAngle + annotationRotation;\n // Normalize to [0, 360)\n const normalized = ((totalAngle % 360) + 360) % 360;\n // Map to 45-degree sector (0..7)\n const sector = Math.round(normalized / 45) % 8;\n return SECTOR_CURSORS[sector];\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 pageQuarterTurns = ((cfg.pageRotation ?? 0) % 4) as QuarterTurns;\n const annotationRot = cfg.annotationRotation ?? 0;\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\n ? diagonalCursor(handle, pageQuarterTurns, annotationRot)\n : 'default',\n pointerEvents: 'auto',\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 pointerEvents: 'auto',\n touchAction: 'none',\n },\n attrs: { 'data-epdf-vertex': i },\n };\n });\n}\n\n/**\n * Describe the rotation handle position and style.\n * The rotation handle orbits around the center of the bounding box based on the current angle.\n *\n * @param cfg - The drag/resize config containing the element rect and scale\n * @param ui - UI customization options\n * @param currentAngle - The current rotation angle in degrees (0 = top, clockwise positive)\n */\nexport function describeRotationFromConfig(\n cfg: DragResizeConfig,\n ui: RotationUI = {},\n currentAngle: number = 0,\n): RotationHandleDescriptor {\n const { handleSize = 16, zIndex = 5, showConnector = true, connectorWidth = 1 } = ui;\n\n const scale = cfg.scale ?? 1;\n const rect = cfg.element;\n\n const orbitRect = cfg.rotationElement ?? rect;\n const orbitCenter = cfg.rotationCenter ?? {\n x: rect.origin.x + rect.size.width / 2,\n y: rect.origin.y + rect.size.height / 2,\n };\n\n // Center in scaled coordinates, relative to the orbit rect's origin.\n const scaledWidth = orbitRect.size.width * scale;\n const scaledHeight = orbitRect.size.height * scale;\n const centerX = (orbitCenter.x - orbitRect.origin.x) * scale;\n const centerY = (orbitCenter.y - orbitRect.origin.y) * scale;\n\n // Handle orbits at currentAngle (0° = top, clockwise positive)\n const angleRad = (currentAngle * Math.PI) / 180;\n\n // Calculate radius - distance from center to handle.\n // The handle always sits at the shape's local \"top\" because currentAngle\n // matches the annotation rotation and the shape rotates with it. So the\n // distance from center to the nearest edge in the handle's direction is\n // always halfHeight of the unrotated rect, regardless of the angle.\n const margin = ui.margin ?? ROTATION_HANDLE_MARGIN;\n const radius = (rect.size.height * scale) / 2 + margin;\n\n const handleCenterX = centerX + radius * Math.sin(angleRad);\n const handleCenterY = centerY - radius * Math.cos(angleRad);\n const handleLeft = handleCenterX - handleSize / 2;\n const handleTop = handleCenterY - handleSize / 2;\n\n return {\n handleStyle: {\n position: 'absolute',\n left: handleLeft + 'px',\n top: handleTop + 'px',\n width: handleSize + 'px',\n height: handleSize + 'px',\n borderRadius: '50%',\n cursor: 'grab',\n zIndex,\n pointerEvents: 'auto',\n touchAction: 'none',\n },\n connectorStyle: showConnector\n ? {\n position: 'absolute',\n left: centerX - connectorWidth / 2 + 'px',\n top: centerY - radius + 'px',\n width: connectorWidth + 'px',\n height: radius + 'px',\n transformOrigin: 'center bottom',\n transform: `rotate(${currentAngle}deg)`,\n zIndex: zIndex - 1,\n pointerEvents: 'none',\n }\n : {},\n radius,\n attrs: { 'data-epdf-rotation-handle': true },\n };\n}\n","/**\n * Pure geometric functions for the resize pipeline.\n *\n * Extracted from DragResizeController so that:\n * 1. The resize math is independently testable\n * 2. The controller stays focused on state machine + coordinate transformation\n */\nimport { Position, Rect, rotatePointAround, calculateRotatedRectAABB } from '@embedpdf/models';\n\nimport type { ResizeHandle } from './drag-resize-controller';\n\n// ---------------------------------------------------------------------------\n// Anchor helpers\n// ---------------------------------------------------------------------------\n\n/** Anchor describes which edges stay fixed when resizing. */\nexport type Anchor = {\n x: 'left' | 'right' | 'center';\n y: 'top' | 'bottom' | 'center';\n};\n\n/**\n * Derive anchor from handle.\n * - 'e' means we're dragging east → left edge is anchored\n * - 'nw' means we're dragging north-west → bottom-right corner is anchored\n */\nexport function getAnchor(handle: ResizeHandle): Anchor {\n return {\n x: handle.includes('e') ? 'left' : handle.includes('w') ? 'right' : 'center',\n y: handle.includes('s') ? 'top' : handle.includes('n') ? 'bottom' : 'center',\n };\n}\n\n/** Get the anchor point (the visually fixed point) in page space for a given rect and anchor. */\nexport function getAnchorPoint(rect: Rect, anchor: Anchor): Position {\n const x =\n anchor.x === 'left'\n ? rect.origin.x\n : anchor.x === 'right'\n ? rect.origin.x + rect.size.width\n : rect.origin.x + rect.size.width / 2;\n const y =\n anchor.y === 'top'\n ? rect.origin.y\n : anchor.y === 'bottom'\n ? rect.origin.y + rect.size.height\n : rect.origin.y + rect.size.height / 2;\n return { x, y };\n}\n\n// ---------------------------------------------------------------------------\n// Constraint types\n// ---------------------------------------------------------------------------\n\nexport interface ResizeConstraints {\n minWidth?: number;\n minHeight?: number;\n maxWidth?: number;\n maxHeight?: number;\n boundingBox?: { width: number; height: number };\n}\n\n// ---------------------------------------------------------------------------\n// Pipeline stages (pure functions)\n// ---------------------------------------------------------------------------\n\n/**\n * Apply the mouse delta to produce a raw (unconstrained) resized rect.\n */\nexport function applyResizeDelta(startRect: Rect, delta: Position, anchor: Anchor): Rect {\n let x = startRect.origin.x;\n let y = startRect.origin.y;\n let width = startRect.size.width;\n let height = startRect.size.height;\n\n if (anchor.x === 'left') {\n width += delta.x;\n } else if (anchor.x === 'right') {\n x += delta.x;\n width -= delta.x;\n }\n\n if (anchor.y === 'top') {\n height += delta.y;\n } else if (anchor.y === 'bottom') {\n y += delta.y;\n height -= delta.y;\n }\n\n return { origin: { x, y }, size: { width, height } };\n}\n\n/**\n * Enforce aspect ratio while respecting the anchor.\n * For edge handles (center anchor on one axis), the rect expands symmetrically on that axis.\n * For corner handles, the anchor corner stays fixed.\n */\nexport function enforceAspectRatio(\n rect: Rect,\n startRect: Rect,\n anchor: Anchor,\n aspectRatio: number,\n): Rect {\n let { x, y } = rect.origin;\n let { width, height } = rect.size;\n\n const isEdgeHandle = anchor.x === 'center' || anchor.y === 'center';\n\n if (isEdgeHandle) {\n if (anchor.y === 'center') {\n height = width / aspectRatio;\n y = startRect.origin.y + (startRect.size.height - height) / 2;\n } else {\n width = height * aspectRatio;\n x = startRect.origin.x + (startRect.size.width - width) / 2;\n }\n } else {\n const dw = Math.abs(width - startRect.size.width);\n const dh = Math.abs(height - startRect.size.height);\n const total = dw + dh;\n\n if (total === 0) {\n width = startRect.size.width;\n height = startRect.size.height;\n } else {\n // Smooth weighted blend between the width-driven and height-driven\n // results. Both candidate pairs lie on the line w/h = aspectRatio\n // through the origin, so any linear combination preserves the ratio\n // exactly — while eliminating the discontinuous jump that the old\n // hard `dw >= dh` switch caused at the boundary.\n const wWeight = dw / total;\n const hWeight = dh / total;\n const wFromW = width;\n const hFromW = width / aspectRatio;\n const wFromH = height * aspectRatio;\n const hFromH = height;\n width = wWeight * wFromW + hWeight * wFromH;\n height = wWeight * hFromW + hWeight * hFromH;\n }\n }\n\n if (anchor.x === 'right') {\n x = startRect.origin.x + startRect.size.width - width;\n }\n if (anchor.y === 'bottom') {\n y = startRect.origin.y + startRect.size.height - height;\n }\n\n return { origin: { x, y }, size: { width, height } };\n}\n\n/**\n * Clamp rect to bounding box while respecting anchor.\n */\nexport function clampToBounds(\n rect: Rect,\n startRect: Rect,\n anchor: Anchor,\n bbox: { width: number; height: number } | undefined,\n maintainAspectRatio: boolean,\n): Rect {\n if (!bbox) return rect;\n\n let { x, y } = rect.origin;\n let { width, height } = rect.size;\n\n width = Math.max(1, width);\n height = Math.max(1, height);\n\n const anchorX =\n anchor.x === 'left' ? startRect.origin.x : startRect.origin.x + startRect.size.width;\n const anchorY =\n anchor.y === 'top' ? startRect.origin.y : startRect.origin.y + startRect.size.height;\n\n const maxW =\n anchor.x === 'left'\n ? bbox.width - anchorX\n : anchor.x === 'right'\n ? anchorX\n : Math.min(startRect.origin.x, bbox.width - startRect.origin.x - startRect.size.width) * 2 +\n startRect.size.width;\n\n const maxH =\n anchor.y === 'top'\n ? bbox.height - anchorY\n : anchor.y === 'bottom'\n ? anchorY\n : Math.min(startRect.origin.y, bbox.height - startRect.origin.y - startRect.size.height) *\n 2 +\n startRect.size.height;\n\n if (maintainAspectRatio) {\n const scaleW = width > maxW ? maxW / width : 1;\n const scaleH = height > maxH ? maxH / height : 1;\n const scale = Math.min(scaleW, scaleH);\n\n if (scale < 1) {\n width *= scale;\n height *= scale;\n }\n } else {\n width = Math.min(width, maxW);\n height = Math.min(height, maxH);\n }\n\n if (anchor.x === 'left') {\n x = anchorX;\n } else if (anchor.x === 'right') {\n x = anchorX - width;\n } else {\n x = startRect.origin.x + (startRect.size.width - width) / 2;\n }\n\n if (anchor.y === 'top') {\n y = anchorY;\n } else if (anchor.y === 'bottom') {\n y = anchorY - height;\n } else {\n y = startRect.origin.y + (startRect.size.height - height) / 2;\n }\n\n x = Math.max(0, Math.min(x, bbox.width - width));\n y = Math.max(0, Math.min(y, bbox.height - height));\n\n return { origin: { x, y }, size: { width, height } };\n}\n\n/**\n * Reposition rect from current size so the start-gesture anchor remains fixed.\n * This prevents translation drift when constraints clamp width/height.\n */\nexport function reanchorRect(rect: Rect, startRect: Rect, anchor: Anchor): Rect {\n let x: number;\n let y: number;\n\n if (anchor.x === 'left') {\n x = startRect.origin.x;\n } else if (anchor.x === 'right') {\n x = startRect.origin.x + startRect.size.width - rect.size.width;\n } else {\n x = startRect.origin.x + (startRect.size.width - rect.size.width) / 2;\n }\n\n if (anchor.y === 'top') {\n y = startRect.origin.y;\n } else if (anchor.y === 'bottom') {\n y = startRect.origin.y + startRect.size.height - rect.size.height;\n } else {\n y = startRect.origin.y + (startRect.size.height - rect.size.height) / 2;\n }\n\n return { origin: { x, y }, size: rect.size };\n}\n\n/**\n * Apply min/max constraints. Also used by the drag pipeline for position clamping.\n */\nexport function applyConstraints(\n position: Rect,\n constraints: ResizeConstraints | undefined,\n maintainAspectRatio: boolean,\n skipBoundingClamp: boolean = false,\n): Rect {\n if (!constraints) return position;\n\n let {\n origin: { x, y },\n size: { width, height },\n } = position;\n\n const minW = constraints.minWidth ?? 1;\n const minH = constraints.minHeight ?? 1;\n const maxW = constraints.maxWidth;\n const maxH = constraints.maxHeight;\n\n if (maintainAspectRatio && width > 0 && height > 0) {\n const ratio = width / height;\n\n if (width < minW) {\n width = minW;\n height = width / ratio;\n }\n if (height < minH) {\n height = minH;\n width = height * ratio;\n }\n\n if (maxW !== undefined && width > maxW) {\n width = maxW;\n height = width / ratio;\n }\n if (maxH !== undefined && height > maxH) {\n height = maxH;\n width = height * ratio;\n }\n } else {\n width = Math.max(minW, width);\n height = Math.max(minH, height);\n if (maxW !== undefined) width = Math.min(maxW, width);\n if (maxH !== undefined) height = Math.min(maxH, height);\n }\n\n if (constraints.boundingBox && !skipBoundingClamp) {\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/**\n * Check if a rect, when rotated, fits within the given page bounds.\n */\nexport function isRectWithinRotatedBounds(\n rect: Rect,\n angleDegrees: number,\n bbox: { width: number; height: number },\n): boolean {\n const eps = 1e-6;\n const aabb = calculateRotatedRectAABB(rect, angleDegrees);\n return (\n aabb.origin.x >= -eps &&\n aabb.origin.y >= -eps &&\n aabb.origin.x + aabb.size.width <= bbox.width + eps &&\n aabb.origin.y + aabb.size.height <= bbox.height + eps\n );\n}\n\n// ---------------------------------------------------------------------------\n// Full resize pipeline\n// ---------------------------------------------------------------------------\n\nexport interface ResizeConfig {\n startRect: Rect;\n maintainAspectRatio?: boolean;\n annotationRotation?: number;\n constraints?: ResizeConstraints;\n}\n\n/**\n * Run the full resize pipeline for a single step:\n * delta → anchor → raw resize → aspect ratio → bounds clamp → constraints → anchor compensation\n */\nfunction computeResizeStep(\n delta: Position,\n handle: ResizeHandle,\n config: ResizeConfig,\n clampLocalBounds: boolean,\n skipConstraintBoundingClamp: boolean,\n): Rect {\n const { startRect, maintainAspectRatio = false, annotationRotation = 0, constraints } = config;\n const anchor = getAnchor(handle);\n const aspectRatio = startRect.size.width / startRect.size.height || 1;\n\n // Step 1: Apply delta to get raw resize\n let rect = applyResizeDelta(startRect, delta, anchor);\n\n // Step 2: Enforce aspect ratio if enabled\n if (maintainAspectRatio) {\n rect = enforceAspectRatio(rect, startRect, anchor, aspectRatio);\n }\n\n // Step 3: Clamp in local/unrotated frame when requested\n if (clampLocalBounds) {\n rect = clampToBounds(rect, startRect, anchor, constraints?.boundingBox, maintainAspectRatio);\n }\n\n // Step 4: Apply min/max constraints\n rect = applyConstraints(rect, constraints, maintainAspectRatio, skipConstraintBoundingClamp);\n\n // In rotated resize mode we skip axis-aligned bounding clamps and solve\n // against visual bounds separately. Re-anchor after size constraints so\n // dragging past min/max does not keep translating the rect.\n if (skipConstraintBoundingClamp) {\n rect = reanchorRect(rect, startRect, anchor);\n }\n\n // Step 5: Compensate for visual anchor drift when the annotation is rotated.\n if (annotationRotation !== 0) {\n const anchorPt = getAnchorPoint(startRect, anchor);\n const oldCenter: Position = {\n x: startRect.origin.x + startRect.size.width / 2,\n y: startRect.origin.y + startRect.size.height / 2,\n };\n const newCenter: Position = {\n x: rect.origin.x + rect.size.width / 2,\n y: rect.origin.y + rect.size.height / 2,\n };\n const oldVisual = rotatePointAround(anchorPt, oldCenter, annotationRotation);\n const newVisual = rotatePointAround(anchorPt, newCenter, annotationRotation);\n rect = {\n origin: {\n x: rect.origin.x + (oldVisual.x - newVisual.x),\n y: rect.origin.y + (oldVisual.y - newVisual.y),\n },\n size: rect.size,\n };\n }\n\n return rect;\n}\n\n/**\n * Calculate the new rect after a resize operation.\n *\n * For non-rotated annotations, runs the pipeline once with local bound clamping.\n * For rotated annotations, uses a binary search to find the largest delta that\n * keeps the visual AABB within page bounds.\n */\nexport function computeResizedRect(\n delta: Position,\n handle: ResizeHandle,\n config: ResizeConfig,\n): Rect {\n const { annotationRotation = 0, constraints } = config;\n const bbox = constraints?.boundingBox;\n\n // For rotated annotations, clamp using visual AABB bounds via binary search.\n if (annotationRotation !== 0 && bbox) {\n const target = computeResizeStep(delta, handle, config, false, true);\n if (isRectWithinRotatedBounds(target, annotationRotation, bbox)) {\n return target;\n }\n\n let best = computeResizeStep({ x: 0, y: 0 }, handle, config, false, true);\n let low = 0;\n let high = 1;\n for (let i = 0; i < 20; i += 1) {\n const mid = (low + high) / 2;\n const trial = computeResizeStep(\n { x: delta.x * mid, y: delta.y * mid },\n handle,\n config,\n false,\n true,\n );\n if (isRectWithinRotatedBounds(trial, annotationRotation, bbox)) {\n best = trial;\n low = mid;\n } else {\n high = mid;\n }\n }\n\n return best;\n }\n\n return computeResizeStep(delta, handle, config, true, false);\n}\n","import { Position, Rect, rotatePointAround, normalizeAngle } from '@embedpdf/models';\nimport { ROTATION_HANDLE_MARGIN } from './utils';\nimport { computeResizedRect, applyConstraints } from './resize-geometry';\n\nexport interface DragResizeConfig {\n element: Rect;\n /**\n * Optional world-space pivot to use for rotation interactions.\n * Defaults to the center of `element`.\n */\n rotationCenter?: Position;\n /**\n * Optional rect used for rotation-handle orbit layout (typically the visible AABB container).\n * Defaults to `element`.\n */\n rotationElement?: 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 /** Rotation of the annotation itself in degrees (used to project mouse deltas into local space for resize/vertex-edit) */\n annotationRotation?: number;\n scale?: number;\n rotationSnapAngles?: number[];\n rotationSnapThreshold?: number;\n}\n\nexport type InteractionState = 'idle' | 'dragging' | 'resizing' | 'vertex-editing' | 'rotating';\nexport type ResizeHandle = 'nw' | 'ne' | 'sw' | 'se' | 'n' | 'e' | 's' | 'w';\n\nexport interface TransformData {\n type: 'move' | 'resize' | 'vertex-edit' | 'rotate';\n changes: {\n rect?: Rect;\n vertices?: Position[];\n rotation?: number;\n };\n metadata?: {\n handle?: ResizeHandle;\n vertexIndex?: number;\n maintainAspectRatio?: boolean;\n /** The rotation angle in degrees */\n rotationAngle?: number;\n /** The center point used for rotation */\n rotationCenter?: Position;\n rotationDelta?: number;\n isSnapped?: boolean;\n snappedAngle?: number;\n /** Screen-space cursor position during the gesture */\n cursorPosition?: { clientX: number; clientY: number };\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/rotate logic.\n */\nexport class DragResizeController {\n private state: InteractionState = 'idle';\n private startPoint: Position | null = null;\n private startElement: Rect | null = null;\n private startRotationElement: Rect | null = null;\n private gestureRotationCenter: Position | 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 // Rotation state\n private rotationCenter: Position | null = null;\n private centerScreen: Position | null = null; // Cached center in screen coords\n private initialRotation: number = 0; // The rotation value when interaction started\n private lastComputedRotation: number = 0; // The last computed rotation during move\n private rotationDelta: number = 0;\n private rotationSnappedAngle: number | null = null;\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 // Keep the gesture buffer stable during active vertex editing.\n // Otherwise rerendered preview vertices can overwrite `currentVertices`\n // and cause end() to emit compensated vertices a second time.\n if (this.state !== 'vertex-editing') {\n this.currentVertices = config.vertices || [];\n }\n }\n\n // ---------------------------------------------------------------------------\n // Gesture start\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.startRotationElement = this.config.rotationElement\n ? { ...this.config.rotationElement }\n : null;\n this.currentPosition = { ...this.config.element };\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'move',\n changes: { rect: this.startElement },\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: { rect: this.startElement },\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 this.gestureRotationCenter = this.config.rotationCenter ?? {\n x: this.config.element.origin.x + this.config.element.size.width / 2,\n y: this.config.element.origin.y + this.config.element.size.height / 2,\n };\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'vertex-edit',\n changes: { vertices: this.startVertices },\n metadata: { vertexIndex },\n },\n });\n }\n\n startRotation(\n clientX: number,\n clientY: number,\n initialRotation: number = 0,\n orbitRadiusPx?: number,\n ) {\n this.state = 'rotating';\n this.startPoint = { x: clientX, y: clientY };\n this.startElement = { ...this.config.element };\n\n // Use explicit rotation center when provided (keeps pivot stable after vertex edits).\n this.rotationCenter = this.config.rotationCenter ?? {\n x: this.config.element.origin.x + this.config.element.size.width / 2,\n y: this.config.element.origin.y + this.config.element.size.height / 2,\n };\n\n // Cache the center in screen coordinates, derived from the handle's DOM center\n const { scale = 1 } = this.config;\n const orbitRect = this.config.rotationElement ?? this.config.element;\n const sw = orbitRect.size.width * scale;\n const sh = orbitRect.size.height * scale;\n const radius = orbitRadiusPx ?? Math.max(sw, sh) / 2 + ROTATION_HANDLE_MARGIN;\n const pageRotOffset = (this.config.pageRotation ?? 0) * 90;\n const screenAngleRad = ((initialRotation + pageRotOffset) * Math.PI) / 180;\n this.centerScreen = {\n x: clientX - radius * Math.sin(screenAngleRad),\n y: clientY + radius * Math.cos(screenAngleRad),\n };\n\n this.initialRotation = initialRotation;\n this.lastComputedRotation = initialRotation;\n this.rotationDelta = 0;\n this.rotationSnappedAngle = null;\n\n this.onUpdate({\n state: 'start',\n transformData: {\n type: 'rotate',\n changes: { rotation: initialRotation },\n metadata: {\n rotationAngle: initialRotation,\n rotationDelta: 0,\n rotationCenter: this.rotationCenter,\n isSnapped: false,\n },\n },\n });\n }\n\n // ---------------------------------------------------------------------------\n // Gesture move\n // ---------------------------------------------------------------------------\n\n move(clientX: number, clientY: number, buttons?: number) {\n if (this.state === 'idle' || !this.startPoint) return;\n\n // Safety net: if the button is no longer pressed but we never received\n // pointerup/pointercancel, finalize the gesture to avoid a \"stuck\" drag.\n if (buttons !== undefined && buttons === 0) {\n this.end();\n return;\n }\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: { type: 'move', changes: { rect: position } },\n });\n } else if (this.state === 'resizing' && this.activeHandle && this.startElement) {\n const delta = this.calculateLocalDelta(clientX, clientY);\n const position = computeResizedRect(delta, this.activeHandle, {\n startRect: this.startElement,\n maintainAspectRatio: this.config.maintainAspectRatio,\n annotationRotation: this.config.annotationRotation,\n constraints: this.config.constraints,\n });\n this.currentPosition = position;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'resize',\n changes: { rect: position },\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: { vertices },\n metadata: { vertexIndex: this.activeVertexIndex },\n },\n });\n } else if (this.state === 'rotating' && this.rotationCenter) {\n const absoluteAngle = this.calculateAngleFromMouse(clientX, clientY);\n const snapResult = this.applyRotationSnapping(absoluteAngle);\n const snappedAngle = normalizeAngle(snapResult.angle);\n const previousAngle = this.lastComputedRotation;\n const rawDelta = snappedAngle - previousAngle;\n const adjustedDelta =\n rawDelta > 180 ? rawDelta - 360 : rawDelta < -180 ? rawDelta + 360 : rawDelta;\n\n this.rotationDelta += adjustedDelta;\n this.lastComputedRotation = snappedAngle;\n this.rotationSnappedAngle = snapResult.isSnapped ? snappedAngle : null;\n\n this.onUpdate({\n state: 'move',\n transformData: {\n type: 'rotate',\n changes: { rotation: snappedAngle },\n metadata: {\n rotationAngle: snappedAngle,\n rotationDelta: this.rotationDelta,\n rotationCenter: this.rotationCenter,\n isSnapped: snapResult.isSnapped,\n snappedAngle: this.rotationSnappedAngle ?? undefined,\n cursorPosition: { clientX, clientY },\n },\n },\n });\n }\n }\n\n // ---------------------------------------------------------------------------\n // Gesture end / cancel\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: { vertices: this.currentVertices },\n metadata: { vertexIndex: vertexIndex || undefined },\n },\n });\n } else if (wasState === 'rotating') {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: 'rotate',\n changes: { rotation: this.lastComputedRotation },\n metadata: {\n rotationAngle: this.lastComputedRotation,\n rotationDelta: this.rotationDelta,\n rotationCenter: this.rotationCenter || undefined,\n isSnapped: this.rotationSnappedAngle !== null,\n snappedAngle: this.rotationSnappedAngle ?? undefined,\n },\n },\n });\n } else {\n const finalPosition = this.currentPosition || this.config.element;\n this.onUpdate({\n state: 'end',\n transformData: {\n type: wasState === 'dragging' ? 'move' : 'resize',\n changes: { rect: finalPosition },\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: { vertices: this.startVertices },\n metadata: { vertexIndex: this.activeVertexIndex || undefined },\n },\n });\n } else if (this.state === 'rotating') {\n this.onUpdate({\n state: 'end',\n transformData: {\n type: 'rotate',\n changes: { rotation: this.initialRotation },\n metadata: {\n rotationAngle: this.initialRotation,\n rotationDelta: 0,\n rotationCenter: this.rotationCenter || undefined,\n isSnapped: false,\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: { rect: this.startElement },\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 // ---------------------------------------------------------------------------\n // Private: state management\n // ---------------------------------------------------------------------------\n\n private reset() {\n this.state = 'idle';\n this.startPoint = null;\n this.startElement = null;\n this.startRotationElement = null;\n this.gestureRotationCenter = null;\n this.activeHandle = null;\n this.currentPosition = null;\n this.activeVertexIndex = null;\n this.startVertices = [];\n // Reset rotation state\n this.rotationCenter = null;\n this.centerScreen = null;\n this.initialRotation = 0;\n this.lastComputedRotation = 0;\n this.rotationDelta = 0;\n this.rotationSnappedAngle = null;\n }\n\n // ---------------------------------------------------------------------------\n // Private: coordinate transformation (screen → page → local)\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 /**\n * Calculate delta projected into the annotation's local (unrotated) coordinate space.\n * Used for resize and vertex-edit where mouse movement must be mapped to the\n * annotation's own axes, accounting for its rotation.\n */\n private calculateLocalDelta(clientX: number, clientY: number): Position {\n const pageDelta = this.calculateDelta(clientX, clientY);\n const { annotationRotation = 0 } = this.config;\n if (annotationRotation === 0) return pageDelta;\n\n const rad = (annotationRotation * Math.PI) / 180;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n return {\n x: cos * pageDelta.x + sin * pageDelta.y,\n y: -sin * pageDelta.x + cos * pageDelta.y,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Private: vertex clamping\n // ---------------------------------------------------------------------------\n\n private clampPoint(p: Position): Position {\n const bbox = this.config.constraints?.boundingBox;\n if (!bbox) return p;\n\n const { annotationRotation = 0 } = this.config;\n if (annotationRotation === 0) {\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 // When rotated, vertices live in unrotated space. Transform to visual\n // (page) space, clamp to page bounds, then inverse-rotate back.\n const center = this.gestureRotationCenter ??\n this.config.rotationCenter ?? {\n x: this.config.element.origin.x + this.config.element.size.width / 2,\n y: this.config.element.origin.y + this.config.element.size.height / 2,\n };\n const visual = rotatePointAround(p, center, annotationRotation);\n\n const clampedX = Math.max(0, Math.min(visual.x, bbox.width));\n const clampedY = Math.max(0, Math.min(visual.y, bbox.height));\n\n if (clampedX === visual.x && clampedY === visual.y) return p;\n\n return rotatePointAround({ x: clampedX, y: clampedY }, center, -annotationRotation);\n }\n\n private calculateVertexPosition(clientX: number, clientY: number): Position[] {\n if (this.activeVertexIndex === null) return this.startVertices;\n\n const delta = this.calculateLocalDelta(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 // ---------------------------------------------------------------------------\n // Private: drag position\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 // When the annotation is rotated, the visible footprint is the AABB, not\n // the unrotatedRect. Clamp based on AABB dimensions so the annotation can\n // move freely within the page bounds.\n const { annotationRotation = 0, constraints } = this.config;\n const bbox = constraints?.boundingBox;\n if (annotationRotation !== 0 && bbox) {\n let aabbW: number;\n let aabbH: number;\n let offsetX: number;\n let offsetY: number;\n\n if (this.startRotationElement) {\n aabbW = this.startRotationElement.size.width;\n aabbH = this.startRotationElement.size.height;\n offsetX = this.startRotationElement.origin.x - this.startElement.origin.x;\n offsetY = this.startRotationElement.origin.y - this.startElement.origin.y;\n } else {\n const rad = Math.abs((annotationRotation * Math.PI) / 180);\n const cos = Math.abs(Math.cos(rad));\n const sin = Math.abs(Math.sin(rad));\n const w = position.size.width;\n const h = position.size.height;\n aabbW = w * cos + h * sin;\n aabbH = w * sin + h * cos;\n offsetX = (w - aabbW) / 2;\n offsetY = (h - aabbH) / 2;\n }\n\n let { x, y } = position.origin;\n x = Math.max(-offsetX, Math.min(x, bbox.width - aabbW - offsetX));\n y = Math.max(-offsetY, Math.min(y, bbox.height - aabbH - offsetY));\n\n return { origin: { x, y }, size: position.size };\n }\n\n return applyConstraints(position, constraints, this.config.maintainAspectRatio ?? false);\n }\n\n // ---------------------------------------------------------------------------\n // Private: rotation\n // ---------------------------------------------------------------------------\n\n /**\n * Calculate the angle from the center to a point in screen coordinates.\n */\n private calculateAngleFromMouse(clientX: number, clientY: number): number {\n if (!this.centerScreen) return this.initialRotation;\n\n const dx = clientX - this.centerScreen.x;\n const dy = clientY - this.centerScreen.y;\n\n // Dead zone: when the mouse is very close to the center, atan2 becomes\n // extremely sensitive to sub-pixel movements. Hold the last stable angle.\n const dist = Math.sqrt(dx * dx + dy * dy);\n if (dist < 10) return this.lastComputedRotation;\n\n // atan2 gives angle from +X axis; rotate +90° so 0° = top (north).\n // Subtract the page rotation offset to convert the screen-space angle\n // back to the page-space angle used by the annotation model.\n const pageRotOffset = (this.config.pageRotation ?? 0) * 90;\n const angleDeg = Math.atan2(dy, dx) * (180 / Math.PI) + 90 - pageRotOffset;\n\n return normalizeAngle(Math.round(angleDeg));\n }\n\n private applyRotationSnapping(angle: number): {\n angle: number;\n isSnapped: boolean;\n snapTarget?: number;\n } {\n const snapAngles = this.config.rotationSnapAngles ?? [0, 90, 180, 270];\n const threshold = this.config.rotationSnapThreshold ?? 4;\n const normalizedAngle = normalizeAngle(angle);\n\n for (const candidate of snapAngles) {\n const normalizedCandidate = normalizeAngle(candidate);\n const diff = Math.abs(normalizedAngle - normalizedCandidate);\n const minimalDiff = Math.min(diff, 360 - diff);\n if (minimalDiff <= threshold) {\n return {\n angle: normalizedCandidate,\n isSnapped: true,\n snapTarget: normalizedCandidate,\n };\n }\n }\n\n return { angle: normalizedAngle, isSnapped: false };\n }\n}\n","import {\n type DragResizeConfig,\n DragResizeController,\n type InteractionEvent,\n type ResizeHandle,\n} from '../../shared/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(getOptions: () => UseDragResizeOptions) {\n // Use getter function to maintain reactivity\n const config = $derived.by(() => {\n const opts = getOptions();\n const { onUpdate, enabled, ...rest } = opts;\n return rest;\n });\n\n const enabled = $derived(getOptions().enabled ?? true);\n const onUpdate = $derived(getOptions().onUpdate);\n\n let controller = $state<DragResizeController | null>(null);\n\n // Initialize or update controller\n $effect(() => {\n if (!controller) {\n controller = new DragResizeController(config, (event) => onUpdate?.(event));\n } else {\n controller.updateConfig(config);\n }\n });\n\n const handleDragStart = (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controller?.startDrag(e.clientX, e.clientY);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n };\n\n const handleMove = (e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controller?.move(e.clientX, e.clientY, e.buttons);\n };\n\n const handleEnd = (e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n controller?.end();\n (e.currentTarget as HTMLElement).releasePointerCapture?.(e.pointerId);\n };\n\n const createResizeHandler = (handle: ResizeHandle): ResizeHandleEventProps => ({\n onpointerdown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controller?.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\n const createVertexHandler = (vertexIndex: number): ResizeHandleEventProps => ({\n onpointerdown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n controller?.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\n const createRotationHandler = (\n initialRotation: number = 0,\n orbitRadiusPx?: number,\n ): ResizeHandleEventProps => ({\n onpointerdown: (e: PointerEvent) => {\n if (!enabled) return;\n e.preventDefault();\n e.stopPropagation();\n // Use the handle's actual DOM center, not the raw click position.\n // This avoids up to handleSize/2 px error when the user clicks\n // near the edge of the handle circle, which would shift the\n // reverse-engineered center and distort angles near the center.\n const handleRect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n const handleCenterX = handleRect.left + handleRect.width / 2;\n const handleCenterY = handleRect.top + handleRect.height / 2;\n controller?.startRotation(handleCenterX, handleCenterY, initialRotation, orbitRadiusPx);\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n },\n onpointermove: handleMove,\n onpointerup: handleEnd,\n onpointercancel: handleEnd,\n });\n\n const dragProps = $derived(\n enabled\n ? {\n onpointerdown: handleDragStart,\n onpointermove: handleMove,\n onpointerup: handleEnd,\n onpointercancel: handleEnd,\n }\n : {},\n );\n\n return {\n get dragProps() {\n return dragProps;\n },\n createResizeProps: createResizeHandler,\n createVertexProps: createVertexHandler,\n createRotationProps: createRotationHandler,\n };\n}\n","/**\n * Converts a style object with camelCase properties to a CSS string with kebab-case properties.\n *\n * This is useful in Svelte 5 where spreading style objects doesn't work with the `style:` directive.\n * Instead, you can convert the entire style object to a string and apply it to the `style` attribute.\n *\n * @param style - An object containing CSS properties in camelCase format with string or number values\n * @returns A CSS string with kebab-case properties suitable for the HTML style attribute\n *\n * @example\n * ```ts\n * const styles = {\n * position: 'absolute',\n * zIndex: 10,\n * borderRadius: '50%',\n * backgroundColor: '#007ACC'\n * };\n *\n * const cssString = stylesToString(styles);\n * // Returns: \"position: absolute; z-index: 10; border-radius: 50%; background-color: #007ACC\"\n * ```\n *\n * @example\n * Usage in Svelte templates:\n * ```svelte\n * <div style=\"{stylesToString(myStyles)}; color: red;\"></div>\n * ```\n */\nexport function stylesToString(style: Record<string, string | number>): string {\n return Object.entries(style)\n .map(([key, value]) => {\n const cssKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);\n return `${cssKey}: ${value}`;\n })\n .join('; ');\n}\n","import { useDragResize, type UseDragResizeOptions } from './use-drag-resize.svelte';\nimport {\n describeResizeFromConfig,\n describeVerticesFromConfig,\n describeRotationFromConfig,\n type ResizeUI,\n type VertexUI,\n type RotationUI,\n} from '../../shared/plugin-interaction-primitives';\nimport { stylesToString } from '../utils/styles-to-string';\n\nexport type HandleElementProps = {\n key?: string | number;\n style: string;\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 type RotationHandleElementProps = {\n /** Props for the rotation handle element */\n handle: HandleElementProps;\n /** Props for the connector line element (if shown) */\n connector: {\n style: string;\n } & Record<string, any>;\n};\n\nexport function useInteractionHandles(\n getOpts: () => {\n controller: UseDragResizeOptions;\n resizeUI?: ResizeUI;\n vertexUI?: VertexUI;\n rotationUI?: RotationUI;\n includeVertices?: boolean;\n includeRotation?: boolean;\n /** Current rotation angle of the annotation (for initializing rotation interaction) */\n currentRotation?: number;\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 rotationAttrs?: () => Record<string, any> | void;\n },\n) {\n // Use getter function and $derived to maintain reactivity\n const controller = $derived(getOpts().controller);\n const resizeUI = $derived(getOpts().resizeUI);\n const vertexUI = $derived(getOpts().vertexUI);\n const rotationUI = $derived(getOpts().rotationUI);\n const includeVertices = $derived(getOpts().includeVertices ?? false);\n const includeRotation = $derived(getOpts().includeRotation ?? false);\n const currentRotation = $derived(getOpts().currentRotation ?? 0);\n const handleAttrs = $derived(getOpts().handleAttrs);\n const vertexAttrs = $derived(getOpts().vertexAttrs);\n const rotationAttrs = $derived(getOpts().rotationAttrs);\n\n const dragResize = useDragResize(() => controller);\n\n // Resize handles: computed from controller config\n const resize = $derived.by((): HandleElementProps[] => {\n const desc = describeResizeFromConfig(controller, resizeUI);\n return desc.map((d) => ({\n key: d.attrs?.['data-epdf-handle'] as string,\n style: stylesToString(d.style),\n ...dragResize.createResizeProps(d.handle),\n ...(d.attrs ?? {}),\n ...(handleAttrs?.(d.handle) ?? {}),\n }));\n });\n\n // Vertex handles: computed from controller config and vertices\n const vertices = $derived.by((): HandleElementProps[] => {\n if (!includeVertices) return [];\n const desc = describeVerticesFromConfig(controller, vertexUI, controller.vertices);\n return desc.map((d, i) => ({\n key: i,\n style: stylesToString(d.style),\n ...dragResize.createVertexProps(i),\n ...(d.attrs ?? {}),\n ...(vertexAttrs?.(i) ?? {}),\n }));\n });\n\n // Rotation handle: orbits around the center of the element based on current angle\n const rotation = $derived.by((): RotationHandleElementProps | null => {\n if (!includeRotation) return null;\n const desc = describeRotationFromConfig(controller, rotationUI, currentRotation);\n return {\n handle: {\n style: stylesToString(desc.handleStyle),\n ...dragResize.createRotationProps(currentRotation, desc.radius),\n ...(desc.attrs ?? {}),\n ...(rotationAttrs?.() ?? {}),\n },\n connector: {\n style: stylesToString(desc.connectorStyle),\n 'data-epdf-rotation-connector': true,\n },\n };\n });\n\n // Return getters to maintain reactivity when accessed from outside\n return {\n get dragProps() {\n return dragResize.dragProps;\n },\n get resize() {\n return resize;\n },\n get vertices() {\n return vertices;\n },\n get rotation() {\n return rotation;\n },\n };\n}\n","export type DoublePressOptions = {\n delay?: number; // ms between taps\n tolerancePx?: number; // spatial tolerance\n onDouble?: (e: PointerEvent | MouseEvent) => void;\n};\n\nexport function doublePress<T extends Element = Element>(\n node: T,\n options: DoublePressOptions = {},\n) {\n let { onDouble, delay = 300, tolerancePx = 18 } = options;\n\n // last pointerup (time & position)\n const last = { t: 0, x: 0, y: 0 };\n\n const handlePointerUp = (e: Event) => {\n const ev = e as PointerEvent;\n if (!onDouble) return;\n\n // ignore mouse (mouse uses native dblclick)\n // ignore non-primary pointers (multi-touch, etc.)\n if (ev.pointerType === 'mouse' || ev.isPrimary === false) return;\n\n const now = performance.now();\n const x = ev.clientX;\n const y = ev.clientY;\n\n const withinTime = now - last.t <= delay;\n const dx = x - last.x;\n const dy = y - last.y;\n const withinDist = dx * dx + dy * dy <= tolerancePx * tolerancePx;\n\n if (withinTime && withinDist) onDouble?.(ev);\n\n last.t = now;\n last.x = x;\n last.y = y;\n };\n\n const handleDblClick = (e: Event) => {\n onDouble?.(e as MouseEvent);\n };\n\n node.addEventListener('pointerup', handlePointerUp, { capture: true });\n node.addEventListener('dblclick', handleDblClick);\n\n return {\n update(next?: DoublePressOptions) {\n if (!next) return;\n onDouble = next.onDouble;\n // use nullish coalescing so 0 isn't swallowed accidentally (even though 0 isn't useful here)\n delay = next.delay ?? delay;\n tolerancePx = next.tolerancePx ?? tolerancePx;\n },\n destroy() {\n node.removeEventListener('pointerup', handlePointerUp, { capture: true } as any);\n node.removeEventListener('dblclick', handleDblClick);\n },\n };\n}\n","<script lang=\"ts\">\n import type { Snippet } from 'svelte';\n import type { Action } from 'svelte/action';\n import { getCounterRotation } from '@embedpdf/utils';\n import type { Rect, Rotation } from '@embedpdf/models';\n import type { MenuWrapperProps } from './types';\n\n interface CounterRotateProps {\n rect: Rect;\n rotation: Rotation;\n }\n\n interface CounterRotateChildrenProps {\n matrix: string;\n rect: Rect;\n menuWrapperProps: MenuWrapperProps;\n }\n\n interface Props extends CounterRotateProps {\n children?: Snippet<[CounterRotateChildrenProps]>;\n }\n\n let { rect, rotation, children }: Props = $props();\n const counterRotation = $derived(getCounterRotation(rect, rotation));\n\n // Svelte action for capture-phase event handling\n // This is the idiomatic way to attach lifecycle-managed behavior to DOM elements\n const menuWrapperAction: Action<HTMLElement> = (node) => {\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 };\n\n // Use capture phase to intercept before synthetic events\n node.addEventListener('pointerdown', handlePointerDown, { capture: true });\n node.addEventListener('touchstart', handleTouchStart, { capture: true });\n\n return {\n destroy() {\n node.removeEventListener('pointerdown', handlePointerDown, { capture: true });\n node.removeEventListener('touchstart', handleTouchStart, { capture: true });\n },\n };\n };\n\n const menuWrapperStyle = $derived(\n `position: absolute; ` +\n `left: ${rect.origin.x}px; ` +\n `top: ${rect.origin.y}px; ` +\n `transform: ${counterRotation.matrix}; ` +\n `transform-origin: 0 0; ` +\n `width: ${counterRotation.width}px; ` +\n `height: ${counterRotation.height}px; ` +\n `pointer-events: none; ` +\n `z-index: 3`,\n );\n\n const menuWrapperProps: MenuWrapperProps = $derived({\n style: menuWrapperStyle,\n action: menuWrapperAction,\n });\n</script>\n\n{#if children}\n {@render children({\n menuWrapperProps,\n matrix: counterRotation.matrix,\n rect: {\n origin: { x: rect.origin.x, y: rect.origin.y },\n size: { width: counterRotation.width, height: counterRotation.height },\n },\n })}\n{/if}\n","/**\n * Converts Svelte proxy objects to plain JavaScript objects.\n * This is useful when passing data to Web Workers or other contexts\n * that cannot handle Svelte's reactive proxies.\n *\n * Inspired by the Vue implementation, this recursively traverses the object\n * and handles primitives, arrays, and plain objects while stripping reactive proxies.\n */\nexport function deepToRaw<T extends Record<string, any>>(sourceObj: T): T {\n const objectIterator = (input: any): any => {\n // Handle null and undefined\n if (input === null || input === undefined) {\n return input;\n }\n\n // Handle primitives (string, number, boolean, bigint, symbol)\n if (typeof input !== 'object') {\n return input;\n }\n\n // Handle Arrays\n if (Array.isArray(input)) {\n return input.map((item) => objectIterator(item));\n }\n\n // Handle Date objects\n if (input instanceof Date) {\n return new Date(input.getTime());\n }\n\n // Handle RegExp\n if (input instanceof RegExp) {\n return new RegExp(input.source, input.flags);\n }\n\n // Handle plain objects (including Svelte proxies)\n // For Svelte proxies, we recursively extract plain values\n if (Object.prototype.toString.call(input) === '[object Object]') {\n return Object.keys(input).reduce((acc, key) => {\n // Skip non-enumerable properties and functions\n const value = input[key];\n if (typeof value !== 'function') {\n acc[key as keyof typeof acc] = objectIterator(value);\n }\n return acc;\n }, {} as T);\n }\n\n // For other object types (Map, Set, etc.), use JSON roundtrip as fallback\n // This will convert them to plain objects/arrays\n try {\n return JSON.parse(JSON.stringify(input));\n } catch {\n // If JSON serialization fails, return undefined\n return undefined;\n }\n };\n\n return objectIterator(sourceObj);\n}\n"],"names":["onUpdate","enabled"],"mappings":";;;;AAiCO,MAAM,yBAAyB;AAuBtC,MAAM,oBAAkD;AAAA,EACtD,GAAG;AAAA,EACH,IAAI;AAAA,EACJ,GAAG;AAAA,EACH,IAAI;AAAA,EACJ,GAAG;AAAA,EACH,IAAI;AAAA,EACJ,GAAG;AAAA,EACH,IAAI;AACN;AAMA,MAAM,iBAA2B;AAAA,EAC/B;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AAEA,SAAS,eACP,QACA,kBACA,qBAA6B,GACrB;AACR,QAAM,YAAY,mBAAmB;AACrC,QAAM,aAAa,kBAAkB,MAAM,IAAI,YAAY;AAE3D,QAAM,cAAe,aAAa,MAAO,OAAO;AAEhD,QAAM,SAAS,KAAK,MAAM,aAAa,EAAE,IAAI;AAC7C,SAAO,eAAe,MAAM;AAC9B;AAEA,SAAS,WAAW,GAAW,SAAiB,MAAuC;AAErF,QAAM,OAAO,CAAC,IAAI;AAClB,MAAI,SAAS,SAAU,QAAO;AAE9B,SAAO,SAAS,YAAY,OAAO,UAAU,OAAO;AACtD;AAEO,SAAS,yBACd,KACA,KAAe,IACK;AACpB,QAAM;AAAA,IACJ,aAAa;AAAA,IACb,UAAU;AAAA,IACV,aAAa;AAAA,IACb,eAAe;AAAA,IACf,SAAS;AAAA,IACT,sBAAsB;AAAA,EAAA,IACpB;AAEJ,QAAM,oBAAqB,IAAI,gBAAgB,KAAK;AACpD,QAAM,gBAAgB,IAAI,sBAAsB;AAEhD,QAAM,MAAM,CAAC,UAA+C;AAAA,IAC1D,CAAC,IAAI,GAAG,WAAW,YAAY,SAAS,UAAU,IAAI;AAAA,EAAA;AAGxD,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,EAAA,CAAG;AAAA,EAAA;AAE9C,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,MAAA,CAAO;AAAA,EAAA,IAEnE,CAAA;AAEJ,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;AAAA,MACpB,QAAQ,aAAa;AAAA,MACrB,cAAc;AAAA,MACd;AAAA,MACA,QAAQ,sBACJ,eAAe,QAAQ,kBAAkB,aAAa,IACtD;AAAA,MACJ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,GAAI;AAAA,IAAA;AAAA,IAEN,OAAO,EAAE,oBAAoB,OAAA;AAAA,EAAO,EACpC;AACJ;AAEO,SAAS,2BACd,KACA,KAAe,CAAA,GACf,cACoB;AACpB,QAAM,EAAE,aAAa,IAAI,SAAS,MAAM;AACxC,QAAM,OAAa,IAAI;AACvB,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,QAAQ,gBAAgB,IAAI,YAAY,CAAA;AAE9C,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;AACzD,WAAO;AAAA,MACL,QAAQ;AAAA;AAAA,MACR,OAAO;AAAA,QACL,UAAU;AAAA,QACV,MAAM,OAAO;AAAA,QACb,KAAK,MAAM;AAAA,QACX,OAAO,aAAa;AAAA,QACpB,QAAQ,aAAa;AAAA,QACrB,cAAc;AAAA,QACd,QAAQ;AAAA,QACR;AAAA,QACA,eAAe;AAAA,QACf,aAAa;AAAA,MAAA;AAAA,MAEf,OAAO,EAAE,oBAAoB,EAAA;AAAA,IAAE;AAAA,EAEnC,CAAC;AACH;AAUO,SAAS,2BACd,KACA,KAAiB,CAAA,GACjB,eAAuB,GACG;AAC1B,QAAM,EAAE,aAAa,IAAI,SAAS,GAAG,gBAAgB,MAAM,iBAAiB,EAAA,IAAM;AAElF,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,OAAO,IAAI;AAEjB,QAAM,YAAY,IAAI,mBAAmB;AACzC,QAAM,cAAc,IAAI,kBAAkB;AAAA,IACxC,GAAG,KAAK,OAAO,IAAI,KAAK,KAAK,QAAQ;AAAA,IACrC,GAAG,KAAK,OAAO,IAAI,KAAK,KAAK,SAAS;AAAA,EAAA;AAIpB,YAAU,KAAK,QAAQ;AACtB,YAAU,KAAK,SAAS;AAC7C,QAAM,WAAW,YAAY,IAAI,UAAU,OAAO,KAAK;AACvD,QAAM,WAAW,YAAY,IAAI,UAAU,OAAO,KAAK;AAGvD,QAAM,WAAY,eAAe,KAAK,KAAM;AAO5C,QAAM,SAAS,GAAG,UAAU;AAC5B,QAAM,SAAU,KAAK,KAAK,SAAS,QAAS,IAAI;AAEhD,QAAM,gBAAgB,UAAU,SAAS,KAAK,IAAI,QAAQ;AAC1D,QAAM,gBAAgB,UAAU,SAAS,KAAK,IAAI,QAAQ;AAC1D,QAAM,aAAa,gBAAgB,aAAa;AAChD,QAAM,YAAY,gBAAgB,aAAa;AAE/C,SAAO;AAAA,IACL,aAAa;AAAA,MACX,UAAU;AAAA,MACV,MAAM,aAAa;AAAA,MACnB,KAAK,YAAY;AAAA,MACjB,OAAO,aAAa;AAAA,MACpB,QAAQ,aAAa;AAAA,MACrB,cAAc;AAAA,MACd,QAAQ;AAAA,MACR;AAAA,MACA,eAAe;AAAA,MACf,aAAa;AAAA,IAAA;AAAA,IAEf,gBAAgB,gBACZ;AAAA,MACE,UAAU;AAAA,MACV,MAAM,UAAU,iBAAiB,IAAI;AAAA,MACrC,KAAK,UAAU,SAAS;AAAA,MACxB,OAAO,iBAAiB;AAAA,MACxB,QAAQ,SAAS;AAAA,MACjB,iBAAiB;AAAA,MACjB,WAAW,UAAU,YAAY;AAAA,MACjC,QAAQ,SAAS;AAAA,MACjB,eAAe;AAAA,IAAA,IAEjB,CAAA;AAAA,IACJ;AAAA,IACA,OAAO,EAAE,6BAA6B,KAAA;AAAA,EAAK;AAE/C;ACjPO,SAAS,UAAU,QAA8B;AACtD,SAAO;AAAA,IACL,GAAG,OAAO,SAAS,GAAG,IAAI,SAAS,OAAO,SAAS,GAAG,IAAI,UAAU;AAAA,IACpE,GAAG,OAAO,SAAS,GAAG,IAAI,QAAQ,OAAO,SAAS,GAAG,IAAI,WAAW;AAAA,EAAA;AAExE;AAGO,SAAS,eAAe,MAAY,QAA0B;AACnE,QAAM,IACJ,OAAO,MAAM,SACT,KAAK,OAAO,IACZ,OAAO,MAAM,UACX,KAAK,OAAO,IAAI,KAAK,KAAK,QAC1B,KAAK,OAAO,IAAI,KAAK,KAAK,QAAQ;AAC1C,QAAM,IACJ,OAAO,MAAM,QACT,KAAK,OAAO,IACZ,OAAO,MAAM,WACX,KAAK,OAAO,IAAI,KAAK,KAAK,SAC1B,KAAK,OAAO,IAAI,KAAK,KAAK,SAAS;AAC3C,SAAO,EAAE,GAAG,EAAA;AACd;AAqBO,SAAS,iBAAiB,WAAiB,OAAiB,QAAsB;AACvF,MAAI,IAAI,UAAU,OAAO;AACzB,MAAI,IAAI,UAAU,OAAO;AACzB,MAAI,QAAQ,UAAU,KAAK;AAC3B,MAAI,SAAS,UAAU,KAAK;AAE5B,MAAI,OAAO,MAAM,QAAQ;AACvB,aAAS,MAAM;AAAA,EACjB,WAAW,OAAO,MAAM,SAAS;AAC/B,SAAK,MAAM;AACX,aAAS,MAAM;AAAA,EACjB;AAEA,MAAI,OAAO,MAAM,OAAO;AACtB,cAAU,MAAM;AAAA,EAClB,WAAW,OAAO,MAAM,UAAU;AAChC,SAAK,MAAM;AACX,cAAU,MAAM;AAAA,EAClB;AAEA,SAAO,EAAE,QAAQ,EAAE,GAAG,EAAA,GAAK,MAAM,EAAE,OAAO,SAAO;AACnD;AAOO,SAAS,mBACd,MACA,WACA,QACA,aACM;AACN,MAAI,EAAE,GAAG,EAAA,IAAM,KAAK;AACpB,MAAI,EAAE,OAAO,OAAA,IAAW,KAAK;AAE7B,QAAM,eAAe,OAAO,MAAM,YAAY,OAAO,MAAM;AAE3D,MAAI,cAAc;AAChB,QAAI,OAAO,MAAM,UAAU;AACzB,eAAS,QAAQ;AACjB,UAAI,UAAU,OAAO,KAAK,UAAU,KAAK,SAAS,UAAU;AAAA,IAC9D,OAAO;AACL,cAAQ,SAAS;AACjB,UAAI,UAAU,OAAO,KAAK,UAAU,KAAK,QAAQ,SAAS;AAAA,IAC5D;AAAA,EACF,OAAO;AACL,UAAM,KAAK,KAAK,IAAI,QAAQ,UAAU,KAAK,KAAK;AAChD,UAAM,KAAK,KAAK,IAAI,SAAS,UAAU,KAAK,MAAM;AAClD,UAAM,QAAQ,KAAK;AAEnB,QAAI,UAAU,GAAG;AACf,cAAQ,UAAU,KAAK;AACvB,eAAS,UAAU,KAAK;AAAA,IAC1B,OAAO;AAML,YAAM,UAAU,KAAK;AACrB,YAAM,UAAU,KAAK;AACrB,YAAM,SAAS;AACf,YAAM,SAAS,QAAQ;AACvB,YAAM,SAAS,SAAS;AACxB,YAAM,SAAS;AACf,cAAQ,UAAU,SAAS,UAAU;AACrC,eAAS,UAAU,SAAS,UAAU;AAAA,IACxC;AAAA,EACF;AAEA,MAAI,OAAO,MAAM,SAAS;AACxB,QAAI,UAAU,OAAO,IAAI,UAAU,KAAK,QAAQ;AAAA,EAClD;AACA,MAAI,OAAO,MAAM,UAAU;AACzB,QAAI,UAAU,OAAO,IAAI,UAAU,KAAK,SAAS;AAAA,EACnD;AAEA,SAAO,EAAE,QAAQ,EAAE,GAAG,EAAA,GAAK,MAAM,EAAE,OAAO,SAAO;AACnD;AAKO,SAAS,cACd,MACA,WACA,QACA,MACA,qBACM;AACN,MAAI,CAAC,KAAM,QAAO;AAElB,MAAI,EAAE,GAAG,EAAA,IAAM,KAAK;AACpB,MAAI,EAAE,OAAO,OAAA,IAAW,KAAK;AAE7B,UAAQ,KAAK,IAAI,GAAG,KAAK;AACzB,WAAS,KAAK,IAAI,GAAG,MAAM;AAE3B,QAAM,UACJ,OAAO,MAAM,SAAS,UAAU,OAAO,IAAI,UAAU,OAAO,IAAI,UAAU,KAAK;AACjF,QAAM,UACJ,OAAO,MAAM,QAAQ,UAAU,OAAO,IAAI,UAAU,OAAO,IAAI,UAAU,KAAK;AAEhF,QAAM,OACJ,OAAO,MAAM,SACT,KAAK,QAAQ,UACb,OAAO,MAAM,UACX,UACA,KAAK,IAAI,UAAU,OAAO,GAAG,KAAK,QAAQ,UAAU,OAAO,IAAI,UAAU,KAAK,KAAK,IAAI,IACvF,UAAU,KAAK;AAEvB,QAAM,OACJ,OAAO,MAAM,QACT,KAAK,SAAS,UACd,OAAO,MAAM,WACX,UACA,KAAK,IAAI,UAAU,OAAO,GAAG,KAAK,SAAS,UAAU,OAAO,IAAI,UAAU,KAAK,MAAM,IACnF,IACF,UAAU,KAAK;AAEvB,MAAI,qBAAqB;AACvB,UAAM,SAAS,QAAQ,OAAO,OAAO,QAAQ;AAC7C,UAAM,SAAS,SAAS,OAAO,OAAO,SAAS;AAC/C,UAAM,QAAQ,KAAK,IAAI,QAAQ,MAAM;AAErC,QAAI,QAAQ,GAAG;AACb,eAAS;AACT,gBAAU;AAAA,IACZ;AAAA,EACF,OAAO;AACL,YAAQ,KAAK,IAAI,OAAO,IAAI;AAC5B,aAAS,KAAK,IAAI,QAAQ,IAAI;AAAA,EAChC;AAEA,MAAI,OAAO,MAAM,QAAQ;AACvB,QAAI;AAAA,EACN,WAAW,OAAO,MAAM,SAAS;AAC/B,QAAI,UAAU;AAAA,EAChB,OAAO;AACL,QAAI,UAAU,OAAO,KAAK,UAAU,KAAK,QAAQ,SAAS;AAAA,EAC5D;AAEA,MAAI,OAAO,MAAM,OAAO;AACtB,QAAI;AAAA,EACN,WAAW,OAAO,MAAM,UAAU;AAChC,QAAI,UAAU;AAAA,EAChB,OAAO;AACL,QAAI,UAAU,OAAO,KAAK,UAAU,KAAK,SAAS,UAAU;AAAA,EAC9D;AAEA,MAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,QAAQ,KAAK,CAAC;AAC/C,MAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,SAAS,MAAM,CAAC;AAEjD,SAAO,EAAE,QAAQ,EAAE,GAAG,EAAA,GAAK,MAAM,EAAE,OAAO,SAAO;AACnD;AAMO,SAAS,aAAa,MAAY,WAAiB,QAAsB;AAC9E,MAAI;AACJ,MAAI;AAEJ,MAAI,OAAO,MAAM,QAAQ;AACvB,QAAI,UAAU,OAAO;AAAA,EACvB,WAAW,OAAO,MAAM,SAAS;AAC/B,QAAI,UAAU,OAAO,IAAI,UAAU,KAAK,QAAQ,KAAK,KAAK;AAAA,EAC5D,OAAO;AACL,QAAI,UAAU,OAAO,KAAK,UAAU,KAAK,QAAQ,KAAK,KAAK,SAAS;AAAA,EACtE;AAEA,MAAI,OAAO,MAAM,OAAO;AACtB,QAAI,UAAU,OAAO;AAAA,EACvB,WAAW,OAAO,MAAM,UAAU;AAChC,QAAI,UAAU,OAAO,IAAI,UAAU,KAAK,SAAS,KAAK,KAAK;AAAA,EAC7D,OAAO;AACL,QAAI,UAAU,OAAO,KAAK,UAAU,KAAK,SAAS,KAAK,KAAK,UAAU;AAAA,EACxE;AAEA,SAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,MAAM,KAAK,KAAA;AACxC;AAKO,SAAS,iBACd,UACA,aACA,qBACA,oBAA6B,OACvB;AACN,MAAI,CAAC,YAAa,QAAO;AAEzB,MAAI;AAAA,IACF,QAAQ,EAAE,GAAG,EAAA;AAAA,IACb,MAAM,EAAE,OAAO,OAAA;AAAA,EAAO,IACpB;AAEJ,QAAM,OAAO,YAAY,YAAY;AACrC,QAAM,OAAO,YAAY,aAAa;AACtC,QAAM,OAAO,YAAY;AACzB,QAAM,OAAO,YAAY;AAEzB,MAAI,uBAAuB,QAAQ,KAAK,SAAS,GAAG;AAClD,UAAM,QAAQ,QAAQ;AAEtB,QAAI,QAAQ,MAAM;AAChB,cAAQ;AACR,eAAS,QAAQ;AAAA,IACnB;AACA,QAAI,SAAS,MAAM;AACjB,eAAS;AACT,cAAQ,SAAS;AAAA,IACnB;AAEA,QAAI,SAAS,UAAa,QAAQ,MAAM;AACtC,cAAQ;AACR,eAAS,QAAQ;AAAA,IACnB;AACA,QAAI,SAAS,UAAa,SAAS,MAAM;AACvC,eAAS;AACT,cAAQ,SAAS;AAAA,IACnB;AAAA,EACF,OAAO;AACL,YAAQ,KAAK,IAAI,MAAM,KAAK;AAC5B,aAAS,KAAK,IAAI,MAAM,MAAM;AAC9B,QAAI,SAAS,OAAW,SAAQ,KAAK,IAAI,MAAM,KAAK;AACpD,QAAI,SAAS,OAAW,UAAS,KAAK,IAAI,MAAM,MAAM;AAAA,EACxD;AAEA,MAAI,YAAY,eAAe,CAAC,mBAAmB;AACjD,QAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,YAAY,YAAY,QAAQ,KAAK,CAAC;AAClE,QAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,YAAY,YAAY,SAAS,MAAM,CAAC;AAAA,EACtE;AAEA,SAAO,EAAE,QAAQ,EAAE,GAAG,EAAA,GAAK,MAAM,EAAE,OAAO,SAAO;AACnD;AAKO,SAAS,0BACd,MACA,cACA,MACS;AACT,QAAM,MAAM;AACZ,QAAM,OAAO,yBAAyB,MAAM,YAAY;AACxD,SACE,KAAK,OAAO,KAAK,CAAC,OAClB,KAAK,OAAO,KAAK,CAAC,OAClB,KAAK,OAAO,IAAI,KAAK,KAAK,SAAS,KAAK,QAAQ,OAChD,KAAK,OAAO,IAAI,KAAK,KAAK,UAAU,KAAK,SAAS;AAEtD;AAiBA,SAAS,kBACP,OACA,QACA,QACA,kBACA,6BACM;AACN,QAAM,EAAE,WAAW,sBAAsB,OAAO,qBAAqB,GAAG,gBAAgB;AACxF,QAAM,SAAS,UAAU,MAAM;AAC/B,QAAM,cAAc,UAAU,KAAK,QAAQ,UAAU,KAAK,UAAU;AAGpE,MAAI,OAAO,iBAAiB,WAAW,OAAO,MAAM;AAGpD,MAAI,qBAAqB;AACvB,WAAO,mBAAmB,MAAM,WAAW,QAAQ,WAAW;AAAA,EAChE;AAGA,MAAI,kBAAkB;AACpB,WAAO,cAAc,MAAM,WAAW,QAAQ,2CAAa,aAAa,mBAAmB;AAAA,EAC7F;AAGA,SAAO,iBAAiB,MAAM,aAAa,qBAAqB,2BAA2B;AAK3F,MAAI,6BAA6B;AAC/B,WAAO,aAAa,MAAM,WAAW,MAAM;AAAA,EAC7C;AAGA,MAAI,uBAAuB,GAAG;AAC5B,UAAM,WAAW,eAAe,WAAW,MAAM;AACjD,UAAM,YAAsB;AAAA,MAC1B,GAAG,UAAU,OAAO,IAAI,UAAU,KAAK,QAAQ;AAAA,MAC/C,GAAG,UAAU,OAAO,IAAI,UAAU,KAAK,SAAS;AAAA,IAAA;AAElD,UAAM,YAAsB;AAAA,MAC1B,GAAG,KAAK,OAAO,IAAI,KAAK,KAAK,QAAQ;AAAA,MACrC,GAAG,KAAK,OAAO,IAAI,KAAK,KAAK,SAAS;AAAA,IAAA;AAExC,UAAM,YAAY,kBAAkB,UAAU,WAAW,kBAAkB;AAC3E,UAAM,YAAY,kBAAkB,UAAU,WAAW,kBAAkB;AAC3E,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,GAAG,KAAK,OAAO,KAAK,UAAU,IAAI,UAAU;AAAA,QAC5C,GAAG,KAAK,OAAO,KAAK,UAAU,IAAI,UAAU;AAAA,MAAA;AAAA,MAE9C,MAAM,KAAK;AAAA,IAAA;AAAA,EAEf;AAEA,SAAO;AACT;AASO,SAAS,mBACd,OACA,QACA,QACM;AACN,QAAM,EAAE,qBAAqB,GAAG,YAAA,IAAgB;AAChD,QAAM,OAAO,2CAAa;AAG1B,MAAI,uBAAuB,KAAK,MAAM;AACpC,UAAM,SAAS,kBAAkB,OAAO,QAAQ,QAAQ,OAAO,IAAI;AACnE,QAAI,0BAA0B,QAAQ,oBAAoB,IAAI,GAAG;AAC/D,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,kBAAkB,EAAE,GAAG,GAAG,GAAG,EAAA,GAAK,QAAQ,QAAQ,OAAO,IAAI;AACxE,QAAI,MAAM;AACV,QAAI,OAAO;AACX,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK,GAAG;AAC9B,YAAM,OAAO,MAAM,QAAQ;AAC3B,YAAM,QAAQ;AAAA,QACZ,EAAE,GAAG,MAAM,IAAI,KAAK,GAAG,MAAM,IAAI,IAAA;AAAA,QACjC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAEF,UAAI,0BAA0B,OAAO,oBAAoB,IAAI,GAAG;AAC9D,eAAO;AACP,cAAM;AAAA,MACR,OAAO;AACL,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,SAAO,kBAAkB,OAAO,QAAQ,QAAQ,MAAM,KAAK;AAC7D;AC7XO,MAAM,qBAAqB;AAAA,EAsBhC,YACU,QACA,UACR;AAFQ,SAAA,SAAA;AACA,SAAA,WAAA;AAvBV,SAAQ,QAA0B;AAClC,SAAQ,aAA8B;AACtC,SAAQ,eAA4B;AACpC,SAAQ,uBAAoC;AAC5C,SAAQ,wBAAyC;AACjD,SAAQ,eAAoC;AAC5C,SAAQ,kBAA+B;AAGvC,SAAQ,oBAAmC;AAC3C,SAAQ,gBAA4B,CAAA;AACpC,SAAQ,kBAA8B,CAAA;AAGtC,SAAQ,iBAAkC;AAC1C,SAAQ,eAAgC;AACxC,SAAQ,kBAA0B;AAClC,SAAQ,uBAA+B;AACvC,SAAQ,gBAAwB;AAChC,SAAQ,uBAAsC;AAM5C,SAAK,kBAAkB,OAAO,YAAY,CAAA;AAAA,EAC5C;AAAA,EAEA,aAAa,QAAmC;AAC9C,SAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,OAAA;AAInC,QAAI,KAAK,UAAU,kBAAkB;AACnC,WAAK,kBAAkB,OAAO,YAAY,CAAA;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,SAAiB,SAAiB;AAC1C,SAAK,QAAQ;AACb,SAAK,aAAa,EAAE,GAAG,SAAS,GAAG,QAAA;AACnC,SAAK,eAAe,EAAE,GAAG,KAAK,OAAO,QAAA;AACrC,SAAK,uBAAuB,KAAK,OAAO,kBACpC,EAAE,GAAG,KAAK,OAAO,gBAAA,IACjB;AACJ,SAAK,kBAAkB,EAAE,GAAG,KAAK,OAAO,QAAA;AAExC,SAAK,SAAS;AAAA,MACZ,OAAO;AAAA,MACP,eAAe;AAAA,QACb,MAAM;AAAA,QACN,SAAS,EAAE,MAAM,KAAK,aAAA;AAAA,MAAa;AAAA,IACrC,CACD;AAAA,EACH;AAAA,EAEA,YAAY,QAAsB,SAAiB,SAAiB;AAClE,SAAK,QAAQ;AACb,SAAK,eAAe;AACpB,SAAK,aAAa,EAAE,GAAG,SAAS,GAAG,QAAA;AACnC,SAAK,eAAe,EAAE,GAAG,KAAK,OAAO,QAAA;AACrC,SAAK,kBAAkB,EAAE,GAAG,KAAK,OAAO,QAAA;AAExC,SAAK,SAAS;AAAA,MACZ,OAAO;AAAA,MACP,eAAe;AAAA,QACb,MAAM;AAAA,QACN,SAAS,EAAE,MAAM,KAAK,aAAA;AAAA,QACtB,UAAU;AAAA,UACR,QAAQ,KAAK;AAAA,UACb,qBAAqB,KAAK,OAAO;AAAA,QAAA;AAAA,MACnC;AAAA,IACF,CACD;AAAA,EACH;AAAA,EAEA,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,QAAA;AACnC,SAAK,gBAAgB,CAAC,GAAG,KAAK,eAAe;AAC7C,SAAK,wBAAwB,KAAK,OAAO,kBAAkB;AAAA,MACzD,GAAG,KAAK,OAAO,QAAQ,OAAO,IAAI,KAAK,OAAO,QAAQ,KAAK,QAAQ;AAAA,MACnE,GAAG,KAAK,OAAO,QAAQ,OAAO,IAAI,KAAK,OAAO,QAAQ,KAAK,SAAS;AAAA,IAAA;AAGtE,SAAK,SAAS;AAAA,MACZ,OAAO;AAAA,MACP,eAAe;AAAA,QACb,MAAM;AAAA,QACN,SAAS,EAAE,UAAU,KAAK,cAAA;AAAA,QAC1B,UAAU,EAAE,YAAA;AAAA,MAAY;AAAA,IAC1B,CACD;AAAA,EACH;AAAA,EAEA,cACE,SACA,SACA,kBAA0B,GAC1B,eACA;AACA,SAAK,QAAQ;AACb,SAAK,aAAa,EAAE,GAAG,SAAS,GAAG,QAAA;AACnC,SAAK,eAAe,EAAE,GAAG,KAAK,OAAO,QAAA;AAGrC,SAAK,iBAAiB,KAAK,OAAO,kBAAkB;AAAA,MAClD,GAAG,KAAK,OAAO,QAAQ,OAAO,IAAI,KAAK,OAAO,QAAQ,KAAK,QAAQ;AAAA,MACnE,GAAG,KAAK,OAAO,QAAQ,OAAO,IAAI,KAAK,OAAO,QAAQ,KAAK,SAAS;AAAA,IAAA;AAItE,UAAM,EAAE,QAAQ,EAAA,IAAM,KAAK;AAC3B,UAAM,YAAY,KAAK,OAAO,mBAAmB,KAAK,OAAO;AAC7D,UAAM,KAAK,UAAU,KAAK,QAAQ;AAClC,UAAM,KAAK,UAAU,KAAK,SAAS;AACnC,UAAM,SAAS,iBAAiB,KAAK,IAAI,IAAI,EAAE,IAAI,IAAI;AACvD,UAAM,iBAAiB,KAAK,OAAO,gBAAgB,KAAK;AACxD,UAAM,kBAAmB,kBAAkB,iBAAiB,KAAK,KAAM;AACvE,SAAK,eAAe;AAAA,MAClB,GAAG,UAAU,SAAS,KAAK,IAAI,cAAc;AAAA,MAC7C,GAAG,UAAU,SAAS,KAAK,IAAI,cAAc;AAAA,IAAA;AAG/C,SAAK,kBAAkB;AACvB,SAAK,uBAAuB;AAC5B,SAAK,gBAAgB;AACrB,SAAK,uBAAuB;AAE5B,SAAK,SAAS;AAAA,MACZ,OAAO;AAAA,MACP,eAAe;AAAA,QACb,MAAM;AAAA,QACN,SAAS,EAAE,UAAU,gBAAA;AAAA,QACrB,UAAU;AAAA,UACR,eAAe;AAAA,UACf,eAAe;AAAA,UACf,gBAAgB,KAAK;AAAA,UACrB,WAAW;AAAA,QAAA;AAAA,MACb;AAAA,IACF,CACD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,SAAiB,SAAiB,SAAkB;AACvD,QAAI,KAAK,UAAU,UAAU,CAAC,KAAK,WAAY;AAI/C,QAAI,YAAY,UAAa,YAAY,GAAG;AAC1C,WAAK,IAAA;AACL;AAAA,IACF;AAEA,QAAI,KAAK,UAAU,cAAc,KAAK,cAAc;AAClD,YAAM,QAAQ,KAAK,eAAe,SAAS,OAAO;AAClD,YAAM,WAAW,KAAK,sBAAsB,KAAK;AACjD,WAAK,kBAAkB;AAEvB,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe,EAAE,MAAM,QAAQ,SAAS,EAAE,MAAM,WAAS;AAAA,MAAE,CAC5D;AAAA,IACH,WAAW,KAAK,UAAU,cAAc,KAAK,gBAAgB,KAAK,cAAc;AAC9E,YAAM,QAAQ,KAAK,oBAAoB,SAAS,OAAO;AACvD,YAAM,WAAW,mBAAmB,OAAO,KAAK,cAAc;AAAA,QAC5D,WAAW,KAAK;AAAA,QAChB,qBAAqB,KAAK,OAAO;AAAA,QACjC,oBAAoB,KAAK,OAAO;AAAA,QAChC,aAAa,KAAK,OAAO;AAAA,MAAA,CAC1B;AACD,WAAK,kBAAkB;AAEvB,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM;AAAA,UACN,SAAS,EAAE,MAAM,SAAA;AAAA,UACjB,UAAU;AAAA,YACR,QAAQ,KAAK;AAAA,YACb,qBAAqB,KAAK,OAAO;AAAA,UAAA;AAAA,QACnC;AAAA,MACF,CACD;AAAA,IACH,WAAW,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,EAAE,SAAA;AAAA,UACX,UAAU,EAAE,aAAa,KAAK,kBAAA;AAAA,QAAkB;AAAA,MAClD,CACD;AAAA,IACH,WAAW,KAAK,UAAU,cAAc,KAAK,gBAAgB;AAC3D,YAAM,gBAAgB,KAAK,wBAAwB,SAAS,OAAO;AACnE,YAAM,aAAa,KAAK,sBAAsB,aAAa;AAC3D,YAAM,eAAe,eAAe,WAAW,KAAK;AACpD,YAAM,gBAAgB,KAAK;AAC3B,YAAM,WAAW,eAAe;AAChC,YAAM,gBACJ,WAAW,MAAM,WAAW,MAAM,WAAW,OAAO,WAAW,MAAM;AAEvE,WAAK,iBAAiB;AACtB,WAAK,uBAAuB;AAC5B,WAAK,uBAAuB,WAAW,YAAY,eAAe;AAElE,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM;AAAA,UACN,SAAS,EAAE,UAAU,aAAA;AAAA,UACrB,UAAU;AAAA,YACR,eAAe;AAAA,YACf,eAAe,KAAK;AAAA,YACpB,gBAAgB,KAAK;AAAA,YACrB,WAAW,WAAW;AAAA,YACtB,cAAc,KAAK,wBAAwB;AAAA,YAC3C,gBAAgB,EAAE,SAAS,QAAA;AAAA,UAAQ;AAAA,QACrC;AAAA,MACF,CACD;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM;AACJ,QAAI,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,EAAE,UAAU,KAAK,gBAAA;AAAA,UAC1B,UAAU,EAAE,aAAa,eAAe,OAAA;AAAA,QAAU;AAAA,MACpD,CACD;AAAA,IACH,WAAW,aAAa,YAAY;AAClC,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM;AAAA,UACN,SAAS,EAAE,UAAU,KAAK,qBAAA;AAAA,UAC1B,UAAU;AAAA,YACR,eAAe,KAAK;AAAA,YACpB,eAAe,KAAK;AAAA,YACpB,gBAAgB,KAAK,kBAAkB;AAAA,YACvC,WAAW,KAAK,yBAAyB;AAAA,YACzC,cAAc,KAAK,wBAAwB;AAAA,UAAA;AAAA,QAC7C;AAAA,MACF,CACD;AAAA,IACH,OAAO;AACL,YAAM,gBAAgB,KAAK,mBAAmB,KAAK,OAAO;AAC1D,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM,aAAa,aAAa,SAAS;AAAA,UACzC,SAAS,EAAE,MAAM,cAAA;AAAA,UACjB,UACE,aAAa,aACT,SACA;AAAA,YACE,QAAQ,UAAU;AAAA,YAClB,qBAAqB,KAAK,OAAO;AAAA,UAAA;AAAA,QACnC;AAAA,MACR,CACD;AAAA,IACH;AAEA,SAAK,MAAA;AAAA,EACP;AAAA,EAEA,SAAS;AACP,QAAI,KAAK,UAAU,OAAQ;AAE3B,QAAI,KAAK,UAAU,kBAAkB;AACnC,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM;AAAA,UACN,SAAS,EAAE,UAAU,KAAK,cAAA;AAAA,UAC1B,UAAU,EAAE,aAAa,KAAK,qBAAqB,OAAA;AAAA,QAAU;AAAA,MAC/D,CACD;AAAA,IACH,WAAW,KAAK,UAAU,YAAY;AACpC,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM;AAAA,UACN,SAAS,EAAE,UAAU,KAAK,gBAAA;AAAA,UAC1B,UAAU;AAAA,YACR,eAAe,KAAK;AAAA,YACpB,eAAe;AAAA,YACf,gBAAgB,KAAK,kBAAkB;AAAA,YACvC,WAAW;AAAA,UAAA;AAAA,QACb;AAAA,MACF,CACD;AAAA,IACH,WAAW,KAAK,cAAc;AAC5B,WAAK,SAAS;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,UACb,MAAM,KAAK,UAAU,aAAa,SAAS;AAAA,UAC3C,SAAS,EAAE,MAAM,KAAK,aAAA;AAAA,UACtB,UACE,KAAK,UAAU,aACX,SACA;AAAA,YACE,QAAQ,KAAK,gBAAgB;AAAA,YAC7B,qBAAqB,KAAK,OAAO;AAAA,UAAA;AAAA,QACnC;AAAA,MACR,CACD;AAAA,IACH;AAEA,SAAK,MAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAMQ,QAAQ;AACd,SAAK,QAAQ;AACb,SAAK,aAAa;AAClB,SAAK,eAAe;AACpB,SAAK,uBAAuB;AAC5B,SAAK,wBAAwB;AAC7B,SAAK,eAAe;AACpB,SAAK,kBAAkB;AACvB,SAAK,oBAAoB;AACzB,SAAK,gBAAgB,CAAA;AAErB,SAAK,iBAAiB;AACtB,SAAK,eAAe;AACpB,SAAK,kBAAkB;AACvB,SAAK,uBAAuB;AAC5B,SAAK,gBAAgB;AACrB,SAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe,SAAiB,SAA2B;AACjE,QAAI,CAAC,KAAK,WAAY,QAAO,EAAE,GAAG,GAAG,GAAG,EAAA;AAExC,UAAM,WAAqB;AAAA,MACzB,GAAG,UAAU,KAAK,WAAW;AAAA,MAC7B,GAAG,UAAU,KAAK,WAAW;AAAA,IAAA;AAG/B,WAAO,KAAK,eAAe,QAAQ;AAAA,EACrC;AAAA,EAEQ,eAAe,OAA2B;AAChD,UAAM,EAAE,eAAe,GAAG,QAAQ,EAAA,IAAM,KAAK;AAE7C,UAAM,MAAO,eAAe,KAAK,KAAM;AACvC,UAAM,MAAM,KAAK,IAAI,GAAG;AACxB,UAAM,MAAM,KAAK,IAAI,GAAG;AAExB,UAAM,UAAU,MAAM,IAAI;AAC1B,UAAM,UAAU,MAAM,IAAI;AAE1B,WAAO;AAAA,MACL,GAAG,MAAM,UAAU,MAAM;AAAA,MACzB,GAAG,CAAC,MAAM,UAAU,MAAM;AAAA,IAAA;AAAA,EAE9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,oBAAoB,SAAiB,SAA2B;AACtE,UAAM,YAAY,KAAK,eAAe,SAAS,OAAO;AACtD,UAAM,EAAE,qBAAqB,EAAA,IAAM,KAAK;AACxC,QAAI,uBAAuB,EAAG,QAAO;AAErC,UAAM,MAAO,qBAAqB,KAAK,KAAM;AAC7C,UAAM,MAAM,KAAK,IAAI,GAAG;AACxB,UAAM,MAAM,KAAK,IAAI,GAAG;AACxB,WAAO;AAAA,MACL,GAAG,MAAM,UAAU,IAAI,MAAM,UAAU;AAAA,MACvC,GAAG,CAAC,MAAM,UAAU,IAAI,MAAM,UAAU;AAAA,IAAA;AAAA,EAE5C;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAW,GAAuB;;AACxC,UAAM,QAAO,UAAK,OAAO,gBAAZ,mBAAyB;AACtC,QAAI,CAAC,KAAM,QAAO;AAElB,UAAM,EAAE,qBAAqB,EAAA,IAAM,KAAK;AACxC,QAAI,uBAAuB,GAAG;AAC5B,aAAO;AAAA,QACL,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC;AAAA,QACxC,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,MAAA;AAAA,IAE7C;AAIA,UAAM,SAAS,KAAK,yBAClB,KAAK,OAAO,kBAAkB;AAAA,MAC5B,GAAG,KAAK,OAAO,QAAQ,OAAO,IAAI,KAAK,OAAO,QAAQ,KAAK,QAAQ;AAAA,MACnE,GAAG,KAAK,OAAO,QAAQ,OAAO,IAAI,KAAK,OAAO,QAAQ,KAAK,SAAS;AAAA,IAAA;AAExE,UAAM,SAAS,kBAAkB,GAAG,QAAQ,kBAAkB;AAE9D,UAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,GAAG,KAAK,KAAK,CAAC;AAC3D,UAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,GAAG,KAAK,MAAM,CAAC;AAE5D,QAAI,aAAa,OAAO,KAAK,aAAa,OAAO,EAAG,QAAO;AAE3D,WAAO,kBAAkB,EAAE,GAAG,UAAU,GAAG,SAAA,GAAY,QAAQ,CAAC,kBAAkB;AAAA,EACpF;AAAA,EAEQ,wBAAwB,SAAiB,SAA6B;AAC5E,QAAI,KAAK,sBAAsB,KAAM,QAAO,KAAK;AAEjD,UAAM,QAAQ,KAAK,oBAAoB,SAAS,OAAO;AACvD,UAAM,cAAc,CAAC,GAAG,KAAK,aAAa;AAC1C,UAAM,gBAAgB,YAAY,KAAK,iBAAiB;AAExD,UAAM,QAAQ;AAAA,MACZ,GAAG,cAAc,IAAI,MAAM;AAAA,MAC3B,GAAG,cAAc,IAAI,MAAM;AAAA,IAAA;AAE7B,gBAAY,KAAK,iBAAiB,IAAI,KAAK,WAAW,KAAK;AAE3D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMQ,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,MAAA;AAAA,MAExC,MAAM;AAAA,QACJ,OAAO,KAAK,aAAa,KAAK;AAAA,QAC9B,QAAQ,KAAK,aAAa,KAAK;AAAA,MAAA;AAAA,IACjC;AAMF,UAAM,EAAE,qBAAqB,GAAG,YAAA,IAAgB,KAAK;AACrD,UAAM,OAAO,2CAAa;AAC1B,QAAI,uBAAuB,KAAK,MAAM;AACpC,UAAI;AACJ,UAAI;AACJ,UAAI;AACJ,UAAI;AAEJ,UAAI,KAAK,sBAAsB;AAC7B,gBAAQ,KAAK,qBAAqB,KAAK;AACvC,gBAAQ,KAAK,qBAAqB,KAAK;AACvC,kBAAU,KAAK,qBAAqB,OAAO,IAAI,KAAK,aAAa,OAAO;AACxE,kBAAU,KAAK,qBAAqB,OAAO,IAAI,KAAK,aAAa,OAAO;AAAA,MAC1E,OAAO;AACL,cAAM,MAAM,KAAK,IAAK,qBAAqB,KAAK,KAAM,GAAG;AACzD,cAAM,MAAM,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC;AAClC,cAAM,MAAM,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC;AAClC,cAAM,IAAI,SAAS,KAAK;AACxB,cAAM,IAAI,SAAS,KAAK;AACxB,gBAAQ,IAAI,MAAM,IAAI;AACtB,gBAAQ,IAAI,MAAM,IAAI;AACtB,mBAAW,IAAI,SAAS;AACxB,mBAAW,IAAI,SAAS;AAAA,MAC1B;AAEA,UAAI,EAAE,GAAG,EAAA,IAAM,SAAS;AACxB,UAAI,KAAK,IAAI,CAAC,SAAS,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,OAAO,CAAC;AAChE,UAAI,KAAK,IAAI,CAAC,SAAS,KAAK,IAAI,GAAG,KAAK,SAAS,QAAQ,OAAO,CAAC;AAEjE,aAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,MAAM,SAAS,KAAA;AAAA,IAC5C;AAEA,WAAO,iBAAiB,UAAU,aAAa,KAAK,OAAO,uBAAuB,KAAK;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,wBAAwB,SAAiB,SAAyB;AACxE,QAAI,CAAC,KAAK,aAAc,QAAO,KAAK;AAEpC,UAAM,KAAK,UAAU,KAAK,aAAa;AACvC,UAAM,KAAK,UAAU,KAAK,aAAa;AAIvC,UAAM,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACxC,QAAI,OAAO,GAAI,QAAO,KAAK;AAK3B,UAAM,iBAAiB,KAAK,OAAO,gBAAgB,KAAK;AACxD,UAAM,WAAW,KAAK,MAAM,IAAI,EAAE,KAAK,MAAM,KAAK,MAAM,KAAK;AAE7D,WAAO,eAAe,KAAK,MAAM,QAAQ,CAAC;AAAA,EAC5C;AAAA,EAEQ,sBAAsB,OAI5B;AACA,UAAM,aAAa,KAAK,OAAO,sBAAsB,CAAC,GAAG,IAAI,KAAK,GAAG;AACrE,UAAM,YAAY,KAAK,OAAO,yBAAyB;AACvD,UAAM,kBAAkB,eAAe,KAAK;AAE5C,eAAW,aAAa,YAAY;AAClC,YAAM,sBAAsB,eAAe,SAAS;AACpD,YAAM,OAAO,KAAK,IAAI,kBAAkB,mBAAmB;AAC3D,YAAM,cAAc,KAAK,IAAI,MAAM,MAAM,IAAI;AAC7C,UAAI,eAAe,WAAW;AAC5B,eAAO;AAAA,UACL,OAAO;AAAA,UACP,WAAW;AAAA,UACX,YAAY;AAAA,QAAA;AAAA,MAEhB;AAAA,IACF;AAEA,WAAO,EAAE,OAAO,iBAAiB,WAAW,MAAA;AAAA,EAC9C;AACF;SC5mBgB,cAAc,YAAwC;AAE9D,QAAA,yBAA2B;AACzB,UAAA,OAAO,WAAA;YACL,UAAAA,WAAU,SAAAC,UAAAA,GAAY,SAAS;WAChC;AAAA,EACT,CAAC;AAEK,QAAA,UAAA,EAAA,QAAA,MAAmB,WAAA,EAAa,WAAW,IAAI;QAC/C,WAAA,EAAA,QAAA,MAAoB,WAAA,EAAa,QAAQ;MAE3C,aAAa,EAAA,MAAoC,IAAI;AAGzD,IAAA,kBAAc;AACP,QAAA,CAAA,EAAA,IAAA,UAAA,GAAY;YACf,YAAA,IAAiB,qBAAA,EAAA,IAAqB,MAAA,IAAS,UAAA;;AAAA,uBAAA,IAAU,QAAA,MAAV,mBAAqB;AAAA,OAAK,GAAA,IAAA;AAAA,IAC3E,OAAO;YACL,UAAA,EAAW,mBAAa,MAAM,CAAA;AAAA,IAChC;AAAA,EACF,CAAC;QAEK,kBAAA,CAAmB,MAAoB;;eACtC,OAAA,EAAA;AACL,MAAE,eAAA;AACF,MAAE,gBAAA;gBACF,UAAA,yBAAY,UAAU,EAAE,SAAS,EAAE;AAClC,MAAE,cAA8B,kBAAkB,EAAE,SAAS;AAAA,EAChE;QAEM,aAAA,CAAc,MAAoB;;AACtC,MAAE,eAAA;AACF,MAAE,gBAAA;AACF,YAAA,IAAA,UAAA,MAAA,mBAAY,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE;AAAA,EAC3C;QAEM,YAAA,CAAa,MAAoB;;AACrC,MAAE,eAAA;AACF,MAAE,gBAAA;AACF,YAAA,IAAA,UAAA,MAAA,mBAAY;AACX,kBAAE,eAA8B,0BAAhC,4BAAwD,EAAE;AAAA,EAC7D;AAEM,QAAA,uBAAuB,YAAA;AAAA,IAC3B,eAAA,CAAgB,MAAoB;;iBAC7B,OAAA,EAAA;AACL,QAAE,eAAA;AACF,QAAE,gBAAA;kBACF,UAAA,yBAAY,YAAY,QAAQ,EAAE,SAAS,EAAE;AAC5C,QAAE,cAA8B,kBAAkB,EAAE,SAAS;AAAA,IAChE;AAAA,IACA,eAAe;AAAA,IACf,aAAa;AAAA,IACb,iBAAiB;AAAA;AAGb,QAAA,uBAAuB,iBAAA;AAAA,IAC3B,eAAA,CAAgB,MAAoB;;iBAC7B,OAAA,EAAA;AACL,QAAE,eAAA;AACF,QAAE,gBAAA;kBACF,UAAA,yBAAY,gBAAgB,aAAa,EAAE,SAAS,EAAE;AACrD,QAAE,cAA8B,kBAAkB,EAAE,SAAS;AAAA,IAChE;AAAA,IACA,eAAe;AAAA,IACf,aAAa;AAAA,IACb,iBAAiB;AAAA;AAGb,QAAA,wBAAA,CACJ,kBAA0B,GAC1B,mBAAA;AAAA,IAEA,eAAA,CAAgB,MAAoB;;iBAC7B,OAAA,EAAA;AACL,QAAE,eAAA;AACF,QAAE,gBAAA;AAKI,YAAA,aAAc,EAAE,cAA8B,sBAAA;YAC9C,gBAAgB,WAAW,OAAO,WAAW,QAAQ;YACrD,gBAAgB,WAAW,MAAM,WAAW,SAAS;kBAC3D,UAAA,yBAAY,cAAc,eAAe,eAAe,iBAAiB;AACxE,QAAE,cAA8B,kBAAkB,EAAE,SAAS;AAAA,IAChE;AAAA,IACA,eAAe;AAAA,IACf,aAAa;AAAA,IACb,iBAAiB;AAAA;AAGb,QAAA,kCACJ,OAAA;IAEM,eAAe;AAAA,IACf,eAAe;AAAA,IACf,aAAa;AAAA,IACb,iBAAiB;AAAA;;IAMnB,IAAA,YAAY;mBACP,SAAA;AAAA,IACT;AAAA,IACA,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,IACnB,qBAAqB;AAAA;AAEzB;ACtGO,SAAS,eAAe,OAAgD;AAC7E,SAAO,OAAO,QAAQ,KAAK,EACxB,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AACrB,UAAM,SAAS,IAAI,QAAQ,UAAU,CAAC,MAAM,IAAI,EAAE,YAAA,CAAa,EAAE;AACjE,WAAO,GAAG,MAAM,KAAK,KAAK;AAAA,EAC5B,CAAC,EACA,KAAK,IAAI;AACd;SCNgB,sBACd,SAeA;QAEM,aAAA,EAAA,QAAA,MAAsB,QAAA,EAAU,UAAU;QAC1C,WAAA,EAAA,QAAA,MAAoB,QAAA,EAAU,QAAQ;QACtC,WAAA,EAAA,QAAA,MAAoB,QAAA,EAAU,QAAQ;QACtC,aAAA,EAAA,QAAA,MAAsB,QAAA,EAAU,UAAU;AAC1C,QAAA,kBAAA,EAAA,QAAA,MAA2B,QAAA,EAAU,mBAAmB,KAAK;AAC7D,QAAA,kBAAA,EAAA,QAAA,MAA2B,QAAA,EAAU,mBAAmB,KAAK;AAC7D,QAAA,kBAAA,EAAA,QAAA,MAA2B,QAAA,EAAU,mBAAmB,CAAC;QACzD,cAAA,EAAA,QAAA,MAAuB,QAAA,EAAU,WAAW;QAC5C,cAAA,EAAA,QAAA,MAAuB,QAAA,EAAU,WAAW;QAC5C,gBAAA,EAAA,QAAA,MAAyB,QAAA,EAAU,aAAa;QAEhD,aAAa,cAAA,MAAA,EAAA,IAAoB,UAAU,CAAA;AAG3C,QAAA,yBAAiD;AAC/C,UAAA,OAAO,yBAAA,EAAA,IAAyB,UAAA,SAAY,QAAQ,CAAA;WACnD,KAAK,IAAA,CAAK,MAAA;;AAAA;AAAA,QACf,MAAK,OAAE,UAAF,mBAAU;AAAA,QACf,OAAO,eAAe,EAAE,KAAK;AAAA,QAC1B,GAAA,WAAW,kBAAkB,EAAE,MAAM;AAAA,QACpC,GAAA,EAAE,SAAA,CAAA;AAAA,wBACF,WAAA,yBAAc,EAAE,YAAM,CAAA;AAAA;;EAE9B,CAAC;AAGK,QAAA,2BAAmD;eAClD,eAAA,EAAA,QAAA,CAAA;UACC,OAAO,2BAAA,EAAA,IAA2B,UAAA,SAAY,QAAA,GAAA,EAAA,IAAU,YAAW,QAAQ;AAC1E,WAAA,KAAK,IAAA,CAAK,GAAG,MAAA;;AAAA;AAAA,QAClB,KAAK;AAAA,QACL,OAAO,eAAe,EAAE,KAAK;AAAA,WAC1B,WAAW,kBAAkB,CAAC;AAAA,QAC7B,GAAA,EAAE,SAAA,CAAA;AAAA,QACF,KAAA,OAAA,IAAA,WAAA,MAAA,mBAAc,OAAC,CAAA;AAAA;;EAEvB,CAAC;AAGK,QAAA,2BAAgE;;AAC/D,QAAA,CAAA,EAAA,IAAA,yBAAwB;AACvB,UAAA,OAAO,2BAAA,EAAA,IAA2B,UAAA,GAAA,EAAA,IAAY,UAAA,SAAY,eAAe,CAAA;;MAE7E,QAAA;AAAA,QACE,OAAO,eAAe,KAAK,WAAW;AAAA,QACnC,GAAA,WAAW,oBAAA,EAAA,IAAoB,eAAA,GAAiB,KAAK,MAAM;AAAA,QAC1D,GAAA,KAAK,SAAA,CAAA;AAAA,wBACL,aAAA,+BAAA,CAAA;AAAA;MAEN,WAAA;AAAA,QACE,OAAO,eAAe,KAAK,cAAc;AAAA,QACzC,gCAAgC;AAAA;;EAGtC,CAAC;;IAIK,IAAA,YAAY;AACP,aAAA,WAAW;AAAA,IACpB;AAAA,IACI,IAAA,SAAS;mBACJ,MAAA;AAAA,IACT;AAAA,IACI,IAAA,WAAW;mBACN,QAAA;AAAA,IACT;AAAA,IACI,IAAA,WAAW;mBACN,QAAA;AAAA,IACT;AAAA;AAEJ;AChHO,SAAS,YACd,MACA,UAA8B,IAC9B;AACA,MAAI,EAAE,UAAU,QAAQ,KAAK,cAAc,OAAO;AAGlD,QAAM,OAAO,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,EAAA;AAE9B,QAAM,kBAAkB,CAAC,MAAa;AACpC,UAAM,KAAK;AACX,QAAI,CAAC,SAAU;AAIf,QAAI,GAAG,gBAAgB,WAAW,GAAG,cAAc,MAAO;AAE1D,UAAM,MAAM,YAAY,IAAA;AACxB,UAAM,IAAI,GAAG;AACb,UAAM,IAAI,GAAG;AAEb,UAAM,aAAa,MAAM,KAAK,KAAK;AACnC,UAAM,KAAK,IAAI,KAAK;AACpB,UAAM,KAAK,IAAI,KAAK;AACpB,UAAM,aAAa,KAAK,KAAK,KAAK,MAAM,cAAc;AAEtD,QAAI,cAAc,WAAY,sCAAW;AAEzC,SAAK,IAAI;AACT,SAAK,IAAI;AACT,SAAK,IAAI;AAAA,EACX;AAEA,QAAM,iBAAiB,CAAC,MAAa;AACnC,yCAAW;AAAA,EACb;AAEA,OAAK,iBAAiB,aAAa,iBAAiB,EAAE,SAAS,MAAM;AACrE,OAAK,iBAAiB,YAAY,cAAc;AAEhD,SAAO;AAAA,IACL,OAAO,MAA2B;AAChC,UAAI,CAAC,KAAM;AACX,iBAAW,KAAK;AAEhB,cAAQ,KAAK,SAAS;AACtB,oBAAc,KAAK,eAAe;AAAA,IACpC;AAAA,IACA,UAAU;AACR,WAAK,oBAAoB,aAAa,iBAAiB,EAAE,SAAS,MAAa;AAC/E,WAAK,oBAAoB,YAAY,cAAc;AAAA,IACrD;AAAA,EAAA;AAEJ;mDC3DA;;AAuBQ,QAAA,kCAA2B,mBAAkB,QAAA,MAAA,QAAA,QAAA,CAAA;QAI7C,oBAAsC,CAAI,SAAS;UACjD,oBAAiB,CAAI,MAAa;AAEtC,QAAE,gBAAe;AAAA,IAInB;UAEM,mBAAgB,CAAI,MAAa;AAErC,QAAE,gBAAe;AAAA,IAEnB;AAGA,SAAK,iBAAiB,eAAe,mBAAiB,EAAI,SAAS,MAAI;AACvE,SAAK,iBAAiB,cAAc,kBAAgB,EAAI,SAAS,MAAI;;MAGnE,UAAU;AACR,aAAK,oBAAoB,eAAe,mBAAiB,EAAI,SAAS,MAAI;AAC1E,aAAK,oBAAoB,cAAc,kBAAgB,EAAI,SAAS,MAAI;AAAA,MAC1E;AAAA;EAEJ;AAEM,QAAA,6EAEY,OAAO,CAAC,YAAA,QAAA,KACT,OAAO,CAAC,kBAAA,EAAA,IACP,eAAe,EAAC,MAAM,yCAE1B,eAAe,EAAC,KAAK,eAAA,EAAA,IACpB,eAAe,EAAC,MAAM,sCAAA;AAK/B,QAAA,sCACJ,OAAK,EAAA,IAAE,gBAAgB,GACvB,QAAQ,kBAAiB,EAAA;;;;;;;;QAMzB,wBAAA,gBAAgB;AAAA,QAChB,QAAM,EAAA,IAAE,eAAe,EAAC;AAAA,QACxB,MAAI;AAAA,UACF,QAAM,EAAI,GAAC,QAAA,KAAO,OAAO,GAAG,GAAC,QAAA,KAAO,OAAO,EAAC;AAAA,UAC5C,MAAI;AAAA,YAAI,OAAK,EAAA,IAAE,eAAe,EAAC;AAAA,YAAO,QAAM,EAAA,IAAE,eAAe,EAAC;AAAA;;;;;;;;;;;AAR5D;AC9DD,SAAS,UAAyC,WAAiB;AACxE,QAAM,iBAAiB,CAAC,UAAoB;AAE1C,QAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,aAAO;AAAA,IACT;AAGA,QAAI,OAAO,UAAU,UAAU;AAC7B,aAAO;AAAA,IACT;AAGA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,aAAO,MAAM,IAAI,CAAC,SAAS,eAAe,IAAI,CAAC;AAAA,IACjD;AAGA,QAAI,iBAAiB,MAAM;AACzB,aAAO,IAAI,KAAK,MAAM,SAAS;AAAA,IACjC;AAGA,QAAI,iBAAiB,QAAQ;AAC3B,aAAO,IAAI,OAAO,MAAM,QAAQ,MAAM,KAAK;AAAA,IAC7C;AAIA,QAAI,OAAO,UAAU,SAAS,KAAK,KAAK,MAAM,mBAAmB;AAC/D,aAAO,OAAO,KAAK,KAAK,EAAE,OAAO,CAAC,KAAK,QAAQ;AAE7C,cAAM,QAAQ,MAAM,GAAG;AACvB,YAAI,OAAO,UAAU,YAAY;AAC/B,cAAI,GAAuB,IAAI,eAAe,KAAK;AAAA,QACrD;AACA,eAAO;AAAA,MACT,GAAG,CAAA,CAAO;AAAA,IACZ;AAIA,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AAAA,IACzC,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,eAAe,SAAS;AACjC;"}
@@ -3,10 +3,13 @@ import { DragResizeConfig, InteractionEvent, ResizeHandle } from '../../shared-v
3
3
  import { MaybeRef } from '../utils/interaction-normalize';
4
4
  export interface UseDragResizeOptions {
5
5
  element: MaybeRef<Rect>;
6
+ rotationCenter?: MaybeRef<Position | undefined>;
7
+ rotationElement?: MaybeRef<Rect | undefined>;
6
8
  vertices?: MaybeRef<Position[]>;
7
9
  constraints?: MaybeRef<DragResizeConfig['constraints']>;
8
10
  maintainAspectRatio?: MaybeRef<boolean>;
9
11
  pageRotation?: MaybeRef<number>;
12
+ annotationRotation?: MaybeRef<number>;
10
13
  scale?: MaybeRef<number>;
11
14
  onUpdate?: (event: InteractionEvent) => void;
12
15
  enabled?: MaybeRef<boolean>;
@@ -35,4 +38,10 @@ export declare function useDragResize(options: UseDragResizeOptions): {
35
38
  onPointerup: (e: PointerEvent) => void;
36
39
  onPointercancel: (e: PointerEvent) => void;
37
40
  };
41
+ createRotationProps: (initialRotation?: number, orbitRadiusPx?: number) => {
42
+ onPointerdown: (e: PointerEvent) => void;
43
+ onPointermove: (e: PointerEvent) => void | undefined;
44
+ onPointerup: (e: PointerEvent) => void;
45
+ onPointercancel: (e: PointerEvent) => void;
46
+ };
38
47
  };
@@ -1,21 +1,35 @@
1
1
  import { CSSProperties } from 'vue';
2
2
  import { UseDragResizeOptions } from './use-drag-resize';
3
- import { ResizeUI, VertexUI } from '../../shared-vue/plugin-interaction-primitives/utils';
3
+ import { ResizeUI, VertexUI, RotationUI } from '../../shared-vue/plugin-interaction-primitives/utils';
4
+ import { MaybeRef } from '../utils/interaction-normalize';
4
5
  export type HandleElementProps = {
5
- key: string | number;
6
+ key?: string | number;
6
7
  style: CSSProperties;
7
8
  onPointerdown: (e: PointerEvent) => void;
8
9
  onPointermove: (e: PointerEvent) => void;
9
10
  onPointerup: (e: PointerEvent) => void;
10
11
  onPointercancel: (e: PointerEvent) => void;
11
12
  } & Record<string, any>;
13
+ export type RotationHandleProps = {
14
+ /** Props for the rotation handle element */
15
+ handle: HandleElementProps;
16
+ /** Props for the connector line element (if shown) */
17
+ connector: {
18
+ style: CSSProperties;
19
+ } & Record<string, any>;
20
+ };
12
21
  export interface UseInteractionHandlesOptions {
13
22
  controller: UseDragResizeOptions;
14
23
  resizeUI?: ResizeUI;
15
24
  vertexUI?: VertexUI;
25
+ rotationUI?: RotationUI;
16
26
  includeVertices?: boolean;
27
+ includeRotation?: MaybeRef<boolean>;
28
+ /** Current rotation angle of the annotation (for initializing rotation interaction) */
29
+ currentRotation?: MaybeRef<number>;
17
30
  handleAttrs?: (h: 'nw' | 'ne' | 'sw' | 'se' | 'n' | 'e' | 's' | 'w') => Record<string, any> | void;
18
31
  vertexAttrs?: (i: number) => Record<string, any> | void;
32
+ rotationAttrs?: () => Record<string, any> | void;
19
33
  }
20
34
  export declare function useInteractionHandles(opts: UseInteractionHandlesOptions): {
21
35
  dragProps: import('vue').ComputedRef<{
@@ -31,4 +45,5 @@ export declare function useInteractionHandles(opts: UseInteractionHandlesOptions
31
45
  }>;
32
46
  resize: import('vue').ComputedRef<HandleElementProps[]>;
33
47
  vertices: import('vue').ComputedRef<HandleElementProps[]>;
48
+ rotation: import('vue').ComputedRef<RotationHandleProps | null>;
34
49
  };
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("vue"),e=require("@embedpdf/utils"),i=t.defineComponent({__name:"counter-rotate-container",props:{rect:{},rotation:{}},setup(i){const n=i,s=t.computed(()=>e.getCounterRotation(n.rect,n.rotation)),a=t.computed(()=>({style:{position:"absolute",left:`${n.rect.origin.x}px`,top:`${n.rect.origin.y}px`,transform:s.value.matrix,transformOrigin:"0 0",width:`${s.value.width}px`,height:`${s.value.height}px`,pointerEvents:"none",zIndex:3},onPointerdown:t=>{t.stopPropagation(),t.preventDefault()},onTouchstart:t=>{t.stopPropagation(),t.preventDefault()}})),r=t.computed(()=>({origin:{x:n.rect.origin.x,y:n.rect.origin.y},size:{width:s.value.width,height:s.value.height}}));return(e,i)=>t.renderSlot(e.$slots,"default",{menuWrapperProps:a.value,matrix:s.value.matrix,rect:r.value})}});class n{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),a=Math.sin(n),r=t.x/i,o=t.y/i;return{x:s*r+a*o,y:-a*r+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],a={x:s.x+i.x,y:s.y+i.y};return n[this.activeVertexIndex]=this.clampPoint(a),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){if(!this.startElement)return this.config.element;const i=function(t){return{x:t.includes("e")?"left":t.includes("w")?"right":"center",y:t.includes("s")?"top":t.includes("n")?"bottom":"center"}}(e),n=this.startElement.size.width/this.startElement.size.height||1;let s=this.applyResizeDelta(t,i);return this.config.maintainAspectRatio&&(s=this.enforceAspectRatio(s,i,n)),s=this.clampToBounds(s,i,n),this.applyConstraints(s)}applyResizeDelta(t,e){const i=this.startElement;let n=i.origin.x,s=i.origin.y,a=i.size.width,r=i.size.height;return"left"===e.x?a+=t.x:"right"===e.x&&(n+=t.x,a-=t.x),"top"===e.y?r+=t.y:"bottom"===e.y&&(s+=t.y,r-=t.y),{origin:{x:n,y:s},size:{width:a,height:r}}}enforceAspectRatio(t,e,i){const n=this.startElement;let{x:s,y:a}=t.origin,{width:r,height:o}=t.size;if("center"===e.x||"center"===e.y)"center"===e.y?(o=r/i,a=n.origin.y+(n.size.height-o)/2):(r=o*i,s=n.origin.x+(n.size.width-r)/2);else{Math.abs(r-n.size.width)>=Math.abs(o-n.size.height)?o=r/i:r=o*i}return"right"===e.x&&(s=n.origin.x+n.size.width-r),"bottom"===e.y&&(a=n.origin.y+n.size.height-o),{origin:{x:s,y:a},size:{width:r,height:o}}}clampToBounds(t,e,i){var n;const s=null==(n=this.config.constraints)?void 0:n.boundingBox;if(!s)return t;const a=this.startElement;let{x:r,y:o}=t.origin,{width:l,height:c}=t.size;l=Math.max(1,l),c=Math.max(1,c);const h="left"===e.x?a.origin.x:a.origin.x+a.size.width,d="top"===e.y?a.origin.y:a.origin.y+a.size.height,u="left"===e.x?s.width-h:"right"===e.x?h:2*Math.min(a.origin.x,s.width-a.origin.x-a.size.width)+a.size.width,p="top"===e.y?s.height-d:"bottom"===e.y?d:2*Math.min(a.origin.y,s.height-a.origin.y-a.size.height)+a.size.height;if(this.config.maintainAspectRatio){const t=l>u?u/l:1,e=c>p?p/c:1,i=Math.min(t,e);i<1&&(l*=i,c*=i)}else l=Math.min(l,u),c=Math.min(c,p);return r="left"===e.x?h:"right"===e.x?h-l:a.origin.x+(a.size.width-l)/2,o="top"===e.y?d:"bottom"===e.y?d-c:a.origin.y+(a.size.height-c)/2,r=Math.max(0,Math.min(r,s.width-l)),o=Math.max(0,Math.min(o,s.height-c)),{origin:{x:r,y:o},size:{width:l,height:c}}}applyConstraints(t){const{constraints:e}=this.config;if(!e)return t;let{origin:{x:i,y:n},size:{width:s,height:a}}=t;const r=e.minWidth??1,o=e.minHeight??1,l=e.maxWidth,c=e.maxHeight;if(this.config.maintainAspectRatio&&s>0&&a>0){const t=s/a;s<r&&(s=r,a=s/t),a<o&&(a=o,s=a*t),void 0!==l&&s>l&&(s=l,a=s/t),void 0!==c&&a>c&&(a=c,s=a*t)}else s=Math.max(r,s),a=Math.max(o,a),void 0!==l&&(s=Math.min(l,s)),void 0!==c&&(a=Math.min(c,a));return e.boundingBox&&(i=Math.max(0,Math.min(i,e.boundingBox.width-s)),n=Math.max(0,Math.min(n,e.boundingBox.height-a))),{origin:{x:i,y:n},size:{width:s,height:a}}}}function s(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 a(t,e,i){const n=-t/2;return"center"===i?n:"outside"===i?n-e:n+e}const r=e=>t.toRaw(t.isRef(e)?t.unref(e):e),o=(t,e=0)=>{const i=Number(t);return Number.isFinite(i)?i:e},l=t=>{var e,i,n,s;return{origin:{x:o(null==(e=null==t?void 0:t.origin)?void 0:e.x),y:o(null==(i=null==t?void 0:t.origin)?void 0:i.y)},size:{width:o(null==(n=null==t?void 0:t.size)?void 0:n.width),height:o(null==(s=null==t?void 0:t.size)?void 0:s.height)}}},c=(t=[])=>t.map(t=>({x:o(null==t?void 0:t.x),y:o(null==t?void 0:t.y)})),h=t=>void 0===t?void 0:Boolean(t),d=t=>void 0===t?void 0:o(t),u=t=>t?r(t):void 0;function p(e){const i=t.ref(null),{onUpdate:s,element:a,vertices:o,constraints:p,maintainAspectRatio:g,pageRotation:v,scale:m,enabled:x}=e,f={element:l(r(a)),vertices:o?c(r(o)):void 0,constraints:u(p),maintainAspectRatio:h(void 0===x?void 0:r(g)),pageRotation:d(void 0===v?void 0:r(v)),scale:d(void 0===m?void 0:r(m))};i.value||(i.value=t.markRaw(new n(f,t=>null==s?void 0:s(t)))),t.watch(()=>({element:a,vertices:o,constraints:p,maintainAspectRatio:g,pageRotation:v,scale:m}),t=>{var e;null==(e=i.value)||e.updateConfig({element:l(r(t.element)),vertices:t.vertices?c(r(t.vertices)):void 0,constraints:u(t.constraints),maintainAspectRatio:h(void 0===t.maintainAspectRatio?void 0:r(t.maintainAspectRatio)),pageRotation:d(void 0===t.pageRotation?void 0:r(t.pageRotation)),scale:d(void 0===t.scale?void 0:r(t.scale))})},{deep:!0}),t.onUnmounted(()=>{i.value=null});const y=()=>Boolean(void 0===x||r(x)),z=t=>{var e,n,s;y()&&(t.preventDefault(),t.stopPropagation(),null==(e=i.value)||e.startDrag(t.clientX,t.clientY),null==(s=(n=t.currentTarget).setPointerCapture)||s.call(n,t.pointerId))},P=t=>{var e;return null==(e=i.value)?void 0:e.move(t.clientX,t.clientY)},w=t=>{var e,n,s;null==(e=i.value)||e.end(),null==(s=(n=t.currentTarget).releasePointerCapture)||s.call(n,t.pointerId)},R=t=>{var e,n,s;null==(e=i.value)||e.cancel(),null==(s=(n=t.currentTarget).releasePointerCapture)||s.call(n,t.pointerId)};return{dragProps:t.computed(()=>y()?{onPointerdown:z,onPointermove:P,onPointerup:w,onPointercancel:R}:{}),createResizeProps:t=>({onPointerdown:e=>{var n,s,a;y()&&(e.preventDefault(),e.stopPropagation(),null==(n=i.value)||n.startResize(t,e.clientX,e.clientY),null==(a=(s=e.currentTarget).setPointerCapture)||a.call(s,e.pointerId))},onPointermove:P,onPointerup:w,onPointercancel:R}),createVertexProps:t=>({onPointerdown:e=>{var n,s,a;y()&&(e.preventDefault(),e.stopPropagation(),null==(n=i.value)||n.startVertexEdit(t,e.clientX,e.clientY),null==(a=(s=e.currentTarget).setPointerCapture)||a.call(s,e.pointerId))},onPointermove:P,onPointerup:w,onPointercancel:R})}}exports.CounterRotate=i,exports.deepToRaw=function(e){const i=e=>Array.isArray(e)?e.map(t=>i(t)):t.isRef(e)||t.isReactive(e)||t.isProxy(e)?i(t.toRaw(e)):e&&"object"==typeof e?Object.keys(e).reduce((t,n)=>(t[n]=i(e[n]),t),{}):e;return i(e)},exports.useDoublePressProps=function(e,{delay:i=300,tolerancePx:n=18}={}){const s=t.ref({t:0,x:0,y:0});return e?{onDblclick:t=>{null==e||e(t)},onPointerupCapture:t=>{if(!e)return;if("mouse"===t.pointerType||!1===t.isPrimary)return;const a=performance.now(),r=t.clientX,o=t.clientY,l=a-s.value.t<=i,c=r-s.value.x,h=o-s.value.y;l&&c*c+h*h<=n*n&&(null==e||e(t)),s.value={t:a,x:r,y:o}}}:{}},exports.useDragResize=p,exports.useInteractionHandles=function(e){const{controller:i,resizeUI:n,vertexUI:o,includeVertices:h=!1,handleAttrs:d,vertexAttrs:u}=e,{dragProps:g,createResizeProps:v,createVertexProps:m}=p(i),x=t.computed(()=>l(r(i.element))),f=t.computed(()=>i.vertices?c(r(i.vertices)):void 0),y=t.computed(()=>Number(r(i.scale??1))),z=t.computed(()=>Number(r(i.pageRotation??0))),P=t.computed(()=>void 0===i.maintainAspectRatio?void 0:Boolean(r(i.maintainAspectRatio))),w=t.computed(()=>r(i.constraints??void 0));return{dragProps:g,resize:t.computed(()=>function(t,e={}){const{handleSize:i=8,spacing:n=1,offsetMode:r="outside",includeSides:o=!1,zIndex:l=3,rotationAwareCursor:c=!0}=e,h=(t.pageRotation??0)%4,d=t=>({[t]:a(i,n,r)+"px"});return[["nw",{...d("top"),...d("left")}],["ne",{...d("top"),...d("right")}],["sw",{...d("bottom"),...d("left")}],["se",{...d("bottom"),...d("right")}],...o?[["n",{...d("top"),left:`calc(50% - ${i/2}px)`}],["s",{...d("bottom"),left:`calc(50% - ${i/2}px)`}],["w",{...d("left"),top:`calc(50% - ${i/2}px)`}],["e",{...d("right"),top:`calc(50% - ${i/2}px)`}]]:[]].map(([t,e])=>({handle:t,style:{position:"absolute",width:i+"px",height:i+"px",borderRadius:"50%",zIndex:l,cursor:c?s(t,h):"default",touchAction:"none",...e},attrs:{"data-epdf-handle":t}}))}({element:x.value,scale:y.value,pageRotation:z.value,maintainAspectRatio:P.value,constraints:w.value},n).map(t=>{var e;return{key:(null==(e=t.attrs)?void 0:e["data-epdf-handle"])??t.handle,style:t.style,...v(t.handle),...t.attrs??{},...(null==d?void 0:d(t.handle))??{}}})),vertices:t.computed(()=>{if(!h)return[];const t=f.value??[];return function(t,e={},i){const{vertexSize:n=12,zIndex:s=4}=e,a=t.element,r=t.scale??1;return(i??t.vertices??[]).map((t,e)=>({handle:"nw",style:{position:"absolute",left:(t.x-a.origin.x)*r-n/2+"px",top:(t.y-a.origin.y)*r-n/2+"px",width:n+"px",height:n+"px",borderRadius:"50%",cursor:"pointer",zIndex:s,touchAction:"none"},attrs:{"data-epdf-vertex":e}}))}({element:x.value,scale:y.value,vertices:t},o,t).map((t,e)=>({key:e,style:t.style,...m(e),...t.attrs??{},...(null==u?void 0:u(e))??{}}))})}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("vue"),e=require("@embedpdf/utils"),i=require("@embedpdf/models"),n=t.defineComponent({__name:"counter-rotate-container",props:{rect:{},rotation:{}},setup(i){const n=i,o=t.computed(()=>e.getCounterRotation(n.rect,n.rotation)),a=t.computed(()=>({style:{position:"absolute",left:`${n.rect.origin.x}px`,top:`${n.rect.origin.y}px`,transform:o.value.matrix,transformOrigin:"0 0",width:`${o.value.width}px`,height:`${o.value.height}px`,pointerEvents:"none",zIndex:3},onPointerdown:t=>{t.stopPropagation(),t.preventDefault()},onTouchstart:t=>{t.stopPropagation(),t.preventDefault()}})),r=t.computed(()=>({origin:{x:n.rect.origin.x,y:n.rect.origin.y},size:{width:o.value.width,height:o.value.height}}));return(e,i)=>t.renderSlot(e.$slots,"default",{menuWrapperProps:a.value,matrix:o.value.matrix,rect:r.value})}}),o={n:0,ne:45,e:90,se:135,s:180,sw:225,w:270,nw:315},a=["ns-resize","nesw-resize","ew-resize","nwse-resize","ns-resize","nesw-resize","ew-resize","nwse-resize"];function r(t,e,i=0){const n=((o[t]+90*e+i)%360+360)%360,r=Math.round(n/45)%8;return a[r]}function s(t,e,i){const n=-t/2;return"center"===i?n:"outside"===i?n-e:n+e}function l(t,e,i,n=!1){if(!e)return t;let{origin:{x:o,y:a},size:{width:r,height:s}}=t;const l=e.minWidth??1,h=e.minHeight??1,c=e.maxWidth,d=e.maxHeight;if(i&&r>0&&s>0){const t=r/s;r<l&&(r=l,s=r/t),s<h&&(s=h,r=s*t),void 0!==c&&r>c&&(r=c,s=r/t),void 0!==d&&s>d&&(s=d,r=s*t)}else r=Math.max(l,r),s=Math.max(h,s),void 0!==c&&(r=Math.min(c,r)),void 0!==d&&(s=Math.min(d,s));return e.boundingBox&&!n&&(o=Math.max(0,Math.min(o,e.boundingBox.width-r)),a=Math.max(0,Math.min(a,e.boundingBox.height-s))),{origin:{x:o,y:a},size:{width:r,height:s}}}function h(t,e,n){const o=1e-6,a=i.calculateRotatedRectAABB(t,e);return a.origin.x>=-o&&a.origin.y>=-o&&a.origin.x+a.size.width<=n.width+o&&a.origin.y+a.size.height<=n.height+o}function c(t,e,n,o,a){const{startRect:r,maintainAspectRatio:s=!1,annotationRotation:h=0,constraints:c}=n,d=function(t){return{x:t.includes("e")?"left":t.includes("w")?"right":"center",y:t.includes("s")?"top":t.includes("n")?"bottom":"center"}}(e),u=r.size.width/r.size.height||1;let g=function(t,e,i){let n=t.origin.x,o=t.origin.y,a=t.size.width,r=t.size.height;return"left"===i.x?a+=e.x:"right"===i.x&&(n+=e.x,a-=e.x),"top"===i.y?r+=e.y:"bottom"===i.y&&(o+=e.y,r-=e.y),{origin:{x:n,y:o},size:{width:a,height:r}}}(r,t,d);if(s&&(g=function(t,e,i,n){let{x:o,y:a}=t.origin,{width:r,height:s}=t.size;if("center"===i.x||"center"===i.y)"center"===i.y?(s=r/n,a=e.origin.y+(e.size.height-s)/2):(r=s*n,o=e.origin.x+(e.size.width-r)/2);else{const t=Math.abs(r-e.size.width),i=Math.abs(s-e.size.height),o=t+i;if(0===o)r=e.size.width,s=e.size.height;else{const e=t/o,a=i/o,l=r/n;r=e*r+a*(s*n),s=e*l+a*s}}return"right"===i.x&&(o=e.origin.x+e.size.width-r),"bottom"===i.y&&(a=e.origin.y+e.size.height-s),{origin:{x:o,y:a},size:{width:r,height:s}}}(g,r,d,u)),o&&(g=function(t,e,i,n,o){if(!n)return t;let{x:a,y:r}=t.origin,{width:s,height:l}=t.size;s=Math.max(1,s),l=Math.max(1,l);const h="left"===i.x?e.origin.x:e.origin.x+e.size.width,c="top"===i.y?e.origin.y:e.origin.y+e.size.height,d="left"===i.x?n.width-h:"right"===i.x?h:2*Math.min(e.origin.x,n.width-e.origin.x-e.size.width)+e.size.width,u="top"===i.y?n.height-c:"bottom"===i.y?c:2*Math.min(e.origin.y,n.height-e.origin.y-e.size.height)+e.size.height;if(o){const t=s>d?d/s:1,e=l>u?u/l:1,i=Math.min(t,e);i<1&&(s*=i,l*=i)}else s=Math.min(s,d),l=Math.min(l,u);return a="left"===i.x?h:"right"===i.x?h-s:e.origin.x+(e.size.width-s)/2,r="top"===i.y?c:"bottom"===i.y?c-l:e.origin.y+(e.size.height-l)/2,a=Math.max(0,Math.min(a,n.width-s)),r=Math.max(0,Math.min(r,n.height-l)),{origin:{x:a,y:r},size:{width:s,height:l}}}(g,r,d,null==c?void 0:c.boundingBox,s)),g=l(g,c,s,a),a&&(g=function(t,e,i){let n,o;return n="left"===i.x?e.origin.x:"right"===i.x?e.origin.x+e.size.width-t.size.width:e.origin.x+(e.size.width-t.size.width)/2,o="top"===i.y?e.origin.y:"bottom"===i.y?e.origin.y+e.size.height-t.size.height:e.origin.y+(e.size.height-t.size.height)/2,{origin:{x:n,y:o},size:t.size}}(g,r,d)),0!==h){const t=function(t,e){return{x:"left"===e.x?t.origin.x:"right"===e.x?t.origin.x+t.size.width:t.origin.x+t.size.width/2,y:"top"===e.y?t.origin.y:"bottom"===e.y?t.origin.y+t.size.height:t.origin.y+t.size.height/2}}(r,d),e={x:r.origin.x+r.size.width/2,y:r.origin.y+r.size.height/2},n={x:g.origin.x+g.size.width/2,y:g.origin.y+g.size.height/2},o=i.rotatePointAround(t,e,h),a=i.rotatePointAround(t,n,h);g={origin:{x:g.origin.x+(o.x-a.x),y:g.origin.y+(o.y-a.y)},size:g.size}}return g}class d{constructor(t,e){this.config=t,this.onUpdate=e,this.state="idle",this.startPoint=null,this.startElement=null,this.startRotationElement=null,this.gestureRotationCenter=null,this.activeHandle=null,this.currentPosition=null,this.activeVertexIndex=null,this.startVertices=[],this.currentVertices=[],this.rotationCenter=null,this.centerScreen=null,this.initialRotation=0,this.lastComputedRotation=0,this.rotationDelta=0,this.rotationSnappedAngle=null,this.currentVertices=t.vertices||[]}updateConfig(t){this.config={...this.config,...t},"vertex-editing"!==this.state&&(this.currentVertices=t.vertices||[])}startDrag(t,e){this.state="dragging",this.startPoint={x:t,y:e},this.startElement={...this.config.element},this.startRotationElement=this.config.rotationElement?{...this.config.rotationElement}:null,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.gestureRotationCenter=this.config.rotationCenter??{x:this.config.element.origin.x+this.config.element.size.width/2,y:this.config.element.origin.y+this.config.element.size.height/2},this.onUpdate({state:"start",transformData:{type:"vertex-edit",changes:{vertices:this.startVertices},metadata:{vertexIndex:t}}}))}startRotation(t,e,i=0,n){this.state="rotating",this.startPoint={x:t,y:e},this.startElement={...this.config.element},this.rotationCenter=this.config.rotationCenter??{x:this.config.element.origin.x+this.config.element.size.width/2,y:this.config.element.origin.y+this.config.element.size.height/2};const{scale:o=1}=this.config,a=this.config.rotationElement??this.config.element,r=a.size.width*o,s=a.size.height*o,l=n??Math.max(r,s)/2+35,h=(i+90*(this.config.pageRotation??0))*Math.PI/180;this.centerScreen={x:t-l*Math.sin(h),y:e+l*Math.cos(h)},this.initialRotation=i,this.lastComputedRotation=i,this.rotationDelta=0,this.rotationSnappedAngle=null,this.onUpdate({state:"start",transformData:{type:"rotate",changes:{rotation:i},metadata:{rotationAngle:i,rotationDelta:0,rotationCenter:this.rotationCenter,isSnapped:!1}}})}move(t,e,n){if("idle"!==this.state&&this.startPoint)if(void 0===n||0!==n){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=function(t,e,i){const{annotationRotation:n=0,constraints:o}=i,a=null==o?void 0:o.boundingBox;if(0!==n&&a){const o=c(t,e,i,!1,!0);if(h(o,n,a))return o;let r=c({x:0,y:0},e,i,!1,!0),s=0,l=1;for(let d=0;d<20;d+=1){const o=(s+l)/2,d=c({x:t.x*o,y:t.y*o},e,i,!1,!0);h(d,n,a)?(r=d,s=o):l=o}return r}return c(t,e,i,!0,!1)}(this.calculateLocalDelta(t,e),this.activeHandle,{startRect:this.startElement,maintainAspectRatio:this.config.maintainAspectRatio,annotationRotation:this.config.annotationRotation,constraints:this.config.constraints});this.currentPosition=i,this.onUpdate({state:"move",transformData:{type:"resize",changes:{rect:i},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}}})}else if("rotating"===this.state&&this.rotationCenter){const n=this.calculateAngleFromMouse(t,e),o=this.applyRotationSnapping(n),a=i.normalizeAngle(o.angle),r=a-this.lastComputedRotation,s=r>180?r-360:r<-180?r+360:r;this.rotationDelta+=s,this.lastComputedRotation=a,this.rotationSnappedAngle=o.isSnapped?a:null,this.onUpdate({state:"move",transformData:{type:"rotate",changes:{rotation:a},metadata:{rotationAngle:a,rotationDelta:this.rotationDelta,rotationCenter:this.rotationCenter,isSnapped:o.isSnapped,snappedAngle:this.rotationSnappedAngle??void 0,cursorPosition:{clientX:t,clientY:e}}}})}}else this.end()}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 if("rotating"===t)this.onUpdate({state:"end",transformData:{type:"rotate",changes:{rotation:this.lastComputedRotation},metadata:{rotationAngle:this.lastComputedRotation,rotationDelta:this.rotationDelta,rotationCenter:this.rotationCenter||void 0,isSnapped:null!==this.rotationSnappedAngle,snappedAngle:this.rotationSnappedAngle??void 0}}});else{const i=this.currentPosition||this.config.element;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}}}):"rotating"===this.state?this.onUpdate({state:"end",transformData:{type:"rotate",changes:{rotation:this.initialRotation},metadata:{rotationAngle:this.initialRotation,rotationDelta:0,rotationCenter:this.rotationCenter||void 0,isSnapped:!1}}}):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.startRotationElement=null,this.gestureRotationCenter=null,this.activeHandle=null,this.currentPosition=null,this.activeVertexIndex=null,this.startVertices=[],this.rotationCenter=null,this.centerScreen=null,this.initialRotation=0,this.lastComputedRotation=0,this.rotationDelta=0,this.rotationSnappedAngle=null}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,o=Math.cos(n),a=Math.sin(n),r=t.x/i,s=t.y/i;return{x:o*r+a*s,y:-a*r+o*s}}calculateLocalDelta(t,e){const i=this.calculateDelta(t,e),{annotationRotation:n=0}=this.config;if(0===n)return i;const o=n*Math.PI/180,a=Math.cos(o),r=Math.sin(o);return{x:a*i.x+r*i.y,y:-r*i.x+a*i.y}}clampPoint(t){var e;const n=null==(e=this.config.constraints)?void 0:e.boundingBox;if(!n)return t;const{annotationRotation:o=0}=this.config;if(0===o)return{x:Math.max(0,Math.min(t.x,n.width)),y:Math.max(0,Math.min(t.y,n.height))};const a=this.gestureRotationCenter??this.config.rotationCenter??{x:this.config.element.origin.x+this.config.element.size.width/2,y:this.config.element.origin.y+this.config.element.size.height/2},r=i.rotatePointAround(t,a,o),s=Math.max(0,Math.min(r.x,n.width)),l=Math.max(0,Math.min(r.y,n.height));return s===r.x&&l===r.y?t:i.rotatePointAround({x:s,y:l},a,-o)}calculateVertexPosition(t,e){if(null===this.activeVertexIndex)return this.startVertices;const i=this.calculateLocalDelta(t,e),n=[...this.startVertices],o=n[this.activeVertexIndex],a={x:o.x+i.x,y:o.y+i.y};return n[this.activeVertexIndex]=this.clampPoint(a),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}},{annotationRotation:i=0,constraints:n}=this.config,o=null==n?void 0:n.boundingBox;if(0!==i&&o){let t,n,a,r;if(this.startRotationElement)t=this.startRotationElement.size.width,n=this.startRotationElement.size.height,a=this.startRotationElement.origin.x-this.startElement.origin.x,r=this.startRotationElement.origin.y-this.startElement.origin.y;else{const o=Math.abs(i*Math.PI/180),s=Math.abs(Math.cos(o)),l=Math.abs(Math.sin(o)),h=e.size.width,c=e.size.height;t=h*s+c*l,n=h*l+c*s,a=(h-t)/2,r=(c-n)/2}let{x:s,y:l}=e.origin;return s=Math.max(-a,Math.min(s,o.width-t-a)),l=Math.max(-r,Math.min(l,o.height-n-r)),{origin:{x:s,y:l},size:e.size}}return l(e,n,this.config.maintainAspectRatio??!1)}calculateAngleFromMouse(t,e){if(!this.centerScreen)return this.initialRotation;const n=t-this.centerScreen.x,o=e-this.centerScreen.y;if(Math.sqrt(n*n+o*o)<10)return this.lastComputedRotation;const a=90*(this.config.pageRotation??0),r=Math.atan2(o,n)*(180/Math.PI)+90-a;return i.normalizeAngle(Math.round(r))}applyRotationSnapping(t){const e=this.config.rotationSnapAngles??[0,90,180,270],n=this.config.rotationSnapThreshold??4,o=i.normalizeAngle(t);for(const a of e){const t=i.normalizeAngle(a),e=Math.abs(o-t);if(Math.min(e,360-e)<=n)return{angle:t,isSnapped:!0,snapTarget:t}}return{angle:o,isSnapped:!1}}}const u=e=>t.toRaw(t.isRef(e)?t.unref(e):e),g=(t,e=0)=>{const i=Number(t);return Number.isFinite(i)?i:e},p=t=>{var e,i,n,o;return{origin:{x:g(null==(e=null==t?void 0:t.origin)?void 0:e.x),y:g(null==(i=null==t?void 0:t.origin)?void 0:i.y)},size:{width:g(null==(n=null==t?void 0:t.size)?void 0:n.width),height:g(null==(o=null==t?void 0:t.size)?void 0:o.height)}}},m=(t=[])=>t.map(t=>({x:g(null==t?void 0:t.x),y:g(null==t?void 0:t.y)})),x=t=>void 0===t?void 0:Boolean(t),v=t=>void 0===t?void 0:g(t),f=t=>t?u(t):void 0;function y(e){const i=t.ref(null),{onUpdate:n,element:o,rotationCenter:a,rotationElement:r,vertices:s,constraints:l,maintainAspectRatio:h,pageRotation:c,annotationRotation:g,scale:y,enabled:z}=e,R={element:p(u(o)),rotationCenter:a?u(a):void 0,rotationElement:r?p(u(r)):void 0,vertices:s?m(u(s)):void 0,constraints:f(l),maintainAspectRatio:x(void 0===z?void 0:u(h)),pageRotation:v(void 0===c?void 0:u(c)),annotationRotation:v(void 0===g?void 0:u(g)),scale:v(void 0===y?void 0:u(y))};i.value||(i.value=t.markRaw(new d(R,t=>null==n?void 0:n(t)))),t.watch(()=>({element:o,rotationCenter:a,rotationElement:r,vertices:s,constraints:l,maintainAspectRatio:h,pageRotation:c,annotationRotation:g,scale:y}),t=>{var e;null==(e=i.value)||e.updateConfig({element:p(u(t.element)),rotationCenter:t.rotationCenter?u(t.rotationCenter):void 0,rotationElement:t.rotationElement?p(u(t.rotationElement)):void 0,vertices:t.vertices?m(u(t.vertices)):void 0,constraints:f(t.constraints),maintainAspectRatio:x(void 0===t.maintainAspectRatio?void 0:u(t.maintainAspectRatio)),pageRotation:v(void 0===t.pageRotation?void 0:u(t.pageRotation)),annotationRotation:v(void 0===t.annotationRotation?void 0:u(t.annotationRotation)),scale:v(void 0===t.scale?void 0:u(t.scale))})},{deep:!0}),t.onUnmounted(()=>{i.value=null});const w=()=>Boolean(void 0===z||u(z)),P=t=>{var e,n,o;w()&&(t.preventDefault(),t.stopPropagation(),null==(e=i.value)||e.startDrag(t.clientX,t.clientY),null==(o=(n=t.currentTarget).setPointerCapture)||o.call(n,t.pointerId))},M=t=>{var e;return null==(e=i.value)?void 0:e.move(t.clientX,t.clientY,t.buttons)},A=t=>{var e,n,o;null==(e=i.value)||e.end(),null==(o=(n=t.currentTarget).releasePointerCapture)||o.call(n,t.pointerId)},C=t=>{var e,n,o;null==(e=i.value)||e.cancel(),null==(o=(n=t.currentTarget).releasePointerCapture)||o.call(n,t.pointerId)};return{dragProps:t.computed(()=>w()?{onPointerdown:P,onPointermove:M,onPointerup:A,onPointercancel:C}:{}),createResizeProps:t=>({onPointerdown:e=>{var n,o,a;w()&&(e.preventDefault(),e.stopPropagation(),null==(n=i.value)||n.startResize(t,e.clientX,e.clientY),null==(a=(o=e.currentTarget).setPointerCapture)||a.call(o,e.pointerId))},onPointermove:M,onPointerup:A,onPointercancel:C}),createVertexProps:t=>({onPointerdown:e=>{var n,o,a;w()&&(e.preventDefault(),e.stopPropagation(),null==(n=i.value)||n.startVertexEdit(t,e.clientX,e.clientY),null==(a=(o=e.currentTarget).setPointerCapture)||a.call(o,e.pointerId))},onPointermove:M,onPointerup:A,onPointercancel:C}),createRotationProps:(t=0,e)=>({onPointerdown:n=>{var o,a,r;if(!w())return;n.preventDefault(),n.stopPropagation();const s=n.currentTarget.getBoundingClientRect(),l=s.left+s.width/2,h=s.top+s.height/2;null==(o=i.value)||o.startRotation(l,h,t,e),null==(r=(a=n.currentTarget).setPointerCapture)||r.call(a,n.pointerId)},onPointermove:M,onPointerup:A,onPointercancel:C})}}exports.CounterRotate=n,exports.deepToRaw=function(e){const i=e=>Array.isArray(e)?e.map(t=>i(t)):t.isRef(e)||t.isReactive(e)||t.isProxy(e)?i(t.toRaw(e)):e&&"object"==typeof e?Object.keys(e).reduce((t,n)=>(t[n]=i(e[n]),t),{}):e;return i(e)},exports.useDoublePressProps=function(e,{delay:i=300,tolerancePx:n=18}={}){const o=t.ref({t:0,x:0,y:0});return e?{onDblclick:t=>{null==e||e(t)},onPointerupCapture:t=>{if(!e)return;if("mouse"===t.pointerType||!1===t.isPrimary)return;const a=performance.now(),r=t.clientX,s=t.clientY,l=a-o.value.t<=i,h=r-o.value.x,c=s-o.value.y;l&&h*h+c*c<=n*n&&(null==e||e(t)),o.value={t:a,x:r,y:s}}}:{}},exports.useDragResize=y,exports.useInteractionHandles=function(e){const{controller:i,resizeUI:n,vertexUI:o,rotationUI:a,includeVertices:l=!1,includeRotation:h=!1,currentRotation:c=0,handleAttrs:d,vertexAttrs:g,rotationAttrs:x}=e,{dragProps:v,createResizeProps:f,createVertexProps:z,createRotationProps:R}=y(i),w=t.computed(()=>p(u(i.element))),P=t.computed(()=>i.vertices?m(u(i.vertices)):void 0),M=t.computed(()=>Number(u(i.scale??1))),A=t.computed(()=>Number(u(i.pageRotation??0))),C=t.computed(()=>void 0!==i.annotationRotation?Number(u(i.annotationRotation)):void 0),b=t.computed(()=>void 0===i.maintainAspectRatio?void 0:Boolean(u(i.maintainAspectRatio))),E=t.computed(()=>u(i.constraints??void 0)),D=t.computed(()=>i.rotationCenter?u(i.rotationCenter):void 0),I=t.computed(()=>i.rotationElement?p(u(i.rotationElement)):void 0);return{dragProps:v,resize:t.computed(()=>function(t,e={}){const{handleSize:i=8,spacing:n=1,offsetMode:o="outside",includeSides:a=!1,zIndex:l=3,rotationAwareCursor:h=!0}=e,c=(t.pageRotation??0)%4,d=t.annotationRotation??0,u=t=>({[t]:s(i,n,o)+"px"});return[["nw",{...u("top"),...u("left")}],["ne",{...u("top"),...u("right")}],["sw",{...u("bottom"),...u("left")}],["se",{...u("bottom"),...u("right")}],...a?[["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:l,cursor:h?r(t,c,d):"default",pointerEvents:"auto",touchAction:"none",...e},attrs:{"data-epdf-handle":t}}))}({element:w.value,scale:M.value,pageRotation:A.value,annotationRotation:C.value,maintainAspectRatio:b.value,constraints:E.value},n).map(t=>{var e;return{key:(null==(e=t.attrs)?void 0:e["data-epdf-handle"])??t.handle,style:t.style,...f(t.handle),...t.attrs??{},...(null==d?void 0:d(t.handle))??{}}})),vertices:t.computed(()=>{if(!l)return[];const t=P.value??[];return function(t,e={},i){const{vertexSize:n=12,zIndex:o=4}=e,a=t.element,r=t.scale??1;return(i??t.vertices??[]).map((t,e)=>({handle:"nw",style:{position:"absolute",left:(t.x-a.origin.x)*r-n/2+"px",top:(t.y-a.origin.y)*r-n/2+"px",width:n+"px",height:n+"px",borderRadius:"50%",cursor:"pointer",zIndex:o,pointerEvents:"auto",touchAction:"none"},attrs:{"data-epdf-vertex":e}}))}({element:w.value,scale:M.value,vertices:t},o,t).map((t,e)=>({key:e,style:t.style,...z(e),...t.attrs??{},...(null==g?void 0:g(e))??{}}))}),rotation:t.computed(()=>{if(!Boolean(u(h??!1)))return null;const t=Number(u(c??0)),e=function(t,e={},i=0){const{handleSize:n=16,zIndex:o=5,showConnector:a=!0,connectorWidth:r=1}=e,s=t.scale??1,l=t.element,h=t.rotationElement??l,c=t.rotationCenter??{x:l.origin.x+l.size.width/2,y:l.origin.y+l.size.height/2};h.size.width,h.size.height;const d=(c.x-h.origin.x)*s,u=(c.y-h.origin.y)*s,g=i*Math.PI/180,p=e.margin??35,m=l.size.height*s/2+p;return{handleStyle:{position:"absolute",left:d+m*Math.sin(g)-n/2+"px",top:u-m*Math.cos(g)-n/2+"px",width:n+"px",height:n+"px",borderRadius:"50%",cursor:"grab",zIndex:o,pointerEvents:"auto",touchAction:"none"},connectorStyle:a?{position:"absolute",left:d-r/2+"px",top:u-m+"px",width:r+"px",height:m+"px",transformOrigin:"center bottom",transform:`rotate(${i}deg)`,zIndex:o-1,pointerEvents:"none"}:{},radius:m,attrs:{"data-epdf-rotation-handle":!0}}}({element:w.value,rotationCenter:D.value,rotationElement:I.value,scale:M.value},a,t);return{handle:{style:e.handleStyle,...R(t,e.radius),...e.attrs??{},...(null==x?void 0:x())??{}},connector:{style:e.connectorStyle,"data-epdf-rotation-connector":!0}}})}};
2
2
  //# sourceMappingURL=index.cjs.map