@ewjdev/anyclick-react 1.1.1 → 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/dist/index.d.mts +66 -36
- package/dist/index.d.ts +66 -36
- package/dist/index.js +174 -64
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +176 -65
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
useRef as useRef2,
|
|
10
10
|
useState as useState3
|
|
11
11
|
} from "react";
|
|
12
|
-
import {
|
|
12
|
+
import { createAnyclickClient } from "@ewjdev/anyclick-core";
|
|
13
13
|
|
|
14
14
|
// src/context.ts
|
|
15
15
|
import { createContext, useContext } from "react";
|
|
@@ -78,16 +78,19 @@ var menuStyles = {
|
|
|
78
78
|
...menuCSSVariables
|
|
79
79
|
},
|
|
80
80
|
header: {
|
|
81
|
-
padding: "12px
|
|
81
|
+
padding: "8px 12px",
|
|
82
82
|
borderBottom: "1px solid var(--anyclick-menu-border, #e5e5e5)",
|
|
83
83
|
color: "var(--anyclick-menu-text-muted, #666)",
|
|
84
84
|
fontSize: "12px",
|
|
85
85
|
fontWeight: 500,
|
|
86
86
|
textTransform: "uppercase",
|
|
87
|
-
letterSpacing: "0.5px"
|
|
87
|
+
letterSpacing: "0.5px",
|
|
88
|
+
display: "flex",
|
|
89
|
+
justifyContent: "space-between",
|
|
90
|
+
alignItems: "center"
|
|
88
91
|
},
|
|
89
92
|
itemList: {
|
|
90
|
-
padding: "
|
|
93
|
+
padding: "0px 0px"
|
|
91
94
|
},
|
|
92
95
|
item: {
|
|
93
96
|
display: "flex",
|
|
@@ -489,6 +492,7 @@ function generateHighlightCSS(colors) {
|
|
|
489
492
|
border-radius: 4px !important;
|
|
490
493
|
position: relative;
|
|
491
494
|
z-index: 9997;
|
|
495
|
+
top: 0;
|
|
492
496
|
}
|
|
493
497
|
|
|
494
498
|
.${HIGHLIGHT_CONTAINER_CLASS} {
|
|
@@ -1030,19 +1034,27 @@ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
|
1030
1034
|
var VIEWPORT_PADDING = 10;
|
|
1031
1035
|
var screenshotIndicatorStyle = {
|
|
1032
1036
|
display: "flex",
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
color: "var(--anyclick-menu-text-muted, #9ca3af)",
|
|
1038
|
-
borderTop: "1px solid var(--anyclick-menu-border, #f3f4f6)",
|
|
1039
|
-
marginTop: "4px"
|
|
1037
|
+
marginLeft: "4px",
|
|
1038
|
+
opacity: 0.7,
|
|
1039
|
+
justifyContent: "flex-end",
|
|
1040
|
+
flex: 1
|
|
1040
1041
|
};
|
|
1041
1042
|
var defaultIcons = {
|
|
1042
1043
|
issue: /* @__PURE__ */ jsx2(Flag, { className: "w-4 h-4" }),
|
|
1043
1044
|
feature: /* @__PURE__ */ jsx2(Plus, { className: "w-4 h-4" }),
|
|
1044
1045
|
like: /* @__PURE__ */ jsx2(ThumbsUp, { className: "w-4 h-4" })
|
|
1045
1046
|
};
|
|
1047
|
+
var DefaultHeader = ({
|
|
1048
|
+
styles,
|
|
1049
|
+
className,
|
|
1050
|
+
title = "Send Feedback",
|
|
1051
|
+
children
|
|
1052
|
+
}) => {
|
|
1053
|
+
return /* @__PURE__ */ jsxs2("div", { style: styles, className, children: [
|
|
1054
|
+
/* @__PURE__ */ jsx2("span", { children: title }),
|
|
1055
|
+
children
|
|
1056
|
+
] });
|
|
1057
|
+
};
|
|
1046
1058
|
function MenuItem({
|
|
1047
1059
|
item,
|
|
1048
1060
|
onClick,
|
|
@@ -1220,7 +1232,9 @@ function ContextMenu({
|
|
|
1220
1232
|
className,
|
|
1221
1233
|
highlightConfig,
|
|
1222
1234
|
screenshotConfig,
|
|
1223
|
-
positionMode = "inView"
|
|
1235
|
+
positionMode = "inView",
|
|
1236
|
+
header,
|
|
1237
|
+
footer
|
|
1224
1238
|
}) {
|
|
1225
1239
|
const [selectedType, setSelectedType] = useState2(null);
|
|
1226
1240
|
const [currentView, setCurrentView] = useState2("menu");
|
|
@@ -1409,11 +1423,24 @@ function ContextMenu({
|
|
|
1409
1423
|
if (!visible || !targetElement) {
|
|
1410
1424
|
return null;
|
|
1411
1425
|
}
|
|
1412
|
-
const handleItemClick = (item) => {
|
|
1426
|
+
const handleItemClick = async (item) => {
|
|
1413
1427
|
if (item.children && item.children.length > 0) {
|
|
1414
1428
|
setSubmenuStack((prev) => [...prev, item.children]);
|
|
1415
1429
|
return;
|
|
1416
1430
|
}
|
|
1431
|
+
if (item.onClick) {
|
|
1432
|
+
try {
|
|
1433
|
+
const result = await item.onClick({
|
|
1434
|
+
targetElement,
|
|
1435
|
+
containerElement,
|
|
1436
|
+
closeMenu: onClose
|
|
1437
|
+
});
|
|
1438
|
+
return result;
|
|
1439
|
+
} catch (error) {
|
|
1440
|
+
console.error("Anyclick menu onClick error:", error);
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1417
1444
|
if (item.showComment) {
|
|
1418
1445
|
setSelectedType(item.type);
|
|
1419
1446
|
setCurrentView("comment");
|
|
@@ -1494,45 +1521,35 @@ function ContextMenu({
|
|
|
1494
1521
|
role: "menu",
|
|
1495
1522
|
"aria-label": "Feedback options",
|
|
1496
1523
|
children: [
|
|
1497
|
-
currentView !== "screenshot-preview" && /* @__PURE__ */ jsxs2(
|
|
1498
|
-
"div",
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
"
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
onMouseLeave: (e) => {
|
|
1527
|
-
e.currentTarget.style.opacity = "0.5";
|
|
1528
|
-
},
|
|
1529
|
-
title: "Drag to move",
|
|
1530
|
-
children: /* @__PURE__ */ jsx2(GripVertical, { className: "w-4 h-4" })
|
|
1531
|
-
}
|
|
1532
|
-
)
|
|
1533
|
-
]
|
|
1534
|
-
}
|
|
1535
|
-
),
|
|
1524
|
+
!header && currentView !== "screenshot-preview" && /* @__PURE__ */ jsxs2(DefaultHeader, { styles: menuStyles.header, title: "Send Feedback", children: [
|
|
1525
|
+
showPreview && /* @__PURE__ */ jsx2("div", { style: screenshotIndicatorStyle, children: /* @__PURE__ */ jsx2(Camera, { className: "w-3 h-3" }) }),
|
|
1526
|
+
positionMode === "dynamic" && /* @__PURE__ */ jsx2(
|
|
1527
|
+
"div",
|
|
1528
|
+
{
|
|
1529
|
+
"data-drag-handle": true,
|
|
1530
|
+
onPointerDown: handleDragStart,
|
|
1531
|
+
style: {
|
|
1532
|
+
cursor: isDragging ? "grabbing" : "grab",
|
|
1533
|
+
padding: "4px",
|
|
1534
|
+
marginRight: "-4px",
|
|
1535
|
+
borderRadius: "4px",
|
|
1536
|
+
display: "flex",
|
|
1537
|
+
alignItems: "center",
|
|
1538
|
+
opacity: 0.5,
|
|
1539
|
+
transition: "opacity 0.15s"
|
|
1540
|
+
},
|
|
1541
|
+
onMouseEnter: (e) => {
|
|
1542
|
+
e.currentTarget.style.opacity = "1";
|
|
1543
|
+
},
|
|
1544
|
+
onMouseLeave: (e) => {
|
|
1545
|
+
e.currentTarget.style.opacity = "0.5";
|
|
1546
|
+
},
|
|
1547
|
+
title: "Drag to move",
|
|
1548
|
+
children: /* @__PURE__ */ jsx2(GripVertical, { className: "w-4 h-4" })
|
|
1549
|
+
}
|
|
1550
|
+
)
|
|
1551
|
+
] }),
|
|
1552
|
+
!!header && header,
|
|
1536
1553
|
currentView === "menu" && /* @__PURE__ */ jsxs2("div", { style: menuStyles.itemList, children: [
|
|
1537
1554
|
submenuStack.length > 0 && /* @__PURE__ */ jsx2(BackButton, { onClick: handleBack }),
|
|
1538
1555
|
currentItems.map((item) => /* @__PURE__ */ jsx2(
|
|
@@ -1544,11 +1561,7 @@ function ContextMenu({
|
|
|
1544
1561
|
hasChildren: item.children && item.children.length > 0
|
|
1545
1562
|
},
|
|
1546
1563
|
item.type
|
|
1547
|
-
))
|
|
1548
|
-
showPreview && /* @__PURE__ */ jsxs2("div", { style: screenshotIndicatorStyle, children: [
|
|
1549
|
-
/* @__PURE__ */ jsx2(Camera, { className: "w-3 h-3" }),
|
|
1550
|
-
/* @__PURE__ */ jsx2("span", { children: "Screenshots will be captured" })
|
|
1551
|
-
] })
|
|
1564
|
+
))
|
|
1552
1565
|
] }),
|
|
1553
1566
|
currentView === "comment" && /* @__PURE__ */ jsx2(
|
|
1554
1567
|
CommentForm,
|
|
@@ -1786,6 +1799,7 @@ function AnyclickProvider({
|
|
|
1786
1799
|
menuClassName,
|
|
1787
1800
|
disabled = false,
|
|
1788
1801
|
highlightConfig,
|
|
1802
|
+
header,
|
|
1789
1803
|
screenshotConfig,
|
|
1790
1804
|
scoped = false,
|
|
1791
1805
|
theme,
|
|
@@ -1996,7 +2010,7 @@ function AnyclickProvider({
|
|
|
1996
2010
|
localThemeColors: localTheme.highlightConfig?.colors
|
|
1997
2011
|
});
|
|
1998
2012
|
}
|
|
1999
|
-
const client =
|
|
2013
|
+
const client = createAnyclickClient({
|
|
2000
2014
|
adapter,
|
|
2001
2015
|
targetFilter,
|
|
2002
2016
|
maxInnerTextLength,
|
|
@@ -2038,13 +2052,13 @@ function AnyclickProvider({
|
|
|
2038
2052
|
touchHoldDurationMs,
|
|
2039
2053
|
touchMoveThreshold
|
|
2040
2054
|
]);
|
|
2041
|
-
const
|
|
2055
|
+
const submitAnyclick = useCallback2(
|
|
2042
2056
|
async (element, type, comment, screenshots) => {
|
|
2043
2057
|
const client = clientRef.current;
|
|
2044
2058
|
if (!client) return;
|
|
2045
2059
|
setIsSubmitting(true);
|
|
2046
2060
|
try {
|
|
2047
|
-
await client.
|
|
2061
|
+
await client.submitAnyclick(element, type, {
|
|
2048
2062
|
comment,
|
|
2049
2063
|
metadata,
|
|
2050
2064
|
screenshots
|
|
@@ -2080,10 +2094,10 @@ function AnyclickProvider({
|
|
|
2080
2094
|
const handleMenuSelect = useCallback2(
|
|
2081
2095
|
(type, comment, screenshots) => {
|
|
2082
2096
|
if (targetElement) {
|
|
2083
|
-
|
|
2097
|
+
submitAnyclick(targetElement, type, comment, screenshots);
|
|
2084
2098
|
}
|
|
2085
2099
|
},
|
|
2086
|
-
[targetElement,
|
|
2100
|
+
[targetElement, submitAnyclick]
|
|
2087
2101
|
);
|
|
2088
2102
|
const inheritedTheme = getMergedTheme(providerId);
|
|
2089
2103
|
const mergedTheme = useMemo(
|
|
@@ -2126,7 +2140,7 @@ function AnyclickProvider({
|
|
|
2126
2140
|
() => ({
|
|
2127
2141
|
isEnabled: !effectiveDisabled && !isDisabledByAncestor(providerId),
|
|
2128
2142
|
isSubmitting,
|
|
2129
|
-
|
|
2143
|
+
submitAnyclick,
|
|
2130
2144
|
openMenu,
|
|
2131
2145
|
closeMenu,
|
|
2132
2146
|
theme: mergedTheme,
|
|
@@ -2138,7 +2152,7 @@ function AnyclickProvider({
|
|
|
2138
2152
|
providerId,
|
|
2139
2153
|
isDisabledByAncestor,
|
|
2140
2154
|
isSubmitting,
|
|
2141
|
-
|
|
2155
|
+
submitAnyclick,
|
|
2142
2156
|
openMenu,
|
|
2143
2157
|
closeMenu,
|
|
2144
2158
|
mergedTheme,
|
|
@@ -2162,13 +2176,109 @@ function AnyclickProvider({
|
|
|
2162
2176
|
style: effectiveMenuStyle,
|
|
2163
2177
|
className: effectiveMenuClassName,
|
|
2164
2178
|
highlightConfig: effectiveHighlightConfig,
|
|
2165
|
-
screenshotConfig: effectiveScreenshotConfig
|
|
2179
|
+
screenshotConfig: effectiveScreenshotConfig,
|
|
2180
|
+
header
|
|
2166
2181
|
}
|
|
2167
2182
|
)
|
|
2168
2183
|
] });
|
|
2169
2184
|
}
|
|
2170
2185
|
var FeedbackProvider = AnyclickProvider;
|
|
2171
2186
|
|
|
2187
|
+
// src/FunModeBridge.tsx
|
|
2188
|
+
import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3 } from "react";
|
|
2189
|
+
import {
|
|
2190
|
+
usePointer
|
|
2191
|
+
} from "@ewjdev/anyclick-pointer";
|
|
2192
|
+
function isFunModeEnabled(theme) {
|
|
2193
|
+
if (!theme) return false;
|
|
2194
|
+
if (theme.funMode === void 0) return false;
|
|
2195
|
+
if (typeof theme.funMode === "boolean") return theme.funMode;
|
|
2196
|
+
return theme.funMode.enabled ?? true;
|
|
2197
|
+
}
|
|
2198
|
+
function buildFunConfig(theme, container) {
|
|
2199
|
+
const funTheme = typeof theme?.funMode === "object" ? theme.funMode : {};
|
|
2200
|
+
const resolveTrackElement = () => {
|
|
2201
|
+
let el = container;
|
|
2202
|
+
while (el) {
|
|
2203
|
+
const rect = el.getBoundingClientRect();
|
|
2204
|
+
if (rect.width > 0 && rect.height > 0) {
|
|
2205
|
+
return el;
|
|
2206
|
+
}
|
|
2207
|
+
el = el.parentElement;
|
|
2208
|
+
}
|
|
2209
|
+
return document.body;
|
|
2210
|
+
};
|
|
2211
|
+
const getTrackElement = () => resolveTrackElement();
|
|
2212
|
+
return {
|
|
2213
|
+
maxSpeed: funTheme.maxSpeed,
|
|
2214
|
+
acceleration: funTheme.acceleration,
|
|
2215
|
+
getTrackElement,
|
|
2216
|
+
getObstacles: () => {
|
|
2217
|
+
const trackElement = getTrackElement();
|
|
2218
|
+
const obstacles = [];
|
|
2219
|
+
const parent = trackElement.parentElement;
|
|
2220
|
+
if (parent) {
|
|
2221
|
+
Array.from(parent.children).forEach((sibling) => {
|
|
2222
|
+
if (sibling !== trackElement) {
|
|
2223
|
+
obstacles.push(sibling.getBoundingClientRect());
|
|
2224
|
+
}
|
|
2225
|
+
});
|
|
2226
|
+
}
|
|
2227
|
+
Array.from(trackElement.children).forEach((child) => {
|
|
2228
|
+
obstacles.push(child.getBoundingClientRect());
|
|
2229
|
+
});
|
|
2230
|
+
return obstacles;
|
|
2231
|
+
}
|
|
2232
|
+
};
|
|
2233
|
+
}
|
|
2234
|
+
function FunModeBridge() {
|
|
2235
|
+
const { setConfig } = usePointer();
|
|
2236
|
+
const providerStore = useProviderStore();
|
|
2237
|
+
const activeProviderRef = useRef3(null);
|
|
2238
|
+
const cachedConfigs = useRef3({});
|
|
2239
|
+
const findActiveFunProvider = useMemo2(() => {
|
|
2240
|
+
return (el) => {
|
|
2241
|
+
if (!el) return null;
|
|
2242
|
+
const providers = providerStore.findProvidersForElement(el);
|
|
2243
|
+
for (const provider of providers) {
|
|
2244
|
+
if (provider.scoped && !provider.disabled && isFunModeEnabled(provider.theme)) {
|
|
2245
|
+
return provider;
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
return null;
|
|
2249
|
+
};
|
|
2250
|
+
}, [providerStore]);
|
|
2251
|
+
useEffect3(() => {
|
|
2252
|
+
const handleMove = (event) => {
|
|
2253
|
+
const el = document.elementFromPoint(event.clientX, event.clientY);
|
|
2254
|
+
const provider = findActiveFunProvider(el);
|
|
2255
|
+
if (!provider || !provider.containerRef.current) {
|
|
2256
|
+
if (activeProviderRef.current !== null) {
|
|
2257
|
+
activeProviderRef.current = null;
|
|
2258
|
+
setConfig({ mode: "normal" });
|
|
2259
|
+
}
|
|
2260
|
+
return;
|
|
2261
|
+
}
|
|
2262
|
+
if (activeProviderRef.current === provider.id) {
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
activeProviderRef.current = provider.id;
|
|
2266
|
+
if (!cachedConfigs.current[provider.id]) {
|
|
2267
|
+
cachedConfigs.current[provider.id] = {
|
|
2268
|
+
mode: "fun",
|
|
2269
|
+
funConfig: buildFunConfig(provider.theme, provider.containerRef.current)
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
2272
|
+
setConfig(cachedConfigs.current[provider.id]);
|
|
2273
|
+
};
|
|
2274
|
+
window.addEventListener("pointermove", handleMove, { passive: true });
|
|
2275
|
+
return () => {
|
|
2276
|
+
window.removeEventListener("pointermove", handleMove);
|
|
2277
|
+
};
|
|
2278
|
+
}, [findActiveFunProvider, setConfig]);
|
|
2279
|
+
return null;
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2172
2282
|
// src/types.ts
|
|
2173
2283
|
function filterMenuItemsByRole(items, userContext) {
|
|
2174
2284
|
if (!userContext) {
|
|
@@ -2203,6 +2313,7 @@ export {
|
|
|
2203
2313
|
DEFAULT_SENSITIVE_SELECTORS,
|
|
2204
2314
|
FeedbackContext,
|
|
2205
2315
|
FeedbackProvider,
|
|
2316
|
+
FunModeBridge,
|
|
2206
2317
|
ScreenshotPreview,
|
|
2207
2318
|
applyHighlights,
|
|
2208
2319
|
captureAllScreenshots2 as captureAllScreenshots,
|