@ewjdev/anyclick-react 1.1.0 → 1.2.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/README.md +53 -63
- package/dist/index.d.mts +88 -36
- package/dist/index.d.ts +88 -36
- package/dist/index.js +416 -74
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +418 -75
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -28,6 +28,7 @@ __export(index_exports, {
|
|
|
28
28
|
DEFAULT_SENSITIVE_SELECTORS: () => import_anyclick_core4.DEFAULT_SENSITIVE_SELECTORS,
|
|
29
29
|
FeedbackContext: () => FeedbackContext,
|
|
30
30
|
FeedbackProvider: () => FeedbackProvider,
|
|
31
|
+
FunModeBridge: () => FunModeBridge,
|
|
31
32
|
ScreenshotPreview: () => ScreenshotPreview,
|
|
32
33
|
applyHighlights: () => applyHighlights,
|
|
33
34
|
captureAllScreenshots: () => import_anyclick_core4.captureAllScreenshots,
|
|
@@ -120,16 +121,19 @@ var menuStyles = {
|
|
|
120
121
|
...menuCSSVariables
|
|
121
122
|
},
|
|
122
123
|
header: {
|
|
123
|
-
padding: "12px
|
|
124
|
+
padding: "8px 12px",
|
|
124
125
|
borderBottom: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
125
126
|
color: "var(--anyclick-menu-text-muted, #666)",
|
|
126
127
|
fontSize: "12px",
|
|
127
128
|
fontWeight: 500,
|
|
128
129
|
textTransform: "uppercase",
|
|
129
|
-
letterSpacing: "0.5px"
|
|
130
|
+
letterSpacing: "0.5px",
|
|
131
|
+
display: "flex",
|
|
132
|
+
justifyContent: "space-between",
|
|
133
|
+
alignItems: "center"
|
|
130
134
|
},
|
|
131
135
|
itemList: {
|
|
132
|
-
padding: "
|
|
136
|
+
padding: "0px 0px"
|
|
133
137
|
},
|
|
134
138
|
item: {
|
|
135
139
|
display: "flex",
|
|
@@ -531,6 +535,7 @@ function generateHighlightCSS(colors) {
|
|
|
531
535
|
border-radius: 4px !important;
|
|
532
536
|
position: relative;
|
|
533
537
|
z-index: 9997;
|
|
538
|
+
top: 0;
|
|
534
539
|
}
|
|
535
540
|
|
|
536
541
|
.${HIGHLIGHT_CONTAINER_CLASS} {
|
|
@@ -773,45 +778,56 @@ var __iconNode7 = [
|
|
|
773
778
|
];
|
|
774
779
|
var Flag = createLucideIcon("flag", __iconNode7);
|
|
775
780
|
|
|
776
|
-
// ../../node_modules/lucide-react/dist/esm/icons/
|
|
781
|
+
// ../../node_modules/lucide-react/dist/esm/icons/grip-vertical.js
|
|
777
782
|
var __iconNode8 = [
|
|
783
|
+
["circle", { cx: "9", cy: "12", r: "1", key: "1vctgf" }],
|
|
784
|
+
["circle", { cx: "9", cy: "5", r: "1", key: "hp0tcf" }],
|
|
785
|
+
["circle", { cx: "9", cy: "19", r: "1", key: "fkjjf6" }],
|
|
786
|
+
["circle", { cx: "15", cy: "12", r: "1", key: "1tmaij" }],
|
|
787
|
+
["circle", { cx: "15", cy: "5", r: "1", key: "19l28e" }],
|
|
788
|
+
["circle", { cx: "15", cy: "19", r: "1", key: "f4zoj3" }]
|
|
789
|
+
];
|
|
790
|
+
var GripVertical = createLucideIcon("grip-vertical", __iconNode8);
|
|
791
|
+
|
|
792
|
+
// ../../node_modules/lucide-react/dist/esm/icons/image.js
|
|
793
|
+
var __iconNode9 = [
|
|
778
794
|
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
|
|
779
795
|
["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
|
|
780
796
|
["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
|
|
781
797
|
];
|
|
782
|
-
var Image = createLucideIcon("image",
|
|
798
|
+
var Image = createLucideIcon("image", __iconNode9);
|
|
783
799
|
|
|
784
800
|
// ../../node_modules/lucide-react/dist/esm/icons/loader-circle.js
|
|
785
|
-
var
|
|
786
|
-
var LoaderCircle = createLucideIcon("loader-circle",
|
|
801
|
+
var __iconNode10 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
|
|
802
|
+
var LoaderCircle = createLucideIcon("loader-circle", __iconNode10);
|
|
787
803
|
|
|
788
804
|
// ../../node_modules/lucide-react/dist/esm/icons/plus.js
|
|
789
|
-
var
|
|
805
|
+
var __iconNode11 = [
|
|
790
806
|
["path", { d: "M5 12h14", key: "1ays0h" }],
|
|
791
807
|
["path", { d: "M12 5v14", key: "s699le" }]
|
|
792
808
|
];
|
|
793
|
-
var Plus = createLucideIcon("plus",
|
|
809
|
+
var Plus = createLucideIcon("plus", __iconNode11);
|
|
794
810
|
|
|
795
811
|
// ../../node_modules/lucide-react/dist/esm/icons/refresh-cw.js
|
|
796
|
-
var
|
|
812
|
+
var __iconNode12 = [
|
|
797
813
|
["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
814
|
["path", { d: "M21 3v5h-5", key: "1q7to0" }],
|
|
799
815
|
["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
816
|
["path", { d: "M8 16H3v5", key: "1cv678" }]
|
|
801
817
|
];
|
|
802
|
-
var RefreshCw = createLucideIcon("refresh-cw",
|
|
818
|
+
var RefreshCw = createLucideIcon("refresh-cw", __iconNode12);
|
|
803
819
|
|
|
804
820
|
// ../../node_modules/lucide-react/dist/esm/icons/shrink.js
|
|
805
|
-
var
|
|
821
|
+
var __iconNode13 = [
|
|
806
822
|
["path", { d: "m15 15 6 6m-6-6v4.8m0-4.8h4.8", key: "17vawe" }],
|
|
807
823
|
["path", { d: "M9 19.8V15m0 0H4.2M9 15l-6 6", key: "chjx8e" }],
|
|
808
824
|
["path", { d: "M15 4.2V9m0 0h4.8M15 9l6-6", key: "lav6yq" }],
|
|
809
825
|
["path", { d: "M9 4.2V9m0 0H4.2M9 9 3 3", key: "1pxi2q" }]
|
|
810
826
|
];
|
|
811
|
-
var Shrink = createLucideIcon("shrink",
|
|
827
|
+
var Shrink = createLucideIcon("shrink", __iconNode13);
|
|
812
828
|
|
|
813
829
|
// ../../node_modules/lucide-react/dist/esm/icons/thumbs-up.js
|
|
814
|
-
var
|
|
830
|
+
var __iconNode14 = [
|
|
815
831
|
["path", { d: "M7 10v12", key: "1qc93n" }],
|
|
816
832
|
[
|
|
817
833
|
"path",
|
|
@@ -821,14 +837,14 @@ var __iconNode13 = [
|
|
|
821
837
|
}
|
|
822
838
|
]
|
|
823
839
|
];
|
|
824
|
-
var ThumbsUp = createLucideIcon("thumbs-up",
|
|
840
|
+
var ThumbsUp = createLucideIcon("thumbs-up", __iconNode14);
|
|
825
841
|
|
|
826
842
|
// ../../node_modules/lucide-react/dist/esm/icons/x.js
|
|
827
|
-
var
|
|
843
|
+
var __iconNode15 = [
|
|
828
844
|
["path", { d: "M18 6 6 18", key: "1bl5f8" }],
|
|
829
845
|
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
830
846
|
];
|
|
831
|
-
var X = createLucideIcon("x",
|
|
847
|
+
var X = createLucideIcon("x", __iconNode15);
|
|
832
848
|
|
|
833
849
|
// src/ScreenshotPreview.tsx
|
|
834
850
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -1058,11 +1074,30 @@ function ScreenshotPreview({
|
|
|
1058
1074
|
|
|
1059
1075
|
// src/ContextMenu.tsx
|
|
1060
1076
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1077
|
+
var VIEWPORT_PADDING = 10;
|
|
1078
|
+
var screenshotIndicatorStyle = {
|
|
1079
|
+
display: "flex",
|
|
1080
|
+
marginLeft: "4px",
|
|
1081
|
+
opacity: 0.7,
|
|
1082
|
+
justifyContent: "flex-end",
|
|
1083
|
+
flex: 1
|
|
1084
|
+
};
|
|
1061
1085
|
var defaultIcons = {
|
|
1062
1086
|
issue: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Flag, { className: "w-4 h-4" }),
|
|
1063
1087
|
feature: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Plus, { className: "w-4 h-4" }),
|
|
1064
1088
|
like: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThumbsUp, { className: "w-4 h-4" })
|
|
1065
1089
|
};
|
|
1090
|
+
var DefaultHeader = ({
|
|
1091
|
+
styles,
|
|
1092
|
+
className,
|
|
1093
|
+
title = "Send Feedback",
|
|
1094
|
+
children
|
|
1095
|
+
}) => {
|
|
1096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles, className, children: [
|
|
1097
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: title }),
|
|
1098
|
+
children
|
|
1099
|
+
] });
|
|
1100
|
+
};
|
|
1066
1101
|
function MenuItem({
|
|
1067
1102
|
item,
|
|
1068
1103
|
onClick,
|
|
@@ -1070,6 +1105,7 @@ function MenuItem({
|
|
|
1070
1105
|
hasChildren
|
|
1071
1106
|
}) {
|
|
1072
1107
|
const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
|
|
1108
|
+
const [isPressed, setIsPressed] = (0, import_react5.useState)(false);
|
|
1073
1109
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1074
1110
|
"button",
|
|
1075
1111
|
{
|
|
@@ -1077,11 +1113,25 @@ function MenuItem({
|
|
|
1077
1113
|
onClick,
|
|
1078
1114
|
disabled,
|
|
1079
1115
|
onMouseEnter: () => setIsHovered(true),
|
|
1080
|
-
onMouseLeave: () =>
|
|
1116
|
+
onMouseLeave: () => {
|
|
1117
|
+
setIsHovered(false);
|
|
1118
|
+
setIsPressed(false);
|
|
1119
|
+
},
|
|
1120
|
+
onTouchStart: () => setIsPressed(true),
|
|
1121
|
+
onTouchEnd: () => setIsPressed(false),
|
|
1122
|
+
onTouchCancel: () => setIsPressed(false),
|
|
1081
1123
|
style: {
|
|
1082
1124
|
...menuStyles.item,
|
|
1083
|
-
|
|
1084
|
-
...
|
|
1125
|
+
// Apply hover/pressed state for both mouse and touch
|
|
1126
|
+
...isHovered || isPressed ? menuStyles.itemHover : {},
|
|
1127
|
+
...disabled ? { opacity: 0.5, cursor: "not-allowed" } : {},
|
|
1128
|
+
// Ensure minimum touch target size (44px is recommended)
|
|
1129
|
+
minHeight: "44px",
|
|
1130
|
+
// Prevent text selection on touch
|
|
1131
|
+
WebkitUserSelect: "none",
|
|
1132
|
+
userSelect: "none",
|
|
1133
|
+
// Prevent touch callout on iOS
|
|
1134
|
+
WebkitTouchCallout: "none"
|
|
1085
1135
|
},
|
|
1086
1136
|
children: [
|
|
1087
1137
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: menuStyles.itemIcon, children: item.icon ?? defaultIcons[item.type] }),
|
|
@@ -1099,18 +1149,31 @@ function MenuItem({
|
|
|
1099
1149
|
}
|
|
1100
1150
|
function BackButton({ onClick }) {
|
|
1101
1151
|
const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
|
|
1152
|
+
const [isPressed, setIsPressed] = (0, import_react5.useState)(false);
|
|
1102
1153
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1103
1154
|
"button",
|
|
1104
1155
|
{
|
|
1105
1156
|
type: "button",
|
|
1106
1157
|
onClick,
|
|
1107
1158
|
onMouseEnter: () => setIsHovered(true),
|
|
1108
|
-
onMouseLeave: () =>
|
|
1159
|
+
onMouseLeave: () => {
|
|
1160
|
+
setIsHovered(false);
|
|
1161
|
+
setIsPressed(false);
|
|
1162
|
+
},
|
|
1163
|
+
onTouchStart: () => setIsPressed(true),
|
|
1164
|
+
onTouchEnd: () => setIsPressed(false),
|
|
1165
|
+
onTouchCancel: () => setIsPressed(false),
|
|
1109
1166
|
style: {
|
|
1110
1167
|
...menuStyles.item,
|
|
1111
|
-
...isHovered ? menuStyles.itemHover : {},
|
|
1168
|
+
...isHovered || isPressed ? menuStyles.itemHover : {},
|
|
1112
1169
|
borderBottom: "1px solid #e5e5e5",
|
|
1113
|
-
marginBottom: "4px"
|
|
1170
|
+
marginBottom: "4px",
|
|
1171
|
+
// Ensure minimum touch target size
|
|
1172
|
+
minHeight: "44px",
|
|
1173
|
+
// Prevent text selection on touch
|
|
1174
|
+
WebkitUserSelect: "none",
|
|
1175
|
+
userSelect: "none",
|
|
1176
|
+
WebkitTouchCallout: "none"
|
|
1114
1177
|
},
|
|
1115
1178
|
children: [
|
|
1116
1179
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChevronLeft, { className: "w-4 h-4", style: { opacity: 0.5 } }),
|
|
@@ -1180,6 +1243,25 @@ function CommentForm({
|
|
|
1180
1243
|
] })
|
|
1181
1244
|
] });
|
|
1182
1245
|
}
|
|
1246
|
+
function calculateInViewPosition(requestedX, requestedY, menuWidth, menuHeight) {
|
|
1247
|
+
const viewportWidth = window.innerWidth;
|
|
1248
|
+
const viewportHeight = window.innerHeight;
|
|
1249
|
+
let x = requestedX;
|
|
1250
|
+
let y = requestedY;
|
|
1251
|
+
if (x + menuWidth > viewportWidth - VIEWPORT_PADDING) {
|
|
1252
|
+
x = viewportWidth - menuWidth - VIEWPORT_PADDING;
|
|
1253
|
+
}
|
|
1254
|
+
if (x < VIEWPORT_PADDING) {
|
|
1255
|
+
x = VIEWPORT_PADDING;
|
|
1256
|
+
}
|
|
1257
|
+
if (y + menuHeight > viewportHeight - VIEWPORT_PADDING) {
|
|
1258
|
+
y = viewportHeight - menuHeight - VIEWPORT_PADDING;
|
|
1259
|
+
}
|
|
1260
|
+
if (y < VIEWPORT_PADDING) {
|
|
1261
|
+
y = VIEWPORT_PADDING;
|
|
1262
|
+
}
|
|
1263
|
+
return { x, y };
|
|
1264
|
+
}
|
|
1183
1265
|
function ContextMenu({
|
|
1184
1266
|
visible,
|
|
1185
1267
|
position,
|
|
@@ -1192,7 +1274,10 @@ function ContextMenu({
|
|
|
1192
1274
|
style,
|
|
1193
1275
|
className,
|
|
1194
1276
|
highlightConfig,
|
|
1195
|
-
screenshotConfig
|
|
1277
|
+
screenshotConfig,
|
|
1278
|
+
positionMode = "inView",
|
|
1279
|
+
header,
|
|
1280
|
+
footer
|
|
1196
1281
|
}) {
|
|
1197
1282
|
const [selectedType, setSelectedType] = (0, import_react5.useState)(null);
|
|
1198
1283
|
const [currentView, setCurrentView] = (0, import_react5.useState)("menu");
|
|
@@ -1201,6 +1286,13 @@ function ContextMenu({
|
|
|
1201
1286
|
const [screenshots, setScreenshots] = (0, import_react5.useState)(null);
|
|
1202
1287
|
const [isCapturing, setIsCapturing] = (0, import_react5.useState)(false);
|
|
1203
1288
|
const menuRef = (0, import_react5.useRef)(null);
|
|
1289
|
+
const [adjustedPosition, setAdjustedPosition] = (0, import_react5.useState)(position);
|
|
1290
|
+
const [isDragging, setIsDragging] = (0, import_react5.useState)(false);
|
|
1291
|
+
const [dragOffset, setDragOffset] = (0, import_react5.useState)({
|
|
1292
|
+
x: 0,
|
|
1293
|
+
y: 0
|
|
1294
|
+
});
|
|
1295
|
+
const dragStartRef = (0, import_react5.useRef)(null);
|
|
1204
1296
|
const mergedScreenshotConfig = {
|
|
1205
1297
|
...import_anyclick_core2.DEFAULT_SCREENSHOT_CONFIG,
|
|
1206
1298
|
...screenshotConfig
|
|
@@ -1232,6 +1324,9 @@ function ContextMenu({
|
|
|
1232
1324
|
setSubmenuStack([]);
|
|
1233
1325
|
setScreenshots(null);
|
|
1234
1326
|
setIsCapturing(false);
|
|
1327
|
+
setIsDragging(false);
|
|
1328
|
+
setDragOffset({ x: 0, y: 0 });
|
|
1329
|
+
dragStartRef.current = null;
|
|
1235
1330
|
}
|
|
1236
1331
|
}, [visible]);
|
|
1237
1332
|
(0, import_react5.useEffect)(() => {
|
|
@@ -1252,6 +1347,9 @@ function ContextMenu({
|
|
|
1252
1347
|
const handlePointerDown = (event) => {
|
|
1253
1348
|
if (!menuRef.current) return;
|
|
1254
1349
|
const target = event.target;
|
|
1350
|
+
if (target.closest?.("[data-drag-handle]")) {
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1255
1353
|
if (!menuRef.current.contains(target)) {
|
|
1256
1354
|
onClose();
|
|
1257
1355
|
}
|
|
@@ -1262,24 +1360,71 @@ function ContextMenu({
|
|
|
1262
1360
|
};
|
|
1263
1361
|
}, [visible, onClose]);
|
|
1264
1362
|
(0, import_react5.useEffect)(() => {
|
|
1265
|
-
if (visible
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
if (
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1363
|
+
if (visible) {
|
|
1364
|
+
setAdjustedPosition(position);
|
|
1365
|
+
setDragOffset({ x: 0, y: 0 });
|
|
1366
|
+
}
|
|
1367
|
+
}, [visible, position.x, position.y]);
|
|
1368
|
+
(0, import_react5.useEffect)(() => {
|
|
1369
|
+
if (!visible || !menuRef.current) return;
|
|
1370
|
+
const updatePosition = () => {
|
|
1371
|
+
const menuElement = menuRef.current;
|
|
1372
|
+
if (!menuElement) return;
|
|
1373
|
+
const rect = menuElement.getBoundingClientRect();
|
|
1374
|
+
const baseX = position.x + dragOffset.x;
|
|
1375
|
+
const baseY = position.y + dragOffset.y;
|
|
1376
|
+
if (positionMode === "static") {
|
|
1377
|
+
setAdjustedPosition({ x: baseX, y: baseY });
|
|
1378
|
+
} else if (positionMode === "inView" || positionMode === "dynamic") {
|
|
1379
|
+
const adjusted = calculateInViewPosition(
|
|
1380
|
+
baseX,
|
|
1381
|
+
baseY,
|
|
1382
|
+
rect.width,
|
|
1383
|
+
rect.height
|
|
1384
|
+
);
|
|
1385
|
+
setAdjustedPosition(adjusted);
|
|
1280
1386
|
}
|
|
1387
|
+
};
|
|
1388
|
+
requestAnimationFrame(updatePosition);
|
|
1389
|
+
window.addEventListener("resize", updatePosition);
|
|
1390
|
+
return () => window.removeEventListener("resize", updatePosition);
|
|
1391
|
+
}, [visible, position, positionMode, dragOffset, currentView]);
|
|
1392
|
+
(0, import_react5.useEffect)(() => {
|
|
1393
|
+
if (!visible || positionMode !== "dynamic") return;
|
|
1394
|
+
const handlePointerMove = (event) => {
|
|
1395
|
+
if (!isDragging || !dragStartRef.current) return;
|
|
1396
|
+
const deltaX = event.clientX - dragStartRef.current.x;
|
|
1397
|
+
const deltaY = event.clientY - dragStartRef.current.y;
|
|
1398
|
+
setDragOffset((prev) => ({
|
|
1399
|
+
x: prev.x + deltaX,
|
|
1400
|
+
y: prev.y + deltaY
|
|
1401
|
+
}));
|
|
1402
|
+
dragStartRef.current = { x: event.clientX, y: event.clientY };
|
|
1403
|
+
};
|
|
1404
|
+
const handlePointerUp = () => {
|
|
1405
|
+
setIsDragging(false);
|
|
1406
|
+
dragStartRef.current = null;
|
|
1407
|
+
};
|
|
1408
|
+
if (isDragging) {
|
|
1409
|
+
document.addEventListener("pointermove", handlePointerMove);
|
|
1410
|
+
document.addEventListener("pointerup", handlePointerUp);
|
|
1411
|
+
document.addEventListener("pointercancel", handlePointerUp);
|
|
1412
|
+
return () => {
|
|
1413
|
+
document.removeEventListener("pointermove", handlePointerMove);
|
|
1414
|
+
document.removeEventListener("pointerup", handlePointerUp);
|
|
1415
|
+
document.removeEventListener("pointercancel", handlePointerUp);
|
|
1416
|
+
};
|
|
1281
1417
|
}
|
|
1282
|
-
}, [visible,
|
|
1418
|
+
}, [visible, positionMode, isDragging]);
|
|
1419
|
+
const handleDragStart = (0, import_react5.useCallback)(
|
|
1420
|
+
(event) => {
|
|
1421
|
+
if (positionMode !== "dynamic") return;
|
|
1422
|
+
event.preventDefault();
|
|
1423
|
+
setIsDragging(true);
|
|
1424
|
+
dragStartRef.current = { x: event.clientX, y: event.clientY };
|
|
1425
|
+
},
|
|
1426
|
+
[positionMode]
|
|
1427
|
+
);
|
|
1283
1428
|
(0, import_react5.useEffect)(() => {
|
|
1284
1429
|
const handleKeyDown = (e) => {
|
|
1285
1430
|
if (e.key === "Escape") {
|
|
@@ -1301,14 +1446,44 @@ function ContextMenu({
|
|
|
1301
1446
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1302
1447
|
}
|
|
1303
1448
|
}, [visible, currentView, submenuStack.length, onClose]);
|
|
1449
|
+
(0, import_react5.useEffect)(() => {
|
|
1450
|
+
const menuElement = menuRef.current;
|
|
1451
|
+
if (!visible || !menuElement) return;
|
|
1452
|
+
const preventTouchDefault = (e) => {
|
|
1453
|
+
const target = e.target;
|
|
1454
|
+
if (target.tagName === "TEXTAREA" || target.tagName === "INPUT" || target.isContentEditable) {
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
e.preventDefault();
|
|
1458
|
+
};
|
|
1459
|
+
menuElement.addEventListener("touchmove", preventTouchDefault, {
|
|
1460
|
+
passive: false
|
|
1461
|
+
});
|
|
1462
|
+
return () => {
|
|
1463
|
+
menuElement.removeEventListener("touchmove", preventTouchDefault);
|
|
1464
|
+
};
|
|
1465
|
+
}, [visible]);
|
|
1304
1466
|
if (!visible || !targetElement) {
|
|
1305
1467
|
return null;
|
|
1306
1468
|
}
|
|
1307
|
-
const handleItemClick = (item) => {
|
|
1469
|
+
const handleItemClick = async (item) => {
|
|
1308
1470
|
if (item.children && item.children.length > 0) {
|
|
1309
1471
|
setSubmenuStack((prev) => [...prev, item.children]);
|
|
1310
1472
|
return;
|
|
1311
1473
|
}
|
|
1474
|
+
if (item.onClick) {
|
|
1475
|
+
try {
|
|
1476
|
+
const result = await item.onClick({
|
|
1477
|
+
targetElement,
|
|
1478
|
+
containerElement,
|
|
1479
|
+
closeMenu: onClose
|
|
1480
|
+
});
|
|
1481
|
+
return result;
|
|
1482
|
+
} catch (error) {
|
|
1483
|
+
console.error("Anyclick menu onClick error:", error);
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1312
1487
|
if (item.showComment) {
|
|
1313
1488
|
setSelectedType(item.type);
|
|
1314
1489
|
setCurrentView("comment");
|
|
@@ -1373,15 +1548,51 @@ function ContextMenu({
|
|
|
1373
1548
|
className,
|
|
1374
1549
|
style: {
|
|
1375
1550
|
...menuStyles.container,
|
|
1376
|
-
left:
|
|
1377
|
-
top:
|
|
1551
|
+
left: adjustedPosition.x,
|
|
1552
|
+
top: adjustedPosition.y,
|
|
1378
1553
|
...containerWidth ? { width: containerWidth, minWidth: containerWidth } : {},
|
|
1554
|
+
// Touch-specific styles
|
|
1555
|
+
WebkitUserSelect: "none",
|
|
1556
|
+
userSelect: "none",
|
|
1557
|
+
WebkitTouchCallout: "none",
|
|
1558
|
+
touchAction: "none",
|
|
1559
|
+
// Prevent default touch behaviors
|
|
1560
|
+
// Cursor style for dragging
|
|
1561
|
+
...isDragging ? { cursor: "grabbing" } : {},
|
|
1379
1562
|
...style
|
|
1380
1563
|
},
|
|
1381
1564
|
role: "menu",
|
|
1382
1565
|
"aria-label": "Feedback options",
|
|
1383
1566
|
children: [
|
|
1384
|
-
currentView !== "screenshot-preview" && /* @__PURE__ */ (0, import_jsx_runtime2.
|
|
1567
|
+
!header && currentView !== "screenshot-preview" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(DefaultHeader, { styles: menuStyles.header, title: "Send Feedback", children: [
|
|
1568
|
+
showPreview && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: screenshotIndicatorStyle, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Camera, { className: "w-3 h-3" }) }),
|
|
1569
|
+
positionMode === "dynamic" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1570
|
+
"div",
|
|
1571
|
+
{
|
|
1572
|
+
"data-drag-handle": true,
|
|
1573
|
+
onPointerDown: handleDragStart,
|
|
1574
|
+
style: {
|
|
1575
|
+
cursor: isDragging ? "grabbing" : "grab",
|
|
1576
|
+
padding: "4px",
|
|
1577
|
+
marginRight: "-4px",
|
|
1578
|
+
borderRadius: "4px",
|
|
1579
|
+
display: "flex",
|
|
1580
|
+
alignItems: "center",
|
|
1581
|
+
opacity: 0.5,
|
|
1582
|
+
transition: "opacity 0.15s"
|
|
1583
|
+
},
|
|
1584
|
+
onMouseEnter: (e) => {
|
|
1585
|
+
e.currentTarget.style.opacity = "1";
|
|
1586
|
+
},
|
|
1587
|
+
onMouseLeave: (e) => {
|
|
1588
|
+
e.currentTarget.style.opacity = "0.5";
|
|
1589
|
+
},
|
|
1590
|
+
title: "Drag to move",
|
|
1591
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GripVertical, { className: "w-4 h-4" })
|
|
1592
|
+
}
|
|
1593
|
+
)
|
|
1594
|
+
] }),
|
|
1595
|
+
!!header && header,
|
|
1385
1596
|
currentView === "menu" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: menuStyles.itemList, children: [
|
|
1386
1597
|
submenuStack.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BackButton, { onClick: handleBack }),
|
|
1387
1598
|
currentItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -1393,11 +1604,7 @@ function ContextMenu({
|
|
|
1393
1604
|
hasChildren: item.children && item.children.length > 0
|
|
1394
1605
|
},
|
|
1395
1606
|
item.type
|
|
1396
|
-
))
|
|
1397
|
-
showPreview && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: screenshotIndicatorStyle, children: [
|
|
1398
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Camera, { className: "w-3 h-3" }),
|
|
1399
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Screenshots will be captured" })
|
|
1400
|
-
] })
|
|
1607
|
+
))
|
|
1401
1608
|
] }),
|
|
1402
1609
|
currentView === "comment" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1403
1610
|
CommentForm,
|
|
@@ -1422,16 +1629,6 @@ function ContextMenu({
|
|
|
1422
1629
|
}
|
|
1423
1630
|
);
|
|
1424
1631
|
}
|
|
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
1632
|
|
|
1436
1633
|
// src/store.ts
|
|
1437
1634
|
var import_zustand = require("zustand");
|
|
@@ -1577,17 +1774,45 @@ var useProviderStore = (0, import_zustand.create)((set, get) => ({
|
|
|
1577
1774
|
}
|
|
1578
1775
|
}
|
|
1579
1776
|
return false;
|
|
1777
|
+
},
|
|
1778
|
+
isElementInAnyScopedProvider: (element) => {
|
|
1779
|
+
const { providers } = get();
|
|
1780
|
+
for (const provider of providers.values()) {
|
|
1781
|
+
if (!provider.scoped) continue;
|
|
1782
|
+
const container = provider.containerRef.current;
|
|
1783
|
+
if (!container) continue;
|
|
1784
|
+
if (container.contains(element)) {
|
|
1785
|
+
if (process.env.NODE_ENV === "development") {
|
|
1786
|
+
console.log(
|
|
1787
|
+
`[Store:isElementInAnyScopedProvider] Element is in scoped provider: ${provider.id}`,
|
|
1788
|
+
{
|
|
1789
|
+
elementTag: element.tagName,
|
|
1790
|
+
providerId: provider.id,
|
|
1791
|
+
providerDisabled: provider.disabled
|
|
1792
|
+
}
|
|
1793
|
+
);
|
|
1794
|
+
}
|
|
1795
|
+
return true;
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
return false;
|
|
1580
1799
|
}
|
|
1581
1800
|
}));
|
|
1582
1801
|
function dispatchContextMenuEvent(event, element) {
|
|
1583
1802
|
const store = useProviderStore.getState();
|
|
1584
1803
|
const providers = store.findProvidersForElement(element);
|
|
1804
|
+
const menuEvent = {
|
|
1805
|
+
clientX: event.clientX,
|
|
1806
|
+
clientY: event.clientY,
|
|
1807
|
+
originalEvent: event,
|
|
1808
|
+
isTouch: false
|
|
1809
|
+
};
|
|
1585
1810
|
for (const provider of providers) {
|
|
1586
1811
|
if (store.isDisabledByAncestor(provider.id)) {
|
|
1587
1812
|
continue;
|
|
1588
1813
|
}
|
|
1589
1814
|
if (provider.onContextMenu) {
|
|
1590
|
-
provider.onContextMenu(
|
|
1815
|
+
provider.onContextMenu(menuEvent, element);
|
|
1591
1816
|
break;
|
|
1592
1817
|
}
|
|
1593
1818
|
}
|
|
@@ -1617,9 +1842,12 @@ function AnyclickProvider({
|
|
|
1617
1842
|
menuClassName,
|
|
1618
1843
|
disabled = false,
|
|
1619
1844
|
highlightConfig,
|
|
1845
|
+
header,
|
|
1620
1846
|
screenshotConfig,
|
|
1621
1847
|
scoped = false,
|
|
1622
|
-
theme
|
|
1848
|
+
theme,
|
|
1849
|
+
touchHoldDurationMs,
|
|
1850
|
+
touchMoveThreshold
|
|
1623
1851
|
}) {
|
|
1624
1852
|
const [isSubmitting, setIsSubmitting] = (0, import_react6.useState)(false);
|
|
1625
1853
|
const [menuVisible, setMenuVisible] = (0, import_react6.useState)(false);
|
|
@@ -1666,7 +1894,8 @@ function AnyclickProvider({
|
|
|
1666
1894
|
getMergedTheme,
|
|
1667
1895
|
isDisabledByAncestor,
|
|
1668
1896
|
findParentProvider,
|
|
1669
|
-
isElementInDisabledScope
|
|
1897
|
+
isElementInDisabledScope,
|
|
1898
|
+
isElementInAnyScopedProvider
|
|
1670
1899
|
} = useProviderStore();
|
|
1671
1900
|
const parentId = parentContext?.providerId ?? null;
|
|
1672
1901
|
const depth = parentContext ? parentContext.scoped ? 1 : 0 : 0;
|
|
@@ -1712,6 +1941,17 @@ function AnyclickProvider({
|
|
|
1712
1941
|
}
|
|
1713
1942
|
return false;
|
|
1714
1943
|
}
|
|
1944
|
+
if (!scoped && event.isTouch && isElementInAnyScopedProvider(element)) {
|
|
1945
|
+
if (process.env.NODE_ENV === "development") {
|
|
1946
|
+
console.log(
|
|
1947
|
+
`[AnyclickProvider:${providerId}] Deferring to scoped provider for touch event`,
|
|
1948
|
+
{
|
|
1949
|
+
targetTag: element.tagName
|
|
1950
|
+
}
|
|
1951
|
+
);
|
|
1952
|
+
}
|
|
1953
|
+
return false;
|
|
1954
|
+
}
|
|
1715
1955
|
const mergedTheme2 = getMergedTheme(providerId);
|
|
1716
1956
|
if (process.env.NODE_ENV === "development") {
|
|
1717
1957
|
console.log(
|
|
@@ -1720,7 +1960,8 @@ function AnyclickProvider({
|
|
|
1720
1960
|
scoped,
|
|
1721
1961
|
targetTag: element.tagName,
|
|
1722
1962
|
mergedThemeColors: mergedTheme2.highlightConfig?.colors,
|
|
1723
|
-
position: { x: event.clientX, y: event.clientY }
|
|
1963
|
+
position: { x: event.clientX, y: event.clientY },
|
|
1964
|
+
isTouch: event.isTouch
|
|
1724
1965
|
}
|
|
1725
1966
|
);
|
|
1726
1967
|
}
|
|
@@ -1739,7 +1980,8 @@ function AnyclickProvider({
|
|
|
1739
1980
|
getMergedTheme,
|
|
1740
1981
|
highlightConfig,
|
|
1741
1982
|
scoped,
|
|
1742
|
-
isElementInDisabledScope
|
|
1983
|
+
isElementInDisabledScope,
|
|
1984
|
+
isElementInAnyScopedProvider
|
|
1743
1985
|
]
|
|
1744
1986
|
);
|
|
1745
1987
|
(0, import_react6.useLayoutEffect)(() => {
|
|
@@ -1811,7 +2053,7 @@ function AnyclickProvider({
|
|
|
1811
2053
|
localThemeColors: localTheme.highlightConfig?.colors
|
|
1812
2054
|
});
|
|
1813
2055
|
}
|
|
1814
|
-
const client = (0, import_anyclick_core3.
|
|
2056
|
+
const client = (0, import_anyclick_core3.createAnyclickClient)({
|
|
1815
2057
|
adapter,
|
|
1816
2058
|
targetFilter,
|
|
1817
2059
|
maxInnerTextLength,
|
|
@@ -1820,7 +2062,9 @@ function AnyclickProvider({
|
|
|
1820
2062
|
cooldownMs,
|
|
1821
2063
|
stripAttributes,
|
|
1822
2064
|
// For scoped providers, pass the container
|
|
1823
|
-
container: scoped ? containerRef.current : null
|
|
2065
|
+
container: scoped ? containerRef.current : null,
|
|
2066
|
+
touchHoldDurationMs,
|
|
2067
|
+
touchMoveThreshold
|
|
1824
2068
|
});
|
|
1825
2069
|
client.onSubmitSuccess = onSubmitSuccess;
|
|
1826
2070
|
client.onSubmitError = onSubmitError;
|
|
@@ -1847,15 +2091,17 @@ function AnyclickProvider({
|
|
|
1847
2091
|
containerReady,
|
|
1848
2092
|
providerId,
|
|
1849
2093
|
isDisabledByAncestor,
|
|
1850
|
-
handleContextMenu
|
|
2094
|
+
handleContextMenu,
|
|
2095
|
+
touchHoldDurationMs,
|
|
2096
|
+
touchMoveThreshold
|
|
1851
2097
|
]);
|
|
1852
|
-
const
|
|
2098
|
+
const submitAnyclick = (0, import_react6.useCallback)(
|
|
1853
2099
|
async (element, type, comment, screenshots) => {
|
|
1854
2100
|
const client = clientRef.current;
|
|
1855
2101
|
if (!client) return;
|
|
1856
2102
|
setIsSubmitting(true);
|
|
1857
2103
|
try {
|
|
1858
|
-
await client.
|
|
2104
|
+
await client.submitAnyclick(element, type, {
|
|
1859
2105
|
comment,
|
|
1860
2106
|
metadata,
|
|
1861
2107
|
screenshots
|
|
@@ -1891,10 +2137,10 @@ function AnyclickProvider({
|
|
|
1891
2137
|
const handleMenuSelect = (0, import_react6.useCallback)(
|
|
1892
2138
|
(type, comment, screenshots) => {
|
|
1893
2139
|
if (targetElement) {
|
|
1894
|
-
|
|
2140
|
+
submitAnyclick(targetElement, type, comment, screenshots);
|
|
1895
2141
|
}
|
|
1896
2142
|
},
|
|
1897
|
-
[targetElement,
|
|
2143
|
+
[targetElement, submitAnyclick]
|
|
1898
2144
|
);
|
|
1899
2145
|
const inheritedTheme = getMergedTheme(providerId);
|
|
1900
2146
|
const mergedTheme = (0, import_react6.useMemo)(
|
|
@@ -1937,7 +2183,7 @@ function AnyclickProvider({
|
|
|
1937
2183
|
() => ({
|
|
1938
2184
|
isEnabled: !effectiveDisabled && !isDisabledByAncestor(providerId),
|
|
1939
2185
|
isSubmitting,
|
|
1940
|
-
|
|
2186
|
+
submitAnyclick,
|
|
1941
2187
|
openMenu,
|
|
1942
2188
|
closeMenu,
|
|
1943
2189
|
theme: mergedTheme,
|
|
@@ -1949,7 +2195,7 @@ function AnyclickProvider({
|
|
|
1949
2195
|
providerId,
|
|
1950
2196
|
isDisabledByAncestor,
|
|
1951
2197
|
isSubmitting,
|
|
1952
|
-
|
|
2198
|
+
submitAnyclick,
|
|
1953
2199
|
openMenu,
|
|
1954
2200
|
closeMenu,
|
|
1955
2201
|
mergedTheme,
|
|
@@ -1973,13 +2219,107 @@ function AnyclickProvider({
|
|
|
1973
2219
|
style: effectiveMenuStyle,
|
|
1974
2220
|
className: effectiveMenuClassName,
|
|
1975
2221
|
highlightConfig: effectiveHighlightConfig,
|
|
1976
|
-
screenshotConfig: effectiveScreenshotConfig
|
|
2222
|
+
screenshotConfig: effectiveScreenshotConfig,
|
|
2223
|
+
header
|
|
1977
2224
|
}
|
|
1978
2225
|
)
|
|
1979
2226
|
] });
|
|
1980
2227
|
}
|
|
1981
2228
|
var FeedbackProvider = AnyclickProvider;
|
|
1982
2229
|
|
|
2230
|
+
// src/FunModeBridge.tsx
|
|
2231
|
+
var import_react7 = require("react");
|
|
2232
|
+
var import_anyclick_pointer = require("@ewjdev/anyclick-pointer");
|
|
2233
|
+
function isFunModeEnabled(theme) {
|
|
2234
|
+
if (!theme) return false;
|
|
2235
|
+
if (theme.funMode === void 0) return false;
|
|
2236
|
+
if (typeof theme.funMode === "boolean") return theme.funMode;
|
|
2237
|
+
return theme.funMode.enabled ?? true;
|
|
2238
|
+
}
|
|
2239
|
+
function buildFunConfig(theme, container) {
|
|
2240
|
+
const funTheme = typeof theme?.funMode === "object" ? theme.funMode : {};
|
|
2241
|
+
const resolveTrackElement = () => {
|
|
2242
|
+
let el = container;
|
|
2243
|
+
while (el) {
|
|
2244
|
+
const rect = el.getBoundingClientRect();
|
|
2245
|
+
if (rect.width > 0 && rect.height > 0) {
|
|
2246
|
+
return el;
|
|
2247
|
+
}
|
|
2248
|
+
el = el.parentElement;
|
|
2249
|
+
}
|
|
2250
|
+
return document.body;
|
|
2251
|
+
};
|
|
2252
|
+
const getTrackElement = () => resolveTrackElement();
|
|
2253
|
+
return {
|
|
2254
|
+
maxSpeed: funTheme.maxSpeed,
|
|
2255
|
+
acceleration: funTheme.acceleration,
|
|
2256
|
+
getTrackElement,
|
|
2257
|
+
getObstacles: () => {
|
|
2258
|
+
const trackElement = getTrackElement();
|
|
2259
|
+
const obstacles = [];
|
|
2260
|
+
const parent = trackElement.parentElement;
|
|
2261
|
+
if (parent) {
|
|
2262
|
+
Array.from(parent.children).forEach((sibling) => {
|
|
2263
|
+
if (sibling !== trackElement) {
|
|
2264
|
+
obstacles.push(sibling.getBoundingClientRect());
|
|
2265
|
+
}
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2268
|
+
Array.from(trackElement.children).forEach((child) => {
|
|
2269
|
+
obstacles.push(child.getBoundingClientRect());
|
|
2270
|
+
});
|
|
2271
|
+
return obstacles;
|
|
2272
|
+
}
|
|
2273
|
+
};
|
|
2274
|
+
}
|
|
2275
|
+
function FunModeBridge() {
|
|
2276
|
+
const { setConfig } = (0, import_anyclick_pointer.usePointer)();
|
|
2277
|
+
const providerStore = useProviderStore();
|
|
2278
|
+
const activeProviderRef = (0, import_react7.useRef)(null);
|
|
2279
|
+
const cachedConfigs = (0, import_react7.useRef)({});
|
|
2280
|
+
const findActiveFunProvider = (0, import_react7.useMemo)(() => {
|
|
2281
|
+
return (el) => {
|
|
2282
|
+
if (!el) return null;
|
|
2283
|
+
const providers = providerStore.findProvidersForElement(el);
|
|
2284
|
+
for (const provider of providers) {
|
|
2285
|
+
if (provider.scoped && !provider.disabled && isFunModeEnabled(provider.theme)) {
|
|
2286
|
+
return provider;
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
return null;
|
|
2290
|
+
};
|
|
2291
|
+
}, [providerStore]);
|
|
2292
|
+
(0, import_react7.useEffect)(() => {
|
|
2293
|
+
const handleMove = (event) => {
|
|
2294
|
+
const el = document.elementFromPoint(event.clientX, event.clientY);
|
|
2295
|
+
const provider = findActiveFunProvider(el);
|
|
2296
|
+
if (!provider || !provider.containerRef.current) {
|
|
2297
|
+
if (activeProviderRef.current !== null) {
|
|
2298
|
+
activeProviderRef.current = null;
|
|
2299
|
+
setConfig({ mode: "normal" });
|
|
2300
|
+
}
|
|
2301
|
+
return;
|
|
2302
|
+
}
|
|
2303
|
+
if (activeProviderRef.current === provider.id) {
|
|
2304
|
+
return;
|
|
2305
|
+
}
|
|
2306
|
+
activeProviderRef.current = provider.id;
|
|
2307
|
+
if (!cachedConfigs.current[provider.id]) {
|
|
2308
|
+
cachedConfigs.current[provider.id] = {
|
|
2309
|
+
mode: "fun",
|
|
2310
|
+
funConfig: buildFunConfig(provider.theme, provider.containerRef.current)
|
|
2311
|
+
};
|
|
2312
|
+
}
|
|
2313
|
+
setConfig(cachedConfigs.current[provider.id]);
|
|
2314
|
+
};
|
|
2315
|
+
window.addEventListener("pointermove", handleMove, { passive: true });
|
|
2316
|
+
return () => {
|
|
2317
|
+
window.removeEventListener("pointermove", handleMove);
|
|
2318
|
+
};
|
|
2319
|
+
}, [findActiveFunProvider, setConfig]);
|
|
2320
|
+
return null;
|
|
2321
|
+
}
|
|
2322
|
+
|
|
1983
2323
|
// src/types.ts
|
|
1984
2324
|
function filterMenuItemsByRole(items, userContext) {
|
|
1985
2325
|
if (!userContext) {
|
|
@@ -2007,6 +2347,7 @@ var import_anyclick_core4 = require("@ewjdev/anyclick-core");
|
|
|
2007
2347
|
DEFAULT_SENSITIVE_SELECTORS,
|
|
2008
2348
|
FeedbackContext,
|
|
2009
2349
|
FeedbackProvider,
|
|
2350
|
+
FunModeBridge,
|
|
2010
2351
|
ScreenshotPreview,
|
|
2011
2352
|
applyHighlights,
|
|
2012
2353
|
captureAllScreenshots,
|
|
@@ -2043,6 +2384,7 @@ lucide-react/dist/esm/icons/chevron-right.js:
|
|
|
2043
2384
|
lucide-react/dist/esm/icons/circle-alert.js:
|
|
2044
2385
|
lucide-react/dist/esm/icons/expand.js:
|
|
2045
2386
|
lucide-react/dist/esm/icons/flag.js:
|
|
2387
|
+
lucide-react/dist/esm/icons/grip-vertical.js:
|
|
2046
2388
|
lucide-react/dist/esm/icons/image.js:
|
|
2047
2389
|
lucide-react/dist/esm/icons/loader-circle.js:
|
|
2048
2390
|
lucide-react/dist/esm/icons/plus.js:
|