@howone/sdk 0.1.27 → 0.1.28
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 +54 -1
- package/dist/index.d.ts +54 -1
- package/dist/index.js +1059 -827
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1055 -827
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -239,6 +239,8 @@ __export(index_exports, {
|
|
|
239
239
|
DEFAULT_SELECTOR_CONFIG: () => DEFAULT_SELECTOR_CONFIG,
|
|
240
240
|
DefaultErrorFallback: () => DefaultErrorFallback,
|
|
241
241
|
ERROR_CONFIG: () => ERROR_CONFIG,
|
|
242
|
+
ElementSelector: () => ElementSelector,
|
|
243
|
+
ElementSelectorProvider: () => ElementSelectorProvider,
|
|
242
244
|
ErrorBoundary: () => ErrorBoundary,
|
|
243
245
|
ErrorHandler: () => ErrorHandler,
|
|
244
246
|
FloatingButton: () => FloatingButton,
|
|
@@ -268,6 +270,7 @@ __export(index_exports, {
|
|
|
268
270
|
onAuthStateChanged: () => onAuthStateChanged,
|
|
269
271
|
parseUserFromToken: () => parseUserFromToken,
|
|
270
272
|
request: () => request,
|
|
273
|
+
sendElementSelectionToParent: () => sendElementSelectionToParent,
|
|
271
274
|
sendEmailVerificationCode: () => sendEmailVerificationCode,
|
|
272
275
|
setAuthRoot: () => setAuthRoot,
|
|
273
276
|
setDefaultProjectId: () => setDefaultProjectId,
|
|
@@ -276,6 +279,7 @@ __export(index_exports, {
|
|
|
276
279
|
unifiedOAuth: () => unifiedOAuth,
|
|
277
280
|
useAuth: () => useAuth,
|
|
278
281
|
useDebounce: () => useDebounce,
|
|
282
|
+
useElementSelector: () => useElementSelector,
|
|
279
283
|
useHowoneContext: () => useHowoneContext,
|
|
280
284
|
useIsMobile: () => useIsMobile,
|
|
281
285
|
useTheme: () => useTheme,
|
|
@@ -1581,7 +1585,7 @@ var LoginForm = ({
|
|
|
1581
1585
|
};
|
|
1582
1586
|
|
|
1583
1587
|
// src/components/auth/HowoneProvider.tsx
|
|
1584
|
-
var
|
|
1588
|
+
var import_react8 = require("react");
|
|
1585
1589
|
init_auth();
|
|
1586
1590
|
|
|
1587
1591
|
// src/components/theme/ThemeProvider.tsx
|
|
@@ -1650,869 +1654,444 @@ function GlobalToastContainer() {
|
|
|
1650
1654
|
);
|
|
1651
1655
|
}
|
|
1652
1656
|
|
|
1653
|
-
// src/components/
|
|
1657
|
+
// src/components/ElementSelectorProvider.tsx
|
|
1658
|
+
var import_react7 = require("react");
|
|
1659
|
+
|
|
1660
|
+
// src/components/ElementSelector.tsx
|
|
1661
|
+
var import_react5 = require("react");
|
|
1654
1662
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1655
|
-
var
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
projectId,
|
|
1660
|
-
defaultTheme = "system",
|
|
1661
|
-
themeStorageKey = "howone-theme",
|
|
1662
|
-
forceDefaultTheme = false,
|
|
1663
|
-
authUrl = "https://howone.dev/auth",
|
|
1664
|
-
redirectOnUnauthenticated = true
|
|
1663
|
+
var ElementSelector = ({
|
|
1664
|
+
active,
|
|
1665
|
+
onSelect,
|
|
1666
|
+
onCancel
|
|
1665
1667
|
}) => {
|
|
1666
|
-
const [
|
|
1667
|
-
const [
|
|
1668
|
-
const
|
|
1669
|
-
(0, import_react5.
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
if (
|
|
1674
|
-
const hashParams = new URLSearchParams(window.location.hash.slice(1));
|
|
1675
|
-
urlToken = hashParams.get("access_token") || hashParams.get("token");
|
|
1676
|
-
}
|
|
1677
|
-
if (urlToken) {
|
|
1678
|
-
console.log("[HowOneProvider] Token captured from URL, storing to localStorage...");
|
|
1679
|
-
setToken(urlToken);
|
|
1680
|
-
setTokenState(urlToken);
|
|
1681
|
-
setUser(parseUserFromToken(urlToken));
|
|
1682
|
-
params.delete("access_token");
|
|
1683
|
-
params.delete("token");
|
|
1684
|
-
params.delete("project_id");
|
|
1685
|
-
const newSearch = params.toString();
|
|
1686
|
-
const newUrl = window.location.pathname + (newSearch ? "?" + newSearch : "");
|
|
1687
|
-
window.history.replaceState({}, "", newUrl);
|
|
1688
|
-
console.log("[HowOneProvider] Token stored successfully, URL cleaned");
|
|
1689
|
-
}
|
|
1690
|
-
} catch (e) {
|
|
1691
|
-
console.error("[HowOneProvider] Failed to capture token from URL:", e);
|
|
1692
|
-
} finally {
|
|
1693
|
-
setHasCheckedUrlToken(true);
|
|
1694
|
-
}
|
|
1695
|
-
}, []);
|
|
1696
|
-
(0, import_react5.useEffect)(() => {
|
|
1697
|
-
if (!hasCheckedUrlToken) {
|
|
1698
|
-
return;
|
|
1699
|
-
}
|
|
1700
|
-
if (redirectOnUnauthenticated && !token && !user) {
|
|
1701
|
-
const currentUrl = new URL(window.location.href);
|
|
1702
|
-
if (!currentUrl.pathname.includes("/auth")) {
|
|
1703
|
-
console.log("[HowOneProvider] No token found, redirecting to auth page...");
|
|
1668
|
+
const [hoveredElement, setHoveredElement] = (0, import_react5.useState)(null);
|
|
1669
|
+
const [highlightRect, setHighlightRect] = (0, import_react5.useState)(null);
|
|
1670
|
+
const overlayRef = (0, import_react5.useRef)(null);
|
|
1671
|
+
const getSourceLocation = (0, import_react5.useCallback)((element) => {
|
|
1672
|
+
let current = element;
|
|
1673
|
+
while (current && current !== document.body) {
|
|
1674
|
+
const sourceLocationAttr = current.getAttribute("data-source-location");
|
|
1675
|
+
if (sourceLocationAttr) {
|
|
1704
1676
|
try {
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
if (projectId) {
|
|
1709
|
-
authUrlObj.searchParams.set("project_id", projectId);
|
|
1710
|
-
}
|
|
1711
|
-
console.log("[HowOneProvider] Redirecting to:", authUrlObj.toString());
|
|
1712
|
-
window.location.href = authUrlObj.toString();
|
|
1713
|
-
} catch (error) {
|
|
1714
|
-
console.error("[HowOneProvider] Failed to build auth URL:", error);
|
|
1715
|
-
window.location.href = authUrl;
|
|
1677
|
+
return JSON.parse(sourceLocationAttr.replace(/"/g, '"'));
|
|
1678
|
+
} catch (e) {
|
|
1679
|
+
console.error("Failed to parse source location:", e);
|
|
1716
1680
|
}
|
|
1717
1681
|
}
|
|
1682
|
+
current = current.parentElement;
|
|
1718
1683
|
}
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
if (!ctx) {
|
|
1753
|
-
const t = getToken();
|
|
1754
|
-
return {
|
|
1755
|
-
user: parseUserFromToken(t),
|
|
1756
|
-
token: t,
|
|
1757
|
-
isAuthenticated: !!t,
|
|
1758
|
-
logout: () => {
|
|
1759
|
-
try {
|
|
1760
|
-
setToken(null);
|
|
1761
|
-
} catch {
|
|
1762
|
-
}
|
|
1684
|
+
return null;
|
|
1685
|
+
}, []);
|
|
1686
|
+
const handleMouseMove = (0, import_react5.useCallback)((e) => {
|
|
1687
|
+
if (!active) return;
|
|
1688
|
+
const elements = document.elementsFromPoint(e.clientX, e.clientY);
|
|
1689
|
+
const targetElement = elements.find(
|
|
1690
|
+
(el) => el !== overlayRef.current && !overlayRef.current?.contains(el) && el !== document.body && el !== document.documentElement
|
|
1691
|
+
);
|
|
1692
|
+
if (targetElement && targetElement !== hoveredElement) {
|
|
1693
|
+
setHoveredElement(targetElement);
|
|
1694
|
+
const rect = targetElement.getBoundingClientRect();
|
|
1695
|
+
setHighlightRect(rect);
|
|
1696
|
+
}
|
|
1697
|
+
}, [active, hoveredElement]);
|
|
1698
|
+
const handleClick = (0, import_react5.useCallback)((e) => {
|
|
1699
|
+
if (!active || !hoveredElement) return;
|
|
1700
|
+
e.preventDefault();
|
|
1701
|
+
e.stopPropagation();
|
|
1702
|
+
const sourceLocation = getSourceLocation(hoveredElement);
|
|
1703
|
+
const rect = hoveredElement.getBoundingClientRect();
|
|
1704
|
+
const elementData = {
|
|
1705
|
+
sourceLocation,
|
|
1706
|
+
element: {
|
|
1707
|
+
tagName: hoveredElement.tagName,
|
|
1708
|
+
className: hoveredElement.className,
|
|
1709
|
+
id: hoveredElement.id,
|
|
1710
|
+
text: hoveredElement.textContent?.substring(0, 100) || ""
|
|
1711
|
+
},
|
|
1712
|
+
rect: {
|
|
1713
|
+
top: rect.top,
|
|
1714
|
+
left: rect.left,
|
|
1715
|
+
width: rect.width,
|
|
1716
|
+
height: rect.height
|
|
1763
1717
|
}
|
|
1764
1718
|
};
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
// src/components/index.ts
|
|
1770
|
-
init_auth();
|
|
1771
|
-
|
|
1772
|
-
// src/howone/client.ts
|
|
1773
|
-
init_auth();
|
|
1774
|
-
init_config();
|
|
1775
|
-
var HowoneAuthClient = class {
|
|
1776
|
-
constructor() {
|
|
1777
|
-
this.listeners = /* @__PURE__ */ new Set();
|
|
1778
|
-
this.loading = false;
|
|
1779
|
-
}
|
|
1780
|
-
emit() {
|
|
1781
|
-
const state = {
|
|
1782
|
-
user: parseUserFromToken(getToken()),
|
|
1783
|
-
isLoading: this.loading
|
|
1784
|
-
};
|
|
1785
|
-
for (const l of this.listeners) {
|
|
1786
|
-
try {
|
|
1787
|
-
l(state);
|
|
1788
|
-
} catch (e) {
|
|
1789
|
-
void e;
|
|
1719
|
+
if (onSelect) {
|
|
1720
|
+
onSelect(elementData);
|
|
1721
|
+
if (onCancel) {
|
|
1722
|
+
onCancel();
|
|
1790
1723
|
}
|
|
1791
1724
|
}
|
|
1792
|
-
}
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1725
|
+
}, [active, hoveredElement, getSourceLocation, onSelect, onCancel]);
|
|
1726
|
+
(0, import_react5.useEffect)(() => {
|
|
1727
|
+
if (active) {
|
|
1728
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
1729
|
+
document.addEventListener("click", handleClick, true);
|
|
1730
|
+
document.body.style.overflow = "hidden";
|
|
1731
|
+
return () => {
|
|
1732
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
1733
|
+
document.removeEventListener("click", handleClick, true);
|
|
1734
|
+
document.body.style.overflow = "";
|
|
1735
|
+
};
|
|
1736
|
+
} else {
|
|
1737
|
+
setHoveredElement(null);
|
|
1738
|
+
setHighlightRect(null);
|
|
1799
1739
|
}
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
try {
|
|
1818
|
-
if (window.top && window.top !== window) {
|
|
1819
|
-
window.top.location.replace(authUrl.toString());
|
|
1820
|
-
} else {
|
|
1821
|
-
window.location.replace(authUrl.toString());
|
|
1740
|
+
}, [active, handleMouseMove, handleClick]);
|
|
1741
|
+
if (!active) return null;
|
|
1742
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1743
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1744
|
+
"div",
|
|
1745
|
+
{
|
|
1746
|
+
ref: overlayRef,
|
|
1747
|
+
style: {
|
|
1748
|
+
position: "fixed",
|
|
1749
|
+
top: 0,
|
|
1750
|
+
left: 0,
|
|
1751
|
+
right: 0,
|
|
1752
|
+
bottom: 0,
|
|
1753
|
+
backgroundColor: "rgba(0, 0, 0, 0.3)",
|
|
1754
|
+
zIndex: 999998,
|
|
1755
|
+
cursor: "crosshair",
|
|
1756
|
+
pointerEvents: "none"
|
|
1822
1757
|
}
|
|
1823
|
-
}
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1758
|
+
}
|
|
1759
|
+
),
|
|
1760
|
+
highlightRect && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1761
|
+
"div",
|
|
1762
|
+
{
|
|
1763
|
+
style: {
|
|
1764
|
+
position: "fixed",
|
|
1765
|
+
top: highlightRect.top,
|
|
1766
|
+
left: highlightRect.left,
|
|
1767
|
+
width: highlightRect.width,
|
|
1768
|
+
height: highlightRect.height,
|
|
1769
|
+
border: "2px dashed #36D2A6",
|
|
1770
|
+
borderRadius: "5px",
|
|
1771
|
+
backgroundColor: "rgba(54, 210, 166, 0.1)",
|
|
1772
|
+
zIndex: 999999,
|
|
1773
|
+
pointerEvents: "none",
|
|
1774
|
+
transition: "all 0.1s ease"
|
|
1827
1775
|
}
|
|
1828
1776
|
}
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1777
|
+
),
|
|
1778
|
+
hoveredElement && highlightRect && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1779
|
+
"div",
|
|
1780
|
+
{
|
|
1781
|
+
style: {
|
|
1782
|
+
position: "fixed",
|
|
1783
|
+
top: highlightRect.top - 30,
|
|
1784
|
+
left: highlightRect.left,
|
|
1785
|
+
backgroundColor: "#36D2A6",
|
|
1786
|
+
color: "white",
|
|
1787
|
+
padding: "4px 8px",
|
|
1788
|
+
borderRadius: "4px",
|
|
1789
|
+
fontSize: "12px",
|
|
1790
|
+
zIndex: 1e6,
|
|
1791
|
+
pointerEvents: "none",
|
|
1792
|
+
whiteSpace: "nowrap"
|
|
1793
|
+
},
|
|
1794
|
+
children: (() => {
|
|
1795
|
+
const location = getSourceLocation(hoveredElement);
|
|
1796
|
+
return location ? `${location.component} (${location.file}:${location.line})` : hoveredElement.tagName.toLowerCase();
|
|
1797
|
+
})()
|
|
1833
1798
|
}
|
|
1834
|
-
|
|
1835
|
-
}
|
|
1836
|
-
logout() {
|
|
1837
|
-
setToken(null);
|
|
1838
|
-
this.emit();
|
|
1839
|
-
}
|
|
1840
|
-
getUser() {
|
|
1841
|
-
return parseUserFromToken(getToken());
|
|
1842
|
-
}
|
|
1843
|
-
// helper to programmatically set token (e.g., after callback handling)
|
|
1844
|
-
setToken(token) {
|
|
1845
|
-
setToken(token);
|
|
1846
|
-
this.emit();
|
|
1847
|
-
}
|
|
1848
|
-
};
|
|
1849
|
-
var howone = {
|
|
1850
|
-
auth: new HowoneAuthClient()
|
|
1799
|
+
)
|
|
1800
|
+
] });
|
|
1851
1801
|
};
|
|
1852
|
-
var client_default = howone;
|
|
1853
1802
|
|
|
1854
|
-
// src/
|
|
1855
|
-
var
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
})
|
|
1862
|
-
const
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1803
|
+
// src/hooks/use-element-selector.ts
|
|
1804
|
+
var import_react6 = require("react");
|
|
1805
|
+
function useElementSelector() {
|
|
1806
|
+
const [isSelecting, setIsSelecting] = (0, import_react6.useState)(false);
|
|
1807
|
+
const [selectedElement, setSelectedElement] = (0, import_react6.useState)(null);
|
|
1808
|
+
const startSelecting = (0, import_react6.useCallback)(() => {
|
|
1809
|
+
setIsSelecting(true);
|
|
1810
|
+
}, []);
|
|
1811
|
+
const stopSelecting = (0, import_react6.useCallback)(() => {
|
|
1812
|
+
setIsSelecting(false);
|
|
1813
|
+
}, []);
|
|
1814
|
+
const clearSelection = (0, import_react6.useCallback)(() => {
|
|
1815
|
+
setSelectedElement(null);
|
|
1816
|
+
}, []);
|
|
1817
|
+
return {
|
|
1818
|
+
isSelecting,
|
|
1819
|
+
selectedElement,
|
|
1820
|
+
startSelecting,
|
|
1821
|
+
stopSelecting,
|
|
1822
|
+
clearSelection
|
|
1866
1823
|
};
|
|
1867
|
-
|
|
1868
|
-
|
|
1824
|
+
}
|
|
1825
|
+
function sendElementSelectionToParent(data) {
|
|
1826
|
+
if (window.parent && window.parent !== window) {
|
|
1827
|
+
window.parent.postMessage({
|
|
1828
|
+
type: "ELEMENT_SELECTED",
|
|
1829
|
+
payload: data
|
|
1830
|
+
}, "*");
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
// src/components/ElementSelectorProvider.tsx
|
|
1835
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1836
|
+
var ElementSelectorProvider = ({ children }) => {
|
|
1837
|
+
const [isSelecting, setIsSelecting] = (0, import_react7.useState)(false);
|
|
1838
|
+
const handleCancel = (0, import_react7.useCallback)(() => {
|
|
1839
|
+
setIsSelecting(false);
|
|
1840
|
+
if (window.parent && window.parent !== window) {
|
|
1841
|
+
window.parent.postMessage({
|
|
1842
|
+
type: "ELEMENT_SELECTION_CANCELLED"
|
|
1843
|
+
}, "*");
|
|
1844
|
+
}
|
|
1845
|
+
console.log("\u{1F6AB} \u5143\u7D20\u9009\u62E9\u5DF2\u53D6\u6D88 (ESC)");
|
|
1846
|
+
}, []);
|
|
1847
|
+
const handleSelect = (0, import_react7.useCallback)((data) => {
|
|
1848
|
+
sendElementSelectionToParent(data);
|
|
1849
|
+
console.log("\u{1F3AF} \u5143\u7D20\u5DF2\u9009\u4E2D:", data.element.tagName, data.sourceLocation?.file);
|
|
1850
|
+
}, []);
|
|
1851
|
+
(0, import_react7.useEffect)(() => {
|
|
1852
|
+
const handleStartSelection = () => {
|
|
1853
|
+
setIsSelecting(true);
|
|
1854
|
+
};
|
|
1855
|
+
const handleCancelSelection = () => {
|
|
1856
|
+
handleCancel();
|
|
1857
|
+
};
|
|
1858
|
+
window.addEventListener("howone:start-element-selection", handleStartSelection);
|
|
1859
|
+
window.addEventListener("howone:cancel-element-selection", handleCancelSelection);
|
|
1860
|
+
const handleMessage = (event) => {
|
|
1861
|
+
if (event.data.type === "START_ELEMENT_SELECTION") {
|
|
1862
|
+
setIsSelecting(true);
|
|
1863
|
+
} else if (event.data.type === "CANCEL_ELEMENT_SELECTION") {
|
|
1864
|
+
handleCancel();
|
|
1865
|
+
}
|
|
1866
|
+
};
|
|
1867
|
+
window.addEventListener("message", handleMessage);
|
|
1868
|
+
return () => {
|
|
1869
|
+
window.removeEventListener("howone:start-element-selection", handleStartSelection);
|
|
1870
|
+
window.removeEventListener("howone:cancel-element-selection", handleCancelSelection);
|
|
1871
|
+
window.removeEventListener("message", handleMessage);
|
|
1872
|
+
};
|
|
1873
|
+
}, [handleCancel]);
|
|
1874
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1875
|
+
children,
|
|
1869
1876
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1870
|
-
|
|
1877
|
+
ElementSelector,
|
|
1871
1878
|
{
|
|
1872
|
-
|
|
1879
|
+
active: isSelecting,
|
|
1880
|
+
onSelect: handleSelect,
|
|
1881
|
+
onCancel: handleCancel
|
|
1873
1882
|
}
|
|
1874
|
-
)
|
|
1875
|
-
|
|
1876
|
-
] }) });
|
|
1877
|
-
};
|
|
1878
|
-
var LoadingSpinner = ({
|
|
1879
|
-
size = "md",
|
|
1880
|
-
className = ""
|
|
1881
|
-
}) => {
|
|
1882
|
-
const sizeClasses = {
|
|
1883
|
-
sm: "h-4 w-4",
|
|
1884
|
-
md: "h-8 w-8",
|
|
1885
|
-
lg: "h-12 w-12"
|
|
1886
|
-
};
|
|
1887
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1888
|
-
"div",
|
|
1889
|
-
{
|
|
1890
|
-
className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 ${sizeClasses[size]} ${className}`
|
|
1891
|
-
}
|
|
1892
|
-
);
|
|
1883
|
+
)
|
|
1884
|
+
] });
|
|
1893
1885
|
};
|
|
1894
1886
|
|
|
1895
|
-
// src/
|
|
1896
|
-
var
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1887
|
+
// src/utils/unified-error-handler/types.ts
|
|
1888
|
+
var ERROR_CONFIG = {
|
|
1889
|
+
MAX_ERRORS: 100,
|
|
1890
|
+
MAX_INTERACTIONS: 50,
|
|
1891
|
+
DEDUP_WINDOW: 1e3,
|
|
1892
|
+
DEBOUNCE_TIME: 100,
|
|
1893
|
+
CACHE_DURATION: 3e5,
|
|
1894
|
+
SEVERITY_KEYWORDS: {
|
|
1895
|
+
CRITICAL: ["fatal", "critical", "security", "crash", "corruption"],
|
|
1896
|
+
HIGH: ["error", "exception", "failed", "timeout", "network error"],
|
|
1897
|
+
MEDIUM: ["warning", "deprecated", "slow", "performance"],
|
|
1898
|
+
LOW: ["info", "debug", "trace", "notice"]
|
|
1899
|
+
},
|
|
1900
|
+
CATEGORY_KEYWORDS: {
|
|
1901
|
+
SYNTAX: ["syntaxerror", "unexpected token", "parse error", "invalid syntax"],
|
|
1902
|
+
NETWORK: ["fetch", "xhr", "network", "cors", "timeout", "connection"],
|
|
1903
|
+
RUNTIME: ["referenceerror", "typeerror", "rangeerror", "undefined"],
|
|
1904
|
+
SECURITY: ["csp", "xss", "csrf", "security", "unauthorized"],
|
|
1905
|
+
PERFORMANCE: ["slow", "memory", "leak", "performance", "timeout"],
|
|
1906
|
+
DEVELOPMENT: ["vite", "hmr", "hot reload", "dev server", "webpack"],
|
|
1907
|
+
REACT: ["react", "jsx", "component", "hook", "render"],
|
|
1908
|
+
VITE: ["vite", "[vite]", "vite:react", "transform failed"]
|
|
1915
1909
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1910
|
+
};
|
|
1911
|
+
var GLOBAL_CONFIG = {
|
|
1912
|
+
ALLOWED_ORIGINS: [
|
|
1913
|
+
"https://howone.ai",
|
|
1914
|
+
"https://howone.dev",
|
|
1915
|
+
"http://localhost:3000",
|
|
1916
|
+
"http://localhost:5173"
|
|
1917
|
+
],
|
|
1918
|
+
DEBOUNCE_DELAY: 10,
|
|
1919
|
+
OVERRIDE_STYLESHEET_ID: "howone-override-styles"
|
|
1920
|
+
};
|
|
1921
|
+
var DEFAULT_SELECTOR_CONFIG = {
|
|
1922
|
+
HIGHLIGHT_COLOR: "#ff6b6b",
|
|
1923
|
+
HIGHLIGHT_BORDER_WIDTH: "2px",
|
|
1924
|
+
HIGHLIGHT_BORDER_STYLE: "solid",
|
|
1925
|
+
SELECTED_COLOR: "#4ecdc4",
|
|
1926
|
+
SELECTED_BORDER_WIDTH: "3px",
|
|
1927
|
+
TOOLTIP_BACKGROUND: "#333",
|
|
1928
|
+
TOOLTIP_COLOR: "#fff",
|
|
1929
|
+
TOOLTIP_PADDING: "8px 12px",
|
|
1930
|
+
TOOLTIP_BORDER_RADIUS: "4px",
|
|
1931
|
+
TOOLTIP_FONT_SIZE: "12px",
|
|
1932
|
+
TOOLTIP_Z_INDEX: "10000",
|
|
1933
|
+
FULL_WIDTH_TOOLTIP_OFFSET: 10,
|
|
1934
|
+
highlightClass: "howone-highlight",
|
|
1935
|
+
selectedClass: "howone-selected",
|
|
1936
|
+
cursor: "crosshair"
|
|
1937
|
+
};
|
|
1938
|
+
|
|
1939
|
+
// src/utils/unified-error-handler/utils/DeepSerializer.ts
|
|
1940
|
+
var CircularReference = class {
|
|
1941
|
+
constructor(path) {
|
|
1942
|
+
this.message = `[Circular Reference to ${path}]`;
|
|
1938
1943
|
}
|
|
1939
1944
|
};
|
|
1940
|
-
var
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1945
|
+
var TypeWrapper = class {
|
|
1946
|
+
constructor(type, value) {
|
|
1947
|
+
this._type = type;
|
|
1948
|
+
this.value = value;
|
|
1949
|
+
}
|
|
1950
|
+
};
|
|
1951
|
+
var DeepSerializer = class {
|
|
1952
|
+
/**
|
|
1953
|
+
* 深度序列化对象
|
|
1954
|
+
*/
|
|
1955
|
+
static serialize(obj, options = {}, visitedObjects = /* @__PURE__ */ new WeakMap(), path = "root") {
|
|
1956
|
+
const opts = { ...this.DEFAULT_OPTIONS, ...options };
|
|
1957
|
+
if (path.split(".").length > opts.maxDepth) {
|
|
1958
|
+
return new TypeWrapper(
|
|
1959
|
+
"MaxDepthReached",
|
|
1960
|
+
`[Max depth of ${opts.maxDepth} reached]`
|
|
1961
|
+
);
|
|
1949
1962
|
}
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
// src/components/theme/ThemeToggle.tsx
|
|
1954
|
-
var React4 = __toESM(require("react"));
|
|
1955
|
-
var import_react7 = require("@iconify/react");
|
|
1956
|
-
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1957
|
-
function ThemeToggle({ className }) {
|
|
1958
|
-
const { setTheme, theme } = useTheme();
|
|
1959
|
-
const [mounted, setMounted] = React4.useState(false);
|
|
1960
|
-
React4.useEffect(() => {
|
|
1961
|
-
setMounted(true);
|
|
1962
|
-
}, []);
|
|
1963
|
-
const handleToggle = () => {
|
|
1964
|
-
if (theme === "dark") {
|
|
1965
|
-
setTheme("light");
|
|
1966
|
-
} else {
|
|
1967
|
-
setTheme("dark");
|
|
1963
|
+
if (obj === void 0) {
|
|
1964
|
+
return new TypeWrapper("undefined", "undefined");
|
|
1968
1965
|
}
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1972
|
-
"button",
|
|
1973
|
-
{
|
|
1974
|
-
className: `relative inline-flex h-10 w-12 items-center justify-center rounded-md border border-input bg-background hover:bg-accent hover:text-accent-foreground ${className || ""}`,
|
|
1975
|
-
disabled: true,
|
|
1976
|
-
children: [
|
|
1977
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react7.Icon, { icon: "solar:sun-bold", width: 20, height: 20 }),
|
|
1978
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "sr-only", children: "\u5207\u6362\u4E3B\u9898" })
|
|
1979
|
-
]
|
|
1980
|
-
}
|
|
1981
|
-
);
|
|
1982
|
-
}
|
|
1983
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1984
|
-
"button",
|
|
1985
|
-
{
|
|
1986
|
-
className: `inline-flex h-10 w-12 items-center justify-center rounded-md border border-input bg-background hover:bg-accent hover:text-accent-foreground transition-colors ${className || ""}`,
|
|
1987
|
-
onClick: handleToggle,
|
|
1988
|
-
children: [
|
|
1989
|
-
theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react7.Icon, { icon: "solar:sun-bold", width: 20, height: 20 }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react7.Icon, { icon: "solar:moon-linear", width: 20, height: 20 }),
|
|
1990
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "sr-only", children: "\u5207\u6362\u4E3B\u9898" })
|
|
1991
|
-
]
|
|
1966
|
+
if (obj === null) {
|
|
1967
|
+
return null;
|
|
1992
1968
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
var import_react_toastify2 = require("react-toastify");
|
|
1999
|
-
var import_react9 = require("@iconify/react");
|
|
2000
|
-
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2001
|
-
var TOAST_ICONS = {
|
|
2002
|
-
success: {
|
|
2003
|
-
icon: "mdi:success",
|
|
2004
|
-
color: "text-green-400",
|
|
2005
|
-
className: "text-green-400",
|
|
2006
|
-
// 深色主题配置
|
|
2007
|
-
dark: {
|
|
2008
|
-
bgGradient: "bg-[#14181d]",
|
|
2009
|
-
// 移除透明度 f2
|
|
2010
|
-
gradientColor: "#389726",
|
|
2011
|
-
borderGradient: "border-[#389726]",
|
|
2012
|
-
borderGradientColor: "#389726"
|
|
2013
|
-
},
|
|
2014
|
-
// 浅色主题配置
|
|
2015
|
-
light: {
|
|
2016
|
-
bgGradient: "bg-[#fafafa]",
|
|
2017
|
-
// 移除透明度 ff
|
|
2018
|
-
gradientColor: "#22c55e",
|
|
2019
|
-
borderGradient: "border-[#22c55e]",
|
|
2020
|
-
borderGradientColor: "#22c55e"
|
|
1969
|
+
if (typeof obj === "string") {
|
|
1970
|
+
return obj.length > opts.maxStringLength ? new TypeWrapper(
|
|
1971
|
+
"String",
|
|
1972
|
+
`${obj.slice(0, opts.maxStringLength)}... [${obj.length - opts.maxStringLength} more characters]`
|
|
1973
|
+
) : obj;
|
|
2021
1974
|
}
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
icon: "ic:outline-close",
|
|
2025
|
-
color: "text-red-400",
|
|
2026
|
-
className: "text-red-400",
|
|
2027
|
-
dark: {
|
|
2028
|
-
bgGradient: "bg-[#14181d]",
|
|
2029
|
-
// 移除透明度 f2
|
|
2030
|
-
gradientColor: "#ef4444",
|
|
2031
|
-
borderGradient: "border-[#ef4444]",
|
|
2032
|
-
borderGradientColor: "#ef4444"
|
|
2033
|
-
},
|
|
2034
|
-
light: {
|
|
2035
|
-
bgGradient: "bg-[#fafafa]",
|
|
2036
|
-
// 移除透明度 ff
|
|
2037
|
-
gradientColor: "#f87171",
|
|
2038
|
-
borderGradient: "border-[#f87171]",
|
|
2039
|
-
borderGradientColor: "#f87171"
|
|
1975
|
+
if (typeof obj === "number") {
|
|
1976
|
+
return Number.isNaN(obj) ? new TypeWrapper("Number", "NaN") : Number.isFinite(obj) ? obj : new TypeWrapper("Number", obj > 0 ? "Infinity" : "-Infinity");
|
|
2040
1977
|
}
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
icon: "mi:warning",
|
|
2044
|
-
color: "text-yellow-400",
|
|
2045
|
-
className: "text-yellow-400",
|
|
2046
|
-
dark: {
|
|
2047
|
-
bgGradient: "bg-[#14181d]",
|
|
2048
|
-
// 移除透明度 f2
|
|
2049
|
-
gradientColor: "#facc15",
|
|
2050
|
-
borderGradient: "border-[#facc15]",
|
|
2051
|
-
borderGradientColor: "#facc15"
|
|
2052
|
-
},
|
|
2053
|
-
light: {
|
|
2054
|
-
bgGradient: "bg-[#fafafa]",
|
|
2055
|
-
// 移除透明度 ff
|
|
2056
|
-
gradientColor: "#f59e0b",
|
|
2057
|
-
borderGradient: "border-[#f59e0b]",
|
|
2058
|
-
borderGradientColor: "#f59e0b"
|
|
1978
|
+
if (typeof obj === "boolean") {
|
|
1979
|
+
return obj;
|
|
2059
1980
|
}
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
icon: "ic:outline-info",
|
|
2063
|
-
color: "text-blue-400",
|
|
2064
|
-
className: "text-blue-400",
|
|
2065
|
-
dark: {
|
|
2066
|
-
bgGradient: "bg-[#14181d]",
|
|
2067
|
-
// 移除透明度 f2
|
|
2068
|
-
gradientColor: "#60a5fa",
|
|
2069
|
-
borderGradient: "border-[#60a5fa]",
|
|
2070
|
-
borderGradientColor: "#f0f0f0"
|
|
2071
|
-
},
|
|
2072
|
-
light: {
|
|
2073
|
-
bgGradient: "bg-[#fafafa]",
|
|
2074
|
-
// 移除透明度 ff
|
|
2075
|
-
gradientColor: "#3b82f6",
|
|
2076
|
-
borderGradient: "border-[#3b82f6]",
|
|
2077
|
-
borderGradientColor: "#3b82f6"
|
|
1981
|
+
if (typeof obj === "bigint") {
|
|
1982
|
+
return new TypeWrapper("BigInt", obj.toString());
|
|
2078
1983
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
icon: "ic:round-notifications",
|
|
2082
|
-
color: "text-gray-400",
|
|
2083
|
-
className: "text-gray-400",
|
|
2084
|
-
dark: {
|
|
2085
|
-
bgGradient: "bg-[#14181d]",
|
|
2086
|
-
// 移除透明度 f2
|
|
2087
|
-
gradientColor: "#9ca3af",
|
|
2088
|
-
borderGradient: "border-[#9ca3af]",
|
|
2089
|
-
borderGradientColor: "#9ca3af"
|
|
2090
|
-
},
|
|
2091
|
-
light: {
|
|
2092
|
-
bgGradient: "bg-[#fafafa]",
|
|
2093
|
-
// 移除透明度 ff
|
|
2094
|
-
gradientColor: "#6b7280",
|
|
2095
|
-
borderGradient: "border-[#6b7280]",
|
|
2096
|
-
borderGradientColor: "#6b7280"
|
|
1984
|
+
if (typeof obj === "symbol") {
|
|
1985
|
+
return new TypeWrapper("Symbol", obj.toString());
|
|
2097
1986
|
}
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
2109
|
-
return actualTheme === "dark" ? "#b4b4b4" : "#6b7280";
|
|
2110
|
-
};
|
|
2111
|
-
const getCloseButtonHoverColor = () => {
|
|
2112
|
-
const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
2113
|
-
return actualTheme === "dark" ? "white" : "#374151";
|
|
2114
|
-
};
|
|
2115
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2116
|
-
import_react9.Icon,
|
|
2117
|
-
{
|
|
2118
|
-
icon: "vaadin:close",
|
|
2119
|
-
className: "flex items-center justify-center rounded-full relative z-10 flex-shrink-0 cursor-pointer \n transition-colors duration-200 drop-shadow-sm",
|
|
2120
|
-
onClick: handleClick,
|
|
2121
|
-
width: 14,
|
|
2122
|
-
height: 14,
|
|
2123
|
-
style: {
|
|
2124
|
-
color: getCloseButtonColor()
|
|
2125
|
-
},
|
|
2126
|
-
onMouseEnter: (e) => {
|
|
2127
|
-
e.currentTarget.style.color = getCloseButtonHoverColor();
|
|
2128
|
-
},
|
|
2129
|
-
onMouseLeave: (e) => {
|
|
2130
|
-
e.currentTarget.style.color = getCloseButtonColor();
|
|
1987
|
+
if (typeof obj === "function") {
|
|
1988
|
+
return new TypeWrapper("Function", {
|
|
1989
|
+
name: obj.name || "anonymous",
|
|
1990
|
+
stringValue: obj.toString().slice(0, opts.maxStringLength),
|
|
1991
|
+
length: obj.length
|
|
1992
|
+
});
|
|
1993
|
+
}
|
|
1994
|
+
if (obj && typeof obj === "object") {
|
|
1995
|
+
if (visitedObjects.has(obj)) {
|
|
1996
|
+
return new CircularReference(visitedObjects.get(obj));
|
|
2131
1997
|
}
|
|
1998
|
+
visitedObjects.set(obj, path);
|
|
2132
1999
|
}
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2000
|
+
if (obj instanceof Error) {
|
|
2001
|
+
return this.serializeError(obj, opts, visitedObjects, path);
|
|
2002
|
+
}
|
|
2003
|
+
if (obj instanceof Date) {
|
|
2004
|
+
return new TypeWrapper("Date", {
|
|
2005
|
+
iso: obj.toISOString(),
|
|
2006
|
+
value: obj.valueOf(),
|
|
2007
|
+
local: obj.toString()
|
|
2008
|
+
});
|
|
2009
|
+
}
|
|
2010
|
+
if (obj instanceof RegExp) {
|
|
2011
|
+
return new TypeWrapper("RegExp", {
|
|
2012
|
+
source: obj.source,
|
|
2013
|
+
flags: obj.flags,
|
|
2014
|
+
string: obj.toString()
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
2017
|
+
if (obj instanceof Promise) {
|
|
2018
|
+
return new TypeWrapper("Promise", "[Promise]");
|
|
2019
|
+
}
|
|
2020
|
+
if (obj instanceof WeakMap || obj instanceof WeakSet) {
|
|
2021
|
+
return new TypeWrapper(
|
|
2022
|
+
obj.constructor.name,
|
|
2023
|
+
"[" + obj.constructor.name + "]"
|
|
2024
|
+
);
|
|
2025
|
+
}
|
|
2026
|
+
if (obj instanceof Set) {
|
|
2027
|
+
return this.serializeSet(obj, opts, visitedObjects, path);
|
|
2028
|
+
}
|
|
2029
|
+
if (obj instanceof Map) {
|
|
2030
|
+
return this.serializeMap(obj, opts, visitedObjects, path);
|
|
2031
|
+
}
|
|
2032
|
+
if (ArrayBuffer.isView(obj)) {
|
|
2033
|
+
return this.serializeTypedArray(obj);
|
|
2034
|
+
}
|
|
2035
|
+
if (Array.isArray(obj)) {
|
|
2036
|
+
return this.serializeArray(obj, opts, visitedObjects, path);
|
|
2037
|
+
}
|
|
2038
|
+
return this.serializeObject(obj, opts, visitedObjects, path);
|
|
2156
2039
|
}
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
}
|
|
2176
|
-
|
|
2177
|
-
),
|
|
2178
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2179
|
-
"div",
|
|
2180
|
-
{
|
|
2181
|
-
className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-xl",
|
|
2182
|
-
style: {
|
|
2183
|
-
border: "2px solid transparent",
|
|
2184
|
-
backgroundImage: theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? `linear-gradient(135deg, ${themeConfig.borderGradientColor}60 0%, ${themeConfig.borderGradientColor}40 5%, transparent 22%)` : `linear-gradient(135deg, ${themeConfig.borderGradientColor}40 0%, ${themeConfig.borderGradientColor}25 5%, transparent 22%)`,
|
|
2185
|
-
backgroundOrigin: "border-box",
|
|
2186
|
-
backgroundClip: "border-box",
|
|
2187
|
-
WebkitMask: "linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)",
|
|
2188
|
-
WebkitMaskComposite: "xor",
|
|
2189
|
-
mask: "linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)",
|
|
2190
|
-
maskComposite: "exclude"
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
),
|
|
2194
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex-shrink-0 mt-0.5 relative z-10", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `w-7 h-7 backdrop-blur-sm rounded-full flex items-center justify-center ${theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "bg-white/10" : "bg-black/5"}`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2195
|
-
import_react9.Icon,
|
|
2196
|
-
{
|
|
2197
|
-
icon: iconConfig.icon,
|
|
2198
|
-
width: 16,
|
|
2199
|
-
height: 16,
|
|
2200
|
-
className: iconConfig.color,
|
|
2201
|
-
style: {
|
|
2202
|
-
color: themeConfig.gradientColor
|
|
2040
|
+
/**
|
|
2041
|
+
* 序列化错误对象
|
|
2042
|
+
*/
|
|
2043
|
+
static serializeError(error, opts, visitedObjects, path) {
|
|
2044
|
+
const errorObj = {
|
|
2045
|
+
name: error.name,
|
|
2046
|
+
message: error.message,
|
|
2047
|
+
stack: error.stack
|
|
2048
|
+
};
|
|
2049
|
+
for (const key of Object.getOwnPropertyNames(error)) {
|
|
2050
|
+
if (!errorObj[key]) {
|
|
2051
|
+
try {
|
|
2052
|
+
errorObj[key] = this.serialize(
|
|
2053
|
+
error[key],
|
|
2054
|
+
opts,
|
|
2055
|
+
visitedObjects,
|
|
2056
|
+
`${path}.${key}`
|
|
2057
|
+
);
|
|
2058
|
+
} catch (e) {
|
|
2059
|
+
errorObj[key] = new TypeWrapper("Error", `[Unable to serialize: ${e}]`);
|
|
2203
2060
|
}
|
|
2204
2061
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
backgroundClip: "text"
|
|
2225
|
-
},
|
|
2226
|
-
children: message
|
|
2227
|
-
}
|
|
2062
|
+
}
|
|
2063
|
+
return new TypeWrapper("Error", errorObj);
|
|
2064
|
+
}
|
|
2065
|
+
/**
|
|
2066
|
+
* 序列化 Set
|
|
2067
|
+
*/
|
|
2068
|
+
static serializeSet(set, opts, visitedObjects, path) {
|
|
2069
|
+
const values = Array.from(set);
|
|
2070
|
+
if (values.length > opts.maxArrayLength) {
|
|
2071
|
+
return new TypeWrapper("Set", {
|
|
2072
|
+
values: values.slice(0, opts.maxArrayLength).map(
|
|
2073
|
+
(item, index) => this.serialize(item, opts, visitedObjects, `${path}.Set[${index}]`)
|
|
2074
|
+
),
|
|
2075
|
+
truncated: values.length - opts.maxArrayLength
|
|
2076
|
+
});
|
|
2077
|
+
}
|
|
2078
|
+
return new TypeWrapper("Set", {
|
|
2079
|
+
values: values.map(
|
|
2080
|
+
(item, index) => this.serialize(item, opts, visitedObjects, `${path}.Set[${index}]`)
|
|
2228
2081
|
)
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
transition: import_react_toastify2.Bounce
|
|
2243
|
-
};
|
|
2244
|
-
var createToast = (type) => {
|
|
2245
|
-
return (params) => {
|
|
2246
|
-
const { title, message, component, options } = params;
|
|
2247
|
-
(0, import_react_toastify2.toast)(
|
|
2248
|
-
({ closeToast }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2249
|
-
ToastContent,
|
|
2250
|
-
{
|
|
2251
|
-
type,
|
|
2252
|
-
title,
|
|
2253
|
-
message: message || "",
|
|
2254
|
-
component,
|
|
2255
|
-
closeToast
|
|
2256
|
-
}
|
|
2257
|
-
),
|
|
2258
|
-
{
|
|
2259
|
-
...defaultToastOptions,
|
|
2260
|
-
...options,
|
|
2261
|
-
// 确保圆角样式不被覆盖,添加 rounded-xl 类
|
|
2262
|
-
className: "!p-0 !shadow-none !rounded-xl",
|
|
2263
|
-
style: { padding: 0, borderRadius: "0.75rem" }
|
|
2264
|
-
}
|
|
2265
|
-
);
|
|
2266
|
-
};
|
|
2267
|
-
};
|
|
2268
|
-
var ClayxToast = {
|
|
2269
|
-
success: createToast("success"),
|
|
2270
|
-
error: createToast("error"),
|
|
2271
|
-
warning: createToast("warning"),
|
|
2272
|
-
info: createToast("info"),
|
|
2273
|
-
default: createToast("default")
|
|
2274
|
-
};
|
|
2275
|
-
|
|
2276
|
-
// src/hooks/use-mobile.ts
|
|
2277
|
-
var React6 = __toESM(require("react"));
|
|
2278
|
-
var MOBILE_BREAKPOINT = 768;
|
|
2279
|
-
function useIsMobile() {
|
|
2280
|
-
const [isMobile, setIsMobile] = React6.useState(void 0);
|
|
2281
|
-
React6.useEffect(() => {
|
|
2282
|
-
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
2283
|
-
const onChange = () => {
|
|
2284
|
-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
2285
|
-
};
|
|
2286
|
-
mql.addEventListener("change", onChange);
|
|
2287
|
-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
2288
|
-
return () => mql.removeEventListener("change", onChange);
|
|
2289
|
-
}, []);
|
|
2290
|
-
return !!isMobile;
|
|
2291
|
-
}
|
|
2292
|
-
|
|
2293
|
-
// src/hooks/use-debounce.ts
|
|
2294
|
-
var import_react10 = require("react");
|
|
2295
|
-
function useDebounce(value, delay) {
|
|
2296
|
-
const [debouncedValue, setDebouncedValue] = (0, import_react10.useState)(value);
|
|
2297
|
-
(0, import_react10.useEffect)(() => {
|
|
2298
|
-
const handler = setTimeout(() => {
|
|
2299
|
-
setDebouncedValue(value);
|
|
2300
|
-
}, delay);
|
|
2301
|
-
return () => {
|
|
2302
|
-
clearTimeout(handler);
|
|
2303
|
-
};
|
|
2304
|
-
}, [value, delay]);
|
|
2305
|
-
return debouncedValue;
|
|
2306
|
-
}
|
|
2307
|
-
|
|
2308
|
-
// src/utils/unified-error-handler/types.ts
|
|
2309
|
-
var ERROR_CONFIG = {
|
|
2310
|
-
MAX_ERRORS: 100,
|
|
2311
|
-
MAX_INTERACTIONS: 50,
|
|
2312
|
-
DEDUP_WINDOW: 1e3,
|
|
2313
|
-
DEBOUNCE_TIME: 100,
|
|
2314
|
-
CACHE_DURATION: 3e5,
|
|
2315
|
-
SEVERITY_KEYWORDS: {
|
|
2316
|
-
CRITICAL: ["fatal", "critical", "security", "crash", "corruption"],
|
|
2317
|
-
HIGH: ["error", "exception", "failed", "timeout", "network error"],
|
|
2318
|
-
MEDIUM: ["warning", "deprecated", "slow", "performance"],
|
|
2319
|
-
LOW: ["info", "debug", "trace", "notice"]
|
|
2320
|
-
},
|
|
2321
|
-
CATEGORY_KEYWORDS: {
|
|
2322
|
-
SYNTAX: ["syntaxerror", "unexpected token", "parse error", "invalid syntax"],
|
|
2323
|
-
NETWORK: ["fetch", "xhr", "network", "cors", "timeout", "connection"],
|
|
2324
|
-
RUNTIME: ["referenceerror", "typeerror", "rangeerror", "undefined"],
|
|
2325
|
-
SECURITY: ["csp", "xss", "csrf", "security", "unauthorized"],
|
|
2326
|
-
PERFORMANCE: ["slow", "memory", "leak", "performance", "timeout"],
|
|
2327
|
-
DEVELOPMENT: ["vite", "hmr", "hot reload", "dev server", "webpack"],
|
|
2328
|
-
REACT: ["react", "jsx", "component", "hook", "render"],
|
|
2329
|
-
VITE: ["vite", "[vite]", "vite:react", "transform failed"]
|
|
2330
|
-
}
|
|
2331
|
-
};
|
|
2332
|
-
var GLOBAL_CONFIG = {
|
|
2333
|
-
ALLOWED_ORIGINS: [
|
|
2334
|
-
"https://howone.ai",
|
|
2335
|
-
"https://howone.dev",
|
|
2336
|
-
"http://localhost:3000",
|
|
2337
|
-
"http://localhost:5173"
|
|
2338
|
-
],
|
|
2339
|
-
DEBOUNCE_DELAY: 10,
|
|
2340
|
-
OVERRIDE_STYLESHEET_ID: "howone-override-styles"
|
|
2341
|
-
};
|
|
2342
|
-
var DEFAULT_SELECTOR_CONFIG = {
|
|
2343
|
-
HIGHLIGHT_COLOR: "#ff6b6b",
|
|
2344
|
-
HIGHLIGHT_BORDER_WIDTH: "2px",
|
|
2345
|
-
HIGHLIGHT_BORDER_STYLE: "solid",
|
|
2346
|
-
SELECTED_COLOR: "#4ecdc4",
|
|
2347
|
-
SELECTED_BORDER_WIDTH: "3px",
|
|
2348
|
-
TOOLTIP_BACKGROUND: "#333",
|
|
2349
|
-
TOOLTIP_COLOR: "#fff",
|
|
2350
|
-
TOOLTIP_PADDING: "8px 12px",
|
|
2351
|
-
TOOLTIP_BORDER_RADIUS: "4px",
|
|
2352
|
-
TOOLTIP_FONT_SIZE: "12px",
|
|
2353
|
-
TOOLTIP_Z_INDEX: "10000",
|
|
2354
|
-
FULL_WIDTH_TOOLTIP_OFFSET: 10,
|
|
2355
|
-
highlightClass: "howone-highlight",
|
|
2356
|
-
selectedClass: "howone-selected",
|
|
2357
|
-
cursor: "crosshair"
|
|
2358
|
-
};
|
|
2359
|
-
|
|
2360
|
-
// src/utils/unified-error-handler/utils/DeepSerializer.ts
|
|
2361
|
-
var CircularReference = class {
|
|
2362
|
-
constructor(path) {
|
|
2363
|
-
this.message = `[Circular Reference to ${path}]`;
|
|
2364
|
-
}
|
|
2365
|
-
};
|
|
2366
|
-
var TypeWrapper = class {
|
|
2367
|
-
constructor(type, value) {
|
|
2368
|
-
this._type = type;
|
|
2369
|
-
this.value = value;
|
|
2370
|
-
}
|
|
2371
|
-
};
|
|
2372
|
-
var DeepSerializer = class {
|
|
2373
|
-
/**
|
|
2374
|
-
* 深度序列化对象
|
|
2375
|
-
*/
|
|
2376
|
-
static serialize(obj, options = {}, visitedObjects = /* @__PURE__ */ new WeakMap(), path = "root") {
|
|
2377
|
-
const opts = { ...this.DEFAULT_OPTIONS, ...options };
|
|
2378
|
-
if (path.split(".").length > opts.maxDepth) {
|
|
2379
|
-
return new TypeWrapper(
|
|
2380
|
-
"MaxDepthReached",
|
|
2381
|
-
`[Max depth of ${opts.maxDepth} reached]`
|
|
2382
|
-
);
|
|
2383
|
-
}
|
|
2384
|
-
if (obj === void 0) {
|
|
2385
|
-
return new TypeWrapper("undefined", "undefined");
|
|
2386
|
-
}
|
|
2387
|
-
if (obj === null) {
|
|
2388
|
-
return null;
|
|
2389
|
-
}
|
|
2390
|
-
if (typeof obj === "string") {
|
|
2391
|
-
return obj.length > opts.maxStringLength ? new TypeWrapper(
|
|
2392
|
-
"String",
|
|
2393
|
-
`${obj.slice(0, opts.maxStringLength)}... [${obj.length - opts.maxStringLength} more characters]`
|
|
2394
|
-
) : obj;
|
|
2395
|
-
}
|
|
2396
|
-
if (typeof obj === "number") {
|
|
2397
|
-
return Number.isNaN(obj) ? new TypeWrapper("Number", "NaN") : Number.isFinite(obj) ? obj : new TypeWrapper("Number", obj > 0 ? "Infinity" : "-Infinity");
|
|
2398
|
-
}
|
|
2399
|
-
if (typeof obj === "boolean") {
|
|
2400
|
-
return obj;
|
|
2401
|
-
}
|
|
2402
|
-
if (typeof obj === "bigint") {
|
|
2403
|
-
return new TypeWrapper("BigInt", obj.toString());
|
|
2404
|
-
}
|
|
2405
|
-
if (typeof obj === "symbol") {
|
|
2406
|
-
return new TypeWrapper("Symbol", obj.toString());
|
|
2407
|
-
}
|
|
2408
|
-
if (typeof obj === "function") {
|
|
2409
|
-
return new TypeWrapper("Function", {
|
|
2410
|
-
name: obj.name || "anonymous",
|
|
2411
|
-
stringValue: obj.toString().slice(0, opts.maxStringLength),
|
|
2412
|
-
length: obj.length
|
|
2413
|
-
});
|
|
2414
|
-
}
|
|
2415
|
-
if (obj && typeof obj === "object") {
|
|
2416
|
-
if (visitedObjects.has(obj)) {
|
|
2417
|
-
return new CircularReference(visitedObjects.get(obj));
|
|
2418
|
-
}
|
|
2419
|
-
visitedObjects.set(obj, path);
|
|
2420
|
-
}
|
|
2421
|
-
if (obj instanceof Error) {
|
|
2422
|
-
return this.serializeError(obj, opts, visitedObjects, path);
|
|
2423
|
-
}
|
|
2424
|
-
if (obj instanceof Date) {
|
|
2425
|
-
return new TypeWrapper("Date", {
|
|
2426
|
-
iso: obj.toISOString(),
|
|
2427
|
-
value: obj.valueOf(),
|
|
2428
|
-
local: obj.toString()
|
|
2429
|
-
});
|
|
2430
|
-
}
|
|
2431
|
-
if (obj instanceof RegExp) {
|
|
2432
|
-
return new TypeWrapper("RegExp", {
|
|
2433
|
-
source: obj.source,
|
|
2434
|
-
flags: obj.flags,
|
|
2435
|
-
string: obj.toString()
|
|
2436
|
-
});
|
|
2437
|
-
}
|
|
2438
|
-
if (obj instanceof Promise) {
|
|
2439
|
-
return new TypeWrapper("Promise", "[Promise]");
|
|
2440
|
-
}
|
|
2441
|
-
if (obj instanceof WeakMap || obj instanceof WeakSet) {
|
|
2442
|
-
return new TypeWrapper(
|
|
2443
|
-
obj.constructor.name,
|
|
2444
|
-
"[" + obj.constructor.name + "]"
|
|
2445
|
-
);
|
|
2446
|
-
}
|
|
2447
|
-
if (obj instanceof Set) {
|
|
2448
|
-
return this.serializeSet(obj, opts, visitedObjects, path);
|
|
2449
|
-
}
|
|
2450
|
-
if (obj instanceof Map) {
|
|
2451
|
-
return this.serializeMap(obj, opts, visitedObjects, path);
|
|
2452
|
-
}
|
|
2453
|
-
if (ArrayBuffer.isView(obj)) {
|
|
2454
|
-
return this.serializeTypedArray(obj);
|
|
2455
|
-
}
|
|
2456
|
-
if (Array.isArray(obj)) {
|
|
2457
|
-
return this.serializeArray(obj, opts, visitedObjects, path);
|
|
2458
|
-
}
|
|
2459
|
-
return this.serializeObject(obj, opts, visitedObjects, path);
|
|
2460
|
-
}
|
|
2461
|
-
/**
|
|
2462
|
-
* 序列化错误对象
|
|
2463
|
-
*/
|
|
2464
|
-
static serializeError(error, opts, visitedObjects, path) {
|
|
2465
|
-
const errorObj = {
|
|
2466
|
-
name: error.name,
|
|
2467
|
-
message: error.message,
|
|
2468
|
-
stack: error.stack
|
|
2469
|
-
};
|
|
2470
|
-
for (const key of Object.getOwnPropertyNames(error)) {
|
|
2471
|
-
if (!errorObj[key]) {
|
|
2472
|
-
try {
|
|
2473
|
-
errorObj[key] = this.serialize(
|
|
2474
|
-
error[key],
|
|
2475
|
-
opts,
|
|
2476
|
-
visitedObjects,
|
|
2477
|
-
`${path}.${key}`
|
|
2478
|
-
);
|
|
2479
|
-
} catch (e) {
|
|
2480
|
-
errorObj[key] = new TypeWrapper("Error", `[Unable to serialize: ${e}]`);
|
|
2481
|
-
}
|
|
2482
|
-
}
|
|
2483
|
-
}
|
|
2484
|
-
return new TypeWrapper("Error", errorObj);
|
|
2485
|
-
}
|
|
2486
|
-
/**
|
|
2487
|
-
* 序列化 Set
|
|
2488
|
-
*/
|
|
2489
|
-
static serializeSet(set, opts, visitedObjects, path) {
|
|
2490
|
-
const values = Array.from(set);
|
|
2491
|
-
if (values.length > opts.maxArrayLength) {
|
|
2492
|
-
return new TypeWrapper("Set", {
|
|
2493
|
-
values: values.slice(0, opts.maxArrayLength).map(
|
|
2494
|
-
(item, index) => this.serialize(item, opts, visitedObjects, `${path}.Set[${index}]`)
|
|
2495
|
-
),
|
|
2496
|
-
truncated: values.length - opts.maxArrayLength
|
|
2497
|
-
});
|
|
2498
|
-
}
|
|
2499
|
-
return new TypeWrapper("Set", {
|
|
2500
|
-
values: values.map(
|
|
2501
|
-
(item, index) => this.serialize(item, opts, visitedObjects, `${path}.Set[${index}]`)
|
|
2502
|
-
)
|
|
2503
|
-
});
|
|
2504
|
-
}
|
|
2505
|
-
/**
|
|
2506
|
-
* 序列化 Map
|
|
2507
|
-
*/
|
|
2508
|
-
static serializeMap(map, opts, visitedObjects, path) {
|
|
2509
|
-
const entries = {};
|
|
2510
|
-
let truncatedCount = 0;
|
|
2511
|
-
let addedCount = 0;
|
|
2512
|
-
for (const [key, value] of map.entries()) {
|
|
2513
|
-
if (addedCount >= opts.maxObjectKeys) {
|
|
2514
|
-
truncatedCount++;
|
|
2515
|
-
continue;
|
|
2082
|
+
});
|
|
2083
|
+
}
|
|
2084
|
+
/**
|
|
2085
|
+
* 序列化 Map
|
|
2086
|
+
*/
|
|
2087
|
+
static serializeMap(map, opts, visitedObjects, path) {
|
|
2088
|
+
const entries = {};
|
|
2089
|
+
let truncatedCount = 0;
|
|
2090
|
+
let addedCount = 0;
|
|
2091
|
+
for (const [key, value] of map.entries()) {
|
|
2092
|
+
if (addedCount >= opts.maxObjectKeys) {
|
|
2093
|
+
truncatedCount++;
|
|
2094
|
+
continue;
|
|
2516
2095
|
}
|
|
2517
2096
|
const keyString = typeof key === "object" ? JSON.stringify(
|
|
2518
2097
|
this.serialize(key, opts, visitedObjects, `${path}.MapKey`)
|
|
@@ -5069,7 +4648,7 @@ var InteractionTracking = class {
|
|
|
5069
4648
|
};
|
|
5070
4649
|
|
|
5071
4650
|
// src/utils/unified-error-handler/features/ElementSelector.ts
|
|
5072
|
-
var
|
|
4651
|
+
var ElementSelector2 = class {
|
|
5073
4652
|
constructor(sendMessage) {
|
|
5074
4653
|
this.config = { ...DEFAULT_SELECTOR_CONFIG };
|
|
5075
4654
|
this.isActive = false;
|
|
@@ -6063,7 +5642,6 @@ var MessageBridge = class {
|
|
|
6063
5642
|
this.handleSetStylesheet(payload);
|
|
6064
5643
|
break;
|
|
6065
5644
|
default:
|
|
6066
|
-
console.warn("[MessageBridge] \u672A\u77E5\u6D88\u606F\u7C7B\u578B:", type);
|
|
6067
5645
|
break;
|
|
6068
5646
|
}
|
|
6069
5647
|
} catch (error) {
|
|
@@ -6595,7 +6173,7 @@ var ErrorHandler = class {
|
|
|
6595
6173
|
const sendMessage = this.messageSender.createSendFunction();
|
|
6596
6174
|
this.errorTracking = new ErrorTracking(sendMessage);
|
|
6597
6175
|
this.interactionTracking = new InteractionTracking(sendMessage);
|
|
6598
|
-
this.elementSelector = new
|
|
6176
|
+
this.elementSelector = new ElementSelector2(sendMessage);
|
|
6599
6177
|
this.messageBridge = new MessageBridge();
|
|
6600
6178
|
this.viewDetector = new ViewDetector();
|
|
6601
6179
|
this.hardRefreshManager = new HardRefreshManager(GLOBAL_CONFIG.ALLOWED_ORIGINS);
|
|
@@ -6872,6 +6450,656 @@ var ErrorHandler = class {
|
|
|
6872
6450
|
}
|
|
6873
6451
|
};
|
|
6874
6452
|
|
|
6453
|
+
// src/components/auth/HowoneProvider.tsx
|
|
6454
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
6455
|
+
var HowoneContext = (0, import_react8.createContext)(null);
|
|
6456
|
+
var HowOneProvider = ({
|
|
6457
|
+
children,
|
|
6458
|
+
showFloatingButton = true,
|
|
6459
|
+
projectId,
|
|
6460
|
+
defaultTheme = "system",
|
|
6461
|
+
themeStorageKey = "howone-theme",
|
|
6462
|
+
forceDefaultTheme = false,
|
|
6463
|
+
authUrl = "https://howone.dev/auth",
|
|
6464
|
+
redirectOnUnauthenticated = true
|
|
6465
|
+
}) => {
|
|
6466
|
+
const [user, setUser] = (0, import_react8.useState)(() => parseUserFromToken(getToken()));
|
|
6467
|
+
const [token, setTokenState] = (0, import_react8.useState)(() => getToken());
|
|
6468
|
+
const [hasCheckedUrlToken, setHasCheckedUrlToken] = (0, import_react8.useState)(false);
|
|
6469
|
+
(0, import_react8.useEffect)(() => {
|
|
6470
|
+
const errorHandler = new ErrorHandler({
|
|
6471
|
+
enableViteHMR: true,
|
|
6472
|
+
enableElementSelector: true,
|
|
6473
|
+
enableInteractionTracking: true
|
|
6474
|
+
// enableConsoleCapture: true,
|
|
6475
|
+
// enableNetworkCapture: true,
|
|
6476
|
+
// maxErrors: 100,
|
|
6477
|
+
// maxInteractions: 50,
|
|
6478
|
+
// debounceTime: 100,
|
|
6479
|
+
// reportToParent: true,
|
|
6480
|
+
// reportToConsole: true
|
|
6481
|
+
});
|
|
6482
|
+
errorHandler.init();
|
|
6483
|
+
window.__ERROR_HANDLER__ = errorHandler;
|
|
6484
|
+
try {
|
|
6485
|
+
const params = new URLSearchParams(window.location.search);
|
|
6486
|
+
let urlToken = params.get("access_token") || params.get("token");
|
|
6487
|
+
if (!urlToken && window.location.hash) {
|
|
6488
|
+
const hashParams = new URLSearchParams(window.location.hash.slice(1));
|
|
6489
|
+
urlToken = hashParams.get("access_token") || hashParams.get("token");
|
|
6490
|
+
}
|
|
6491
|
+
if (urlToken) {
|
|
6492
|
+
console.log("[HowOneProvider] Token captured from URL, storing to localStorage...");
|
|
6493
|
+
setToken(urlToken);
|
|
6494
|
+
setTokenState(urlToken);
|
|
6495
|
+
setUser(parseUserFromToken(urlToken));
|
|
6496
|
+
params.delete("access_token");
|
|
6497
|
+
params.delete("token");
|
|
6498
|
+
params.delete("project_id");
|
|
6499
|
+
const newSearch = params.toString();
|
|
6500
|
+
const newUrl = window.location.pathname + (newSearch ? "?" + newSearch : "");
|
|
6501
|
+
window.history.replaceState({}, "", newUrl);
|
|
6502
|
+
console.log("[HowOneProvider] Token stored successfully, URL cleaned");
|
|
6503
|
+
}
|
|
6504
|
+
} catch (e) {
|
|
6505
|
+
console.error("[HowOneProvider] Failed to capture token from URL:", e);
|
|
6506
|
+
} finally {
|
|
6507
|
+
setHasCheckedUrlToken(true);
|
|
6508
|
+
}
|
|
6509
|
+
}, []);
|
|
6510
|
+
(0, import_react8.useEffect)(() => {
|
|
6511
|
+
if (!hasCheckedUrlToken) {
|
|
6512
|
+
return;
|
|
6513
|
+
}
|
|
6514
|
+
}, [token, user, redirectOnUnauthenticated, authUrl, projectId, hasCheckedUrlToken]);
|
|
6515
|
+
const logout = () => {
|
|
6516
|
+
try {
|
|
6517
|
+
setToken(null);
|
|
6518
|
+
} catch {
|
|
6519
|
+
}
|
|
6520
|
+
setTokenState(null);
|
|
6521
|
+
setUser(null);
|
|
6522
|
+
};
|
|
6523
|
+
const value = {
|
|
6524
|
+
user,
|
|
6525
|
+
token,
|
|
6526
|
+
isAuthenticated: !!token,
|
|
6527
|
+
logout
|
|
6528
|
+
};
|
|
6529
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
6530
|
+
ThemeProvider,
|
|
6531
|
+
{
|
|
6532
|
+
defaultTheme,
|
|
6533
|
+
storageKey: themeStorageKey,
|
|
6534
|
+
forceDefault: forceDefaultTheme,
|
|
6535
|
+
children: [
|
|
6536
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ElementSelectorProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(HowoneContext.Provider, { value, children: [
|
|
6537
|
+
children,
|
|
6538
|
+
showFloatingButton && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloatingButton, { onClick: () => window.open("https://howone.ai", "_blank") })
|
|
6539
|
+
] }) }),
|
|
6540
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(GlobalToastContainer, {})
|
|
6541
|
+
]
|
|
6542
|
+
}
|
|
6543
|
+
);
|
|
6544
|
+
};
|
|
6545
|
+
function useHowoneContext() {
|
|
6546
|
+
const ctx = (0, import_react8.useContext)(HowoneContext);
|
|
6547
|
+
if (!ctx) {
|
|
6548
|
+
const t = getToken();
|
|
6549
|
+
return {
|
|
6550
|
+
user: parseUserFromToken(t),
|
|
6551
|
+
token: t,
|
|
6552
|
+
isAuthenticated: !!t,
|
|
6553
|
+
logout: () => {
|
|
6554
|
+
try {
|
|
6555
|
+
setToken(null);
|
|
6556
|
+
} catch {
|
|
6557
|
+
}
|
|
6558
|
+
}
|
|
6559
|
+
};
|
|
6560
|
+
}
|
|
6561
|
+
return ctx;
|
|
6562
|
+
}
|
|
6563
|
+
|
|
6564
|
+
// src/components/index.ts
|
|
6565
|
+
init_auth();
|
|
6566
|
+
|
|
6567
|
+
// src/howone/client.ts
|
|
6568
|
+
init_auth();
|
|
6569
|
+
init_config();
|
|
6570
|
+
var HowoneAuthClient = class {
|
|
6571
|
+
constructor() {
|
|
6572
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
6573
|
+
this.loading = false;
|
|
6574
|
+
}
|
|
6575
|
+
emit() {
|
|
6576
|
+
const state = {
|
|
6577
|
+
user: parseUserFromToken(getToken()),
|
|
6578
|
+
isLoading: this.loading
|
|
6579
|
+
};
|
|
6580
|
+
for (const l of this.listeners) {
|
|
6581
|
+
try {
|
|
6582
|
+
l(state);
|
|
6583
|
+
} catch (e) {
|
|
6584
|
+
void e;
|
|
6585
|
+
}
|
|
6586
|
+
}
|
|
6587
|
+
}
|
|
6588
|
+
onAuthStateChanged(listener) {
|
|
6589
|
+
this.listeners.add(listener);
|
|
6590
|
+
try {
|
|
6591
|
+
listener({ user: parseUserFromToken(getToken()), isLoading: this.loading });
|
|
6592
|
+
} catch (e) {
|
|
6593
|
+
void e;
|
|
6594
|
+
}
|
|
6595
|
+
return () => {
|
|
6596
|
+
this.listeners.delete(listener);
|
|
6597
|
+
};
|
|
6598
|
+
}
|
|
6599
|
+
// Simple redirect-based login trigger (consumer can override)
|
|
6600
|
+
login() {
|
|
6601
|
+
const root = getAuthRoot() || "https://create-x-backend-dev.fly.dev";
|
|
6602
|
+
try {
|
|
6603
|
+
const loc = window.location.href;
|
|
6604
|
+
const authUrl = new URL("/auth", String(root));
|
|
6605
|
+
authUrl.searchParams.set("redirect_uri", String(loc));
|
|
6606
|
+
try {
|
|
6607
|
+
const cfg = (init_config(), __toCommonJS(config_exports));
|
|
6608
|
+
const pid = cfg.getDefaultProjectId && cfg.getDefaultProjectId();
|
|
6609
|
+
if (pid) authUrl.searchParams.set("project_id", String(pid));
|
|
6610
|
+
} catch {
|
|
6611
|
+
}
|
|
6612
|
+
try {
|
|
6613
|
+
if (window.top && window.top !== window) {
|
|
6614
|
+
window.top.location.replace(authUrl.toString());
|
|
6615
|
+
} else {
|
|
6616
|
+
window.location.replace(authUrl.toString());
|
|
6617
|
+
}
|
|
6618
|
+
} catch {
|
|
6619
|
+
try {
|
|
6620
|
+
window.location.replace(String(root));
|
|
6621
|
+
} catch {
|
|
6622
|
+
}
|
|
6623
|
+
}
|
|
6624
|
+
} catch {
|
|
6625
|
+
try {
|
|
6626
|
+
window.location.replace(String(root));
|
|
6627
|
+
} catch {
|
|
6628
|
+
}
|
|
6629
|
+
}
|
|
6630
|
+
}
|
|
6631
|
+
logout() {
|
|
6632
|
+
setToken(null);
|
|
6633
|
+
this.emit();
|
|
6634
|
+
}
|
|
6635
|
+
getUser() {
|
|
6636
|
+
return parseUserFromToken(getToken());
|
|
6637
|
+
}
|
|
6638
|
+
// helper to programmatically set token (e.g., after callback handling)
|
|
6639
|
+
setToken(token) {
|
|
6640
|
+
setToken(token);
|
|
6641
|
+
this.emit();
|
|
6642
|
+
}
|
|
6643
|
+
};
|
|
6644
|
+
var howone = {
|
|
6645
|
+
auth: new HowoneAuthClient()
|
|
6646
|
+
};
|
|
6647
|
+
var client_default = howone;
|
|
6648
|
+
|
|
6649
|
+
// src/components/ui/Loading.tsx
|
|
6650
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
6651
|
+
var Loading = ({
|
|
6652
|
+
size = "md",
|
|
6653
|
+
text = "Loading...",
|
|
6654
|
+
className = "",
|
|
6655
|
+
fullScreen = false
|
|
6656
|
+
}) => {
|
|
6657
|
+
const sizeClasses = {
|
|
6658
|
+
sm: "h-4 w-4",
|
|
6659
|
+
md: "h-8 w-8",
|
|
6660
|
+
lg: "h-12 w-12"
|
|
6661
|
+
};
|
|
6662
|
+
const containerClasses = fullScreen ? "fixed inset-0 flex items-center justify-center bg-white/80 backdrop-blur-sm z-50" : "flex items-center justify-center p-4";
|
|
6663
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: `${containerClasses} ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "text-center", children: [
|
|
6664
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
6665
|
+
"div",
|
|
6666
|
+
{
|
|
6667
|
+
className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 mx-auto ${sizeClasses[size]}`
|
|
6668
|
+
}
|
|
6669
|
+
),
|
|
6670
|
+
text && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "mt-2 text-sm text-gray-600", children: text })
|
|
6671
|
+
] }) });
|
|
6672
|
+
};
|
|
6673
|
+
var LoadingSpinner = ({
|
|
6674
|
+
size = "md",
|
|
6675
|
+
className = ""
|
|
6676
|
+
}) => {
|
|
6677
|
+
const sizeClasses = {
|
|
6678
|
+
sm: "h-4 w-4",
|
|
6679
|
+
md: "h-8 w-8",
|
|
6680
|
+
lg: "h-12 w-12"
|
|
6681
|
+
};
|
|
6682
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
6683
|
+
"div",
|
|
6684
|
+
{
|
|
6685
|
+
className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 ${sizeClasses[size]} ${className}`
|
|
6686
|
+
}
|
|
6687
|
+
);
|
|
6688
|
+
};
|
|
6689
|
+
|
|
6690
|
+
// src/components/ui/ErrorBoundary.tsx
|
|
6691
|
+
var import_react9 = require("react");
|
|
6692
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
6693
|
+
var ErrorBoundary = class extends import_react9.Component {
|
|
6694
|
+
constructor(props) {
|
|
6695
|
+
super(props);
|
|
6696
|
+
this.handleRetry = () => {
|
|
6697
|
+
this.setState({ hasError: false, error: void 0, errorInfo: void 0 });
|
|
6698
|
+
};
|
|
6699
|
+
this.state = { hasError: false };
|
|
6700
|
+
}
|
|
6701
|
+
static getDerivedStateFromError(error) {
|
|
6702
|
+
return { hasError: true, error };
|
|
6703
|
+
}
|
|
6704
|
+
componentDidCatch(error, errorInfo) {
|
|
6705
|
+
this.setState({
|
|
6706
|
+
error,
|
|
6707
|
+
errorInfo
|
|
6708
|
+
});
|
|
6709
|
+
this.props.onError?.(error, errorInfo);
|
|
6710
|
+
}
|
|
6711
|
+
render() {
|
|
6712
|
+
if (this.state.hasError) {
|
|
6713
|
+
if (this.props.fallback) {
|
|
6714
|
+
const FallbackComponent = this.props.fallback;
|
|
6715
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FallbackComponent, { error: this.state.error, retry: this.handleRetry });
|
|
6716
|
+
}
|
|
6717
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "min-h-[400px] flex items-center justify-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "text-center max-w-md", children: [
|
|
6718
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-red-500 text-6xl mb-4", children: "\u26A0\uFE0F" }),
|
|
6719
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h2", { className: "text-xl font-semibold text-gray-900 mb-2", children: "Something went wrong" }),
|
|
6720
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-gray-600 mb-4", children: "An unexpected error occurred. Please try refreshing the page." }),
|
|
6721
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
6722
|
+
"button",
|
|
6723
|
+
{
|
|
6724
|
+
onClick: this.handleRetry,
|
|
6725
|
+
className: "px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors",
|
|
6726
|
+
children: "Try Again"
|
|
6727
|
+
}
|
|
6728
|
+
),
|
|
6729
|
+
false
|
|
6730
|
+
] }) });
|
|
6731
|
+
}
|
|
6732
|
+
return this.props.children;
|
|
6733
|
+
}
|
|
6734
|
+
};
|
|
6735
|
+
var DefaultErrorFallback = ({ retry }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "min-h-[200px] flex items-center justify-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "text-center", children: [
|
|
6736
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-red-500 text-4xl mb-2", children: "\u26A0\uFE0F" }),
|
|
6737
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-gray-600 mb-2", children: "Something went wrong" }),
|
|
6738
|
+
retry && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
6739
|
+
"button",
|
|
6740
|
+
{
|
|
6741
|
+
onClick: retry,
|
|
6742
|
+
className: "px-3 py-1 bg-blue-600 text-white text-sm rounded hover:bg-blue-700 transition-colors",
|
|
6743
|
+
children: "Retry"
|
|
6744
|
+
}
|
|
6745
|
+
)
|
|
6746
|
+
] }) });
|
|
6747
|
+
|
|
6748
|
+
// src/components/theme/ThemeToggle.tsx
|
|
6749
|
+
var React6 = __toESM(require("react"));
|
|
6750
|
+
var import_react10 = require("@iconify/react");
|
|
6751
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
6752
|
+
function ThemeToggle({ className }) {
|
|
6753
|
+
const { setTheme, theme } = useTheme();
|
|
6754
|
+
const [mounted, setMounted] = React6.useState(false);
|
|
6755
|
+
React6.useEffect(() => {
|
|
6756
|
+
setMounted(true);
|
|
6757
|
+
}, []);
|
|
6758
|
+
const handleToggle = () => {
|
|
6759
|
+
if (theme === "dark") {
|
|
6760
|
+
setTheme("light");
|
|
6761
|
+
} else {
|
|
6762
|
+
setTheme("dark");
|
|
6763
|
+
}
|
|
6764
|
+
};
|
|
6765
|
+
if (!mounted) {
|
|
6766
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
6767
|
+
"button",
|
|
6768
|
+
{
|
|
6769
|
+
className: `relative inline-flex h-10 w-12 items-center justify-center rounded-md border border-input bg-background hover:bg-accent hover:text-accent-foreground ${className || ""}`,
|
|
6770
|
+
disabled: true,
|
|
6771
|
+
children: [
|
|
6772
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react10.Icon, { icon: "solar:sun-bold", width: 20, height: 20 }),
|
|
6773
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "sr-only", children: "\u5207\u6362\u4E3B\u9898" })
|
|
6774
|
+
]
|
|
6775
|
+
}
|
|
6776
|
+
);
|
|
6777
|
+
}
|
|
6778
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
6779
|
+
"button",
|
|
6780
|
+
{
|
|
6781
|
+
className: `inline-flex h-10 w-12 items-center justify-center rounded-md border border-input bg-background hover:bg-accent hover:text-accent-foreground transition-colors ${className || ""}`,
|
|
6782
|
+
onClick: handleToggle,
|
|
6783
|
+
children: [
|
|
6784
|
+
theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react10.Icon, { icon: "solar:sun-bold", width: 20, height: 20 }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react10.Icon, { icon: "solar:moon-linear", width: 20, height: 20 }),
|
|
6785
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "sr-only", children: "\u5207\u6362\u4E3B\u9898" })
|
|
6786
|
+
]
|
|
6787
|
+
}
|
|
6788
|
+
);
|
|
6789
|
+
}
|
|
6790
|
+
|
|
6791
|
+
// src/components/ui/Toast/ClayxToast.tsx
|
|
6792
|
+
var import_react11 = __toESM(require("react"));
|
|
6793
|
+
var import_react_toastify2 = require("react-toastify");
|
|
6794
|
+
var import_react12 = require("@iconify/react");
|
|
6795
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
6796
|
+
var TOAST_ICONS = {
|
|
6797
|
+
success: {
|
|
6798
|
+
icon: "mdi:success",
|
|
6799
|
+
color: "text-green-400",
|
|
6800
|
+
className: "text-green-400",
|
|
6801
|
+
// 深色主题配置
|
|
6802
|
+
dark: {
|
|
6803
|
+
bgGradient: "bg-[#14181d]",
|
|
6804
|
+
// 移除透明度 f2
|
|
6805
|
+
gradientColor: "#389726",
|
|
6806
|
+
borderGradient: "border-[#389726]",
|
|
6807
|
+
borderGradientColor: "#389726"
|
|
6808
|
+
},
|
|
6809
|
+
// 浅色主题配置
|
|
6810
|
+
light: {
|
|
6811
|
+
bgGradient: "bg-[#fafafa]",
|
|
6812
|
+
// 移除透明度 ff
|
|
6813
|
+
gradientColor: "#22c55e",
|
|
6814
|
+
borderGradient: "border-[#22c55e]",
|
|
6815
|
+
borderGradientColor: "#22c55e"
|
|
6816
|
+
}
|
|
6817
|
+
},
|
|
6818
|
+
error: {
|
|
6819
|
+
icon: "ic:outline-close",
|
|
6820
|
+
color: "text-red-400",
|
|
6821
|
+
className: "text-red-400",
|
|
6822
|
+
dark: {
|
|
6823
|
+
bgGradient: "bg-[#14181d]",
|
|
6824
|
+
// 移除透明度 f2
|
|
6825
|
+
gradientColor: "#ef4444",
|
|
6826
|
+
borderGradient: "border-[#ef4444]",
|
|
6827
|
+
borderGradientColor: "#ef4444"
|
|
6828
|
+
},
|
|
6829
|
+
light: {
|
|
6830
|
+
bgGradient: "bg-[#fafafa]",
|
|
6831
|
+
// 移除透明度 ff
|
|
6832
|
+
gradientColor: "#f87171",
|
|
6833
|
+
borderGradient: "border-[#f87171]",
|
|
6834
|
+
borderGradientColor: "#f87171"
|
|
6835
|
+
}
|
|
6836
|
+
},
|
|
6837
|
+
warning: {
|
|
6838
|
+
icon: "mi:warning",
|
|
6839
|
+
color: "text-yellow-400",
|
|
6840
|
+
className: "text-yellow-400",
|
|
6841
|
+
dark: {
|
|
6842
|
+
bgGradient: "bg-[#14181d]",
|
|
6843
|
+
// 移除透明度 f2
|
|
6844
|
+
gradientColor: "#facc15",
|
|
6845
|
+
borderGradient: "border-[#facc15]",
|
|
6846
|
+
borderGradientColor: "#facc15"
|
|
6847
|
+
},
|
|
6848
|
+
light: {
|
|
6849
|
+
bgGradient: "bg-[#fafafa]",
|
|
6850
|
+
// 移除透明度 ff
|
|
6851
|
+
gradientColor: "#f59e0b",
|
|
6852
|
+
borderGradient: "border-[#f59e0b]",
|
|
6853
|
+
borderGradientColor: "#f59e0b"
|
|
6854
|
+
}
|
|
6855
|
+
},
|
|
6856
|
+
info: {
|
|
6857
|
+
icon: "ic:outline-info",
|
|
6858
|
+
color: "text-blue-400",
|
|
6859
|
+
className: "text-blue-400",
|
|
6860
|
+
dark: {
|
|
6861
|
+
bgGradient: "bg-[#14181d]",
|
|
6862
|
+
// 移除透明度 f2
|
|
6863
|
+
gradientColor: "#60a5fa",
|
|
6864
|
+
borderGradient: "border-[#60a5fa]",
|
|
6865
|
+
borderGradientColor: "#f0f0f0"
|
|
6866
|
+
},
|
|
6867
|
+
light: {
|
|
6868
|
+
bgGradient: "bg-[#fafafa]",
|
|
6869
|
+
// 移除透明度 ff
|
|
6870
|
+
gradientColor: "#3b82f6",
|
|
6871
|
+
borderGradient: "border-[#3b82f6]",
|
|
6872
|
+
borderGradientColor: "#3b82f6"
|
|
6873
|
+
}
|
|
6874
|
+
},
|
|
6875
|
+
default: {
|
|
6876
|
+
icon: "ic:round-notifications",
|
|
6877
|
+
color: "text-gray-400",
|
|
6878
|
+
className: "text-gray-400",
|
|
6879
|
+
dark: {
|
|
6880
|
+
bgGradient: "bg-[#14181d]",
|
|
6881
|
+
// 移除透明度 f2
|
|
6882
|
+
gradientColor: "#9ca3af",
|
|
6883
|
+
borderGradient: "border-[#9ca3af]",
|
|
6884
|
+
borderGradientColor: "#9ca3af"
|
|
6885
|
+
},
|
|
6886
|
+
light: {
|
|
6887
|
+
bgGradient: "bg-[#fafafa]",
|
|
6888
|
+
// 移除透明度 ff
|
|
6889
|
+
gradientColor: "#6b7280",
|
|
6890
|
+
borderGradient: "border-[#6b7280]",
|
|
6891
|
+
borderGradientColor: "#6b7280"
|
|
6892
|
+
}
|
|
6893
|
+
}
|
|
6894
|
+
};
|
|
6895
|
+
var CloseButton = import_react11.default.memo(({ closeToast }) => {
|
|
6896
|
+
const { theme } = useTheme();
|
|
6897
|
+
const handleClick = (0, import_react11.useCallback)((e) => {
|
|
6898
|
+
e.preventDefault();
|
|
6899
|
+
e.stopPropagation();
|
|
6900
|
+
closeToast?.();
|
|
6901
|
+
}, [closeToast]);
|
|
6902
|
+
const getCloseButtonColor = () => {
|
|
6903
|
+
const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
6904
|
+
return actualTheme === "dark" ? "#b4b4b4" : "#6b7280";
|
|
6905
|
+
};
|
|
6906
|
+
const getCloseButtonHoverColor = () => {
|
|
6907
|
+
const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
6908
|
+
return actualTheme === "dark" ? "white" : "#374151";
|
|
6909
|
+
};
|
|
6910
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
6911
|
+
import_react12.Icon,
|
|
6912
|
+
{
|
|
6913
|
+
icon: "vaadin:close",
|
|
6914
|
+
className: "flex items-center justify-center rounded-full relative z-10 flex-shrink-0 cursor-pointer \n transition-colors duration-200 drop-shadow-sm",
|
|
6915
|
+
onClick: handleClick,
|
|
6916
|
+
width: 14,
|
|
6917
|
+
height: 14,
|
|
6918
|
+
style: {
|
|
6919
|
+
color: getCloseButtonColor()
|
|
6920
|
+
},
|
|
6921
|
+
onMouseEnter: (e) => {
|
|
6922
|
+
e.currentTarget.style.color = getCloseButtonHoverColor();
|
|
6923
|
+
},
|
|
6924
|
+
onMouseLeave: (e) => {
|
|
6925
|
+
e.currentTarget.style.color = getCloseButtonColor();
|
|
6926
|
+
}
|
|
6927
|
+
}
|
|
6928
|
+
);
|
|
6929
|
+
});
|
|
6930
|
+
CloseButton.displayName = "CloseButton";
|
|
6931
|
+
var ToastContent = ({ type, title, message, component, closeToast }) => {
|
|
6932
|
+
const iconConfig = TOAST_ICONS[type];
|
|
6933
|
+
const { theme } = useTheme();
|
|
6934
|
+
const handleClose = (0, import_react11.useCallback)(() => {
|
|
6935
|
+
closeToast?.();
|
|
6936
|
+
}, [closeToast]);
|
|
6937
|
+
const getTextColor = () => {
|
|
6938
|
+
const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
6939
|
+
return actualTheme === "dark" ? "white" : "#1f2937";
|
|
6940
|
+
};
|
|
6941
|
+
const getThemeConfig = () => {
|
|
6942
|
+
const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
6943
|
+
return actualTheme === "dark" ? iconConfig.dark : iconConfig.light;
|
|
6944
|
+
};
|
|
6945
|
+
const themeConfig = getThemeConfig();
|
|
6946
|
+
if (component) {
|
|
6947
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `flex items-start gap-3 !min-h-[90px] w-full backdrop-blur-md p-4 shadow-2xl relative overflow-hidden ${themeConfig.bgGradient}`, children: [
|
|
6948
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex-1 relative z-10", children: component }),
|
|
6949
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "relative z-10", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CloseButton, { closeToast: handleClose }) })
|
|
6950
|
+
] });
|
|
6951
|
+
}
|
|
6952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `flex items-start gap-3 !min-h-[90px] w-full backdrop-blur-md p-4 shadow-2xl relative overflow-hidden ${themeConfig.bgGradient}`, children: [
|
|
6953
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
6954
|
+
"div",
|
|
6955
|
+
{
|
|
6956
|
+
className: "absolute left-0 top-0 w-full h-full rounded-xl",
|
|
6957
|
+
style: {
|
|
6958
|
+
background: theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "#0f1419" : "#ffffff",
|
|
6959
|
+
zIndex: -2
|
|
6960
|
+
}
|
|
6961
|
+
}
|
|
6962
|
+
),
|
|
6963
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
6964
|
+
"div",
|
|
6965
|
+
{
|
|
6966
|
+
className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-xl",
|
|
6967
|
+
style: {
|
|
6968
|
+
background: theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? `linear-gradient(135deg, ${themeConfig.gradientColor}30 0%, ${themeConfig.gradientColor}20 15%, #14181df2 30%)` : `linear-gradient(135deg, ${themeConfig.gradientColor}15 0%, ${themeConfig.gradientColor}08 15%, #fafafaff 30%)`,
|
|
6969
|
+
zIndex: -1
|
|
6970
|
+
}
|
|
6971
|
+
}
|
|
6972
|
+
),
|
|
6973
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
6974
|
+
"div",
|
|
6975
|
+
{
|
|
6976
|
+
className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-xl",
|
|
6977
|
+
style: {
|
|
6978
|
+
border: "2px solid transparent",
|
|
6979
|
+
backgroundImage: theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? `linear-gradient(135deg, ${themeConfig.borderGradientColor}60 0%, ${themeConfig.borderGradientColor}40 5%, transparent 22%)` : `linear-gradient(135deg, ${themeConfig.borderGradientColor}40 0%, ${themeConfig.borderGradientColor}25 5%, transparent 22%)`,
|
|
6980
|
+
backgroundOrigin: "border-box",
|
|
6981
|
+
backgroundClip: "border-box",
|
|
6982
|
+
WebkitMask: "linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)",
|
|
6983
|
+
WebkitMaskComposite: "xor",
|
|
6984
|
+
mask: "linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)",
|
|
6985
|
+
maskComposite: "exclude"
|
|
6986
|
+
}
|
|
6987
|
+
}
|
|
6988
|
+
),
|
|
6989
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex-shrink-0 mt-0.5 relative z-10", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `w-7 h-7 backdrop-blur-sm rounded-full flex items-center justify-center ${theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "bg-white/10" : "bg-black/5"}`, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
6990
|
+
import_react12.Icon,
|
|
6991
|
+
{
|
|
6992
|
+
icon: iconConfig.icon,
|
|
6993
|
+
width: 16,
|
|
6994
|
+
height: 16,
|
|
6995
|
+
className: iconConfig.color,
|
|
6996
|
+
style: {
|
|
6997
|
+
color: themeConfig.gradientColor
|
|
6998
|
+
}
|
|
6999
|
+
}
|
|
7000
|
+
) }) }),
|
|
7001
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-1 flex-1 relative z-10", children: [
|
|
7002
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7003
|
+
"div",
|
|
7004
|
+
{
|
|
7005
|
+
className: "text-[16px] font-semibold leading-tight drop-shadow-sm",
|
|
7006
|
+
style: {
|
|
7007
|
+
color: getTextColor(),
|
|
7008
|
+
backgroundClip: "text"
|
|
7009
|
+
},
|
|
7010
|
+
children: title
|
|
7011
|
+
}
|
|
7012
|
+
),
|
|
7013
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7014
|
+
"div",
|
|
7015
|
+
{
|
|
7016
|
+
className: "text-[13px] font-normal leading-relaxed drop-shadow-sm",
|
|
7017
|
+
style: {
|
|
7018
|
+
color: getTextColor(),
|
|
7019
|
+
backgroundClip: "text"
|
|
7020
|
+
},
|
|
7021
|
+
children: message
|
|
7022
|
+
}
|
|
7023
|
+
)
|
|
7024
|
+
] }),
|
|
7025
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "relative z-10", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CloseButton, { closeToast: handleClose }) })
|
|
7026
|
+
] });
|
|
7027
|
+
};
|
|
7028
|
+
var defaultToastOptions = {
|
|
7029
|
+
position: "bottom-right",
|
|
7030
|
+
autoClose: 3e3,
|
|
7031
|
+
hideProgressBar: true,
|
|
7032
|
+
closeOnClick: false,
|
|
7033
|
+
pauseOnHover: true,
|
|
7034
|
+
draggable: true,
|
|
7035
|
+
pauseOnFocusLoss: false,
|
|
7036
|
+
theme: "dark",
|
|
7037
|
+
transition: import_react_toastify2.Bounce
|
|
7038
|
+
};
|
|
7039
|
+
var createToast = (type) => {
|
|
7040
|
+
return (params) => {
|
|
7041
|
+
const { title, message, component, options } = params;
|
|
7042
|
+
(0, import_react_toastify2.toast)(
|
|
7043
|
+
({ closeToast }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7044
|
+
ToastContent,
|
|
7045
|
+
{
|
|
7046
|
+
type,
|
|
7047
|
+
title,
|
|
7048
|
+
message: message || "",
|
|
7049
|
+
component,
|
|
7050
|
+
closeToast
|
|
7051
|
+
}
|
|
7052
|
+
),
|
|
7053
|
+
{
|
|
7054
|
+
...defaultToastOptions,
|
|
7055
|
+
...options,
|
|
7056
|
+
// 确保圆角样式不被覆盖,添加 rounded-xl 类
|
|
7057
|
+
className: "!p-0 !shadow-none !rounded-xl",
|
|
7058
|
+
style: { padding: 0, borderRadius: "0.75rem" }
|
|
7059
|
+
}
|
|
7060
|
+
);
|
|
7061
|
+
};
|
|
7062
|
+
};
|
|
7063
|
+
var ClayxToast = {
|
|
7064
|
+
success: createToast("success"),
|
|
7065
|
+
error: createToast("error"),
|
|
7066
|
+
warning: createToast("warning"),
|
|
7067
|
+
info: createToast("info"),
|
|
7068
|
+
default: createToast("default")
|
|
7069
|
+
};
|
|
7070
|
+
|
|
7071
|
+
// src/hooks/use-mobile.ts
|
|
7072
|
+
var React8 = __toESM(require("react"));
|
|
7073
|
+
var MOBILE_BREAKPOINT = 768;
|
|
7074
|
+
function useIsMobile() {
|
|
7075
|
+
const [isMobile, setIsMobile] = React8.useState(void 0);
|
|
7076
|
+
React8.useEffect(() => {
|
|
7077
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
7078
|
+
const onChange = () => {
|
|
7079
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
7080
|
+
};
|
|
7081
|
+
mql.addEventListener("change", onChange);
|
|
7082
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
7083
|
+
return () => mql.removeEventListener("change", onChange);
|
|
7084
|
+
}, []);
|
|
7085
|
+
return !!isMobile;
|
|
7086
|
+
}
|
|
7087
|
+
|
|
7088
|
+
// src/hooks/use-debounce.ts
|
|
7089
|
+
var import_react13 = require("react");
|
|
7090
|
+
function useDebounce(value, delay) {
|
|
7091
|
+
const [debouncedValue, setDebouncedValue] = (0, import_react13.useState)(value);
|
|
7092
|
+
(0, import_react13.useEffect)(() => {
|
|
7093
|
+
const handler = setTimeout(() => {
|
|
7094
|
+
setDebouncedValue(value);
|
|
7095
|
+
}, delay);
|
|
7096
|
+
return () => {
|
|
7097
|
+
clearTimeout(handler);
|
|
7098
|
+
};
|
|
7099
|
+
}, [value, delay]);
|
|
7100
|
+
return debouncedValue;
|
|
7101
|
+
}
|
|
7102
|
+
|
|
6875
7103
|
// src/utils/unified-error-handler/simple.ts
|
|
6876
7104
|
var SimpleErrorHandler = class {
|
|
6877
7105
|
constructor() {
|
|
@@ -6967,6 +7195,8 @@ init_config();
|
|
|
6967
7195
|
DEFAULT_SELECTOR_CONFIG,
|
|
6968
7196
|
DefaultErrorFallback,
|
|
6969
7197
|
ERROR_CONFIG,
|
|
7198
|
+
ElementSelector,
|
|
7199
|
+
ElementSelectorProvider,
|
|
6970
7200
|
ErrorBoundary,
|
|
6971
7201
|
ErrorHandler,
|
|
6972
7202
|
FloatingButton,
|
|
@@ -6996,6 +7226,7 @@ init_config();
|
|
|
6996
7226
|
onAuthStateChanged,
|
|
6997
7227
|
parseUserFromToken,
|
|
6998
7228
|
request,
|
|
7229
|
+
sendElementSelectionToParent,
|
|
6999
7230
|
sendEmailVerificationCode,
|
|
7000
7231
|
setAuthRoot,
|
|
7001
7232
|
setDefaultProjectId,
|
|
@@ -7004,6 +7235,7 @@ init_config();
|
|
|
7004
7235
|
unifiedOAuth,
|
|
7005
7236
|
useAuth,
|
|
7006
7237
|
useDebounce,
|
|
7238
|
+
useElementSelector,
|
|
7007
7239
|
useHowoneContext,
|
|
7008
7240
|
useIsMobile,
|
|
7009
7241
|
useTheme,
|