@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.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
- useFeedback: () => useFeedback
50
+ useAnyclick: () => useAnyclick,
51
+ useFeedback: () => useFeedback,
52
+ useProviderStore: () => useProviderStore
46
53
  });
47
54
  module.exports = __toCommonJS(index_exports);
48
55
 
49
- // src/FeedbackProvider.tsx
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 FeedbackContext = (0, import_react.createContext)(null);
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)(FeedbackContext);
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
- background: "none",
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 { targetColor, containerColor, targetShadowOpacity, containerShadowOpacity } = colors;
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 solid ${targetColor} !important;
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/expand.js
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", __iconNode5);
762
+ var Expand = createLucideIcon("expand", __iconNode6);
476
763
 
477
764
  // ../../node_modules/lucide-react/dist/esm/icons/flag.js
478
- var __iconNode6 = [
765
+ var __iconNode7 = [
479
766
  [
480
767
  "path",
481
768
  {
@@ -484,47 +771,47 @@ var __iconNode6 = [
484
771
  }
485
772
  ]
486
773
  ];
487
- var Flag = createLucideIcon("flag", __iconNode6);
774
+ var Flag = createLucideIcon("flag", __iconNode7);
488
775
 
489
776
  // ../../node_modules/lucide-react/dist/esm/icons/image.js
490
- var __iconNode7 = [
777
+ var __iconNode8 = [
491
778
  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
492
779
  ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
493
780
  ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
494
781
  ];
495
- var Image = createLucideIcon("image", __iconNode7);
782
+ var Image = createLucideIcon("image", __iconNode8);
496
783
 
497
784
  // ../../node_modules/lucide-react/dist/esm/icons/loader-circle.js
498
- var __iconNode8 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
499
- var LoaderCircle = createLucideIcon("loader-circle", __iconNode8);
785
+ var __iconNode9 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
786
+ var LoaderCircle = createLucideIcon("loader-circle", __iconNode9);
500
787
 
501
788
  // ../../node_modules/lucide-react/dist/esm/icons/plus.js
502
- var __iconNode9 = [
789
+ var __iconNode10 = [
503
790
  ["path", { d: "M5 12h14", key: "1ays0h" }],
504
791
  ["path", { d: "M12 5v14", key: "s699le" }]
505
792
  ];
506
- var Plus = createLucideIcon("plus", __iconNode9);
793
+ var Plus = createLucideIcon("plus", __iconNode10);
507
794
 
508
795
  // ../../node_modules/lucide-react/dist/esm/icons/refresh-cw.js
509
- var __iconNode10 = [
796
+ var __iconNode11 = [
510
797
  ["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
798
  ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
512
799
  ["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
800
  ["path", { d: "M8 16H3v5", key: "1cv678" }]
514
801
  ];
515
- var RefreshCw = createLucideIcon("refresh-cw", __iconNode10);
802
+ var RefreshCw = createLucideIcon("refresh-cw", __iconNode11);
516
803
 
517
804
  // ../../node_modules/lucide-react/dist/esm/icons/shrink.js
518
- var __iconNode11 = [
805
+ var __iconNode12 = [
519
806
  ["path", { d: "m15 15 6 6m-6-6v4.8m0-4.8h4.8", key: "17vawe" }],
520
807
  ["path", { d: "M9 19.8V15m0 0H4.2M9 15l-6 6", key: "chjx8e" }],
521
808
  ["path", { d: "M15 4.2V9m0 0h4.8M15 9l6-6", key: "lav6yq" }],
522
809
  ["path", { d: "M9 4.2V9m0 0H4.2M9 9 3 3", key: "1pxi2q" }]
523
810
  ];
524
- var Shrink = createLucideIcon("shrink", __iconNode11);
811
+ var Shrink = createLucideIcon("shrink", __iconNode12);
525
812
 
526
813
  // ../../node_modules/lucide-react/dist/esm/icons/thumbs-up.js
527
- var __iconNode12 = [
814
+ var __iconNode13 = [
528
815
  ["path", { d: "M7 10v12", key: "1qc93n" }],
529
816
  [
530
817
  "path",
@@ -534,14 +821,14 @@ var __iconNode12 = [
534
821
  }
535
822
  ]
536
823
  ];
537
- var ThumbsUp = createLucideIcon("thumbs-up", __iconNode12);
824
+ var ThumbsUp = createLucideIcon("thumbs-up", __iconNode13);
538
825
 
539
826
  // ../../node_modules/lucide-react/dist/esm/icons/x.js
540
- var __iconNode13 = [
827
+ var __iconNode14 = [
541
828
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
542
829
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
543
830
  ];
544
- var X = createLucideIcon("x", __iconNode13);
831
+ var X = createLucideIcon("x", __iconNode14);
545
832
 
546
833
  // src/ScreenshotPreview.tsx
547
834
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -556,7 +843,7 @@ function ScreenshotPreview({
556
843
  const [activeTab, setActiveTab] = (0, import_react4.useState)("element");
557
844
  const [isExpanded, setIsExpanded] = (0, import_react4.useState)(false);
558
845
  if (isLoading) {
559
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.loadingContainer, children: [
846
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.loadingContainer, children: [
560
847
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
561
848
  LoaderCircle,
562
849
  {
@@ -564,76 +851,117 @@ function ScreenshotPreview({
564
851
  style: { color: "#3b82f6" }
565
852
  }
566
853
  ),
567
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.loadingText, children: "Capturing screenshots..." })
854
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.loadingText, children: "Capturing screenshots..." })
568
855
  ] }) });
569
856
  }
570
857
  if (!screenshots) {
571
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.emptyContainer, children: [
858
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: screenshotPreviewStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.emptyContainer, children: [
572
859
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Image, { className: "w-8 h-8", style: { color: "#9ca3af" } }),
573
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.emptyText, children: "No screenshots captured" }),
574
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
575
- "button",
576
- {
577
- type: "button",
578
- onClick: onRetake,
579
- style: styles.retakeButton,
580
- disabled: isSubmitting,
581
- children: [
582
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: "w-4 h-4" }),
583
- "Capture Screenshots"
584
- ]
585
- }
586
- )
587
- ] }) });
588
- }
589
- const allTabs = [
590
- { key: "element", label: "Element", data: screenshots.element },
591
- {
860
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.emptyText, children: "Screenshots unavailable" }),
861
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.emptySubtext, children: "Some elements can't be captured (e.g., gradient text)" }),
862
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.emptyActions, children: [
863
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
864
+ "button",
865
+ {
866
+ type: "button",
867
+ onClick: onRetake,
868
+ style: screenshotPreviewStyles.retakeButtonOutline,
869
+ disabled: isSubmitting,
870
+ children: [
871
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: "w-4 h-4" }),
872
+ "Try Again"
873
+ ]
874
+ }
875
+ ),
876
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
877
+ "button",
878
+ {
879
+ type: "button",
880
+ onClick: () => onConfirm({ capturedAt: (/* @__PURE__ */ new Date()).toISOString() }),
881
+ style: screenshotPreviewStyles.continueButton,
882
+ disabled: isSubmitting,
883
+ children: [
884
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "w-4 h-4" }),
885
+ "Continue Without"
886
+ ]
887
+ }
888
+ )
889
+ ] })
890
+ ] }) });
891
+ }
892
+ const getError = (key) => {
893
+ return screenshots.errors?.[key];
894
+ };
895
+ const allTabs = [
896
+ {
897
+ key: "element",
898
+ label: "Element",
899
+ data: screenshots.element,
900
+ error: getError("element")
901
+ },
902
+ {
592
903
  key: "container",
593
904
  label: "Container",
594
- data: screenshots.container
905
+ data: screenshots.container,
906
+ error: getError("container")
595
907
  },
596
- { key: "viewport", label: "Viewport", data: screenshots.viewport }
908
+ {
909
+ key: "viewport",
910
+ label: "Viewport",
911
+ data: screenshots.viewport,
912
+ error: getError("viewport")
913
+ }
597
914
  ];
598
- const tabs = allTabs.filter((tab) => tab.data);
915
+ const tabs = allTabs.filter((tab) => tab.data || tab.error);
599
916
  const activeScreenshot = activeTab === "element" ? screenshots.element : activeTab === "container" ? screenshots.container : screenshots.viewport;
917
+ const activeError = getError(activeTab);
600
918
  const totalSize = (0, import_anyclick_core.estimateTotalSize)(screenshots);
919
+ console.log({ styles: screenshotPreviewStyles });
601
920
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
602
921
  "div",
603
922
  {
604
923
  style: {
605
- ...styles.container,
606
- ...isExpanded ? styles.containerExpanded : {}
924
+ ...screenshotPreviewStyles.container,
925
+ ...isExpanded ? screenshotPreviewStyles.containerExpanded : {},
926
+ padding: "8px"
607
927
  },
608
928
  children: [
609
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.header, children: [
610
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.headerTitle, children: "Screenshot Preview" }),
611
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.headerActions, children: [
612
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sizeLabel, children: (0, import_anyclick_core.formatBytes)(totalSize) }),
929
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.header, children: [
930
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.headerTitle, children: "Review Screenshots" }),
931
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.headerActions, children: [
932
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.sizeLabel, children: (0, import_anyclick_core.formatBytes)(totalSize) }),
613
933
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
614
934
  "button",
615
935
  {
616
936
  type: "button",
617
937
  onClick: () => setIsExpanded(!isExpanded),
618
- style: styles.iconButton,
938
+ style: screenshotPreviewStyles.iconButton,
619
939
  title: isExpanded ? "Collapse" : "Expand",
620
940
  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
941
  }
622
942
  )
623
943
  ] })
624
944
  ] }),
625
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.tabContainer, children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
945
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: screenshotPreviewStyles.tabContainer, children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
626
946
  "button",
627
947
  {
628
948
  type: "button",
629
949
  onClick: () => setActiveTab(tab.key),
630
950
  style: {
631
- ...styles.tab,
632
- ...activeTab === tab.key ? styles.tabActive : {}
951
+ ...screenshotPreviewStyles.tab,
952
+ ...activeTab === tab.key ? screenshotPreviewStyles.tabActive : {},
953
+ ...tab.error && !tab.data ? screenshotPreviewStyles.tabError : {}
633
954
  },
634
955
  children: [
956
+ tab.error && !tab.data && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
957
+ CircleAlert,
958
+ {
959
+ className: "w-3 h-3",
960
+ style: { color: "#ef4444" }
961
+ }
962
+ ),
635
963
  tab.label,
636
- tab.data && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.tabSize, children: (0, import_anyclick_core.formatBytes)(tab.data.sizeBytes) })
964
+ tab.data && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.tabSize, children: (0, import_anyclick_core.formatBytes)(tab.data.sizeBytes) })
637
965
  ]
638
966
  },
639
967
  tab.key
@@ -642,17 +970,21 @@ function ScreenshotPreview({
642
970
  "div",
643
971
  {
644
972
  style: {
645
- ...styles.previewContainer,
646
- ...isExpanded ? styles.previewContainerExpanded : {}
973
+ ...screenshotPreviewStyles.previewContainer,
974
+ ...isExpanded ? screenshotPreviewStyles.previewContainerExpanded : {}
647
975
  },
648
976
  children: activeScreenshot ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
649
977
  "img",
650
978
  {
651
979
  src: activeScreenshot.dataUrl,
652
980
  alt: `${activeTab} screenshot`,
653
- style: styles.previewImage
981
+ style: screenshotPreviewStyles.previewImage
654
982
  }
655
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.noPreview, children: [
983
+ ) : activeError ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.errorPreview, children: [
984
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleAlert, { className: "w-8 h-8", style: { color: "#ef4444" } }),
985
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.errorTitle, children: "Capture Failed" }),
986
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: screenshotPreviewStyles.errorMessage, children: activeError.message })
987
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.noPreview, children: [
656
988
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Image, { className: "w-6 h-6", style: { color: "#9ca3af" } }),
657
989
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
658
990
  "No ",
@@ -662,27 +994,27 @@ function ScreenshotPreview({
662
994
  ] })
663
995
  }
664
996
  ),
665
- activeScreenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.dimensionsInfo, children: [
997
+ activeScreenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.dimensionsInfo, children: [
666
998
  activeScreenshot.width,
667
999
  " \xD7 ",
668
1000
  activeScreenshot.height,
669
1001
  "px"
670
1002
  ] }),
671
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.actions, children: [
1003
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.actions, children: [
672
1004
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
673
1005
  "button",
674
1006
  {
675
1007
  type: "button",
676
1008
  onClick: onRetake,
677
1009
  disabled: isSubmitting,
678
- style: styles.retakeButtonSmall,
1010
+ style: screenshotPreviewStyles.retakeButtonSmall,
679
1011
  children: [
680
1012
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: "w-3 h-3" }),
681
1013
  "Retake"
682
1014
  ]
683
1015
  }
684
1016
  ),
685
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.actionsRight, children: [
1017
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: screenshotPreviewStyles.actionsRight, children: [
686
1018
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
687
1019
  "button",
688
1020
  {
@@ -723,183 +1055,6 @@ function ScreenshotPreview({
723
1055
  }
724
1056
  );
725
1057
  }
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
1058
 
904
1059
  // src/ContextMenu.tsx
905
1060
  var import_jsx_runtime2 = require("react/jsx-runtime");
@@ -1203,6 +1358,14 @@ function ContextMenu({
1203
1358
  captureScreenshots();
1204
1359
  };
1205
1360
  const containerWidth = currentView === "screenshot-preview" ? 360 : void 0;
1361
+ if (process.env.NODE_ENV === "development" && visible) {
1362
+ console.log("[ContextMenu] Style Debug", {
1363
+ styleExists: !!style,
1364
+ styleKeys: style ? Object.keys(style) : [],
1365
+ styleValues: style,
1366
+ className
1367
+ });
1368
+ }
1206
1369
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1207
1370
  "div",
1208
1371
  {
@@ -1218,7 +1381,7 @@ function ContextMenu({
1218
1381
  role: "menu",
1219
1382
  "aria-label": "Feedback options",
1220
1383
  children: [
1221
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: menuStyles.header, children: currentView === "screenshot-preview" ? "Review Screenshots" : "Send Feedback" }),
1384
+ currentView !== "screenshot-preview" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: menuStyles.header, children: "Send Feedback" }),
1222
1385
  currentView === "menu" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: menuStyles.itemList, children: [
1223
1386
  submenuStack.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BackButton, { onClick: handleBack }),
1224
1387
  currentItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -1265,19 +1428,179 @@ var screenshotIndicatorStyle = {
1265
1428
  gap: "6px",
1266
1429
  padding: "8px 12px",
1267
1430
  fontSize: "11px",
1268
- color: "#9ca3af",
1269
- borderTop: "1px solid #f3f4f6",
1431
+ color: "var(--anyclick-menu-text-muted, #9ca3af)",
1432
+ borderTop: "1px solid var(--anyclick-menu-border, #f3f4f6)",
1270
1433
  marginTop: "4px"
1271
1434
  };
1272
1435
 
1273
- // src/FeedbackProvider.tsx
1436
+ // src/store.ts
1437
+ var import_zustand = require("zustand");
1438
+ var providerIdCounter = 0;
1439
+ function generateProviderId() {
1440
+ return `anyclick-provider-${++providerIdCounter}`;
1441
+ }
1442
+ var useProviderStore = (0, import_zustand.create)((set, get) => ({
1443
+ providers: /* @__PURE__ */ new Map(),
1444
+ registerProvider: (provider) => {
1445
+ set((state) => {
1446
+ const newProviders = new Map(state.providers);
1447
+ newProviders.set(provider.id, provider);
1448
+ return { providers: newProviders };
1449
+ });
1450
+ },
1451
+ unregisterProvider: (id) => {
1452
+ set((state) => {
1453
+ const newProviders = new Map(state.providers);
1454
+ newProviders.delete(id);
1455
+ return { providers: newProviders };
1456
+ });
1457
+ },
1458
+ updateProvider: (id, updates) => {
1459
+ set((state) => {
1460
+ const newProviders = new Map(state.providers);
1461
+ const existing = newProviders.get(id);
1462
+ if (existing) {
1463
+ newProviders.set(id, { ...existing, ...updates });
1464
+ }
1465
+ return { providers: newProviders };
1466
+ });
1467
+ },
1468
+ findProvidersForElement: (element) => {
1469
+ const { providers } = get();
1470
+ const matching = [];
1471
+ for (const provider of providers.values()) {
1472
+ if (provider.disabled) continue;
1473
+ const container = provider.containerRef.current;
1474
+ if (provider.scoped && container) {
1475
+ if (container.contains(element)) {
1476
+ matching.push(provider);
1477
+ }
1478
+ } else if (!provider.scoped) {
1479
+ matching.push(provider);
1480
+ }
1481
+ }
1482
+ return matching.sort((a, b) => b.depth - a.depth);
1483
+ },
1484
+ findParentProvider: (container, excludeId) => {
1485
+ const { providers } = get();
1486
+ if (!container) return null;
1487
+ let nearestParent = null;
1488
+ let nearestDepth = -1;
1489
+ for (const provider of providers.values()) {
1490
+ if (provider.id === excludeId) continue;
1491
+ const providerContainer = provider.containerRef.current;
1492
+ if (!providerContainer) continue;
1493
+ if (providerContainer.contains(container)) {
1494
+ if (provider.depth > nearestDepth) {
1495
+ nearestParent = provider;
1496
+ nearestDepth = provider.depth;
1497
+ }
1498
+ }
1499
+ }
1500
+ return nearestParent;
1501
+ },
1502
+ getMergedTheme: (providerId) => {
1503
+ const { providers } = get();
1504
+ const provider = providers.get(providerId);
1505
+ if (!provider) {
1506
+ if (process.env.NODE_ENV === "development") {
1507
+ console.log(`[Store:getMergedTheme] Provider not found: ${providerId}`);
1508
+ }
1509
+ return {};
1510
+ }
1511
+ const ancestors = [];
1512
+ let current = provider;
1513
+ while (current) {
1514
+ ancestors.unshift(current);
1515
+ current = current.parentId ? providers.get(current.parentId) : void 0;
1516
+ }
1517
+ if (process.env.NODE_ENV === "development") {
1518
+ console.log(`[Store:getMergedTheme] Provider: ${providerId}`, {
1519
+ ancestorCount: ancestors.length,
1520
+ ancestorIds: ancestors.map((a) => a.id),
1521
+ providerHasTheme: !!provider.theme,
1522
+ providerThemeMenuStyle: provider.theme?.menuStyle ? Object.keys(provider.theme.menuStyle) : []
1523
+ });
1524
+ }
1525
+ const mergedTheme = {};
1526
+ for (const ancestor of ancestors) {
1527
+ if (ancestor.theme) {
1528
+ Object.assign(mergedTheme, ancestor.theme);
1529
+ if (ancestor.theme.highlightConfig) {
1530
+ mergedTheme.highlightConfig = {
1531
+ ...mergedTheme.highlightConfig,
1532
+ ...ancestor.theme.highlightConfig,
1533
+ colors: {
1534
+ ...mergedTheme.highlightConfig?.colors,
1535
+ ...ancestor.theme.highlightConfig.colors
1536
+ }
1537
+ };
1538
+ }
1539
+ if (ancestor.theme.screenshotConfig) {
1540
+ mergedTheme.screenshotConfig = {
1541
+ ...mergedTheme.screenshotConfig,
1542
+ ...ancestor.theme.screenshotConfig
1543
+ };
1544
+ }
1545
+ }
1546
+ }
1547
+ if (process.env.NODE_ENV === "development") {
1548
+ console.log(`[Store:getMergedTheme] Result for ${providerId}`, {
1549
+ hasMenuStyle: !!mergedTheme.menuStyle,
1550
+ menuStyleKeys: mergedTheme.menuStyle ? Object.keys(mergedTheme.menuStyle) : []
1551
+ });
1552
+ }
1553
+ return mergedTheme;
1554
+ },
1555
+ isDisabledByAncestor: (providerId) => {
1556
+ const { providers } = get();
1557
+ const provider = providers.get(providerId);
1558
+ if (!provider) return false;
1559
+ let current = provider;
1560
+ while (current) {
1561
+ if (current.disabled || current.theme?.disabled) {
1562
+ return true;
1563
+ }
1564
+ current = current.parentId ? providers.get(current.parentId) : void 0;
1565
+ }
1566
+ return false;
1567
+ },
1568
+ isElementInDisabledScope: (element) => {
1569
+ const { providers } = get();
1570
+ for (const provider of providers.values()) {
1571
+ if (!provider.scoped) continue;
1572
+ if (!provider.disabled && !provider.theme?.disabled) continue;
1573
+ const container = provider.containerRef.current;
1574
+ if (!container) continue;
1575
+ if (container.contains(element)) {
1576
+ return true;
1577
+ }
1578
+ }
1579
+ return false;
1580
+ }
1581
+ }));
1582
+ function dispatchContextMenuEvent(event, element) {
1583
+ const store = useProviderStore.getState();
1584
+ const providers = store.findProvidersForElement(element);
1585
+ for (const provider of providers) {
1586
+ if (store.isDisabledByAncestor(provider.id)) {
1587
+ continue;
1588
+ }
1589
+ if (provider.onContextMenu) {
1590
+ provider.onContextMenu(event, element);
1591
+ break;
1592
+ }
1593
+ }
1594
+ }
1595
+
1596
+ // src/AnyclickProvider.tsx
1274
1597
  var import_jsx_runtime3 = require("react/jsx-runtime");
1275
1598
  var defaultMenuItems = [
1276
1599
  { type: "issue", label: "Report an issue", showComment: true },
1277
1600
  { type: "feature", label: "Request a feature", showComment: true },
1278
1601
  { type: "like", label: "I like this!", showComment: false }
1279
1602
  ];
1280
- function FeedbackProvider({
1603
+ function AnyclickProvider({
1281
1604
  adapter,
1282
1605
  children,
1283
1606
  targetFilter,
@@ -1294,7 +1617,9 @@ function FeedbackProvider({
1294
1617
  menuClassName,
1295
1618
  disabled = false,
1296
1619
  highlightConfig,
1297
- screenshotConfig
1620
+ screenshotConfig,
1621
+ scoped = false,
1622
+ theme
1298
1623
  }) {
1299
1624
  const [isSubmitting, setIsSubmitting] = (0, import_react6.useState)(false);
1300
1625
  const [menuVisible, setMenuVisible] = (0, import_react6.useState)(false);
@@ -1303,8 +1628,189 @@ function FeedbackProvider({
1303
1628
  const [containerElement, setContainerElement] = (0, import_react6.useState)(
1304
1629
  null
1305
1630
  );
1631
+ const providerIdRef = (0, import_react6.useRef)(generateProviderId());
1632
+ const providerId = providerIdRef.current;
1633
+ const containerRef = (0, import_react6.useRef)(null);
1634
+ const [containerReady, setContainerReady] = (0, import_react6.useState)(!scoped);
1306
1635
  const clientRef = (0, import_react6.useRef)(null);
1636
+ const setContainerRef = (0, import_react6.useCallback)(
1637
+ (node) => {
1638
+ if (process.env.NODE_ENV === "development") {
1639
+ console.log(`[AnyclickProvider:${providerId}] Container ref callback`, {
1640
+ scoped,
1641
+ nodeReceived: !!node,
1642
+ hadPreviousNode: !!containerRef.current,
1643
+ clientExists: !!clientRef.current
1644
+ });
1645
+ }
1646
+ containerRef.current = node;
1647
+ if (scoped && node) {
1648
+ setContainerReady(true);
1649
+ if (clientRef.current) {
1650
+ clientRef.current.setContainer(node);
1651
+ }
1652
+ }
1653
+ },
1654
+ [scoped, providerId]
1655
+ );
1656
+ let parentContext = null;
1657
+ try {
1658
+ parentContext = useAnyclick();
1659
+ } catch {
1660
+ parentContext = null;
1661
+ }
1662
+ const {
1663
+ registerProvider,
1664
+ unregisterProvider,
1665
+ updateProvider,
1666
+ getMergedTheme,
1667
+ isDisabledByAncestor,
1668
+ findParentProvider,
1669
+ isElementInDisabledScope
1670
+ } = useProviderStore();
1671
+ const parentId = parentContext?.providerId ?? null;
1672
+ const depth = parentContext ? parentContext.scoped ? 1 : 0 : 0;
1673
+ const actualDepth = (0, import_react6.useMemo)(() => {
1674
+ if (!parentContext) return 0;
1675
+ let d = 0;
1676
+ let currentId = parentId;
1677
+ const providers = useProviderStore.getState().providers;
1678
+ while (currentId) {
1679
+ d++;
1680
+ const parent = providers.get(currentId);
1681
+ currentId = parent?.parentId ?? null;
1682
+ }
1683
+ return d;
1684
+ }, [parentId]);
1685
+ const isDisabledByTheme = theme === null || theme?.disabled === true;
1686
+ const effectiveDisabled = disabled || isDisabledByTheme;
1687
+ const localTheme = (0, import_react6.useMemo)(() => {
1688
+ if (theme === null) {
1689
+ return { disabled: true };
1690
+ }
1691
+ const explicitThemeProps = {};
1692
+ if (menuStyle) explicitThemeProps.menuStyle = menuStyle;
1693
+ if (menuClassName) explicitThemeProps.menuClassName = menuClassName;
1694
+ if (highlightConfig) explicitThemeProps.highlightConfig = highlightConfig;
1695
+ if (screenshotConfig)
1696
+ explicitThemeProps.screenshotConfig = screenshotConfig;
1697
+ return {
1698
+ ...explicitThemeProps,
1699
+ ...theme
1700
+ };
1701
+ }, [theme, menuStyle, menuClassName, highlightConfig, screenshotConfig]);
1702
+ const handleContextMenu = (0, import_react6.useCallback)(
1703
+ (event, element) => {
1704
+ if (!scoped && isElementInDisabledScope(element)) {
1705
+ if (process.env.NODE_ENV === "development") {
1706
+ console.log(
1707
+ `[AnyclickProvider:${providerId}] Allowing native menu - element is in disabled scope`,
1708
+ {
1709
+ targetTag: element.tagName
1710
+ }
1711
+ );
1712
+ }
1713
+ return false;
1714
+ }
1715
+ const mergedTheme2 = getMergedTheme(providerId);
1716
+ if (process.env.NODE_ENV === "development") {
1717
+ console.log(
1718
+ `[AnyclickProvider:${providerId}] handleContextMenu called`,
1719
+ {
1720
+ scoped,
1721
+ targetTag: element.tagName,
1722
+ mergedThemeColors: mergedTheme2.highlightConfig?.colors,
1723
+ position: { x: event.clientX, y: event.clientY }
1724
+ }
1725
+ );
1726
+ }
1727
+ setTargetElement(element);
1728
+ const container = findContainerParent(
1729
+ element,
1730
+ mergedTheme2.highlightConfig ?? highlightConfig
1731
+ );
1732
+ setContainerElement(container);
1733
+ setMenuPosition({ x: event.clientX, y: event.clientY });
1734
+ setMenuVisible(true);
1735
+ return true;
1736
+ },
1737
+ [
1738
+ providerId,
1739
+ getMergedTheme,
1740
+ highlightConfig,
1741
+ scoped,
1742
+ isElementInDisabledScope
1743
+ ]
1744
+ );
1745
+ (0, import_react6.useLayoutEffect)(() => {
1746
+ const providerInstance = {
1747
+ id: providerId,
1748
+ containerRef,
1749
+ scoped,
1750
+ theme: localTheme,
1751
+ disabled: effectiveDisabled,
1752
+ parentId,
1753
+ depth: actualDepth,
1754
+ onContextMenu: handleContextMenu
1755
+ };
1756
+ registerProvider(providerInstance);
1757
+ return () => {
1758
+ unregisterProvider(providerId);
1759
+ };
1760
+ }, [
1761
+ providerId,
1762
+ scoped,
1763
+ localTheme,
1764
+ effectiveDisabled,
1765
+ parentId,
1766
+ actualDepth,
1767
+ handleContextMenu,
1768
+ registerProvider,
1769
+ unregisterProvider
1770
+ ]);
1771
+ (0, import_react6.useEffect)(() => {
1772
+ updateProvider(providerId, {
1773
+ theme: localTheme,
1774
+ disabled: effectiveDisabled,
1775
+ onContextMenu: handleContextMenu
1776
+ });
1777
+ }, [
1778
+ providerId,
1779
+ localTheme,
1780
+ effectiveDisabled,
1781
+ handleContextMenu,
1782
+ updateProvider
1783
+ ]);
1307
1784
  (0, import_react6.useEffect)(() => {
1785
+ if (isDisabledByAncestor(providerId)) {
1786
+ if (process.env.NODE_ENV === "development") {
1787
+ console.log(
1788
+ `[AnyclickProvider:${providerId}] Skipping - disabled by ancestor`
1789
+ );
1790
+ }
1791
+ return;
1792
+ }
1793
+ if (scoped && !containerReady) {
1794
+ if (process.env.NODE_ENV === "development") {
1795
+ console.log(
1796
+ `[AnyclickProvider:${providerId}] Waiting for container to be ready`,
1797
+ {
1798
+ scoped,
1799
+ containerReady
1800
+ }
1801
+ );
1802
+ }
1803
+ return;
1804
+ }
1805
+ if (process.env.NODE_ENV === "development") {
1806
+ console.log(`[AnyclickProvider:${providerId}] Creating client`, {
1807
+ scoped,
1808
+ containerReady,
1809
+ hasContainer: !!containerRef.current,
1810
+ effectiveDisabled,
1811
+ localThemeColors: localTheme.highlightConfig?.colors
1812
+ });
1813
+ }
1308
1814
  const client = (0, import_anyclick_core3.createFeedbackClient)({
1309
1815
  adapter,
1310
1816
  targetFilter,
@@ -1312,19 +1818,15 @@ function FeedbackProvider({
1312
1818
  maxOuterHTMLLength,
1313
1819
  maxAncestors,
1314
1820
  cooldownMs,
1315
- stripAttributes
1821
+ stripAttributes,
1822
+ // For scoped providers, pass the container
1823
+ container: scoped ? containerRef.current : null
1316
1824
  });
1317
1825
  client.onSubmitSuccess = onSubmitSuccess;
1318
1826
  client.onSubmitError = onSubmitError;
1319
- client.onContextMenu = (event, element) => {
1320
- setTargetElement(element);
1321
- const container = findContainerParent(element, highlightConfig);
1322
- setContainerElement(container);
1323
- setMenuPosition({ x: event.clientX, y: event.clientY });
1324
- setMenuVisible(true);
1325
- };
1827
+ client.onContextMenu = handleContextMenu;
1326
1828
  clientRef.current = client;
1327
- if (!disabled) {
1829
+ if (!effectiveDisabled) {
1328
1830
  client.attach();
1329
1831
  }
1330
1832
  return () => {
@@ -1340,8 +1842,12 @@ function FeedbackProvider({
1340
1842
  stripAttributes,
1341
1843
  onSubmitSuccess,
1342
1844
  onSubmitError,
1343
- disabled,
1344
- highlightConfig
1845
+ effectiveDisabled,
1846
+ scoped,
1847
+ containerReady,
1848
+ providerId,
1849
+ isDisabledByAncestor,
1850
+ handleContextMenu
1345
1851
  ]);
1346
1852
  const submitFeedback = (0, import_react6.useCallback)(
1347
1853
  async (element, type, comment, screenshots) => {
@@ -1366,12 +1872,16 @@ function FeedbackProvider({
1366
1872
  const openMenu = (0, import_react6.useCallback)(
1367
1873
  (element, position) => {
1368
1874
  setTargetElement(element);
1369
- const container = findContainerParent(element, highlightConfig);
1875
+ const mergedTheme2 = getMergedTheme(providerId);
1876
+ const container = findContainerParent(
1877
+ element,
1878
+ mergedTheme2.highlightConfig ?? highlightConfig
1879
+ );
1370
1880
  setContainerElement(container);
1371
1881
  setMenuPosition(position);
1372
1882
  setMenuVisible(true);
1373
1883
  },
1374
- [highlightConfig]
1884
+ [providerId, getMergedTheme, highlightConfig]
1375
1885
  );
1376
1886
  const closeMenu = (0, import_react6.useCallback)(() => {
1377
1887
  setMenuVisible(false);
@@ -1386,22 +1896,73 @@ function FeedbackProvider({
1386
1896
  },
1387
1897
  [targetElement, submitFeedback]
1388
1898
  );
1899
+ const inheritedTheme = getMergedTheme(providerId);
1900
+ const mergedTheme = (0, import_react6.useMemo)(
1901
+ () => ({
1902
+ ...inheritedTheme,
1903
+ ...localTheme,
1904
+ // Deep merge for nested configs
1905
+ highlightConfig: {
1906
+ ...inheritedTheme.highlightConfig,
1907
+ ...localTheme.highlightConfig,
1908
+ colors: {
1909
+ ...inheritedTheme.highlightConfig?.colors,
1910
+ ...localTheme.highlightConfig?.colors
1911
+ }
1912
+ },
1913
+ screenshotConfig: {
1914
+ ...inheritedTheme.screenshotConfig,
1915
+ ...localTheme.screenshotConfig
1916
+ }
1917
+ }),
1918
+ [inheritedTheme, localTheme]
1919
+ );
1920
+ const effectiveMenuStyle = mergedTheme.menuStyle ?? menuStyle;
1921
+ const effectiveMenuClassName = mergedTheme.menuClassName ?? menuClassName;
1922
+ if (process.env.NODE_ENV === "development") {
1923
+ console.log(`[AnyclickProvider:${providerId}] Theme Debug`, {
1924
+ scoped,
1925
+ localThemeHasMenuStyle: !!localTheme.menuStyle,
1926
+ localThemeMenuStyleKeys: localTheme.menuStyle ? Object.keys(localTheme.menuStyle) : [],
1927
+ mergedThemeHasMenuStyle: !!mergedTheme.menuStyle,
1928
+ mergedThemeMenuStyleKeys: mergedTheme.menuStyle ? Object.keys(mergedTheme.menuStyle) : [],
1929
+ effectiveMenuStyleExists: !!effectiveMenuStyle,
1930
+ effectiveMenuStyleKeys: effectiveMenuStyle ? Object.keys(effectiveMenuStyle) : [],
1931
+ menuStyleProp: !!menuStyle
1932
+ });
1933
+ }
1934
+ const effectiveHighlightConfig = mergedTheme.highlightConfig ?? highlightConfig;
1935
+ const effectiveScreenshotConfig = mergedTheme.screenshotConfig ?? screenshotConfig;
1389
1936
  const contextValue = (0, import_react6.useMemo)(
1390
1937
  () => ({
1391
- isEnabled: !disabled,
1938
+ isEnabled: !effectiveDisabled && !isDisabledByAncestor(providerId),
1392
1939
  isSubmitting,
1393
1940
  submitFeedback,
1394
1941
  openMenu,
1395
- closeMenu
1942
+ closeMenu,
1943
+ theme: mergedTheme,
1944
+ scoped,
1945
+ providerId
1396
1946
  }),
1397
- [disabled, isSubmitting, submitFeedback, openMenu, closeMenu]
1947
+ [
1948
+ effectiveDisabled,
1949
+ providerId,
1950
+ isDisabledByAncestor,
1951
+ isSubmitting,
1952
+ submitFeedback,
1953
+ openMenu,
1954
+ closeMenu,
1955
+ mergedTheme,
1956
+ scoped
1957
+ ]
1398
1958
  );
1399
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FeedbackContext.Provider, { value: contextValue, children: [
1400
- children,
1959
+ const content = scoped ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: setContainerRef, style: { display: "contents" }, children }) : children;
1960
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(AnyclickContext.Provider, { value: contextValue, children: [
1961
+ content,
1401
1962
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1402
1963
  ContextMenu,
1403
1964
  {
1404
- visible: menuVisible && !disabled,
1965
+ visible: menuVisible && !effectiveDisabled,
1405
1966
  position: menuPosition,
1406
1967
  targetElement,
1407
1968
  containerElement,
@@ -1409,14 +1970,15 @@ function FeedbackProvider({
1409
1970
  onSelect: handleMenuSelect,
1410
1971
  onClose: closeMenu,
1411
1972
  isSubmitting,
1412
- style: menuStyle,
1413
- className: menuClassName,
1414
- highlightConfig,
1415
- screenshotConfig
1973
+ style: effectiveMenuStyle,
1974
+ className: effectiveMenuClassName,
1975
+ highlightConfig: effectiveHighlightConfig,
1976
+ screenshotConfig: effectiveScreenshotConfig
1416
1977
  }
1417
1978
  )
1418
1979
  ] });
1419
1980
  }
1981
+ var FeedbackProvider = AnyclickProvider;
1420
1982
 
1421
1983
  // src/types.ts
1422
1984
  function filterMenuItemsByRole(items, userContext) {
@@ -1438,6 +2000,8 @@ function filterMenuItemsByRole(items, userContext) {
1438
2000
  var import_anyclick_core4 = require("@ewjdev/anyclick-core");
1439
2001
  // Annotate the CommonJS export names for ESM import in node:
1440
2002
  0 && (module.exports = {
2003
+ AnyclickContext,
2004
+ AnyclickProvider,
1441
2005
  ContextMenu,
1442
2006
  DEFAULT_SCREENSHOT_CONFIG,
1443
2007
  DEFAULT_SENSITIVE_SELECTORS,
@@ -1451,15 +2015,20 @@ var import_anyclick_core4 = require("@ewjdev/anyclick-core");
1451
2015
  darkMenuStyles,
1452
2016
  defaultContainerSelectors,
1453
2017
  defaultHighlightColors,
2018
+ dispatchContextMenuEvent,
1454
2019
  estimateTotalSize,
1455
2020
  filterMenuItemsByRole,
1456
2021
  findContainerParent,
1457
2022
  formatBytes,
2023
+ generateProviderId,
1458
2024
  highlightContainer,
1459
2025
  highlightTarget,
1460
2026
  isScreenshotSupported,
2027
+ menuCSSVariables,
1461
2028
  menuStyles,
1462
- useFeedback
2029
+ useAnyclick,
2030
+ useFeedback,
2031
+ useProviderStore
1463
2032
  });
1464
2033
  /*! Bundled license information:
1465
2034
 
@@ -1471,6 +2040,7 @@ lucide-react/dist/esm/icons/camera.js:
1471
2040
  lucide-react/dist/esm/icons/check.js:
1472
2041
  lucide-react/dist/esm/icons/chevron-left.js:
1473
2042
  lucide-react/dist/esm/icons/chevron-right.js:
2043
+ lucide-react/dist/esm/icons/circle-alert.js:
1474
2044
  lucide-react/dist/esm/icons/expand.js:
1475
2045
  lucide-react/dist/esm/icons/flag.js:
1476
2046
  lucide-react/dist/esm/icons/image.js: