@h4md1/visual-image-tool 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -31
- package/dist/visual-image-tool.cjs +13 -3
- package/dist/visual-image-tool.cjs.map +1 -1
- package/dist/visual-image-tool.esm.js +13 -3
- package/dist/visual-image-tool.esm.js.map +1 -1
- package/dist/visual-image-tool.umd.js +1 -1
- package/dist/visual-image-tool.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/visual-image-tool.js +13 -3
- package/src/visual-image-tool.test.js +52 -0
package/README.md
CHANGED
|
@@ -27,16 +27,23 @@ import { VisualImageTool } from "@h4md1/visual-image-tool";
|
|
|
27
27
|
|
|
28
28
|
// OR CommonJS import
|
|
29
29
|
const { VisualImageTool } = require("@h4md1/visual-image-tool");
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or load the UMD build directly with a script tag:
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
```html
|
|
35
|
+
<script src="node_modules/@h4md1/visual-image-tool/dist/visual-image-tool.umd.js"></script>
|
|
33
36
|
```
|
|
34
37
|
|
|
38
|
+
The UMD build exposes a global `VisualImageTool` object holding the named
|
|
39
|
+
export, so the class is `VisualImageTool.VisualImageTool`. With an `import` or
|
|
40
|
+
`require` you already have the class itself.
|
|
41
|
+
|
|
35
42
|
### 2. Initialization
|
|
36
43
|
|
|
37
44
|
```javascript
|
|
38
45
|
// Create an instance with an image
|
|
39
|
-
const imageTool = new VisualImageTool
|
|
46
|
+
const imageTool = new VisualImageTool({
|
|
40
47
|
imageElement: document.getElementById("myImage"),
|
|
41
48
|
debug: true, // Enable debug logs for overlay positioning (optional)
|
|
42
49
|
onChange: (data) => {
|
|
@@ -46,6 +53,14 @@ const imageTool = new VisualImageTool.VisualImageTool({
|
|
|
46
53
|
});
|
|
47
54
|
```
|
|
48
55
|
|
|
56
|
+
Via the script tag above, the same call reads:
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
const imageTool = new VisualImageTool.VisualImageTool({
|
|
60
|
+
imageElement: document.getElementById("myImage"),
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
49
64
|
### 3. Using the Features
|
|
50
65
|
|
|
51
66
|
```javascript
|
|
@@ -69,7 +84,7 @@ const cropZone = imageTool.getCropZone();
|
|
|
69
84
|
## Configuration Options
|
|
70
85
|
|
|
71
86
|
```javascript
|
|
72
|
-
const imageTool = new VisualImageTool
|
|
87
|
+
const imageTool = new VisualImageTool({
|
|
73
88
|
// Image element (required) - can be a CSS selector or a DOM element
|
|
74
89
|
imageElement: "#myImage",
|
|
75
90
|
|
|
@@ -153,6 +168,11 @@ Gets the current position of the focus point.
|
|
|
153
168
|
|
|
154
169
|
- Returns: An object `{x, y}` with coordinates in original pixels.
|
|
155
170
|
|
|
171
|
+
The focus point starts at `{x: 0, y: 0}`, and `getFocusPoint()` returns that
|
|
172
|
+
until the feature is first enabled. The first `toggleFocusPoint(true)` moves a
|
|
173
|
+
still-unset point to the centre of the image, so read it back after enabling
|
|
174
|
+
the feature — or call `setFocusPoint(x, y)` yourself to place it explicitly.
|
|
175
|
+
|
|
156
176
|
#### `getCropZone()`
|
|
157
177
|
|
|
158
178
|
Gets the current position and dimensions of the crop zone.
|
|
@@ -234,34 +254,32 @@ function ImageEditor() {
|
|
|
234
254
|
</div>
|
|
235
255
|
</template>
|
|
236
256
|
|
|
237
|
-
<script>
|
|
257
|
+
<script setup>
|
|
258
|
+
import { onBeforeUnmount, onMounted, ref } from "vue";
|
|
238
259
|
import { VisualImageTool } from "@h4md1/visual-image-tool";
|
|
239
260
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
},
|
|
264
|
-
};
|
|
261
|
+
const editableImage = ref(null);
|
|
262
|
+
let imageTool = null;
|
|
263
|
+
|
|
264
|
+
onMounted(() => {
|
|
265
|
+
imageTool = new VisualImageTool({
|
|
266
|
+
imageElement: editableImage.value,
|
|
267
|
+
onChange: (data) => {
|
|
268
|
+
console.log("Updated data:", data);
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// Enable features
|
|
273
|
+
imageTool.toggleFocusPoint(true);
|
|
274
|
+
imageTool.toggleCropZone(true);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
onBeforeUnmount(() => {
|
|
278
|
+
if (imageTool) {
|
|
279
|
+
imageTool.destroy();
|
|
280
|
+
imageTool = null;
|
|
281
|
+
}
|
|
282
|
+
});
|
|
265
283
|
</script>
|
|
266
284
|
```
|
|
267
285
|
|
|
@@ -295,7 +313,7 @@ This project uses a combination of tools for code formatting and linting to ensu
|
|
|
295
313
|
- Fix: `npm run lint:fix` (`biome check --write .`)
|
|
296
314
|
- **[Prettier](https://prettier.io/)**: Handles formatting for other file types like HTML, CSS, Markdown, etc.
|
|
297
315
|
- Check: `npm run format:check` (`prettier --check --ignore-unknown .`)
|
|
298
|
-
- Fix: `npm run format:
|
|
316
|
+
- Fix: `npm run format:fix` (`prettier --write --ignore-unknown .`)
|
|
299
317
|
|
|
300
318
|
These formatting checks are automatically enforced in the CI pipeline (see `.github/workflows/code-quality.yml`) to maintain code quality.
|
|
301
319
|
|
|
@@ -167,16 +167,26 @@ class VisualImageTool {
|
|
|
167
167
|
this.spinnerElement.style.boxSizing = "border-box";
|
|
168
168
|
this.spinnerElement.style.zIndex = "1000"; // Ensure it's above other elements
|
|
169
169
|
this.spinnerElement.style.display = "block"; // Initially visible
|
|
170
|
-
this.spinnerElement.style.animation =
|
|
170
|
+
this.spinnerElement.style.animation =
|
|
171
|
+
"visual-image-tool-spin 1s linear infinite";
|
|
171
172
|
|
|
172
173
|
this.imageElement.parentNode.appendChild(this.spinnerElement);
|
|
173
174
|
|
|
174
|
-
// Add CSS keyframes for spinner animation
|
|
175
|
+
// Add CSS keyframes for spinner animation.
|
|
176
|
+
//
|
|
177
|
+
// The animation name is namespaced: keyframes are global to the
|
|
178
|
+
// document, so a bare name like `spin` would collide with one
|
|
179
|
+
// defined by the host page, and whichever stylesheet was injected
|
|
180
|
+
// last would silently win.
|
|
181
|
+
//
|
|
182
|
+
// This stylesheet is shared by every instance and deliberately
|
|
183
|
+
// outlives destroy(): removing it would break the animation for
|
|
184
|
+
// any instance still alive. The id guard keeps it to one element.
|
|
175
185
|
if (!document.getElementById("visual-image-tool-spinner-styles")) {
|
|
176
186
|
const styleElement = document.createElement("style");
|
|
177
187
|
styleElement.id = "visual-image-tool-spinner-styles";
|
|
178
188
|
styleElement.innerHTML = `
|
|
179
|
-
@keyframes spin {
|
|
189
|
+
@keyframes visual-image-tool-spin {
|
|
180
190
|
0% { transform: translate(-50%, -50%) rotate(0deg); }
|
|
181
191
|
100% { transform: translate(-50%, -50%) rotate(360deg); }
|
|
182
192
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visual-image-tool.cjs","sources":["../src/visual-image-tool.js"],"sourcesContent":["/**\n * ImageTool - A lightweight tool for defining focus points and crop zones on images\n * @module visual-image-tool\n */\n\nclass VisualImageTool {\n\t/**\n\t * Creates an instance of the image tool.\n\t * The focus point is initialized to `{x:0, y:0}` in `this.state`. When `toggleFocusPoint(true)` is called for the first time, if the focus point is still `{x:0, y:0}`, it will be automatically centered on the image.\n\t * @param {Object} options - Configuration options\n\t * @param {HTMLElement|string} options.imageElement - Image element or CSS selector\n\t * @param {Object} [options.focusPoint] - Focus point configuration\n\t * @param {boolean} [options.focusPoint.enabled=true] - Enable focus point functionality\n\t * @param {Object} [options.focusPoint.style] - Custom styles for the focus point marker\n\t * @param {Object} [options.cropZone] - Crop zone configuration\n\t * @param {boolean} [options.cropZone.enabled=true] - Enable crop zone functionality\n\t * @param {Object} [options.cropZone.style] - Custom styles for the crop overlay\n\t * @param {Function} [options.onChange] - Callback called on changes\n\t */\n\tconstructor(options) {\n\t\t// Validate options\n\t\tif (!options || !options.imageElement) {\n\t\t\tthrow new Error(\"Image element is required\");\n\t\t}\n\n\t\t// Initialize properties\n\t\tthis.imageElement =\n\t\t\ttypeof options.imageElement === \"string\"\n\t\t\t\t? document.querySelector(options.imageElement)\n\t\t\t\t: options.imageElement;\n\n\t\tif (!this.imageElement || this.imageElement.tagName !== \"IMG\") {\n\t\t\tthrow new Error(\"Invalid image element\");\n\t\t}\n\n\t\t// Default options\n\t\tthis.options = {\n\t\t\tfocusPoint: {\n\t\t\t\tenabled: true,\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: \"30px\",\n\t\t\t\t\theight: \"30px\",\n\t\t\t\t\tborder: \"3px solid white\",\n\t\t\t\t\tboxShadow: \"0 0 0 2px black, 0 0 5px rgba(0,0,0,0.5)\",\n\t\t\t\t\tbackgroundColor: \"rgba(255, 0, 0, 0.5)\",\n\t\t\t\t},\n\t\t\t\t...options.focusPoint,\n\t\t\t},\n\t\t\tcropZone: {\n\t\t\t\tenabled: true,\n\t\t\t\tstyle: {\n\t\t\t\t\tborder: \"1px dashed #fff\",\n\t\t\t\t\tbackgroundColor: \"rgba(0, 0, 0, 0.4)\",\n\t\t\t\t},\n\t\t\t\thandleStyle: {\n\t\t\t\t\twidth: \"14px\",\n\t\t\t\t\theight: \"14px\",\n\t\t\t\t\tbackgroundColor: \"white\",\n\t\t\t\t\tborder: \"2px solid black\",\n\t\t\t\t\tboxShadow: \"0 0 3px rgba(0,0,0,0.5)\",\n\t\t\t\t},\n\t\t\t\t...options.cropZone,\n\t\t\t},\n\t\t\tonChange: options.onChange || (() => {}),\n\t\t\tdebug: options.debug || false,\n\t\t};\n\n\t\t// Internal state\n\t\tthis.state = {\n\t\t\tfocusMarker: null,\n\t\t\tcropOverlay: null,\n\t\t\tfocusActive: false,\n\t\t\tcropActive: false,\n\t\t\tfocusPoint: { x: 0, y: 0 },\n\t\t\tcropZone: { x: 0, y: 0, width: 0, height: 0 },\n\t\t\toriginalWidth: 1,\n\t\t\toriginalHeight: 1,\n\t\t\tdisplayWidth: 1,\n\t\t\tdisplayHeight: 1,\n\t\t\tscaleX: 1,\n\t\t\tscaleY: 1,\n\t\t};\n\n\t\t// Handlers are bound once here: addEventListener and removeEventListener\n\t\t// must be handed the same function reference for removal to work.\n\t\tthis._boundUpdateScaling = this._updateScaling.bind(this);\n\t\tthis._boundHandleMouseUp = this._handleMouseUp.bind(this);\n\t\tthis._boundHandleMouseMove = this._handleMouseMove.bind(this);\n\t\tthis._boundFocusMarkerMouseDown =\n\t\t\tthis._handleFocusMarkerMouseDown.bind(this);\n\t\tthis._boundCropOverlayMouseDown =\n\t\t\tthis._handleCropOverlayMouseDown.bind(this);\n\t\tthis._boundCropHandleMouseDown = this._handleCropHandleMouseDown.bind(this);\n\n\t\t// Resize handles, tracked so their listeners can be removed on destroy\n\t\tthis.cropHandles = [];\n\n\t\t// Variables for tracking interactions\n\t\tthis.interaction = {\n\t\t\tfocusDragging: false,\n\t\t\tfocusDragOffsetX: 0,\n\t\t\tfocusDragOffsetY: 0,\n\t\t\tcropDragging: false,\n\t\t\tcropResizing: false,\n\t\t\tactiveHandle: null,\n\t\t\tstartX: 0,\n\t\t\tstartY: 0,\n\t\t\tstartWidth: 0,\n\t\t\tstartHeight: 0,\n\t\t\tstartMouseX: 0,\n\t\t\tstartMouseY: 0,\n\t\t};\n\n\t\tthis.spinnerElement = null;\n\t\tthis.initialLoadComplete = false;\n\n\t\t// Initialize the tool\n\t\tthis._init();\n\t}\n\n\t/**\n\t * Initializes the image tool\n\t * @private\n\t */\n\t_init() {\n\t\t// Prepare the parent container\n\t\tthis._prepareContainer();\n\n\t\t// Initialize dimensions\n\t\tthis._updateScaling();\n\n\t\t// Create UI elements if enabled\n\t\tif (this.options.focusPoint.enabled) {\n\t\t\tthis._createFocusMarker();\n\t\t}\n\n\t\tif (this.options.cropZone.enabled) {\n\t\t\tthis._createCropOverlay();\n\t\t}\n\n\t\t// Add event listeners\n\t\tthis._setupEventListeners();\n\t}\n\n\t/**\n\t * Prepares the image's parent container\n\t * @private\n\t */\n\t_prepareContainer() {\n\t\t// Ensure the parent is positioned\n\t\tif (this.imageElement.parentNode) {\n\t\t\tthis.imageElement.parentNode.style.position = \"relative\";\n\n\t\t\t// Create spinner element\n\t\t\tthis.spinnerElement = document.createElement(\"div\");\n\t\t\tthis.spinnerElement.style.position = \"absolute\";\n\t\t\tthis.spinnerElement.style.top = \"50%\";\n\t\t\tthis.spinnerElement.style.left = \"50%\";\n\t\t\tthis.spinnerElement.style.transform = \"translate(-50%, -50%)\";\n\t\t\tthis.spinnerElement.style.width = \"40px\";\n\t\t\tthis.spinnerElement.style.height = \"40px\";\n\t\t\tthis.spinnerElement.style.border = \"4px solid #f3f3f3\"; // Light grey\n\t\t\tthis.spinnerElement.style.borderTop = \"4px solid #3498db\"; // Blue\n\t\t\tthis.spinnerElement.style.borderRadius = \"50%\";\n\t\t\tthis.spinnerElement.style.boxSizing = \"border-box\";\n\t\t\tthis.spinnerElement.style.zIndex = \"1000\"; // Ensure it's above other elements\n\t\t\tthis.spinnerElement.style.display = \"block\"; // Initially visible\n\t\t\tthis.spinnerElement.style.animation = \"spin 1s linear infinite\";\n\n\t\t\tthis.imageElement.parentNode.appendChild(this.spinnerElement);\n\n\t\t\t// Add CSS keyframes for spinner animation\n\t\t\tif (!document.getElementById(\"visual-image-tool-spinner-styles\")) {\n\t\t\t\tconst styleElement = document.createElement(\"style\");\n\t\t\t\tstyleElement.id = \"visual-image-tool-spinner-styles\";\n\t\t\t\tstyleElement.innerHTML = `\n@keyframes spin {\n 0% { transform: translate(-50%, -50%) rotate(0deg); }\n 100% { transform: translate(-50%, -50%) rotate(360deg); }\n}\n `;\n\t\t\t\tdocument.head.appendChild(styleElement);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Updates scaling factors\n\t * @private\n\t */\n\t_updateScaling() {\n\t\tthis.state.originalWidth = this.imageElement.naturalWidth || 1;\n\t\tthis.state.originalHeight = this.imageElement.naturalHeight || 1;\n\n\t\t// Hide spinner once image is loaded and dimensions are available\n\t\tif (\n\t\t\t!this.initialLoadComplete &&\n\t\t\tthis.spinnerElement &&\n\t\t\tthis.state.originalWidth > 1 &&\n\t\t\tthis.state.originalHeight > 1\n\t\t) {\n\t\t\tthis.spinnerElement.style.display = \"none\";\n\t\t\tthis.initialLoadComplete = true;\n\t\t}\n\t\tthis.state.displayWidth = this.imageElement.offsetWidth;\n\t\tthis.state.displayHeight = this.imageElement.offsetHeight;\n\t\tthis.state.scaleX = this.state.displayWidth / this.state.originalWidth;\n\t\tthis.state.scaleY = this.state.displayHeight / this.state.originalHeight;\n\n\t\t// Update spinner position during initial load if still visible\n\t\tif (!this.initialLoadComplete && this.spinnerElement) {\n\t\t\tthis.spinnerElement.style.top = `${this.state.displayHeight / 2}px`;\n\t\t\tthis.spinnerElement.style.left = `${this.state.displayWidth / 2}px`;\n\t\t}\n\n\t\t// Reposition elements if active\n\t\tif (this.state.focusActive) {\n\t\t\tthis._updateFocusMarkerPosition();\n\t\t}\n\n\t\tif (this.state.cropActive) {\n\t\t\tthis._updateCropOverlayPosition();\n\t\t}\n\t}\n\n\t/**\n\t * Converts display coordinates to original coordinates\n\t * @private\n\t * @param {number} scaledX - X-coordinate at display scale\n\t * @param {number} scaledY - Y-coordinate at display scale\n\t * @returns {Object} Original coordinates {x, y}\n\t */\n\t_toOriginalCoords(scaledX, scaledY) {\n\t\treturn {\n\t\t\tx: scaledX / this.state.scaleX,\n\t\t\ty: scaledY / this.state.scaleY,\n\t\t};\n\t}\n\n\t/**\n\t * Converts original coordinates to display coordinates\n\t * @private\n\t * @param {number} originalX - Original X-coordinate\n\t * @param {number} originalY - Original Y-coordinate\n\t * @returns {Object} Display scale coordinates {x, y}\n\t */\n\t_toScaledCoords(originalX, originalY) {\n\t\treturn {\n\t\t\tx: originalX * this.state.scaleX,\n\t\t\ty: originalY * this.state.scaleY,\n\t\t};\n\t}\n\n\t/**\n\t * Creates the focus point marker\n\t * @private\n\t */\n\t_createFocusMarker() {\n\t\tif (this.state.focusMarker) return;\n\n\t\tconst marker = document.createElement(\"div\");\n\t\tmarker.style.position = \"absolute\";\n\t\tmarker.style.width = this.options.focusPoint.style.width;\n\t\tmarker.style.height = this.options.focusPoint.style.height;\n\t\tmarker.style.border = this.options.focusPoint.style.border;\n\t\tmarker.style.boxShadow = this.options.focusPoint.style.boxShadow;\n\t\tmarker.style.backgroundColor =\n\t\t\tthis.options.focusPoint.style.backgroundColor;\n\t\tmarker.style.cursor = \"move\";\n\t\tmarker.style.display = \"none\";\n\t\tmarker.style.zIndex = \"999\";\n\t\tmarker.style.clipPath =\n\t\t\t\"polygon(40% 0%, 60% 0%, 60% 40%, 100% 40%, 100% 60%, 60% 60%, 60% 100%, 40% 100%, 40% 60%, 0% 60%, 0% 40%, 40% 40%)\";\n\n\t\tthis.imageElement.parentNode.appendChild(marker);\n\t\tthis.state.focusMarker = marker;\n\n\t\t// Add event listeners to the marker\n\t\tmarker.addEventListener(\"mousedown\", this._boundFocusMarkerMouseDown);\n\t}\n\n\t/**\n\t * Handles mousedown event on the focus point marker\n\t * @private\n\t * @param {MouseEvent} e - Mousedown event\n\t */\n\t_handleFocusMarkerMouseDown(e) {\n\t\tthis.interaction.focusDragging = true;\n\t\tthis.state.focusMarker.style.cursor = \"grabbing\";\n\n\t\t// Calculate offset from marker center\n\t\tconst rect = this.state.focusMarker.getBoundingClientRect();\n\t\tthis.interaction.focusDragOffsetX =\n\t\t\te.clientX - (rect.left + rect.width / 2);\n\t\tthis.interaction.focusDragOffsetY =\n\t\t\te.clientY - (rect.top + rect.height / 2);\n\n\t\te.preventDefault();\n\t}\n\n\t/**\n\t * Creates the crop zone overlay\n\t * @private\n\t */\n\t_createCropOverlay() {\n\t\tif (this.state.cropOverlay) return;\n\n\t\tconst overlay = document.createElement(\"div\");\n\t\toverlay.style.position = \"absolute\";\n\t\toverlay.style.border = this.options.cropZone.style.border;\n\t\toverlay.style.backgroundColor = this.options.cropZone.style.backgroundColor;\n\t\toverlay.style.boxSizing = \"border-box\";\n\t\toverlay.style.cursor = \"move\";\n\t\toverlay.style.display = \"none\";\n\t\toverlay.style.zIndex = \"998\";\n\n\t\t// Add resize handles\n\t\tconst handles = [\"tl\", \"tm\", \"tr\", \"ml\", \"mr\", \"bl\", \"bm\", \"br\"];\n\t\tfor (const handleType of handles) {\n\t\t\tconst handle = document.createElement(\"div\");\n\t\t\thandle.style.position = \"absolute\";\n\t\t\thandle.style.width = this.options.cropZone.handleStyle.width;\n\t\t\thandle.style.height = this.options.cropZone.handleStyle.height;\n\t\t\thandle.style.backgroundColor =\n\t\t\t\tthis.options.cropZone.handleStyle.backgroundColor;\n\t\t\thandle.style.border = this.options.cropZone.handleStyle.border;\n\t\t\thandle.style.boxShadow = this.options.cropZone.handleStyle.boxShadow;\n\t\t\thandle.style.boxSizing = \"border-box\";\n\t\t\thandle.dataset.handle = handleType;\n\n\t\t\t// Position the handle\n\t\t\tswitch (handleType) {\n\t\t\t\tcase \"tl\": // Top-left\n\t\t\t\t\thandle.style.top = \"-7px\";\n\t\t\t\t\thandle.style.left = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"nwse-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"tm\": // Top-middle\n\t\t\t\t\thandle.style.top = \"-7px\";\n\t\t\t\t\thandle.style.left = \"50%\";\n\t\t\t\t\thandle.style.marginLeft = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"ns-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"tr\": // Top-right\n\t\t\t\t\thandle.style.top = \"-7px\";\n\t\t\t\t\thandle.style.right = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"nesw-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"ml\": // Middle-left\n\t\t\t\t\thandle.style.top = \"50%\";\n\t\t\t\t\thandle.style.left = \"-7px\";\n\t\t\t\t\thandle.style.marginTop = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"ew-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"mr\": // Middle-right\n\t\t\t\t\thandle.style.top = \"50%\";\n\t\t\t\t\thandle.style.right = \"-7px\";\n\t\t\t\t\thandle.style.marginTop = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"ew-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"bl\": // Bottom-left\n\t\t\t\t\thandle.style.bottom = \"-7px\";\n\t\t\t\t\thandle.style.left = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"nesw-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"bm\": // Bottom-middle\n\t\t\t\t\thandle.style.bottom = \"-7px\";\n\t\t\t\t\thandle.style.left = \"50%\";\n\t\t\t\t\thandle.style.marginLeft = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"ns-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"br\": // Bottom-right\n\t\t\t\t\thandle.style.bottom = \"-7px\";\n\t\t\t\t\thandle.style.right = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"nwse-resize\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Add event listener\n\t\t\thandle.addEventListener(\"mousedown\", this._boundCropHandleMouseDown);\n\n\t\t\toverlay.appendChild(handle);\n\t\t\tthis.cropHandles.push(handle);\n\t\t}\n\n\t\t// Add listener for overlay dragging\n\t\toverlay.addEventListener(\"mousedown\", this._boundCropOverlayMouseDown);\n\n\t\tthis.imageElement.parentNode.appendChild(overlay);\n\t\tthis.state.cropOverlay = overlay;\n\t}\n\n\t/**\n\t * Handles mousedown event on a resize handle\n\t * @private\n\t * @param {MouseEvent} e - Mousedown event\n\t */\n\t_handleCropHandleMouseDown(e) {\n\t\tconst handleType = e.currentTarget.dataset.handle;\n\n\t\tthis.interaction.cropResizing = true;\n\t\tthis.interaction.activeHandle = handleType;\n\n\t\t// Record initial dimensions and position\n\t\tthis.interaction.startX =\n\t\t\tNumber.parseInt(this.state.cropOverlay.style.left, 10) || 0;\n\t\tthis.interaction.startY =\n\t\t\tNumber.parseInt(this.state.cropOverlay.style.top, 10) || 0;\n\t\tthis.interaction.startWidth = this.state.cropOverlay.offsetWidth;\n\t\tthis.interaction.startHeight = this.state.cropOverlay.offsetHeight;\n\t\tthis.interaction.startMouseX = e.clientX;\n\t\tthis.interaction.startMouseY = e.clientY;\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t}\n\n\t/**\n\t * Handles mousedown event on the crop overlay\n\t * @private\n\t * @param {MouseEvent} e - Mousedown event\n\t */\n\t_handleCropOverlayMouseDown(e) {\n\t\t// Ignore if clicking on a handle\n\t\tif (e.target !== this.state.cropOverlay) return;\n\n\t\tthis.interaction.cropDragging = true;\n\t\tthis.state.cropOverlay.style.cursor = \"grabbing\";\n\n\t\t// Record initial position\n\t\tthis.interaction.startX =\n\t\t\tNumber.parseInt(this.state.cropOverlay.style.left, 10) || 0;\n\t\tthis.interaction.startY =\n\t\t\tNumber.parseInt(this.state.cropOverlay.style.top, 10) || 0;\n\t\tthis.interaction.startMouseX = e.clientX;\n\t\tthis.interaction.startMouseY = e.clientY;\n\n\t\te.preventDefault();\n\t}\n\n\t/**\n\t * Sets up global event listeners\n\t * @private\n\t */\n\t_setupEventListeners() {\n\t\t// Listener for window resize\n\t\twindow.addEventListener(\"resize\", this._boundUpdateScaling);\n\n\t\t// Listener for image load\n\t\tif (!this.imageElement.complete) {\n\t\t\tthis.imageElement.addEventListener(\"load\", this._boundUpdateScaling);\n\t\t}\n\n\t\t// Listeners for mouse interactions\n\t\tdocument.addEventListener(\"mouseup\", this._boundHandleMouseUp);\n\t\tdocument.addEventListener(\"mousemove\", this._boundHandleMouseMove);\n\t}\n\n\t/**\n\t * Handles global mouseup event\n\t * @private\n\t */\n\t_handleMouseUp() {\n\t\tif (this.interaction.focusDragging) {\n\t\t\tthis.interaction.focusDragging = false;\n\t\t\tif (this.state.focusMarker) this.state.focusMarker.style.cursor = \"move\";\n\t\t}\n\n\t\tif (this.interaction.cropDragging) {\n\t\t\tthis.interaction.cropDragging = false;\n\t\t\tif (this.state.cropOverlay) this.state.cropOverlay.style.cursor = \"move\";\n\t\t}\n\n\t\tthis.interaction.cropResizing = false;\n\t\tthis.interaction.activeHandle = null;\n\t\tdocument.body.style.cursor = \"default\";\n\t}\n\n\t/**\n\t * Handles global mousemove event\n\t * @private\n\t * @param {MouseEvent} e - Mousemove event\n\t */\n\t_handleMouseMove(e) {\n\t\t// Handle focus point dragging\n\t\tif (this.interaction.focusDragging && this.state.focusMarker) {\n\t\t\tthis._handleFocusMarkerDrag(e);\n\t\t}\n\n\t\t// Handle crop zone dragging\n\t\tif (this.interaction.cropDragging) {\n\t\t\tthis._handleCropOverlayDrag(e);\n\t\t}\n\n\t\t// Handle crop zone resizing\n\t\tif (this.interaction.cropResizing) {\n\t\t\tthis._handleCropOverlayResize(e);\n\t\t}\n\t}\n\n\t/**\n\t * Handles focus point marker drag\n\t * @private\n\t * @param {MouseEvent} e - Mousemove event\n\t */\n\t_handleFocusMarkerDrag(e) {\n\t\tconst imageRect = this.imageElement.getBoundingClientRect();\n\n\t\t// Calculate target position relative to the image\n\t\tconst targetScaledX =\n\t\t\te.clientX - imageRect.left - this.interaction.focusDragOffsetX;\n\t\tconst targetScaledY =\n\t\t\te.clientY - imageRect.top - this.interaction.focusDragOffsetY;\n\n\t\t// Convert to original coordinates\n\t\tconst original = this._toOriginalCoords(targetScaledX, targetScaledY);\n\n\t\t// Update focus point\n\t\tthis.setFocusPoint(original.x, original.y);\n\t}\n\n\t/**\n\t * Handles crop overlay drag\n\t * @private\n\t * @param {MouseEvent} e - Mousemove event\n\t */\n\t_handleCropOverlayDrag(e) {\n\t\tconst deltaX = e.clientX - this.interaction.startMouseX;\n\t\tconst deltaY = e.clientY - this.interaction.startMouseY;\n\n\t\t// Calculate new position in display pixels\n\t\tconst newX = this.interaction.startX + deltaX;\n\t\tconst newY = this.interaction.startY + deltaY;\n\n\t\t// Convert to original coordinates\n\t\tconst original = this._toOriginalCoords(newX, newY);\n\n\t\t// Get current dimensions in original coordinates\n\t\tconst { width, height } = this.state.cropZone;\n\n\t\t// Update crop zone\n\t\tthis.setCropZone(original.x, original.y, width, height);\n\t}\n\n\t/**\n\t * Handles crop overlay resize\n\t * @private\n\t * @param {MouseEvent} e - Mousemove event\n\t */\n\t_handleCropOverlayResize(e) {\n\t\tif (!this.interaction.activeHandle) return;\n\n\t\tconst deltaX = e.clientX - this.interaction.startMouseX;\n\t\tconst deltaY = e.clientY - this.interaction.startMouseY;\n\n\t\tlet newX = this.interaction.startX;\n\t\tlet newY = this.interaction.startY;\n\t\tlet newWidth = this.interaction.startWidth;\n\t\tlet newHeight = this.interaction.startHeight;\n\n\t\t// Adjust based on active handle\n\t\tif (this.interaction.activeHandle.includes(\"t\")) {\n\t\t\t// Top\n\t\t\tnewY = this.interaction.startY + deltaY;\n\t\t\tnewHeight = this.interaction.startHeight - deltaY;\n\t\t}\n\t\tif (this.interaction.activeHandle.includes(\"b\")) {\n\t\t\t// Bottom\n\t\t\tnewHeight = this.interaction.startHeight + deltaY;\n\t\t}\n\t\tif (this.interaction.activeHandle.includes(\"l\")) {\n\t\t\t// Left\n\t\t\tnewX = this.interaction.startX + deltaX;\n\t\t\tnewWidth = this.interaction.startWidth - deltaX;\n\t\t}\n\t\tif (this.interaction.activeHandle.includes(\"r\")) {\n\t\t\t// Right\n\t\t\tnewWidth = this.interaction.startWidth + deltaX;\n\t\t}\n\n\t\t// Prevent negative dimensions\n\t\tif (newWidth < 10) {\n\t\t\tif (this.interaction.activeHandle.includes(\"l\")) {\n\t\t\t\tnewX = this.interaction.startX + this.interaction.startWidth - 10;\n\t\t\t}\n\t\t\tnewWidth = 10;\n\t\t}\n\t\tif (newHeight < 10) {\n\t\t\tif (this.interaction.activeHandle.includes(\"t\")) {\n\t\t\t\tnewY = this.interaction.startY + this.interaction.startHeight - 10;\n\t\t\t}\n\t\t\tnewHeight = 10;\n\t\t}\n\n\t\t// Convert display coordinates to original coordinates\n\t\tconst originalX = newX / this.state.scaleX;\n\t\tconst originalY = newY / this.state.scaleY;\n\t\tconst originalWidth = newWidth / this.state.scaleX;\n\t\tconst originalHeight = newHeight / this.state.scaleY;\n\n\t\t// Update crop zone\n\t\tthis.setCropZone(originalX, originalY, originalWidth, originalHeight);\n\t}\n\n\t/**\n\t * Updates the focus point marker position\n\t * @private\n\t */\n\t_updateFocusMarkerPosition() {\n\t\tif (!this.state.focusMarker) return;\n\n\t\tconst { x, y } = this.state.focusPoint;\n\n\t\t// Clamp coordinates to image dimensions\n\t\tconst clampedX = Math.max(0, Math.min(x, this.state.originalWidth));\n\t\tconst clampedY = Math.max(0, Math.min(y, this.state.originalHeight));\n\n\t\t// Update state if coordinates were clamped\n\t\tif (x !== clampedX || y !== clampedY) {\n\t\t\tthis.state.focusPoint = { x: clampedX, y: clampedY };\n\t\t}\n\n\t\tconst scaled = this._toScaledCoords(clampedX, clampedY);\n\n\t\t// LOGGING: Validate padding offset\n\t\tif (this.options.debug) {\n\t\t\tconst container = this.imageElement.parentNode;\n\t\t\tconst computedStyle = window.getComputedStyle(container);\n\t\t\tconst paddingLeft = Number.parseFloat(computedStyle.paddingLeft);\n\t\t\tconst paddingTop = Number.parseFloat(computedStyle.paddingTop);\n\t\t\tconsole.log(\n\t\t\t\t\"[FocusMarker] scaled:\",\n\t\t\t\tscaled,\n\t\t\t\t\"paddingLeft:\",\n\t\t\t\tpaddingLeft,\n\t\t\t\t\"paddingTop:\",\n\t\t\t\tpaddingTop,\n\t\t\t\t\"containerRect:\",\n\t\t\t\tcontainer.getBoundingClientRect(),\n\t\t\t);\n\t\t}\n\n\t\t// Adjust to center the marker\n\t\t// Adjust for container padding (use unique variable names)\n\t\tlet focusPaddingLeft = 0;\n\t\tlet focusPaddingTop = 0;\n\t\t{\n\t\t\tconst container = this.imageElement.parentNode;\n\t\t\tconst computedStyle = window.getComputedStyle(container);\n\t\t\tfocusPaddingLeft = Number.parseFloat(computedStyle.paddingLeft);\n\t\t\tfocusPaddingTop = Number.parseFloat(computedStyle.paddingTop);\n\t\t}\n\n\t\tthis.state.focusMarker.style.left = `${\n\t\t\tscaled.x + focusPaddingLeft - this.state.focusMarker.offsetWidth / 2\n\t\t}px`;\n\t\tthis.state.focusMarker.style.top = `${\n\t\t\tscaled.y + focusPaddingTop - this.state.focusMarker.offsetHeight / 2\n\t\t}px`;\n\t\tif (this.options.debug) {\n\t\t\tconsole.log(\n\t\t\t\t\"[FocusMarker] style.left:\",\n\t\t\t\tthis.state.focusMarker.style.left,\n\t\t\t\t\"style.top:\",\n\t\t\t\tthis.state.focusMarker.style.top,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Updates the crop overlay position and dimensions\n\t * @private\n\t */\n\t_updateCropOverlayPosition() {\n\t\tif (!this.state.cropOverlay) return;\n\n\t\tconst { x, y, width, height } = this.state.cropZone;\n\n\t\t// Clamp to image dimensions\n\t\tconst clampedX = Math.max(0, Math.min(x, this.state.originalWidth - width));\n\t\tconst clampedY = Math.max(\n\t\t\t0,\n\t\t\tMath.min(y, this.state.originalHeight - height),\n\t\t);\n\t\tconst clampedWidth = Math.max(\n\t\t\t10,\n\t\t\tMath.min(width, this.state.originalWidth - clampedX),\n\t\t);\n\t\tconst clampedHeight = Math.max(\n\t\t\t10,\n\t\t\tMath.min(height, this.state.originalHeight - clampedY),\n\t\t);\n\n\t\t// Update state if values were clamped\n\t\tif (\n\t\t\tx !== clampedX ||\n\t\t\ty !== clampedY ||\n\t\t\twidth !== clampedWidth ||\n\t\t\theight !== clampedHeight\n\t\t) {\n\t\t\tthis.state.cropZone = {\n\t\t\t\tx: clampedX,\n\t\t\t\ty: clampedY,\n\t\t\t\twidth: clampedWidth,\n\t\t\t\theight: clampedHeight,\n\t\t\t};\n\t\t}\n\n\t\t// Convert to display coordinates\n\t\tconst scaled = this._toScaledCoords(clampedX, clampedY);\n\t\tconst scaledWidth = clampedWidth * this.state.scaleX;\n\t\tconst scaledHeight = clampedHeight * this.state.scaleY;\n\n\t\t// LOGGING: Validate padding offset\n\t\tif (this.options.debug) {\n\t\t\tconst container = this.imageElement.parentNode;\n\t\t\tconst computedStyle = window.getComputedStyle(container);\n\t\t\tconst paddingLeft = Number.parseFloat(computedStyle.paddingLeft);\n\t\t\tconst paddingTop = Number.parseFloat(computedStyle.paddingTop);\n\t\t\tconsole.log(\n\t\t\t\t\"[CropOverlay] scaled:\",\n\t\t\t\tscaled,\n\t\t\t\t\"paddingLeft:\",\n\t\t\t\tpaddingLeft,\n\t\t\t\t\"paddingTop:\",\n\t\t\t\tpaddingTop,\n\t\t\t\t\"containerRect:\",\n\t\t\t\tcontainer.getBoundingClientRect(),\n\t\t\t);\n\t\t}\n\n\t\t// Update overlay\n\t\t// Adjust for container padding (use unique variable names)\n\t\tlet cropPaddingLeft = 0;\n\t\tlet cropPaddingTop = 0;\n\t\t{\n\t\t\tconst container = this.imageElement.parentNode;\n\t\t\tconst computedStyle = window.getComputedStyle(container);\n\t\t\tcropPaddingLeft = Number.parseFloat(computedStyle.paddingLeft);\n\t\t\tcropPaddingTop = Number.parseFloat(computedStyle.paddingTop);\n\t\t}\n\n\t\tthis.state.cropOverlay.style.left = `${scaled.x + cropPaddingLeft}px`;\n\t\tthis.state.cropOverlay.style.top = `${scaled.y + cropPaddingTop}px`;\n\t\tthis.state.cropOverlay.style.width = `${scaledWidth}px`;\n\t\tthis.state.cropOverlay.style.height = `${scaledHeight}px`;\n\t\tif (this.options.debug) {\n\t\t\tconsole.log(\n\t\t\t\t\"[CropOverlay] style.left:\",\n\t\t\t\tthis.state.cropOverlay.style.left,\n\t\t\t\t\"style.top:\",\n\t\t\t\tthis.state.cropOverlay.style.top,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Enables or disables the focus point.\n\t * If the focus point is at its initial state `{x:0, y:0}` (top-left corner), it will be moved to the center of the image when this method is called with `active = true` for the first time.\n\t * @public\n\t * @param {boolean} active - Activation state\n\t * @returns {VisualImageTool} Instance for chaining\n\t */\n\ttoggleFocusPoint(active) {\n\t\tif (!this.options.focusPoint.enabled) return this;\n\n\t\tconst isActive = active === undefined ? !this.state.focusActive : active;\n\n\t\tif (isActive && !this.state.focusActive) {\n\t\t\t// Enable focus point\n\t\t\tif (!this.state.focusMarker) {\n\t\t\t\tthis._createFocusMarker();\n\t\t\t}\n\n\t\t\t// Position at image center by default if not already set\n\t\t\tif (this.state.focusPoint.x === 0 && this.state.focusPoint.y === 0) {\n\t\t\t\tthis.state.focusPoint = {\n\t\t\t\t\tx: this.state.originalWidth / 2,\n\t\t\t\t\ty: this.state.originalHeight / 2,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tthis._updateFocusMarkerPosition();\n\t\t\tthis.state.focusMarker.style.display = \"block\";\n\t\t\tthis.state.focusActive = true;\n\t\t} else if (!isActive && this.state.focusActive) {\n\t\t\t// Disable focus point\n\t\t\tif (this.state.focusMarker) {\n\t\t\t\tthis.state.focusMarker.style.display = \"none\";\n\t\t\t}\n\t\t\tthis.state.focusActive = false;\n\t\t}\n\n\t\t// Notify change\n\t\tthis._notifyChange();\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Enables or disables the crop zone\n\t * @public\n\t * @param {boolean} active - Activation state\n\t * @returns {VisualImageTool} Instance for chaining\n\t */\n\ttoggleCropZone(active) {\n\t\tif (!this.options.cropZone.enabled) return this;\n\n\t\tconst isActive = active === undefined ? !this.state.cropActive : active;\n\n\t\tif (isActive && !this.state.cropActive) {\n\t\t\t// Enable crop zone\n\t\t\tif (!this.state.cropOverlay) {\n\t\t\t\tthis._createCropOverlay();\n\t\t\t}\n\n\t\t\t// Define a default zone if not already set\n\t\t\tif (this.state.cropZone.width === 0 || this.state.cropZone.height === 0) {\n\t\t\t\tconst defaultWidth = this.state.originalWidth / 2;\n\t\t\t\tconst defaultHeight = this.state.originalHeight / 2;\n\t\t\t\tconst defaultX = (this.state.originalWidth - defaultWidth) / 2;\n\t\t\t\tconst defaultY = (this.state.originalHeight - defaultHeight) / 2;\n\n\t\t\t\tthis.state.cropZone = {\n\t\t\t\t\tx: defaultX,\n\t\t\t\t\ty: defaultY,\n\t\t\t\t\twidth: defaultWidth,\n\t\t\t\t\theight: defaultHeight,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tthis._updateCropOverlayPosition();\n\t\t\tthis.state.cropOverlay.style.display = \"block\";\n\t\t\tthis.state.cropActive = true;\n\t\t} else if (!isActive && this.state.cropActive) {\n\t\t\t// Disable crop zone\n\t\t\tif (this.state.cropOverlay) {\n\t\t\t\tthis.state.cropOverlay.style.display = \"none\";\n\t\t\t}\n\t\t\tthis.state.cropActive = false;\n\t\t}\n\n\t\t// Notify change\n\t\tthis._notifyChange();\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the focus point position\n\t * @public\n\t * @param {number} x - X-coordinate in original pixels\n\t * @param {number} y - Y-coordinate in original pixels\n\t * @returns {VisualImageTool} Instance for chaining\n\t */\n\tsetFocusPoint(x, y) {\n\t\t// Clamp coordinates to image dimensions\n\t\tconst clampedX = Math.max(0, Math.min(x, this.state.originalWidth));\n\t\tconst clampedY = Math.max(0, Math.min(y, this.state.originalHeight));\n\n\t\tthis.state.focusPoint = { x: clampedX, y: clampedY };\n\n\t\tif (this.state.focusActive && this.state.focusMarker) {\n\t\t\tthis._updateFocusMarkerPosition();\n\t\t}\n\n\t\t// Notify change\n\t\tthis._notifyChange();\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the crop zone position and dimensions\n\t * @public\n\t * @param {number} x - X-coordinate in original pixels\n\t * @param {number} y - Y-coordinate in original pixels\n\t * @param {number} width - Width in original pixels\n\t * @param {number} height - Height in original pixels\n\t * @returns {VisualImageTool} Instance for chaining\n\t */\n\tsetCropZone(x, y, width, height) {\n\t\t// Clamp to image dimensions\n\t\tconst clampedX = Math.max(0, Math.min(x, this.state.originalWidth - width));\n\t\tconst clampedY = Math.max(\n\t\t\t0,\n\t\t\tMath.min(y, this.state.originalHeight - height),\n\t\t);\n\t\tconst clampedWidth = Math.max(\n\t\t\t10,\n\t\t\tMath.min(width, this.state.originalWidth - clampedX),\n\t\t);\n\t\tconst clampedHeight = Math.max(\n\t\t\t10,\n\t\t\tMath.min(height, this.state.originalHeight - clampedY),\n\t\t);\n\n\t\tthis.state.cropZone = {\n\t\t\tx: clampedX,\n\t\t\ty: clampedY,\n\t\t\twidth: clampedWidth,\n\t\t\theight: clampedHeight,\n\t\t};\n\n\t\tif (this.state.cropActive && this.state.cropOverlay) {\n\t\t\tthis._updateCropOverlayPosition();\n\t\t}\n\n\t\t// Notify change\n\t\tthis._notifyChange();\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets the current focus point position\n\t * @public\n\t * @returns {Object} Focus point coordinates {x, y}\n\t */\n\tgetFocusPoint() {\n\t\treturn { ...this.state.focusPoint };\n\t}\n\n\t/**\n\t * Gets the current crop zone position and dimensions\n\t * @public\n\t * @returns {Object} Crop zone {x, y, width, height}\n\t */\n\tgetCropZone() {\n\t\treturn { ...this.state.cropZone };\n\t}\n\n\t/**\n\t * Gets the original image dimensions\n\t * @public\n\t * @returns {Object} Dimensions {width, height}\n\t */\n\tgetImageDimensions() {\n\t\treturn {\n\t\t\twidth: this.state.originalWidth,\n\t\t\theight: this.state.originalHeight,\n\t\t};\n\t}\n\n\t/**\n\t * Notifies changes via callback\n\t * @private\n\t */\n\t_notifyChange() {\n\t\tif (typeof this.options.onChange === \"function\") {\n\t\t\tthis.options.onChange({\n\t\t\t\tfocusPoint: this.getFocusPoint(),\n\t\t\t\tcropZone: this.getCropZone(),\n\t\t\t\tfocusActive: this.state.focusActive,\n\t\t\t\tcropActive: this.state.cropActive,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Destroys the instance and cleans up resources\n\t * @public\n\t */\n\tdestroy() {\n\t\t// Already destroyed\n\t\tif (!this.state) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remove element listeners\n\t\tif (this.state.focusMarker) {\n\t\t\tthis.state.focusMarker.removeEventListener(\n\t\t\t\t\"mousedown\",\n\t\t\t\tthis._boundFocusMarkerMouseDown,\n\t\t\t);\n\t\t}\n\n\t\tif (this.state.cropOverlay) {\n\t\t\tthis.state.cropOverlay.removeEventListener(\n\t\t\t\t\"mousedown\",\n\t\t\t\tthis._boundCropOverlayMouseDown,\n\t\t\t);\n\t\t}\n\n\t\tfor (const handle of this.cropHandles) {\n\t\t\thandle.removeEventListener(\"mousedown\", this._boundCropHandleMouseDown);\n\t\t}\n\t\tthis.cropHandles = [];\n\n\t\t// Remove DOM elements\n\t\tif (this.state.focusMarker?.parentNode) {\n\t\t\tthis.state.focusMarker.parentNode.removeChild(this.state.focusMarker);\n\t\t}\n\n\t\tif (this.state.cropOverlay?.parentNode) {\n\t\t\tthis.state.cropOverlay.parentNode.removeChild(this.state.cropOverlay);\n\t\t}\n\n\t\tif (this.spinnerElement?.parentNode) {\n\t\t\tthis.spinnerElement.parentNode.removeChild(this.spinnerElement);\n\t\t}\n\t\tthis.spinnerElement = null;\n\n\t\t// Remove global listeners\n\t\twindow.removeEventListener(\"resize\", this._boundUpdateScaling);\n\t\tdocument.removeEventListener(\"mouseup\", this._boundHandleMouseUp);\n\t\tdocument.removeEventListener(\"mousemove\", this._boundHandleMouseMove);\n\n\t\tif (this.imageElement) {\n\t\t\tthis.imageElement.removeEventListener(\"load\", this._boundUpdateScaling);\n\t\t}\n\n\t\t// Release bound handlers\n\t\tthis._boundUpdateScaling = null;\n\t\tthis._boundHandleMouseUp = null;\n\t\tthis._boundHandleMouseMove = null;\n\t\tthis._boundFocusMarkerMouseDown = null;\n\t\tthis._boundCropOverlayMouseDown = null;\n\t\tthis._boundCropHandleMouseDown = null;\n\n\t\t// Reset state\n\t\tthis.state = null;\n\t\tthis.interaction = null;\n\t\tthis.options = null;\n\t\tthis.imageElement = null;\n\t}\n}\n\n// Export class\nexport default VisualImageTool;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"visual-image-tool.cjs","sources":["../src/visual-image-tool.js"],"sourcesContent":["/**\n * ImageTool - A lightweight tool for defining focus points and crop zones on images\n * @module visual-image-tool\n */\n\nclass VisualImageTool {\n\t/**\n\t * Creates an instance of the image tool.\n\t * The focus point is initialized to `{x:0, y:0}` in `this.state`. When `toggleFocusPoint(true)` is called for the first time, if the focus point is still `{x:0, y:0}`, it will be automatically centered on the image.\n\t * @param {Object} options - Configuration options\n\t * @param {HTMLElement|string} options.imageElement - Image element or CSS selector\n\t * @param {Object} [options.focusPoint] - Focus point configuration\n\t * @param {boolean} [options.focusPoint.enabled=true] - Enable focus point functionality\n\t * @param {Object} [options.focusPoint.style] - Custom styles for the focus point marker\n\t * @param {Object} [options.cropZone] - Crop zone configuration\n\t * @param {boolean} [options.cropZone.enabled=true] - Enable crop zone functionality\n\t * @param {Object} [options.cropZone.style] - Custom styles for the crop overlay\n\t * @param {Function} [options.onChange] - Callback called on changes\n\t */\n\tconstructor(options) {\n\t\t// Validate options\n\t\tif (!options || !options.imageElement) {\n\t\t\tthrow new Error(\"Image element is required\");\n\t\t}\n\n\t\t// Initialize properties\n\t\tthis.imageElement =\n\t\t\ttypeof options.imageElement === \"string\"\n\t\t\t\t? document.querySelector(options.imageElement)\n\t\t\t\t: options.imageElement;\n\n\t\tif (!this.imageElement || this.imageElement.tagName !== \"IMG\") {\n\t\t\tthrow new Error(\"Invalid image element\");\n\t\t}\n\n\t\t// Default options\n\t\tthis.options = {\n\t\t\tfocusPoint: {\n\t\t\t\tenabled: true,\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: \"30px\",\n\t\t\t\t\theight: \"30px\",\n\t\t\t\t\tborder: \"3px solid white\",\n\t\t\t\t\tboxShadow: \"0 0 0 2px black, 0 0 5px rgba(0,0,0,0.5)\",\n\t\t\t\t\tbackgroundColor: \"rgba(255, 0, 0, 0.5)\",\n\t\t\t\t},\n\t\t\t\t...options.focusPoint,\n\t\t\t},\n\t\t\tcropZone: {\n\t\t\t\tenabled: true,\n\t\t\t\tstyle: {\n\t\t\t\t\tborder: \"1px dashed #fff\",\n\t\t\t\t\tbackgroundColor: \"rgba(0, 0, 0, 0.4)\",\n\t\t\t\t},\n\t\t\t\thandleStyle: {\n\t\t\t\t\twidth: \"14px\",\n\t\t\t\t\theight: \"14px\",\n\t\t\t\t\tbackgroundColor: \"white\",\n\t\t\t\t\tborder: \"2px solid black\",\n\t\t\t\t\tboxShadow: \"0 0 3px rgba(0,0,0,0.5)\",\n\t\t\t\t},\n\t\t\t\t...options.cropZone,\n\t\t\t},\n\t\t\tonChange: options.onChange || (() => {}),\n\t\t\tdebug: options.debug || false,\n\t\t};\n\n\t\t// Internal state\n\t\tthis.state = {\n\t\t\tfocusMarker: null,\n\t\t\tcropOverlay: null,\n\t\t\tfocusActive: false,\n\t\t\tcropActive: false,\n\t\t\tfocusPoint: { x: 0, y: 0 },\n\t\t\tcropZone: { x: 0, y: 0, width: 0, height: 0 },\n\t\t\toriginalWidth: 1,\n\t\t\toriginalHeight: 1,\n\t\t\tdisplayWidth: 1,\n\t\t\tdisplayHeight: 1,\n\t\t\tscaleX: 1,\n\t\t\tscaleY: 1,\n\t\t};\n\n\t\t// Handlers are bound once here: addEventListener and removeEventListener\n\t\t// must be handed the same function reference for removal to work.\n\t\tthis._boundUpdateScaling = this._updateScaling.bind(this);\n\t\tthis._boundHandleMouseUp = this._handleMouseUp.bind(this);\n\t\tthis._boundHandleMouseMove = this._handleMouseMove.bind(this);\n\t\tthis._boundFocusMarkerMouseDown =\n\t\t\tthis._handleFocusMarkerMouseDown.bind(this);\n\t\tthis._boundCropOverlayMouseDown =\n\t\t\tthis._handleCropOverlayMouseDown.bind(this);\n\t\tthis._boundCropHandleMouseDown = this._handleCropHandleMouseDown.bind(this);\n\n\t\t// Resize handles, tracked so their listeners can be removed on destroy\n\t\tthis.cropHandles = [];\n\n\t\t// Variables for tracking interactions\n\t\tthis.interaction = {\n\t\t\tfocusDragging: false,\n\t\t\tfocusDragOffsetX: 0,\n\t\t\tfocusDragOffsetY: 0,\n\t\t\tcropDragging: false,\n\t\t\tcropResizing: false,\n\t\t\tactiveHandle: null,\n\t\t\tstartX: 0,\n\t\t\tstartY: 0,\n\t\t\tstartWidth: 0,\n\t\t\tstartHeight: 0,\n\t\t\tstartMouseX: 0,\n\t\t\tstartMouseY: 0,\n\t\t};\n\n\t\tthis.spinnerElement = null;\n\t\tthis.initialLoadComplete = false;\n\n\t\t// Initialize the tool\n\t\tthis._init();\n\t}\n\n\t/**\n\t * Initializes the image tool\n\t * @private\n\t */\n\t_init() {\n\t\t// Prepare the parent container\n\t\tthis._prepareContainer();\n\n\t\t// Initialize dimensions\n\t\tthis._updateScaling();\n\n\t\t// Create UI elements if enabled\n\t\tif (this.options.focusPoint.enabled) {\n\t\t\tthis._createFocusMarker();\n\t\t}\n\n\t\tif (this.options.cropZone.enabled) {\n\t\t\tthis._createCropOverlay();\n\t\t}\n\n\t\t// Add event listeners\n\t\tthis._setupEventListeners();\n\t}\n\n\t/**\n\t * Prepares the image's parent container\n\t * @private\n\t */\n\t_prepareContainer() {\n\t\t// Ensure the parent is positioned\n\t\tif (this.imageElement.parentNode) {\n\t\t\tthis.imageElement.parentNode.style.position = \"relative\";\n\n\t\t\t// Create spinner element\n\t\t\tthis.spinnerElement = document.createElement(\"div\");\n\t\t\tthis.spinnerElement.style.position = \"absolute\";\n\t\t\tthis.spinnerElement.style.top = \"50%\";\n\t\t\tthis.spinnerElement.style.left = \"50%\";\n\t\t\tthis.spinnerElement.style.transform = \"translate(-50%, -50%)\";\n\t\t\tthis.spinnerElement.style.width = \"40px\";\n\t\t\tthis.spinnerElement.style.height = \"40px\";\n\t\t\tthis.spinnerElement.style.border = \"4px solid #f3f3f3\"; // Light grey\n\t\t\tthis.spinnerElement.style.borderTop = \"4px solid #3498db\"; // Blue\n\t\t\tthis.spinnerElement.style.borderRadius = \"50%\";\n\t\t\tthis.spinnerElement.style.boxSizing = \"border-box\";\n\t\t\tthis.spinnerElement.style.zIndex = \"1000\"; // Ensure it's above other elements\n\t\t\tthis.spinnerElement.style.display = \"block\"; // Initially visible\n\t\t\tthis.spinnerElement.style.animation =\n\t\t\t\t\"visual-image-tool-spin 1s linear infinite\";\n\n\t\t\tthis.imageElement.parentNode.appendChild(this.spinnerElement);\n\n\t\t\t// Add CSS keyframes for spinner animation.\n\t\t\t//\n\t\t\t// The animation name is namespaced: keyframes are global to the\n\t\t\t// document, so a bare name like `spin` would collide with one\n\t\t\t// defined by the host page, and whichever stylesheet was injected\n\t\t\t// last would silently win.\n\t\t\t//\n\t\t\t// This stylesheet is shared by every instance and deliberately\n\t\t\t// outlives destroy(): removing it would break the animation for\n\t\t\t// any instance still alive. The id guard keeps it to one element.\n\t\t\tif (!document.getElementById(\"visual-image-tool-spinner-styles\")) {\n\t\t\t\tconst styleElement = document.createElement(\"style\");\n\t\t\t\tstyleElement.id = \"visual-image-tool-spinner-styles\";\n\t\t\t\tstyleElement.innerHTML = `\n@keyframes visual-image-tool-spin {\n 0% { transform: translate(-50%, -50%) rotate(0deg); }\n 100% { transform: translate(-50%, -50%) rotate(360deg); }\n}\n `;\n\t\t\t\tdocument.head.appendChild(styleElement);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Updates scaling factors\n\t * @private\n\t */\n\t_updateScaling() {\n\t\tthis.state.originalWidth = this.imageElement.naturalWidth || 1;\n\t\tthis.state.originalHeight = this.imageElement.naturalHeight || 1;\n\n\t\t// Hide spinner once image is loaded and dimensions are available\n\t\tif (\n\t\t\t!this.initialLoadComplete &&\n\t\t\tthis.spinnerElement &&\n\t\t\tthis.state.originalWidth > 1 &&\n\t\t\tthis.state.originalHeight > 1\n\t\t) {\n\t\t\tthis.spinnerElement.style.display = \"none\";\n\t\t\tthis.initialLoadComplete = true;\n\t\t}\n\t\tthis.state.displayWidth = this.imageElement.offsetWidth;\n\t\tthis.state.displayHeight = this.imageElement.offsetHeight;\n\t\tthis.state.scaleX = this.state.displayWidth / this.state.originalWidth;\n\t\tthis.state.scaleY = this.state.displayHeight / this.state.originalHeight;\n\n\t\t// Update spinner position during initial load if still visible\n\t\tif (!this.initialLoadComplete && this.spinnerElement) {\n\t\t\tthis.spinnerElement.style.top = `${this.state.displayHeight / 2}px`;\n\t\t\tthis.spinnerElement.style.left = `${this.state.displayWidth / 2}px`;\n\t\t}\n\n\t\t// Reposition elements if active\n\t\tif (this.state.focusActive) {\n\t\t\tthis._updateFocusMarkerPosition();\n\t\t}\n\n\t\tif (this.state.cropActive) {\n\t\t\tthis._updateCropOverlayPosition();\n\t\t}\n\t}\n\n\t/**\n\t * Converts display coordinates to original coordinates\n\t * @private\n\t * @param {number} scaledX - X-coordinate at display scale\n\t * @param {number} scaledY - Y-coordinate at display scale\n\t * @returns {Object} Original coordinates {x, y}\n\t */\n\t_toOriginalCoords(scaledX, scaledY) {\n\t\treturn {\n\t\t\tx: scaledX / this.state.scaleX,\n\t\t\ty: scaledY / this.state.scaleY,\n\t\t};\n\t}\n\n\t/**\n\t * Converts original coordinates to display coordinates\n\t * @private\n\t * @param {number} originalX - Original X-coordinate\n\t * @param {number} originalY - Original Y-coordinate\n\t * @returns {Object} Display scale coordinates {x, y}\n\t */\n\t_toScaledCoords(originalX, originalY) {\n\t\treturn {\n\t\t\tx: originalX * this.state.scaleX,\n\t\t\ty: originalY * this.state.scaleY,\n\t\t};\n\t}\n\n\t/**\n\t * Creates the focus point marker\n\t * @private\n\t */\n\t_createFocusMarker() {\n\t\tif (this.state.focusMarker) return;\n\n\t\tconst marker = document.createElement(\"div\");\n\t\tmarker.style.position = \"absolute\";\n\t\tmarker.style.width = this.options.focusPoint.style.width;\n\t\tmarker.style.height = this.options.focusPoint.style.height;\n\t\tmarker.style.border = this.options.focusPoint.style.border;\n\t\tmarker.style.boxShadow = this.options.focusPoint.style.boxShadow;\n\t\tmarker.style.backgroundColor =\n\t\t\tthis.options.focusPoint.style.backgroundColor;\n\t\tmarker.style.cursor = \"move\";\n\t\tmarker.style.display = \"none\";\n\t\tmarker.style.zIndex = \"999\";\n\t\tmarker.style.clipPath =\n\t\t\t\"polygon(40% 0%, 60% 0%, 60% 40%, 100% 40%, 100% 60%, 60% 60%, 60% 100%, 40% 100%, 40% 60%, 0% 60%, 0% 40%, 40% 40%)\";\n\n\t\tthis.imageElement.parentNode.appendChild(marker);\n\t\tthis.state.focusMarker = marker;\n\n\t\t// Add event listeners to the marker\n\t\tmarker.addEventListener(\"mousedown\", this._boundFocusMarkerMouseDown);\n\t}\n\n\t/**\n\t * Handles mousedown event on the focus point marker\n\t * @private\n\t * @param {MouseEvent} e - Mousedown event\n\t */\n\t_handleFocusMarkerMouseDown(e) {\n\t\tthis.interaction.focusDragging = true;\n\t\tthis.state.focusMarker.style.cursor = \"grabbing\";\n\n\t\t// Calculate offset from marker center\n\t\tconst rect = this.state.focusMarker.getBoundingClientRect();\n\t\tthis.interaction.focusDragOffsetX =\n\t\t\te.clientX - (rect.left + rect.width / 2);\n\t\tthis.interaction.focusDragOffsetY =\n\t\t\te.clientY - (rect.top + rect.height / 2);\n\n\t\te.preventDefault();\n\t}\n\n\t/**\n\t * Creates the crop zone overlay\n\t * @private\n\t */\n\t_createCropOverlay() {\n\t\tif (this.state.cropOverlay) return;\n\n\t\tconst overlay = document.createElement(\"div\");\n\t\toverlay.style.position = \"absolute\";\n\t\toverlay.style.border = this.options.cropZone.style.border;\n\t\toverlay.style.backgroundColor = this.options.cropZone.style.backgroundColor;\n\t\toverlay.style.boxSizing = \"border-box\";\n\t\toverlay.style.cursor = \"move\";\n\t\toverlay.style.display = \"none\";\n\t\toverlay.style.zIndex = \"998\";\n\n\t\t// Add resize handles\n\t\tconst handles = [\"tl\", \"tm\", \"tr\", \"ml\", \"mr\", \"bl\", \"bm\", \"br\"];\n\t\tfor (const handleType of handles) {\n\t\t\tconst handle = document.createElement(\"div\");\n\t\t\thandle.style.position = \"absolute\";\n\t\t\thandle.style.width = this.options.cropZone.handleStyle.width;\n\t\t\thandle.style.height = this.options.cropZone.handleStyle.height;\n\t\t\thandle.style.backgroundColor =\n\t\t\t\tthis.options.cropZone.handleStyle.backgroundColor;\n\t\t\thandle.style.border = this.options.cropZone.handleStyle.border;\n\t\t\thandle.style.boxShadow = this.options.cropZone.handleStyle.boxShadow;\n\t\t\thandle.style.boxSizing = \"border-box\";\n\t\t\thandle.dataset.handle = handleType;\n\n\t\t\t// Position the handle\n\t\t\tswitch (handleType) {\n\t\t\t\tcase \"tl\": // Top-left\n\t\t\t\t\thandle.style.top = \"-7px\";\n\t\t\t\t\thandle.style.left = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"nwse-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"tm\": // Top-middle\n\t\t\t\t\thandle.style.top = \"-7px\";\n\t\t\t\t\thandle.style.left = \"50%\";\n\t\t\t\t\thandle.style.marginLeft = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"ns-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"tr\": // Top-right\n\t\t\t\t\thandle.style.top = \"-7px\";\n\t\t\t\t\thandle.style.right = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"nesw-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"ml\": // Middle-left\n\t\t\t\t\thandle.style.top = \"50%\";\n\t\t\t\t\thandle.style.left = \"-7px\";\n\t\t\t\t\thandle.style.marginTop = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"ew-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"mr\": // Middle-right\n\t\t\t\t\thandle.style.top = \"50%\";\n\t\t\t\t\thandle.style.right = \"-7px\";\n\t\t\t\t\thandle.style.marginTop = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"ew-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"bl\": // Bottom-left\n\t\t\t\t\thandle.style.bottom = \"-7px\";\n\t\t\t\t\thandle.style.left = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"nesw-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"bm\": // Bottom-middle\n\t\t\t\t\thandle.style.bottom = \"-7px\";\n\t\t\t\t\thandle.style.left = \"50%\";\n\t\t\t\t\thandle.style.marginLeft = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"ns-resize\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"br\": // Bottom-right\n\t\t\t\t\thandle.style.bottom = \"-7px\";\n\t\t\t\t\thandle.style.right = \"-7px\";\n\t\t\t\t\thandle.style.cursor = \"nwse-resize\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Add event listener\n\t\t\thandle.addEventListener(\"mousedown\", this._boundCropHandleMouseDown);\n\n\t\t\toverlay.appendChild(handle);\n\t\t\tthis.cropHandles.push(handle);\n\t\t}\n\n\t\t// Add listener for overlay dragging\n\t\toverlay.addEventListener(\"mousedown\", this._boundCropOverlayMouseDown);\n\n\t\tthis.imageElement.parentNode.appendChild(overlay);\n\t\tthis.state.cropOverlay = overlay;\n\t}\n\n\t/**\n\t * Handles mousedown event on a resize handle\n\t * @private\n\t * @param {MouseEvent} e - Mousedown event\n\t */\n\t_handleCropHandleMouseDown(e) {\n\t\tconst handleType = e.currentTarget.dataset.handle;\n\n\t\tthis.interaction.cropResizing = true;\n\t\tthis.interaction.activeHandle = handleType;\n\n\t\t// Record initial dimensions and position\n\t\tthis.interaction.startX =\n\t\t\tNumber.parseInt(this.state.cropOverlay.style.left, 10) || 0;\n\t\tthis.interaction.startY =\n\t\t\tNumber.parseInt(this.state.cropOverlay.style.top, 10) || 0;\n\t\tthis.interaction.startWidth = this.state.cropOverlay.offsetWidth;\n\t\tthis.interaction.startHeight = this.state.cropOverlay.offsetHeight;\n\t\tthis.interaction.startMouseX = e.clientX;\n\t\tthis.interaction.startMouseY = e.clientY;\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t}\n\n\t/**\n\t * Handles mousedown event on the crop overlay\n\t * @private\n\t * @param {MouseEvent} e - Mousedown event\n\t */\n\t_handleCropOverlayMouseDown(e) {\n\t\t// Ignore if clicking on a handle\n\t\tif (e.target !== this.state.cropOverlay) return;\n\n\t\tthis.interaction.cropDragging = true;\n\t\tthis.state.cropOverlay.style.cursor = \"grabbing\";\n\n\t\t// Record initial position\n\t\tthis.interaction.startX =\n\t\t\tNumber.parseInt(this.state.cropOverlay.style.left, 10) || 0;\n\t\tthis.interaction.startY =\n\t\t\tNumber.parseInt(this.state.cropOverlay.style.top, 10) || 0;\n\t\tthis.interaction.startMouseX = e.clientX;\n\t\tthis.interaction.startMouseY = e.clientY;\n\n\t\te.preventDefault();\n\t}\n\n\t/**\n\t * Sets up global event listeners\n\t * @private\n\t */\n\t_setupEventListeners() {\n\t\t// Listener for window resize\n\t\twindow.addEventListener(\"resize\", this._boundUpdateScaling);\n\n\t\t// Listener for image load\n\t\tif (!this.imageElement.complete) {\n\t\t\tthis.imageElement.addEventListener(\"load\", this._boundUpdateScaling);\n\t\t}\n\n\t\t// Listeners for mouse interactions\n\t\tdocument.addEventListener(\"mouseup\", this._boundHandleMouseUp);\n\t\tdocument.addEventListener(\"mousemove\", this._boundHandleMouseMove);\n\t}\n\n\t/**\n\t * Handles global mouseup event\n\t * @private\n\t */\n\t_handleMouseUp() {\n\t\tif (this.interaction.focusDragging) {\n\t\t\tthis.interaction.focusDragging = false;\n\t\t\tif (this.state.focusMarker) this.state.focusMarker.style.cursor = \"move\";\n\t\t}\n\n\t\tif (this.interaction.cropDragging) {\n\t\t\tthis.interaction.cropDragging = false;\n\t\t\tif (this.state.cropOverlay) this.state.cropOverlay.style.cursor = \"move\";\n\t\t}\n\n\t\tthis.interaction.cropResizing = false;\n\t\tthis.interaction.activeHandle = null;\n\t\tdocument.body.style.cursor = \"default\";\n\t}\n\n\t/**\n\t * Handles global mousemove event\n\t * @private\n\t * @param {MouseEvent} e - Mousemove event\n\t */\n\t_handleMouseMove(e) {\n\t\t// Handle focus point dragging\n\t\tif (this.interaction.focusDragging && this.state.focusMarker) {\n\t\t\tthis._handleFocusMarkerDrag(e);\n\t\t}\n\n\t\t// Handle crop zone dragging\n\t\tif (this.interaction.cropDragging) {\n\t\t\tthis._handleCropOverlayDrag(e);\n\t\t}\n\n\t\t// Handle crop zone resizing\n\t\tif (this.interaction.cropResizing) {\n\t\t\tthis._handleCropOverlayResize(e);\n\t\t}\n\t}\n\n\t/**\n\t * Handles focus point marker drag\n\t * @private\n\t * @param {MouseEvent} e - Mousemove event\n\t */\n\t_handleFocusMarkerDrag(e) {\n\t\tconst imageRect = this.imageElement.getBoundingClientRect();\n\n\t\t// Calculate target position relative to the image\n\t\tconst targetScaledX =\n\t\t\te.clientX - imageRect.left - this.interaction.focusDragOffsetX;\n\t\tconst targetScaledY =\n\t\t\te.clientY - imageRect.top - this.interaction.focusDragOffsetY;\n\n\t\t// Convert to original coordinates\n\t\tconst original = this._toOriginalCoords(targetScaledX, targetScaledY);\n\n\t\t// Update focus point\n\t\tthis.setFocusPoint(original.x, original.y);\n\t}\n\n\t/**\n\t * Handles crop overlay drag\n\t * @private\n\t * @param {MouseEvent} e - Mousemove event\n\t */\n\t_handleCropOverlayDrag(e) {\n\t\tconst deltaX = e.clientX - this.interaction.startMouseX;\n\t\tconst deltaY = e.clientY - this.interaction.startMouseY;\n\n\t\t// Calculate new position in display pixels\n\t\tconst newX = this.interaction.startX + deltaX;\n\t\tconst newY = this.interaction.startY + deltaY;\n\n\t\t// Convert to original coordinates\n\t\tconst original = this._toOriginalCoords(newX, newY);\n\n\t\t// Get current dimensions in original coordinates\n\t\tconst { width, height } = this.state.cropZone;\n\n\t\t// Update crop zone\n\t\tthis.setCropZone(original.x, original.y, width, height);\n\t}\n\n\t/**\n\t * Handles crop overlay resize\n\t * @private\n\t * @param {MouseEvent} e - Mousemove event\n\t */\n\t_handleCropOverlayResize(e) {\n\t\tif (!this.interaction.activeHandle) return;\n\n\t\tconst deltaX = e.clientX - this.interaction.startMouseX;\n\t\tconst deltaY = e.clientY - this.interaction.startMouseY;\n\n\t\tlet newX = this.interaction.startX;\n\t\tlet newY = this.interaction.startY;\n\t\tlet newWidth = this.interaction.startWidth;\n\t\tlet newHeight = this.interaction.startHeight;\n\n\t\t// Adjust based on active handle\n\t\tif (this.interaction.activeHandle.includes(\"t\")) {\n\t\t\t// Top\n\t\t\tnewY = this.interaction.startY + deltaY;\n\t\t\tnewHeight = this.interaction.startHeight - deltaY;\n\t\t}\n\t\tif (this.interaction.activeHandle.includes(\"b\")) {\n\t\t\t// Bottom\n\t\t\tnewHeight = this.interaction.startHeight + deltaY;\n\t\t}\n\t\tif (this.interaction.activeHandle.includes(\"l\")) {\n\t\t\t// Left\n\t\t\tnewX = this.interaction.startX + deltaX;\n\t\t\tnewWidth = this.interaction.startWidth - deltaX;\n\t\t}\n\t\tif (this.interaction.activeHandle.includes(\"r\")) {\n\t\t\t// Right\n\t\t\tnewWidth = this.interaction.startWidth + deltaX;\n\t\t}\n\n\t\t// Prevent negative dimensions\n\t\tif (newWidth < 10) {\n\t\t\tif (this.interaction.activeHandle.includes(\"l\")) {\n\t\t\t\tnewX = this.interaction.startX + this.interaction.startWidth - 10;\n\t\t\t}\n\t\t\tnewWidth = 10;\n\t\t}\n\t\tif (newHeight < 10) {\n\t\t\tif (this.interaction.activeHandle.includes(\"t\")) {\n\t\t\t\tnewY = this.interaction.startY + this.interaction.startHeight - 10;\n\t\t\t}\n\t\t\tnewHeight = 10;\n\t\t}\n\n\t\t// Convert display coordinates to original coordinates\n\t\tconst originalX = newX / this.state.scaleX;\n\t\tconst originalY = newY / this.state.scaleY;\n\t\tconst originalWidth = newWidth / this.state.scaleX;\n\t\tconst originalHeight = newHeight / this.state.scaleY;\n\n\t\t// Update crop zone\n\t\tthis.setCropZone(originalX, originalY, originalWidth, originalHeight);\n\t}\n\n\t/**\n\t * Updates the focus point marker position\n\t * @private\n\t */\n\t_updateFocusMarkerPosition() {\n\t\tif (!this.state.focusMarker) return;\n\n\t\tconst { x, y } = this.state.focusPoint;\n\n\t\t// Clamp coordinates to image dimensions\n\t\tconst clampedX = Math.max(0, Math.min(x, this.state.originalWidth));\n\t\tconst clampedY = Math.max(0, Math.min(y, this.state.originalHeight));\n\n\t\t// Update state if coordinates were clamped\n\t\tif (x !== clampedX || y !== clampedY) {\n\t\t\tthis.state.focusPoint = { x: clampedX, y: clampedY };\n\t\t}\n\n\t\tconst scaled = this._toScaledCoords(clampedX, clampedY);\n\n\t\t// LOGGING: Validate padding offset\n\t\tif (this.options.debug) {\n\t\t\tconst container = this.imageElement.parentNode;\n\t\t\tconst computedStyle = window.getComputedStyle(container);\n\t\t\tconst paddingLeft = Number.parseFloat(computedStyle.paddingLeft);\n\t\t\tconst paddingTop = Number.parseFloat(computedStyle.paddingTop);\n\t\t\tconsole.log(\n\t\t\t\t\"[FocusMarker] scaled:\",\n\t\t\t\tscaled,\n\t\t\t\t\"paddingLeft:\",\n\t\t\t\tpaddingLeft,\n\t\t\t\t\"paddingTop:\",\n\t\t\t\tpaddingTop,\n\t\t\t\t\"containerRect:\",\n\t\t\t\tcontainer.getBoundingClientRect(),\n\t\t\t);\n\t\t}\n\n\t\t// Adjust to center the marker\n\t\t// Adjust for container padding (use unique variable names)\n\t\tlet focusPaddingLeft = 0;\n\t\tlet focusPaddingTop = 0;\n\t\t{\n\t\t\tconst container = this.imageElement.parentNode;\n\t\t\tconst computedStyle = window.getComputedStyle(container);\n\t\t\tfocusPaddingLeft = Number.parseFloat(computedStyle.paddingLeft);\n\t\t\tfocusPaddingTop = Number.parseFloat(computedStyle.paddingTop);\n\t\t}\n\n\t\tthis.state.focusMarker.style.left = `${\n\t\t\tscaled.x + focusPaddingLeft - this.state.focusMarker.offsetWidth / 2\n\t\t}px`;\n\t\tthis.state.focusMarker.style.top = `${\n\t\t\tscaled.y + focusPaddingTop - this.state.focusMarker.offsetHeight / 2\n\t\t}px`;\n\t\tif (this.options.debug) {\n\t\t\tconsole.log(\n\t\t\t\t\"[FocusMarker] style.left:\",\n\t\t\t\tthis.state.focusMarker.style.left,\n\t\t\t\t\"style.top:\",\n\t\t\t\tthis.state.focusMarker.style.top,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Updates the crop overlay position and dimensions\n\t * @private\n\t */\n\t_updateCropOverlayPosition() {\n\t\tif (!this.state.cropOverlay) return;\n\n\t\tconst { x, y, width, height } = this.state.cropZone;\n\n\t\t// Clamp to image dimensions\n\t\tconst clampedX = Math.max(0, Math.min(x, this.state.originalWidth - width));\n\t\tconst clampedY = Math.max(\n\t\t\t0,\n\t\t\tMath.min(y, this.state.originalHeight - height),\n\t\t);\n\t\tconst clampedWidth = Math.max(\n\t\t\t10,\n\t\t\tMath.min(width, this.state.originalWidth - clampedX),\n\t\t);\n\t\tconst clampedHeight = Math.max(\n\t\t\t10,\n\t\t\tMath.min(height, this.state.originalHeight - clampedY),\n\t\t);\n\n\t\t// Update state if values were clamped\n\t\tif (\n\t\t\tx !== clampedX ||\n\t\t\ty !== clampedY ||\n\t\t\twidth !== clampedWidth ||\n\t\t\theight !== clampedHeight\n\t\t) {\n\t\t\tthis.state.cropZone = {\n\t\t\t\tx: clampedX,\n\t\t\t\ty: clampedY,\n\t\t\t\twidth: clampedWidth,\n\t\t\t\theight: clampedHeight,\n\t\t\t};\n\t\t}\n\n\t\t// Convert to display coordinates\n\t\tconst scaled = this._toScaledCoords(clampedX, clampedY);\n\t\tconst scaledWidth = clampedWidth * this.state.scaleX;\n\t\tconst scaledHeight = clampedHeight * this.state.scaleY;\n\n\t\t// LOGGING: Validate padding offset\n\t\tif (this.options.debug) {\n\t\t\tconst container = this.imageElement.parentNode;\n\t\t\tconst computedStyle = window.getComputedStyle(container);\n\t\t\tconst paddingLeft = Number.parseFloat(computedStyle.paddingLeft);\n\t\t\tconst paddingTop = Number.parseFloat(computedStyle.paddingTop);\n\t\t\tconsole.log(\n\t\t\t\t\"[CropOverlay] scaled:\",\n\t\t\t\tscaled,\n\t\t\t\t\"paddingLeft:\",\n\t\t\t\tpaddingLeft,\n\t\t\t\t\"paddingTop:\",\n\t\t\t\tpaddingTop,\n\t\t\t\t\"containerRect:\",\n\t\t\t\tcontainer.getBoundingClientRect(),\n\t\t\t);\n\t\t}\n\n\t\t// Update overlay\n\t\t// Adjust for container padding (use unique variable names)\n\t\tlet cropPaddingLeft = 0;\n\t\tlet cropPaddingTop = 0;\n\t\t{\n\t\t\tconst container = this.imageElement.parentNode;\n\t\t\tconst computedStyle = window.getComputedStyle(container);\n\t\t\tcropPaddingLeft = Number.parseFloat(computedStyle.paddingLeft);\n\t\t\tcropPaddingTop = Number.parseFloat(computedStyle.paddingTop);\n\t\t}\n\n\t\tthis.state.cropOverlay.style.left = `${scaled.x + cropPaddingLeft}px`;\n\t\tthis.state.cropOverlay.style.top = `${scaled.y + cropPaddingTop}px`;\n\t\tthis.state.cropOverlay.style.width = `${scaledWidth}px`;\n\t\tthis.state.cropOverlay.style.height = `${scaledHeight}px`;\n\t\tif (this.options.debug) {\n\t\t\tconsole.log(\n\t\t\t\t\"[CropOverlay] style.left:\",\n\t\t\t\tthis.state.cropOverlay.style.left,\n\t\t\t\t\"style.top:\",\n\t\t\t\tthis.state.cropOverlay.style.top,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Enables or disables the focus point.\n\t * If the focus point is at its initial state `{x:0, y:0}` (top-left corner), it will be moved to the center of the image when this method is called with `active = true` for the first time.\n\t * @public\n\t * @param {boolean} active - Activation state\n\t * @returns {VisualImageTool} Instance for chaining\n\t */\n\ttoggleFocusPoint(active) {\n\t\tif (!this.options.focusPoint.enabled) return this;\n\n\t\tconst isActive = active === undefined ? !this.state.focusActive : active;\n\n\t\tif (isActive && !this.state.focusActive) {\n\t\t\t// Enable focus point\n\t\t\tif (!this.state.focusMarker) {\n\t\t\t\tthis._createFocusMarker();\n\t\t\t}\n\n\t\t\t// Position at image center by default if not already set\n\t\t\tif (this.state.focusPoint.x === 0 && this.state.focusPoint.y === 0) {\n\t\t\t\tthis.state.focusPoint = {\n\t\t\t\t\tx: this.state.originalWidth / 2,\n\t\t\t\t\ty: this.state.originalHeight / 2,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tthis._updateFocusMarkerPosition();\n\t\t\tthis.state.focusMarker.style.display = \"block\";\n\t\t\tthis.state.focusActive = true;\n\t\t} else if (!isActive && this.state.focusActive) {\n\t\t\t// Disable focus point\n\t\t\tif (this.state.focusMarker) {\n\t\t\t\tthis.state.focusMarker.style.display = \"none\";\n\t\t\t}\n\t\t\tthis.state.focusActive = false;\n\t\t}\n\n\t\t// Notify change\n\t\tthis._notifyChange();\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Enables or disables the crop zone\n\t * @public\n\t * @param {boolean} active - Activation state\n\t * @returns {VisualImageTool} Instance for chaining\n\t */\n\ttoggleCropZone(active) {\n\t\tif (!this.options.cropZone.enabled) return this;\n\n\t\tconst isActive = active === undefined ? !this.state.cropActive : active;\n\n\t\tif (isActive && !this.state.cropActive) {\n\t\t\t// Enable crop zone\n\t\t\tif (!this.state.cropOverlay) {\n\t\t\t\tthis._createCropOverlay();\n\t\t\t}\n\n\t\t\t// Define a default zone if not already set\n\t\t\tif (this.state.cropZone.width === 0 || this.state.cropZone.height === 0) {\n\t\t\t\tconst defaultWidth = this.state.originalWidth / 2;\n\t\t\t\tconst defaultHeight = this.state.originalHeight / 2;\n\t\t\t\tconst defaultX = (this.state.originalWidth - defaultWidth) / 2;\n\t\t\t\tconst defaultY = (this.state.originalHeight - defaultHeight) / 2;\n\n\t\t\t\tthis.state.cropZone = {\n\t\t\t\t\tx: defaultX,\n\t\t\t\t\ty: defaultY,\n\t\t\t\t\twidth: defaultWidth,\n\t\t\t\t\theight: defaultHeight,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tthis._updateCropOverlayPosition();\n\t\t\tthis.state.cropOverlay.style.display = \"block\";\n\t\t\tthis.state.cropActive = true;\n\t\t} else if (!isActive && this.state.cropActive) {\n\t\t\t// Disable crop zone\n\t\t\tif (this.state.cropOverlay) {\n\t\t\t\tthis.state.cropOverlay.style.display = \"none\";\n\t\t\t}\n\t\t\tthis.state.cropActive = false;\n\t\t}\n\n\t\t// Notify change\n\t\tthis._notifyChange();\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the focus point position\n\t * @public\n\t * @param {number} x - X-coordinate in original pixels\n\t * @param {number} y - Y-coordinate in original pixels\n\t * @returns {VisualImageTool} Instance for chaining\n\t */\n\tsetFocusPoint(x, y) {\n\t\t// Clamp coordinates to image dimensions\n\t\tconst clampedX = Math.max(0, Math.min(x, this.state.originalWidth));\n\t\tconst clampedY = Math.max(0, Math.min(y, this.state.originalHeight));\n\n\t\tthis.state.focusPoint = { x: clampedX, y: clampedY };\n\n\t\tif (this.state.focusActive && this.state.focusMarker) {\n\t\t\tthis._updateFocusMarkerPosition();\n\t\t}\n\n\t\t// Notify change\n\t\tthis._notifyChange();\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the crop zone position and dimensions\n\t * @public\n\t * @param {number} x - X-coordinate in original pixels\n\t * @param {number} y - Y-coordinate in original pixels\n\t * @param {number} width - Width in original pixels\n\t * @param {number} height - Height in original pixels\n\t * @returns {VisualImageTool} Instance for chaining\n\t */\n\tsetCropZone(x, y, width, height) {\n\t\t// Clamp to image dimensions\n\t\tconst clampedX = Math.max(0, Math.min(x, this.state.originalWidth - width));\n\t\tconst clampedY = Math.max(\n\t\t\t0,\n\t\t\tMath.min(y, this.state.originalHeight - height),\n\t\t);\n\t\tconst clampedWidth = Math.max(\n\t\t\t10,\n\t\t\tMath.min(width, this.state.originalWidth - clampedX),\n\t\t);\n\t\tconst clampedHeight = Math.max(\n\t\t\t10,\n\t\t\tMath.min(height, this.state.originalHeight - clampedY),\n\t\t);\n\n\t\tthis.state.cropZone = {\n\t\t\tx: clampedX,\n\t\t\ty: clampedY,\n\t\t\twidth: clampedWidth,\n\t\t\theight: clampedHeight,\n\t\t};\n\n\t\tif (this.state.cropActive && this.state.cropOverlay) {\n\t\t\tthis._updateCropOverlayPosition();\n\t\t}\n\n\t\t// Notify change\n\t\tthis._notifyChange();\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets the current focus point position\n\t * @public\n\t * @returns {Object} Focus point coordinates {x, y}\n\t */\n\tgetFocusPoint() {\n\t\treturn { ...this.state.focusPoint };\n\t}\n\n\t/**\n\t * Gets the current crop zone position and dimensions\n\t * @public\n\t * @returns {Object} Crop zone {x, y, width, height}\n\t */\n\tgetCropZone() {\n\t\treturn { ...this.state.cropZone };\n\t}\n\n\t/**\n\t * Gets the original image dimensions\n\t * @public\n\t * @returns {Object} Dimensions {width, height}\n\t */\n\tgetImageDimensions() {\n\t\treturn {\n\t\t\twidth: this.state.originalWidth,\n\t\t\theight: this.state.originalHeight,\n\t\t};\n\t}\n\n\t/**\n\t * Notifies changes via callback\n\t * @private\n\t */\n\t_notifyChange() {\n\t\tif (typeof this.options.onChange === \"function\") {\n\t\t\tthis.options.onChange({\n\t\t\t\tfocusPoint: this.getFocusPoint(),\n\t\t\t\tcropZone: this.getCropZone(),\n\t\t\t\tfocusActive: this.state.focusActive,\n\t\t\t\tcropActive: this.state.cropActive,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Destroys the instance and cleans up resources\n\t * @public\n\t */\n\tdestroy() {\n\t\t// Already destroyed\n\t\tif (!this.state) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remove element listeners\n\t\tif (this.state.focusMarker) {\n\t\t\tthis.state.focusMarker.removeEventListener(\n\t\t\t\t\"mousedown\",\n\t\t\t\tthis._boundFocusMarkerMouseDown,\n\t\t\t);\n\t\t}\n\n\t\tif (this.state.cropOverlay) {\n\t\t\tthis.state.cropOverlay.removeEventListener(\n\t\t\t\t\"mousedown\",\n\t\t\t\tthis._boundCropOverlayMouseDown,\n\t\t\t);\n\t\t}\n\n\t\tfor (const handle of this.cropHandles) {\n\t\t\thandle.removeEventListener(\"mousedown\", this._boundCropHandleMouseDown);\n\t\t}\n\t\tthis.cropHandles = [];\n\n\t\t// Remove DOM elements\n\t\tif (this.state.focusMarker?.parentNode) {\n\t\t\tthis.state.focusMarker.parentNode.removeChild(this.state.focusMarker);\n\t\t}\n\n\t\tif (this.state.cropOverlay?.parentNode) {\n\t\t\tthis.state.cropOverlay.parentNode.removeChild(this.state.cropOverlay);\n\t\t}\n\n\t\tif (this.spinnerElement?.parentNode) {\n\t\t\tthis.spinnerElement.parentNode.removeChild(this.spinnerElement);\n\t\t}\n\t\tthis.spinnerElement = null;\n\n\t\t// Remove global listeners\n\t\twindow.removeEventListener(\"resize\", this._boundUpdateScaling);\n\t\tdocument.removeEventListener(\"mouseup\", this._boundHandleMouseUp);\n\t\tdocument.removeEventListener(\"mousemove\", this._boundHandleMouseMove);\n\n\t\tif (this.imageElement) {\n\t\t\tthis.imageElement.removeEventListener(\"load\", this._boundUpdateScaling);\n\t\t}\n\n\t\t// Release bound handlers\n\t\tthis._boundUpdateScaling = null;\n\t\tthis._boundHandleMouseUp = null;\n\t\tthis._boundHandleMouseMove = null;\n\t\tthis._boundFocusMarkerMouseDown = null;\n\t\tthis._boundCropOverlayMouseDown = null;\n\t\tthis._boundCropHandleMouseDown = null;\n\n\t\t// Reset state\n\t\tthis.state = null;\n\t\tthis.interaction = null;\n\t\tthis.options = null;\n\t\tthis.imageElement = null;\n\t}\n}\n\n// Export class\nexport default VisualImageTool;\n"],"names":[],"mappings":"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"}
|
|
@@ -165,16 +165,26 @@ class VisualImageTool {
|
|
|
165
165
|
this.spinnerElement.style.boxSizing = "border-box";
|
|
166
166
|
this.spinnerElement.style.zIndex = "1000"; // Ensure it's above other elements
|
|
167
167
|
this.spinnerElement.style.display = "block"; // Initially visible
|
|
168
|
-
this.spinnerElement.style.animation =
|
|
168
|
+
this.spinnerElement.style.animation =
|
|
169
|
+
"visual-image-tool-spin 1s linear infinite";
|
|
169
170
|
|
|
170
171
|
this.imageElement.parentNode.appendChild(this.spinnerElement);
|
|
171
172
|
|
|
172
|
-
// Add CSS keyframes for spinner animation
|
|
173
|
+
// Add CSS keyframes for spinner animation.
|
|
174
|
+
//
|
|
175
|
+
// The animation name is namespaced: keyframes are global to the
|
|
176
|
+
// document, so a bare name like `spin` would collide with one
|
|
177
|
+
// defined by the host page, and whichever stylesheet was injected
|
|
178
|
+
// last would silently win.
|
|
179
|
+
//
|
|
180
|
+
// This stylesheet is shared by every instance and deliberately
|
|
181
|
+
// outlives destroy(): removing it would break the animation for
|
|
182
|
+
// any instance still alive. The id guard keeps it to one element.
|
|
173
183
|
if (!document.getElementById("visual-image-tool-spinner-styles")) {
|
|
174
184
|
const styleElement = document.createElement("style");
|
|
175
185
|
styleElement.id = "visual-image-tool-spinner-styles";
|
|
176
186
|
styleElement.innerHTML = `
|
|
177
|
-
@keyframes spin {
|
|
187
|
+
@keyframes visual-image-tool-spin {
|
|
178
188
|
0% { transform: translate(-50%, -50%) rotate(0deg); }
|
|
179
189
|
100% { transform: translate(-50%, -50%) rotate(360deg); }
|
|
180
190
|
}
|