@buoy-gg/image-overlay 7.0.39 → 7.0.41
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 +4 -0
- package/lib/commonjs/imageOverlay/components/ImageOverlayModal.js +9 -4
- package/lib/commonjs/imageOverlay/components/ImageOverlayStandalone.js +87 -80
- package/lib/commonjs/imageOverlay/utils/ImageOverlayController.js +34 -1
- package/lib/commonjs/imageOverlay/utils/fiberScanner.js +7 -5
- package/lib/commonjs/imageOverlay/utils/imageClipboard.js +22 -0
- package/lib/commonjs/imageOverlay/utils/imageClipboard.web.js +44 -0
- package/lib/module/imageOverlay/components/ImageOverlayModal.js +9 -4
- package/lib/module/imageOverlay/components/ImageOverlayStandalone.js +87 -80
- package/lib/module/imageOverlay/utils/ImageOverlayController.js +34 -1
- package/lib/module/imageOverlay/utils/fiberScanner.js +7 -5
- package/lib/module/imageOverlay/utils/imageClipboard.js +17 -0
- package/lib/module/imageOverlay/utils/imageClipboard.web.js +39 -0
- package/lib/typescript/imageOverlay/components/ImageOverlayModal.d.ts.map +1 -1
- package/lib/typescript/imageOverlay/components/ImageOverlayStandalone.d.ts.map +1 -1
- package/lib/typescript/imageOverlay/utils/ImageOverlayController.d.ts.map +1 -1
- package/lib/typescript/imageOverlay/utils/fiberScanner.d.ts.map +1 -1
- package/lib/typescript/imageOverlay/utils/imageClipboard.d.ts +3 -0
- package/lib/typescript/imageOverlay/utils/imageClipboard.d.ts.map +1 -0
- package/lib/typescript/imageOverlay/utils/imageClipboard.web.d.ts +9 -0
- package/lib/typescript/imageOverlay/utils/imageClipboard.web.d.ts.map +1 -0
- package/lib/web/index.mjs +5 -0
- package/package.json +32 -10
package/README.md
CHANGED
|
@@ -85,3 +85,7 @@ Use a Free or Pro Buoy account. History limits and paid features vary by tool; s
|
|
|
85
85
|
📚 [Full docs](https://buoy.gg/buoy/latest/docs/tools/image-overlay) · [All Buoy tools](https://github.com/Buoy-gg/buoy)
|
|
86
86
|
|
|
87
87
|
Proprietary software. © Buoy LLC. [Terms](https://buoy.gg/terms)
|
|
88
|
+
|
|
89
|
+
## Web support (unreleased)
|
|
90
|
+
|
|
91
|
+
Tag browser targets with data-testid="image-target:Name" and import the browser registration before React DOM. The shared controls support target and free placement. The browser build is available in this checkout and has not been published yet. See the [web setup guide](https://buoy.gg/buoy/latest/docs/web-preview) for registration, dependencies, and browser boundaries.
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.ImageOverlayModal = ImageOverlayModal;
|
|
7
7
|
exports.ImageOverlayToolView = ImageOverlayToolView;
|
|
8
|
+
var _imageClipboard = require("../utils/imageClipboard");
|
|
8
9
|
var _react = require("react");
|
|
9
10
|
var _reactNative = require("react-native");
|
|
10
11
|
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
@@ -80,7 +81,7 @@ function ImageOverlayModal({
|
|
|
80
81
|
// Try expo-clipboard (supports images)
|
|
81
82
|
let expoClipboard = null;
|
|
82
83
|
try {
|
|
83
|
-
expoClipboard =
|
|
84
|
+
expoClipboard = (0, _imageClipboard.loadImageClipboard)();
|
|
84
85
|
} catch {/* not installed */}
|
|
85
86
|
|
|
86
87
|
// Only fall back to @react-native-clipboard/clipboard when expo-clipboard
|
|
@@ -89,7 +90,7 @@ function ImageOverlayModal({
|
|
|
89
90
|
let rnClipboard = null;
|
|
90
91
|
if (!expoClipboard) {
|
|
91
92
|
try {
|
|
92
|
-
const mod =
|
|
93
|
+
const mod = (0, _imageClipboard.loadTextClipboard)();
|
|
93
94
|
rnClipboard = mod.default || mod;
|
|
94
95
|
} catch {/* not installed */}
|
|
95
96
|
}
|
|
@@ -323,7 +324,9 @@ function ImageOverlayModal({
|
|
|
323
324
|
placeholder: "or enter URL...",
|
|
324
325
|
placeholderTextColor: _sharedUi.night.color.placeholder,
|
|
325
326
|
autoCapitalize: "none",
|
|
326
|
-
autoCorrect: false
|
|
327
|
+
autoCorrect: false,
|
|
328
|
+
returnKeyType: "go",
|
|
329
|
+
onSubmitEditing: handleLoadImage
|
|
327
330
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
328
331
|
style: [styles.loadButton, !imageUrl.trim() && styles.loadButtonDisabled],
|
|
329
332
|
onPress: handleLoadImage,
|
|
@@ -444,7 +447,9 @@ function ImageOverlayModal({
|
|
|
444
447
|
placeholder: "or enter URL...",
|
|
445
448
|
placeholderTextColor: _sharedUi.night.color.placeholder,
|
|
446
449
|
autoCapitalize: "none",
|
|
447
|
-
autoCorrect: false
|
|
450
|
+
autoCorrect: false,
|
|
451
|
+
returnKeyType: "go",
|
|
452
|
+
onSubmitEditing: handleLoadImage
|
|
448
453
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
449
454
|
style: [styles.loadButton, !imageUrl.trim() && styles.loadButtonDisabled],
|
|
450
455
|
onPress: handleLoadImage,
|
|
@@ -38,6 +38,7 @@ function OverlayImage({
|
|
|
38
38
|
transform
|
|
39
39
|
} : {};
|
|
40
40
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, {
|
|
41
|
+
testID: "buoy-internal-image-overlay",
|
|
41
42
|
source: {
|
|
42
43
|
uri
|
|
43
44
|
},
|
|
@@ -191,90 +192,96 @@ function FreePlacement({
|
|
|
191
192
|
..._sharedUi.absoluteFill,
|
|
192
193
|
opacity
|
|
193
194
|
};
|
|
194
|
-
return
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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, {
|
|
195
|
+
return (
|
|
196
|
+
/*#__PURE__*/
|
|
197
|
+
// Locked means "let me use the app under it": the box must not swallow
|
|
198
|
+
// touches, or a locked full-screen mockup blocks every tap on the screen.
|
|
199
|
+
(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
200
|
+
style: {
|
|
201
|
+
position: "absolute",
|
|
202
|
+
left: x,
|
|
203
|
+
top: y,
|
|
204
|
+
width,
|
|
205
|
+
height
|
|
206
|
+
},
|
|
207
|
+
pointerEvents: locked ? "none" : "auto",
|
|
215
208
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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]
|
|
209
|
+
style: _reactNative.StyleSheet.absoluteFill,
|
|
210
|
+
...(locked ? {} : dragResponder.panHandlers),
|
|
211
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(OverlayImage, {
|
|
212
|
+
uri: imageUri,
|
|
213
|
+
style: imageStyle,
|
|
214
|
+
invertX: invertX,
|
|
215
|
+
invertY: invertY
|
|
259
216
|
})
|
|
260
217
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
261
|
-
|
|
262
|
-
style: [styles.
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
218
|
+
pointerEvents: "none",
|
|
219
|
+
style: [styles.freeBorder, isInteracting && styles.freeBorderActive, locked && styles.freeBorderLocked]
|
|
220
|
+
}), !locked && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
221
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
222
|
+
...resizeHandlers.topLeft.panHandlers,
|
|
223
|
+
style: [styles.cornerWrapper, {
|
|
224
|
+
top: -20,
|
|
225
|
+
left: -20
|
|
226
|
+
}],
|
|
227
|
+
hitSlop: {
|
|
228
|
+
top: 10,
|
|
229
|
+
left: 10,
|
|
230
|
+
right: 10,
|
|
231
|
+
bottom: 10
|
|
232
|
+
},
|
|
233
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
234
|
+
style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
|
|
235
|
+
})
|
|
236
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
237
|
+
...resizeHandlers.topRight.panHandlers,
|
|
238
|
+
style: [styles.cornerWrapper, {
|
|
239
|
+
top: -20,
|
|
240
|
+
right: -20
|
|
241
|
+
}],
|
|
242
|
+
hitSlop: {
|
|
243
|
+
top: 10,
|
|
244
|
+
left: 10,
|
|
245
|
+
right: 10,
|
|
246
|
+
bottom: 10
|
|
247
|
+
},
|
|
248
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
249
|
+
style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
|
|
250
|
+
})
|
|
251
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
252
|
+
...resizeHandlers.bottomLeft.panHandlers,
|
|
253
|
+
style: [styles.cornerWrapper, {
|
|
254
|
+
bottom: -20,
|
|
255
|
+
left: -20
|
|
256
|
+
}],
|
|
257
|
+
hitSlop: {
|
|
258
|
+
top: 10,
|
|
259
|
+
left: 10,
|
|
260
|
+
right: 10,
|
|
261
|
+
bottom: 10
|
|
262
|
+
},
|
|
263
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
264
|
+
style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
|
|
265
|
+
})
|
|
266
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
267
|
+
...resizeHandlers.bottomRight.panHandlers,
|
|
268
|
+
style: [styles.cornerWrapper, {
|
|
269
|
+
bottom: -20,
|
|
270
|
+
right: -20
|
|
271
|
+
}],
|
|
272
|
+
hitSlop: {
|
|
273
|
+
top: 10,
|
|
274
|
+
left: 10,
|
|
275
|
+
right: 10,
|
|
276
|
+
bottom: 10
|
|
277
|
+
},
|
|
278
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
279
|
+
style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
|
|
280
|
+
})
|
|
281
|
+
})]
|
|
275
282
|
})]
|
|
276
|
-
})
|
|
277
|
-
|
|
283
|
+
})
|
|
284
|
+
);
|
|
278
285
|
}
|
|
279
286
|
|
|
280
287
|
// ─── Main Standalone Overlay ──────────────────────────────────────────────────
|
|
@@ -107,7 +107,34 @@ function startTraceTracking() {
|
|
|
107
107
|
traceUnsubscribe = hook.sub("traceUpdates", handleTraceForAutoTrack);
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Remeasure once per frame while Auto Track is on.
|
|
113
|
+
*
|
|
114
|
+
* traceUpdates alone missed the common case: a native scroll moves the target
|
|
115
|
+
* without any React render, so the overlay stayed where the row used to be.
|
|
116
|
+
* One measure in flight at a time, so a slow bridge never queues frames.
|
|
117
|
+
*/
|
|
118
|
+
let frameHandle = null;
|
|
119
|
+
let frameMeasuring = false;
|
|
120
|
+
function startFrameTracking() {
|
|
121
|
+
if (frameHandle !== null || typeof requestAnimationFrame !== "function") return;
|
|
122
|
+
const tick = () => {
|
|
123
|
+
frameHandle = requestAnimationFrame(tick);
|
|
124
|
+
if (frameMeasuring || !autoTrackEnabled || !targetInstance) return;
|
|
125
|
+
frameMeasuring = true;
|
|
126
|
+
remeasureTarget().finally(() => {
|
|
127
|
+
frameMeasuring = false;
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
frameHandle = requestAnimationFrame(tick);
|
|
131
|
+
}
|
|
132
|
+
function stopFrameTracking() {
|
|
133
|
+
if (frameHandle !== null && typeof cancelAnimationFrame === "function") cancelAnimationFrame(frameHandle);
|
|
134
|
+
frameHandle = null;
|
|
135
|
+
}
|
|
110
136
|
function stopTraceTracking() {
|
|
137
|
+
stopFrameTracking();
|
|
111
138
|
if (traceUnsubscribe) {
|
|
112
139
|
traceUnsubscribe();
|
|
113
140
|
traceUnsubscribe = null;
|
|
@@ -122,7 +149,10 @@ function handleTraceForAutoTrack(_nodes) {
|
|
|
122
149
|
|
|
123
150
|
// Don't filter by nativeTag — any render could have caused a layout
|
|
124
151
|
// shift (e.g. sibling resize, scroll). Just remeasure cheaply.
|
|
125
|
-
|
|
152
|
+
void remeasureTarget();
|
|
153
|
+
}
|
|
154
|
+
function remeasureTarget() {
|
|
155
|
+
return (0, _componentMeasurement.measureInstance)(targetInstance).then(rect => {
|
|
126
156
|
if (rect && state.targetRect) {
|
|
127
157
|
// Only notify if position actually changed
|
|
128
158
|
const prev = state.targetRect;
|
|
@@ -134,6 +164,8 @@ function handleTraceForAutoTrack(_nodes) {
|
|
|
134
164
|
notify();
|
|
135
165
|
}
|
|
136
166
|
}
|
|
167
|
+
}).catch(() => {
|
|
168
|
+
// The target unmounted mid-measure; the next frame tries again.
|
|
137
169
|
});
|
|
138
170
|
}
|
|
139
171
|
function getImageSize(uri) {
|
|
@@ -237,6 +269,7 @@ const ImageOverlayController = exports.ImageOverlayController = {
|
|
|
237
269
|
autoTrackEnabled = enabled;
|
|
238
270
|
if (enabled) {
|
|
239
271
|
startTraceTracking();
|
|
272
|
+
startFrameTracking();
|
|
240
273
|
} else {
|
|
241
274
|
stopTraceTracking();
|
|
242
275
|
}
|
|
@@ -20,12 +20,14 @@ const OffscreenComponent = 22;
|
|
|
20
20
|
function getFiberRoots() {
|
|
21
21
|
const hook = (0, _devtoolsHook.getDevToolsHook)();
|
|
22
22
|
if (!hook?.getFiberRoots) return [];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
const roots = new Set();
|
|
24
|
+
const ids = hook.renderers?.keys ? Array.from(hook.renderers.keys()) : [1];
|
|
25
|
+
for (const id of ids) {
|
|
26
|
+
try {
|
|
27
|
+
hook.getFiberRoots(id)?.forEach(root => roots.add(root));
|
|
28
|
+
} catch {/* Other renderers can still provide roots. */}
|
|
28
29
|
}
|
|
30
|
+
return [...roots];
|
|
29
31
|
}
|
|
30
32
|
function isHiddenOffscreen(fiber) {
|
|
31
33
|
return fiber.tag === OffscreenComponent && fiber.memoizedState !== null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.loadImageClipboard = loadImageClipboard;
|
|
7
|
+
exports.loadTextClipboard = loadTextClipboard;
|
|
8
|
+
function loadImageClipboard() {
|
|
9
|
+
try {
|
|
10
|
+
return require('expo-clipboard');
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function loadTextClipboard() {
|
|
16
|
+
try {
|
|
17
|
+
const mod = require('@react-native-clipboard/clipboard');
|
|
18
|
+
return mod.default ?? mod;
|
|
19
|
+
} catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.loadImageClipboard = loadImageClipboard;
|
|
7
|
+
exports.loadTextClipboard = loadTextClipboard;
|
|
8
|
+
let image;
|
|
9
|
+
function loadImageClipboard() {
|
|
10
|
+
if (typeof navigator === 'undefined' || !navigator.clipboard) return null;
|
|
11
|
+
return {
|
|
12
|
+
async hasImageAsync() {
|
|
13
|
+
image = undefined;
|
|
14
|
+
if (!navigator.clipboard.read) return false;
|
|
15
|
+
const items = await navigator.clipboard.read();
|
|
16
|
+
for (const item of items) {
|
|
17
|
+
const type = item.types.find(value => value.startsWith('image/'));
|
|
18
|
+
if (type) {
|
|
19
|
+
image = await item.getType(type);
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
},
|
|
25
|
+
async getImageAsync() {
|
|
26
|
+
if (!image) return null;
|
|
27
|
+
const blob = image;
|
|
28
|
+
image = undefined;
|
|
29
|
+
const data = await new Promise((resolve, reject) => {
|
|
30
|
+
const reader = new FileReader();
|
|
31
|
+
reader.onload = () => resolve(String(reader.result));
|
|
32
|
+
reader.onerror = reject;
|
|
33
|
+
reader.readAsDataURL(blob);
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
data
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
getStringAsync: () => navigator.clipboard.readText()
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function loadTextClipboard() {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
import { loadImageClipboard, loadTextClipboard } from "../utils/imageClipboard";
|
|
3
4
|
import { useState, useEffect, useCallback } from "react";
|
|
4
5
|
import { View, Text, TextInput, TouchableOpacity, StyleSheet, Alert } from "react-native";
|
|
5
6
|
import { JsModal, ModalHeader, macOSColors, night, Trash2, SquareDashed, Image, PowerToggleButton, windowDragProps, ToggleRow, monoFont } from "@buoy-gg/shared-ui";
|
|
@@ -75,7 +76,7 @@ export function ImageOverlayModal({
|
|
|
75
76
|
// Try expo-clipboard (supports images)
|
|
76
77
|
let expoClipboard = null;
|
|
77
78
|
try {
|
|
78
|
-
expoClipboard =
|
|
79
|
+
expoClipboard = loadImageClipboard();
|
|
79
80
|
} catch {/* not installed */}
|
|
80
81
|
|
|
81
82
|
// Only fall back to @react-native-clipboard/clipboard when expo-clipboard
|
|
@@ -84,7 +85,7 @@ export function ImageOverlayModal({
|
|
|
84
85
|
let rnClipboard = null;
|
|
85
86
|
if (!expoClipboard) {
|
|
86
87
|
try {
|
|
87
|
-
const mod =
|
|
88
|
+
const mod = loadTextClipboard();
|
|
88
89
|
rnClipboard = mod.default || mod;
|
|
89
90
|
} catch {/* not installed */}
|
|
90
91
|
}
|
|
@@ -318,7 +319,9 @@ export function ImageOverlayModal({
|
|
|
318
319
|
placeholder: "or enter URL...",
|
|
319
320
|
placeholderTextColor: night.color.placeholder,
|
|
320
321
|
autoCapitalize: "none",
|
|
321
|
-
autoCorrect: false
|
|
322
|
+
autoCorrect: false,
|
|
323
|
+
returnKeyType: "go",
|
|
324
|
+
onSubmitEditing: handleLoadImage
|
|
322
325
|
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
323
326
|
style: [styles.loadButton, !imageUrl.trim() && styles.loadButtonDisabled],
|
|
324
327
|
onPress: handleLoadImage,
|
|
@@ -439,7 +442,9 @@ export function ImageOverlayModal({
|
|
|
439
442
|
placeholder: "or enter URL...",
|
|
440
443
|
placeholderTextColor: night.color.placeholder,
|
|
441
444
|
autoCapitalize: "none",
|
|
442
|
-
autoCorrect: false
|
|
445
|
+
autoCorrect: false,
|
|
446
|
+
returnKeyType: "go",
|
|
447
|
+
onSubmitEditing: handleLoadImage
|
|
443
448
|
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
444
449
|
style: [styles.loadButton, !imageUrl.trim() && styles.loadButtonDisabled],
|
|
445
450
|
onPress: handleLoadImage,
|
|
@@ -34,6 +34,7 @@ function OverlayImage({
|
|
|
34
34
|
transform
|
|
35
35
|
} : {};
|
|
36
36
|
return /*#__PURE__*/_jsx(RNImage, {
|
|
37
|
+
testID: "buoy-internal-image-overlay",
|
|
37
38
|
source: {
|
|
38
39
|
uri
|
|
39
40
|
},
|
|
@@ -187,90 +188,96 @@ function FreePlacement({
|
|
|
187
188
|
...absoluteFill,
|
|
188
189
|
opacity
|
|
189
190
|
};
|
|
190
|
-
return
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
style: imageStyle,
|
|
204
|
-
invertX: invertX,
|
|
205
|
-
invertY: invertY
|
|
206
|
-
})
|
|
207
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
208
|
-
pointerEvents: "none",
|
|
209
|
-
style: [styles.freeBorder, isInteracting && styles.freeBorderActive, locked && styles.freeBorderLocked]
|
|
210
|
-
}), !locked && /*#__PURE__*/_jsxs(_Fragment, {
|
|
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",
|
|
211
204
|
children: [/*#__PURE__*/_jsx(View, {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
left: 10,
|
|
220
|
-
right: 10,
|
|
221
|
-
bottom: 10
|
|
222
|
-
},
|
|
223
|
-
children: /*#__PURE__*/_jsx(View, {
|
|
224
|
-
style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
|
|
225
|
-
})
|
|
226
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
227
|
-
...resizeHandlers.topRight.panHandlers,
|
|
228
|
-
style: [styles.cornerWrapper, {
|
|
229
|
-
top: -20,
|
|
230
|
-
right: -20
|
|
231
|
-
}],
|
|
232
|
-
hitSlop: {
|
|
233
|
-
top: 10,
|
|
234
|
-
left: 10,
|
|
235
|
-
right: 10,
|
|
236
|
-
bottom: 10
|
|
237
|
-
},
|
|
238
|
-
children: /*#__PURE__*/_jsx(View, {
|
|
239
|
-
style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
|
|
240
|
-
})
|
|
241
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
242
|
-
...resizeHandlers.bottomLeft.panHandlers,
|
|
243
|
-
style: [styles.cornerWrapper, {
|
|
244
|
-
bottom: -20,
|
|
245
|
-
left: -20
|
|
246
|
-
}],
|
|
247
|
-
hitSlop: {
|
|
248
|
-
top: 10,
|
|
249
|
-
left: 10,
|
|
250
|
-
right: 10,
|
|
251
|
-
bottom: 10
|
|
252
|
-
},
|
|
253
|
-
children: /*#__PURE__*/_jsx(View, {
|
|
254
|
-
style: [styles.cornerHandle, isInteracting && styles.cornerHandleActive]
|
|
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
|
|
255
212
|
})
|
|
256
213
|
}), /*#__PURE__*/_jsx(View, {
|
|
257
|
-
|
|
258
|
-
style: [styles.
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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
|
+
})]
|
|
271
278
|
})]
|
|
272
|
-
})
|
|
273
|
-
|
|
279
|
+
})
|
|
280
|
+
);
|
|
274
281
|
}
|
|
275
282
|
|
|
276
283
|
// ─── Main Standalone Overlay ──────────────────────────────────────────────────
|
|
@@ -103,7 +103,34 @@ function startTraceTracking() {
|
|
|
103
103
|
traceUnsubscribe = hook.sub("traceUpdates", handleTraceForAutoTrack);
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Remeasure once per frame while Auto Track is on.
|
|
109
|
+
*
|
|
110
|
+
* traceUpdates alone missed the common case: a native scroll moves the target
|
|
111
|
+
* without any React render, so the overlay stayed where the row used to be.
|
|
112
|
+
* One measure in flight at a time, so a slow bridge never queues frames.
|
|
113
|
+
*/
|
|
114
|
+
let frameHandle = null;
|
|
115
|
+
let frameMeasuring = false;
|
|
116
|
+
function startFrameTracking() {
|
|
117
|
+
if (frameHandle !== null || typeof requestAnimationFrame !== "function") return;
|
|
118
|
+
const tick = () => {
|
|
119
|
+
frameHandle = requestAnimationFrame(tick);
|
|
120
|
+
if (frameMeasuring || !autoTrackEnabled || !targetInstance) return;
|
|
121
|
+
frameMeasuring = true;
|
|
122
|
+
remeasureTarget().finally(() => {
|
|
123
|
+
frameMeasuring = false;
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
frameHandle = requestAnimationFrame(tick);
|
|
127
|
+
}
|
|
128
|
+
function stopFrameTracking() {
|
|
129
|
+
if (frameHandle !== null && typeof cancelAnimationFrame === "function") cancelAnimationFrame(frameHandle);
|
|
130
|
+
frameHandle = null;
|
|
131
|
+
}
|
|
106
132
|
function stopTraceTracking() {
|
|
133
|
+
stopFrameTracking();
|
|
107
134
|
if (traceUnsubscribe) {
|
|
108
135
|
traceUnsubscribe();
|
|
109
136
|
traceUnsubscribe = null;
|
|
@@ -118,7 +145,10 @@ function handleTraceForAutoTrack(_nodes) {
|
|
|
118
145
|
|
|
119
146
|
// Don't filter by nativeTag — any render could have caused a layout
|
|
120
147
|
// shift (e.g. sibling resize, scroll). Just remeasure cheaply.
|
|
121
|
-
|
|
148
|
+
void remeasureTarget();
|
|
149
|
+
}
|
|
150
|
+
function remeasureTarget() {
|
|
151
|
+
return measureInstance(targetInstance).then(rect => {
|
|
122
152
|
if (rect && state.targetRect) {
|
|
123
153
|
// Only notify if position actually changed
|
|
124
154
|
const prev = state.targetRect;
|
|
@@ -130,6 +160,8 @@ function handleTraceForAutoTrack(_nodes) {
|
|
|
130
160
|
notify();
|
|
131
161
|
}
|
|
132
162
|
}
|
|
163
|
+
}).catch(() => {
|
|
164
|
+
// The target unmounted mid-measure; the next frame tries again.
|
|
133
165
|
});
|
|
134
166
|
}
|
|
135
167
|
function getImageSize(uri) {
|
|
@@ -233,6 +265,7 @@ export const ImageOverlayController = {
|
|
|
233
265
|
autoTrackEnabled = enabled;
|
|
234
266
|
if (enabled) {
|
|
235
267
|
startTraceTracking();
|
|
268
|
+
startFrameTracking();
|
|
236
269
|
} else {
|
|
237
270
|
stopTraceTracking();
|
|
238
271
|
}
|
|
@@ -16,12 +16,14 @@ const OffscreenComponent = 22;
|
|
|
16
16
|
function getFiberRoots() {
|
|
17
17
|
const hook = getDevToolsHook();
|
|
18
18
|
if (!hook?.getFiberRoots) return [];
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
const roots = new Set();
|
|
20
|
+
const ids = hook.renderers?.keys ? Array.from(hook.renderers.keys()) : [1];
|
|
21
|
+
for (const id of ids) {
|
|
22
|
+
try {
|
|
23
|
+
hook.getFiberRoots(id)?.forEach(root => roots.add(root));
|
|
24
|
+
} catch {/* Other renderers can still provide roots. */}
|
|
24
25
|
}
|
|
26
|
+
return [...roots];
|
|
25
27
|
}
|
|
26
28
|
function isHiddenOffscreen(fiber) {
|
|
27
29
|
return fiber.tag === OffscreenComponent && fiber.memoizedState !== null;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export function loadImageClipboard() {
|
|
4
|
+
try {
|
|
5
|
+
return require('expo-clipboard');
|
|
6
|
+
} catch {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function loadTextClipboard() {
|
|
11
|
+
try {
|
|
12
|
+
const mod = require('@react-native-clipboard/clipboard');
|
|
13
|
+
return mod.default ?? mod;
|
|
14
|
+
} catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
let image;
|
|
4
|
+
export function loadImageClipboard() {
|
|
5
|
+
if (typeof navigator === 'undefined' || !navigator.clipboard) return null;
|
|
6
|
+
return {
|
|
7
|
+
async hasImageAsync() {
|
|
8
|
+
image = undefined;
|
|
9
|
+
if (!navigator.clipboard.read) return false;
|
|
10
|
+
const items = await navigator.clipboard.read();
|
|
11
|
+
for (const item of items) {
|
|
12
|
+
const type = item.types.find(value => value.startsWith('image/'));
|
|
13
|
+
if (type) {
|
|
14
|
+
image = await item.getType(type);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
},
|
|
20
|
+
async getImageAsync() {
|
|
21
|
+
if (!image) return null;
|
|
22
|
+
const blob = image;
|
|
23
|
+
image = undefined;
|
|
24
|
+
const data = await new Promise((resolve, reject) => {
|
|
25
|
+
const reader = new FileReader();
|
|
26
|
+
reader.onload = () => resolve(String(reader.result));
|
|
27
|
+
reader.onerror = reject;
|
|
28
|
+
reader.readAsDataURL(blob);
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
data
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
getStringAsync: () => navigator.clipboard.readText()
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function loadTextClipboard() {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageOverlayModal.d.ts","sourceRoot":"","sources":["../../../../src/imageOverlay/components/ImageOverlayModal.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ImageOverlayModal.d.ts","sourceRoot":"","sources":["../../../../src/imageOverlay/components/ImageOverlayModal.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,sBAAsB,EAAkC,MAAM,UAAU,CAAC;AAMvF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAKjE,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,2BAAmC,EACnC,iBAAiB,EACjB,sBAAsB,EACtB,MAAc,EACd,WAAW,GACZ,EAAE,sBAAsB,+BAwiBxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,GAAE,IAAI,CAAC,sBAAsB,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAM,+BAG3E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageOverlayStandalone.d.ts","sourceRoot":"","sources":["../../../../src/imageOverlay/components/ImageOverlayStandalone.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageOverlayStandalone.d.ts","sourceRoot":"","sources":["../../../../src/imageOverlay/components/ImageOverlayStandalone.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AA2NjF,wBAAgB,sBAAsB,IAAI,KAAK,CAAC,YAAY,GAAG,IAAI,CAuFlE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageOverlayController.d.ts","sourceRoot":"","sources":["../../../../src/imageOverlay/utils/ImageOverlayController.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAgB,YAAY,EAAE,MAAM,UAAU,CAAC;AAK3D,KAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageOverlayController.d.ts","sourceRoot":"","sources":["../../../../src/imageOverlay/utils/ImageOverlayController.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAgB,YAAY,EAAE,MAAM,UAAU,CAAC;AAK3D,KAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;AAsK9C,eAAO,MAAM,sBAAsB;wBACb,QAAQ,GAAG,MAAM,IAAI;gBAM7B,YAAY;wBAME,GAAG,SAAS,MAAM,UAAU,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;qBAmBlD,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;sBAmB3B,MAAM;oBAKR,MAAM;iBAKT,MAAM,KAAK,MAAM;;;sBAeZ,OAAO;0BAKH,OAAO;sBAUX,OAAO;yBAIJ,OAAO;wBAKR,OAAO;;;;;iBA+CR,OAAO,CAAC,IAAI,CAAC;uBAYP,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;uBAkC5B,MAAM,KAAK,MAAM;6BAKX,MAAM,UAAU,MAAM,KAAK,MAAM,KAAK,MAAM;;CAgBtE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fiberScanner.d.ts","sourceRoot":"","sources":["../../../../src/imageOverlay/utils/fiberScanner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"fiberScanner.d.ts","sourceRoot":"","sources":["../../../../src/imageOverlay/utils/fiberScanner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAkFjD;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,EAAE,CAmCxD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageClipboard.d.ts","sourceRoot":"","sources":["../../../../src/imageOverlay/utils/imageClipboard.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB,IAAI,GAAG,CAAqE;AAC9G,wBAAgB,iBAAiB,IAAI,GAAG,CAAwH"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function loadImageClipboard(): {
|
|
2
|
+
hasImageAsync(): Promise<boolean>;
|
|
3
|
+
getImageAsync(): Promise<{
|
|
4
|
+
data: string;
|
|
5
|
+
} | null>;
|
|
6
|
+
getStringAsync: () => Promise<string>;
|
|
7
|
+
} | null;
|
|
8
|
+
export declare function loadTextClipboard(): null;
|
|
9
|
+
//# sourceMappingURL=imageClipboard.web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageClipboard.web.d.ts","sourceRoot":"","sources":["../../../../src/imageOverlay/utils/imageClipboard.web.ts"],"names":[],"mappings":"AACA,wBAAgB,kBAAkB;;;;;;SAuBjC;AACD,wBAAgB,iBAAiB,IAAI,IAAI,CAAiB"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var _e=Object.defineProperty;var at=Object.getOwnPropertyDescriptor;var it=Object.getOwnPropertyNames;var lt=Object.prototype.hasOwnProperty;var st=(e,o)=>{for(var n in o)_e(e,n,{get:o[n],enumerable:!0})},Fe=(e,o,n,a)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of it(o))!lt.call(e,r)&&r!==n&&_e(e,r,{get:()=>o[r],enumerable:!(a=at(o,r))||a.enumerable});return e},M=(e,o,n)=>(Fe(e,o,"default"),n&&Fe(n,o,"default"));typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import{ImageOverlayIcon as Po,createToolFactory as Bo,defineToolPreset as Wo}from"@buoy-gg/shared-ui/web";var fe;function Xe(){return typeof navigator>"u"||!navigator.clipboard?null:{async hasImageAsync(){if(fe=void 0,!navigator.clipboard.read)return!1;let e=await navigator.clipboard.read();for(let o of e){let n=o.types.find(a=>a.startsWith("image/"));if(n)return fe=await o.getType(n),!0}return!1},async getImageAsync(){if(!fe)return null;let e=fe;return fe=void 0,{data:await new Promise((n,a)=>{let r=new FileReader;r.onload=()=>n(String(r.result)),r.onerror=a,r.readAsDataURL(e)})}},getStringAsync:()=>navigator.clipboard.readText()}}function Ye(){return null}import{useState as Te,useEffect as De,useCallback as ue}from"react";var R={};st(R,{AccessibilityInfo:()=>Tt,ActivityIndicator:()=>ht,Alert:()=>le,Animated:()=>wt,AppRegistry:()=>St,AppState:()=>Rt,Appearance:()=>vt,BackHandler:()=>Ct,Button:()=>yt,CheckBox:()=>Dt,Clipboard:()=>It,DeviceEventEmitter:()=>Qt,Dimensions:()=>se,Easing:()=>Ot,FlatList:()=>Et,I18nManager:()=>Mt,Image:()=>pe,ImageBackground:()=>Ft,InteractionManager:()=>Pt,Keyboard:()=>Vt,KeyboardAvoidingView:()=>_t,LayoutAnimation:()=>Bt,Linking:()=>Wt,LogBox:()=>Zt,Modal:()=>pt,NativeEventEmitter:()=>Ht,NativeModules:()=>xt,PanResponder:()=>ce,Picker:()=>Xt,PixelRatio:()=>kt,Platform:()=>At,Pressable:()=>ft,ProgressBar:()=>Yt,RefreshControl:()=>Nt,SafeAreaView:()=>Ut,ScrollView:()=>Pe,SectionList:()=>$t,Share:()=>Lt,StatusBar:()=>jt,StyleSheet:()=>J,Switch:()=>mt,Text:()=>g,TextInput:()=>we,Touchable:()=>Gt,TouchableHighlight:()=>ut,TouchableNativeFeedback:()=>qt,TouchableOpacity:()=>O,TouchableWithoutFeedback:()=>gt,UIManager:()=>We,Vibration:()=>zt,View:()=>l,VirtualizedList:()=>Kt,YellowBox:()=>Jt,findNodeHandle:()=>Be,unstable_createElement:()=>bt,useColorScheme:()=>eo,useLocaleContext:()=>to,useWindowDimensions:()=>oo});M(R,Go);import*as Go from"react-native-web";import{unstable_createElement as bt,NativeModules as xt,AccessibilityInfo as Tt,Animated as wt,Appearance as vt,AppRegistry as St,AppState as Rt,BackHandler as Ct,Clipboard as It,Dimensions as se,Easing as Ot,I18nManager as Mt,Keyboard as Vt,InteractionManager as Pt,LayoutAnimation as Bt,Linking as Wt,NativeEventEmitter as Ht,PanResponder as ce,PixelRatio as kt,Platform as At,Share as Lt,StyleSheet as J,UIManager as We,Vibration as zt,CheckBox as Dt,FlatList as Et,Image as pe,ImageBackground as Ft,KeyboardAvoidingView as _t,Picker as Xt,ProgressBar as Yt,RefreshControl as Nt,SafeAreaView as Ut,SectionList as $t,StatusBar as jt,Touchable as Gt,TouchableNativeFeedback as qt,VirtualizedList as Kt,YellowBox as Jt,LogBox as Zt,DeviceEventEmitter as Qt,useColorScheme as eo,useLocaleContext as to,useWindowDimensions as oo}from"react-native-web";import*as I from"react-native-web";import{createElement as ct,forwardRef as dt}from"react";function j(e){let o=dt((a,r)=>{let{accessibilityState:y,accessibilityValue:T,...h}=a;for(let b of["busy","checked","disabled","expanded","selected"])y?.[b]!==void 0&&h[`aria-${b}`]===void 0&&(h[`aria-${b}`]=y[b]);for(let[b,c]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))T?.[b]!==void 0&&h[`aria-${c}`]===void 0&&(h[`aria-${c}`]=T[b]);return ct(e,{...h,ref:r})}),n=e.State;return n&&Object.assign(o,{State:n}),o.displayName=e.displayName??e.name??"NativeWebView",o}var l=j(I.View),g=j(I.Text),we=j(I.TextInput),O=j(I.TouchableOpacity),ut=j(I.TouchableHighlight),gt=j(I.TouchableWithoutFeedback),ft=j(I.Pressable),Pe=j(I.ScrollView),pt=j(I.Modal),mt=j(I.Switch),ht=j(I.ActivityIndicator),yt=j(I.Button),Be=I.findNodeHandle,le={alert(e,o,n,a){if(typeof document>"u")return;let r=document.createElement("dialog");r.dataset.buoyRoot="",r.setAttribute("aria-label",e),r.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let y=document.createElement("h2");if(y.textContent=e,y.style.cssText="font-size:18px;margin:0 0 12px",r.appendChild(y),o){let c=document.createElement("p");c.textContent=o,c.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",r.appendChild(c)}let T=document.createElement("div");T.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let h=n?.length?n:[{text:"OK"}],b=()=>{r.close?.(),r.remove()};for(let c of h){let v=document.createElement("button");v.type="button",v.textContent=c.text??"OK",v.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${c.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,v.onclick=()=>{b(),c.onPress?.()},T.appendChild(v)}r.addEventListener("cancel",c=>{c.preventDefault(),a?.cancelable!==!1&&(b(),a?.onDismiss?.())}),r.appendChild(T),document.body.appendChild(r),r.showModal?r.showModal():r.setAttribute("open","")}};import{JsModal as vo,ModalHeader as Oe,macOSColors as Je,night as m,Trash2 as So,SquareDashed as Ro,Image as Co,PowerToggleButton as Io,windowDragProps as Oo,ToggleRow as Ee,monoFont as Mo}from"@buoy-gg/shared-ui/web";function ve(e){return new Promise(o=>{try{let n=[];e&&n.push(e),e?.canonical?.publicInstance&&n.push(e.canonical.publicInstance),e?.canonical&&e.canonical!==e&&n.push(e.canonical);for(let a of n)if(typeof a.getBoundingClientRect=="function")try{let r=a.getBoundingClientRect();if(r&&typeof r.x=="number"&&typeof r.y=="number"&&typeof r.width=="number"&&typeof r.height=="number"&&r.width>0&&r.height>0){o({x:r.x,y:r.y,width:r.width,height:r.height});return}}catch{}for(let a of n)if(typeof a.measure=="function"){let r=setTimeout(()=>o(null),200);a.measure((y,T,h,b,c,v)=>{clearTimeout(r),c!=null&&v!=null&&h!=null&&b!=null&&h>0&&b>0?o({x:c,y:v,width:h,height:b}):o(null)});return}try{let a=Be(e);if(a!=null){let r=setTimeout(()=>o(null),200);We.measure(a,(y,T,h,b,c,v)=>{clearTimeout(r),c!=null&&v!=null&&h!=null&&b!=null&&h>0&&b>0?o({x:c,y:v,width:h,height:b}):o(null)});return}}catch{}o(null)}catch{o(null)}})}var He=null;function no(e){He=e??null}function Se(){return He||(typeof globalThis>"u"?null:globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__??null)}var Ne="image-target:",ro=5,ao=22;function io(){let e=Se();if(!e?.getFiberRoots)return[];let o=new Set,n=e.renderers?.keys?Array.from(e.renderers.keys()):[1];for(let a of n)try{e.getFiberRoots(a)?.forEach(r=>o.add(r))}catch{}return[...o]}function lo(e){return e.tag===ao&&e.memoizedState!==null}function so(e){return e.memoizedProps?.activityState===0}function me(e,o,n=0,a=new Set){if(!(!e||a.has(e)||n>500)){if(a.add(e),lo(e)){e.sibling&&me(e.sibling,o,n,a);return}if(so(e)){e.sibling&&me(e.sibling,o,n,a);return}o(e,n),e.child&&me(e.child,o,n+1,a),e.sibling&&me(e.sibling,o,n,a)}}function co(e){let o=new Set(["View","RCTView","Text","RCTText","Image","RCTImageView","ScrollView","RCTScrollView","TextInput","RCTTextInput","TouchableOpacity","TouchableHighlight","TouchableWithoutFeedback","Pressable","FlatList","SectionList","SafeAreaView"]),n=e._debugOwner||e.return,a=0;for(;n&&a<30;){a++;let r=n.type;if(r){let y=typeof r=="string"?r:r.displayName||r.name;if(y&&!o.has(y))return y}n=n.return}return null}function ne(){let e=io();if(e.length===0)return[];let o=[];for(let n of e)me(n.current,a=>{if(a.tag!==ro)return;let r=a.memoizedProps?.testID??a.pendingProps?.testID??a.memoizedProps?.["data-testid"]??a.pendingProps?.["data-testid"];if(!r||!r.startsWith(Ne))return;let y=r.slice(Ne.length);y&&o.push({label:y,testID:r,fiber:a,instance:a.stateNode,componentName:co(a)})});return o}var Ge={mode:null,enabled:!1,imageUri:null,imageWidth:null,imageHeight:null,targetTag:null,targetLabel:null,targetRect:null,showOutline:!0,opacity:.5,scale:1,offsetX:0,offsetY:0,invertX:!1,invertY:!1,locked:!1,freeX:0,freeY:0,freeWidth:200,freeHeight:200},i={...Ge},Ae=new Set,Z=null,Re=null,he=!1,ye=null,uo=null;function V(){for(let e of Ae)e(i)}function go(e){return e?typeof e._nativeTag=="number"?e._nativeTag:typeof e.canonical?._nativeTag=="number"?e.canonical._nativeTag:typeof e.__nativeTag=="number"?e.__nativeTag:null:null}async function Ue(e,o){let n=await ve(e);if(n)return{rect:n,freshInstance:e};let r=ne().find(y=>y.label===o);return r&&(n=await ve(r.instance),n)?{rect:n,freshInstance:r.instance}:{rect:null,freshInstance:e}}function fo(){if(ye)return;let e=Se();if(e){if(e.rendererInterfaces)for(let[,o]of e.rendererInterfaces)typeof o.setTraceUpdatesEnabled=="function"&&o.setTraceUpdatesEnabled(!0);typeof e.sub=="function"&&(ye=e.sub("traceUpdates",ho))}}var de=null,ke=!1;function po(){if(de!==null||typeof requestAnimationFrame!="function")return;let e=()=>{de=requestAnimationFrame(e),!(ke||!he||!Z)&&(ke=!0,qe().finally(()=>{ke=!1}))};de=requestAnimationFrame(e)}function mo(){de!==null&&typeof cancelAnimationFrame=="function"&&cancelAnimationFrame(de),de=null}function $e(){mo(),ye&&(ye(),ye=null)}function ho(e){!he||!Z||qe()}function qe(){return ve(Z).then(e=>{if(e&&i.targetRect){let o=i.targetRect;(Math.abs(e.x-o.x)>.5||Math.abs(e.y-o.y)>.5||Math.abs(e.width-o.width)>.5||Math.abs(e.height-o.height)>.5)&&(i={...i,targetRect:e},V())}}).catch(()=>{})}function je(e){return new Promise(o=>{pe.getSize(e,(n,a)=>o({width:n,height:a}),()=>o(null))})}var p={subscribe(e){return Ae.add(e),e(i),()=>Ae.delete(e)},getState(){return i},async setTarget(e,o,n){Z=e,Re=o;let a=n?.stateNode??e,{rect:r,freshInstance:y}=await Ue(a,o);Z=y;let T=go(Z);i={...i,mode:"component",targetTag:T,targetLabel:o,targetRect:r},V()},async setImageUri(e){let o=await je(e),n=1;o&&i.targetRect&&o.width>0&&(n=i.targetRect.width/o.width),i={...i,imageUri:e,imageWidth:o?.width??null,imageHeight:o?.height??null,scale:n,showOutline:!1},V()},setOpacity(e){i={...i,opacity:Math.max(0,Math.min(1,e))},V()},setScale(e){i={...i,scale:Math.max(.01,Math.min(5,e))},V()},setOffset(e,o){i={...i,offsetX:e,offsetY:o},V()},toggleInvertX(){i={...i,invertX:!i.invertX},V()},toggleInvertY(){i={...i,invertY:!i.invertY},V()},setLocked(e){i={...i,locked:e},V()},setAutoTrack(e){he=e,e?(fo(),po()):$e()},isAutoTracking(){return he},setShowOutline(e){i={...i,showOutline:e},V()},setEnabled(e){i={...i,enabled:e},V()},toggle(){i={...i,enabled:!i.enabled},V()},fitWidth(){i.imageWidth&&i.targetRect&&i.imageWidth>0&&(i={...i,scale:i.targetRect.width/i.imageWidth},V())},fitHeight(){i.imageHeight&&i.targetRect&&i.imageHeight>0&&(i={...i,scale:i.targetRect.height/i.imageHeight},V())},resetSettings(){if(i.mode==="free"){let e=se.get("window"),o=i.imageWidth??200,n=i.imageHeight??200;i={...i,opacity:.5,freeX:(e.width-o)/2,freeY:(e.height-n)/2,freeWidth:o,freeHeight:n}}else{let e=1;i.imageWidth&&i.targetRect&&i.imageWidth>0&&(e=i.targetRect.width/i.imageWidth),i={...i,opacity:.5,scale:e,offsetX:0,offsetY:0}}V()},async remeasure(){if(!Re)return;let{rect:e,freshInstance:o}=await Ue(Z,Re);Z=o,e&&(i={...i,targetRect:e},V())},async startFreeMode(e){let o=await je(e),n=se.get("window"),a=o?.width??200,r=o?.height??200,y=a,T=r,h=n.width*.8,b=n.height*.6;if(y>h||T>b){let c=Math.min(h/y,b/T);y=Math.round(y*c),T=Math.round(T*c)}i={...i,mode:"free",enabled:!0,imageUri:e,imageWidth:o?.width??null,imageHeight:o?.height??null,opacity:.5,freeX:Math.round((n.width-y)/2),freeY:Math.round((n.height-T)/2),freeWidth:Math.round(y),freeHeight:Math.round(T)},V()},setFreePosition(e,o){i={...i,freeX:e,freeY:o},V()},setFreeDimensions(e,o,n,a){i={...i,freeWidth:e,freeHeight:o,freeX:n,freeY:a},V()},reset(){$e(),he=!1,uo=null,Z=null,Re=null,i={...Ge},V()}};import{ChevronRight as yo,night as q,Hash as bo,ToolEmptyState as xo,monoFont as Le}from"@buoy-gg/shared-ui/web";import{jsx as K,jsxs as be}from"react/jsx-runtime";function To({target:e,onSelect:o}){return be(O,{style:X.card,onPress:o,activeOpacity:.7,children:[K(l,{style:X.colorIndicator}),be(l,{style:X.content,children:[K(l,{style:X.topRow,children:K(g,{style:X.label,numberOfLines:1,children:e.label})}),be(l,{style:X.bottomRow,children:[be(l,{style:X.badgeRow,children:[be(l,{style:X.testIdBadge,children:[K(bo,{size:8,color:q.color.accent}),K(g,{style:X.testIdBadgeText,children:"testID"})]}),K(g,{style:X.testIdValue,numberOfLines:1,children:e.testID})]}),e.componentName&&K(g,{style:X.componentName,numberOfLines:1,children:e.componentName})]})]}),K(yo,{size:16,color:q.color.textTertiary})]})}function Ke({targets:e,onSelect:o}){return e.length===0?K(xo,{testID:"buoy-image-overlay-empty",otto:"scanning",title:"No targets found",message:`Tag components with
|
|
3
|
+
testID="image-target:YourLabel"`}):K(Pe,{style:X.list,contentContainerStyle:X.listContent,children:e.map(n=>K(To,{target:n,onSelect:()=>o(n)},n.testID))})}var X=J.create({list:{flex:1},listContent:{paddingTop:8,paddingBottom:20},card:{flexDirection:"row",alignItems:"center",paddingVertical:10,paddingHorizontal:12,marginHorizontal:12,marginBottom:6,backgroundColor:q.color.surface,borderRadius:8,borderWidth:1,borderColor:q.color.border},colorIndicator:{width:4,height:36,borderRadius:2,marginRight:10,backgroundColor:q.color.accent},content:{flex:1,marginRight:8},topRow:{flexDirection:"row",alignItems:"center",marginBottom:4},label:{fontSize:13,fontWeight:"600",color:q.color.text,flex:1},bottomRow:{gap:2},badgeRow:{flexDirection:"row",alignItems:"center",gap:4},testIdBadge:{flexDirection:"row",alignItems:"center",paddingVertical:2,paddingHorizontal:5,borderRadius:4,backgroundColor:q.color.accentSoft,gap:3},testIdBadgeText:{fontSize:9,fontWeight:"700",color:q.color.accent},testIdValue:{fontSize:11,color:q.color.text,fontFamily:Le,flex:1},componentName:{fontSize:10,color:"#a855f7",fontFamily:Le,marginTop:1},emptyState:{alignItems:"center",paddingVertical:40,paddingHorizontal:32},emptyTitle:{color:q.color.text,fontSize:14,fontWeight:"600",marginBottom:6},emptyText:{color:q.color.textTertiary,fontSize:12,textAlign:"center",lineHeight:18,fontFamily:Le}});import{useRef as oe,useCallback as Ce}from"react";import{night as Q,monoFont as wo}from"@buoy-gg/shared-ui/web";import{jsx as F,jsxs as Ie}from"react/jsx-runtime";function xe({label:e,value:o,min:n,max:a,step:r,displayValue:y,onChange:T}){let h=oe(0),b=oe(0),c=Ce(S=>Math.max(n,Math.min(a,S)),[n,a]),v=a>n?(o-n)/(a-n):0,L=oe(T),N=oe(c),u=oe(n),W=oe(a);L.current=T,N.current=c,u.current=n,W.current=a;let H=Ce(S=>{let E=S-b.current,k=Math.max(0,Math.min(1,E/h.current)),A=u.current+k*(W.current-u.current);L.current(N.current(A))},[]),D=oe(ce.create({onStartShouldSetPanResponder:()=>!0,onMoveShouldSetPanResponder:()=>!0,onPanResponderTerminationRequest:()=>!1,onPanResponderGrant:S=>{H(S.nativeEvent.pageX)},onPanResponderMove:S=>{H(S.nativeEvent.pageX)}})).current,U=Ce(S=>{h.current=S.nativeEvent.layout.width},[]),ee=oe(null),_=Ce(()=>{ee.current?.measure?.((S,E,k,A,x)=>{b.current=x})},[]);return Ie(l,{style:Y.controlRow,children:[F(g,{style:Y.label,children:e}),Ie(l,{style:Y.controlRight,children:[F(O,{style:Y.stepperButton,onPress:()=>T(c(o-r)),activeOpacity:.6,children:F(g,{style:Y.stepperButtonText,children:"-"})}),F(l,{style:Y.sliderHitArea,...D.panHandlers,children:Ie(l,{ref:ee,style:Y.sliderTrack,onLayout:S=>{U(S),_()},pointerEvents:"none",children:[F(l,{style:[Y.sliderFill,{width:`${v*100}%`}]}),F(l,{style:[Y.sliderThumb,{left:`${v*100}%`}]})]})}),F(O,{style:Y.stepperButton,onPress:()=>T(c(o+r)),activeOpacity:.6,children:F(g,{style:Y.stepperButtonText,children:"+"})}),F(g,{style:Y.valueText,children:y})]})]})}function ze({opacity:e,scale:o,offsetX:n,offsetY:a,onOpacityChange:r,onScaleChange:y,onOffsetChange:T,opacityOnly:h}){return h?F(xe,{label:"Opacity",value:e,min:0,max:1,step:.05,displayValue:`${Math.round(e*100)}%`,onChange:r}):Ie(l,{style:Y.container,children:[F(xe,{label:"Opacity",value:e,min:0,max:1,step:.05,displayValue:`${Math.round(e*100)}%`,onChange:r}),F(xe,{label:"Scale",value:o,min:.05,max:3,step:.05,displayValue:`${Math.round(o*100)}%`,onChange:y}),F(xe,{label:"Offset X",value:n,min:-200,max:200,step:2,displayValue:`${Math.round(n)}px`,onChange:b=>T(Math.round(b),a)}),F(xe,{label:"Offset Y",value:a,min:-200,max:200,step:2,displayValue:`${Math.round(a)}px`,onChange:b=>T(n,Math.round(b))})]})}var Y=J.create({container:{gap:8},controlRow:{paddingHorizontal:12,gap:4},label:{fontSize:11,fontWeight:"600",color:Q.color.textTertiary,textTransform:"uppercase",letterSpacing:.5},controlRight:{flexDirection:"row",alignItems:"center",gap:6},stepperButton:{width:28,height:28,borderRadius:6,backgroundColor:Q.color.surfaceElevated,borderWidth:1,borderColor:Q.color.border,justifyContent:"center",alignItems:"center"},stepperButtonText:{fontSize:16,fontWeight:"700",color:Q.color.text,lineHeight:18},sliderHitArea:{flex:1,paddingVertical:20,paddingHorizontal:40,marginVertical:-20,marginHorizontal:-40},sliderTrack:{height:28,justifyContent:"center",borderRadius:6,backgroundColor:Q.color.bg,borderWidth:1,borderColor:Q.color.border,overflow:"hidden"},sliderFill:{position:"absolute",left:0,top:0,bottom:0,backgroundColor:Q.color.accentFill,borderRadius:5},sliderThumb:{position:"absolute",width:4,top:4,bottom:4,marginLeft:-2,borderRadius:2,backgroundColor:Q.color.accent},valueText:{fontSize:11,fontWeight:"600",color:Q.color.text,width:45,textAlign:"right",fontFamily:wo}});import{Fragment as Ze,jsx as s,jsxs as f}from"react/jsx-runtime";var re="";function Me({visible:e,onClose:o,onBack:n,onMinimize:a,enableSharedModalDimensions:r=!1,initialModalState:y,minimizeTargetPosition:T,inline:h=!1,initialView:b}){let[c,v]=Te(()=>{if(b)return b;let d=p.getState();return d.mode==="free"?"free":d.targetRect?"controls":"idle"}),[L,N]=Te(()=>b==="targets"?ne():[]),[u,W]=Te(()=>p.getState()),[H,D]=Te(re),[U,ee]=Te(()=>p.isAutoTracking());De(()=>{re=H},[H]),De(()=>p.subscribe(W),[]),De(()=>(p.setAutoTrack(U),()=>{}),[U]);let _=ue(()=>{let d=ne();N(d),v("targets")},[]),S=ue(async d=>{await p.setTarget(d.instance,d.label,d.fiber),re.trim()&&(await p.setImageUri(re.trim()),p.setEnabled(!0)),v("controls")},[]),E=ue(async()=>{let d=re.trim();d&&(c==="free"?await p.startFreeMode(d):(await p.setImageUri(d),p.setEnabled(!0)))},[c]),k=ue(async()=>{let d=null;try{d=Xe()}catch{}let w=null;if(!d)try{let C=Ye();w=C.default||C}catch{}if(!d&&!w){le.alert("Clipboard not available","Install expo-clipboard or @react-native-clipboard/clipboard to use paste.");return}try{if(d&&typeof d.hasImageAsync=="function"&&await d.hasImageAsync()){let $=await d.getImageAsync({format:"png"});if($?.data){c==="free"?await p.startFreeMode($.data):(await p.setImageUri($.data),p.setEnabled(!0));return}}let C=null;if(d&&typeof d.getStringAsync=="function"?C=await d.getStringAsync():w&&typeof w.getString=="function"&&(C=await w.getString()),C&&(C.startsWith("http")||C.startsWith("data:"))){D(C),re=C;return}d?le.alert("No image detected","Try saving your design image, opening it in Photos or Preview, and copying it from there."):le.alert("Image paste requires expo-clipboard","Your project uses @react-native-clipboard/clipboard which only supports text. Install expo-clipboard to paste images directly, or paste an image URL instead.")}catch{le.alert("Paste failed","Something went wrong reading the clipboard. Try copying the image again.")}},[c]),A=ue(()=>{p.reset(),re="",v("idle"),D(""),N([])},[]),x=ue(()=>{if(c==="controls"){let d=ne();N(d),v("targets")}else(c==="targets"||c==="free")&&p.reset(),v("idle")},[c]),z=(()=>{switch(c){case"targets":return`Targets (${L.length})`;case"controls":return u.targetLabel||"Component Match";case"free":return"Free Placement";default:return"Image Overlay"}})(),ae={showToggleButton:!1,customContent:f(Oe,{children:[s(Oe.Navigation,{onBack:c!=="idle"?x:n}),s(Oe.Content,{title:z}),f(Oe.Actions,{children:[c==="targets"&&s(O,{style:t.headerTextButton,onPress:_,activeOpacity:.7,children:s(g,{style:t.headerTextButtonLabel,children:"Scan"})}),(c==="controls"||c==="free")&&u.imageUri&&s(Io,{isEnabled:u.enabled,onToggle:()=>p.toggle(),accessibilityLabel:"Toggle image overlay"}),c!=="idle"&&s(O,{style:t.headerActionButton,onPress:A,activeOpacity:.7,children:s(So,{size:14,color:m.color.textSecondary})})]})]})},ie=f(l,{style:t.container,children:[c==="idle"&&f(l,{style:t.homeContainer,children:[s(g,{style:t.homeSubtitle,children:"Choose a mode"}),f(l,{style:t.modeGrid,children:[f(O,{style:t.modePanel,onPress:_,activeOpacity:.7,children:[s(l,{style:[t.modeIconCircle,{backgroundColor:m.color.accentSoft}],children:s(Ro,{size:24,color:m.color.accent})}),f(g,{style:t.modePanelTitle,children:["Component",`
|
|
4
|
+
`,"Match"]}),s(g,{style:t.modePanelDesc,children:"Overlay on a tagged component"})]}),f(O,{style:t.modePanel,onPress:()=>v("free"),activeOpacity:.7,children:[s(l,{style:[t.modeIconCircle,{backgroundColor:m.color.accentSoft}],children:s(Co,{size:24,color:m.color.accent})}),f(g,{style:t.modePanelTitle,children:["Free",`
|
|
5
|
+
`,"Placement"]}),s(g,{style:t.modePanelDesc,children:"Drag and resize anywhere"})]})]})]}),c==="targets"&&s(Ke,{targets:L,onSelect:S}),c==="controls"&&f(l,{style:t.controlsContainer,children:[u.targetRect&&f(l,{style:t.infoCard,children:[f(l,{style:t.infoRow,children:[s(g,{style:t.infoLabel,children:"Component"}),s(g,{style:t.infoValue,children:u.targetLabel})]}),f(l,{style:t.infoRow,children:[s(g,{style:t.infoLabel,children:"Size"}),f(g,{style:t.infoValueMono,children:[Math.round(u.targetRect.width)," x ",Math.round(u.targetRect.height)]})]}),f(l,{style:t.infoRow,children:[s(g,{style:t.infoLabel,children:"Position"}),f(g,{style:t.infoValueMono,children:[Math.round(u.targetRect.x),", ",Math.round(u.targetRect.y)]})]}),u.imageWidth!=null&&u.imageHeight!=null&&f(l,{style:t.infoRow,children:[s(g,{style:t.infoLabel,children:"Image"}),f(g,{style:t.infoValueMono,children:[u.imageWidth," x ",u.imageHeight]})]})]}),f(l,{style:t.inputSection,children:[s(g,{style:t.sectionLabel,children:"Image"}),s(O,{style:t.pasteButton,onPress:k,activeOpacity:.7,accessibilityLabel:"Paste from clipboard",accessibilityRole:"button",children:s(g,{style:t.pasteButtonText,children:"Paste from Clipboard"})}),f(l,{style:t.urlRow,children:[s(we,{style:t.urlInput,value:H,onChangeText:D,placeholder:"or enter URL...",placeholderTextColor:m.color.placeholder,autoCapitalize:"none",autoCorrect:!1,returnKeyType:"go",onSubmitEditing:E}),s(O,{style:[t.loadButton,!H.trim()&&t.loadButtonDisabled],onPress:E,disabled:!H.trim(),activeOpacity:.7,children:s(g,{style:t.loadButtonText,children:"Load"})})]})]}),f(l,{style:t.toggleSection,children:[s(Ee,{label:"Show Outline",value:u.showOutline,onValueChange:d=>p.setShowOutline(d)}),s(Ee,{label:"Auto Track",value:U,onValueChange:ee}),u.imageUri&&f(Ze,{children:[f(l,{style:t.blendRow,children:[s(g,{style:t.toggleLabel,children:"Opacity"}),s(l,{style:t.blendButtons,children:[0,25,50,75,100].map(d=>s(O,{style:[t.blendButton,Math.round(u.opacity*100)===d&&t.blendButtonActive],onPress:()=>p.setOpacity(d/100),activeOpacity:.7,children:f(g,{style:[t.blendButtonText,Math.round(u.opacity*100)===d&&t.blendButtonTextActive],children:[d,"%"]})},d))})]}),f(l,{style:t.blendRow,children:[s(g,{style:t.toggleLabel,children:"Flip"}),f(l,{style:t.blendButtons,children:[s(O,{style:[t.blendButton,u.invertX&&t.blendButtonActive],onPress:()=>p.toggleInvertX(),activeOpacity:.7,children:s(g,{style:[t.blendButtonText,u.invertX&&t.blendButtonTextActive],children:"Horizontal"})}),s(O,{style:[t.blendButton,u.invertY&&t.blendButtonActive],onPress:()=>p.toggleInvertY(),activeOpacity:.7,children:s(g,{style:[t.blendButtonText,u.invertY&&t.blendButtonTextActive],children:"Vertical"})})]})]})]})]}),u.imageUri&&s(ze,{opacity:u.opacity,scale:u.scale,offsetX:u.offsetX,offsetY:u.offsetY,onOpacityChange:d=>p.setOpacity(d),onScaleChange:d=>p.setScale(d),onOffsetChange:(d,w)=>p.setOffset(d,w)}),f(l,{style:t.actions,children:[s(O,{style:t.actionButton,onPress:()=>p.resetSettings(),activeOpacity:.7,children:s(g,{style:t.actionButtonText,children:"Reset Settings"})}),s(O,{style:t.actionButton,onPress:()=>p.remeasure(),activeOpacity:.7,children:s(g,{style:t.actionButtonText,children:"Remeasure"})})]})]}),c==="free"&&f(l,{style:t.controlsContainer,children:[f(l,{style:t.inputSection,children:[s(g,{style:t.sectionLabel,children:"Image"}),s(O,{style:t.pasteButton,onPress:k,activeOpacity:.7,accessibilityLabel:"Paste from clipboard",accessibilityRole:"button",children:s(g,{style:t.pasteButtonText,children:"Paste from Clipboard"})}),f(l,{style:t.urlRow,children:[s(we,{style:t.urlInput,value:H,onChangeText:D,placeholder:"or enter URL...",placeholderTextColor:m.color.placeholder,autoCapitalize:"none",autoCorrect:!1,returnKeyType:"go",onSubmitEditing:E}),s(O,{style:[t.loadButton,!H.trim()&&t.loadButtonDisabled],onPress:E,disabled:!H.trim(),activeOpacity:.7,children:s(g,{style:t.loadButtonText,children:"Load"})})]})]}),u.imageUri&&u.mode==="free"&&f(Ze,{children:[f(l,{style:t.infoCard,children:[f(l,{style:t.infoRow,children:[s(g,{style:t.infoLabel,children:"Position"}),f(g,{style:t.infoValueMono,children:[Math.round(u.freeX),", ",Math.round(u.freeY)]})]}),f(l,{style:t.infoRow,children:[s(g,{style:t.infoLabel,children:"Size"}),f(g,{style:t.infoValueMono,children:[Math.round(u.freeWidth)," x ",Math.round(u.freeHeight)]})]}),u.imageWidth!=null&&u.imageHeight!=null&&f(l,{style:t.infoRow,children:[s(g,{style:t.infoLabel,children:"Original"}),f(g,{style:t.infoValueMono,children:[u.imageWidth," x ",u.imageHeight]})]})]}),s(l,{style:t.inputSection,children:s(ze,{opacity:u.opacity,scale:1,offsetX:0,offsetY:0,onOpacityChange:d=>p.setOpacity(d),onScaleChange:()=>{},onOffsetChange:()=>{},opacityOnly:!0})}),f(l,{style:t.toggleSection,children:[s(Ee,{label:"Lock Position",tone:"warning",value:u.locked,onValueChange:d=>p.setLocked(d)}),f(l,{style:t.blendRow,children:[s(g,{style:t.toggleLabel,children:"Opacity"}),s(l,{style:t.blendButtons,children:[0,25,50,75,100].map(d=>s(O,{style:[t.blendButton,Math.round(u.opacity*100)===d&&t.blendButtonActive],onPress:()=>p.setOpacity(d/100),activeOpacity:.7,children:f(g,{style:[t.blendButtonText,Math.round(u.opacity*100)===d&&t.blendButtonTextActive],children:[d,"%"]})},d))})]}),f(l,{style:t.blendRow,children:[s(g,{style:t.toggleLabel,children:"Flip"}),f(l,{style:t.blendButtons,children:[s(O,{style:[t.blendButton,u.invertX&&t.blendButtonActive],onPress:()=>p.toggleInvertX(),activeOpacity:.7,children:s(g,{style:[t.blendButtonText,u.invertX&&t.blendButtonTextActive],children:"Horizontal"})}),s(O,{style:[t.blendButton,u.invertY&&t.blendButtonActive],onPress:()=>p.toggleInvertY(),activeOpacity:.7,children:s(g,{style:[t.blendButtonText,u.invertY&&t.blendButtonTextActive],children:"Vertical"})})]})]})]}),s(l,{style:t.actions,children:s(O,{style:t.actionButton,onPress:()=>p.resetSettings(),activeOpacity:.7,children:s(g,{style:t.actionButtonText,children:"Reset Position"})})})]})]})]});return h?f(l,{style:t.inlineRoot,children:[s(l,{style:t.inlineHeader,...Oo,children:ae.customContent}),ie]}):s(vo,{visible:e,onClose:o,onMinimize:a,minimizeTargetPosition:T,initialModalState:y,header:ae,initialMode:"bottomSheet",persistenceKey:"buoy-image-overlay-modal",enablePersistence:!0,children:ie})}function Vo(e={}){return s(Me,{...e,inline:!0,visible:!0,onClose:()=>{}})}var t=J.create({inlineRoot:{flex:1,minHeight:0,backgroundColor:Je.background.base},inlineHeader:{borderBottomWidth:1,borderBottomColor:Je.border.default,backgroundColor:"transparent"},container:{flex:1,backgroundColor:"transparent"},headerTextButton:{height:32,paddingHorizontal:12,borderRadius:8,backgroundColor:m.color.buttonSurface,borderWidth:1,borderColor:m.color.border,alignItems:"center",justifyContent:"center"},headerTextButtonLabel:{fontSize:12,fontWeight:"600",color:m.color.accent},headerActionButton:{width:32,height:32,borderRadius:8,backgroundColor:m.color.buttonSurface,borderWidth:1,borderColor:m.color.border,alignItems:"center",justifyContent:"center"},homeContainer:{flex:1,paddingHorizontal:12,paddingTop:16,paddingBottom:20,gap:12},homeSubtitle:{fontSize:12,fontWeight:"600",color:m.color.textTertiary,textTransform:"uppercase",letterSpacing:.5,textAlign:"center"},modeGrid:{flexDirection:"row",gap:10},modePanel:{flex:1,alignItems:"center",paddingVertical:20,paddingHorizontal:12,backgroundColor:m.color.surface,borderRadius:12,borderWidth:1,borderColor:m.color.border,gap:8},modeIconCircle:{width:48,height:48,borderRadius:24,alignItems:"center",justifyContent:"center",marginBottom:4},modePanelTitle:{fontSize:13,fontWeight:"700",color:m.color.text,textAlign:"center",lineHeight:17},modePanelDesc:{fontSize:11,color:m.color.textTertiary,textAlign:"center",lineHeight:15},controlsContainer:{flex:1,paddingTop:8,paddingBottom:24,gap:10},infoCard:{marginHorizontal:12,backgroundColor:m.color.surface,borderRadius:8,borderWidth:1,borderColor:m.color.border,padding:10,gap:4},infoRow:{flexDirection:"row",justifyContent:"space-between",alignItems:"center"},infoLabel:{fontSize:11,fontWeight:"500",color:m.color.textTertiary,textTransform:"uppercase",letterSpacing:.3},infoValue:{fontSize:12,fontWeight:"600",color:m.color.text},infoValueMono:{fontSize:12,fontWeight:"600",color:m.color.text,fontFamily:Mo},inputSection:{paddingHorizontal:12,gap:6},sectionLabel:{fontSize:11,fontWeight:"600",color:m.color.textTertiary,textTransform:"uppercase",letterSpacing:.5},pasteButton:{paddingVertical:10,borderRadius:8,backgroundColor:m.color.accentSoft,borderWidth:1,borderColor:m.color.accentBorderStrong,alignItems:"center"},pasteButtonText:{fontSize:13,fontWeight:"600",color:m.color.accent},urlRow:{flexDirection:"row",gap:8},urlInput:{flex:1,height:36,borderRadius:10,backgroundColor:m.color.surfaceElevated,borderWidth:1,borderColor:m.color.border,paddingHorizontal:12,fontSize:13,color:m.color.text},loadButton:{height:36,paddingHorizontal:14,borderRadius:8,backgroundColor:m.color.accent,justifyContent:"center",alignItems:"center"},loadButtonDisabled:{opacity:.4},loadButtonText:{fontSize:13,fontWeight:"600",color:m.color.onAccent},toggleSection:{paddingHorizontal:12,gap:6},toggleRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",backgroundColor:m.color.surfaceElevated,borderRadius:8,borderWidth:1,borderColor:m.color.border,paddingHorizontal:12,paddingVertical:8},toggleLabel:{fontSize:13,fontWeight:"500",color:m.color.textSecondary},blendRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",backgroundColor:m.color.surfaceElevated,borderRadius:8,borderWidth:1,borderColor:m.color.border,paddingHorizontal:12,paddingVertical:6},blendButtons:{flexDirection:"row",gap:4},blendButton:{paddingHorizontal:10,paddingVertical:5,borderRadius:6,backgroundColor:"transparent"},blendButtonActive:{backgroundColor:m.color.accentSoft},blendButtonText:{fontSize:12,fontWeight:"600",color:m.color.textTertiary},blendButtonTextActive:{color:m.color.accent},actions:{flexDirection:"row",paddingHorizontal:12,gap:8,marginTop:4},actionButton:{flex:1,flexDirection:"row",alignItems:"center",justifyContent:"center",gap:6,paddingVertical:8,paddingHorizontal:12,borderRadius:8,backgroundColor:m.color.surfaceElevated,borderWidth:1,borderColor:m.color.border},actionButtonText:{fontSize:12,fontWeight:"500",color:m.color.textSecondary}});import{jsx as Ao}from"react/jsx-runtime";var Ho="#A855F7",Qe=Wo({id:"image-overlay",name:"IMG",description:"Design mockup overlay",slot:"both",icon:({size:e})=>Ao(Po,{size:e,color:Ho}),component:Me,props:{enableSharedModalDimensions:!1}}),ko=Bo(Qe,e=>({enableSharedModalDimensions:e.enableSharedModalDimensions??!1}));import{useState as ot,useEffect as Lo,useRef as et,useMemo as tt,useCallback as zo}from"react";import{absoluteFill as Do,monoFont as Eo}from"@buoy-gg/shared-ui/web";import{Fragment as rt,jsx as B,jsxs as Ve}from"react/jsx-runtime";function nt({uri:e,style:o,invertX:n,invertY:a}){let r=[];n&&r.push({scaleX:-1}),a&&r.push({scaleY:-1});let y=r.length>0?{transform:r}:{};return B(pe,{testID:"buoy-internal-image-overlay",source:{uri:e},style:[o,y],pointerEvents:"none"})}var ge=30;function Fo({imageUri:e,x:o,y:n,width:a,height:r,opacity:y,aspectRatio:T,invertX:h,invertY:b,locked:c}){let[v,L]=ot(!1),N=et({x:0,y:0}),u=et({x:0,y:0,width:0,height:0}),W=se.get("window"),H=tt(()=>ce.create({onStartShouldSetPanResponder:()=>!c,onMoveShouldSetPanResponder:(_,S)=>!c&&(Math.abs(S.dx)>2||Math.abs(S.dy)>2),onPanResponderTerminationRequest:()=>!1,onPanResponderGrant:()=>{let _=p.getState();N.current={x:_.freeX,y:_.freeY},L(!0)},onPanResponderMove:(_,S)=>{let E=p.getState(),k=Math.max(0,Math.min(N.current.x+S.dx,W.width-E.freeWidth)),A=Math.max(0,Math.min(N.current.y+S.dy,W.height-E.freeHeight));p.setFreePosition(k,A)},onPanResponderRelease:()=>L(!1),onPanResponderTerminate:()=>L(!1)}),[W.width,W.height,c]),D=zo(_=>ce.create({onStartShouldSetPanResponder:()=>!c,onMoveShouldSetPanResponder:()=>!c,onPanResponderTerminationRequest:()=>!1,onPanResponderGrant:()=>{let S=p.getState();u.current={x:S.freeX,y:S.freeY,width:S.freeWidth,height:S.freeHeight},L(!0)},onPanResponderMove:(S,E)=>{let{dx:k,dy:A}=E;if(Math.abs(k)<.5&&Math.abs(A)<.5)return;let x=u.current,z=T>0?T:x.width/x.height,ae=Math.abs(k),ie=Math.abs(A),d=ae>=ie,w,C,te=x.x,$=x.y;switch(_){case"bottomRight":{w=d?x.width+k:(x.height+A)*z,w=Math.max(ge,Math.min(w,W.width-x.x)),C=w/z;break}case"bottomLeft":{w=d?x.width-k:(x.height+A)*z,w=Math.max(ge,w),C=w/z,te=x.x+x.width-w,te=Math.max(0,te),w=Math.min(w,x.x+x.width),C=w/z;break}case"topRight":{w=d?x.width+k:(x.height-A)*z,w=Math.max(ge,Math.min(w,W.width-x.x)),C=w/z,$=x.y+x.height-C,$=Math.max(0,$),C=Math.min(C,x.y+x.height),w=C*z;break}case"topLeft":{w=d?x.width-k:(x.height-A)*z,w=Math.max(ge,w),C=w/z,te=x.x+x.width-w,$=x.y+x.height-C,te=Math.max(0,te),$=Math.max(0,$),w=Math.min(w,x.x+x.width),C=w/z,$=x.y+x.height-C;break}}w=Math.max(ge,Math.round(w)),C=Math.max(ge,Math.round(C)),p.setFreeDimensions(w,C,Math.round(te),Math.round($))},onPanResponderRelease:()=>L(!1),onPanResponderTerminate:()=>L(!1)}),[W.width,W.height,T,c]),U=tt(()=>({topLeft:D("topLeft"),topRight:D("topRight"),bottomLeft:D("bottomLeft"),bottomRight:D("bottomRight")}),[D]),ee={...Do,opacity:y};return Ve(l,{style:{position:"absolute",left:o,top:n,width:a,height:r},pointerEvents:c?"none":"auto",children:[B(l,{style:J.absoluteFill,...c?{}:H.panHandlers,children:B(nt,{uri:e,style:ee,invertX:h,invertY:b})}),B(l,{pointerEvents:"none",style:[P.freeBorder,v&&P.freeBorderActive,c&&P.freeBorderLocked]}),!c&&Ve(rt,{children:[B(l,{...U.topLeft.panHandlers,style:[P.cornerWrapper,{top:-20,left:-20}],hitSlop:{top:10,left:10,right:10,bottom:10},children:B(l,{style:[P.cornerHandle,v&&P.cornerHandleActive]})}),B(l,{...U.topRight.panHandlers,style:[P.cornerWrapper,{top:-20,right:-20}],hitSlop:{top:10,left:10,right:10,bottom:10},children:B(l,{style:[P.cornerHandle,v&&P.cornerHandleActive]})}),B(l,{...U.bottomLeft.panHandlers,style:[P.cornerWrapper,{bottom:-20,left:-20}],hitSlop:{top:10,left:10,right:10,bottom:10},children:B(l,{style:[P.cornerHandle,v&&P.cornerHandleActive]})}),B(l,{...U.bottomRight.panHandlers,style:[P.cornerWrapper,{bottom:-20,right:-20}],hitSlop:{top:10,left:10,right:10,bottom:10},children:B(l,{style:[P.cornerHandle,v&&P.cornerHandleActive]})})]})]})}function _o(){let[e,o]=ot(()=>p.getState());Lo(()=>p.subscribe(o),[]);let{mode:n,enabled:a,imageUri:r,imageWidth:y,imageHeight:T,targetRect:h,targetLabel:b,showOutline:c,opacity:v,scale:L,offsetX:N,offsetY:u,invertX:W,invertY:H,locked:D,freeX:U,freeY:ee,freeWidth:_,freeHeight:S}=e,E=y&&T&&T>0?y/T:0;if(n==="free"&&a&&r)return B(l,{style:P.overlay,pointerEvents:"box-none",nativeID:"image-overlay-standalone",children:B(Fo,{imageUri:r,x:U,y:ee,width:_,height:S,opacity:v,aspectRatio:E,invertX:W,invertY:H,locked:D})});if(!h)return null;let k=a&&r;return Ve(l,{style:P.overlay,pointerEvents:"box-none",nativeID:"image-overlay-standalone",children:[c&&Ve(rt,{children:[B(l,{pointerEvents:"none",nativeID:"__image_overlay_highlight__",style:[P.highlight,{left:h.x-3,top:h.y-3,width:h.width+6,height:h.height+6}]}),b&&B(l,{pointerEvents:"none",style:[P.label,{left:h.x,top:h.y-20}],children:B(g,{style:P.labelText,children:b})})]}),k&&(()=>{let A=(y??h.width)*L,x=(T??h.height)*L,z=h.x+h.width/2,ae=h.y+h.height/2,ie={position:"absolute",left:z-A/2+N,top:ae-x/2+u,width:A,height:x,opacity:v};return B(nt,{uri:r,style:ie,invertX:W,invertY:H})})()]})}var P=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:Eo},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}});export{p as ImageOverlayController,Me as ImageOverlayModal,_o as ImageOverlayStandalone,Vo as ImageOverlayToolView,ko as createImageOverlayTool,Qe as imageOverlayToolPreset,ne as scanForImageTargets,no as setDevToolsHookOverride};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/image-overlay",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.41",
|
|
4
4
|
"description": "Overlay a design mockup on a running React Native app and adjust opacity to compare spacing and alignment.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -10,27 +10,37 @@
|
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"react-native": "./lib/module/index.js",
|
|
13
|
+
"browser": {
|
|
14
|
+
"types": "./lib/typescript/index.d.ts",
|
|
15
|
+
"default": "./lib/web/index.mjs"
|
|
16
|
+
},
|
|
13
17
|
"import": {
|
|
14
|
-
"
|
|
15
|
-
"
|
|
18
|
+
"types": "./lib/typescript/index.d.ts",
|
|
19
|
+
"default": "./lib/module/index.js"
|
|
16
20
|
},
|
|
17
21
|
"require": {
|
|
18
|
-
"
|
|
19
|
-
"
|
|
22
|
+
"types": "./lib/typescript/index.d.ts",
|
|
23
|
+
"default": "./lib/commonjs/index.js"
|
|
20
24
|
}
|
|
21
25
|
},
|
|
22
|
-
"./package.json": "./package.json"
|
|
26
|
+
"./package.json": "./package.json",
|
|
27
|
+
"./web": {
|
|
28
|
+
"types": "./lib/typescript/index.d.ts",
|
|
29
|
+
"default": "./lib/web/index.mjs"
|
|
30
|
+
}
|
|
23
31
|
},
|
|
24
32
|
"files": [
|
|
25
33
|
"lib"
|
|
26
34
|
],
|
|
27
35
|
"sideEffects": false,
|
|
28
36
|
"dependencies": {
|
|
29
|
-
"@buoy-gg/shared-ui": "^7.0.
|
|
37
|
+
"@buoy-gg/shared-ui": "^7.0.41"
|
|
30
38
|
},
|
|
31
39
|
"peerDependencies": {
|
|
32
40
|
"react": "*",
|
|
33
|
-
"react-native": "*"
|
|
41
|
+
"react-native": "*",
|
|
42
|
+
"react-native-web": "^0.21.0",
|
|
43
|
+
"react-dom": ">=18"
|
|
34
44
|
},
|
|
35
45
|
"devDependencies": {
|
|
36
46
|
"@types/react": "^19.1.0",
|
|
@@ -85,10 +95,22 @@
|
|
|
85
95
|
"pixel-perfect",
|
|
86
96
|
"ui-review"
|
|
87
97
|
],
|
|
98
|
+
"peerDependenciesMeta": {
|
|
99
|
+
"react-native": {
|
|
100
|
+
"optional": true
|
|
101
|
+
},
|
|
102
|
+
"react-native-web": {
|
|
103
|
+
"optional": true
|
|
104
|
+
},
|
|
105
|
+
"react-dom": {
|
|
106
|
+
"optional": true
|
|
107
|
+
}
|
|
108
|
+
},
|
|
88
109
|
"scripts": {
|
|
89
|
-
"build": "bob build",
|
|
110
|
+
"build": "bob build && pnpm run build:web",
|
|
90
111
|
"typecheck": "tsc --noEmit",
|
|
91
112
|
"clean": "rimraf lib",
|
|
92
|
-
"test": "pnpm run typecheck"
|
|
113
|
+
"test": "pnpm run typecheck",
|
|
114
|
+
"build:web": "node ../../scripts/build-web.mjs image-overlay"
|
|
93
115
|
}
|
|
94
116
|
}
|