@buoy-gg/image-overlay 7.0.40 → 7.0.42

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 (42) hide show
  1. package/README.md +12 -72
  2. package/lib/commonjs/imageOverlay/components/ImageOverlayModal.js +1 -875
  3. package/lib/commonjs/imageOverlay/components/ImageOverlayStandalone.js +1 -456
  4. package/lib/commonjs/imageOverlay/components/OverlayControls.js +1 -253
  5. package/lib/commonjs/imageOverlay/components/TargetList.js +1 -181
  6. package/lib/commonjs/imageOverlay/types/index.js +1 -1
  7. package/lib/commonjs/imageOverlay/utils/ImageOverlayController.js +1 -393
  8. package/lib/commonjs/imageOverlay/utils/componentMeasurement.js +1 -106
  9. package/lib/commonjs/imageOverlay/utils/devtoolsHook.js +1 -36
  10. package/lib/commonjs/imageOverlay/utils/fiberScanner.js +1 -102
  11. package/lib/commonjs/imageOverlay/utils/imageClipboard.js +1 -0
  12. package/lib/commonjs/imageOverlay/utils/imageClipboard.web.js +1 -0
  13. package/lib/commonjs/index.js +1 -59
  14. package/lib/commonjs/preset.js +1 -42
  15. package/lib/module/imageOverlay/components/ImageOverlayModal.js +1 -870
  16. package/lib/module/imageOverlay/components/ImageOverlayStandalone.js +1 -452
  17. package/lib/module/imageOverlay/components/OverlayControls.js +1 -249
  18. package/lib/module/imageOverlay/components/TargetList.js +1 -177
  19. package/lib/module/imageOverlay/types/index.js +1 -1
  20. package/lib/module/imageOverlay/utils/ImageOverlayController.js +1 -389
  21. package/lib/module/imageOverlay/utils/componentMeasurement.js +1 -102
  22. package/lib/module/imageOverlay/utils/devtoolsHook.js +1 -31
  23. package/lib/module/imageOverlay/utils/fiberScanner.js +1 -98
  24. package/lib/module/imageOverlay/utils/imageClipboard.js +1 -0
  25. package/lib/module/imageOverlay/utils/imageClipboard.web.js +1 -0
  26. package/lib/module/index.js +1 -35
  27. package/lib/module/preset.js +1 -38
  28. package/lib/typescript/imageOverlay/utils/imageClipboard.d.ts +3 -0
  29. package/lib/typescript/imageOverlay/utils/imageClipboard.web.d.ts +9 -0
  30. package/lib/web/index.mjs +4 -0
  31. package/package.json +32 -10
  32. package/lib/typescript/imageOverlay/components/ImageOverlayModal.d.ts.map +0 -1
  33. package/lib/typescript/imageOverlay/components/ImageOverlayStandalone.d.ts.map +0 -1
  34. package/lib/typescript/imageOverlay/components/OverlayControls.d.ts.map +0 -1
  35. package/lib/typescript/imageOverlay/components/TargetList.d.ts.map +0 -1
  36. package/lib/typescript/imageOverlay/types/index.d.ts.map +0 -1
  37. package/lib/typescript/imageOverlay/utils/ImageOverlayController.d.ts.map +0 -1
  38. package/lib/typescript/imageOverlay/utils/componentMeasurement.d.ts.map +0 -1
  39. package/lib/typescript/imageOverlay/utils/devtoolsHook.d.ts.map +0 -1
  40. package/lib/typescript/imageOverlay/utils/fiberScanner.d.ts.map +0 -1
  41. package/lib/typescript/index.d.ts.map +0 -1
  42. package/lib/typescript/preset.d.ts.map +0 -1
@@ -1,456 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.ImageOverlayStandalone = ImageOverlayStandalone;
7
- var _react = _interopRequireWildcard(require("react"));
8
- var _reactNative = require("react-native");
9
- var _sharedUi = require("@buoy-gg/shared-ui");
10
- var _ImageOverlayController = require("../utils/ImageOverlayController");
11
- var _jsxRuntime = require("react/jsx-runtime");
12
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
13
- /**
14
- * Standalone overlay that renders:
15
- * - Component mode: highlight border + image overlay on a tagged component
16
- * - Free mode: draggable, resizable image anywhere on screen (aspect-ratio locked)
17
- *
18
- * Supports Normal, Difference, and Multiply blend modes.
19
- * Supports image inversion (flip X/Y) and position locking.
20
- * Auto-mounted by FloatingDevTools alongside other standalone overlays.
21
- */
22
-
23
- // ─── Overlay Image (handles flip transforms) ─────────────────────────────────
24
- function OverlayImage({
25
- uri,
26
- style,
27
- invertX,
28
- invertY
29
- }) {
30
- const transform = [];
31
- if (invertX) transform.push({
32
- scaleX: -1
33
- });
34
- if (invertY) transform.push({
35
- scaleY: -1
36
- });
37
- const flipStyle = transform.length > 0 ? {
38
- transform
39
- } : {};
40
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, {
41
- source: {
42
- uri
43
- },
44
- style: [style, flipStyle]
45
- // @ts-ignore
46
- ,
47
- pointerEvents: "none"
48
- });
49
- }
50
-
51
- // ─── Free Placement ───────────────────────────────────────────────────────────
52
-
53
- const FREE_MIN_SIZE = 30;
54
- function FreePlacement({
55
- imageUri,
56
- x,
57
- y,
58
- width,
59
- height,
60
- opacity,
61
- aspectRatio,
62
- invertX,
63
- invertY,
64
- locked
65
- }) {
66
- const [isInteracting, setIsInteracting] = (0, _react.useState)(false);
67
- const startPosRef = (0, _react.useRef)({
68
- x: 0,
69
- y: 0
70
- });
71
- const startDimsRef = (0, _react.useRef)({
72
- x: 0,
73
- y: 0,
74
- width: 0,
75
- height: 0
76
- });
77
- const screen = _reactNative.Dimensions.get("window");
78
-
79
- // ── Drag ──
80
- const dragResponder = (0, _react.useMemo)(() => _reactNative.PanResponder.create({
81
- onStartShouldSetPanResponder: () => !locked,
82
- onMoveShouldSetPanResponder: (_, g) => !locked && (Math.abs(g.dx) > 2 || Math.abs(g.dy) > 2),
83
- onPanResponderTerminationRequest: () => false,
84
- onPanResponderGrant: () => {
85
- const s = _ImageOverlayController.ImageOverlayController.getState();
86
- startPosRef.current = {
87
- x: s.freeX,
88
- y: s.freeY
89
- };
90
- setIsInteracting(true);
91
- },
92
- onPanResponderMove: (_, g) => {
93
- const s = _ImageOverlayController.ImageOverlayController.getState();
94
- const newX = Math.max(0, Math.min(startPosRef.current.x + g.dx, screen.width - s.freeWidth));
95
- const newY = Math.max(0, Math.min(startPosRef.current.y + g.dy, screen.height - s.freeHeight));
96
- _ImageOverlayController.ImageOverlayController.setFreePosition(newX, newY);
97
- },
98
- onPanResponderRelease: () => setIsInteracting(false),
99
- onPanResponderTerminate: () => setIsInteracting(false)
100
- }), [screen.width, screen.height, locked]);
101
-
102
- // ── Aspect-ratio-locked corner resize ──
103
- const createResizeHandler = (0, _react.useCallback)(corner => _reactNative.PanResponder.create({
104
- onStartShouldSetPanResponder: () => !locked,
105
- onMoveShouldSetPanResponder: () => !locked,
106
- onPanResponderTerminationRequest: () => false,
107
- onPanResponderGrant: () => {
108
- const s = _ImageOverlayController.ImageOverlayController.getState();
109
- startDimsRef.current = {
110
- x: s.freeX,
111
- y: s.freeY,
112
- width: s.freeWidth,
113
- height: s.freeHeight
114
- };
115
- setIsInteracting(true);
116
- },
117
- onPanResponderMove: (_, g) => {
118
- const {
119
- dx,
120
- dy
121
- } = g;
122
- if (Math.abs(dx) < 0.5 && Math.abs(dy) < 0.5) return;
123
- const start = startDimsRef.current;
124
- const ratio = aspectRatio > 0 ? aspectRatio : start.width / start.height;
125
- const absDx = Math.abs(dx);
126
- const absDy = Math.abs(dy);
127
- const useDx = absDx >= absDy;
128
- let newWidth;
129
- let newHeight;
130
- let newX = start.x;
131
- let newY = start.y;
132
- switch (corner) {
133
- case "bottomRight":
134
- {
135
- newWidth = useDx ? start.width + dx : (start.height + dy) * ratio;
136
- newWidth = Math.max(FREE_MIN_SIZE, Math.min(newWidth, screen.width - start.x));
137
- newHeight = newWidth / ratio;
138
- break;
139
- }
140
- case "bottomLeft":
141
- {
142
- newWidth = useDx ? start.width - dx : (start.height + dy) * ratio;
143
- newWidth = Math.max(FREE_MIN_SIZE, newWidth);
144
- newHeight = newWidth / ratio;
145
- newX = start.x + start.width - newWidth;
146
- newX = Math.max(0, newX);
147
- newWidth = Math.min(newWidth, start.x + start.width);
148
- newHeight = newWidth / ratio;
149
- break;
150
- }
151
- case "topRight":
152
- {
153
- newWidth = useDx ? start.width + dx : (start.height - dy) * ratio;
154
- newWidth = Math.max(FREE_MIN_SIZE, Math.min(newWidth, screen.width - start.x));
155
- newHeight = newWidth / ratio;
156
- newY = start.y + start.height - newHeight;
157
- newY = Math.max(0, newY);
158
- newHeight = Math.min(newHeight, start.y + start.height);
159
- newWidth = newHeight * ratio;
160
- break;
161
- }
162
- case "topLeft":
163
- {
164
- newWidth = useDx ? start.width - dx : (start.height - dy) * ratio;
165
- newWidth = Math.max(FREE_MIN_SIZE, newWidth);
166
- newHeight = newWidth / ratio;
167
- newX = start.x + start.width - newWidth;
168
- newY = start.y + start.height - newHeight;
169
- newX = Math.max(0, newX);
170
- newY = Math.max(0, newY);
171
- newWidth = Math.min(newWidth, start.x + start.width);
172
- newHeight = newWidth / ratio;
173
- newY = start.y + start.height - newHeight;
174
- break;
175
- }
176
- }
177
- newWidth = Math.max(FREE_MIN_SIZE, Math.round(newWidth));
178
- newHeight = Math.max(FREE_MIN_SIZE, Math.round(newHeight));
179
- _ImageOverlayController.ImageOverlayController.setFreeDimensions(newWidth, newHeight, Math.round(newX), Math.round(newY));
180
- },
181
- onPanResponderRelease: () => setIsInteracting(false),
182
- onPanResponderTerminate: () => setIsInteracting(false)
183
- }), [screen.width, screen.height, aspectRatio, locked]);
184
- const resizeHandlers = (0, _react.useMemo)(() => ({
185
- topLeft: createResizeHandler("topLeft"),
186
- topRight: createResizeHandler("topRight"),
187
- bottomLeft: createResizeHandler("bottomLeft"),
188
- bottomRight: createResizeHandler("bottomRight")
189
- }), [createResizeHandler]);
190
- const imageStyle = {
191
- ..._sharedUi.absoluteFill,
192
- opacity
193
- };
194
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
195
- style: {
196
- position: "absolute",
197
- left: x,
198
- top: y,
199
- width,
200
- height
201
- },
202
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
203
- style: _reactNative.StyleSheet.absoluteFill,
204
- ...(locked ? {} : dragResponder.panHandlers),
205
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(OverlayImage, {
206
- uri: imageUri,
207
- style: imageStyle,
208
- invertX: invertX,
209
- invertY: invertY
210
- })
211
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
212
- pointerEvents: "none",
213
- style: [styles.freeBorder, isInteracting && styles.freeBorderActive, locked && styles.freeBorderLocked]
214
- }), !locked && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
215
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
216
- ...resizeHandlers.topLeft.panHandlers,
217
- style: [styles.cornerWrapper, {
218
- top: -20,
219
- left: -20
220
- }],
221
- hitSlop: {
222
- top: 10,
223
- left: 10,
224
- right: 10,
225
- bottom: 10
226
- },
227
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
228
- style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
229
- })
230
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
231
- ...resizeHandlers.topRight.panHandlers,
232
- style: [styles.cornerWrapper, {
233
- top: -20,
234
- right: -20
235
- }],
236
- hitSlop: {
237
- top: 10,
238
- left: 10,
239
- right: 10,
240
- bottom: 10
241
- },
242
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
243
- style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
244
- })
245
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
246
- ...resizeHandlers.bottomLeft.panHandlers,
247
- style: [styles.cornerWrapper, {
248
- bottom: -20,
249
- left: -20
250
- }],
251
- hitSlop: {
252
- top: 10,
253
- left: 10,
254
- right: 10,
255
- bottom: 10
256
- },
257
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
258
- style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
259
- })
260
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
261
- ...resizeHandlers.bottomRight.panHandlers,
262
- style: [styles.cornerWrapper, {
263
- bottom: -20,
264
- right: -20
265
- }],
266
- hitSlop: {
267
- top: 10,
268
- left: 10,
269
- right: 10,
270
- bottom: 10
271
- },
272
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
273
- style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
274
- })
275
- })]
276
- })]
277
- });
278
- }
279
-
280
- // ─── Main Standalone Overlay ──────────────────────────────────────────────────
281
-
282
- function ImageOverlayStandalone() {
283
- const [state, setState] = (0, _react.useState)(() => _ImageOverlayController.ImageOverlayController.getState());
284
- (0, _react.useEffect)(() => {
285
- return _ImageOverlayController.ImageOverlayController.subscribe(setState);
286
- }, []);
287
- const {
288
- mode,
289
- enabled,
290
- imageUri,
291
- imageWidth,
292
- imageHeight,
293
- targetRect,
294
- targetLabel,
295
- showOutline,
296
- opacity,
297
- scale,
298
- offsetX,
299
- offsetY,
300
- invertX,
301
- invertY,
302
- locked,
303
- freeX,
304
- freeY,
305
- freeWidth,
306
- freeHeight
307
- } = state;
308
- const aspectRatio = imageWidth && imageHeight && imageHeight > 0 ? imageWidth / imageHeight : 0;
309
-
310
- // ─── Free Placement Mode ───
311
- if (mode === "free" && enabled && imageUri) {
312
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
313
- style: styles.overlay,
314
- pointerEvents: "box-none",
315
- nativeID: "image-overlay-standalone",
316
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(FreePlacement, {
317
- imageUri: imageUri,
318
- x: freeX,
319
- y: freeY,
320
- width: freeWidth,
321
- height: freeHeight,
322
- opacity: opacity,
323
- aspectRatio: aspectRatio,
324
- invertX: invertX,
325
- invertY: invertY,
326
- locked: locked
327
- })
328
- });
329
- }
330
-
331
- // ─── Component Match Mode ───
332
- if (!targetRect) return null;
333
- const showImage = enabled && imageUri;
334
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
335
- style: styles.overlay,
336
- pointerEvents: "box-none",
337
- nativeID: "image-overlay-standalone",
338
- children: [showOutline && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
339
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
340
- pointerEvents: "none",
341
- nativeID: "__image_overlay_highlight__",
342
- style: [styles.highlight, {
343
- left: targetRect.x - 3,
344
- top: targetRect.y - 3,
345
- width: targetRect.width + 6,
346
- height: targetRect.height + 6
347
- }]
348
- }), targetLabel && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
349
- pointerEvents: "none",
350
- style: [styles.label, {
351
- left: targetRect.x,
352
- top: targetRect.y - 20
353
- }],
354
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
355
- style: styles.labelText,
356
- children: targetLabel
357
- })
358
- })]
359
- }), showImage && (() => {
360
- const w = (imageWidth ?? targetRect.width) * scale;
361
- const h = (imageHeight ?? targetRect.height) * scale;
362
- const centerX = targetRect.x + targetRect.width / 2;
363
- const centerY = targetRect.y + targetRect.height / 2;
364
- const imgStyle = {
365
- position: "absolute",
366
- left: centerX - w / 2 + offsetX,
367
- top: centerY - h / 2 + offsetY,
368
- width: w,
369
- height: h,
370
- opacity
371
- };
372
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(OverlayImage, {
373
- uri: imageUri,
374
- style: imgStyle,
375
- invertX: invertX,
376
- invertY: invertY
377
- });
378
- })()]
379
- });
380
- }
381
- const styles = _reactNative.StyleSheet.create({
382
- overlay: {
383
- position: "absolute",
384
- top: 0,
385
- left: 0,
386
- right: 0,
387
- bottom: 0,
388
- zIndex: 999999,
389
- elevation: 999999,
390
- borderWidth: 0
391
- },
392
- highlight: {
393
- position: "absolute",
394
- borderWidth: 2,
395
- borderStyle: "dashed",
396
- borderColor: "#20C997",
397
- backgroundColor: "transparent"
398
- },
399
- label: {
400
- position: "absolute",
401
- backgroundColor: "#20C997",
402
- paddingHorizontal: 6,
403
- paddingVertical: 2,
404
- borderRadius: 3
405
- },
406
- labelText: {
407
- color: "#fff",
408
- fontSize: 10,
409
- fontWeight: "700",
410
- fontFamily: _sharedUi.monoFont
411
- },
412
- freeBorder: {
413
- position: "absolute",
414
- top: -6,
415
- left: -6,
416
- right: -6,
417
- bottom: -6,
418
- borderWidth: 1,
419
- borderColor: "transparent",
420
- borderRadius: 4
421
- },
422
- freeBorderActive: {
423
- borderColor: "#20C997",
424
- borderStyle: "dashed"
425
- },
426
- freeBorderLocked: {
427
- borderColor: "#f59e0b",
428
- borderStyle: "solid"
429
- },
430
- cornerWrapper: {
431
- position: "absolute",
432
- width: 24,
433
- height: 24,
434
- zIndex: 1000,
435
- alignItems: "center",
436
- justifyContent: "center"
437
- },
438
- cornerHandle: {
439
- width: 12,
440
- height: 12,
441
- borderRadius: 6,
442
- backgroundColor: "#20C997",
443
- borderWidth: 2,
444
- borderColor: "#fff"
445
- },
446
- cornerHandleActive: {
447
- backgroundColor: "#10b981",
448
- shadowColor: "#10b981",
449
- shadowOffset: {
450
- width: 0,
451
- height: 0
452
- },
453
- shadowOpacity: 0.8,
454
- shadowRadius: 6
455
- }
456
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ImageOverlayStandalone=ImageOverlayStandalone;var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _ImageOverlayController=require("../utils/ImageOverlayController");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireWildcard(x,w){if("function"==typeof WeakMap)var v=new WeakMap,u=new WeakMap;return(_interopRequireWildcard=function(r,c){if(!c&&r&&r.__esModule)return r;var a,o,g={__proto__:null,default:r};if(null===r||"object"!=typeof r&&"function"!=typeof r)return g;if(a=c?u:v){if(a.has(r))return a.get(r);a.set(r,g)}for(const n in r)"default"!==n&&{}.hasOwnProperty.call(r,n)&&((o=(a=Object.defineProperty)&&Object.getOwnPropertyDescriptor(r,n))&&(o.get||o.set)?a(g,n,o):g[n]=r[n]);return g})(x,w)}function OverlayImage({uri:x,style:w,invertX:v,invertY:u}){const r=[];if(v)r.push({scaleX:-1});if(u)r.push({scaleY:-1});const c=r.length>0?{transform:r}:{};return(0,_jsxRuntime.jsx)(_reactNative.Image,{testID:"buoy-internal-image-overlay",source:{uri:x},style:[w,c],pointerEvents:"none"})}const FREE_MIN_SIZE=30;function FreePlacement({imageUri:x,x:w,y:v,width:u,height:r,opacity:c,aspectRatio:a,invertX:o,invertY:g,locked:n}){const[y,p]=(0,_react.useState)(false);const I=(0,_react.useRef)({x:0,y:0});const C=(0,_react.useRef)({x:0,y:0,width:0,height:0});const h=_reactNative.Dimensions.get("window");const _=(0,_react.useMemo)(()=>_reactNative.PanResponder.create({onStartShouldSetPanResponder:()=>!n,onMoveShouldSetPanResponder:(m,s)=>!n&&(Math.abs(s.dx)>2||Math.abs(s.dy)>2),onPanResponderTerminationRequest:()=>false,onPanResponderGrant:()=>{const m=_ImageOverlayController.ImageOverlayController.getState();I.current={x:m.freeX,y:m.freeY};p(true)},onPanResponderMove:(m,s)=>{const j=_ImageOverlayController.ImageOverlayController.getState();const f=Math.max(0,Math.min(I.current.x+s.dx,h.width-j.freeWidth));const d=Math.max(0,Math.min(I.current.y+s.dy,h.height-j.freeHeight));_ImageOverlayController.ImageOverlayController.setFreePosition(f,d)},onPanResponderRelease:()=>p(false),onPanResponderTerminate:()=>p(false)}),[h.width,h.height,n]);const R=(0,_react.useCallback)(m=>_reactNative.PanResponder.create({onStartShouldSetPanResponder:()=>!n,onMoveShouldSetPanResponder:()=>!n,onPanResponderTerminationRequest:()=>false,onPanResponderGrant:()=>{const s=_ImageOverlayController.ImageOverlayController.getState();C.current={x:s.freeX,y:s.freeY,width:s.freeWidth,height:s.freeHeight};p(true)},onPanResponderMove:(s,j)=>{const{dx:f,dy:d}=j;if(Math.abs(f)<.5&&Math.abs(d)<.5)return;const e=C.current;const l=a>0?a:e.width/e.height;const O=Math.abs(f);const W=Math.abs(d);const H=O>=W;let t;let i;let M=e.x;let b=e.y;switch(m){case"bottomRight":{t=H?e.width+f:(e.height+d)*l;t=Math.max(FREE_MIN_SIZE,Math.min(t,h.width-e.x));i=t/l;break}case"bottomLeft":{t=H?e.width-f:(e.height+d)*l;t=Math.max(FREE_MIN_SIZE,t);i=t/l;M=e.x+e.width-t;M=Math.max(0,M);t=Math.min(t,e.x+e.width);i=t/l;break}case"topRight":{t=H?e.width+f:(e.height-d)*l;t=Math.max(FREE_MIN_SIZE,Math.min(t,h.width-e.x));i=t/l;b=e.y+e.height-i;b=Math.max(0,b);i=Math.min(i,e.y+e.height);t=i*l;break}case"topLeft":{t=H?e.width-f:(e.height-d)*l;t=Math.max(FREE_MIN_SIZE,t);i=t/l;M=e.x+e.width-t;b=e.y+e.height-i;M=Math.max(0,M);b=Math.max(0,b);t=Math.min(t,e.x+e.width);i=t/l;b=e.y+e.height-i;break}}t=Math.max(FREE_MIN_SIZE,Math.round(t));i=Math.max(FREE_MIN_SIZE,Math.round(i));_ImageOverlayController.ImageOverlayController.setFreeDimensions(t,i,Math.round(M),Math.round(b))},onPanResponderRelease:()=>p(false),onPanResponderTerminate:()=>p(false)}),[h.width,h.height,a,n]);const S=(0,_react.useMemo)(()=>({topLeft:R("topLeft"),topRight:R("topRight"),bottomLeft:R("bottomLeft"),bottomRight:R("bottomRight")}),[R]);const P={..._sharedUi.absoluteFill,opacity:c};return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{position:"absolute",left:w,top:v,width:u,height:r},pointerEvents:n?"none":"auto",children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:_reactNative.StyleSheet.absoluteFill,...n?{}:_.panHandlers,children:(0,_jsxRuntime.jsx)(OverlayImage,{uri:x,style:P,invertX:o,invertY:g})}),(0,_jsxRuntime.jsx)(_reactNative.View,{pointerEvents:"none",style:[styles.freeBorder,y&&styles.freeBorderActive,n&&styles.freeBorderLocked]}),!n&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_reactNative.View,{...S.topLeft.panHandlers,style:[styles.cornerWrapper,{top:-20,left:-20}],hitSlop:{top:10,left:10,right:10,bottom:10},children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.cornerHandle,y&&styles.cornerHandleActive]})}),(0,_jsxRuntime.jsx)(_reactNative.View,{...S.topRight.panHandlers,style:[styles.cornerWrapper,{top:-20,right:-20}],hitSlop:{top:10,left:10,right:10,bottom:10},children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.cornerHandle,y&&styles.cornerHandleActive]})}),(0,_jsxRuntime.jsx)(_reactNative.View,{...S.bottomLeft.panHandlers,style:[styles.cornerWrapper,{bottom:-20,left:-20}],hitSlop:{top:10,left:10,right:10,bottom:10},children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.cornerHandle,y&&styles.cornerHandleActive]})}),(0,_jsxRuntime.jsx)(_reactNative.View,{...S.bottomRight.panHandlers,style:[styles.cornerWrapper,{bottom:-20,right:-20}],hitSlop:{top:10,left:10,right:10,bottom:10},children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.cornerHandle,y&&styles.cornerHandleActive]})})]})]})}function ImageOverlayStandalone(){const[x,w]=(0,_react.useState)(()=>_ImageOverlayController.ImageOverlayController.getState());(0,_react.useEffect)(()=>{return _ImageOverlayController.ImageOverlayController.subscribe(w)},[]);const{mode:v,enabled:u,imageUri:r,imageWidth:c,imageHeight:a,targetRect:o,targetLabel:g,showOutline:n,opacity:y,scale:p,offsetX:I,offsetY:C,invertX:h,invertY:_,locked:R,freeX:S,freeY:P,freeWidth:m,freeHeight:s}=x;const j=c&&a&&a>0?c/a:0;if(v==="free"&&u&&r){return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.overlay,pointerEvents:"box-none",nativeID:"image-overlay-standalone",children:(0,_jsxRuntime.jsx)(FreePlacement,{imageUri:r,x:S,y:P,width:m,height:s,opacity:y,aspectRatio:j,invertX:h,invertY:_,locked:R})})}if(!o)return null;const f=u&&r;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.overlay,pointerEvents:"box-none",nativeID:"image-overlay-standalone",children:[n&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_reactNative.View,{pointerEvents:"none",nativeID:"__image_overlay_highlight__",style:[styles.highlight,{left:o.x-3,top:o.y-3,width:o.width+6,height:o.height+6}]}),g&&(0,_jsxRuntime.jsx)(_reactNative.View,{pointerEvents:"none",style:[styles.label,{left:o.x,top:o.y-20}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.labelText,children:g})})]}),f&&(()=>{const d=(c??o.width)*p;const e=(a??o.height)*p;const l=o.x+o.width/2;const O=o.y+o.height/2;const W={position:"absolute",left:l-d/2+I,top:O-e/2+C,width:d,height:e,opacity:y};return(0,_jsxRuntime.jsx)(OverlayImage,{uri:r,style:W,invertX:h,invertY:_})})()]})}const styles=_reactNative.StyleSheet.create({overlay:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:999999,elevation:999999,borderWidth:0},highlight:{position:"absolute",borderWidth:2,borderStyle:"dashed",borderColor:"#20C997",backgroundColor:"transparent"},label:{position:"absolute",backgroundColor:"#20C997",paddingHorizontal:6,paddingVertical:2,borderRadius:3},labelText:{color:"#fff",fontSize:10,fontWeight:"700",fontFamily:_sharedUi.monoFont},freeBorder:{position:"absolute",top:-6,left:-6,right:-6,bottom:-6,borderWidth:1,borderColor:"transparent",borderRadius:4},freeBorderActive:{borderColor:"#20C997",borderStyle:"dashed"},freeBorderLocked:{borderColor:"#f59e0b",borderStyle:"solid"},cornerWrapper:{position:"absolute",width:24,height:24,zIndex:1e3,alignItems:"center",justifyContent:"center"},cornerHandle:{width:12,height:12,borderRadius:6,backgroundColor:"#20C997",borderWidth:2,borderColor:"#fff"},cornerHandleActive:{backgroundColor:"#10b981",shadowColor:"#10b981",shadowOffset:{width:0,height:0},shadowOpacity:.8,shadowRadius:6}});