@ewjdev/anyclick-react 0.1.0 → 1.1.0

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/dist/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  "use client";
2
2
 
3
- // src/FeedbackProvider.tsx
3
+ // src/AnyclickProvider.tsx
4
4
  import {
5
5
  useCallback as useCallback2,
6
6
  useEffect as useEffect2,
7
+ useLayoutEffect,
7
8
  useMemo,
8
9
  useRef as useRef2,
9
10
  useState as useState3
@@ -12,9 +13,17 @@ import { createFeedbackClient } from "@ewjdev/anyclick-core";
12
13
 
13
14
  // src/context.ts
14
15
  import { createContext, useContext } from "react";
15
- var FeedbackContext = createContext(null);
16
+ var AnyclickContext = createContext(null);
17
+ var FeedbackContext = AnyclickContext;
18
+ function useAnyclick() {
19
+ const context = useContext(AnyclickContext);
20
+ if (!context) {
21
+ throw new Error("useAnyclick must be used within an AnyclickProvider");
22
+ }
23
+ return context;
24
+ }
16
25
  function useFeedback() {
17
- const context = useContext(FeedbackContext);
26
+ const context = useContext(AnyclickContext);
18
27
  if (!context) {
19
28
  throw new Error("useFeedback must be used within a FeedbackProvider");
20
29
  }
@@ -30,6 +39,25 @@ import {
30
39
  } from "@ewjdev/anyclick-core";
31
40
 
32
41
  // src/styles.ts
42
+ var menuCSSVariables = {
43
+ // Background colors
44
+ "--anyclick-menu-bg": "#ffffff",
45
+ "--anyclick-menu-hover": "#f5f5f5",
46
+ // Text colors
47
+ "--anyclick-menu-text": "#333333",
48
+ "--anyclick-menu-text-muted": "#666666",
49
+ // Border colors
50
+ "--anyclick-menu-border": "#e5e5e5",
51
+ // Accent/action colors
52
+ "--anyclick-menu-accent": "#0066cc",
53
+ "--anyclick-menu-accent-text": "#ffffff",
54
+ // Input colors
55
+ "--anyclick-menu-input-bg": "#ffffff",
56
+ "--anyclick-menu-input-border": "#dddddd",
57
+ // Cancel button
58
+ "--anyclick-menu-cancel-bg": "#f0f0f0",
59
+ "--anyclick-menu-cancel-text": "#666666"
60
+ };
33
61
  var menuStyles = {
34
62
  overlay: {
35
63
  position: "fixed",
@@ -40,17 +68,19 @@ var menuStyles = {
40
68
  position: "fixed",
41
69
  zIndex: 9999,
42
70
  minWidth: "200px",
43
- backgroundColor: "#ffffff",
71
+ backgroundColor: "var(--anyclick-menu-bg, #ffffff)",
44
72
  borderRadius: "8px",
45
73
  boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.05)",
46
74
  overflow: "hidden",
47
75
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
48
- fontSize: "14px"
76
+ fontSize: "14px",
77
+ // Set default CSS variables
78
+ ...menuCSSVariables
49
79
  },
50
80
  header: {
51
81
  padding: "12px 16px",
52
- borderBottom: "1px solid #e5e5e5",
53
- color: "#666",
82
+ borderBottom: "1px solid var(--anyclick-menu-border, #e5e5e5)",
83
+ color: "var(--anyclick-menu-text-muted, #666)",
54
84
  fontSize: "12px",
55
85
  fontWeight: 500,
56
86
  textTransform: "uppercase",
@@ -66,15 +96,15 @@ var menuStyles = {
66
96
  padding: "10px 16px",
67
97
  cursor: "pointer",
68
98
  transition: "background-color 0.15s",
69
- color: "#333",
99
+ color: "var(--anyclick-menu-text, #333)",
70
100
  border: "none",
71
- background: "none",
101
+ backgroundColor: "transparent",
72
102
  width: "100%",
73
103
  textAlign: "left",
74
104
  fontSize: "14px"
75
105
  },
76
106
  itemHover: {
77
- backgroundColor: "#f5f5f5"
107
+ backgroundColor: "var(--anyclick-menu-hover, #f5f5f5)"
78
108
  },
79
109
  itemIcon: {
80
110
  display: "flex",
@@ -86,19 +116,21 @@ var menuStyles = {
86
116
  },
87
117
  commentSection: {
88
118
  padding: "12px 16px",
89
- borderTop: "1px solid #e5e5e5"
119
+ borderTop: "1px solid var(--anyclick-menu-border, #e5e5e5)"
90
120
  },
91
121
  commentInput: {
92
122
  width: "100%",
93
123
  minHeight: "60px",
94
124
  padding: "8px 12px",
95
- border: "1px solid #ddd",
125
+ border: "1px solid var(--anyclick-menu-input-border, #ddd)",
96
126
  borderRadius: "6px",
97
127
  fontSize: "14px",
98
128
  fontFamily: "inherit",
99
129
  resize: "vertical",
100
130
  outline: "none",
101
- boxSizing: "border-box"
131
+ boxSizing: "border-box",
132
+ backgroundColor: "var(--anyclick-menu-input-bg, #ffffff)",
133
+ color: "var(--anyclick-menu-text, #333)"
102
134
  },
103
135
  buttonRow: {
104
136
  display: "flex",
@@ -116,15 +148,15 @@ var menuStyles = {
116
148
  border: "none"
117
149
  },
118
150
  cancelButton: {
119
- backgroundColor: "#f0f0f0",
120
- color: "#666",
151
+ backgroundColor: "var(--anyclick-menu-cancel-bg, #f0f0f0)",
152
+ color: "var(--anyclick-menu-cancel-text, #666)",
121
153
  display: "flex",
122
154
  alignItems: "center",
123
155
  gap: "2px"
124
156
  },
125
157
  submitButton: {
126
- backgroundColor: "#0066cc",
127
- color: "#ffffff",
158
+ backgroundColor: "var(--anyclick-menu-accent, #0066cc)",
159
+ color: "var(--anyclick-menu-accent-text, #ffffff)",
128
160
  display: "flex",
129
161
  alignItems: "center",
130
162
  gap: "2px"
@@ -168,6 +200,242 @@ var darkMenuStyles = {
168
200
  color: "#ccc"
169
201
  }
170
202
  };
203
+ var screenshotPreviewStyles = {
204
+ container: {
205
+ width: "100%",
206
+ display: "flex",
207
+ flexDirection: "column",
208
+ gap: "8px"
209
+ },
210
+ containerExpanded: {
211
+ position: "fixed",
212
+ top: "50%",
213
+ left: "50%",
214
+ transform: "translate(-50%, -50%)",
215
+ width: "90vw",
216
+ maxWidth: "800px",
217
+ maxHeight: "90vh",
218
+ backgroundColor: "#fff",
219
+ borderRadius: "12px",
220
+ boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
221
+ padding: "16px",
222
+ zIndex: 1e4
223
+ },
224
+ loadingContainer: {
225
+ display: "flex",
226
+ flexDirection: "column",
227
+ alignItems: "center",
228
+ justifyContent: "center",
229
+ gap: "12px",
230
+ padding: "24px"
231
+ },
232
+ loadingText: {
233
+ fontSize: "13px",
234
+ color: "#6b7280"
235
+ },
236
+ emptyContainer: {
237
+ display: "flex",
238
+ flexDirection: "column",
239
+ alignItems: "center",
240
+ justifyContent: "center",
241
+ gap: "8px",
242
+ padding: "24px"
243
+ },
244
+ emptyText: {
245
+ fontSize: "13px",
246
+ color: "#6b7280",
247
+ fontWeight: "500"
248
+ },
249
+ emptySubtext: {
250
+ fontSize: "11px",
251
+ color: "#9ca3af",
252
+ textAlign: "center"
253
+ },
254
+ emptyActions: {
255
+ display: "flex",
256
+ gap: "8px",
257
+ marginTop: "8px"
258
+ },
259
+ retakeButtonOutline: {
260
+ display: "flex",
261
+ alignItems: "center",
262
+ gap: "6px",
263
+ padding: "8px 12px",
264
+ fontSize: "12px",
265
+ color: "#6b7280",
266
+ backgroundColor: "transparent",
267
+ border: "1px solid #e5e7eb",
268
+ borderRadius: "6px",
269
+ cursor: "pointer"
270
+ },
271
+ continueButton: {
272
+ display: "flex",
273
+ alignItems: "center",
274
+ gap: "6px",
275
+ padding: "8px 12px",
276
+ fontSize: "12px",
277
+ color: "#fff",
278
+ backgroundColor: "#3b82f6",
279
+ border: "none",
280
+ borderRadius: "6px",
281
+ cursor: "pointer",
282
+ fontWeight: "500"
283
+ },
284
+ header: {
285
+ display: "flex",
286
+ justifyContent: "space-between",
287
+ alignItems: "center",
288
+ padding: "0 4px"
289
+ },
290
+ headerTitle: {
291
+ fontSize: "12px",
292
+ fontWeight: "600",
293
+ color: "#374151",
294
+ textTransform: "uppercase",
295
+ letterSpacing: "0.05em"
296
+ },
297
+ headerActions: {
298
+ display: "flex",
299
+ alignItems: "center",
300
+ gap: "8px"
301
+ },
302
+ sizeLabel: {
303
+ fontSize: "11px",
304
+ color: "#9ca3af"
305
+ },
306
+ iconButton: {
307
+ display: "flex",
308
+ alignItems: "center",
309
+ justifyContent: "center",
310
+ width: "24px",
311
+ height: "24px",
312
+ border: "none",
313
+ backgroundColor: "transparent",
314
+ borderRadius: "4px",
315
+ cursor: "pointer",
316
+ color: "#6b7280"
317
+ },
318
+ tabContainer: {
319
+ display: "flex",
320
+ gap: "4px",
321
+ borderBottom: "1px solid #e5e7eb",
322
+ paddingBottom: "8px"
323
+ },
324
+ tab: {
325
+ display: "flex",
326
+ alignItems: "center",
327
+ gap: "4px",
328
+ padding: "2px 5px",
329
+ fontSize: "12px",
330
+ color: "#6b7280",
331
+ backgroundColor: "transparent",
332
+ border: "none",
333
+ borderRadius: "4px",
334
+ cursor: "pointer",
335
+ transition: "all 0.15s ease"
336
+ },
337
+ tabActive: {
338
+ backgroundColor: "#eff6ff",
339
+ color: "#3b82f6",
340
+ fontWeight: "500"
341
+ },
342
+ tabError: {
343
+ color: "#ef4444"
344
+ },
345
+ tabSize: {
346
+ fontSize: "10px",
347
+ color: "#9ca3af"
348
+ },
349
+ previewContainer: {
350
+ position: "relative",
351
+ width: "100%",
352
+ height: "150px",
353
+ backgroundColor: "#f9fafb",
354
+ borderRadius: "8px",
355
+ overflow: "hidden",
356
+ display: "flex",
357
+ alignItems: "center",
358
+ justifyContent: "center"
359
+ },
360
+ previewContainerExpanded: {
361
+ height: "60vh",
362
+ maxHeight: "500px"
363
+ },
364
+ previewImage: {
365
+ maxWidth: "100%",
366
+ maxHeight: "100%",
367
+ objectFit: "contain"
368
+ },
369
+ noPreview: {
370
+ display: "flex",
371
+ flexDirection: "column",
372
+ alignItems: "center",
373
+ gap: "8px",
374
+ fontSize: "12px",
375
+ color: "#9ca3af"
376
+ },
377
+ errorPreview: {
378
+ display: "flex",
379
+ flexDirection: "column",
380
+ alignItems: "center",
381
+ justifyContent: "center",
382
+ gap: "8px",
383
+ padding: "16px",
384
+ textAlign: "center"
385
+ },
386
+ errorTitle: {
387
+ fontSize: "14px",
388
+ fontWeight: "600",
389
+ color: "#ef4444"
390
+ },
391
+ errorMessage: {
392
+ fontSize: "12px",
393
+ color: "#6b7280",
394
+ maxWidth: "250px",
395
+ lineHeight: "1.4"
396
+ },
397
+ dimensionsInfo: {
398
+ fontSize: "11px",
399
+ color: "#9ca3af",
400
+ textAlign: "center"
401
+ },
402
+ actions: {
403
+ display: "flex",
404
+ justifyContent: "space-between",
405
+ alignItems: "center",
406
+ paddingTop: "8px",
407
+ borderTop: "1px solid #e5e7eb"
408
+ },
409
+ actionsRight: {
410
+ display: "flex",
411
+ gap: "8px"
412
+ },
413
+ retakeButton: {
414
+ display: "flex",
415
+ alignItems: "center",
416
+ gap: "6px",
417
+ padding: "8px 16px",
418
+ fontSize: "13px",
419
+ color: "#fff",
420
+ backgroundColor: "#3b82f6",
421
+ border: "none",
422
+ borderRadius: "6px",
423
+ cursor: "pointer",
424
+ fontWeight: "500"
425
+ },
426
+ retakeButtonSmall: {
427
+ display: "flex",
428
+ alignItems: "center",
429
+ gap: "4px",
430
+ padding: "4px 8px",
431
+ fontSize: "11px",
432
+ color: "#6b7280",
433
+ backgroundColor: "transparent",
434
+ border: "1px solid #e5e7eb",
435
+ borderRadius: "4px",
436
+ cursor: "pointer"
437
+ }
438
+ };
171
439
 
172
440
  // src/highlight.ts
173
441
  var HIGHLIGHT_TARGET_CLASS = "uifeedback-highlight-target";
@@ -202,7 +470,12 @@ var defaultContainerSelectors = [
202
470
  "footer"
203
471
  ];
204
472
  function generateHighlightCSS(colors) {
205
- const { targetColor, containerColor, targetShadowOpacity, containerShadowOpacity } = colors;
473
+ const {
474
+ targetColor,
475
+ containerColor,
476
+ targetShadowOpacity,
477
+ containerShadowOpacity
478
+ } = colors;
206
479
  const hexToRgba = (hex, alpha) => {
207
480
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
208
481
  if (!result) return `rgba(0, 0, 0, ${alpha})`;
@@ -210,7 +483,7 @@ function generateHighlightCSS(colors) {
210
483
  };
211
484
  return `
212
485
  .${HIGHLIGHT_TARGET_CLASS} {
213
- outline: 2px solid ${targetColor} !important;
486
+ outline: 2px dashed ${targetColor} !important;
214
487
  outline-offset: 2px !important;
215
488
  box-shadow: 0 0 0 4px ${hexToRgba(targetColor, targetShadowOpacity)}, 0 4px 12px ${hexToRgba(targetColor, targetShadowOpacity * 0.6)} !important;
216
489
  border-radius: 4px !important;
@@ -425,8 +698,16 @@ var ChevronLeft = createLucideIcon("chevron-left", __iconNode3);
425
698
  var __iconNode4 = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
426
699
  var ChevronRight = createLucideIcon("chevron-right", __iconNode4);
427
700
 
428
- // ../../node_modules/lucide-react/dist/esm/icons/expand.js
701
+ // ../../node_modules/lucide-react/dist/esm/icons/circle-alert.js
429
702
  var __iconNode5 = [
703
+ ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
704
+ ["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
705
+ ["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
706
+ ];
707
+ var CircleAlert = createLucideIcon("circle-alert", __iconNode5);
708
+
709
+ // ../../node_modules/lucide-react/dist/esm/icons/expand.js
710
+ var __iconNode6 = [
430
711
  ["path", { d: "m15 15 6 6", key: "1s409w" }],
431
712
  ["path", { d: "m15 9 6-6", key: "ko1vev" }],
432
713
  ["path", { d: "M21 16v5h-5", key: "1ck2sf" }],
@@ -436,10 +717,10 @@ var __iconNode5 = [
436
717
  ["path", { d: "M3 8V3h5", key: "1ln10m" }],
437
718
  ["path", { d: "M9 9 3 3", key: "v551iv" }]
438
719
  ];
439
- var Expand = createLucideIcon("expand", __iconNode5);
720
+ var Expand = createLucideIcon("expand", __iconNode6);
440
721
 
441
722
  // ../../node_modules/lucide-react/dist/esm/icons/flag.js
442
- var __iconNode6 = [
723
+ var __iconNode7 = [
443
724
  [
444
725
  "path",
445
726
  {
@@ -448,47 +729,47 @@ var __iconNode6 = [
448
729
  }
449
730
  ]
450
731
  ];
451
- var Flag = createLucideIcon("flag", __iconNode6);
732
+ var Flag = createLucideIcon("flag", __iconNode7);
452
733
 
453
734
  // ../../node_modules/lucide-react/dist/esm/icons/image.js
454
- var __iconNode7 = [
735
+ var __iconNode8 = [
455
736
  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
456
737
  ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
457
738
  ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
458
739
  ];
459
- var Image = createLucideIcon("image", __iconNode7);
740
+ var Image = createLucideIcon("image", __iconNode8);
460
741
 
461
742
  // ../../node_modules/lucide-react/dist/esm/icons/loader-circle.js
462
- var __iconNode8 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
463
- var LoaderCircle = createLucideIcon("loader-circle", __iconNode8);
743
+ var __iconNode9 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
744
+ var LoaderCircle = createLucideIcon("loader-circle", __iconNode9);
464
745
 
465
746
  // ../../node_modules/lucide-react/dist/esm/icons/plus.js
466
- var __iconNode9 = [
747
+ var __iconNode10 = [
467
748
  ["path", { d: "M5 12h14", key: "1ays0h" }],
468
749
  ["path", { d: "M12 5v14", key: "s699le" }]
469
750
  ];
470
- var Plus = createLucideIcon("plus", __iconNode9);
751
+ var Plus = createLucideIcon("plus", __iconNode10);
471
752
 
472
753
  // ../../node_modules/lucide-react/dist/esm/icons/refresh-cw.js
473
- var __iconNode10 = [
754
+ var __iconNode11 = [
474
755
  ["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
475
756
  ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
476
757
  ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
477
758
  ["path", { d: "M8 16H3v5", key: "1cv678" }]
478
759
  ];
479
- var RefreshCw = createLucideIcon("refresh-cw", __iconNode10);
760
+ var RefreshCw = createLucideIcon("refresh-cw", __iconNode11);
480
761
 
481
762
  // ../../node_modules/lucide-react/dist/esm/icons/shrink.js
482
- var __iconNode11 = [
763
+ var __iconNode12 = [
483
764
  ["path", { d: "m15 15 6 6m-6-6v4.8m0-4.8h4.8", key: "17vawe" }],
484
765
  ["path", { d: "M9 19.8V15m0 0H4.2M9 15l-6 6", key: "chjx8e" }],
485
766
  ["path", { d: "M15 4.2V9m0 0h4.8M15 9l6-6", key: "lav6yq" }],
486
767
  ["path", { d: "M9 4.2V9m0 0H4.2M9 9 3 3", key: "1pxi2q" }]
487
768
  ];
488
- var Shrink = createLucideIcon("shrink", __iconNode11);
769
+ var Shrink = createLucideIcon("shrink", __iconNode12);
489
770
 
490
771
  // ../../node_modules/lucide-react/dist/esm/icons/thumbs-up.js
491
- var __iconNode12 = [
772
+ var __iconNode13 = [
492
773
  ["path", { d: "M7 10v12", key: "1qc93n" }],
493
774
  [
494
775
  "path",
@@ -498,14 +779,14 @@ var __iconNode12 = [
498
779
  }
499
780
  ]
500
781
  ];
501
- var ThumbsUp = createLucideIcon("thumbs-up", __iconNode12);
782
+ var ThumbsUp = createLucideIcon("thumbs-up", __iconNode13);
502
783
 
503
784
  // ../../node_modules/lucide-react/dist/esm/icons/x.js
504
- var __iconNode13 = [
785
+ var __iconNode14 = [
505
786
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
506
787
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
507
788
  ];
508
- var X = createLucideIcon("x", __iconNode13);
789
+ var X = createLucideIcon("x", __iconNode14);
509
790
 
510
791
  // src/ScreenshotPreview.tsx
511
792
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -520,7 +801,7 @@ function ScreenshotPreview({
520
801
  const [activeTab, setActiveTab] = useState("element");
521
802
  const [isExpanded, setIsExpanded] = useState(false);
522
803
  if (isLoading) {
523
- return /* @__PURE__ */ jsx("div", { style: styles.container, children: /* @__PURE__ */ jsxs("div", { style: styles.loadingContainer, children: [
804
+ return /* @__PURE__ */ jsx("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ jsxs("div", { style: screenshotPreviewStyles.loadingContainer, children: [
524
805
  /* @__PURE__ */ jsx(
525
806
  LoaderCircle,
526
807
  {
@@ -528,76 +809,117 @@ function ScreenshotPreview({
528
809
  style: { color: "#3b82f6" }
529
810
  }
530
811
  ),
531
- /* @__PURE__ */ jsx("span", { style: styles.loadingText, children: "Capturing screenshots..." })
812
+ /* @__PURE__ */ jsx("span", { style: screenshotPreviewStyles.loadingText, children: "Capturing screenshots..." })
532
813
  ] }) });
533
814
  }
534
815
  if (!screenshots) {
535
- return /* @__PURE__ */ jsx("div", { style: styles.container, children: /* @__PURE__ */ jsxs("div", { style: styles.emptyContainer, children: [
816
+ return /* @__PURE__ */ jsx("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ jsxs("div", { style: screenshotPreviewStyles.emptyContainer, children: [
536
817
  /* @__PURE__ */ jsx(Image, { className: "w-8 h-8", style: { color: "#9ca3af" } }),
537
- /* @__PURE__ */ jsx("span", { style: styles.emptyText, children: "No screenshots captured" }),
538
- /* @__PURE__ */ jsxs(
539
- "button",
540
- {
541
- type: "button",
542
- onClick: onRetake,
543
- style: styles.retakeButton,
544
- disabled: isSubmitting,
545
- children: [
546
- /* @__PURE__ */ jsx(RefreshCw, { className: "w-4 h-4" }),
547
- "Capture Screenshots"
548
- ]
549
- }
550
- )
551
- ] }) });
552
- }
553
- const allTabs = [
554
- { key: "element", label: "Element", data: screenshots.element },
555
- {
818
+ /* @__PURE__ */ jsx("span", { style: screenshotPreviewStyles.emptyText, children: "Screenshots unavailable" }),
819
+ /* @__PURE__ */ jsx("span", { style: screenshotPreviewStyles.emptySubtext, children: "Some elements can't be captured (e.g., gradient text)" }),
820
+ /* @__PURE__ */ jsxs("div", { style: screenshotPreviewStyles.emptyActions, children: [
821
+ /* @__PURE__ */ jsxs(
822
+ "button",
823
+ {
824
+ type: "button",
825
+ onClick: onRetake,
826
+ style: screenshotPreviewStyles.retakeButtonOutline,
827
+ disabled: isSubmitting,
828
+ children: [
829
+ /* @__PURE__ */ jsx(RefreshCw, { className: "w-4 h-4" }),
830
+ "Try Again"
831
+ ]
832
+ }
833
+ ),
834
+ /* @__PURE__ */ jsxs(
835
+ "button",
836
+ {
837
+ type: "button",
838
+ onClick: () => onConfirm({ capturedAt: (/* @__PURE__ */ new Date()).toISOString() }),
839
+ style: screenshotPreviewStyles.continueButton,
840
+ disabled: isSubmitting,
841
+ children: [
842
+ /* @__PURE__ */ jsx(Check, { className: "w-4 h-4" }),
843
+ "Continue Without"
844
+ ]
845
+ }
846
+ )
847
+ ] })
848
+ ] }) });
849
+ }
850
+ const getError = (key) => {
851
+ return screenshots.errors?.[key];
852
+ };
853
+ const allTabs = [
854
+ {
855
+ key: "element",
856
+ label: "Element",
857
+ data: screenshots.element,
858
+ error: getError("element")
859
+ },
860
+ {
556
861
  key: "container",
557
862
  label: "Container",
558
- data: screenshots.container
863
+ data: screenshots.container,
864
+ error: getError("container")
559
865
  },
560
- { key: "viewport", label: "Viewport", data: screenshots.viewport }
866
+ {
867
+ key: "viewport",
868
+ label: "Viewport",
869
+ data: screenshots.viewport,
870
+ error: getError("viewport")
871
+ }
561
872
  ];
562
- const tabs = allTabs.filter((tab) => tab.data);
873
+ const tabs = allTabs.filter((tab) => tab.data || tab.error);
563
874
  const activeScreenshot = activeTab === "element" ? screenshots.element : activeTab === "container" ? screenshots.container : screenshots.viewport;
875
+ const activeError = getError(activeTab);
564
876
  const totalSize = estimateTotalSize(screenshots);
877
+ console.log({ styles: screenshotPreviewStyles });
565
878
  return /* @__PURE__ */ jsxs(
566
879
  "div",
567
880
  {
568
881
  style: {
569
- ...styles.container,
570
- ...isExpanded ? styles.containerExpanded : {}
882
+ ...screenshotPreviewStyles.container,
883
+ ...isExpanded ? screenshotPreviewStyles.containerExpanded : {},
884
+ padding: "8px"
571
885
  },
572
886
  children: [
573
- /* @__PURE__ */ jsxs("div", { style: styles.header, children: [
574
- /* @__PURE__ */ jsx("span", { style: styles.headerTitle, children: "Screenshot Preview" }),
575
- /* @__PURE__ */ jsxs("div", { style: styles.headerActions, children: [
576
- /* @__PURE__ */ jsx("span", { style: styles.sizeLabel, children: formatBytes(totalSize) }),
887
+ /* @__PURE__ */ jsxs("div", { style: screenshotPreviewStyles.header, children: [
888
+ /* @__PURE__ */ jsx("span", { style: screenshotPreviewStyles.headerTitle, children: "Review Screenshots" }),
889
+ /* @__PURE__ */ jsxs("div", { style: screenshotPreviewStyles.headerActions, children: [
890
+ /* @__PURE__ */ jsx("span", { style: screenshotPreviewStyles.sizeLabel, children: formatBytes(totalSize) }),
577
891
  /* @__PURE__ */ jsx(
578
892
  "button",
579
893
  {
580
894
  type: "button",
581
895
  onClick: () => setIsExpanded(!isExpanded),
582
- style: styles.iconButton,
896
+ style: screenshotPreviewStyles.iconButton,
583
897
  title: isExpanded ? "Collapse" : "Expand",
584
898
  children: isExpanded ? /* @__PURE__ */ jsx(Shrink, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx(Expand, { className: "w-4 h-4" })
585
899
  }
586
900
  )
587
901
  ] })
588
902
  ] }),
589
- /* @__PURE__ */ jsx("div", { style: styles.tabContainer, children: tabs.map((tab) => /* @__PURE__ */ jsxs(
903
+ /* @__PURE__ */ jsx("div", { style: screenshotPreviewStyles.tabContainer, children: tabs.map((tab) => /* @__PURE__ */ jsxs(
590
904
  "button",
591
905
  {
592
906
  type: "button",
593
907
  onClick: () => setActiveTab(tab.key),
594
908
  style: {
595
- ...styles.tab,
596
- ...activeTab === tab.key ? styles.tabActive : {}
909
+ ...screenshotPreviewStyles.tab,
910
+ ...activeTab === tab.key ? screenshotPreviewStyles.tabActive : {},
911
+ ...tab.error && !tab.data ? screenshotPreviewStyles.tabError : {}
597
912
  },
598
913
  children: [
914
+ tab.error && !tab.data && /* @__PURE__ */ jsx(
915
+ CircleAlert,
916
+ {
917
+ className: "w-3 h-3",
918
+ style: { color: "#ef4444" }
919
+ }
920
+ ),
599
921
  tab.label,
600
- tab.data && /* @__PURE__ */ jsx("span", { style: styles.tabSize, children: formatBytes(tab.data.sizeBytes) })
922
+ tab.data && /* @__PURE__ */ jsx("span", { style: screenshotPreviewStyles.tabSize, children: formatBytes(tab.data.sizeBytes) })
601
923
  ]
602
924
  },
603
925
  tab.key
@@ -606,17 +928,21 @@ function ScreenshotPreview({
606
928
  "div",
607
929
  {
608
930
  style: {
609
- ...styles.previewContainer,
610
- ...isExpanded ? styles.previewContainerExpanded : {}
931
+ ...screenshotPreviewStyles.previewContainer,
932
+ ...isExpanded ? screenshotPreviewStyles.previewContainerExpanded : {}
611
933
  },
612
934
  children: activeScreenshot ? /* @__PURE__ */ jsx(
613
935
  "img",
614
936
  {
615
937
  src: activeScreenshot.dataUrl,
616
938
  alt: `${activeTab} screenshot`,
617
- style: styles.previewImage
939
+ style: screenshotPreviewStyles.previewImage
618
940
  }
619
- ) : /* @__PURE__ */ jsxs("div", { style: styles.noPreview, children: [
941
+ ) : activeError ? /* @__PURE__ */ jsxs("div", { style: screenshotPreviewStyles.errorPreview, children: [
942
+ /* @__PURE__ */ jsx(CircleAlert, { className: "w-8 h-8", style: { color: "#ef4444" } }),
943
+ /* @__PURE__ */ jsx("span", { style: screenshotPreviewStyles.errorTitle, children: "Capture Failed" }),
944
+ /* @__PURE__ */ jsx("span", { style: screenshotPreviewStyles.errorMessage, children: activeError.message })
945
+ ] }) : /* @__PURE__ */ jsxs("div", { style: screenshotPreviewStyles.noPreview, children: [
620
946
  /* @__PURE__ */ jsx(Image, { className: "w-6 h-6", style: { color: "#9ca3af" } }),
621
947
  /* @__PURE__ */ jsxs("span", { children: [
622
948
  "No ",
@@ -626,27 +952,27 @@ function ScreenshotPreview({
626
952
  ] })
627
953
  }
628
954
  ),
629
- activeScreenshot && /* @__PURE__ */ jsxs("div", { style: styles.dimensionsInfo, children: [
955
+ activeScreenshot && /* @__PURE__ */ jsxs("div", { style: screenshotPreviewStyles.dimensionsInfo, children: [
630
956
  activeScreenshot.width,
631
957
  " \xD7 ",
632
958
  activeScreenshot.height,
633
959
  "px"
634
960
  ] }),
635
- /* @__PURE__ */ jsxs("div", { style: styles.actions, children: [
961
+ /* @__PURE__ */ jsxs("div", { style: screenshotPreviewStyles.actions, children: [
636
962
  /* @__PURE__ */ jsxs(
637
963
  "button",
638
964
  {
639
965
  type: "button",
640
966
  onClick: onRetake,
641
967
  disabled: isSubmitting,
642
- style: styles.retakeButtonSmall,
968
+ style: screenshotPreviewStyles.retakeButtonSmall,
643
969
  children: [
644
970
  /* @__PURE__ */ jsx(RefreshCw, { className: "w-3 h-3" }),
645
971
  "Retake"
646
972
  ]
647
973
  }
648
974
  ),
649
- /* @__PURE__ */ jsxs("div", { style: styles.actionsRight, children: [
975
+ /* @__PURE__ */ jsxs("div", { style: screenshotPreviewStyles.actionsRight, children: [
650
976
  /* @__PURE__ */ jsxs(
651
977
  "button",
652
978
  {
@@ -687,183 +1013,6 @@ function ScreenshotPreview({
687
1013
  }
688
1014
  );
689
1015
  }
690
- var styles = {
691
- container: {
692
- width: "100%",
693
- display: "flex",
694
- flexDirection: "column",
695
- gap: "8px"
696
- },
697
- containerExpanded: {
698
- position: "fixed",
699
- top: "50%",
700
- left: "50%",
701
- transform: "translate(-50%, -50%)",
702
- width: "90vw",
703
- maxWidth: "800px",
704
- maxHeight: "90vh",
705
- backgroundColor: "#fff",
706
- borderRadius: "12px",
707
- boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
708
- padding: "16px",
709
- zIndex: 1e4
710
- },
711
- loadingContainer: {
712
- display: "flex",
713
- flexDirection: "column",
714
- alignItems: "center",
715
- justifyContent: "center",
716
- gap: "12px",
717
- padding: "24px"
718
- },
719
- loadingText: {
720
- fontSize: "13px",
721
- color: "#6b7280"
722
- },
723
- emptyContainer: {
724
- display: "flex",
725
- flexDirection: "column",
726
- alignItems: "center",
727
- justifyContent: "center",
728
- gap: "8px",
729
- padding: "24px"
730
- },
731
- emptyText: {
732
- fontSize: "13px",
733
- color: "#9ca3af"
734
- },
735
- header: {
736
- display: "flex",
737
- justifyContent: "space-between",
738
- alignItems: "center",
739
- padding: "0 4px"
740
- },
741
- headerTitle: {
742
- fontSize: "12px",
743
- fontWeight: "600",
744
- color: "#374151",
745
- textTransform: "uppercase",
746
- letterSpacing: "0.05em"
747
- },
748
- headerActions: {
749
- display: "flex",
750
- alignItems: "center",
751
- gap: "8px"
752
- },
753
- sizeLabel: {
754
- fontSize: "11px",
755
- color: "#9ca3af"
756
- },
757
- iconButton: {
758
- display: "flex",
759
- alignItems: "center",
760
- justifyContent: "center",
761
- width: "24px",
762
- height: "24px",
763
- border: "none",
764
- background: "transparent",
765
- borderRadius: "4px",
766
- cursor: "pointer",
767
- color: "#6b7280"
768
- },
769
- tabContainer: {
770
- display: "flex",
771
- gap: "4px",
772
- borderBottom: "1px solid #e5e7eb",
773
- paddingBottom: "8px"
774
- },
775
- tab: {
776
- display: "flex",
777
- alignItems: "center",
778
- gap: "4px",
779
- padding: "6px 10px",
780
- fontSize: "12px",
781
- color: "#6b7280",
782
- background: "transparent",
783
- border: "none",
784
- borderRadius: "4px",
785
- cursor: "pointer",
786
- transition: "all 0.15s ease"
787
- },
788
- tabActive: {
789
- backgroundColor: "#eff6ff",
790
- color: "#3b82f6",
791
- fontWeight: "500"
792
- },
793
- tabSize: {
794
- fontSize: "10px",
795
- color: "#9ca3af"
796
- },
797
- previewContainer: {
798
- position: "relative",
799
- width: "100%",
800
- height: "150px",
801
- backgroundColor: "#f9fafb",
802
- borderRadius: "8px",
803
- overflow: "hidden",
804
- display: "flex",
805
- alignItems: "center",
806
- justifyContent: "center"
807
- },
808
- previewContainerExpanded: {
809
- height: "60vh",
810
- maxHeight: "500px"
811
- },
812
- previewImage: {
813
- maxWidth: "100%",
814
- maxHeight: "100%",
815
- objectFit: "contain"
816
- },
817
- noPreview: {
818
- display: "flex",
819
- flexDirection: "column",
820
- alignItems: "center",
821
- gap: "8px",
822
- fontSize: "12px",
823
- color: "#9ca3af"
824
- },
825
- dimensionsInfo: {
826
- fontSize: "11px",
827
- color: "#9ca3af",
828
- textAlign: "center"
829
- },
830
- actions: {
831
- display: "flex",
832
- justifyContent: "space-between",
833
- alignItems: "center",
834
- paddingTop: "8px",
835
- borderTop: "1px solid #e5e7eb"
836
- },
837
- actionsRight: {
838
- display: "flex",
839
- gap: "8px"
840
- },
841
- retakeButton: {
842
- display: "flex",
843
- alignItems: "center",
844
- gap: "6px",
845
- padding: "8px 16px",
846
- fontSize: "13px",
847
- color: "#fff",
848
- backgroundColor: "#3b82f6",
849
- border: "none",
850
- borderRadius: "6px",
851
- cursor: "pointer",
852
- fontWeight: "500"
853
- },
854
- retakeButtonSmall: {
855
- display: "flex",
856
- alignItems: "center",
857
- gap: "4px",
858
- padding: "4px 8px",
859
- fontSize: "11px",
860
- color: "#6b7280",
861
- backgroundColor: "transparent",
862
- border: "1px solid #e5e7eb",
863
- borderRadius: "4px",
864
- cursor: "pointer"
865
- }
866
- };
867
1016
 
868
1017
  // src/ContextMenu.tsx
869
1018
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
@@ -1167,6 +1316,14 @@ function ContextMenu({
1167
1316
  captureScreenshots();
1168
1317
  };
1169
1318
  const containerWidth = currentView === "screenshot-preview" ? 360 : void 0;
1319
+ if (process.env.NODE_ENV === "development" && visible) {
1320
+ console.log("[ContextMenu] Style Debug", {
1321
+ styleExists: !!style,
1322
+ styleKeys: style ? Object.keys(style) : [],
1323
+ styleValues: style,
1324
+ className
1325
+ });
1326
+ }
1170
1327
  return /* @__PURE__ */ jsxs2(
1171
1328
  "div",
1172
1329
  {
@@ -1182,7 +1339,7 @@ function ContextMenu({
1182
1339
  role: "menu",
1183
1340
  "aria-label": "Feedback options",
1184
1341
  children: [
1185
- /* @__PURE__ */ jsx2("div", { style: menuStyles.header, children: currentView === "screenshot-preview" ? "Review Screenshots" : "Send Feedback" }),
1342
+ currentView !== "screenshot-preview" && /* @__PURE__ */ jsx2("div", { style: menuStyles.header, children: "Send Feedback" }),
1186
1343
  currentView === "menu" && /* @__PURE__ */ jsxs2("div", { style: menuStyles.itemList, children: [
1187
1344
  submenuStack.length > 0 && /* @__PURE__ */ jsx2(BackButton, { onClick: handleBack }),
1188
1345
  currentItems.map((item) => /* @__PURE__ */ jsx2(
@@ -1229,19 +1386,179 @@ var screenshotIndicatorStyle = {
1229
1386
  gap: "6px",
1230
1387
  padding: "8px 12px",
1231
1388
  fontSize: "11px",
1232
- color: "#9ca3af",
1233
- borderTop: "1px solid #f3f4f6",
1389
+ color: "var(--anyclick-menu-text-muted, #9ca3af)",
1390
+ borderTop: "1px solid var(--anyclick-menu-border, #f3f4f6)",
1234
1391
  marginTop: "4px"
1235
1392
  };
1236
1393
 
1237
- // src/FeedbackProvider.tsx
1394
+ // src/store.ts
1395
+ import { create } from "zustand";
1396
+ var providerIdCounter = 0;
1397
+ function generateProviderId() {
1398
+ return `anyclick-provider-${++providerIdCounter}`;
1399
+ }
1400
+ var useProviderStore = create((set, get) => ({
1401
+ providers: /* @__PURE__ */ new Map(),
1402
+ registerProvider: (provider) => {
1403
+ set((state) => {
1404
+ const newProviders = new Map(state.providers);
1405
+ newProviders.set(provider.id, provider);
1406
+ return { providers: newProviders };
1407
+ });
1408
+ },
1409
+ unregisterProvider: (id) => {
1410
+ set((state) => {
1411
+ const newProviders = new Map(state.providers);
1412
+ newProviders.delete(id);
1413
+ return { providers: newProviders };
1414
+ });
1415
+ },
1416
+ updateProvider: (id, updates) => {
1417
+ set((state) => {
1418
+ const newProviders = new Map(state.providers);
1419
+ const existing = newProviders.get(id);
1420
+ if (existing) {
1421
+ newProviders.set(id, { ...existing, ...updates });
1422
+ }
1423
+ return { providers: newProviders };
1424
+ });
1425
+ },
1426
+ findProvidersForElement: (element) => {
1427
+ const { providers } = get();
1428
+ const matching = [];
1429
+ for (const provider of providers.values()) {
1430
+ if (provider.disabled) continue;
1431
+ const container = provider.containerRef.current;
1432
+ if (provider.scoped && container) {
1433
+ if (container.contains(element)) {
1434
+ matching.push(provider);
1435
+ }
1436
+ } else if (!provider.scoped) {
1437
+ matching.push(provider);
1438
+ }
1439
+ }
1440
+ return matching.sort((a, b) => b.depth - a.depth);
1441
+ },
1442
+ findParentProvider: (container, excludeId) => {
1443
+ const { providers } = get();
1444
+ if (!container) return null;
1445
+ let nearestParent = null;
1446
+ let nearestDepth = -1;
1447
+ for (const provider of providers.values()) {
1448
+ if (provider.id === excludeId) continue;
1449
+ const providerContainer = provider.containerRef.current;
1450
+ if (!providerContainer) continue;
1451
+ if (providerContainer.contains(container)) {
1452
+ if (provider.depth > nearestDepth) {
1453
+ nearestParent = provider;
1454
+ nearestDepth = provider.depth;
1455
+ }
1456
+ }
1457
+ }
1458
+ return nearestParent;
1459
+ },
1460
+ getMergedTheme: (providerId) => {
1461
+ const { providers } = get();
1462
+ const provider = providers.get(providerId);
1463
+ if (!provider) {
1464
+ if (process.env.NODE_ENV === "development") {
1465
+ console.log(`[Store:getMergedTheme] Provider not found: ${providerId}`);
1466
+ }
1467
+ return {};
1468
+ }
1469
+ const ancestors = [];
1470
+ let current = provider;
1471
+ while (current) {
1472
+ ancestors.unshift(current);
1473
+ current = current.parentId ? providers.get(current.parentId) : void 0;
1474
+ }
1475
+ if (process.env.NODE_ENV === "development") {
1476
+ console.log(`[Store:getMergedTheme] Provider: ${providerId}`, {
1477
+ ancestorCount: ancestors.length,
1478
+ ancestorIds: ancestors.map((a) => a.id),
1479
+ providerHasTheme: !!provider.theme,
1480
+ providerThemeMenuStyle: provider.theme?.menuStyle ? Object.keys(provider.theme.menuStyle) : []
1481
+ });
1482
+ }
1483
+ const mergedTheme = {};
1484
+ for (const ancestor of ancestors) {
1485
+ if (ancestor.theme) {
1486
+ Object.assign(mergedTheme, ancestor.theme);
1487
+ if (ancestor.theme.highlightConfig) {
1488
+ mergedTheme.highlightConfig = {
1489
+ ...mergedTheme.highlightConfig,
1490
+ ...ancestor.theme.highlightConfig,
1491
+ colors: {
1492
+ ...mergedTheme.highlightConfig?.colors,
1493
+ ...ancestor.theme.highlightConfig.colors
1494
+ }
1495
+ };
1496
+ }
1497
+ if (ancestor.theme.screenshotConfig) {
1498
+ mergedTheme.screenshotConfig = {
1499
+ ...mergedTheme.screenshotConfig,
1500
+ ...ancestor.theme.screenshotConfig
1501
+ };
1502
+ }
1503
+ }
1504
+ }
1505
+ if (process.env.NODE_ENV === "development") {
1506
+ console.log(`[Store:getMergedTheme] Result for ${providerId}`, {
1507
+ hasMenuStyle: !!mergedTheme.menuStyle,
1508
+ menuStyleKeys: mergedTheme.menuStyle ? Object.keys(mergedTheme.menuStyle) : []
1509
+ });
1510
+ }
1511
+ return mergedTheme;
1512
+ },
1513
+ isDisabledByAncestor: (providerId) => {
1514
+ const { providers } = get();
1515
+ const provider = providers.get(providerId);
1516
+ if (!provider) return false;
1517
+ let current = provider;
1518
+ while (current) {
1519
+ if (current.disabled || current.theme?.disabled) {
1520
+ return true;
1521
+ }
1522
+ current = current.parentId ? providers.get(current.parentId) : void 0;
1523
+ }
1524
+ return false;
1525
+ },
1526
+ isElementInDisabledScope: (element) => {
1527
+ const { providers } = get();
1528
+ for (const provider of providers.values()) {
1529
+ if (!provider.scoped) continue;
1530
+ if (!provider.disabled && !provider.theme?.disabled) continue;
1531
+ const container = provider.containerRef.current;
1532
+ if (!container) continue;
1533
+ if (container.contains(element)) {
1534
+ return true;
1535
+ }
1536
+ }
1537
+ return false;
1538
+ }
1539
+ }));
1540
+ function dispatchContextMenuEvent(event, element) {
1541
+ const store = useProviderStore.getState();
1542
+ const providers = store.findProvidersForElement(element);
1543
+ for (const provider of providers) {
1544
+ if (store.isDisabledByAncestor(provider.id)) {
1545
+ continue;
1546
+ }
1547
+ if (provider.onContextMenu) {
1548
+ provider.onContextMenu(event, element);
1549
+ break;
1550
+ }
1551
+ }
1552
+ }
1553
+
1554
+ // src/AnyclickProvider.tsx
1238
1555
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1239
1556
  var defaultMenuItems = [
1240
1557
  { type: "issue", label: "Report an issue", showComment: true },
1241
1558
  { type: "feature", label: "Request a feature", showComment: true },
1242
1559
  { type: "like", label: "I like this!", showComment: false }
1243
1560
  ];
1244
- function FeedbackProvider({
1561
+ function AnyclickProvider({
1245
1562
  adapter,
1246
1563
  children,
1247
1564
  targetFilter,
@@ -1258,7 +1575,9 @@ function FeedbackProvider({
1258
1575
  menuClassName,
1259
1576
  disabled = false,
1260
1577
  highlightConfig,
1261
- screenshotConfig
1578
+ screenshotConfig,
1579
+ scoped = false,
1580
+ theme
1262
1581
  }) {
1263
1582
  const [isSubmitting, setIsSubmitting] = useState3(false);
1264
1583
  const [menuVisible, setMenuVisible] = useState3(false);
@@ -1267,8 +1586,189 @@ function FeedbackProvider({
1267
1586
  const [containerElement, setContainerElement] = useState3(
1268
1587
  null
1269
1588
  );
1589
+ const providerIdRef = useRef2(generateProviderId());
1590
+ const providerId = providerIdRef.current;
1591
+ const containerRef = useRef2(null);
1592
+ const [containerReady, setContainerReady] = useState3(!scoped);
1270
1593
  const clientRef = useRef2(null);
1594
+ const setContainerRef = useCallback2(
1595
+ (node) => {
1596
+ if (process.env.NODE_ENV === "development") {
1597
+ console.log(`[AnyclickProvider:${providerId}] Container ref callback`, {
1598
+ scoped,
1599
+ nodeReceived: !!node,
1600
+ hadPreviousNode: !!containerRef.current,
1601
+ clientExists: !!clientRef.current
1602
+ });
1603
+ }
1604
+ containerRef.current = node;
1605
+ if (scoped && node) {
1606
+ setContainerReady(true);
1607
+ if (clientRef.current) {
1608
+ clientRef.current.setContainer(node);
1609
+ }
1610
+ }
1611
+ },
1612
+ [scoped, providerId]
1613
+ );
1614
+ let parentContext = null;
1615
+ try {
1616
+ parentContext = useAnyclick();
1617
+ } catch {
1618
+ parentContext = null;
1619
+ }
1620
+ const {
1621
+ registerProvider,
1622
+ unregisterProvider,
1623
+ updateProvider,
1624
+ getMergedTheme,
1625
+ isDisabledByAncestor,
1626
+ findParentProvider,
1627
+ isElementInDisabledScope
1628
+ } = useProviderStore();
1629
+ const parentId = parentContext?.providerId ?? null;
1630
+ const depth = parentContext ? parentContext.scoped ? 1 : 0 : 0;
1631
+ const actualDepth = useMemo(() => {
1632
+ if (!parentContext) return 0;
1633
+ let d = 0;
1634
+ let currentId = parentId;
1635
+ const providers = useProviderStore.getState().providers;
1636
+ while (currentId) {
1637
+ d++;
1638
+ const parent = providers.get(currentId);
1639
+ currentId = parent?.parentId ?? null;
1640
+ }
1641
+ return d;
1642
+ }, [parentId]);
1643
+ const isDisabledByTheme = theme === null || theme?.disabled === true;
1644
+ const effectiveDisabled = disabled || isDisabledByTheme;
1645
+ const localTheme = useMemo(() => {
1646
+ if (theme === null) {
1647
+ return { disabled: true };
1648
+ }
1649
+ const explicitThemeProps = {};
1650
+ if (menuStyle) explicitThemeProps.menuStyle = menuStyle;
1651
+ if (menuClassName) explicitThemeProps.menuClassName = menuClassName;
1652
+ if (highlightConfig) explicitThemeProps.highlightConfig = highlightConfig;
1653
+ if (screenshotConfig)
1654
+ explicitThemeProps.screenshotConfig = screenshotConfig;
1655
+ return {
1656
+ ...explicitThemeProps,
1657
+ ...theme
1658
+ };
1659
+ }, [theme, menuStyle, menuClassName, highlightConfig, screenshotConfig]);
1660
+ const handleContextMenu = useCallback2(
1661
+ (event, element) => {
1662
+ if (!scoped && isElementInDisabledScope(element)) {
1663
+ if (process.env.NODE_ENV === "development") {
1664
+ console.log(
1665
+ `[AnyclickProvider:${providerId}] Allowing native menu - element is in disabled scope`,
1666
+ {
1667
+ targetTag: element.tagName
1668
+ }
1669
+ );
1670
+ }
1671
+ return false;
1672
+ }
1673
+ const mergedTheme2 = getMergedTheme(providerId);
1674
+ if (process.env.NODE_ENV === "development") {
1675
+ console.log(
1676
+ `[AnyclickProvider:${providerId}] handleContextMenu called`,
1677
+ {
1678
+ scoped,
1679
+ targetTag: element.tagName,
1680
+ mergedThemeColors: mergedTheme2.highlightConfig?.colors,
1681
+ position: { x: event.clientX, y: event.clientY }
1682
+ }
1683
+ );
1684
+ }
1685
+ setTargetElement(element);
1686
+ const container = findContainerParent(
1687
+ element,
1688
+ mergedTheme2.highlightConfig ?? highlightConfig
1689
+ );
1690
+ setContainerElement(container);
1691
+ setMenuPosition({ x: event.clientX, y: event.clientY });
1692
+ setMenuVisible(true);
1693
+ return true;
1694
+ },
1695
+ [
1696
+ providerId,
1697
+ getMergedTheme,
1698
+ highlightConfig,
1699
+ scoped,
1700
+ isElementInDisabledScope
1701
+ ]
1702
+ );
1703
+ useLayoutEffect(() => {
1704
+ const providerInstance = {
1705
+ id: providerId,
1706
+ containerRef,
1707
+ scoped,
1708
+ theme: localTheme,
1709
+ disabled: effectiveDisabled,
1710
+ parentId,
1711
+ depth: actualDepth,
1712
+ onContextMenu: handleContextMenu
1713
+ };
1714
+ registerProvider(providerInstance);
1715
+ return () => {
1716
+ unregisterProvider(providerId);
1717
+ };
1718
+ }, [
1719
+ providerId,
1720
+ scoped,
1721
+ localTheme,
1722
+ effectiveDisabled,
1723
+ parentId,
1724
+ actualDepth,
1725
+ handleContextMenu,
1726
+ registerProvider,
1727
+ unregisterProvider
1728
+ ]);
1729
+ useEffect2(() => {
1730
+ updateProvider(providerId, {
1731
+ theme: localTheme,
1732
+ disabled: effectiveDisabled,
1733
+ onContextMenu: handleContextMenu
1734
+ });
1735
+ }, [
1736
+ providerId,
1737
+ localTheme,
1738
+ effectiveDisabled,
1739
+ handleContextMenu,
1740
+ updateProvider
1741
+ ]);
1271
1742
  useEffect2(() => {
1743
+ if (isDisabledByAncestor(providerId)) {
1744
+ if (process.env.NODE_ENV === "development") {
1745
+ console.log(
1746
+ `[AnyclickProvider:${providerId}] Skipping - disabled by ancestor`
1747
+ );
1748
+ }
1749
+ return;
1750
+ }
1751
+ if (scoped && !containerReady) {
1752
+ if (process.env.NODE_ENV === "development") {
1753
+ console.log(
1754
+ `[AnyclickProvider:${providerId}] Waiting for container to be ready`,
1755
+ {
1756
+ scoped,
1757
+ containerReady
1758
+ }
1759
+ );
1760
+ }
1761
+ return;
1762
+ }
1763
+ if (process.env.NODE_ENV === "development") {
1764
+ console.log(`[AnyclickProvider:${providerId}] Creating client`, {
1765
+ scoped,
1766
+ containerReady,
1767
+ hasContainer: !!containerRef.current,
1768
+ effectiveDisabled,
1769
+ localThemeColors: localTheme.highlightConfig?.colors
1770
+ });
1771
+ }
1272
1772
  const client = createFeedbackClient({
1273
1773
  adapter,
1274
1774
  targetFilter,
@@ -1276,19 +1776,15 @@ function FeedbackProvider({
1276
1776
  maxOuterHTMLLength,
1277
1777
  maxAncestors,
1278
1778
  cooldownMs,
1279
- stripAttributes
1779
+ stripAttributes,
1780
+ // For scoped providers, pass the container
1781
+ container: scoped ? containerRef.current : null
1280
1782
  });
1281
1783
  client.onSubmitSuccess = onSubmitSuccess;
1282
1784
  client.onSubmitError = onSubmitError;
1283
- client.onContextMenu = (event, element) => {
1284
- setTargetElement(element);
1285
- const container = findContainerParent(element, highlightConfig);
1286
- setContainerElement(container);
1287
- setMenuPosition({ x: event.clientX, y: event.clientY });
1288
- setMenuVisible(true);
1289
- };
1785
+ client.onContextMenu = handleContextMenu;
1290
1786
  clientRef.current = client;
1291
- if (!disabled) {
1787
+ if (!effectiveDisabled) {
1292
1788
  client.attach();
1293
1789
  }
1294
1790
  return () => {
@@ -1304,8 +1800,12 @@ function FeedbackProvider({
1304
1800
  stripAttributes,
1305
1801
  onSubmitSuccess,
1306
1802
  onSubmitError,
1307
- disabled,
1308
- highlightConfig
1803
+ effectiveDisabled,
1804
+ scoped,
1805
+ containerReady,
1806
+ providerId,
1807
+ isDisabledByAncestor,
1808
+ handleContextMenu
1309
1809
  ]);
1310
1810
  const submitFeedback = useCallback2(
1311
1811
  async (element, type, comment, screenshots) => {
@@ -1330,12 +1830,16 @@ function FeedbackProvider({
1330
1830
  const openMenu = useCallback2(
1331
1831
  (element, position) => {
1332
1832
  setTargetElement(element);
1333
- const container = findContainerParent(element, highlightConfig);
1833
+ const mergedTheme2 = getMergedTheme(providerId);
1834
+ const container = findContainerParent(
1835
+ element,
1836
+ mergedTheme2.highlightConfig ?? highlightConfig
1837
+ );
1334
1838
  setContainerElement(container);
1335
1839
  setMenuPosition(position);
1336
1840
  setMenuVisible(true);
1337
1841
  },
1338
- [highlightConfig]
1842
+ [providerId, getMergedTheme, highlightConfig]
1339
1843
  );
1340
1844
  const closeMenu = useCallback2(() => {
1341
1845
  setMenuVisible(false);
@@ -1350,22 +1854,73 @@ function FeedbackProvider({
1350
1854
  },
1351
1855
  [targetElement, submitFeedback]
1352
1856
  );
1857
+ const inheritedTheme = getMergedTheme(providerId);
1858
+ const mergedTheme = useMemo(
1859
+ () => ({
1860
+ ...inheritedTheme,
1861
+ ...localTheme,
1862
+ // Deep merge for nested configs
1863
+ highlightConfig: {
1864
+ ...inheritedTheme.highlightConfig,
1865
+ ...localTheme.highlightConfig,
1866
+ colors: {
1867
+ ...inheritedTheme.highlightConfig?.colors,
1868
+ ...localTheme.highlightConfig?.colors
1869
+ }
1870
+ },
1871
+ screenshotConfig: {
1872
+ ...inheritedTheme.screenshotConfig,
1873
+ ...localTheme.screenshotConfig
1874
+ }
1875
+ }),
1876
+ [inheritedTheme, localTheme]
1877
+ );
1878
+ const effectiveMenuStyle = mergedTheme.menuStyle ?? menuStyle;
1879
+ const effectiveMenuClassName = mergedTheme.menuClassName ?? menuClassName;
1880
+ if (process.env.NODE_ENV === "development") {
1881
+ console.log(`[AnyclickProvider:${providerId}] Theme Debug`, {
1882
+ scoped,
1883
+ localThemeHasMenuStyle: !!localTheme.menuStyle,
1884
+ localThemeMenuStyleKeys: localTheme.menuStyle ? Object.keys(localTheme.menuStyle) : [],
1885
+ mergedThemeHasMenuStyle: !!mergedTheme.menuStyle,
1886
+ mergedThemeMenuStyleKeys: mergedTheme.menuStyle ? Object.keys(mergedTheme.menuStyle) : [],
1887
+ effectiveMenuStyleExists: !!effectiveMenuStyle,
1888
+ effectiveMenuStyleKeys: effectiveMenuStyle ? Object.keys(effectiveMenuStyle) : [],
1889
+ menuStyleProp: !!menuStyle
1890
+ });
1891
+ }
1892
+ const effectiveHighlightConfig = mergedTheme.highlightConfig ?? highlightConfig;
1893
+ const effectiveScreenshotConfig = mergedTheme.screenshotConfig ?? screenshotConfig;
1353
1894
  const contextValue = useMemo(
1354
1895
  () => ({
1355
- isEnabled: !disabled,
1896
+ isEnabled: !effectiveDisabled && !isDisabledByAncestor(providerId),
1356
1897
  isSubmitting,
1357
1898
  submitFeedback,
1358
1899
  openMenu,
1359
- closeMenu
1900
+ closeMenu,
1901
+ theme: mergedTheme,
1902
+ scoped,
1903
+ providerId
1360
1904
  }),
1361
- [disabled, isSubmitting, submitFeedback, openMenu, closeMenu]
1905
+ [
1906
+ effectiveDisabled,
1907
+ providerId,
1908
+ isDisabledByAncestor,
1909
+ isSubmitting,
1910
+ submitFeedback,
1911
+ openMenu,
1912
+ closeMenu,
1913
+ mergedTheme,
1914
+ scoped
1915
+ ]
1362
1916
  );
1363
- return /* @__PURE__ */ jsxs3(FeedbackContext.Provider, { value: contextValue, children: [
1364
- children,
1917
+ const content = scoped ? /* @__PURE__ */ jsx3("div", { ref: setContainerRef, style: { display: "contents" }, children }) : children;
1918
+ return /* @__PURE__ */ jsxs3(AnyclickContext.Provider, { value: contextValue, children: [
1919
+ content,
1365
1920
  /* @__PURE__ */ jsx3(
1366
1921
  ContextMenu,
1367
1922
  {
1368
- visible: menuVisible && !disabled,
1923
+ visible: menuVisible && !effectiveDisabled,
1369
1924
  position: menuPosition,
1370
1925
  targetElement,
1371
1926
  containerElement,
@@ -1373,14 +1928,15 @@ function FeedbackProvider({
1373
1928
  onSelect: handleMenuSelect,
1374
1929
  onClose: closeMenu,
1375
1930
  isSubmitting,
1376
- style: menuStyle,
1377
- className: menuClassName,
1378
- highlightConfig,
1379
- screenshotConfig
1931
+ style: effectiveMenuStyle,
1932
+ className: effectiveMenuClassName,
1933
+ highlightConfig: effectiveHighlightConfig,
1934
+ screenshotConfig: effectiveScreenshotConfig
1380
1935
  }
1381
1936
  )
1382
1937
  ] });
1383
1938
  }
1939
+ var FeedbackProvider = AnyclickProvider;
1384
1940
 
1385
1941
  // src/types.ts
1386
1942
  function filterMenuItemsByRole(items, userContext) {
@@ -1409,6 +1965,8 @@ import {
1409
1965
  DEFAULT_SENSITIVE_SELECTORS
1410
1966
  } from "@ewjdev/anyclick-core";
1411
1967
  export {
1968
+ AnyclickContext,
1969
+ AnyclickProvider,
1412
1970
  ContextMenu,
1413
1971
  DEFAULT_SCREENSHOT_CONFIG2 as DEFAULT_SCREENSHOT_CONFIG,
1414
1972
  DEFAULT_SENSITIVE_SELECTORS,
@@ -1422,15 +1980,20 @@ export {
1422
1980
  darkMenuStyles,
1423
1981
  defaultContainerSelectors,
1424
1982
  defaultHighlightColors,
1983
+ dispatchContextMenuEvent,
1425
1984
  estimateTotalSize2 as estimateTotalSize,
1426
1985
  filterMenuItemsByRole,
1427
1986
  findContainerParent,
1428
1987
  formatBytes2 as formatBytes,
1988
+ generateProviderId,
1429
1989
  highlightContainer,
1430
1990
  highlightTarget,
1431
1991
  isScreenshotSupported2 as isScreenshotSupported,
1992
+ menuCSSVariables,
1432
1993
  menuStyles,
1433
- useFeedback
1994
+ useAnyclick,
1995
+ useFeedback,
1996
+ useProviderStore
1434
1997
  };
1435
1998
  /*! Bundled license information:
1436
1999
 
@@ -1442,6 +2005,7 @@ lucide-react/dist/esm/icons/camera.js:
1442
2005
  lucide-react/dist/esm/icons/check.js:
1443
2006
  lucide-react/dist/esm/icons/chevron-left.js:
1444
2007
  lucide-react/dist/esm/icons/chevron-right.js:
2008
+ lucide-react/dist/esm/icons/circle-alert.js:
1445
2009
  lucide-react/dist/esm/icons/expand.js:
1446
2010
  lucide-react/dist/esm/icons/flag.js:
1447
2011
  lucide-react/dist/esm/icons/image.js: