@ewjdev/anyclick-react 0.1.0 → 1.1.1
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 +143 -49
- package/dist/index.d.mts +197 -15
- package/dist/index.d.ts +197 -15
- package/dist/index.js +1122 -320
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1115 -319
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -21,6 +21,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/index.ts
|
|
22
22
|
var index_exports = {};
|
|
23
23
|
__export(index_exports, {
|
|
24
|
+
AnyclickContext: () => AnyclickContext,
|
|
25
|
+
AnyclickProvider: () => AnyclickProvider,
|
|
24
26
|
ContextMenu: () => ContextMenu,
|
|
25
27
|
DEFAULT_SCREENSHOT_CONFIG: () => import_anyclick_core4.DEFAULT_SCREENSHOT_CONFIG,
|
|
26
28
|
DEFAULT_SENSITIVE_SELECTORS: () => import_anyclick_core4.DEFAULT_SENSITIVE_SELECTORS,
|
|
@@ -34,27 +36,40 @@ __export(index_exports, {
|
|
|
34
36
|
darkMenuStyles: () => darkMenuStyles,
|
|
35
37
|
defaultContainerSelectors: () => defaultContainerSelectors,
|
|
36
38
|
defaultHighlightColors: () => defaultHighlightColors,
|
|
39
|
+
dispatchContextMenuEvent: () => dispatchContextMenuEvent,
|
|
37
40
|
estimateTotalSize: () => import_anyclick_core4.estimateTotalSize,
|
|
38
41
|
filterMenuItemsByRole: () => filterMenuItemsByRole,
|
|
39
42
|
findContainerParent: () => findContainerParent,
|
|
40
43
|
formatBytes: () => import_anyclick_core4.formatBytes,
|
|
44
|
+
generateProviderId: () => generateProviderId,
|
|
41
45
|
highlightContainer: () => highlightContainer,
|
|
42
46
|
highlightTarget: () => highlightTarget,
|
|
43
47
|
isScreenshotSupported: () => import_anyclick_core4.isScreenshotSupported,
|
|
48
|
+
menuCSSVariables: () => menuCSSVariables,
|
|
44
49
|
menuStyles: () => menuStyles,
|
|
45
|
-
|
|
50
|
+
useAnyclick: () => useAnyclick,
|
|
51
|
+
useFeedback: () => useFeedback,
|
|
52
|
+
useProviderStore: () => useProviderStore
|
|
46
53
|
});
|
|
47
54
|
module.exports = __toCommonJS(index_exports);
|
|
48
55
|
|
|
49
|
-
// src/
|
|
56
|
+
// src/AnyclickProvider.tsx
|
|
50
57
|
var import_react6 = require("react");
|
|
51
58
|
var import_anyclick_core3 = require("@ewjdev/anyclick-core");
|
|
52
59
|
|
|
53
60
|
// src/context.ts
|
|
54
61
|
var import_react = require("react");
|
|
55
|
-
var
|
|
62
|
+
var AnyclickContext = (0, import_react.createContext)(null);
|
|
63
|
+
var FeedbackContext = AnyclickContext;
|
|
64
|
+
function useAnyclick() {
|
|
65
|
+
const context = (0, import_react.useContext)(AnyclickContext);
|
|
66
|
+
if (!context) {
|
|
67
|
+
throw new Error("useAnyclick must be used within an AnyclickProvider");
|
|
68
|
+
}
|
|
69
|
+
return context;
|
|
70
|
+
}
|
|
56
71
|
function useFeedback() {
|
|
57
|
-
const context = (0, import_react.useContext)(
|
|
72
|
+
const context = (0, import_react.useContext)(AnyclickContext);
|
|
58
73
|
if (!context) {
|
|
59
74
|
throw new Error("useFeedback must be used within a FeedbackProvider");
|
|
60
75
|
}
|
|
@@ -66,6 +81,25 @@ var import_react5 = require("react");
|
|
|
66
81
|
var import_anyclick_core2 = require("@ewjdev/anyclick-core");
|
|
67
82
|
|
|
68
83
|
// src/styles.ts
|
|
84
|
+
var menuCSSVariables = {
|
|
85
|
+
// Background colors
|
|
86
|
+
"--anyclick-menu-bg": "#ffffff",
|
|
87
|
+
"--anyclick-menu-hover": "#f5f5f5",
|
|
88
|
+
// Text colors
|
|
89
|
+
"--anyclick-menu-text": "#333333",
|
|
90
|
+
"--anyclick-menu-text-muted": "#666666",
|
|
91
|
+
// Border colors
|
|
92
|
+
"--anyclick-menu-border": "#e5e5e5",
|
|
93
|
+
// Accent/action colors
|
|
94
|
+
"--anyclick-menu-accent": "#0066cc",
|
|
95
|
+
"--anyclick-menu-accent-text": "#ffffff",
|
|
96
|
+
// Input colors
|
|
97
|
+
"--anyclick-menu-input-bg": "#ffffff",
|
|
98
|
+
"--anyclick-menu-input-border": "#dddddd",
|
|
99
|
+
// Cancel button
|
|
100
|
+
"--anyclick-menu-cancel-bg": "#f0f0f0",
|
|
101
|
+
"--anyclick-menu-cancel-text": "#666666"
|
|
102
|
+
};
|
|
69
103
|
var menuStyles = {
|
|
70
104
|
overlay: {
|
|
71
105
|
position: "fixed",
|
|
@@ -76,17 +110,19 @@ var menuStyles = {
|
|
|
76
110
|
position: "fixed",
|
|
77
111
|
zIndex: 9999,
|
|
78
112
|
minWidth: "200px",
|
|
79
|
-
backgroundColor: "#ffffff",
|
|
113
|
+
backgroundColor: "var(--anyclick-menu-bg, #ffffff)",
|
|
80
114
|
borderRadius: "8px",
|
|
81
115
|
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.05)",
|
|
82
116
|
overflow: "hidden",
|
|
83
117
|
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
84
|
-
fontSize: "14px"
|
|
118
|
+
fontSize: "14px",
|
|
119
|
+
// Set default CSS variables
|
|
120
|
+
...menuCSSVariables
|
|
85
121
|
},
|
|
86
122
|
header: {
|
|
87
123
|
padding: "12px 16px",
|
|
88
|
-
borderBottom: "1px solid #e5e5e5",
|
|
89
|
-
color: "#666",
|
|
124
|
+
borderBottom: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
125
|
+
color: "var(--anyclick-menu-text-muted, #666)",
|
|
90
126
|
fontSize: "12px",
|
|
91
127
|
fontWeight: 500,
|
|
92
128
|
textTransform: "uppercase",
|
|
@@ -102,15 +138,15 @@ var menuStyles = {
|
|
|
102
138
|
padding: "10px 16px",
|
|
103
139
|
cursor: "pointer",
|
|
104
140
|
transition: "background-color 0.15s",
|
|
105
|
-
color: "#333",
|
|
141
|
+
color: "var(--anyclick-menu-text, #333)",
|
|
106
142
|
border: "none",
|
|
107
|
-
|
|
143
|
+
backgroundColor: "transparent",
|
|
108
144
|
width: "100%",
|
|
109
145
|
textAlign: "left",
|
|
110
146
|
fontSize: "14px"
|
|
111
147
|
},
|
|
112
148
|
itemHover: {
|
|
113
|
-
backgroundColor: "#f5f5f5"
|
|
149
|
+
backgroundColor: "var(--anyclick-menu-hover, #f5f5f5)"
|
|
114
150
|
},
|
|
115
151
|
itemIcon: {
|
|
116
152
|
display: "flex",
|
|
@@ -122,19 +158,21 @@ var menuStyles = {
|
|
|
122
158
|
},
|
|
123
159
|
commentSection: {
|
|
124
160
|
padding: "12px 16px",
|
|
125
|
-
borderTop: "1px solid #e5e5e5"
|
|
161
|
+
borderTop: "1px solid var(--anyclick-menu-border, #e5e5e5)"
|
|
126
162
|
},
|
|
127
163
|
commentInput: {
|
|
128
164
|
width: "100%",
|
|
129
165
|
minHeight: "60px",
|
|
130
166
|
padding: "8px 12px",
|
|
131
|
-
border: "1px solid #ddd",
|
|
167
|
+
border: "1px solid var(--anyclick-menu-input-border, #ddd)",
|
|
132
168
|
borderRadius: "6px",
|
|
133
169
|
fontSize: "14px",
|
|
134
170
|
fontFamily: "inherit",
|
|
135
171
|
resize: "vertical",
|
|
136
172
|
outline: "none",
|
|
137
|
-
boxSizing: "border-box"
|
|
173
|
+
boxSizing: "border-box",
|
|
174
|
+
backgroundColor: "var(--anyclick-menu-input-bg, #ffffff)",
|
|
175
|
+
color: "var(--anyclick-menu-text, #333)"
|
|
138
176
|
},
|
|
139
177
|
buttonRow: {
|
|
140
178
|
display: "flex",
|
|
@@ -152,15 +190,15 @@ var menuStyles = {
|
|
|
152
190
|
border: "none"
|
|
153
191
|
},
|
|
154
192
|
cancelButton: {
|
|
155
|
-
backgroundColor: "#f0f0f0",
|
|
156
|
-
color: "#666",
|
|
193
|
+
backgroundColor: "var(--anyclick-menu-cancel-bg, #f0f0f0)",
|
|
194
|
+
color: "var(--anyclick-menu-cancel-text, #666)",
|
|
157
195
|
display: "flex",
|
|
158
196
|
alignItems: "center",
|
|
159
197
|
gap: "2px"
|
|
160
198
|
},
|
|
161
199
|
submitButton: {
|
|
162
|
-
backgroundColor: "#0066cc",
|
|
163
|
-
color: "#ffffff",
|
|
200
|
+
backgroundColor: "var(--anyclick-menu-accent, #0066cc)",
|
|
201
|
+
color: "var(--anyclick-menu-accent-text, #ffffff)",
|
|
164
202
|
display: "flex",
|
|
165
203
|
alignItems: "center",
|
|
166
204
|
gap: "2px"
|
|
@@ -204,6 +242,242 @@ var darkMenuStyles = {
|
|
|
204
242
|
color: "#ccc"
|
|
205
243
|
}
|
|
206
244
|
};
|
|
245
|
+
var screenshotPreviewStyles = {
|
|
246
|
+
container: {
|
|
247
|
+
width: "100%",
|
|
248
|
+
display: "flex",
|
|
249
|
+
flexDirection: "column",
|
|
250
|
+
gap: "8px"
|
|
251
|
+
},
|
|
252
|
+
containerExpanded: {
|
|
253
|
+
position: "fixed",
|
|
254
|
+
top: "50%",
|
|
255
|
+
left: "50%",
|
|
256
|
+
transform: "translate(-50%, -50%)",
|
|
257
|
+
width: "90vw",
|
|
258
|
+
maxWidth: "800px",
|
|
259
|
+
maxHeight: "90vh",
|
|
260
|
+
backgroundColor: "#fff",
|
|
261
|
+
borderRadius: "12px",
|
|
262
|
+
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
|
|
263
|
+
padding: "16px",
|
|
264
|
+
zIndex: 1e4
|
|
265
|
+
},
|
|
266
|
+
loadingContainer: {
|
|
267
|
+
display: "flex",
|
|
268
|
+
flexDirection: "column",
|
|
269
|
+
alignItems: "center",
|
|
270
|
+
justifyContent: "center",
|
|
271
|
+
gap: "12px",
|
|
272
|
+
padding: "24px"
|
|
273
|
+
},
|
|
274
|
+
loadingText: {
|
|
275
|
+
fontSize: "13px",
|
|
276
|
+
color: "#6b7280"
|
|
277
|
+
},
|
|
278
|
+
emptyContainer: {
|
|
279
|
+
display: "flex",
|
|
280
|
+
flexDirection: "column",
|
|
281
|
+
alignItems: "center",
|
|
282
|
+
justifyContent: "center",
|
|
283
|
+
gap: "8px",
|
|
284
|
+
padding: "24px"
|
|
285
|
+
},
|
|
286
|
+
emptyText: {
|
|
287
|
+
fontSize: "13px",
|
|
288
|
+
color: "#6b7280",
|
|
289
|
+
fontWeight: "500"
|
|
290
|
+
},
|
|
291
|
+
emptySubtext: {
|
|
292
|
+
fontSize: "11px",
|
|
293
|
+
color: "#9ca3af",
|
|
294
|
+
textAlign: "center"
|
|
295
|
+
},
|
|
296
|
+
emptyActions: {
|
|
297
|
+
display: "flex",
|
|
298
|
+
gap: "8px",
|
|
299
|
+
marginTop: "8px"
|
|
300
|
+
},
|
|
301
|
+
retakeButtonOutline: {
|
|
302
|
+
display: "flex",
|
|
303
|
+
alignItems: "center",
|
|
304
|
+
gap: "6px",
|
|
305
|
+
padding: "8px 12px",
|
|
306
|
+
fontSize: "12px",
|
|
307
|
+
color: "#6b7280",
|
|
308
|
+
backgroundColor: "transparent",
|
|
309
|
+
border: "1px solid #e5e7eb",
|
|
310
|
+
borderRadius: "6px",
|
|
311
|
+
cursor: "pointer"
|
|
312
|
+
},
|
|
313
|
+
continueButton: {
|
|
314
|
+
display: "flex",
|
|
315
|
+
alignItems: "center",
|
|
316
|
+
gap: "6px",
|
|
317
|
+
padding: "8px 12px",
|
|
318
|
+
fontSize: "12px",
|
|
319
|
+
color: "#fff",
|
|
320
|
+
backgroundColor: "#3b82f6",
|
|
321
|
+
border: "none",
|
|
322
|
+
borderRadius: "6px",
|
|
323
|
+
cursor: "pointer",
|
|
324
|
+
fontWeight: "500"
|
|
325
|
+
},
|
|
326
|
+
header: {
|
|
327
|
+
display: "flex",
|
|
328
|
+
justifyContent: "space-between",
|
|
329
|
+
alignItems: "center",
|
|
330
|
+
padding: "0 4px"
|
|
331
|
+
},
|
|
332
|
+
headerTitle: {
|
|
333
|
+
fontSize: "12px",
|
|
334
|
+
fontWeight: "600",
|
|
335
|
+
color: "#374151",
|
|
336
|
+
textTransform: "uppercase",
|
|
337
|
+
letterSpacing: "0.05em"
|
|
338
|
+
},
|
|
339
|
+
headerActions: {
|
|
340
|
+
display: "flex",
|
|
341
|
+
alignItems: "center",
|
|
342
|
+
gap: "8px"
|
|
343
|
+
},
|
|
344
|
+
sizeLabel: {
|
|
345
|
+
fontSize: "11px",
|
|
346
|
+
color: "#9ca3af"
|
|
347
|
+
},
|
|
348
|
+
iconButton: {
|
|
349
|
+
display: "flex",
|
|
350
|
+
alignItems: "center",
|
|
351
|
+
justifyContent: "center",
|
|
352
|
+
width: "24px",
|
|
353
|
+
height: "24px",
|
|
354
|
+
border: "none",
|
|
355
|
+
backgroundColor: "transparent",
|
|
356
|
+
borderRadius: "4px",
|
|
357
|
+
cursor: "pointer",
|
|
358
|
+
color: "#6b7280"
|
|
359
|
+
},
|
|
360
|
+
tabContainer: {
|
|
361
|
+
display: "flex",
|
|
362
|
+
gap: "4px",
|
|
363
|
+
borderBottom: "1px solid #e5e7eb",
|
|
364
|
+
paddingBottom: "8px"
|
|
365
|
+
},
|
|
366
|
+
tab: {
|
|
367
|
+
display: "flex",
|
|
368
|
+
alignItems: "center",
|
|
369
|
+
gap: "4px",
|
|
370
|
+
padding: "2px 5px",
|
|
371
|
+
fontSize: "12px",
|
|
372
|
+
color: "#6b7280",
|
|
373
|
+
backgroundColor: "transparent",
|
|
374
|
+
border: "none",
|
|
375
|
+
borderRadius: "4px",
|
|
376
|
+
cursor: "pointer",
|
|
377
|
+
transition: "all 0.15s ease"
|
|
378
|
+
},
|
|
379
|
+
tabActive: {
|
|
380
|
+
backgroundColor: "#eff6ff",
|
|
381
|
+
color: "#3b82f6",
|
|
382
|
+
fontWeight: "500"
|
|
383
|
+
},
|
|
384
|
+
tabError: {
|
|
385
|
+
color: "#ef4444"
|
|
386
|
+
},
|
|
387
|
+
tabSize: {
|
|
388
|
+
fontSize: "10px",
|
|
389
|
+
color: "#9ca3af"
|
|
390
|
+
},
|
|
391
|
+
previewContainer: {
|
|
392
|
+
position: "relative",
|
|
393
|
+
width: "100%",
|
|
394
|
+
height: "150px",
|
|
395
|
+
backgroundColor: "#f9fafb",
|
|
396
|
+
borderRadius: "8px",
|
|
397
|
+
overflow: "hidden",
|
|
398
|
+
display: "flex",
|
|
399
|
+
alignItems: "center",
|
|
400
|
+
justifyContent: "center"
|
|
401
|
+
},
|
|
402
|
+
previewContainerExpanded: {
|
|
403
|
+
height: "60vh",
|
|
404
|
+
maxHeight: "500px"
|
|
405
|
+
},
|
|
406
|
+
previewImage: {
|
|
407
|
+
maxWidth: "100%",
|
|
408
|
+
maxHeight: "100%",
|
|
409
|
+
objectFit: "contain"
|
|
410
|
+
},
|
|
411
|
+
noPreview: {
|
|
412
|
+
display: "flex",
|
|
413
|
+
flexDirection: "column",
|
|
414
|
+
alignItems: "center",
|
|
415
|
+
gap: "8px",
|
|
416
|
+
fontSize: "12px",
|
|
417
|
+
color: "#9ca3af"
|
|
418
|
+
},
|
|
419
|
+
errorPreview: {
|
|
420
|
+
display: "flex",
|
|
421
|
+
flexDirection: "column",
|
|
422
|
+
alignItems: "center",
|
|
423
|
+
justifyContent: "center",
|
|
424
|
+
gap: "8px",
|
|
425
|
+
padding: "16px",
|
|
426
|
+
textAlign: "center"
|
|
427
|
+
},
|
|
428
|
+
errorTitle: {
|
|
429
|
+
fontSize: "14px",
|
|
430
|
+
fontWeight: "600",
|
|
431
|
+
color: "#ef4444"
|
|
432
|
+
},
|
|
433
|
+
errorMessage: {
|
|
434
|
+
fontSize: "12px",
|
|
435
|
+
color: "#6b7280",
|
|
436
|
+
maxWidth: "250px",
|
|
437
|
+
lineHeight: "1.4"
|
|
438
|
+
},
|
|
439
|
+
dimensionsInfo: {
|
|
440
|
+
fontSize: "11px",
|
|
441
|
+
color: "#9ca3af",
|
|
442
|
+
textAlign: "center"
|
|
443
|
+
},
|
|
444
|
+
actions: {
|
|
445
|
+
display: "flex",
|
|
446
|
+
justifyContent: "space-between",
|
|
447
|
+
alignItems: "center",
|
|
448
|
+
paddingTop: "8px",
|
|
449
|
+
borderTop: "1px solid #e5e7eb"
|
|
450
|
+
},
|
|
451
|
+
actionsRight: {
|
|
452
|
+
display: "flex",
|
|
453
|
+
gap: "8px"
|
|
454
|
+
},
|
|
455
|
+
retakeButton: {
|
|
456
|
+
display: "flex",
|
|
457
|
+
alignItems: "center",
|
|
458
|
+
gap: "6px",
|
|
459
|
+
padding: "8px 16px",
|
|
460
|
+
fontSize: "13px",
|
|
461
|
+
color: "#fff",
|
|
462
|
+
backgroundColor: "#3b82f6",
|
|
463
|
+
border: "none",
|
|
464
|
+
borderRadius: "6px",
|
|
465
|
+
cursor: "pointer",
|
|
466
|
+
fontWeight: "500"
|
|
467
|
+
},
|
|
468
|
+
retakeButtonSmall: {
|
|
469
|
+
display: "flex",
|
|
470
|
+
alignItems: "center",
|
|
471
|
+
gap: "4px",
|
|
472
|
+
padding: "4px 8px",
|
|
473
|
+
fontSize: "11px",
|
|
474
|
+
color: "#6b7280",
|
|
475
|
+
backgroundColor: "transparent",
|
|
476
|
+
border: "1px solid #e5e7eb",
|
|
477
|
+
borderRadius: "4px",
|
|
478
|
+
cursor: "pointer"
|
|
479
|
+
}
|
|
480
|
+
};
|
|
207
481
|
|
|
208
482
|
// src/highlight.ts
|
|
209
483
|
var HIGHLIGHT_TARGET_CLASS = "uifeedback-highlight-target";
|
|
@@ -238,7 +512,12 @@ var defaultContainerSelectors = [
|
|
|
238
512
|
"footer"
|
|
239
513
|
];
|
|
240
514
|
function generateHighlightCSS(colors) {
|
|
241
|
-
const {
|
|
515
|
+
const {
|
|
516
|
+
targetColor,
|
|
517
|
+
containerColor,
|
|
518
|
+
targetShadowOpacity,
|
|
519
|
+
containerShadowOpacity
|
|
520
|
+
} = colors;
|
|
242
521
|
const hexToRgba = (hex, alpha) => {
|
|
243
522
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
244
523
|
if (!result) return `rgba(0, 0, 0, ${alpha})`;
|
|
@@ -246,7 +525,7 @@ function generateHighlightCSS(colors) {
|
|
|
246
525
|
};
|
|
247
526
|
return `
|
|
248
527
|
.${HIGHLIGHT_TARGET_CLASS} {
|
|
249
|
-
outline: 2px
|
|
528
|
+
outline: 2px dashed ${targetColor} !important;
|
|
250
529
|
outline-offset: 2px !important;
|
|
251
530
|
box-shadow: 0 0 0 4px ${hexToRgba(targetColor, targetShadowOpacity)}, 0 4px 12px ${hexToRgba(targetColor, targetShadowOpacity * 0.6)} !important;
|
|
252
531
|
border-radius: 4px !important;
|
|
@@ -461,8 +740,16 @@ var ChevronLeft = createLucideIcon("chevron-left", __iconNode3);
|
|
|
461
740
|
var __iconNode4 = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
|
|
462
741
|
var ChevronRight = createLucideIcon("chevron-right", __iconNode4);
|
|
463
742
|
|
|
464
|
-
// ../../node_modules/lucide-react/dist/esm/icons/
|
|
743
|
+
// ../../node_modules/lucide-react/dist/esm/icons/circle-alert.js
|
|
465
744
|
var __iconNode5 = [
|
|
745
|
+
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
746
|
+
["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
|
|
747
|
+
["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
|
|
748
|
+
];
|
|
749
|
+
var CircleAlert = createLucideIcon("circle-alert", __iconNode5);
|
|
750
|
+
|
|
751
|
+
// ../../node_modules/lucide-react/dist/esm/icons/expand.js
|
|
752
|
+
var __iconNode6 = [
|
|
466
753
|
["path", { d: "m15 15 6 6", key: "1s409w" }],
|
|
467
754
|
["path", { d: "m15 9 6-6", key: "ko1vev" }],
|
|
468
755
|
["path", { d: "M21 16v5h-5", key: "1ck2sf" }],
|
|
@@ -472,10 +759,10 @@ var __iconNode5 = [
|
|
|
472
759
|
["path", { d: "M3 8V3h5", key: "1ln10m" }],
|
|
473
760
|
["path", { d: "M9 9 3 3", key: "v551iv" }]
|
|
474
761
|
];
|
|
475
|
-
var Expand = createLucideIcon("expand",
|
|
762
|
+
var Expand = createLucideIcon("expand", __iconNode6);
|
|
476
763
|
|
|
477
764
|
// ../../node_modules/lucide-react/dist/esm/icons/flag.js
|
|
478
|
-
var
|
|
765
|
+
var __iconNode7 = [
|
|
479
766
|
[
|
|
480
767
|
"path",
|
|
481
768
|
{
|
|
@@ -484,47 +771,58 @@ var __iconNode6 = [
|
|
|
484
771
|
}
|
|
485
772
|
]
|
|
486
773
|
];
|
|
487
|
-
var Flag = createLucideIcon("flag",
|
|
774
|
+
var Flag = createLucideIcon("flag", __iconNode7);
|
|
775
|
+
|
|
776
|
+
// ../../node_modules/lucide-react/dist/esm/icons/grip-vertical.js
|
|
777
|
+
var __iconNode8 = [
|
|
778
|
+
["circle", { cx: "9", cy: "12", r: "1", key: "1vctgf" }],
|
|
779
|
+
["circle", { cx: "9", cy: "5", r: "1", key: "hp0tcf" }],
|
|
780
|
+
["circle", { cx: "9", cy: "19", r: "1", key: "fkjjf6" }],
|
|
781
|
+
["circle", { cx: "15", cy: "12", r: "1", key: "1tmaij" }],
|
|
782
|
+
["circle", { cx: "15", cy: "5", r: "1", key: "19l28e" }],
|
|
783
|
+
["circle", { cx: "15", cy: "19", r: "1", key: "f4zoj3" }]
|
|
784
|
+
];
|
|
785
|
+
var GripVertical = createLucideIcon("grip-vertical", __iconNode8);
|
|
488
786
|
|
|
489
787
|
// ../../node_modules/lucide-react/dist/esm/icons/image.js
|
|
490
|
-
var
|
|
788
|
+
var __iconNode9 = [
|
|
491
789
|
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
|
|
492
790
|
["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
|
|
493
791
|
["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
|
|
494
792
|
];
|
|
495
|
-
var Image = createLucideIcon("image",
|
|
793
|
+
var Image = createLucideIcon("image", __iconNode9);
|
|
496
794
|
|
|
497
795
|
// ../../node_modules/lucide-react/dist/esm/icons/loader-circle.js
|
|
498
|
-
var
|
|
499
|
-
var LoaderCircle = createLucideIcon("loader-circle",
|
|
796
|
+
var __iconNode10 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
|
|
797
|
+
var LoaderCircle = createLucideIcon("loader-circle", __iconNode10);
|
|
500
798
|
|
|
501
799
|
// ../../node_modules/lucide-react/dist/esm/icons/plus.js
|
|
502
|
-
var
|
|
800
|
+
var __iconNode11 = [
|
|
503
801
|
["path", { d: "M5 12h14", key: "1ays0h" }],
|
|
504
802
|
["path", { d: "M12 5v14", key: "s699le" }]
|
|
505
803
|
];
|
|
506
|
-
var Plus = createLucideIcon("plus",
|
|
804
|
+
var Plus = createLucideIcon("plus", __iconNode11);
|
|
507
805
|
|
|
508
806
|
// ../../node_modules/lucide-react/dist/esm/icons/refresh-cw.js
|
|
509
|
-
var
|
|
807
|
+
var __iconNode12 = [
|
|
510
808
|
["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
|
|
511
809
|
["path", { d: "M21 3v5h-5", key: "1q7to0" }],
|
|
512
810
|
["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
|
|
513
811
|
["path", { d: "M8 16H3v5", key: "1cv678" }]
|
|
514
812
|
];
|
|
515
|
-
var RefreshCw = createLucideIcon("refresh-cw",
|
|
813
|
+
var RefreshCw = createLucideIcon("refresh-cw", __iconNode12);
|
|
516
814
|
|
|
517
815
|
// ../../node_modules/lucide-react/dist/esm/icons/shrink.js
|
|
518
|
-
var
|
|
816
|
+
var __iconNode13 = [
|
|
519
817
|
["path", { d: "m15 15 6 6m-6-6v4.8m0-4.8h4.8", key: "17vawe" }],
|
|
520
818
|
["path", { d: "M9 19.8V15m0 0H4.2M9 15l-6 6", key: "chjx8e" }],
|
|
521
819
|
["path", { d: "M15 4.2V9m0 0h4.8M15 9l6-6", key: "lav6yq" }],
|
|
522
820
|
["path", { d: "M9 4.2V9m0 0H4.2M9 9 3 3", key: "1pxi2q" }]
|
|
523
821
|
];
|
|
524
|
-
var Shrink = createLucideIcon("shrink",
|
|
822
|
+
var Shrink = createLucideIcon("shrink", __iconNode13);
|
|
525
823
|
|
|
526
824
|
// ../../node_modules/lucide-react/dist/esm/icons/thumbs-up.js
|
|
527
|
-
var
|
|
825
|
+
var __iconNode14 = [
|
|
528
826
|
["path", { d: "M7 10v12", key: "1qc93n" }],
|
|
529
827
|
[
|
|
530
828
|
"path",
|
|
@@ -534,14 +832,14 @@ var __iconNode12 = [
|
|
|
534
832
|
}
|
|
535
833
|
]
|
|
536
834
|
];
|
|
537
|
-
var ThumbsUp = createLucideIcon("thumbs-up",
|
|
835
|
+
var ThumbsUp = createLucideIcon("thumbs-up", __iconNode14);
|
|
538
836
|
|
|
539
837
|
// ../../node_modules/lucide-react/dist/esm/icons/x.js
|
|
540
|
-
var
|
|
838
|
+
var __iconNode15 = [
|
|
541
839
|
["path", { d: "M18 6 6 18", key: "1bl5f8" }],
|
|
542
840
|
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
543
841
|
];
|
|
544
|
-
var X = createLucideIcon("x",
|
|
842
|
+
var X = createLucideIcon("x", __iconNode15);
|
|
545
843
|
|
|
546
844
|
// src/ScreenshotPreview.tsx
|
|
547
845
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -556,7 +854,7 @@ function ScreenshotPreview({
|
|
|
556
854
|
const [activeTab, setActiveTab] = (0, import_react4.useState)("element");
|
|
557
855
|
const [isExpanded, setIsExpanded] = (0, import_react4.useState)(false);
|
|
558
856
|
if (isLoading) {
|
|
559
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style:
|
|
857
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.loadingContainer, children: [
|
|
560
858
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
561
859
|
LoaderCircle,
|
|
562
860
|
{
|
|
@@ -564,76 +862,117 @@ function ScreenshotPreview({
|
|
|
564
862
|
style: { color: "#3b82f6" }
|
|
565
863
|
}
|
|
566
864
|
),
|
|
567
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style:
|
|
865
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.loadingText, children: "Capturing screenshots..." })
|
|
568
866
|
] }) });
|
|
569
867
|
}
|
|
570
868
|
if (!screenshots) {
|
|
571
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style:
|
|
869
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.emptyContainer, children: [
|
|
572
870
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Image, { className: "w-8 h-8", style: { color: "#9ca3af" } }),
|
|
573
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style:
|
|
574
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
871
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.emptyText, children: "Screenshots unavailable" }),
|
|
872
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.emptySubtext, children: "Some elements can't be captured (e.g., gradient text)" }),
|
|
873
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.emptyActions, children: [
|
|
874
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
875
|
+
"button",
|
|
876
|
+
{
|
|
877
|
+
type: "button",
|
|
878
|
+
onClick: onRetake,
|
|
879
|
+
style: screenshotPreviewStyles.retakeButtonOutline,
|
|
880
|
+
disabled: isSubmitting,
|
|
881
|
+
children: [
|
|
882
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: "w-4 h-4" }),
|
|
883
|
+
"Try Again"
|
|
884
|
+
]
|
|
885
|
+
}
|
|
886
|
+
),
|
|
887
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
888
|
+
"button",
|
|
889
|
+
{
|
|
890
|
+
type: "button",
|
|
891
|
+
onClick: () => onConfirm({ capturedAt: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
892
|
+
style: screenshotPreviewStyles.continueButton,
|
|
893
|
+
disabled: isSubmitting,
|
|
894
|
+
children: [
|
|
895
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "w-4 h-4" }),
|
|
896
|
+
"Continue Without"
|
|
897
|
+
]
|
|
898
|
+
}
|
|
899
|
+
)
|
|
900
|
+
] })
|
|
901
|
+
] }) });
|
|
902
|
+
}
|
|
903
|
+
const getError = (key) => {
|
|
904
|
+
return screenshots.errors?.[key];
|
|
905
|
+
};
|
|
589
906
|
const allTabs = [
|
|
590
|
-
{
|
|
907
|
+
{
|
|
908
|
+
key: "element",
|
|
909
|
+
label: "Element",
|
|
910
|
+
data: screenshots.element,
|
|
911
|
+
error: getError("element")
|
|
912
|
+
},
|
|
591
913
|
{
|
|
592
914
|
key: "container",
|
|
593
915
|
label: "Container",
|
|
594
|
-
data: screenshots.container
|
|
916
|
+
data: screenshots.container,
|
|
917
|
+
error: getError("container")
|
|
595
918
|
},
|
|
596
|
-
{
|
|
919
|
+
{
|
|
920
|
+
key: "viewport",
|
|
921
|
+
label: "Viewport",
|
|
922
|
+
data: screenshots.viewport,
|
|
923
|
+
error: getError("viewport")
|
|
924
|
+
}
|
|
597
925
|
];
|
|
598
|
-
const tabs = allTabs.filter((tab) => tab.data);
|
|
926
|
+
const tabs = allTabs.filter((tab) => tab.data || tab.error);
|
|
599
927
|
const activeScreenshot = activeTab === "element" ? screenshots.element : activeTab === "container" ? screenshots.container : screenshots.viewport;
|
|
928
|
+
const activeError = getError(activeTab);
|
|
600
929
|
const totalSize = (0, import_anyclick_core.estimateTotalSize)(screenshots);
|
|
930
|
+
console.log({ styles: screenshotPreviewStyles });
|
|
601
931
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
602
932
|
"div",
|
|
603
933
|
{
|
|
604
934
|
style: {
|
|
605
|
-
...
|
|
606
|
-
...isExpanded ?
|
|
935
|
+
...screenshotPreviewStyles.container,
|
|
936
|
+
...isExpanded ? screenshotPreviewStyles.containerExpanded : {},
|
|
937
|
+
padding: "8px"
|
|
607
938
|
},
|
|
608
939
|
children: [
|
|
609
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style:
|
|
610
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style:
|
|
611
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style:
|
|
612
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style:
|
|
940
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.header, children: [
|
|
941
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.headerTitle, children: "Review Screenshots" }),
|
|
942
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.headerActions, children: [
|
|
943
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.sizeLabel, children: (0, import_anyclick_core.formatBytes)(totalSize) }),
|
|
613
944
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
614
945
|
"button",
|
|
615
946
|
{
|
|
616
947
|
type: "button",
|
|
617
948
|
onClick: () => setIsExpanded(!isExpanded),
|
|
618
|
-
style:
|
|
949
|
+
style: screenshotPreviewStyles.iconButton,
|
|
619
950
|
title: isExpanded ? "Collapse" : "Expand",
|
|
620
951
|
children: isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Shrink, { className: "w-4 h-4" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Expand, { className: "w-4 h-4" })
|
|
621
952
|
}
|
|
622
953
|
)
|
|
623
954
|
] })
|
|
624
955
|
] }),
|
|
625
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style:
|
|
956
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: screenshotPreviewStyles.tabContainer, children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
626
957
|
"button",
|
|
627
958
|
{
|
|
628
959
|
type: "button",
|
|
629
960
|
onClick: () => setActiveTab(tab.key),
|
|
630
961
|
style: {
|
|
631
|
-
...
|
|
632
|
-
...activeTab === tab.key ?
|
|
962
|
+
...screenshotPreviewStyles.tab,
|
|
963
|
+
...activeTab === tab.key ? screenshotPreviewStyles.tabActive : {},
|
|
964
|
+
...tab.error && !tab.data ? screenshotPreviewStyles.tabError : {}
|
|
633
965
|
},
|
|
634
966
|
children: [
|
|
967
|
+
tab.error && !tab.data && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
968
|
+
CircleAlert,
|
|
969
|
+
{
|
|
970
|
+
className: "w-3 h-3",
|
|
971
|
+
style: { color: "#ef4444" }
|
|
972
|
+
}
|
|
973
|
+
),
|
|
635
974
|
tab.label,
|
|
636
|
-
tab.data && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style:
|
|
975
|
+
tab.data && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.tabSize, children: (0, import_anyclick_core.formatBytes)(tab.data.sizeBytes) })
|
|
637
976
|
]
|
|
638
977
|
},
|
|
639
978
|
tab.key
|
|
@@ -642,17 +981,21 @@ function ScreenshotPreview({
|
|
|
642
981
|
"div",
|
|
643
982
|
{
|
|
644
983
|
style: {
|
|
645
|
-
...
|
|
646
|
-
...isExpanded ?
|
|
984
|
+
...screenshotPreviewStyles.previewContainer,
|
|
985
|
+
...isExpanded ? screenshotPreviewStyles.previewContainerExpanded : {}
|
|
647
986
|
},
|
|
648
987
|
children: activeScreenshot ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
649
988
|
"img",
|
|
650
989
|
{
|
|
651
990
|
src: activeScreenshot.dataUrl,
|
|
652
991
|
alt: `${activeTab} screenshot`,
|
|
653
|
-
style:
|
|
992
|
+
style: screenshotPreviewStyles.previewImage
|
|
654
993
|
}
|
|
655
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style:
|
|
994
|
+
) : activeError ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.errorPreview, children: [
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleAlert, { className: "w-8 h-8", style: { color: "#ef4444" } }),
|
|
996
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.errorTitle, children: "Capture Failed" }),
|
|
997
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.errorMessage, children: activeError.message })
|
|
998
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.noPreview, children: [
|
|
656
999
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Image, { className: "w-6 h-6", style: { color: "#9ca3af" } }),
|
|
657
1000
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
658
1001
|
"No ",
|
|
@@ -662,27 +1005,27 @@ function ScreenshotPreview({
|
|
|
662
1005
|
] })
|
|
663
1006
|
}
|
|
664
1007
|
),
|
|
665
|
-
activeScreenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style:
|
|
1008
|
+
activeScreenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.dimensionsInfo, children: [
|
|
666
1009
|
activeScreenshot.width,
|
|
667
1010
|
" \xD7 ",
|
|
668
1011
|
activeScreenshot.height,
|
|
669
1012
|
"px"
|
|
670
1013
|
] }),
|
|
671
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style:
|
|
1014
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.actions, children: [
|
|
672
1015
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
673
1016
|
"button",
|
|
674
1017
|
{
|
|
675
1018
|
type: "button",
|
|
676
1019
|
onClick: onRetake,
|
|
677
1020
|
disabled: isSubmitting,
|
|
678
|
-
style:
|
|
1021
|
+
style: screenshotPreviewStyles.retakeButtonSmall,
|
|
679
1022
|
children: [
|
|
680
1023
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: "w-3 h-3" }),
|
|
681
1024
|
"Retake"
|
|
682
1025
|
]
|
|
683
1026
|
}
|
|
684
1027
|
),
|
|
685
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style:
|
|
1028
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.actionsRight, children: [
|
|
686
1029
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
687
1030
|
"button",
|
|
688
1031
|
{
|
|
@@ -723,186 +1066,20 @@ function ScreenshotPreview({
|
|
|
723
1066
|
}
|
|
724
1067
|
);
|
|
725
1068
|
}
|
|
726
|
-
var styles = {
|
|
727
|
-
container: {
|
|
728
|
-
width: "100%",
|
|
729
|
-
display: "flex",
|
|
730
|
-
flexDirection: "column",
|
|
731
|
-
gap: "8px"
|
|
732
|
-
},
|
|
733
|
-
containerExpanded: {
|
|
734
|
-
position: "fixed",
|
|
735
|
-
top: "50%",
|
|
736
|
-
left: "50%",
|
|
737
|
-
transform: "translate(-50%, -50%)",
|
|
738
|
-
width: "90vw",
|
|
739
|
-
maxWidth: "800px",
|
|
740
|
-
maxHeight: "90vh",
|
|
741
|
-
backgroundColor: "#fff",
|
|
742
|
-
borderRadius: "12px",
|
|
743
|
-
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
|
|
744
|
-
padding: "16px",
|
|
745
|
-
zIndex: 1e4
|
|
746
|
-
},
|
|
747
|
-
loadingContainer: {
|
|
748
|
-
display: "flex",
|
|
749
|
-
flexDirection: "column",
|
|
750
|
-
alignItems: "center",
|
|
751
|
-
justifyContent: "center",
|
|
752
|
-
gap: "12px",
|
|
753
|
-
padding: "24px"
|
|
754
|
-
},
|
|
755
|
-
loadingText: {
|
|
756
|
-
fontSize: "13px",
|
|
757
|
-
color: "#6b7280"
|
|
758
|
-
},
|
|
759
|
-
emptyContainer: {
|
|
760
|
-
display: "flex",
|
|
761
|
-
flexDirection: "column",
|
|
762
|
-
alignItems: "center",
|
|
763
|
-
justifyContent: "center",
|
|
764
|
-
gap: "8px",
|
|
765
|
-
padding: "24px"
|
|
766
|
-
},
|
|
767
|
-
emptyText: {
|
|
768
|
-
fontSize: "13px",
|
|
769
|
-
color: "#9ca3af"
|
|
770
|
-
},
|
|
771
|
-
header: {
|
|
772
|
-
display: "flex",
|
|
773
|
-
justifyContent: "space-between",
|
|
774
|
-
alignItems: "center",
|
|
775
|
-
padding: "0 4px"
|
|
776
|
-
},
|
|
777
|
-
headerTitle: {
|
|
778
|
-
fontSize: "12px",
|
|
779
|
-
fontWeight: "600",
|
|
780
|
-
color: "#374151",
|
|
781
|
-
textTransform: "uppercase",
|
|
782
|
-
letterSpacing: "0.05em"
|
|
783
|
-
},
|
|
784
|
-
headerActions: {
|
|
785
|
-
display: "flex",
|
|
786
|
-
alignItems: "center",
|
|
787
|
-
gap: "8px"
|
|
788
|
-
},
|
|
789
|
-
sizeLabel: {
|
|
790
|
-
fontSize: "11px",
|
|
791
|
-
color: "#9ca3af"
|
|
792
|
-
},
|
|
793
|
-
iconButton: {
|
|
794
|
-
display: "flex",
|
|
795
|
-
alignItems: "center",
|
|
796
|
-
justifyContent: "center",
|
|
797
|
-
width: "24px",
|
|
798
|
-
height: "24px",
|
|
799
|
-
border: "none",
|
|
800
|
-
background: "transparent",
|
|
801
|
-
borderRadius: "4px",
|
|
802
|
-
cursor: "pointer",
|
|
803
|
-
color: "#6b7280"
|
|
804
|
-
},
|
|
805
|
-
tabContainer: {
|
|
806
|
-
display: "flex",
|
|
807
|
-
gap: "4px",
|
|
808
|
-
borderBottom: "1px solid #e5e7eb",
|
|
809
|
-
paddingBottom: "8px"
|
|
810
|
-
},
|
|
811
|
-
tab: {
|
|
812
|
-
display: "flex",
|
|
813
|
-
alignItems: "center",
|
|
814
|
-
gap: "4px",
|
|
815
|
-
padding: "6px 10px",
|
|
816
|
-
fontSize: "12px",
|
|
817
|
-
color: "#6b7280",
|
|
818
|
-
background: "transparent",
|
|
819
|
-
border: "none",
|
|
820
|
-
borderRadius: "4px",
|
|
821
|
-
cursor: "pointer",
|
|
822
|
-
transition: "all 0.15s ease"
|
|
823
|
-
},
|
|
824
|
-
tabActive: {
|
|
825
|
-
backgroundColor: "#eff6ff",
|
|
826
|
-
color: "#3b82f6",
|
|
827
|
-
fontWeight: "500"
|
|
828
|
-
},
|
|
829
|
-
tabSize: {
|
|
830
|
-
fontSize: "10px",
|
|
831
|
-
color: "#9ca3af"
|
|
832
|
-
},
|
|
833
|
-
previewContainer: {
|
|
834
|
-
position: "relative",
|
|
835
|
-
width: "100%",
|
|
836
|
-
height: "150px",
|
|
837
|
-
backgroundColor: "#f9fafb",
|
|
838
|
-
borderRadius: "8px",
|
|
839
|
-
overflow: "hidden",
|
|
840
|
-
display: "flex",
|
|
841
|
-
alignItems: "center",
|
|
842
|
-
justifyContent: "center"
|
|
843
|
-
},
|
|
844
|
-
previewContainerExpanded: {
|
|
845
|
-
height: "60vh",
|
|
846
|
-
maxHeight: "500px"
|
|
847
|
-
},
|
|
848
|
-
previewImage: {
|
|
849
|
-
maxWidth: "100%",
|
|
850
|
-
maxHeight: "100%",
|
|
851
|
-
objectFit: "contain"
|
|
852
|
-
},
|
|
853
|
-
noPreview: {
|
|
854
|
-
display: "flex",
|
|
855
|
-
flexDirection: "column",
|
|
856
|
-
alignItems: "center",
|
|
857
|
-
gap: "8px",
|
|
858
|
-
fontSize: "12px",
|
|
859
|
-
color: "#9ca3af"
|
|
860
|
-
},
|
|
861
|
-
dimensionsInfo: {
|
|
862
|
-
fontSize: "11px",
|
|
863
|
-
color: "#9ca3af",
|
|
864
|
-
textAlign: "center"
|
|
865
|
-
},
|
|
866
|
-
actions: {
|
|
867
|
-
display: "flex",
|
|
868
|
-
justifyContent: "space-between",
|
|
869
|
-
alignItems: "center",
|
|
870
|
-
paddingTop: "8px",
|
|
871
|
-
borderTop: "1px solid #e5e7eb"
|
|
872
|
-
},
|
|
873
|
-
actionsRight: {
|
|
874
|
-
display: "flex",
|
|
875
|
-
gap: "8px"
|
|
876
|
-
},
|
|
877
|
-
retakeButton: {
|
|
878
|
-
display: "flex",
|
|
879
|
-
alignItems: "center",
|
|
880
|
-
gap: "6px",
|
|
881
|
-
padding: "8px 16px",
|
|
882
|
-
fontSize: "13px",
|
|
883
|
-
color: "#fff",
|
|
884
|
-
backgroundColor: "#3b82f6",
|
|
885
|
-
border: "none",
|
|
886
|
-
borderRadius: "6px",
|
|
887
|
-
cursor: "pointer",
|
|
888
|
-
fontWeight: "500"
|
|
889
|
-
},
|
|
890
|
-
retakeButtonSmall: {
|
|
891
|
-
display: "flex",
|
|
892
|
-
alignItems: "center",
|
|
893
|
-
gap: "4px",
|
|
894
|
-
padding: "4px 8px",
|
|
895
|
-
fontSize: "11px",
|
|
896
|
-
color: "#6b7280",
|
|
897
|
-
backgroundColor: "transparent",
|
|
898
|
-
border: "1px solid #e5e7eb",
|
|
899
|
-
borderRadius: "4px",
|
|
900
|
-
cursor: "pointer"
|
|
901
|
-
}
|
|
902
|
-
};
|
|
903
1069
|
|
|
904
1070
|
// src/ContextMenu.tsx
|
|
905
1071
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1072
|
+
var VIEWPORT_PADDING = 10;
|
|
1073
|
+
var screenshotIndicatorStyle = {
|
|
1074
|
+
display: "flex",
|
|
1075
|
+
alignItems: "center",
|
|
1076
|
+
gap: "6px",
|
|
1077
|
+
padding: "8px 12px",
|
|
1078
|
+
fontSize: "11px",
|
|
1079
|
+
color: "var(--anyclick-menu-text-muted, #9ca3af)",
|
|
1080
|
+
borderTop: "1px solid var(--anyclick-menu-border, #f3f4f6)",
|
|
1081
|
+
marginTop: "4px"
|
|
1082
|
+
};
|
|
906
1083
|
var defaultIcons = {
|
|
907
1084
|
issue: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Flag, { className: "w-4 h-4" }),
|
|
908
1085
|
feature: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Plus, { className: "w-4 h-4" }),
|
|
@@ -915,6 +1092,7 @@ function MenuItem({
|
|
|
915
1092
|
hasChildren
|
|
916
1093
|
}) {
|
|
917
1094
|
const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
|
|
1095
|
+
const [isPressed, setIsPressed] = (0, import_react5.useState)(false);
|
|
918
1096
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
919
1097
|
"button",
|
|
920
1098
|
{
|
|
@@ -922,11 +1100,25 @@ function MenuItem({
|
|
|
922
1100
|
onClick,
|
|
923
1101
|
disabled,
|
|
924
1102
|
onMouseEnter: () => setIsHovered(true),
|
|
925
|
-
onMouseLeave: () =>
|
|
1103
|
+
onMouseLeave: () => {
|
|
1104
|
+
setIsHovered(false);
|
|
1105
|
+
setIsPressed(false);
|
|
1106
|
+
},
|
|
1107
|
+
onTouchStart: () => setIsPressed(true),
|
|
1108
|
+
onTouchEnd: () => setIsPressed(false),
|
|
1109
|
+
onTouchCancel: () => setIsPressed(false),
|
|
926
1110
|
style: {
|
|
927
1111
|
...menuStyles.item,
|
|
928
|
-
|
|
929
|
-
...
|
|
1112
|
+
// Apply hover/pressed state for both mouse and touch
|
|
1113
|
+
...isHovered || isPressed ? menuStyles.itemHover : {},
|
|
1114
|
+
...disabled ? { opacity: 0.5, cursor: "not-allowed" } : {},
|
|
1115
|
+
// Ensure minimum touch target size (44px is recommended)
|
|
1116
|
+
minHeight: "44px",
|
|
1117
|
+
// Prevent text selection on touch
|
|
1118
|
+
WebkitUserSelect: "none",
|
|
1119
|
+
userSelect: "none",
|
|
1120
|
+
// Prevent touch callout on iOS
|
|
1121
|
+
WebkitTouchCallout: "none"
|
|
930
1122
|
},
|
|
931
1123
|
children: [
|
|
932
1124
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: menuStyles.itemIcon, children: item.icon ?? defaultIcons[item.type] }),
|
|
@@ -944,18 +1136,31 @@ function MenuItem({
|
|
|
944
1136
|
}
|
|
945
1137
|
function BackButton({ onClick }) {
|
|
946
1138
|
const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
|
|
1139
|
+
const [isPressed, setIsPressed] = (0, import_react5.useState)(false);
|
|
947
1140
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
948
1141
|
"button",
|
|
949
1142
|
{
|
|
950
1143
|
type: "button",
|
|
951
1144
|
onClick,
|
|
952
1145
|
onMouseEnter: () => setIsHovered(true),
|
|
953
|
-
onMouseLeave: () =>
|
|
1146
|
+
onMouseLeave: () => {
|
|
1147
|
+
setIsHovered(false);
|
|
1148
|
+
setIsPressed(false);
|
|
1149
|
+
},
|
|
1150
|
+
onTouchStart: () => setIsPressed(true),
|
|
1151
|
+
onTouchEnd: () => setIsPressed(false),
|
|
1152
|
+
onTouchCancel: () => setIsPressed(false),
|
|
954
1153
|
style: {
|
|
955
1154
|
...menuStyles.item,
|
|
956
|
-
...isHovered ? menuStyles.itemHover : {},
|
|
1155
|
+
...isHovered || isPressed ? menuStyles.itemHover : {},
|
|
957
1156
|
borderBottom: "1px solid #e5e5e5",
|
|
958
|
-
marginBottom: "4px"
|
|
1157
|
+
marginBottom: "4px",
|
|
1158
|
+
// Ensure minimum touch target size
|
|
1159
|
+
minHeight: "44px",
|
|
1160
|
+
// Prevent text selection on touch
|
|
1161
|
+
WebkitUserSelect: "none",
|
|
1162
|
+
userSelect: "none",
|
|
1163
|
+
WebkitTouchCallout: "none"
|
|
959
1164
|
},
|
|
960
1165
|
children: [
|
|
961
1166
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChevronLeft, { className: "w-4 h-4", style: { opacity: 0.5 } }),
|
|
@@ -1025,6 +1230,25 @@ function CommentForm({
|
|
|
1025
1230
|
] })
|
|
1026
1231
|
] });
|
|
1027
1232
|
}
|
|
1233
|
+
function calculateInViewPosition(requestedX, requestedY, menuWidth, menuHeight) {
|
|
1234
|
+
const viewportWidth = window.innerWidth;
|
|
1235
|
+
const viewportHeight = window.innerHeight;
|
|
1236
|
+
let x = requestedX;
|
|
1237
|
+
let y = requestedY;
|
|
1238
|
+
if (x + menuWidth > viewportWidth - VIEWPORT_PADDING) {
|
|
1239
|
+
x = viewportWidth - menuWidth - VIEWPORT_PADDING;
|
|
1240
|
+
}
|
|
1241
|
+
if (x < VIEWPORT_PADDING) {
|
|
1242
|
+
x = VIEWPORT_PADDING;
|
|
1243
|
+
}
|
|
1244
|
+
if (y + menuHeight > viewportHeight - VIEWPORT_PADDING) {
|
|
1245
|
+
y = viewportHeight - menuHeight - VIEWPORT_PADDING;
|
|
1246
|
+
}
|
|
1247
|
+
if (y < VIEWPORT_PADDING) {
|
|
1248
|
+
y = VIEWPORT_PADDING;
|
|
1249
|
+
}
|
|
1250
|
+
return { x, y };
|
|
1251
|
+
}
|
|
1028
1252
|
function ContextMenu({
|
|
1029
1253
|
visible,
|
|
1030
1254
|
position,
|
|
@@ -1037,7 +1261,8 @@ function ContextMenu({
|
|
|
1037
1261
|
style,
|
|
1038
1262
|
className,
|
|
1039
1263
|
highlightConfig,
|
|
1040
|
-
screenshotConfig
|
|
1264
|
+
screenshotConfig,
|
|
1265
|
+
positionMode = "inView"
|
|
1041
1266
|
}) {
|
|
1042
1267
|
const [selectedType, setSelectedType] = (0, import_react5.useState)(null);
|
|
1043
1268
|
const [currentView, setCurrentView] = (0, import_react5.useState)("menu");
|
|
@@ -1046,6 +1271,13 @@ function ContextMenu({
|
|
|
1046
1271
|
const [screenshots, setScreenshots] = (0, import_react5.useState)(null);
|
|
1047
1272
|
const [isCapturing, setIsCapturing] = (0, import_react5.useState)(false);
|
|
1048
1273
|
const menuRef = (0, import_react5.useRef)(null);
|
|
1274
|
+
const [adjustedPosition, setAdjustedPosition] = (0, import_react5.useState)(position);
|
|
1275
|
+
const [isDragging, setIsDragging] = (0, import_react5.useState)(false);
|
|
1276
|
+
const [dragOffset, setDragOffset] = (0, import_react5.useState)({
|
|
1277
|
+
x: 0,
|
|
1278
|
+
y: 0
|
|
1279
|
+
});
|
|
1280
|
+
const dragStartRef = (0, import_react5.useRef)(null);
|
|
1049
1281
|
const mergedScreenshotConfig = {
|
|
1050
1282
|
...import_anyclick_core2.DEFAULT_SCREENSHOT_CONFIG,
|
|
1051
1283
|
...screenshotConfig
|
|
@@ -1077,6 +1309,9 @@ function ContextMenu({
|
|
|
1077
1309
|
setSubmenuStack([]);
|
|
1078
1310
|
setScreenshots(null);
|
|
1079
1311
|
setIsCapturing(false);
|
|
1312
|
+
setIsDragging(false);
|
|
1313
|
+
setDragOffset({ x: 0, y: 0 });
|
|
1314
|
+
dragStartRef.current = null;
|
|
1080
1315
|
}
|
|
1081
1316
|
}, [visible]);
|
|
1082
1317
|
(0, import_react5.useEffect)(() => {
|
|
@@ -1097,6 +1332,9 @@ function ContextMenu({
|
|
|
1097
1332
|
const handlePointerDown = (event) => {
|
|
1098
1333
|
if (!menuRef.current) return;
|
|
1099
1334
|
const target = event.target;
|
|
1335
|
+
if (target.closest?.("[data-drag-handle]")) {
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1100
1338
|
if (!menuRef.current.contains(target)) {
|
|
1101
1339
|
onClose();
|
|
1102
1340
|
}
|
|
@@ -1107,24 +1345,71 @@ function ContextMenu({
|
|
|
1107
1345
|
};
|
|
1108
1346
|
}, [visible, onClose]);
|
|
1109
1347
|
(0, import_react5.useEffect)(() => {
|
|
1110
|
-
if (visible
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
if (
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1348
|
+
if (visible) {
|
|
1349
|
+
setAdjustedPosition(position);
|
|
1350
|
+
setDragOffset({ x: 0, y: 0 });
|
|
1351
|
+
}
|
|
1352
|
+
}, [visible, position.x, position.y]);
|
|
1353
|
+
(0, import_react5.useEffect)(() => {
|
|
1354
|
+
if (!visible || !menuRef.current) return;
|
|
1355
|
+
const updatePosition = () => {
|
|
1356
|
+
const menuElement = menuRef.current;
|
|
1357
|
+
if (!menuElement) return;
|
|
1358
|
+
const rect = menuElement.getBoundingClientRect();
|
|
1359
|
+
const baseX = position.x + dragOffset.x;
|
|
1360
|
+
const baseY = position.y + dragOffset.y;
|
|
1361
|
+
if (positionMode === "static") {
|
|
1362
|
+
setAdjustedPosition({ x: baseX, y: baseY });
|
|
1363
|
+
} else if (positionMode === "inView" || positionMode === "dynamic") {
|
|
1364
|
+
const adjusted = calculateInViewPosition(
|
|
1365
|
+
baseX,
|
|
1366
|
+
baseY,
|
|
1367
|
+
rect.width,
|
|
1368
|
+
rect.height
|
|
1369
|
+
);
|
|
1370
|
+
setAdjustedPosition(adjusted);
|
|
1125
1371
|
}
|
|
1372
|
+
};
|
|
1373
|
+
requestAnimationFrame(updatePosition);
|
|
1374
|
+
window.addEventListener("resize", updatePosition);
|
|
1375
|
+
return () => window.removeEventListener("resize", updatePosition);
|
|
1376
|
+
}, [visible, position, positionMode, dragOffset, currentView]);
|
|
1377
|
+
(0, import_react5.useEffect)(() => {
|
|
1378
|
+
if (!visible || positionMode !== "dynamic") return;
|
|
1379
|
+
const handlePointerMove = (event) => {
|
|
1380
|
+
if (!isDragging || !dragStartRef.current) return;
|
|
1381
|
+
const deltaX = event.clientX - dragStartRef.current.x;
|
|
1382
|
+
const deltaY = event.clientY - dragStartRef.current.y;
|
|
1383
|
+
setDragOffset((prev) => ({
|
|
1384
|
+
x: prev.x + deltaX,
|
|
1385
|
+
y: prev.y + deltaY
|
|
1386
|
+
}));
|
|
1387
|
+
dragStartRef.current = { x: event.clientX, y: event.clientY };
|
|
1388
|
+
};
|
|
1389
|
+
const handlePointerUp = () => {
|
|
1390
|
+
setIsDragging(false);
|
|
1391
|
+
dragStartRef.current = null;
|
|
1392
|
+
};
|
|
1393
|
+
if (isDragging) {
|
|
1394
|
+
document.addEventListener("pointermove", handlePointerMove);
|
|
1395
|
+
document.addEventListener("pointerup", handlePointerUp);
|
|
1396
|
+
document.addEventListener("pointercancel", handlePointerUp);
|
|
1397
|
+
return () => {
|
|
1398
|
+
document.removeEventListener("pointermove", handlePointerMove);
|
|
1399
|
+
document.removeEventListener("pointerup", handlePointerUp);
|
|
1400
|
+
document.removeEventListener("pointercancel", handlePointerUp);
|
|
1401
|
+
};
|
|
1126
1402
|
}
|
|
1127
|
-
}, [visible,
|
|
1403
|
+
}, [visible, positionMode, isDragging]);
|
|
1404
|
+
const handleDragStart = (0, import_react5.useCallback)(
|
|
1405
|
+
(event) => {
|
|
1406
|
+
if (positionMode !== "dynamic") return;
|
|
1407
|
+
event.preventDefault();
|
|
1408
|
+
setIsDragging(true);
|
|
1409
|
+
dragStartRef.current = { x: event.clientX, y: event.clientY };
|
|
1410
|
+
},
|
|
1411
|
+
[positionMode]
|
|
1412
|
+
);
|
|
1128
1413
|
(0, import_react5.useEffect)(() => {
|
|
1129
1414
|
const handleKeyDown = (e) => {
|
|
1130
1415
|
if (e.key === "Escape") {
|
|
@@ -1146,6 +1431,23 @@ function ContextMenu({
|
|
|
1146
1431
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1147
1432
|
}
|
|
1148
1433
|
}, [visible, currentView, submenuStack.length, onClose]);
|
|
1434
|
+
(0, import_react5.useEffect)(() => {
|
|
1435
|
+
const menuElement = menuRef.current;
|
|
1436
|
+
if (!visible || !menuElement) return;
|
|
1437
|
+
const preventTouchDefault = (e) => {
|
|
1438
|
+
const target = e.target;
|
|
1439
|
+
if (target.tagName === "TEXTAREA" || target.tagName === "INPUT" || target.isContentEditable) {
|
|
1440
|
+
return;
|
|
1441
|
+
}
|
|
1442
|
+
e.preventDefault();
|
|
1443
|
+
};
|
|
1444
|
+
menuElement.addEventListener("touchmove", preventTouchDefault, {
|
|
1445
|
+
passive: false
|
|
1446
|
+
});
|
|
1447
|
+
return () => {
|
|
1448
|
+
menuElement.removeEventListener("touchmove", preventTouchDefault);
|
|
1449
|
+
};
|
|
1450
|
+
}, [visible]);
|
|
1149
1451
|
if (!visible || !targetElement) {
|
|
1150
1452
|
return null;
|
|
1151
1453
|
}
|
|
@@ -1203,6 +1505,14 @@ function ContextMenu({
|
|
|
1203
1505
|
captureScreenshots();
|
|
1204
1506
|
};
|
|
1205
1507
|
const containerWidth = currentView === "screenshot-preview" ? 360 : void 0;
|
|
1508
|
+
if (process.env.NODE_ENV === "development" && visible) {
|
|
1509
|
+
console.log("[ContextMenu] Style Debug", {
|
|
1510
|
+
styleExists: !!style,
|
|
1511
|
+
styleKeys: style ? Object.keys(style) : [],
|
|
1512
|
+
styleValues: style,
|
|
1513
|
+
className
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1206
1516
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1207
1517
|
"div",
|
|
1208
1518
|
{
|
|
@@ -1210,15 +1520,61 @@ function ContextMenu({
|
|
|
1210
1520
|
className,
|
|
1211
1521
|
style: {
|
|
1212
1522
|
...menuStyles.container,
|
|
1213
|
-
left:
|
|
1214
|
-
top:
|
|
1523
|
+
left: adjustedPosition.x,
|
|
1524
|
+
top: adjustedPosition.y,
|
|
1215
1525
|
...containerWidth ? { width: containerWidth, minWidth: containerWidth } : {},
|
|
1526
|
+
// Touch-specific styles
|
|
1527
|
+
WebkitUserSelect: "none",
|
|
1528
|
+
userSelect: "none",
|
|
1529
|
+
WebkitTouchCallout: "none",
|
|
1530
|
+
touchAction: "none",
|
|
1531
|
+
// Prevent default touch behaviors
|
|
1532
|
+
// Cursor style for dragging
|
|
1533
|
+
...isDragging ? { cursor: "grabbing" } : {},
|
|
1216
1534
|
...style
|
|
1217
1535
|
},
|
|
1218
1536
|
role: "menu",
|
|
1219
1537
|
"aria-label": "Feedback options",
|
|
1220
1538
|
children: [
|
|
1221
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
1539
|
+
currentView !== "screenshot-preview" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1540
|
+
"div",
|
|
1541
|
+
{
|
|
1542
|
+
style: {
|
|
1543
|
+
...menuStyles.header,
|
|
1544
|
+
display: "flex",
|
|
1545
|
+
alignItems: "center",
|
|
1546
|
+
justifyContent: "space-between"
|
|
1547
|
+
},
|
|
1548
|
+
children: [
|
|
1549
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Send Feedback" }),
|
|
1550
|
+
positionMode === "dynamic" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1551
|
+
"div",
|
|
1552
|
+
{
|
|
1553
|
+
"data-drag-handle": true,
|
|
1554
|
+
onPointerDown: handleDragStart,
|
|
1555
|
+
style: {
|
|
1556
|
+
cursor: isDragging ? "grabbing" : "grab",
|
|
1557
|
+
padding: "4px",
|
|
1558
|
+
marginRight: "-4px",
|
|
1559
|
+
borderRadius: "4px",
|
|
1560
|
+
display: "flex",
|
|
1561
|
+
alignItems: "center",
|
|
1562
|
+
opacity: 0.5,
|
|
1563
|
+
transition: "opacity 0.15s"
|
|
1564
|
+
},
|
|
1565
|
+
onMouseEnter: (e) => {
|
|
1566
|
+
e.currentTarget.style.opacity = "1";
|
|
1567
|
+
},
|
|
1568
|
+
onMouseLeave: (e) => {
|
|
1569
|
+
e.currentTarget.style.opacity = "0.5";
|
|
1570
|
+
},
|
|
1571
|
+
title: "Drag to move",
|
|
1572
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GripVertical, { className: "w-4 h-4" })
|
|
1573
|
+
}
|
|
1574
|
+
)
|
|
1575
|
+
]
|
|
1576
|
+
}
|
|
1577
|
+
),
|
|
1222
1578
|
currentView === "menu" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: menuStyles.itemList, children: [
|
|
1223
1579
|
submenuStack.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BackButton, { onClick: handleBack }),
|
|
1224
1580
|
currentItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -1259,25 +1615,203 @@ function ContextMenu({
|
|
|
1259
1615
|
}
|
|
1260
1616
|
);
|
|
1261
1617
|
}
|
|
1262
|
-
var screenshotIndicatorStyle = {
|
|
1263
|
-
display: "flex",
|
|
1264
|
-
alignItems: "center",
|
|
1265
|
-
gap: "6px",
|
|
1266
|
-
padding: "8px 12px",
|
|
1267
|
-
fontSize: "11px",
|
|
1268
|
-
color: "#9ca3af",
|
|
1269
|
-
borderTop: "1px solid #f3f4f6",
|
|
1270
|
-
marginTop: "4px"
|
|
1271
|
-
};
|
|
1272
1618
|
|
|
1273
|
-
// src/
|
|
1619
|
+
// src/store.ts
|
|
1620
|
+
var import_zustand = require("zustand");
|
|
1621
|
+
var providerIdCounter = 0;
|
|
1622
|
+
function generateProviderId() {
|
|
1623
|
+
return `anyclick-provider-${++providerIdCounter}`;
|
|
1624
|
+
}
|
|
1625
|
+
var useProviderStore = (0, import_zustand.create)((set, get) => ({
|
|
1626
|
+
providers: /* @__PURE__ */ new Map(),
|
|
1627
|
+
registerProvider: (provider) => {
|
|
1628
|
+
set((state) => {
|
|
1629
|
+
const newProviders = new Map(state.providers);
|
|
1630
|
+
newProviders.set(provider.id, provider);
|
|
1631
|
+
return { providers: newProviders };
|
|
1632
|
+
});
|
|
1633
|
+
},
|
|
1634
|
+
unregisterProvider: (id) => {
|
|
1635
|
+
set((state) => {
|
|
1636
|
+
const newProviders = new Map(state.providers);
|
|
1637
|
+
newProviders.delete(id);
|
|
1638
|
+
return { providers: newProviders };
|
|
1639
|
+
});
|
|
1640
|
+
},
|
|
1641
|
+
updateProvider: (id, updates) => {
|
|
1642
|
+
set((state) => {
|
|
1643
|
+
const newProviders = new Map(state.providers);
|
|
1644
|
+
const existing = newProviders.get(id);
|
|
1645
|
+
if (existing) {
|
|
1646
|
+
newProviders.set(id, { ...existing, ...updates });
|
|
1647
|
+
}
|
|
1648
|
+
return { providers: newProviders };
|
|
1649
|
+
});
|
|
1650
|
+
},
|
|
1651
|
+
findProvidersForElement: (element) => {
|
|
1652
|
+
const { providers } = get();
|
|
1653
|
+
const matching = [];
|
|
1654
|
+
for (const provider of providers.values()) {
|
|
1655
|
+
if (provider.disabled) continue;
|
|
1656
|
+
const container = provider.containerRef.current;
|
|
1657
|
+
if (provider.scoped && container) {
|
|
1658
|
+
if (container.contains(element)) {
|
|
1659
|
+
matching.push(provider);
|
|
1660
|
+
}
|
|
1661
|
+
} else if (!provider.scoped) {
|
|
1662
|
+
matching.push(provider);
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
return matching.sort((a, b) => b.depth - a.depth);
|
|
1666
|
+
},
|
|
1667
|
+
findParentProvider: (container, excludeId) => {
|
|
1668
|
+
const { providers } = get();
|
|
1669
|
+
if (!container) return null;
|
|
1670
|
+
let nearestParent = null;
|
|
1671
|
+
let nearestDepth = -1;
|
|
1672
|
+
for (const provider of providers.values()) {
|
|
1673
|
+
if (provider.id === excludeId) continue;
|
|
1674
|
+
const providerContainer = provider.containerRef.current;
|
|
1675
|
+
if (!providerContainer) continue;
|
|
1676
|
+
if (providerContainer.contains(container)) {
|
|
1677
|
+
if (provider.depth > nearestDepth) {
|
|
1678
|
+
nearestParent = provider;
|
|
1679
|
+
nearestDepth = provider.depth;
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
return nearestParent;
|
|
1684
|
+
},
|
|
1685
|
+
getMergedTheme: (providerId) => {
|
|
1686
|
+
const { providers } = get();
|
|
1687
|
+
const provider = providers.get(providerId);
|
|
1688
|
+
if (!provider) {
|
|
1689
|
+
if (process.env.NODE_ENV === "development") {
|
|
1690
|
+
console.log(`[Store:getMergedTheme] Provider not found: ${providerId}`);
|
|
1691
|
+
}
|
|
1692
|
+
return {};
|
|
1693
|
+
}
|
|
1694
|
+
const ancestors = [];
|
|
1695
|
+
let current = provider;
|
|
1696
|
+
while (current) {
|
|
1697
|
+
ancestors.unshift(current);
|
|
1698
|
+
current = current.parentId ? providers.get(current.parentId) : void 0;
|
|
1699
|
+
}
|
|
1700
|
+
if (process.env.NODE_ENV === "development") {
|
|
1701
|
+
console.log(`[Store:getMergedTheme] Provider: ${providerId}`, {
|
|
1702
|
+
ancestorCount: ancestors.length,
|
|
1703
|
+
ancestorIds: ancestors.map((a) => a.id),
|
|
1704
|
+
providerHasTheme: !!provider.theme,
|
|
1705
|
+
providerThemeMenuStyle: provider.theme?.menuStyle ? Object.keys(provider.theme.menuStyle) : []
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
const mergedTheme = {};
|
|
1709
|
+
for (const ancestor of ancestors) {
|
|
1710
|
+
if (ancestor.theme) {
|
|
1711
|
+
Object.assign(mergedTheme, ancestor.theme);
|
|
1712
|
+
if (ancestor.theme.highlightConfig) {
|
|
1713
|
+
mergedTheme.highlightConfig = {
|
|
1714
|
+
...mergedTheme.highlightConfig,
|
|
1715
|
+
...ancestor.theme.highlightConfig,
|
|
1716
|
+
colors: {
|
|
1717
|
+
...mergedTheme.highlightConfig?.colors,
|
|
1718
|
+
...ancestor.theme.highlightConfig.colors
|
|
1719
|
+
}
|
|
1720
|
+
};
|
|
1721
|
+
}
|
|
1722
|
+
if (ancestor.theme.screenshotConfig) {
|
|
1723
|
+
mergedTheme.screenshotConfig = {
|
|
1724
|
+
...mergedTheme.screenshotConfig,
|
|
1725
|
+
...ancestor.theme.screenshotConfig
|
|
1726
|
+
};
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
if (process.env.NODE_ENV === "development") {
|
|
1731
|
+
console.log(`[Store:getMergedTheme] Result for ${providerId}`, {
|
|
1732
|
+
hasMenuStyle: !!mergedTheme.menuStyle,
|
|
1733
|
+
menuStyleKeys: mergedTheme.menuStyle ? Object.keys(mergedTheme.menuStyle) : []
|
|
1734
|
+
});
|
|
1735
|
+
}
|
|
1736
|
+
return mergedTheme;
|
|
1737
|
+
},
|
|
1738
|
+
isDisabledByAncestor: (providerId) => {
|
|
1739
|
+
const { providers } = get();
|
|
1740
|
+
const provider = providers.get(providerId);
|
|
1741
|
+
if (!provider) return false;
|
|
1742
|
+
let current = provider;
|
|
1743
|
+
while (current) {
|
|
1744
|
+
if (current.disabled || current.theme?.disabled) {
|
|
1745
|
+
return true;
|
|
1746
|
+
}
|
|
1747
|
+
current = current.parentId ? providers.get(current.parentId) : void 0;
|
|
1748
|
+
}
|
|
1749
|
+
return false;
|
|
1750
|
+
},
|
|
1751
|
+
isElementInDisabledScope: (element) => {
|
|
1752
|
+
const { providers } = get();
|
|
1753
|
+
for (const provider of providers.values()) {
|
|
1754
|
+
if (!provider.scoped) continue;
|
|
1755
|
+
if (!provider.disabled && !provider.theme?.disabled) continue;
|
|
1756
|
+
const container = provider.containerRef.current;
|
|
1757
|
+
if (!container) continue;
|
|
1758
|
+
if (container.contains(element)) {
|
|
1759
|
+
return true;
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
return false;
|
|
1763
|
+
},
|
|
1764
|
+
isElementInAnyScopedProvider: (element) => {
|
|
1765
|
+
const { providers } = get();
|
|
1766
|
+
for (const provider of providers.values()) {
|
|
1767
|
+
if (!provider.scoped) continue;
|
|
1768
|
+
const container = provider.containerRef.current;
|
|
1769
|
+
if (!container) continue;
|
|
1770
|
+
if (container.contains(element)) {
|
|
1771
|
+
if (process.env.NODE_ENV === "development") {
|
|
1772
|
+
console.log(
|
|
1773
|
+
`[Store:isElementInAnyScopedProvider] Element is in scoped provider: ${provider.id}`,
|
|
1774
|
+
{
|
|
1775
|
+
elementTag: element.tagName,
|
|
1776
|
+
providerId: provider.id,
|
|
1777
|
+
providerDisabled: provider.disabled
|
|
1778
|
+
}
|
|
1779
|
+
);
|
|
1780
|
+
}
|
|
1781
|
+
return true;
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
return false;
|
|
1785
|
+
}
|
|
1786
|
+
}));
|
|
1787
|
+
function dispatchContextMenuEvent(event, element) {
|
|
1788
|
+
const store = useProviderStore.getState();
|
|
1789
|
+
const providers = store.findProvidersForElement(element);
|
|
1790
|
+
const menuEvent = {
|
|
1791
|
+
clientX: event.clientX,
|
|
1792
|
+
clientY: event.clientY,
|
|
1793
|
+
originalEvent: event,
|
|
1794
|
+
isTouch: false
|
|
1795
|
+
};
|
|
1796
|
+
for (const provider of providers) {
|
|
1797
|
+
if (store.isDisabledByAncestor(provider.id)) {
|
|
1798
|
+
continue;
|
|
1799
|
+
}
|
|
1800
|
+
if (provider.onContextMenu) {
|
|
1801
|
+
provider.onContextMenu(menuEvent, element);
|
|
1802
|
+
break;
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
// src/AnyclickProvider.tsx
|
|
1274
1808
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1275
1809
|
var defaultMenuItems = [
|
|
1276
1810
|
{ type: "issue", label: "Report an issue", showComment: true },
|
|
1277
1811
|
{ type: "feature", label: "Request a feature", showComment: true },
|
|
1278
1812
|
{ type: "like", label: "I like this!", showComment: false }
|
|
1279
1813
|
];
|
|
1280
|
-
function
|
|
1814
|
+
function AnyclickProvider({
|
|
1281
1815
|
adapter,
|
|
1282
1816
|
children,
|
|
1283
1817
|
targetFilter,
|
|
@@ -1294,7 +1828,11 @@ function FeedbackProvider({
|
|
|
1294
1828
|
menuClassName,
|
|
1295
1829
|
disabled = false,
|
|
1296
1830
|
highlightConfig,
|
|
1297
|
-
screenshotConfig
|
|
1831
|
+
screenshotConfig,
|
|
1832
|
+
scoped = false,
|
|
1833
|
+
theme,
|
|
1834
|
+
touchHoldDurationMs,
|
|
1835
|
+
touchMoveThreshold
|
|
1298
1836
|
}) {
|
|
1299
1837
|
const [isSubmitting, setIsSubmitting] = (0, import_react6.useState)(false);
|
|
1300
1838
|
const [menuVisible, setMenuVisible] = (0, import_react6.useState)(false);
|
|
@@ -1303,8 +1841,203 @@ function FeedbackProvider({
|
|
|
1303
1841
|
const [containerElement, setContainerElement] = (0, import_react6.useState)(
|
|
1304
1842
|
null
|
|
1305
1843
|
);
|
|
1844
|
+
const providerIdRef = (0, import_react6.useRef)(generateProviderId());
|
|
1845
|
+
const providerId = providerIdRef.current;
|
|
1846
|
+
const containerRef = (0, import_react6.useRef)(null);
|
|
1847
|
+
const [containerReady, setContainerReady] = (0, import_react6.useState)(!scoped);
|
|
1306
1848
|
const clientRef = (0, import_react6.useRef)(null);
|
|
1849
|
+
const setContainerRef = (0, import_react6.useCallback)(
|
|
1850
|
+
(node) => {
|
|
1851
|
+
if (process.env.NODE_ENV === "development") {
|
|
1852
|
+
console.log(`[AnyclickProvider:${providerId}] Container ref callback`, {
|
|
1853
|
+
scoped,
|
|
1854
|
+
nodeReceived: !!node,
|
|
1855
|
+
hadPreviousNode: !!containerRef.current,
|
|
1856
|
+
clientExists: !!clientRef.current
|
|
1857
|
+
});
|
|
1858
|
+
}
|
|
1859
|
+
containerRef.current = node;
|
|
1860
|
+
if (scoped && node) {
|
|
1861
|
+
setContainerReady(true);
|
|
1862
|
+
if (clientRef.current) {
|
|
1863
|
+
clientRef.current.setContainer(node);
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
},
|
|
1867
|
+
[scoped, providerId]
|
|
1868
|
+
);
|
|
1869
|
+
let parentContext = null;
|
|
1870
|
+
try {
|
|
1871
|
+
parentContext = useAnyclick();
|
|
1872
|
+
} catch {
|
|
1873
|
+
parentContext = null;
|
|
1874
|
+
}
|
|
1875
|
+
const {
|
|
1876
|
+
registerProvider,
|
|
1877
|
+
unregisterProvider,
|
|
1878
|
+
updateProvider,
|
|
1879
|
+
getMergedTheme,
|
|
1880
|
+
isDisabledByAncestor,
|
|
1881
|
+
findParentProvider,
|
|
1882
|
+
isElementInDisabledScope,
|
|
1883
|
+
isElementInAnyScopedProvider
|
|
1884
|
+
} = useProviderStore();
|
|
1885
|
+
const parentId = parentContext?.providerId ?? null;
|
|
1886
|
+
const depth = parentContext ? parentContext.scoped ? 1 : 0 : 0;
|
|
1887
|
+
const actualDepth = (0, import_react6.useMemo)(() => {
|
|
1888
|
+
if (!parentContext) return 0;
|
|
1889
|
+
let d = 0;
|
|
1890
|
+
let currentId = parentId;
|
|
1891
|
+
const providers = useProviderStore.getState().providers;
|
|
1892
|
+
while (currentId) {
|
|
1893
|
+
d++;
|
|
1894
|
+
const parent = providers.get(currentId);
|
|
1895
|
+
currentId = parent?.parentId ?? null;
|
|
1896
|
+
}
|
|
1897
|
+
return d;
|
|
1898
|
+
}, [parentId]);
|
|
1899
|
+
const isDisabledByTheme = theme === null || theme?.disabled === true;
|
|
1900
|
+
const effectiveDisabled = disabled || isDisabledByTheme;
|
|
1901
|
+
const localTheme = (0, import_react6.useMemo)(() => {
|
|
1902
|
+
if (theme === null) {
|
|
1903
|
+
return { disabled: true };
|
|
1904
|
+
}
|
|
1905
|
+
const explicitThemeProps = {};
|
|
1906
|
+
if (menuStyle) explicitThemeProps.menuStyle = menuStyle;
|
|
1907
|
+
if (menuClassName) explicitThemeProps.menuClassName = menuClassName;
|
|
1908
|
+
if (highlightConfig) explicitThemeProps.highlightConfig = highlightConfig;
|
|
1909
|
+
if (screenshotConfig)
|
|
1910
|
+
explicitThemeProps.screenshotConfig = screenshotConfig;
|
|
1911
|
+
return {
|
|
1912
|
+
...explicitThemeProps,
|
|
1913
|
+
...theme
|
|
1914
|
+
};
|
|
1915
|
+
}, [theme, menuStyle, menuClassName, highlightConfig, screenshotConfig]);
|
|
1916
|
+
const handleContextMenu = (0, import_react6.useCallback)(
|
|
1917
|
+
(event, element) => {
|
|
1918
|
+
if (!scoped && isElementInDisabledScope(element)) {
|
|
1919
|
+
if (process.env.NODE_ENV === "development") {
|
|
1920
|
+
console.log(
|
|
1921
|
+
`[AnyclickProvider:${providerId}] Allowing native menu - element is in disabled scope`,
|
|
1922
|
+
{
|
|
1923
|
+
targetTag: element.tagName
|
|
1924
|
+
}
|
|
1925
|
+
);
|
|
1926
|
+
}
|
|
1927
|
+
return false;
|
|
1928
|
+
}
|
|
1929
|
+
if (!scoped && event.isTouch && isElementInAnyScopedProvider(element)) {
|
|
1930
|
+
if (process.env.NODE_ENV === "development") {
|
|
1931
|
+
console.log(
|
|
1932
|
+
`[AnyclickProvider:${providerId}] Deferring to scoped provider for touch event`,
|
|
1933
|
+
{
|
|
1934
|
+
targetTag: element.tagName
|
|
1935
|
+
}
|
|
1936
|
+
);
|
|
1937
|
+
}
|
|
1938
|
+
return false;
|
|
1939
|
+
}
|
|
1940
|
+
const mergedTheme2 = getMergedTheme(providerId);
|
|
1941
|
+
if (process.env.NODE_ENV === "development") {
|
|
1942
|
+
console.log(
|
|
1943
|
+
`[AnyclickProvider:${providerId}] handleContextMenu called`,
|
|
1944
|
+
{
|
|
1945
|
+
scoped,
|
|
1946
|
+
targetTag: element.tagName,
|
|
1947
|
+
mergedThemeColors: mergedTheme2.highlightConfig?.colors,
|
|
1948
|
+
position: { x: event.clientX, y: event.clientY },
|
|
1949
|
+
isTouch: event.isTouch
|
|
1950
|
+
}
|
|
1951
|
+
);
|
|
1952
|
+
}
|
|
1953
|
+
setTargetElement(element);
|
|
1954
|
+
const container = findContainerParent(
|
|
1955
|
+
element,
|
|
1956
|
+
mergedTheme2.highlightConfig ?? highlightConfig
|
|
1957
|
+
);
|
|
1958
|
+
setContainerElement(container);
|
|
1959
|
+
setMenuPosition({ x: event.clientX, y: event.clientY });
|
|
1960
|
+
setMenuVisible(true);
|
|
1961
|
+
return true;
|
|
1962
|
+
},
|
|
1963
|
+
[
|
|
1964
|
+
providerId,
|
|
1965
|
+
getMergedTheme,
|
|
1966
|
+
highlightConfig,
|
|
1967
|
+
scoped,
|
|
1968
|
+
isElementInDisabledScope,
|
|
1969
|
+
isElementInAnyScopedProvider
|
|
1970
|
+
]
|
|
1971
|
+
);
|
|
1972
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
1973
|
+
const providerInstance = {
|
|
1974
|
+
id: providerId,
|
|
1975
|
+
containerRef,
|
|
1976
|
+
scoped,
|
|
1977
|
+
theme: localTheme,
|
|
1978
|
+
disabled: effectiveDisabled,
|
|
1979
|
+
parentId,
|
|
1980
|
+
depth: actualDepth,
|
|
1981
|
+
onContextMenu: handleContextMenu
|
|
1982
|
+
};
|
|
1983
|
+
registerProvider(providerInstance);
|
|
1984
|
+
return () => {
|
|
1985
|
+
unregisterProvider(providerId);
|
|
1986
|
+
};
|
|
1987
|
+
}, [
|
|
1988
|
+
providerId,
|
|
1989
|
+
scoped,
|
|
1990
|
+
localTheme,
|
|
1991
|
+
effectiveDisabled,
|
|
1992
|
+
parentId,
|
|
1993
|
+
actualDepth,
|
|
1994
|
+
handleContextMenu,
|
|
1995
|
+
registerProvider,
|
|
1996
|
+
unregisterProvider
|
|
1997
|
+
]);
|
|
1307
1998
|
(0, import_react6.useEffect)(() => {
|
|
1999
|
+
updateProvider(providerId, {
|
|
2000
|
+
theme: localTheme,
|
|
2001
|
+
disabled: effectiveDisabled,
|
|
2002
|
+
onContextMenu: handleContextMenu
|
|
2003
|
+
});
|
|
2004
|
+
}, [
|
|
2005
|
+
providerId,
|
|
2006
|
+
localTheme,
|
|
2007
|
+
effectiveDisabled,
|
|
2008
|
+
handleContextMenu,
|
|
2009
|
+
updateProvider
|
|
2010
|
+
]);
|
|
2011
|
+
(0, import_react6.useEffect)(() => {
|
|
2012
|
+
if (isDisabledByAncestor(providerId)) {
|
|
2013
|
+
if (process.env.NODE_ENV === "development") {
|
|
2014
|
+
console.log(
|
|
2015
|
+
`[AnyclickProvider:${providerId}] Skipping - disabled by ancestor`
|
|
2016
|
+
);
|
|
2017
|
+
}
|
|
2018
|
+
return;
|
|
2019
|
+
}
|
|
2020
|
+
if (scoped && !containerReady) {
|
|
2021
|
+
if (process.env.NODE_ENV === "development") {
|
|
2022
|
+
console.log(
|
|
2023
|
+
`[AnyclickProvider:${providerId}] Waiting for container to be ready`,
|
|
2024
|
+
{
|
|
2025
|
+
scoped,
|
|
2026
|
+
containerReady
|
|
2027
|
+
}
|
|
2028
|
+
);
|
|
2029
|
+
}
|
|
2030
|
+
return;
|
|
2031
|
+
}
|
|
2032
|
+
if (process.env.NODE_ENV === "development") {
|
|
2033
|
+
console.log(`[AnyclickProvider:${providerId}] Creating client`, {
|
|
2034
|
+
scoped,
|
|
2035
|
+
containerReady,
|
|
2036
|
+
hasContainer: !!containerRef.current,
|
|
2037
|
+
effectiveDisabled,
|
|
2038
|
+
localThemeColors: localTheme.highlightConfig?.colors
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
1308
2041
|
const client = (0, import_anyclick_core3.createFeedbackClient)({
|
|
1309
2042
|
adapter,
|
|
1310
2043
|
targetFilter,
|
|
@@ -1312,19 +2045,17 @@ function FeedbackProvider({
|
|
|
1312
2045
|
maxOuterHTMLLength,
|
|
1313
2046
|
maxAncestors,
|
|
1314
2047
|
cooldownMs,
|
|
1315
|
-
stripAttributes
|
|
2048
|
+
stripAttributes,
|
|
2049
|
+
// For scoped providers, pass the container
|
|
2050
|
+
container: scoped ? containerRef.current : null,
|
|
2051
|
+
touchHoldDurationMs,
|
|
2052
|
+
touchMoveThreshold
|
|
1316
2053
|
});
|
|
1317
2054
|
client.onSubmitSuccess = onSubmitSuccess;
|
|
1318
2055
|
client.onSubmitError = onSubmitError;
|
|
1319
|
-
client.onContextMenu =
|
|
1320
|
-
setTargetElement(element);
|
|
1321
|
-
const container = findContainerParent(element, highlightConfig);
|
|
1322
|
-
setContainerElement(container);
|
|
1323
|
-
setMenuPosition({ x: event.clientX, y: event.clientY });
|
|
1324
|
-
setMenuVisible(true);
|
|
1325
|
-
};
|
|
2056
|
+
client.onContextMenu = handleContextMenu;
|
|
1326
2057
|
clientRef.current = client;
|
|
1327
|
-
if (!
|
|
2058
|
+
if (!effectiveDisabled) {
|
|
1328
2059
|
client.attach();
|
|
1329
2060
|
}
|
|
1330
2061
|
return () => {
|
|
@@ -1340,8 +2071,14 @@ function FeedbackProvider({
|
|
|
1340
2071
|
stripAttributes,
|
|
1341
2072
|
onSubmitSuccess,
|
|
1342
2073
|
onSubmitError,
|
|
1343
|
-
|
|
1344
|
-
|
|
2074
|
+
effectiveDisabled,
|
|
2075
|
+
scoped,
|
|
2076
|
+
containerReady,
|
|
2077
|
+
providerId,
|
|
2078
|
+
isDisabledByAncestor,
|
|
2079
|
+
handleContextMenu,
|
|
2080
|
+
touchHoldDurationMs,
|
|
2081
|
+
touchMoveThreshold
|
|
1345
2082
|
]);
|
|
1346
2083
|
const submitFeedback = (0, import_react6.useCallback)(
|
|
1347
2084
|
async (element, type, comment, screenshots) => {
|
|
@@ -1366,12 +2103,16 @@ function FeedbackProvider({
|
|
|
1366
2103
|
const openMenu = (0, import_react6.useCallback)(
|
|
1367
2104
|
(element, position) => {
|
|
1368
2105
|
setTargetElement(element);
|
|
1369
|
-
const
|
|
2106
|
+
const mergedTheme2 = getMergedTheme(providerId);
|
|
2107
|
+
const container = findContainerParent(
|
|
2108
|
+
element,
|
|
2109
|
+
mergedTheme2.highlightConfig ?? highlightConfig
|
|
2110
|
+
);
|
|
1370
2111
|
setContainerElement(container);
|
|
1371
2112
|
setMenuPosition(position);
|
|
1372
2113
|
setMenuVisible(true);
|
|
1373
2114
|
},
|
|
1374
|
-
[highlightConfig]
|
|
2115
|
+
[providerId, getMergedTheme, highlightConfig]
|
|
1375
2116
|
);
|
|
1376
2117
|
const closeMenu = (0, import_react6.useCallback)(() => {
|
|
1377
2118
|
setMenuVisible(false);
|
|
@@ -1386,22 +2127,73 @@ function FeedbackProvider({
|
|
|
1386
2127
|
},
|
|
1387
2128
|
[targetElement, submitFeedback]
|
|
1388
2129
|
);
|
|
2130
|
+
const inheritedTheme = getMergedTheme(providerId);
|
|
2131
|
+
const mergedTheme = (0, import_react6.useMemo)(
|
|
2132
|
+
() => ({
|
|
2133
|
+
...inheritedTheme,
|
|
2134
|
+
...localTheme,
|
|
2135
|
+
// Deep merge for nested configs
|
|
2136
|
+
highlightConfig: {
|
|
2137
|
+
...inheritedTheme.highlightConfig,
|
|
2138
|
+
...localTheme.highlightConfig,
|
|
2139
|
+
colors: {
|
|
2140
|
+
...inheritedTheme.highlightConfig?.colors,
|
|
2141
|
+
...localTheme.highlightConfig?.colors
|
|
2142
|
+
}
|
|
2143
|
+
},
|
|
2144
|
+
screenshotConfig: {
|
|
2145
|
+
...inheritedTheme.screenshotConfig,
|
|
2146
|
+
...localTheme.screenshotConfig
|
|
2147
|
+
}
|
|
2148
|
+
}),
|
|
2149
|
+
[inheritedTheme, localTheme]
|
|
2150
|
+
);
|
|
2151
|
+
const effectiveMenuStyle = mergedTheme.menuStyle ?? menuStyle;
|
|
2152
|
+
const effectiveMenuClassName = mergedTheme.menuClassName ?? menuClassName;
|
|
2153
|
+
if (process.env.NODE_ENV === "development") {
|
|
2154
|
+
console.log(`[AnyclickProvider:${providerId}] Theme Debug`, {
|
|
2155
|
+
scoped,
|
|
2156
|
+
localThemeHasMenuStyle: !!localTheme.menuStyle,
|
|
2157
|
+
localThemeMenuStyleKeys: localTheme.menuStyle ? Object.keys(localTheme.menuStyle) : [],
|
|
2158
|
+
mergedThemeHasMenuStyle: !!mergedTheme.menuStyle,
|
|
2159
|
+
mergedThemeMenuStyleKeys: mergedTheme.menuStyle ? Object.keys(mergedTheme.menuStyle) : [],
|
|
2160
|
+
effectiveMenuStyleExists: !!effectiveMenuStyle,
|
|
2161
|
+
effectiveMenuStyleKeys: effectiveMenuStyle ? Object.keys(effectiveMenuStyle) : [],
|
|
2162
|
+
menuStyleProp: !!menuStyle
|
|
2163
|
+
});
|
|
2164
|
+
}
|
|
2165
|
+
const effectiveHighlightConfig = mergedTheme.highlightConfig ?? highlightConfig;
|
|
2166
|
+
const effectiveScreenshotConfig = mergedTheme.screenshotConfig ?? screenshotConfig;
|
|
1389
2167
|
const contextValue = (0, import_react6.useMemo)(
|
|
1390
2168
|
() => ({
|
|
1391
|
-
isEnabled: !
|
|
2169
|
+
isEnabled: !effectiveDisabled && !isDisabledByAncestor(providerId),
|
|
1392
2170
|
isSubmitting,
|
|
1393
2171
|
submitFeedback,
|
|
1394
2172
|
openMenu,
|
|
1395
|
-
closeMenu
|
|
2173
|
+
closeMenu,
|
|
2174
|
+
theme: mergedTheme,
|
|
2175
|
+
scoped,
|
|
2176
|
+
providerId
|
|
1396
2177
|
}),
|
|
1397
|
-
[
|
|
2178
|
+
[
|
|
2179
|
+
effectiveDisabled,
|
|
2180
|
+
providerId,
|
|
2181
|
+
isDisabledByAncestor,
|
|
2182
|
+
isSubmitting,
|
|
2183
|
+
submitFeedback,
|
|
2184
|
+
openMenu,
|
|
2185
|
+
closeMenu,
|
|
2186
|
+
mergedTheme,
|
|
2187
|
+
scoped
|
|
2188
|
+
]
|
|
1398
2189
|
);
|
|
1399
|
-
|
|
1400
|
-
|
|
2190
|
+
const content = scoped ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: setContainerRef, style: { display: "contents" }, children }) : children;
|
|
2191
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(AnyclickContext.Provider, { value: contextValue, children: [
|
|
2192
|
+
content,
|
|
1401
2193
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1402
2194
|
ContextMenu,
|
|
1403
2195
|
{
|
|
1404
|
-
visible: menuVisible && !
|
|
2196
|
+
visible: menuVisible && !effectiveDisabled,
|
|
1405
2197
|
position: menuPosition,
|
|
1406
2198
|
targetElement,
|
|
1407
2199
|
containerElement,
|
|
@@ -1409,14 +2201,15 @@ function FeedbackProvider({
|
|
|
1409
2201
|
onSelect: handleMenuSelect,
|
|
1410
2202
|
onClose: closeMenu,
|
|
1411
2203
|
isSubmitting,
|
|
1412
|
-
style:
|
|
1413
|
-
className:
|
|
1414
|
-
highlightConfig,
|
|
1415
|
-
screenshotConfig
|
|
2204
|
+
style: effectiveMenuStyle,
|
|
2205
|
+
className: effectiveMenuClassName,
|
|
2206
|
+
highlightConfig: effectiveHighlightConfig,
|
|
2207
|
+
screenshotConfig: effectiveScreenshotConfig
|
|
1416
2208
|
}
|
|
1417
2209
|
)
|
|
1418
2210
|
] });
|
|
1419
2211
|
}
|
|
2212
|
+
var FeedbackProvider = AnyclickProvider;
|
|
1420
2213
|
|
|
1421
2214
|
// src/types.ts
|
|
1422
2215
|
function filterMenuItemsByRole(items, userContext) {
|
|
@@ -1438,6 +2231,8 @@ function filterMenuItemsByRole(items, userContext) {
|
|
|
1438
2231
|
var import_anyclick_core4 = require("@ewjdev/anyclick-core");
|
|
1439
2232
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1440
2233
|
0 && (module.exports = {
|
|
2234
|
+
AnyclickContext,
|
|
2235
|
+
AnyclickProvider,
|
|
1441
2236
|
ContextMenu,
|
|
1442
2237
|
DEFAULT_SCREENSHOT_CONFIG,
|
|
1443
2238
|
DEFAULT_SENSITIVE_SELECTORS,
|
|
@@ -1451,15 +2246,20 @@ var import_anyclick_core4 = require("@ewjdev/anyclick-core");
|
|
|
1451
2246
|
darkMenuStyles,
|
|
1452
2247
|
defaultContainerSelectors,
|
|
1453
2248
|
defaultHighlightColors,
|
|
2249
|
+
dispatchContextMenuEvent,
|
|
1454
2250
|
estimateTotalSize,
|
|
1455
2251
|
filterMenuItemsByRole,
|
|
1456
2252
|
findContainerParent,
|
|
1457
2253
|
formatBytes,
|
|
2254
|
+
generateProviderId,
|
|
1458
2255
|
highlightContainer,
|
|
1459
2256
|
highlightTarget,
|
|
1460
2257
|
isScreenshotSupported,
|
|
2258
|
+
menuCSSVariables,
|
|
1461
2259
|
menuStyles,
|
|
1462
|
-
|
|
2260
|
+
useAnyclick,
|
|
2261
|
+
useFeedback,
|
|
2262
|
+
useProviderStore
|
|
1463
2263
|
});
|
|
1464
2264
|
/*! Bundled license information:
|
|
1465
2265
|
|
|
@@ -1471,8 +2271,10 @@ lucide-react/dist/esm/icons/camera.js:
|
|
|
1471
2271
|
lucide-react/dist/esm/icons/check.js:
|
|
1472
2272
|
lucide-react/dist/esm/icons/chevron-left.js:
|
|
1473
2273
|
lucide-react/dist/esm/icons/chevron-right.js:
|
|
2274
|
+
lucide-react/dist/esm/icons/circle-alert.js:
|
|
1474
2275
|
lucide-react/dist/esm/icons/expand.js:
|
|
1475
2276
|
lucide-react/dist/esm/icons/flag.js:
|
|
2277
|
+
lucide-react/dist/esm/icons/grip-vertical.js:
|
|
1476
2278
|
lucide-react/dist/esm/icons/image.js:
|
|
1477
2279
|
lucide-react/dist/esm/icons/loader-circle.js:
|
|
1478
2280
|
lucide-react/dist/esm/icons/plus.js:
|