@ewjdev/anyclick-react 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -773,45 +773,56 @@ var __iconNode7 = [
773
773
  ];
774
774
  var Flag = createLucideIcon("flag", __iconNode7);
775
775
 
776
- // ../../node_modules/lucide-react/dist/esm/icons/image.js
776
+ // ../../node_modules/lucide-react/dist/esm/icons/grip-vertical.js
777
777
  var __iconNode8 = [
778
+ ["circle", { cx: "9", cy: "12", r: "1", key: "1vctgf" }],
779
+ ["circle", { cx: "9", cy: "5", r: "1", key: "hp0tcf" }],
780
+ ["circle", { cx: "9", cy: "19", r: "1", key: "fkjjf6" }],
781
+ ["circle", { cx: "15", cy: "12", r: "1", key: "1tmaij" }],
782
+ ["circle", { cx: "15", cy: "5", r: "1", key: "19l28e" }],
783
+ ["circle", { cx: "15", cy: "19", r: "1", key: "f4zoj3" }]
784
+ ];
785
+ var GripVertical = createLucideIcon("grip-vertical", __iconNode8);
786
+
787
+ // ../../node_modules/lucide-react/dist/esm/icons/image.js
788
+ var __iconNode9 = [
778
789
  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
779
790
  ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
780
791
  ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
781
792
  ];
782
- var Image = createLucideIcon("image", __iconNode8);
793
+ var Image = createLucideIcon("image", __iconNode9);
783
794
 
784
795
  // ../../node_modules/lucide-react/dist/esm/icons/loader-circle.js
785
- var __iconNode9 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
786
- var LoaderCircle = createLucideIcon("loader-circle", __iconNode9);
796
+ var __iconNode10 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
797
+ var LoaderCircle = createLucideIcon("loader-circle", __iconNode10);
787
798
 
788
799
  // ../../node_modules/lucide-react/dist/esm/icons/plus.js
789
- var __iconNode10 = [
800
+ var __iconNode11 = [
790
801
  ["path", { d: "M5 12h14", key: "1ays0h" }],
791
802
  ["path", { d: "M12 5v14", key: "s699le" }]
792
803
  ];
793
- var Plus = createLucideIcon("plus", __iconNode10);
804
+ var Plus = createLucideIcon("plus", __iconNode11);
794
805
 
795
806
  // ../../node_modules/lucide-react/dist/esm/icons/refresh-cw.js
796
- var __iconNode11 = [
807
+ var __iconNode12 = [
797
808
  ["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
798
809
  ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
799
810
  ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
800
811
  ["path", { d: "M8 16H3v5", key: "1cv678" }]
801
812
  ];
802
- var RefreshCw = createLucideIcon("refresh-cw", __iconNode11);
813
+ var RefreshCw = createLucideIcon("refresh-cw", __iconNode12);
803
814
 
804
815
  // ../../node_modules/lucide-react/dist/esm/icons/shrink.js
805
- var __iconNode12 = [
816
+ var __iconNode13 = [
806
817
  ["path", { d: "m15 15 6 6m-6-6v4.8m0-4.8h4.8", key: "17vawe" }],
807
818
  ["path", { d: "M9 19.8V15m0 0H4.2M9 15l-6 6", key: "chjx8e" }],
808
819
  ["path", { d: "M15 4.2V9m0 0h4.8M15 9l6-6", key: "lav6yq" }],
809
820
  ["path", { d: "M9 4.2V9m0 0H4.2M9 9 3 3", key: "1pxi2q" }]
810
821
  ];
811
- var Shrink = createLucideIcon("shrink", __iconNode12);
822
+ var Shrink = createLucideIcon("shrink", __iconNode13);
812
823
 
813
824
  // ../../node_modules/lucide-react/dist/esm/icons/thumbs-up.js
814
- var __iconNode13 = [
825
+ var __iconNode14 = [
815
826
  ["path", { d: "M7 10v12", key: "1qc93n" }],
816
827
  [
817
828
  "path",
@@ -821,14 +832,14 @@ var __iconNode13 = [
821
832
  }
822
833
  ]
823
834
  ];
824
- var ThumbsUp = createLucideIcon("thumbs-up", __iconNode13);
835
+ var ThumbsUp = createLucideIcon("thumbs-up", __iconNode14);
825
836
 
826
837
  // ../../node_modules/lucide-react/dist/esm/icons/x.js
827
- var __iconNode14 = [
838
+ var __iconNode15 = [
828
839
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
829
840
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
830
841
  ];
831
- var X = createLucideIcon("x", __iconNode14);
842
+ var X = createLucideIcon("x", __iconNode15);
832
843
 
833
844
  // src/ScreenshotPreview.tsx
834
845
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -1058,6 +1069,17 @@ function ScreenshotPreview({
1058
1069
 
1059
1070
  // src/ContextMenu.tsx
1060
1071
  var import_jsx_runtime2 = require("react/jsx-runtime");
1072
+ var VIEWPORT_PADDING = 10;
1073
+ var screenshotIndicatorStyle = {
1074
+ display: "flex",
1075
+ alignItems: "center",
1076
+ gap: "6px",
1077
+ padding: "8px 12px",
1078
+ fontSize: "11px",
1079
+ color: "var(--anyclick-menu-text-muted, #9ca3af)",
1080
+ borderTop: "1px solid var(--anyclick-menu-border, #f3f4f6)",
1081
+ marginTop: "4px"
1082
+ };
1061
1083
  var defaultIcons = {
1062
1084
  issue: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Flag, { className: "w-4 h-4" }),
1063
1085
  feature: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Plus, { className: "w-4 h-4" }),
@@ -1070,6 +1092,7 @@ function MenuItem({
1070
1092
  hasChildren
1071
1093
  }) {
1072
1094
  const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
1095
+ const [isPressed, setIsPressed] = (0, import_react5.useState)(false);
1073
1096
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1074
1097
  "button",
1075
1098
  {
@@ -1077,11 +1100,25 @@ function MenuItem({
1077
1100
  onClick,
1078
1101
  disabled,
1079
1102
  onMouseEnter: () => setIsHovered(true),
1080
- onMouseLeave: () => setIsHovered(false),
1103
+ onMouseLeave: () => {
1104
+ setIsHovered(false);
1105
+ setIsPressed(false);
1106
+ },
1107
+ onTouchStart: () => setIsPressed(true),
1108
+ onTouchEnd: () => setIsPressed(false),
1109
+ onTouchCancel: () => setIsPressed(false),
1081
1110
  style: {
1082
1111
  ...menuStyles.item,
1083
- ...isHovered ? menuStyles.itemHover : {},
1084
- ...disabled ? { opacity: 0.5, cursor: "not-allowed" } : {}
1112
+ // Apply hover/pressed state for both mouse and touch
1113
+ ...isHovered || isPressed ? menuStyles.itemHover : {},
1114
+ ...disabled ? { opacity: 0.5, cursor: "not-allowed" } : {},
1115
+ // Ensure minimum touch target size (44px is recommended)
1116
+ minHeight: "44px",
1117
+ // Prevent text selection on touch
1118
+ WebkitUserSelect: "none",
1119
+ userSelect: "none",
1120
+ // Prevent touch callout on iOS
1121
+ WebkitTouchCallout: "none"
1085
1122
  },
1086
1123
  children: [
1087
1124
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: menuStyles.itemIcon, children: item.icon ?? defaultIcons[item.type] }),
@@ -1099,18 +1136,31 @@ function MenuItem({
1099
1136
  }
1100
1137
  function BackButton({ onClick }) {
1101
1138
  const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
1139
+ const [isPressed, setIsPressed] = (0, import_react5.useState)(false);
1102
1140
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1103
1141
  "button",
1104
1142
  {
1105
1143
  type: "button",
1106
1144
  onClick,
1107
1145
  onMouseEnter: () => setIsHovered(true),
1108
- onMouseLeave: () => setIsHovered(false),
1146
+ onMouseLeave: () => {
1147
+ setIsHovered(false);
1148
+ setIsPressed(false);
1149
+ },
1150
+ onTouchStart: () => setIsPressed(true),
1151
+ onTouchEnd: () => setIsPressed(false),
1152
+ onTouchCancel: () => setIsPressed(false),
1109
1153
  style: {
1110
1154
  ...menuStyles.item,
1111
- ...isHovered ? menuStyles.itemHover : {},
1155
+ ...isHovered || isPressed ? menuStyles.itemHover : {},
1112
1156
  borderBottom: "1px solid #e5e5e5",
1113
- marginBottom: "4px"
1157
+ marginBottom: "4px",
1158
+ // Ensure minimum touch target size
1159
+ minHeight: "44px",
1160
+ // Prevent text selection on touch
1161
+ WebkitUserSelect: "none",
1162
+ userSelect: "none",
1163
+ WebkitTouchCallout: "none"
1114
1164
  },
1115
1165
  children: [
1116
1166
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChevronLeft, { className: "w-4 h-4", style: { opacity: 0.5 } }),
@@ -1180,6 +1230,25 @@ function CommentForm({
1180
1230
  ] })
1181
1231
  ] });
1182
1232
  }
1233
+ function calculateInViewPosition(requestedX, requestedY, menuWidth, menuHeight) {
1234
+ const viewportWidth = window.innerWidth;
1235
+ const viewportHeight = window.innerHeight;
1236
+ let x = requestedX;
1237
+ let y = requestedY;
1238
+ if (x + menuWidth > viewportWidth - VIEWPORT_PADDING) {
1239
+ x = viewportWidth - menuWidth - VIEWPORT_PADDING;
1240
+ }
1241
+ if (x < VIEWPORT_PADDING) {
1242
+ x = VIEWPORT_PADDING;
1243
+ }
1244
+ if (y + menuHeight > viewportHeight - VIEWPORT_PADDING) {
1245
+ y = viewportHeight - menuHeight - VIEWPORT_PADDING;
1246
+ }
1247
+ if (y < VIEWPORT_PADDING) {
1248
+ y = VIEWPORT_PADDING;
1249
+ }
1250
+ return { x, y };
1251
+ }
1183
1252
  function ContextMenu({
1184
1253
  visible,
1185
1254
  position,
@@ -1192,7 +1261,8 @@ function ContextMenu({
1192
1261
  style,
1193
1262
  className,
1194
1263
  highlightConfig,
1195
- screenshotConfig
1264
+ screenshotConfig,
1265
+ positionMode = "inView"
1196
1266
  }) {
1197
1267
  const [selectedType, setSelectedType] = (0, import_react5.useState)(null);
1198
1268
  const [currentView, setCurrentView] = (0, import_react5.useState)("menu");
@@ -1201,6 +1271,13 @@ function ContextMenu({
1201
1271
  const [screenshots, setScreenshots] = (0, import_react5.useState)(null);
1202
1272
  const [isCapturing, setIsCapturing] = (0, import_react5.useState)(false);
1203
1273
  const menuRef = (0, import_react5.useRef)(null);
1274
+ const [adjustedPosition, setAdjustedPosition] = (0, import_react5.useState)(position);
1275
+ const [isDragging, setIsDragging] = (0, import_react5.useState)(false);
1276
+ const [dragOffset, setDragOffset] = (0, import_react5.useState)({
1277
+ x: 0,
1278
+ y: 0
1279
+ });
1280
+ const dragStartRef = (0, import_react5.useRef)(null);
1204
1281
  const mergedScreenshotConfig = {
1205
1282
  ...import_anyclick_core2.DEFAULT_SCREENSHOT_CONFIG,
1206
1283
  ...screenshotConfig
@@ -1232,6 +1309,9 @@ function ContextMenu({
1232
1309
  setSubmenuStack([]);
1233
1310
  setScreenshots(null);
1234
1311
  setIsCapturing(false);
1312
+ setIsDragging(false);
1313
+ setDragOffset({ x: 0, y: 0 });
1314
+ dragStartRef.current = null;
1235
1315
  }
1236
1316
  }, [visible]);
1237
1317
  (0, import_react5.useEffect)(() => {
@@ -1252,6 +1332,9 @@ function ContextMenu({
1252
1332
  const handlePointerDown = (event) => {
1253
1333
  if (!menuRef.current) return;
1254
1334
  const target = event.target;
1335
+ if (target.closest?.("[data-drag-handle]")) {
1336
+ return;
1337
+ }
1255
1338
  if (!menuRef.current.contains(target)) {
1256
1339
  onClose();
1257
1340
  }
@@ -1262,24 +1345,71 @@ function ContextMenu({
1262
1345
  };
1263
1346
  }, [visible, onClose]);
1264
1347
  (0, import_react5.useEffect)(() => {
1265
- if (visible && menuRef.current) {
1266
- const rect = menuRef.current.getBoundingClientRect();
1267
- const viewportWidth = window.innerWidth;
1268
- const viewportHeight = window.innerHeight;
1269
- let adjustedX = position.x;
1270
- let adjustedY = position.y;
1271
- if (position.x + rect.width > viewportWidth) {
1272
- adjustedX = viewportWidth - rect.width - 10;
1273
- }
1274
- if (position.y + rect.height > viewportHeight) {
1275
- adjustedY = viewportHeight - rect.height - 10;
1276
- }
1277
- if (adjustedX !== position.x || adjustedY !== position.y) {
1278
- menuRef.current.style.left = `${adjustedX}px`;
1279
- menuRef.current.style.top = `${adjustedY}px`;
1348
+ if (visible) {
1349
+ setAdjustedPosition(position);
1350
+ setDragOffset({ x: 0, y: 0 });
1351
+ }
1352
+ }, [visible, position.x, position.y]);
1353
+ (0, import_react5.useEffect)(() => {
1354
+ if (!visible || !menuRef.current) return;
1355
+ const updatePosition = () => {
1356
+ const menuElement = menuRef.current;
1357
+ if (!menuElement) return;
1358
+ const rect = menuElement.getBoundingClientRect();
1359
+ const baseX = position.x + dragOffset.x;
1360
+ const baseY = position.y + dragOffset.y;
1361
+ if (positionMode === "static") {
1362
+ setAdjustedPosition({ x: baseX, y: baseY });
1363
+ } else if (positionMode === "inView" || positionMode === "dynamic") {
1364
+ const adjusted = calculateInViewPosition(
1365
+ baseX,
1366
+ baseY,
1367
+ rect.width,
1368
+ rect.height
1369
+ );
1370
+ setAdjustedPosition(adjusted);
1280
1371
  }
1372
+ };
1373
+ requestAnimationFrame(updatePosition);
1374
+ window.addEventListener("resize", updatePosition);
1375
+ return () => window.removeEventListener("resize", updatePosition);
1376
+ }, [visible, position, positionMode, dragOffset, currentView]);
1377
+ (0, import_react5.useEffect)(() => {
1378
+ if (!visible || positionMode !== "dynamic") return;
1379
+ const handlePointerMove = (event) => {
1380
+ if (!isDragging || !dragStartRef.current) return;
1381
+ const deltaX = event.clientX - dragStartRef.current.x;
1382
+ const deltaY = event.clientY - dragStartRef.current.y;
1383
+ setDragOffset((prev) => ({
1384
+ x: prev.x + deltaX,
1385
+ y: prev.y + deltaY
1386
+ }));
1387
+ dragStartRef.current = { x: event.clientX, y: event.clientY };
1388
+ };
1389
+ const handlePointerUp = () => {
1390
+ setIsDragging(false);
1391
+ dragStartRef.current = null;
1392
+ };
1393
+ if (isDragging) {
1394
+ document.addEventListener("pointermove", handlePointerMove);
1395
+ document.addEventListener("pointerup", handlePointerUp);
1396
+ document.addEventListener("pointercancel", handlePointerUp);
1397
+ return () => {
1398
+ document.removeEventListener("pointermove", handlePointerMove);
1399
+ document.removeEventListener("pointerup", handlePointerUp);
1400
+ document.removeEventListener("pointercancel", handlePointerUp);
1401
+ };
1281
1402
  }
1282
- }, [visible, position]);
1403
+ }, [visible, positionMode, isDragging]);
1404
+ const handleDragStart = (0, import_react5.useCallback)(
1405
+ (event) => {
1406
+ if (positionMode !== "dynamic") return;
1407
+ event.preventDefault();
1408
+ setIsDragging(true);
1409
+ dragStartRef.current = { x: event.clientX, y: event.clientY };
1410
+ },
1411
+ [positionMode]
1412
+ );
1283
1413
  (0, import_react5.useEffect)(() => {
1284
1414
  const handleKeyDown = (e) => {
1285
1415
  if (e.key === "Escape") {
@@ -1301,6 +1431,23 @@ function ContextMenu({
1301
1431
  return () => document.removeEventListener("keydown", handleKeyDown);
1302
1432
  }
1303
1433
  }, [visible, currentView, submenuStack.length, onClose]);
1434
+ (0, import_react5.useEffect)(() => {
1435
+ const menuElement = menuRef.current;
1436
+ if (!visible || !menuElement) return;
1437
+ const preventTouchDefault = (e) => {
1438
+ const target = e.target;
1439
+ if (target.tagName === "TEXTAREA" || target.tagName === "INPUT" || target.isContentEditable) {
1440
+ return;
1441
+ }
1442
+ e.preventDefault();
1443
+ };
1444
+ menuElement.addEventListener("touchmove", preventTouchDefault, {
1445
+ passive: false
1446
+ });
1447
+ return () => {
1448
+ menuElement.removeEventListener("touchmove", preventTouchDefault);
1449
+ };
1450
+ }, [visible]);
1304
1451
  if (!visible || !targetElement) {
1305
1452
  return null;
1306
1453
  }
@@ -1373,15 +1520,61 @@ function ContextMenu({
1373
1520
  className,
1374
1521
  style: {
1375
1522
  ...menuStyles.container,
1376
- left: position.x,
1377
- top: position.y,
1523
+ left: adjustedPosition.x,
1524
+ top: adjustedPosition.y,
1378
1525
  ...containerWidth ? { width: containerWidth, minWidth: containerWidth } : {},
1526
+ // Touch-specific styles
1527
+ WebkitUserSelect: "none",
1528
+ userSelect: "none",
1529
+ WebkitTouchCallout: "none",
1530
+ touchAction: "none",
1531
+ // Prevent default touch behaviors
1532
+ // Cursor style for dragging
1533
+ ...isDragging ? { cursor: "grabbing" } : {},
1379
1534
  ...style
1380
1535
  },
1381
1536
  role: "menu",
1382
1537
  "aria-label": "Feedback options",
1383
1538
  children: [
1384
- currentView !== "screenshot-preview" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: menuStyles.header, children: "Send Feedback" }),
1539
+ currentView !== "screenshot-preview" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1540
+ "div",
1541
+ {
1542
+ style: {
1543
+ ...menuStyles.header,
1544
+ display: "flex",
1545
+ alignItems: "center",
1546
+ justifyContent: "space-between"
1547
+ },
1548
+ children: [
1549
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Send Feedback" }),
1550
+ positionMode === "dynamic" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1551
+ "div",
1552
+ {
1553
+ "data-drag-handle": true,
1554
+ onPointerDown: handleDragStart,
1555
+ style: {
1556
+ cursor: isDragging ? "grabbing" : "grab",
1557
+ padding: "4px",
1558
+ marginRight: "-4px",
1559
+ borderRadius: "4px",
1560
+ display: "flex",
1561
+ alignItems: "center",
1562
+ opacity: 0.5,
1563
+ transition: "opacity 0.15s"
1564
+ },
1565
+ onMouseEnter: (e) => {
1566
+ e.currentTarget.style.opacity = "1";
1567
+ },
1568
+ onMouseLeave: (e) => {
1569
+ e.currentTarget.style.opacity = "0.5";
1570
+ },
1571
+ title: "Drag to move",
1572
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GripVertical, { className: "w-4 h-4" })
1573
+ }
1574
+ )
1575
+ ]
1576
+ }
1577
+ ),
1385
1578
  currentView === "menu" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: menuStyles.itemList, children: [
1386
1579
  submenuStack.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BackButton, { onClick: handleBack }),
1387
1580
  currentItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -1422,16 +1615,6 @@ function ContextMenu({
1422
1615
  }
1423
1616
  );
1424
1617
  }
1425
- var screenshotIndicatorStyle = {
1426
- display: "flex",
1427
- alignItems: "center",
1428
- gap: "6px",
1429
- padding: "8px 12px",
1430
- fontSize: "11px",
1431
- color: "var(--anyclick-menu-text-muted, #9ca3af)",
1432
- borderTop: "1px solid var(--anyclick-menu-border, #f3f4f6)",
1433
- marginTop: "4px"
1434
- };
1435
1618
 
1436
1619
  // src/store.ts
1437
1620
  var import_zustand = require("zustand");
@@ -1577,17 +1760,45 @@ var useProviderStore = (0, import_zustand.create)((set, get) => ({
1577
1760
  }
1578
1761
  }
1579
1762
  return false;
1763
+ },
1764
+ isElementInAnyScopedProvider: (element) => {
1765
+ const { providers } = get();
1766
+ for (const provider of providers.values()) {
1767
+ if (!provider.scoped) continue;
1768
+ const container = provider.containerRef.current;
1769
+ if (!container) continue;
1770
+ if (container.contains(element)) {
1771
+ if (process.env.NODE_ENV === "development") {
1772
+ console.log(
1773
+ `[Store:isElementInAnyScopedProvider] Element is in scoped provider: ${provider.id}`,
1774
+ {
1775
+ elementTag: element.tagName,
1776
+ providerId: provider.id,
1777
+ providerDisabled: provider.disabled
1778
+ }
1779
+ );
1780
+ }
1781
+ return true;
1782
+ }
1783
+ }
1784
+ return false;
1580
1785
  }
1581
1786
  }));
1582
1787
  function dispatchContextMenuEvent(event, element) {
1583
1788
  const store = useProviderStore.getState();
1584
1789
  const providers = store.findProvidersForElement(element);
1790
+ const menuEvent = {
1791
+ clientX: event.clientX,
1792
+ clientY: event.clientY,
1793
+ originalEvent: event,
1794
+ isTouch: false
1795
+ };
1585
1796
  for (const provider of providers) {
1586
1797
  if (store.isDisabledByAncestor(provider.id)) {
1587
1798
  continue;
1588
1799
  }
1589
1800
  if (provider.onContextMenu) {
1590
- provider.onContextMenu(event, element);
1801
+ provider.onContextMenu(menuEvent, element);
1591
1802
  break;
1592
1803
  }
1593
1804
  }
@@ -1619,7 +1830,9 @@ function AnyclickProvider({
1619
1830
  highlightConfig,
1620
1831
  screenshotConfig,
1621
1832
  scoped = false,
1622
- theme
1833
+ theme,
1834
+ touchHoldDurationMs,
1835
+ touchMoveThreshold
1623
1836
  }) {
1624
1837
  const [isSubmitting, setIsSubmitting] = (0, import_react6.useState)(false);
1625
1838
  const [menuVisible, setMenuVisible] = (0, import_react6.useState)(false);
@@ -1666,7 +1879,8 @@ function AnyclickProvider({
1666
1879
  getMergedTheme,
1667
1880
  isDisabledByAncestor,
1668
1881
  findParentProvider,
1669
- isElementInDisabledScope
1882
+ isElementInDisabledScope,
1883
+ isElementInAnyScopedProvider
1670
1884
  } = useProviderStore();
1671
1885
  const parentId = parentContext?.providerId ?? null;
1672
1886
  const depth = parentContext ? parentContext.scoped ? 1 : 0 : 0;
@@ -1712,6 +1926,17 @@ function AnyclickProvider({
1712
1926
  }
1713
1927
  return false;
1714
1928
  }
1929
+ if (!scoped && event.isTouch && isElementInAnyScopedProvider(element)) {
1930
+ if (process.env.NODE_ENV === "development") {
1931
+ console.log(
1932
+ `[AnyclickProvider:${providerId}] Deferring to scoped provider for touch event`,
1933
+ {
1934
+ targetTag: element.tagName
1935
+ }
1936
+ );
1937
+ }
1938
+ return false;
1939
+ }
1715
1940
  const mergedTheme2 = getMergedTheme(providerId);
1716
1941
  if (process.env.NODE_ENV === "development") {
1717
1942
  console.log(
@@ -1720,7 +1945,8 @@ function AnyclickProvider({
1720
1945
  scoped,
1721
1946
  targetTag: element.tagName,
1722
1947
  mergedThemeColors: mergedTheme2.highlightConfig?.colors,
1723
- position: { x: event.clientX, y: event.clientY }
1948
+ position: { x: event.clientX, y: event.clientY },
1949
+ isTouch: event.isTouch
1724
1950
  }
1725
1951
  );
1726
1952
  }
@@ -1739,7 +1965,8 @@ function AnyclickProvider({
1739
1965
  getMergedTheme,
1740
1966
  highlightConfig,
1741
1967
  scoped,
1742
- isElementInDisabledScope
1968
+ isElementInDisabledScope,
1969
+ isElementInAnyScopedProvider
1743
1970
  ]
1744
1971
  );
1745
1972
  (0, import_react6.useLayoutEffect)(() => {
@@ -1820,7 +2047,9 @@ function AnyclickProvider({
1820
2047
  cooldownMs,
1821
2048
  stripAttributes,
1822
2049
  // For scoped providers, pass the container
1823
- container: scoped ? containerRef.current : null
2050
+ container: scoped ? containerRef.current : null,
2051
+ touchHoldDurationMs,
2052
+ touchMoveThreshold
1824
2053
  });
1825
2054
  client.onSubmitSuccess = onSubmitSuccess;
1826
2055
  client.onSubmitError = onSubmitError;
@@ -1847,7 +2076,9 @@ function AnyclickProvider({
1847
2076
  containerReady,
1848
2077
  providerId,
1849
2078
  isDisabledByAncestor,
1850
- handleContextMenu
2079
+ handleContextMenu,
2080
+ touchHoldDurationMs,
2081
+ touchMoveThreshold
1851
2082
  ]);
1852
2083
  const submitFeedback = (0, import_react6.useCallback)(
1853
2084
  async (element, type, comment, screenshots) => {
@@ -2043,6 +2274,7 @@ lucide-react/dist/esm/icons/chevron-right.js:
2043
2274
  lucide-react/dist/esm/icons/circle-alert.js:
2044
2275
  lucide-react/dist/esm/icons/expand.js:
2045
2276
  lucide-react/dist/esm/icons/flag.js:
2277
+ lucide-react/dist/esm/icons/grip-vertical.js:
2046
2278
  lucide-react/dist/esm/icons/image.js:
2047
2279
  lucide-react/dist/esm/icons/loader-circle.js:
2048
2280
  lucide-react/dist/esm/icons/plus.js: