@buoy-gg/image-overlay 7.0.41 → 7.0.43

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