@howone/sdk 0.3.21 → 0.3.23

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.mjs CHANGED
@@ -258,6 +258,69 @@ var init_auth = __esm({
258
258
  }
259
259
  });
260
260
 
261
+ // src/utils/session.ts
262
+ var session_exports = {};
263
+ __export(session_exports, {
264
+ clearGuestSession: () => clearGuestSession,
265
+ consumeGuestSession: () => consumeGuestSession,
266
+ getExistingSessionId: () => getExistingSessionId,
267
+ getGuestSessionId: () => getGuestSessionId,
268
+ isGuestMode: () => isGuestMode
269
+ });
270
+ function getGuestSessionId() {
271
+ if (typeof window === "undefined") return null;
272
+ try {
273
+ let sessionId = localStorage.getItem(GUEST_SESSION_KEY);
274
+ if (!sessionId) {
275
+ sessionId = crypto.randomUUID();
276
+ localStorage.setItem(GUEST_SESSION_KEY, sessionId);
277
+ }
278
+ return sessionId;
279
+ } catch {
280
+ return null;
281
+ }
282
+ }
283
+ function clearGuestSession() {
284
+ if (typeof window === "undefined") return;
285
+ try {
286
+ localStorage.removeItem(GUEST_SESSION_KEY);
287
+ } catch {
288
+ }
289
+ }
290
+ function isGuestMode() {
291
+ if (typeof window === "undefined") return false;
292
+ const hasAuthToken = !!localStorage.getItem("auth_token");
293
+ const hasSession = !!localStorage.getItem(GUEST_SESSION_KEY);
294
+ return !hasAuthToken && hasSession;
295
+ }
296
+ function getExistingSessionId() {
297
+ if (typeof window === "undefined") return null;
298
+ try {
299
+ return localStorage.getItem(GUEST_SESSION_KEY);
300
+ } catch {
301
+ return null;
302
+ }
303
+ }
304
+ function consumeGuestSession() {
305
+ if (typeof window === "undefined") return null;
306
+ try {
307
+ const sessionId = localStorage.getItem(GUEST_SESSION_KEY);
308
+ if (sessionId) {
309
+ localStorage.removeItem(GUEST_SESSION_KEY);
310
+ }
311
+ return sessionId;
312
+ } catch {
313
+ return null;
314
+ }
315
+ }
316
+ var GUEST_SESSION_KEY;
317
+ var init_session = __esm({
318
+ "src/utils/session.ts"() {
319
+ "use strict";
320
+ GUEST_SESSION_KEY = "howone_guest_session";
321
+ }
322
+ });
323
+
261
324
  // src/components/FloatingButton.tsx
262
325
  import { Icon } from "@iconify/react/dist/iconify.js";
263
326
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -951,7 +1014,7 @@ var LoginForm = ({
951
1014
 
952
1015
  // src/components/auth/HowoneProvider.tsx
953
1016
  init_auth();
954
- import { createContext as createContext2, useContext as useContext2, useState as useState7, useEffect as useEffect6, useMemo, useCallback as useCallback4 } from "react";
1017
+ import { createContext as createContext2, useContext as useContext2, useState as useState8, useEffect as useEffect7, useMemo, useCallback as useCallback5 } from "react";
955
1018
 
956
1019
  // src/components/theme/ThemeProvider.tsx
957
1020
  import { createContext, useContext, useEffect as useEffect3, useState as useState3 } from "react";
@@ -1249,666 +1312,176 @@ var ElementSelectorProvider = ({ children }) => {
1249
1312
 
1250
1313
  // src/components/auth/HowoneProvider.tsx
1251
1314
  init_config();
1252
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1253
- var HowoneContext = createContext2(null);
1254
- var redirectOverlayStylesInjected = false;
1255
- var injectRedirectOverlayStyles = () => {
1256
- if (redirectOverlayStylesInjected || typeof document === "undefined") return;
1257
- const style = document.createElement("style");
1258
- style.setAttribute("data-howone-auth-overlay", "true");
1259
- style.textContent = `
1260
- @keyframes howone-logo-pulse {
1261
- 0%, 100% {
1262
- opacity: 0.2;
1263
- transform: scale(0.95);
1264
- filter: drop-shadow(0 0 0 rgba(255, 255, 255, 0.2));
1265
- }
1266
- 50% {
1267
- opacity: 1;
1268
- transform: scale(1.03);
1269
- filter: drop-shadow(0 0 28px rgba(255, 255, 255, 0.55));
1270
- }
1271
- }
1315
+ init_session();
1272
1316
 
1273
- @keyframes howone-glow-ring {
1274
- 0%, 100% {
1275
- opacity: 0.12;
1276
- transform: scale(0.85);
1277
- }
1278
- 50% {
1279
- opacity: 0.42;
1280
- transform: scale(1.05);
1281
- }
1282
- }
1317
+ // src/components/ui/Toast/ClayxToast.tsx
1318
+ import React5, { useCallback as useCallback4 } from "react";
1319
+ import { Bounce, toast } from "react-toastify";
1320
+ import { Icon as Icon4 } from "@iconify/react";
1283
1321
 
1284
- [data-howone-auth-overlay-root] {
1285
- position: fixed;
1286
- inset: 0;
1287
- z-index: 2147483646;
1288
- display: flex;
1289
- flex-direction: column;
1290
- align-items: center;
1291
- justify-content: center;
1292
- width: 100vw;
1293
- height: 100vh;
1294
- color: #ffffff;
1295
- background: rgba(0, 0, 0, 0.65);
1296
- backdrop-filter: blur(6px);
1297
- -webkit-backdrop-filter: blur(6px);
1298
- text-align: center;
1299
- }
1300
- `;
1301
- document.head.appendChild(style);
1302
- redirectOverlayStylesInjected = true;
1303
- };
1304
- var HowOneProvider = ({
1305
- children,
1306
- showFloatingButton = true,
1307
- projectId,
1308
- defaultTheme = "system",
1309
- themeStorageKey = "howone-theme",
1310
- forceDefaultTheme = false,
1311
- redirectOnUnauthenticated = true
1312
- }) => {
1313
- const [user, setUser] = useState7(() => parseUserFromToken(getToken()));
1314
- const [token, setTokenState] = useState7(() => getToken());
1315
- const [hasCheckedUrlToken, setHasCheckedUrlToken] = useState7(false);
1316
- const [pendingRedirect, setPendingRedirect] = useState7(false);
1317
- useEffect6(() => {
1318
- try {
1319
- const params = new URLSearchParams(window.location.search);
1320
- let urlToken = params.get("access_token") || params.get("token");
1321
- if (!urlToken && window.location.hash) {
1322
- const hashParams = new URLSearchParams(window.location.hash.slice(1));
1323
- urlToken = hashParams.get("access_token") || hashParams.get("token");
1324
- }
1325
- if (urlToken) {
1326
- setToken(urlToken);
1327
- setTokenState(urlToken);
1328
- setUser(parseUserFromToken(urlToken));
1329
- params.delete("access_token");
1330
- params.delete("token");
1331
- params.delete("project_id");
1332
- const newSearch = params.toString();
1333
- const newUrl = window.location.pathname + (newSearch ? "?" + newSearch : "");
1334
- window.history.replaceState({}, "", newUrl);
1335
- }
1336
- } catch (e) {
1337
- console.error("[HowOneProvider] Failed to capture token from URL:", e);
1338
- } finally {
1339
- setHasCheckedUrlToken(true);
1340
- }
1341
- }, []);
1342
- const resolvedAuthUrl = useMemo(() => {
1343
- const env3 = getGlobalEnvironment() ?? "dev";
1344
- switch (env3) {
1345
- case "local":
1346
- return "http://localhost:3000/auth";
1347
- case "prod":
1348
- return "https://howone.ai/auth";
1349
- case "dev":
1350
- default:
1351
- return "https://howone.dev/auth";
1352
- }
1322
+ // src/components/theme/ThemeToggle.tsx
1323
+ import * as React4 from "react";
1324
+ import { Icon as Icon3 } from "@iconify/react";
1325
+ import { jsx as jsx7 } from "react/jsx-runtime";
1326
+ function ThemeToggle({ className }) {
1327
+ const { setTheme, theme } = useTheme();
1328
+ const [mounted, setMounted] = React4.useState(false);
1329
+ React4.useEffect(() => {
1330
+ setMounted(true);
1353
1331
  }, []);
1354
- useEffect6(() => {
1355
- if (pendingRedirect) {
1356
- injectRedirectOverlayStyles();
1357
- }
1358
- }, [pendingRedirect]);
1359
- useEffect6(() => {
1360
- if (pendingRedirect) {
1361
- injectRedirectOverlayStyles();
1362
- }
1363
- }, [pendingRedirect]);
1364
- const redirectToAuth = useCallback4(() => {
1365
- if (!redirectOnUnauthenticated || typeof window === "undefined") return;
1366
- const activeProjectId = projectId ?? getDefaultProjectId();
1367
- const navigateToResolvedAuth = () => {
1368
- setPendingRedirect(true);
1369
- requestAnimationFrame(() => {
1370
- if (activeProjectId) {
1371
- try {
1372
- const url = new URL(resolvedAuthUrl);
1373
- url.searchParams.set("redirect_uri", window.location.href);
1374
- url.searchParams.set("project_id", activeProjectId);
1375
- window.location.href = url.toString();
1376
- return;
1377
- } catch (error) {
1378
- console.error("[HowOneProvider] Failed to attach project_id to auth URL:", error);
1379
- }
1380
- }
1381
- window.location.href = resolvedAuthUrl;
1382
- });
1383
- };
1384
- try {
1385
- const currentUrl = new URL(window.location.href);
1386
- if (currentUrl.pathname.includes("/auth")) return;
1387
- try {
1388
- const authUrlObj = new URL(resolvedAuthUrl);
1389
- authUrlObj.searchParams.set("redirect_uri", window.location.href);
1390
- if (activeProjectId) {
1391
- authUrlObj.searchParams.set("project_id", activeProjectId);
1392
- }
1393
- setPendingRedirect(true);
1394
- requestAnimationFrame(() => {
1395
- window.location.href = authUrlObj.toString();
1396
- });
1397
- return;
1398
- } catch (error) {
1399
- console.error("[HowOneProvider] Failed to build auth URL:", error);
1400
- }
1401
- navigateToResolvedAuth();
1402
- } catch {
1403
- navigateToResolvedAuth();
1404
- }
1405
- }, [redirectOnUnauthenticated, resolvedAuthUrl, projectId]);
1406
- useEffect6(() => {
1407
- if (!hasCheckedUrlToken) return;
1408
- if (!token && !user) {
1409
- redirectToAuth();
1410
- }
1411
- }, [token, user, hasCheckedUrlToken, redirectToAuth]);
1412
- const logout = () => {
1413
- try {
1414
- setToken(null);
1415
- } catch {
1332
+ const handleToggle = () => {
1333
+ if (theme === "dark") {
1334
+ setTheme("light");
1335
+ } else {
1336
+ setTheme("dark");
1416
1337
  }
1417
- setTokenState(null);
1418
- setUser(null);
1419
- redirectToAuth();
1420
- };
1421
- const value = {
1422
- user,
1423
- token,
1424
- isAuthenticated: hasCheckedUrlToken && !!token,
1425
- logout
1426
1338
  };
1427
- if (!hasCheckedUrlToken) return null;
1428
- return /* @__PURE__ */ jsxs5(
1429
- ThemeProvider,
1339
+ if (!mounted) {
1340
+ return /* @__PURE__ */ jsx7(Icon3, { icon: "solar:sun-bold", width: 20, height: 20 });
1341
+ }
1342
+ return /* @__PURE__ */ jsx7(
1343
+ "div",
1430
1344
  {
1431
- defaultTheme,
1432
- storageKey: themeStorageKey,
1433
- forceDefault: forceDefaultTheme,
1434
- children: [
1435
- /* @__PURE__ */ jsx7(ElementSelectorProvider, { children: /* @__PURE__ */ jsxs5(HowoneContext.Provider, { value, children: [
1436
- children,
1437
- showFloatingButton && /* @__PURE__ */ jsx7(FloatingButton, { onClick: () => window.open("https://howone.ai", "_blank") }),
1438
- pendingRedirect && /* @__PURE__ */ jsx7(
1439
- "div",
1440
- {
1441
- "data-howone-auth-overlay-root": true,
1442
- className: "fixed inset-0 z-[100000] h-full w-full flex flex-col items-center justify-center bg-black/65 backdrop-blur-sm text-white",
1443
- children: /* @__PURE__ */ jsxs5("div", { className: "relative mt-6 flex h-[220px] w-[220px] items-center justify-center", children: [
1444
- /* @__PURE__ */ jsx7(
1445
- "div",
1446
- {
1447
- className: "absolute inset-0 rounded-full bg-white/20",
1448
- style: { animation: "howone-glow-ring 2.4s ease-in-out infinite" }
1449
- }
1450
- ),
1451
- /* @__PURE__ */ jsx7("div", { className: "absolute inset-0 rounded-full bg-gradient-to-br from-white/10 via-white/25 to-white/10 blur-2xl" }),
1452
- /* @__PURE__ */ jsx7(
1453
- "img",
1454
- {
1455
- style: { width: 250, animation: "howone-logo-pulse 2s ease-in-out infinite" },
1456
- src: "https://sxwxqoixnnklnpeutjrj.supabase.co/storage/v1/object/public/create-x/logo/logo.svg",
1457
- alt: "HowOne"
1458
- }
1459
- )
1460
- ] })
1461
- }
1462
- )
1463
- ] }) }),
1464
- /* @__PURE__ */ jsx7(GlobalToastContainer, {})
1465
- ]
1345
+ className: `cursor-pointer ${className || ""}`,
1346
+ onClick: handleToggle,
1347
+ children: theme === "light" ? /* @__PURE__ */ jsx7(Icon3, { icon: "solar:sun-bold", width: 20, height: 20 }) : /* @__PURE__ */ jsx7(Icon3, { icon: "solar:moon-linear", width: 20, height: 20 })
1466
1348
  }
1467
1349
  );
1468
- };
1469
- function useHowoneContext() {
1470
- const ctx = useContext2(HowoneContext);
1471
- if (!ctx) {
1472
- const t = getToken();
1473
- return {
1474
- user: parseUserFromToken(t),
1475
- token: t,
1476
- isAuthenticated: !!t,
1477
- logout: () => {
1478
- try {
1479
- setToken(null);
1480
- } catch {
1481
- }
1482
- }
1483
- };
1484
- }
1485
- return ctx;
1486
1350
  }
1487
1351
 
1488
- // src/components/index.ts
1489
- init_auth();
1490
-
1491
- // src/howone/client.ts
1492
- init_auth();
1493
- init_config();
1494
- var HowoneAuthClient = class {
1495
- constructor() {
1496
- this.listeners = /* @__PURE__ */ new Set();
1497
- this.loading = false;
1498
- }
1499
- emit() {
1500
- const state = {
1501
- user: parseUserFromToken(getToken()),
1502
- isLoading: this.loading
1503
- };
1504
- for (const l of this.listeners) {
1505
- try {
1506
- l(state);
1507
- } catch (e) {
1508
- void e;
1509
- }
1352
+ // src/components/ui/Toast/ClayxToast.tsx
1353
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1354
+ var TOAST_ICONS = {
1355
+ success: {
1356
+ icon: "mdi:success",
1357
+ color: "text-green-400",
1358
+ className: "text-green-400",
1359
+ // 深色主题配置
1360
+ dark: {
1361
+ bgGradient: "bg-[#14181d]",
1362
+ // 移除透明度 f2
1363
+ gradientColor: "#389726",
1364
+ borderGradient: "border-[#389726]",
1365
+ borderGradientColor: "#389726"
1366
+ },
1367
+ // 浅色主题配置
1368
+ light: {
1369
+ bgGradient: "bg-[#fafafa]",
1370
+ // 移除透明度 ff
1371
+ gradientColor: "#22c55e",
1372
+ borderGradient: "border-[#22c55e]",
1373
+ borderGradientColor: "#22c55e"
1510
1374
  }
1511
- }
1512
- onAuthStateChanged(listener) {
1513
- this.listeners.add(listener);
1514
- try {
1515
- listener({ user: parseUserFromToken(getToken()), isLoading: this.loading });
1516
- } catch (e) {
1517
- void e;
1375
+ },
1376
+ error: {
1377
+ icon: "ic:outline-close",
1378
+ color: "text-red-400",
1379
+ className: "text-red-400",
1380
+ dark: {
1381
+ bgGradient: "bg-[#14181d]",
1382
+ // 移除透明度 f2
1383
+ gradientColor: "#ef4444",
1384
+ borderGradient: "border-[#ef4444]",
1385
+ borderGradientColor: "#ef4444"
1386
+ },
1387
+ light: {
1388
+ bgGradient: "bg-[#fafafa]",
1389
+ // 移除透明度 ff
1390
+ gradientColor: "#f87171",
1391
+ borderGradient: "border-[#f87171]",
1392
+ borderGradientColor: "#f87171"
1518
1393
  }
1519
- return () => {
1520
- this.listeners.delete(listener);
1521
- };
1522
- }
1523
- // Simple redirect-based login trigger (consumer can override)
1524
- login() {
1525
- const root = getEnvs().AUTH_ROOT_VALUE;
1526
- try {
1527
- const loc = window.location.href;
1528
- const authUrl = new URL("/auth", String(root));
1529
- authUrl.searchParams.set("redirect_uri", String(loc));
1530
- try {
1531
- const cfg = (init_config(), __toCommonJS(config_exports));
1532
- const pid = cfg.getDefaultProjectId && cfg.getDefaultProjectId();
1533
- if (pid) authUrl.searchParams.set("project_id", String(pid));
1534
- } catch {
1535
- }
1536
- try {
1537
- if (window.top && window.top !== window) {
1538
- window.top.location.replace(authUrl.toString());
1539
- } else {
1540
- window.location.replace(authUrl.toString());
1541
- }
1542
- } catch {
1543
- try {
1544
- window.location.replace(String(root));
1545
- } catch {
1546
- }
1547
- }
1548
- } catch {
1549
- try {
1550
- window.location.replace(String(root));
1551
- } catch {
1552
- }
1394
+ },
1395
+ warning: {
1396
+ icon: "mi:warning",
1397
+ color: "text-yellow-400",
1398
+ className: "text-yellow-400",
1399
+ dark: {
1400
+ bgGradient: "bg-[#14181d]",
1401
+ // 移除透明度 f2
1402
+ gradientColor: "#facc15",
1403
+ borderGradient: "border-[#facc15]",
1404
+ borderGradientColor: "#facc15"
1405
+ },
1406
+ light: {
1407
+ bgGradient: "bg-[#fafafa]",
1408
+ // 移除透明度 ff
1409
+ gradientColor: "#f59e0b",
1410
+ borderGradient: "border-[#f59e0b]",
1411
+ borderGradientColor: "#f59e0b"
1412
+ }
1413
+ },
1414
+ info: {
1415
+ icon: "ic:outline-info",
1416
+ color: "text-blue-400",
1417
+ className: "text-blue-400",
1418
+ dark: {
1419
+ bgGradient: "bg-[#14181d]",
1420
+ // 移除透明度 f2
1421
+ gradientColor: "#60a5fa",
1422
+ borderGradient: "border-[#60a5fa]",
1423
+ borderGradientColor: "#f0f0f0"
1424
+ },
1425
+ light: {
1426
+ bgGradient: "bg-[#fafafa]",
1427
+ // 移除透明度 ff
1428
+ gradientColor: "#3b82f6",
1429
+ borderGradient: "border-[#3b82f6]",
1430
+ borderGradientColor: "#3b82f6"
1431
+ }
1432
+ },
1433
+ default: {
1434
+ icon: "ic:round-notifications",
1435
+ color: "text-gray-400",
1436
+ className: "text-gray-400",
1437
+ dark: {
1438
+ bgGradient: "bg-[#14181d]",
1439
+ // 移除透明度 f2
1440
+ gradientColor: "#9ca3af",
1441
+ borderGradient: "border-[#9ca3af]",
1442
+ borderGradientColor: "#9ca3af"
1443
+ },
1444
+ light: {
1445
+ bgGradient: "bg-[#fafafa]",
1446
+ // 移除透明度 ff
1447
+ gradientColor: "#6b7280",
1448
+ borderGradient: "border-[#6b7280]",
1449
+ borderGradientColor: "#6b7280"
1553
1450
  }
1554
- }
1555
- logout() {
1556
- setToken(null);
1557
- this.emit();
1558
- }
1559
- getUser() {
1560
- return parseUserFromToken(getToken());
1561
- }
1562
- // helper to programmatically set token (e.g., after callback handling)
1563
- setToken(token) {
1564
- setToken(token);
1565
- this.emit();
1566
1451
  }
1567
1452
  };
1568
- var howone = {
1569
- auth: new HowoneAuthClient()
1570
- };
1571
- var client_default = howone;
1572
-
1573
- // src/components/ui/Loading.tsx
1574
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1575
- var Loading = ({
1576
- size = "md",
1577
- text = "Loading...",
1578
- className = "",
1579
- fullScreen = false
1580
- }) => {
1581
- const sizeClasses = {
1582
- sm: "h-4 w-4",
1583
- md: "h-8 w-8",
1584
- lg: "h-12 w-12"
1453
+ var CloseButton = React5.memo(({ closeToast }) => {
1454
+ const { theme } = useTheme();
1455
+ const handleClick = useCallback4((e) => {
1456
+ e.preventDefault();
1457
+ e.stopPropagation();
1458
+ closeToast?.();
1459
+ }, [closeToast]);
1460
+ const getCloseButtonColor = () => {
1461
+ const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
1462
+ return actualTheme === "dark" ? "#b4b4b4" : "#6b7280";
1585
1463
  };
1586
- 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";
1587
- return /* @__PURE__ */ jsx8("div", { className: `${containerClasses} ${className}`, children: /* @__PURE__ */ jsxs6("div", { className: "text-center", children: [
1588
- /* @__PURE__ */ jsx8(
1589
- "div",
1590
- {
1591
- className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 mx-auto ${sizeClasses[size]}`
1592
- }
1593
- ),
1594
- text && /* @__PURE__ */ jsx8("p", { className: "mt-2 text-sm text-gray-600", children: text })
1595
- ] }) });
1596
- };
1597
- var LoadingSpinner = ({
1598
- size = "md",
1599
- className = ""
1600
- }) => {
1601
- const sizeClasses = {
1602
- sm: "h-4 w-4",
1603
- md: "h-8 w-8",
1604
- lg: "h-12 w-12"
1464
+ const getCloseButtonHoverColor = () => {
1465
+ const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
1466
+ return actualTheme === "dark" ? "white" : "#374151";
1605
1467
  };
1606
1468
  return /* @__PURE__ */ jsx8(
1607
- "div",
1469
+ Icon4,
1608
1470
  {
1609
- className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 ${sizeClasses[size]} ${className}`
1610
- }
1611
- );
1612
- };
1613
-
1614
- // src/components/ui/ErrorBoundary.tsx
1615
- import { Component } from "react";
1616
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1617
- var ErrorBoundary = class extends Component {
1618
- constructor(props) {
1619
- super(props);
1620
- this.handleRetry = () => {
1621
- this.setState({ hasError: false, error: void 0, errorInfo: void 0 });
1622
- };
1623
- this.state = { hasError: false };
1624
- }
1625
- static getDerivedStateFromError(error) {
1626
- return { hasError: true, error };
1627
- }
1628
- componentDidCatch(error, errorInfo) {
1629
- this.setState({
1630
- error,
1631
- errorInfo
1632
- });
1633
- this.props.onError?.(error, errorInfo);
1634
- }
1635
- render() {
1636
- if (this.state.hasError) {
1637
- if (this.props.fallback) {
1638
- const FallbackComponent = this.props.fallback;
1639
- return /* @__PURE__ */ jsx9(FallbackComponent, { error: this.state.error, retry: this.handleRetry });
1640
- }
1641
- return /* @__PURE__ */ jsx9("div", { className: "min-h-[400px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs7("div", { className: "text-center max-w-md", children: [
1642
- /* @__PURE__ */ jsx9("div", { className: "text-red-500 text-6xl mb-4", children: "\u26A0\uFE0F" }),
1643
- /* @__PURE__ */ jsx9("h2", { className: "text-xl font-semibold text-gray-900 mb-2", children: "Something went wrong" }),
1644
- /* @__PURE__ */ jsx9("p", { className: "text-gray-600 mb-4", children: "An unexpected error occurred. Please try refreshing the page." }),
1645
- /* @__PURE__ */ jsx9(
1646
- "button",
1647
- {
1648
- onClick: this.handleRetry,
1649
- className: "px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors",
1650
- children: "Try Again"
1651
- }
1652
- ),
1653
- false
1654
- ] }) });
1655
- }
1656
- return this.props.children;
1657
- }
1658
- };
1659
- var DefaultErrorFallback = ({ retry }) => /* @__PURE__ */ jsx9("div", { className: "min-h-[200px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs7("div", { className: "text-center", children: [
1660
- /* @__PURE__ */ jsx9("div", { className: "text-red-500 text-4xl mb-2", children: "\u26A0\uFE0F" }),
1661
- /* @__PURE__ */ jsx9("p", { className: "text-gray-600 mb-2", children: "Something went wrong" }),
1662
- retry && /* @__PURE__ */ jsx9(
1663
- "button",
1664
- {
1665
- onClick: retry,
1666
- className: "px-3 py-1 bg-blue-600 text-white text-sm rounded hover:bg-blue-700 transition-colors",
1667
- children: "Retry"
1668
- }
1669
- )
1670
- ] }) });
1671
-
1672
- // src/components/ui/ClayxButton.tsx
1673
- import { jsx as jsx10 } from "react/jsx-runtime";
1674
- var getSizeClasses = (size, isIconOnly) => {
1675
- if (isIconOnly) {
1676
- switch (size) {
1677
- case "sm":
1678
- return "h-8 w-8 min-w-8 p-0";
1679
- case "md":
1680
- return "h-10 w-10 min-w-10 p-0";
1681
- case "lg":
1682
- return "h-12 w-12 min-w-12 p-0";
1683
- default:
1684
- return "h-10 w-10 min-w-10 p-0";
1685
- }
1686
- }
1687
- switch (size) {
1688
- case "sm":
1689
- return "h-8 px-3 text-sm";
1690
- case "md":
1691
- return "h-10 px-4 text-base";
1692
- case "lg":
1693
- return "h-12 px-6 text-lg";
1694
- default:
1695
- return "h-10 px-4 text-base";
1696
- }
1697
- };
1698
- var getVariantClasses = (variant) => {
1699
- switch (variant) {
1700
- case "solid":
1701
- return "bg-primary text-white hover:bg-primary/90";
1702
- case "ghost":
1703
- return "bg-transparent hover:bg-white/10";
1704
- case "flat":
1705
- return "bg-white/5 hover:bg-white/10";
1706
- default:
1707
- return "";
1708
- }
1709
- };
1710
- var ClayxButton = ({
1711
- isIconOnly = false,
1712
- size = "md",
1713
- variant = "solid",
1714
- className = "",
1715
- children,
1716
- disabled = false,
1717
- ...props
1718
- }) => {
1719
- const sizeClasses = getSizeClasses(size, isIconOnly);
1720
- const variantClasses = getVariantClasses(variant);
1721
- const baseClasses = `
1722
- inline-flex items-center justify-center
1723
- rounded-md font-medium
1724
- transition-all duration-200
1725
- focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-transparent
1726
- disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none
1727
- `.replace(/\s+/g, " ").trim();
1728
- const combinedClasses = `${baseClasses} ${sizeClasses} ${variantClasses} ${className}`.trim();
1729
- return /* @__PURE__ */ jsx10(
1730
- "button",
1731
- {
1732
- className: combinedClasses,
1733
- disabled,
1734
- ...props,
1735
- children
1736
- }
1737
- );
1738
- };
1739
-
1740
- // src/components/ui/LimitUpgradeToast.tsx
1741
- import React8 from "react";
1742
- import { Icon as Icon5 } from "@iconify/react";
1743
-
1744
- // src/components/ui/Toast/ClayxToast.tsx
1745
- import React7, { useCallback as useCallback5 } from "react";
1746
- import { Bounce, toast } from "react-toastify";
1747
- import { Icon as Icon4 } from "@iconify/react";
1748
-
1749
- // src/components/theme/ThemeToggle.tsx
1750
- import * as React6 from "react";
1751
- import { Icon as Icon3 } from "@iconify/react";
1752
- import { jsx as jsx11 } from "react/jsx-runtime";
1753
- function ThemeToggle({ className }) {
1754
- const { setTheme, theme } = useTheme();
1755
- const [mounted, setMounted] = React6.useState(false);
1756
- React6.useEffect(() => {
1757
- setMounted(true);
1758
- }, []);
1759
- const handleToggle = () => {
1760
- if (theme === "dark") {
1761
- setTheme("light");
1762
- } else {
1763
- setTheme("dark");
1764
- }
1765
- };
1766
- if (!mounted) {
1767
- return /* @__PURE__ */ jsx11(Icon3, { icon: "solar:sun-bold", width: 20, height: 20 });
1768
- }
1769
- return /* @__PURE__ */ jsx11(
1770
- "div",
1771
- {
1772
- className: `cursor-pointer ${className || ""}`,
1773
- onClick: handleToggle,
1774
- children: theme === "light" ? /* @__PURE__ */ jsx11(Icon3, { icon: "solar:sun-bold", width: 20, height: 20 }) : /* @__PURE__ */ jsx11(Icon3, { icon: "solar:moon-linear", width: 20, height: 20 })
1775
- }
1776
- );
1777
- }
1778
-
1779
- // src/components/ui/Toast/ClayxToast.tsx
1780
- import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1781
- var TOAST_ICONS = {
1782
- success: {
1783
- icon: "mdi:success",
1784
- color: "text-green-400",
1785
- className: "text-green-400",
1786
- // 深色主题配置
1787
- dark: {
1788
- bgGradient: "bg-[#14181d]",
1789
- // 移除透明度 f2
1790
- gradientColor: "#389726",
1791
- borderGradient: "border-[#389726]",
1792
- borderGradientColor: "#389726"
1793
- },
1794
- // 浅色主题配置
1795
- light: {
1796
- bgGradient: "bg-[#fafafa]",
1797
- // 移除透明度 ff
1798
- gradientColor: "#22c55e",
1799
- borderGradient: "border-[#22c55e]",
1800
- borderGradientColor: "#22c55e"
1801
- }
1802
- },
1803
- error: {
1804
- icon: "ic:outline-close",
1805
- color: "text-red-400",
1806
- className: "text-red-400",
1807
- dark: {
1808
- bgGradient: "bg-[#14181d]",
1809
- // 移除透明度 f2
1810
- gradientColor: "#ef4444",
1811
- borderGradient: "border-[#ef4444]",
1812
- borderGradientColor: "#ef4444"
1813
- },
1814
- light: {
1815
- bgGradient: "bg-[#fafafa]",
1816
- // 移除透明度 ff
1817
- gradientColor: "#f87171",
1818
- borderGradient: "border-[#f87171]",
1819
- borderGradientColor: "#f87171"
1820
- }
1821
- },
1822
- warning: {
1823
- icon: "mi:warning",
1824
- color: "text-yellow-400",
1825
- className: "text-yellow-400",
1826
- dark: {
1827
- bgGradient: "bg-[#14181d]",
1828
- // 移除透明度 f2
1829
- gradientColor: "#facc15",
1830
- borderGradient: "border-[#facc15]",
1831
- borderGradientColor: "#facc15"
1832
- },
1833
- light: {
1834
- bgGradient: "bg-[#fafafa]",
1835
- // 移除透明度 ff
1836
- gradientColor: "#f59e0b",
1837
- borderGradient: "border-[#f59e0b]",
1838
- borderGradientColor: "#f59e0b"
1839
- }
1840
- },
1841
- info: {
1842
- icon: "ic:outline-info",
1843
- color: "text-blue-400",
1844
- className: "text-blue-400",
1845
- dark: {
1846
- bgGradient: "bg-[#14181d]",
1847
- // 移除透明度 f2
1848
- gradientColor: "#60a5fa",
1849
- borderGradient: "border-[#60a5fa]",
1850
- borderGradientColor: "#f0f0f0"
1851
- },
1852
- light: {
1853
- bgGradient: "bg-[#fafafa]",
1854
- // 移除透明度 ff
1855
- gradientColor: "#3b82f6",
1856
- borderGradient: "border-[#3b82f6]",
1857
- borderGradientColor: "#3b82f6"
1858
- }
1859
- },
1860
- default: {
1861
- icon: "ic:round-notifications",
1862
- color: "text-gray-400",
1863
- className: "text-gray-400",
1864
- dark: {
1865
- bgGradient: "bg-[#14181d]",
1866
- // 移除透明度 f2
1867
- gradientColor: "#9ca3af",
1868
- borderGradient: "border-[#9ca3af]",
1869
- borderGradientColor: "#9ca3af"
1870
- },
1871
- light: {
1872
- bgGradient: "bg-[#fafafa]",
1873
- // 移除透明度 ff
1874
- gradientColor: "#6b7280",
1875
- borderGradient: "border-[#6b7280]",
1876
- borderGradientColor: "#6b7280"
1877
- }
1878
- }
1879
- };
1880
- var CloseButton = React7.memo(({ closeToast }) => {
1881
- const { theme } = useTheme();
1882
- const handleClick = useCallback5((e) => {
1883
- e.preventDefault();
1884
- e.stopPropagation();
1885
- closeToast?.();
1886
- }, [closeToast]);
1887
- const getCloseButtonColor = () => {
1888
- const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
1889
- return actualTheme === "dark" ? "#b4b4b4" : "#6b7280";
1890
- };
1891
- const getCloseButtonHoverColor = () => {
1892
- const actualTheme = theme === "system" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
1893
- return actualTheme === "dark" ? "white" : "#374151";
1894
- };
1895
- return /* @__PURE__ */ jsx12(
1896
- Icon4,
1897
- {
1898
- icon: "vaadin:close",
1899
- className: "flex items-center justify-center rounded-full relative z-10 flex-shrink-0 cursor-pointer \n transition-colors duration-200 drop-shadow-sm",
1900
- onClick: handleClick,
1901
- width: 14,
1902
- height: 14,
1903
- style: {
1904
- color: getCloseButtonColor()
1905
- },
1906
- onMouseEnter: (e) => {
1907
- e.currentTarget.style.color = getCloseButtonHoverColor();
1908
- },
1909
- onMouseLeave: (e) => {
1910
- e.currentTarget.style.color = getCloseButtonColor();
1911
- }
1471
+ icon: "vaadin:close",
1472
+ className: "flex items-center justify-center rounded-full relative z-10 flex-shrink-0 cursor-pointer \n transition-colors duration-200 drop-shadow-sm",
1473
+ onClick: handleClick,
1474
+ width: 14,
1475
+ height: 14,
1476
+ style: {
1477
+ color: getCloseButtonColor()
1478
+ },
1479
+ onMouseEnter: (e) => {
1480
+ e.currentTarget.style.color = getCloseButtonHoverColor();
1481
+ },
1482
+ onMouseLeave: (e) => {
1483
+ e.currentTarget.style.color = getCloseButtonColor();
1484
+ }
1912
1485
  }
1913
1486
  );
1914
1487
  });
@@ -1916,7 +1489,7 @@ CloseButton.displayName = "CloseButton";
1916
1489
  var ToastContent = ({ type, title, message, component, closeToast }) => {
1917
1490
  const iconConfig = TOAST_ICONS[type];
1918
1491
  const { theme } = useTheme();
1919
- const handleClose = useCallback5(() => {
1492
+ const handleClose = useCallback4(() => {
1920
1493
  closeToast?.();
1921
1494
  }, [closeToast]);
1922
1495
  const getTextColor = () => {
@@ -1941,13 +1514,13 @@ var ToastContent = ({ type, title, message, component, closeToast }) => {
1941
1514
  // gray-50
1942
1515
  };
1943
1516
  if (component) {
1944
- return /* @__PURE__ */ jsxs8("div", { className: `flex items-start gap-3 !min-h-[90px] w-full backdrop-blur-md p-4 shadow-2xl overflow-hidden ${themeConfig.bgGradient}`, children: [
1945
- /* @__PURE__ */ jsx12("div", { className: "flex-1 relative z-10", children: component }),
1946
- /* @__PURE__ */ jsx12("div", { className: "relative z-10", children: /* @__PURE__ */ jsx12(CloseButton, { closeToast: handleClose }) })
1517
+ return /* @__PURE__ */ jsxs5("div", { className: `flex items-start gap-3 !min-h-[90px] w-full backdrop-blur-md p-4 shadow-2xl overflow-hidden ${themeConfig.bgGradient}`, children: [
1518
+ /* @__PURE__ */ jsx8("div", { className: "flex-1 relative z-10", children: component }),
1519
+ /* @__PURE__ */ jsx8("div", { className: "relative z-10", children: /* @__PURE__ */ jsx8(CloseButton, { closeToast: handleClose }) })
1947
1520
  ] });
1948
1521
  }
1949
- return /* @__PURE__ */ jsxs8("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: [
1950
- /* @__PURE__ */ jsx12(
1522
+ return /* @__PURE__ */ jsxs5("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: [
1523
+ /* @__PURE__ */ jsx8(
1951
1524
  "div",
1952
1525
  {
1953
1526
  className: "absolute left-0 top-0 w-full h-full rounded-xl",
@@ -1957,7 +1530,7 @@ var ToastContent = ({ type, title, message, component, closeToast }) => {
1957
1530
  }
1958
1531
  }
1959
1532
  ),
1960
- /* @__PURE__ */ jsx12(
1533
+ /* @__PURE__ */ jsx8(
1961
1534
  "div",
1962
1535
  {
1963
1536
  className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-xl",
@@ -1967,133 +1540,716 @@ var ToastContent = ({ type, title, message, component, closeToast }) => {
1967
1540
  }
1968
1541
  }
1969
1542
  ),
1970
- /* @__PURE__ */ jsx12(
1543
+ /* @__PURE__ */ jsx8(
1544
+ "div",
1545
+ {
1546
+ className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-xl",
1547
+ style: {
1548
+ border: "2px solid transparent",
1549
+ 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}99 0%, ${themeConfig.borderGradientColor}66 5%, transparent 22%)`,
1550
+ backgroundOrigin: "border-box",
1551
+ backgroundClip: "border-box",
1552
+ WebkitMask: "linear-gradient(#ffffff 0 0) padding-box, linear-gradient(#ffffff 0 0)",
1553
+ WebkitMaskComposite: "xor",
1554
+ zIndex: 0
1555
+ }
1556
+ }
1557
+ ),
1558
+ /* @__PURE__ */ jsx8("div", { className: "flex-shrink-0 flex-grow-0 mt-0.5 relative z-10", children: /* @__PURE__ */ jsx8(
1559
+ "div",
1560
+ {
1561
+ className: "backdrop-blur-sm rounded-full flex items-center justify-center overflow-hidden flex-shrink-0 flex-grow-0",
1562
+ style: {
1563
+ backgroundColor: theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.05)",
1564
+ width: "28px",
1565
+ height: "28px"
1566
+ },
1567
+ children: /* @__PURE__ */ jsx8("div", { className: "rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx8(
1568
+ Icon4,
1569
+ {
1570
+ icon: iconConfig.icon,
1571
+ width: 16,
1572
+ height: 16,
1573
+ className: `flex-shrink-0`,
1574
+ style: {
1575
+ color: themeConfig.gradientColor,
1576
+ display: "block"
1577
+ }
1578
+ }
1579
+ ) })
1580
+ }
1581
+ ) }),
1582
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-1 flex-1 relative z-10", children: [
1583
+ title && /* @__PURE__ */ jsx8(
1584
+ "div",
1585
+ {
1586
+ className: "text-[16px] font-semibold leading-tight drop-shadow-sm",
1587
+ style: {
1588
+ color: getTextColor(),
1589
+ backgroundClip: "text"
1590
+ },
1591
+ children: title
1592
+ }
1593
+ ),
1594
+ message && /* @__PURE__ */ jsx8(
1595
+ "div",
1596
+ {
1597
+ className: "text-[13px] font-normal leading-relaxed drop-shadow-sm",
1598
+ style: {
1599
+ color: getTextColor(),
1600
+ backgroundClip: "text"
1601
+ },
1602
+ children: message
1603
+ }
1604
+ )
1605
+ ] }),
1606
+ /* @__PURE__ */ jsx8("div", { className: "relative z-10", children: /* @__PURE__ */ jsx8(CloseButton, { closeToast: handleClose }) })
1607
+ ] });
1608
+ };
1609
+ var defaultToastOptions = {
1610
+ position: "bottom-right",
1611
+ autoClose: 1500,
1612
+ hideProgressBar: true,
1613
+ closeOnClick: false,
1614
+ pauseOnHover: true,
1615
+ draggable: true,
1616
+ pauseOnFocusLoss: false,
1617
+ transition: Bounce
1618
+ };
1619
+ var getToastifyTheme = () => {
1620
+ if (typeof window !== "undefined") {
1621
+ const root = document.documentElement;
1622
+ if (root.classList.contains("dark")) return "dark";
1623
+ if (root.classList.contains("light")) return "light";
1624
+ return window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
1625
+ }
1626
+ return "light";
1627
+ };
1628
+ var createToast = (type) => {
1629
+ return (params) => {
1630
+ const { title, message, component, options } = params;
1631
+ toast(
1632
+ ({ closeToast }) => {
1633
+ if (params.render) return params.render(closeToast);
1634
+ return /* @__PURE__ */ jsx8(
1635
+ ToastContent,
1636
+ {
1637
+ type,
1638
+ title,
1639
+ message: message || "",
1640
+ component,
1641
+ closeToast
1642
+ }
1643
+ );
1644
+ },
1645
+ {
1646
+ ...defaultToastOptions,
1647
+ ...options,
1648
+ theme: getToastifyTheme(),
1649
+ // 确保圆角样式不被覆盖,添加 rounded-xl 类
1650
+ className: "!p-0 !shadow-none !rounded-xl",
1651
+ style: { padding: 0, borderRadius: "0.75rem", backgroundColor: "transparent" }
1652
+ }
1653
+ );
1654
+ };
1655
+ };
1656
+ var ClayxToast = {
1657
+ success: createToast("success"),
1658
+ error: createToast("error"),
1659
+ warning: createToast("warning"),
1660
+ info: createToast("info"),
1661
+ default: createToast("default")
1662
+ };
1663
+
1664
+ // src/components/auth/HowoneProvider.tsx
1665
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1666
+ var HowoneContext = createContext2(null);
1667
+ var redirectOverlayStylesInjected = false;
1668
+ var injectRedirectOverlayStyles = () => {
1669
+ if (redirectOverlayStylesInjected || typeof document === "undefined") return;
1670
+ const style = document.createElement("style");
1671
+ style.setAttribute("data-howone-auth-overlay", "true");
1672
+ style.textContent = `
1673
+ @keyframes howone-logo-pulse {
1674
+ 0%, 100% {
1675
+ opacity: 0.2;
1676
+ transform: scale(0.95);
1677
+ filter: drop-shadow(0 0 0 rgba(255, 255, 255, 0.2));
1678
+ }
1679
+ 50% {
1680
+ opacity: 1;
1681
+ transform: scale(1.03);
1682
+ filter: drop-shadow(0 0 28px rgba(255, 255, 255, 0.55));
1683
+ }
1684
+ }
1685
+
1686
+ @keyframes howone-glow-ring {
1687
+ 0%, 100% {
1688
+ opacity: 0.12;
1689
+ transform: scale(0.85);
1690
+ }
1691
+ 50% {
1692
+ opacity: 0.42;
1693
+ transform: scale(1.05);
1694
+ }
1695
+ }
1696
+
1697
+ [data-howone-auth-overlay-root] {
1698
+ position: fixed;
1699
+ inset: 0;
1700
+ z-index: 2147483646;
1701
+ display: flex;
1702
+ flex-direction: column;
1703
+ align-items: center;
1704
+ justify-content: center;
1705
+ width: 100vw;
1706
+ height: 100vh;
1707
+ color: #ffffff;
1708
+ background: rgba(0, 0, 0, 0.65);
1709
+ backdrop-filter: blur(6px);
1710
+ -webkit-backdrop-filter: blur(6px);
1711
+ text-align: center;
1712
+ }
1713
+ `;
1714
+ document.head.appendChild(style);
1715
+ redirectOverlayStylesInjected = true;
1716
+ };
1717
+ var HowOneProvider = ({
1718
+ children,
1719
+ showFloatingButton = true,
1720
+ projectId,
1721
+ defaultTheme = "system",
1722
+ themeStorageKey = "howone-theme",
1723
+ forceDefaultTheme = false,
1724
+ redirectOnUnauthenticated = false
1725
+ }) => {
1726
+ const [user, setUser] = useState8(() => parseUserFromToken(getToken()));
1727
+ const [token, setTokenState] = useState8(() => getToken());
1728
+ const [hasCheckedUrlToken, setHasCheckedUrlToken] = useState8(false);
1729
+ const [pendingRedirect, setPendingRedirect] = useState8(false);
1730
+ const [isGuest, setIsGuest] = useState8(false);
1731
+ useEffect7(() => {
1732
+ try {
1733
+ const params = new URLSearchParams(window.location.search);
1734
+ let urlToken = params.get("access_token") || params.get("token");
1735
+ if (!urlToken && window.location.hash) {
1736
+ const hashParams = new URLSearchParams(window.location.hash.slice(1));
1737
+ urlToken = hashParams.get("access_token") || hashParams.get("token");
1738
+ }
1739
+ if (urlToken) {
1740
+ setToken(urlToken);
1741
+ setTokenState(urlToken);
1742
+ setUser(parseUserFromToken(urlToken));
1743
+ params.delete("access_token");
1744
+ params.delete("token");
1745
+ params.delete("project_id");
1746
+ const newSearch = params.toString();
1747
+ const newUrl = window.location.pathname + (newSearch ? "?" + newSearch : "");
1748
+ window.history.replaceState({}, "", newUrl);
1749
+ }
1750
+ } catch (e) {
1751
+ console.error("[HowOneProvider] Failed to capture token from URL:", e);
1752
+ } finally {
1753
+ setHasCheckedUrlToken(true);
1754
+ }
1755
+ }, []);
1756
+ const resolvedAuthUrl = useMemo(() => {
1757
+ const env3 = getGlobalEnvironment() ?? "dev";
1758
+ switch (env3) {
1759
+ case "local":
1760
+ return "http://localhost:3000/auth";
1761
+ case "prod":
1762
+ return "https://howone.ai/auth";
1763
+ case "dev":
1764
+ default:
1765
+ return "https://howone.dev/auth";
1766
+ }
1767
+ }, []);
1768
+ useEffect7(() => {
1769
+ if (pendingRedirect) {
1770
+ injectRedirectOverlayStyles();
1771
+ }
1772
+ }, [pendingRedirect]);
1773
+ useEffect7(() => {
1774
+ if (pendingRedirect) {
1775
+ injectRedirectOverlayStyles();
1776
+ }
1777
+ }, [pendingRedirect]);
1778
+ const redirectToAuth = useCallback5(() => {
1779
+ if (!redirectOnUnauthenticated || typeof window === "undefined") return;
1780
+ const activeProjectId = projectId ?? getDefaultProjectId();
1781
+ const navigateToResolvedAuth = () => {
1782
+ setPendingRedirect(true);
1783
+ requestAnimationFrame(() => {
1784
+ if (activeProjectId) {
1785
+ try {
1786
+ const url = new URL(resolvedAuthUrl);
1787
+ url.searchParams.set("redirect_uri", window.location.origin);
1788
+ url.searchParams.set("project_id", activeProjectId);
1789
+ window.location.href = url.toString();
1790
+ return;
1791
+ } catch (error) {
1792
+ console.error("[HowOneProvider] Failed to attach project_id to auth URL:", error);
1793
+ }
1794
+ }
1795
+ window.location.href = resolvedAuthUrl;
1796
+ });
1797
+ };
1798
+ try {
1799
+ const currentUrl = new URL(window.location.href);
1800
+ if (currentUrl.pathname.includes("/auth")) return;
1801
+ try {
1802
+ const authUrlObj = new URL(resolvedAuthUrl);
1803
+ authUrlObj.searchParams.set("redirect_uri", window.location.origin);
1804
+ if (activeProjectId) {
1805
+ authUrlObj.searchParams.set("project_id", activeProjectId);
1806
+ }
1807
+ setPendingRedirect(true);
1808
+ requestAnimationFrame(() => {
1809
+ window.location.href = authUrlObj.toString();
1810
+ });
1811
+ return;
1812
+ } catch (error) {
1813
+ console.error("[HowOneProvider] Failed to build auth URL:", error);
1814
+ }
1815
+ navigateToResolvedAuth();
1816
+ } catch {
1817
+ navigateToResolvedAuth();
1818
+ }
1819
+ }, [redirectOnUnauthenticated, resolvedAuthUrl, projectId]);
1820
+ useEffect7(() => {
1821
+ if (!hasCheckedUrlToken) return;
1822
+ const guestMode = isGuestMode() || !!getExistingSessionId();
1823
+ setIsGuest(guestMode);
1824
+ if (token || user || guestMode) {
1825
+ return;
1826
+ }
1827
+ redirectToAuth();
1828
+ }, [token, user, hasCheckedUrlToken, redirectToAuth]);
1829
+ useEffect7(() => {
1830
+ if (!hasCheckedUrlToken || !token || !user) return;
1831
+ const migrateGuestData = async () => {
1832
+ try {
1833
+ const guestSessionId = getExistingSessionId();
1834
+ if (!guestSessionId) return;
1835
+ const activeProjectId = projectId ?? getDefaultProjectId();
1836
+ if (!activeProjectId) {
1837
+ console.warn("[HowOneProvider] No projectId available for guest data migration");
1838
+ return;
1839
+ }
1840
+ const baseUrl = getEnvs().baseUrl;
1841
+ const response = await fetch(
1842
+ `${baseUrl}/entities/apps/${activeProjectId}/migrate-guest-data`,
1843
+ {
1844
+ method: "POST",
1845
+ headers: {
1846
+ "Content-Type": "application/json",
1847
+ "Authorization": `Bearer ${token}`
1848
+ },
1849
+ body: JSON.stringify({ guestSessionId })
1850
+ }
1851
+ );
1852
+ if (response.ok) {
1853
+ const result = await response.json();
1854
+ console.log("[HowOneProvider] Guest data migration result:", result);
1855
+ clearGuestSession();
1856
+ setIsGuest(false);
1857
+ if (result.totalCount > 0) {
1858
+ const entityList = result.details?.map((d) => `${d.entityName} (${d.count})`).join(", ") || "";
1859
+ ClayxToast.success({
1860
+ title: "Data Synced",
1861
+ message: `Migrated ${result.totalCount} records${entityList ? `: ${entityList}` : ""}`
1862
+ });
1863
+ }
1864
+ } else {
1865
+ console.error("[HowOneProvider] Guest data migration failed:", response.status);
1866
+ }
1867
+ } catch (error) {
1868
+ console.error("[HowOneProvider] Failed to migrate guest data:", error);
1869
+ }
1870
+ };
1871
+ migrateGuestData();
1872
+ }, [token, user, hasCheckedUrlToken, projectId]);
1873
+ const logout = () => {
1874
+ try {
1875
+ setToken(null);
1876
+ } catch {
1877
+ }
1878
+ setTokenState(null);
1879
+ setUser(null);
1880
+ redirectToAuth();
1881
+ };
1882
+ const value = {
1883
+ user,
1884
+ token,
1885
+ isAuthenticated: hasCheckedUrlToken && (!!token || isGuest),
1886
+ isGuest,
1887
+ logout
1888
+ };
1889
+ if (!hasCheckedUrlToken) return null;
1890
+ return /* @__PURE__ */ jsxs6(
1891
+ ThemeProvider,
1892
+ {
1893
+ defaultTheme,
1894
+ storageKey: themeStorageKey,
1895
+ forceDefault: forceDefaultTheme,
1896
+ children: [
1897
+ /* @__PURE__ */ jsx9(ElementSelectorProvider, { children: /* @__PURE__ */ jsxs6(HowoneContext.Provider, { value, children: [
1898
+ children,
1899
+ showFloatingButton && /* @__PURE__ */ jsx9(FloatingButton, { onClick: () => window.open("https://howone.ai", "_blank") }),
1900
+ pendingRedirect && /* @__PURE__ */ jsx9(
1901
+ "div",
1902
+ {
1903
+ "data-howone-auth-overlay-root": true,
1904
+ className: "fixed inset-0 z-[100000] h-full w-full flex flex-col items-center justify-center bg-black/65 backdrop-blur-sm text-white",
1905
+ children: /* @__PURE__ */ jsxs6("div", { className: "relative mt-6 flex h-[220px] w-[220px] items-center justify-center", children: [
1906
+ /* @__PURE__ */ jsx9(
1907
+ "div",
1908
+ {
1909
+ className: "absolute inset-0 rounded-full bg-white/20",
1910
+ style: { animation: "howone-glow-ring 2.4s ease-in-out infinite" }
1911
+ }
1912
+ ),
1913
+ /* @__PURE__ */ jsx9("div", { className: "absolute inset-0 rounded-full bg-gradient-to-br from-white/10 via-white/25 to-white/10 blur-2xl" }),
1914
+ /* @__PURE__ */ jsx9(
1915
+ "img",
1916
+ {
1917
+ style: { width: 250, animation: "howone-logo-pulse 2s ease-in-out infinite" },
1918
+ src: "https://sxwxqoixnnklnpeutjrj.supabase.co/storage/v1/object/public/create-x/logo/logo.svg",
1919
+ alt: "HowOne"
1920
+ }
1921
+ )
1922
+ ] })
1923
+ }
1924
+ )
1925
+ ] }) }),
1926
+ /* @__PURE__ */ jsx9(GlobalToastContainer, {})
1927
+ ]
1928
+ }
1929
+ );
1930
+ };
1931
+ function useHowoneContext() {
1932
+ const ctx = useContext2(HowoneContext);
1933
+ if (!ctx) {
1934
+ const t = getToken();
1935
+ const guestMode = isGuestMode() || !!getExistingSessionId();
1936
+ return {
1937
+ user: parseUserFromToken(t),
1938
+ token: t,
1939
+ isAuthenticated: !!t || guestMode,
1940
+ isGuest: guestMode,
1941
+ logout: () => {
1942
+ try {
1943
+ setToken(null);
1944
+ } catch {
1945
+ }
1946
+ }
1947
+ };
1948
+ }
1949
+ return ctx;
1950
+ }
1951
+
1952
+ // src/components/index.ts
1953
+ init_auth();
1954
+
1955
+ // src/howone/client.ts
1956
+ init_auth();
1957
+ init_config();
1958
+ var HowoneAuthClient = class {
1959
+ constructor() {
1960
+ this.listeners = /* @__PURE__ */ new Set();
1961
+ this.loading = false;
1962
+ }
1963
+ emit() {
1964
+ const state = {
1965
+ user: parseUserFromToken(getToken()),
1966
+ isLoading: this.loading
1967
+ };
1968
+ for (const l of this.listeners) {
1969
+ try {
1970
+ l(state);
1971
+ } catch (e) {
1972
+ void e;
1973
+ }
1974
+ }
1975
+ }
1976
+ onAuthStateChanged(listener) {
1977
+ this.listeners.add(listener);
1978
+ try {
1979
+ listener({ user: parseUserFromToken(getToken()), isLoading: this.loading });
1980
+ } catch (e) {
1981
+ void e;
1982
+ }
1983
+ return () => {
1984
+ this.listeners.delete(listener);
1985
+ };
1986
+ }
1987
+ // Simple redirect-based login trigger (consumer can override)
1988
+ login() {
1989
+ const root = getEnvs().AUTH_ROOT_VALUE;
1990
+ try {
1991
+ const loc = window.location.href;
1992
+ const authUrl = new URL("/auth", String(root));
1993
+ authUrl.searchParams.set("redirect_uri", String(loc));
1994
+ try {
1995
+ const cfg = (init_config(), __toCommonJS(config_exports));
1996
+ const pid = cfg.getDefaultProjectId && cfg.getDefaultProjectId();
1997
+ if (pid) authUrl.searchParams.set("project_id", String(pid));
1998
+ } catch {
1999
+ }
2000
+ try {
2001
+ if (window.top && window.top !== window) {
2002
+ window.top.location.replace(authUrl.toString());
2003
+ } else {
2004
+ window.location.replace(authUrl.toString());
2005
+ }
2006
+ } catch {
2007
+ try {
2008
+ window.location.replace(String(root));
2009
+ } catch {
2010
+ }
2011
+ }
2012
+ } catch {
2013
+ try {
2014
+ window.location.replace(String(root));
2015
+ } catch {
2016
+ }
2017
+ }
2018
+ }
2019
+ logout() {
2020
+ setToken(null);
2021
+ this.emit();
2022
+ }
2023
+ getUser() {
2024
+ return parseUserFromToken(getToken());
2025
+ }
2026
+ // helper to programmatically set token (e.g., after callback handling)
2027
+ setToken(token) {
2028
+ setToken(token);
2029
+ this.emit();
2030
+ }
2031
+ };
2032
+ var howone = {
2033
+ auth: new HowoneAuthClient()
2034
+ };
2035
+ var client_default = howone;
2036
+
2037
+ // src/components/ui/Loading.tsx
2038
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2039
+ var Loading = ({
2040
+ size = "md",
2041
+ text = "Loading...",
2042
+ className = "",
2043
+ fullScreen = false
2044
+ }) => {
2045
+ const sizeClasses = {
2046
+ sm: "h-4 w-4",
2047
+ md: "h-8 w-8",
2048
+ lg: "h-12 w-12"
2049
+ };
2050
+ 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";
2051
+ return /* @__PURE__ */ jsx10("div", { className: `${containerClasses} ${className}`, children: /* @__PURE__ */ jsxs7("div", { className: "text-center", children: [
2052
+ /* @__PURE__ */ jsx10(
1971
2053
  "div",
1972
2054
  {
1973
- className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-xl",
1974
- style: {
1975
- border: "2px solid transparent",
1976
- 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}99 0%, ${themeConfig.borderGradientColor}66 5%, transparent 22%)`,
1977
- backgroundOrigin: "border-box",
1978
- backgroundClip: "border-box",
1979
- WebkitMask: "linear-gradient(#ffffff 0 0) padding-box, linear-gradient(#ffffff 0 0)",
1980
- WebkitMaskComposite: "xor",
1981
- zIndex: 0
1982
- }
2055
+ className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 mx-auto ${sizeClasses[size]}`
1983
2056
  }
1984
2057
  ),
1985
- /* @__PURE__ */ jsx12("div", { className: "flex-shrink-0 flex-grow-0 mt-0.5 relative z-10", children: /* @__PURE__ */ jsx12(
1986
- "div",
1987
- {
1988
- className: "backdrop-blur-sm rounded-full flex items-center justify-center overflow-hidden flex-shrink-0 flex-grow-0",
1989
- style: {
1990
- backgroundColor: theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.05)",
1991
- width: "28px",
1992
- height: "28px"
1993
- },
1994
- children: /* @__PURE__ */ jsx12("div", { className: "rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx12(
1995
- Icon4,
1996
- {
1997
- icon: iconConfig.icon,
1998
- width: 16,
1999
- height: 16,
2000
- className: `flex-shrink-0`,
2001
- style: {
2002
- color: themeConfig.gradientColor,
2003
- display: "block"
2004
- }
2005
- }
2006
- ) })
2007
- }
2008
- ) }),
2009
- /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-1 flex-1 relative z-10", children: [
2010
- title && /* @__PURE__ */ jsx12(
2011
- "div",
2012
- {
2013
- className: "text-[16px] font-semibold leading-tight drop-shadow-sm",
2014
- style: {
2015
- color: getTextColor(),
2016
- backgroundClip: "text"
2017
- },
2018
- children: title
2019
- }
2020
- ),
2021
- message && /* @__PURE__ */ jsx12(
2022
- "div",
2023
- {
2024
- className: "text-[13px] font-normal leading-relaxed drop-shadow-sm",
2025
- style: {
2026
- color: getTextColor(),
2027
- backgroundClip: "text"
2028
- },
2029
- children: message
2030
- }
2031
- )
2032
- ] }),
2033
- /* @__PURE__ */ jsx12("div", { className: "relative z-10", children: /* @__PURE__ */ jsx12(CloseButton, { closeToast: handleClose }) })
2034
- ] });
2058
+ text && /* @__PURE__ */ jsx10("p", { className: "mt-2 text-sm text-gray-600", children: text })
2059
+ ] }) });
2035
2060
  };
2036
- var defaultToastOptions = {
2037
- position: "bottom-right",
2038
- autoClose: 1500,
2039
- hideProgressBar: true,
2040
- closeOnClick: false,
2041
- pauseOnHover: true,
2042
- draggable: true,
2043
- pauseOnFocusLoss: false,
2044
- transition: Bounce
2061
+ var LoadingSpinner = ({
2062
+ size = "md",
2063
+ className = ""
2064
+ }) => {
2065
+ const sizeClasses = {
2066
+ sm: "h-4 w-4",
2067
+ md: "h-8 w-8",
2068
+ lg: "h-12 w-12"
2069
+ };
2070
+ return /* @__PURE__ */ jsx10(
2071
+ "div",
2072
+ {
2073
+ className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 ${sizeClasses[size]} ${className}`
2074
+ }
2075
+ );
2045
2076
  };
2046
- var getToastifyTheme = () => {
2047
- if (typeof window !== "undefined") {
2048
- const root = document.documentElement;
2049
- if (root.classList.contains("dark")) return "dark";
2050
- if (root.classList.contains("light")) return "light";
2051
- return window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
2077
+
2078
+ // src/components/ui/ErrorBoundary.tsx
2079
+ import { Component } from "react";
2080
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
2081
+ var ErrorBoundary = class extends Component {
2082
+ constructor(props) {
2083
+ super(props);
2084
+ this.handleRetry = () => {
2085
+ this.setState({ hasError: false, error: void 0, errorInfo: void 0 });
2086
+ };
2087
+ this.state = { hasError: false };
2052
2088
  }
2053
- return "light";
2054
- };
2055
- var createToast = (type) => {
2056
- return (params) => {
2057
- const { title, message, component, options } = params;
2058
- toast(
2059
- ({ closeToast }) => {
2060
- if (params.render) return params.render(closeToast);
2061
- return /* @__PURE__ */ jsx12(
2062
- ToastContent,
2089
+ static getDerivedStateFromError(error) {
2090
+ return { hasError: true, error };
2091
+ }
2092
+ componentDidCatch(error, errorInfo) {
2093
+ this.setState({
2094
+ error,
2095
+ errorInfo
2096
+ });
2097
+ this.props.onError?.(error, errorInfo);
2098
+ }
2099
+ render() {
2100
+ if (this.state.hasError) {
2101
+ if (this.props.fallback) {
2102
+ const FallbackComponent = this.props.fallback;
2103
+ return /* @__PURE__ */ jsx11(FallbackComponent, { error: this.state.error, retry: this.handleRetry });
2104
+ }
2105
+ return /* @__PURE__ */ jsx11("div", { className: "min-h-[400px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs8("div", { className: "text-center max-w-md", children: [
2106
+ /* @__PURE__ */ jsx11("div", { className: "text-red-500 text-6xl mb-4", children: "\u26A0\uFE0F" }),
2107
+ /* @__PURE__ */ jsx11("h2", { className: "text-xl font-semibold text-gray-900 mb-2", children: "Something went wrong" }),
2108
+ /* @__PURE__ */ jsx11("p", { className: "text-gray-600 mb-4", children: "An unexpected error occurred. Please try refreshing the page." }),
2109
+ /* @__PURE__ */ jsx11(
2110
+ "button",
2063
2111
  {
2064
- type,
2065
- title,
2066
- message: message || "",
2067
- component,
2068
- closeToast
2112
+ onClick: this.handleRetry,
2113
+ className: "px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors",
2114
+ children: "Try Again"
2069
2115
  }
2070
- );
2071
- },
2072
- {
2073
- ...defaultToastOptions,
2074
- ...options,
2075
- theme: getToastifyTheme(),
2076
- // 确保圆角样式不被覆盖,添加 rounded-xl 类
2077
- className: "!p-0 !shadow-none !rounded-xl",
2078
- style: { padding: 0, borderRadius: "0.75rem", backgroundColor: "transparent" }
2079
- }
2080
- );
2081
- };
2116
+ ),
2117
+ false
2118
+ ] }) });
2119
+ }
2120
+ return this.props.children;
2121
+ }
2082
2122
  };
2083
- var ClayxToast = {
2084
- success: createToast("success"),
2085
- error: createToast("error"),
2086
- warning: createToast("warning"),
2087
- info: createToast("info"),
2088
- default: createToast("default")
2123
+ var DefaultErrorFallback = ({ retry }) => /* @__PURE__ */ jsx11("div", { className: "min-h-[200px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs8("div", { className: "text-center", children: [
2124
+ /* @__PURE__ */ jsx11("div", { className: "text-red-500 text-4xl mb-2", children: "\u26A0\uFE0F" }),
2125
+ /* @__PURE__ */ jsx11("p", { className: "text-gray-600 mb-2", children: "Something went wrong" }),
2126
+ retry && /* @__PURE__ */ jsx11(
2127
+ "button",
2128
+ {
2129
+ onClick: retry,
2130
+ className: "px-3 py-1 bg-blue-600 text-white text-sm rounded hover:bg-blue-700 transition-colors",
2131
+ children: "Retry"
2132
+ }
2133
+ )
2134
+ ] }) });
2135
+
2136
+ // src/components/ui/ClayxButton.tsx
2137
+ import { jsx as jsx12 } from "react/jsx-runtime";
2138
+ var getSizeClasses = (size, isIconOnly) => {
2139
+ if (isIconOnly) {
2140
+ switch (size) {
2141
+ case "sm":
2142
+ return "h-8 w-8 min-w-8 p-0";
2143
+ case "md":
2144
+ return "h-10 w-10 min-w-10 p-0";
2145
+ case "lg":
2146
+ return "h-12 w-12 min-w-12 p-0";
2147
+ default:
2148
+ return "h-10 w-10 min-w-10 p-0";
2149
+ }
2150
+ }
2151
+ switch (size) {
2152
+ case "sm":
2153
+ return "h-8 px-3 text-sm";
2154
+ case "md":
2155
+ return "h-10 px-4 text-base";
2156
+ case "lg":
2157
+ return "h-12 px-6 text-lg";
2158
+ default:
2159
+ return "h-10 px-4 text-base";
2160
+ }
2161
+ };
2162
+ var getVariantClasses = (variant) => {
2163
+ switch (variant) {
2164
+ case "solid":
2165
+ return "bg-primary text-white hover:bg-primary/90";
2166
+ case "ghost":
2167
+ return "bg-transparent hover:bg-white/10";
2168
+ case "flat":
2169
+ return "bg-white/5 hover:bg-white/10";
2170
+ default:
2171
+ return "";
2172
+ }
2173
+ };
2174
+ var ClayxButton = ({
2175
+ isIconOnly = false,
2176
+ size = "md",
2177
+ variant = "solid",
2178
+ className = "",
2179
+ children,
2180
+ disabled = false,
2181
+ ...props
2182
+ }) => {
2183
+ const sizeClasses = getSizeClasses(size, isIconOnly);
2184
+ const variantClasses = getVariantClasses(variant);
2185
+ const baseClasses = `
2186
+ inline-flex items-center justify-center
2187
+ rounded-md font-medium
2188
+ transition-all duration-200
2189
+ focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-transparent
2190
+ disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none
2191
+ `.replace(/\s+/g, " ").trim();
2192
+ const combinedClasses = `${baseClasses} ${sizeClasses} ${variantClasses} ${className}`.trim();
2193
+ return /* @__PURE__ */ jsx12(
2194
+ "button",
2195
+ {
2196
+ className: combinedClasses,
2197
+ disabled,
2198
+ ...props,
2199
+ children
2200
+ }
2201
+ );
2089
2202
  };
2090
2203
 
2091
2204
  // src/components/ui/LimitUpgradeToast.tsx
2205
+ import React8 from "react";
2206
+ import { Icon as Icon5 } from "@iconify/react";
2092
2207
  import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
2093
- var LimitToastContainer = ({ message, onUpgrade, closeToast }) => {
2208
+ var PremiumActionToast = ({
2209
+ message,
2210
+ onAction,
2211
+ closeToast,
2212
+ buttonText = "Upgrade Now",
2213
+ title = "Information",
2214
+ variant = "purple"
2215
+ }) => {
2094
2216
  const [hover, setHover] = React8.useState(false);
2095
2217
  const [closeHover, setCloseHover] = React8.useState(false);
2096
- return /* @__PURE__ */ jsxs9("div", { className: "relative w-full max-w-[420px] overflow-hidden rounded-md bg-gradient-to-br from-[#1A1A1A] via-[#151515] to-[#1A1A1A] shadow-[0_20px_60px_rgba(168,85,247,0.2)] backdrop-blur-sm", children: [
2218
+ const colors = {
2219
+ purple: {
2220
+ gradient1: "rgba(168,85,247,0.3)",
2221
+ gradient2: "rgba(168,85,247,0.2)",
2222
+ borderStart: "rgba(168,85,247,0.8)",
2223
+ borderEnd: "rgba(168,85,247,0.5)",
2224
+ bgGlow1: "from-purple-500/20 via-pink-500/10",
2225
+ bgGlow2: "from-blue-500/10",
2226
+ tagBg: "bg-purple-500/30",
2227
+ tagText: "text-white",
2228
+ tagBorder: "border border-purple-400/50",
2229
+ borderColor: "#a855f7",
2230
+ btnGradient: hover ? "linear-gradient(to right, #9333ea, #db2777)" : "linear-gradient(to right, #a855f7, #ec4899)",
2231
+ btnShadow: "0 10px 15px -3px rgba(168,85,247,0.3), 0 4px 6px -2px rgba(168,85,247,0.3)",
2232
+ shadow: "0_20px_60px_rgba(168,85,247,0.2)",
2233
+ badge: "Premium"
2234
+ },
2235
+ blue: {
2236
+ gradient1: "rgba(59,130,246,0.3)",
2237
+ gradient2: "rgba(59,130,246,0.2)",
2238
+ borderStart: "rgba(59,130,246,0.8)",
2239
+ borderEnd: "rgba(59,130,246,0.5)",
2240
+ bgGlow1: "from-blue-500/20 via-cyan-500/10",
2241
+ bgGlow2: "from-indigo-500/10",
2242
+ tagBg: "bg-blue-500/30",
2243
+ tagText: "text-white",
2244
+ tagBorder: "border border-blue-400/50",
2245
+ borderColor: "#3b82f6",
2246
+ btnGradient: hover ? "linear-gradient(to right, #1d4ed8, #0ea5e9)" : "linear-gradient(to right, #3b82f6, #06b6d4)",
2247
+ btnShadow: "0 10px 15px -3px rgba(59,130,246,0.3), 0 4px 6px -2px rgba(59,130,246,0.3)",
2248
+ shadow: "0_20px_60px_rgba(59,130,246,0.2)",
2249
+ badge: "Secure"
2250
+ }
2251
+ }[variant];
2252
+ return /* @__PURE__ */ jsxs9("div", { className: `relative w-full max-w-[420px] overflow-hidden rounded-md bg-gradient-to-br from-[#1A1A1A] via-[#151515] to-[#1A1A1A] shadow-[${colors.shadow}] backdrop-blur-sm`, children: [
2097
2253
  /* @__PURE__ */ jsx13(
2098
2254
  "div",
2099
2255
  {
@@ -2109,7 +2265,7 @@ var LimitToastContainer = ({ message, onUpgrade, closeToast }) => {
2109
2265
  {
2110
2266
  className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-md",
2111
2267
  style: {
2112
- background: `linear-gradient(135deg, rgba(168,85,247,0.3) 0%, rgba(168,85,247,0.2) 15%, #1A1A1A 30%)`,
2268
+ background: `linear-gradient(135deg, ${colors.gradient1} 0%, ${colors.gradient2} 15%, #1A1A1A 30%)`,
2113
2269
  zIndex: -1
2114
2270
  }
2115
2271
  }
@@ -2120,7 +2276,7 @@ var LimitToastContainer = ({ message, onUpgrade, closeToast }) => {
2120
2276
  className: "absolute left-0 top-0 w-full h-full pointer-events-none rounded-md",
2121
2277
  style: {
2122
2278
  border: "2px solid transparent",
2123
- backgroundImage: `linear-gradient(135deg, rgba(168,85,247,0.6) 0%, rgba(168,85,247,0.4) 5%, transparent 22%)`,
2279
+ backgroundImage: `linear-gradient(135deg, ${colors.borderStart} 0%, ${colors.borderEnd} 5%, transparent 22%)`,
2124
2280
  backgroundOrigin: "border-box",
2125
2281
  backgroundClip: "border-box",
2126
2282
  WebkitMask: "linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)",
@@ -2130,13 +2286,20 @@ var LimitToastContainer = ({ message, onUpgrade, closeToast }) => {
2130
2286
  }
2131
2287
  }
2132
2288
  ),
2133
- /* @__PURE__ */ jsx13("div", { className: "absolute -top-16 -right-16 h-32 w-32 rounded-full bg-gradient-to-br from-purple-500/20 via-pink-500/10 to-transparent blur-3xl animate-pulse" }),
2134
- /* @__PURE__ */ jsx13("div", { className: "absolute -bottom-16 -left-16 h-32 w-32 rounded-full bg-gradient-to-tr from-blue-500/10 to-transparent blur-2xl animate-pulse", style: { animationDelay: "1s" } }),
2289
+ /* @__PURE__ */ jsx13("div", { className: `absolute -top-16 -right-16 h-32 w-32 rounded-full bg-gradient-to-br ${colors.bgGlow1} to-transparent blur-3xl animate-pulse` }),
2290
+ /* @__PURE__ */ jsx13("div", { className: `absolute -bottom-16 -left-16 h-32 w-32 rounded-full bg-gradient-to-tr ${colors.bgGlow2} to-transparent blur-2xl animate-pulse`, style: { animationDelay: "1s" } }),
2135
2291
  /* @__PURE__ */ jsx13("div", { className: "relative z-10 flex items-start gap-4 p-4", children: /* @__PURE__ */ jsxs9("div", { className: "flex flex-1 flex-col gap-3", children: [
2136
2292
  /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
2137
2293
  /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
2138
- /* @__PURE__ */ jsx13("div", { className: "text-lg font-bold text-white", children: "Upgrade Required" }),
2139
- /* @__PURE__ */ jsx13("div", { className: "px-2 py-0.5 text-xs font-bold bg-purple-500/20 text-purple-400 rounded-md border border-purple-500/30", children: "Premium" })
2294
+ /* @__PURE__ */ jsx13("div", { className: "text-lg font-bold text-white", children: title }),
2295
+ /* @__PURE__ */ jsx13(
2296
+ "div",
2297
+ {
2298
+ className: `px-2 py-0.5 text-xs font-bold ${colors.tagBg} ${colors.tagText} rounded-md border`,
2299
+ style: { borderColor: colors.borderColor },
2300
+ children: colors.badge
2301
+ }
2302
+ )
2140
2303
  ] }),
2141
2304
  /* @__PURE__ */ jsx13(
2142
2305
  ClayxButton,
@@ -2155,16 +2318,16 @@ var LimitToastContainer = ({ message, onUpgrade, closeToast }) => {
2155
2318
  transition: "background-color 150ms ease",
2156
2319
  cursor: "pointer"
2157
2320
  },
2158
- children: /* @__PURE__ */ jsx13(Icon5, { icon: "iconamoon:close", className: "w-4 h-4 text-gray-400" })
2321
+ children: /* @__PURE__ */ jsx13(Icon5, { icon: "iconamoon:close", className: "w-4 h-4 text-gray-300" })
2159
2322
  }
2160
2323
  )
2161
2324
  ] }),
2162
- /* @__PURE__ */ jsx13("p", { className: "text-sm text-gray-300 leading-relaxed", children: message }),
2325
+ /* @__PURE__ */ jsx13("p", { className: "text-sm text-white leading-relaxed font-medium", children: message }),
2163
2326
  /* @__PURE__ */ jsx13("div", { className: "mt-1 flex items-center gap-3", children: /* @__PURE__ */ jsx13(
2164
2327
  ClayxButton,
2165
2328
  {
2166
2329
  onClick: () => {
2167
- onUpgrade();
2330
+ onAction();
2168
2331
  closeToast?.();
2169
2332
  },
2170
2333
  onMouseEnter: () => setHover(true),
@@ -2175,21 +2338,31 @@ var LimitToastContainer = ({ message, onUpgrade, closeToast }) => {
2175
2338
  fontWeight: 600,
2176
2339
  cursor: "pointer",
2177
2340
  transition: "all 300ms ease-in-out",
2178
- backgroundImage: hover ? "linear-gradient(to right, #9333ea, #db2777)" : "linear-gradient(to right, #a855f7, #ec4899)",
2179
- boxShadow: hover ? "0 10px 15px -3px rgba(168,85,247,0.3), 0 4px 6px -2px rgba(168,85,247,0.3)" : "none"
2341
+ backgroundImage: colors.btnGradient,
2342
+ boxShadow: hover ? colors.btnShadow : "none"
2180
2343
  },
2181
2344
  children: /* @__PURE__ */ jsxs9("span", { className: "flex items-center gap-2", children: [
2182
- /* @__PURE__ */ jsx13(Icon5, { icon: "solar:rocket-2-bold", className: "w-4 h-4" }),
2183
- "Upgrade Now"
2345
+ /* @__PURE__ */ jsx13(Icon5, { icon: variant === "purple" ? "solar:rocket-2-bold" : "solar:login-3-bold", className: "w-4 h-4" }),
2346
+ buttonText
2184
2347
  ] })
2185
2348
  }
2186
2349
  ) })
2187
2350
  ] }) })
2188
2351
  ] });
2189
2352
  };
2190
- function showLimitUpgradeToast(message, onUpgrade) {
2353
+ function showPremiumActionToast(message, onAction, buttonText, title, variant = "purple") {
2191
2354
  ClayxToast.default({
2192
- render: (closeToast) => /* @__PURE__ */ jsx13(LimitToastContainer, { message, onUpgrade, closeToast }),
2355
+ render: (closeToast) => /* @__PURE__ */ jsx13(
2356
+ PremiumActionToast,
2357
+ {
2358
+ message,
2359
+ onAction,
2360
+ closeToast,
2361
+ buttonText,
2362
+ title,
2363
+ variant
2364
+ }
2365
+ ),
2193
2366
  options: {
2194
2367
  position: "bottom-right",
2195
2368
  closeOnClick: false,
@@ -2207,6 +2380,12 @@ function showLimitUpgradeToast(message, onUpgrade) {
2207
2380
  }
2208
2381
  });
2209
2382
  }
2383
+ function showLimitUpgradeToast(message, onUpgrade, buttonText, title) {
2384
+ showPremiumActionToast(message, onUpgrade, buttonText, title, "purple");
2385
+ }
2386
+ function showSignInRequiredToast(message, onSignIn, buttonText, title) {
2387
+ showPremiumActionToast(message, onSignIn, buttonText, title, "blue");
2388
+ }
2210
2389
 
2211
2390
  // src/services/ai-workflow.ts
2212
2391
  var AIWorkflowClient = class {
@@ -2582,6 +2761,15 @@ async function executeSSEWorkflow(request, options = {}) {
2582
2761
  };
2583
2762
  if (options.authToken) {
2584
2763
  headers["Authorization"] = `Bearer ${options.authToken}`;
2764
+ } else {
2765
+ try {
2766
+ const { getGuestSessionId: getGuestSessionId2 } = (init_session(), __toCommonJS(session_exports));
2767
+ const sessionId = getGuestSessionId2?.();
2768
+ if (sessionId) {
2769
+ headers["X-Session-Id"] = sessionId;
2770
+ }
2771
+ } catch {
2772
+ }
2585
2773
  }
2586
2774
  const method = request.method?.toUpperCase() ?? "POST";
2587
2775
  const hasBody = request.body && Object.keys(request.body).length > 0;
@@ -2596,7 +2784,23 @@ async function executeSSEWorkflow(request, options = {}) {
2596
2784
  signal: options.signal
2597
2785
  });
2598
2786
  if (!response.ok) {
2599
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
2787
+ if (response.status === 403) {
2788
+ showSignInRequiredToast(
2789
+ "Free trial limit reached. Please sign in to continue.",
2790
+ () => {
2791
+ const authUrl = getEnvs().AUTH_ROOT_VALUE;
2792
+ const redirectUri = window.location.href;
2793
+ const projectId = getDefaultProjectId();
2794
+ let authHref = `${authUrl}/auth?redirect_uri=${encodeURIComponent(redirectUri)}`;
2795
+ if (projectId) {
2796
+ authHref += `&project_id=${encodeURIComponent(projectId)}`;
2797
+ }
2798
+ window.location.href = authHref;
2799
+ },
2800
+ "Sign In",
2801
+ "Sign In Required"
2802
+ );
2803
+ }
2600
2804
  }
2601
2805
  const reader = response.body?.getReader();
2602
2806
  if (!reader) {
@@ -3349,6 +3553,15 @@ function createClient(opts) {
3349
3553
  const availableToken = getAvailableToken();
3350
3554
  if (availableToken) {
3351
3555
  config.headers["Authorization"] = `Bearer ${availableToken}`;
3556
+ } else {
3557
+ try {
3558
+ const { getGuestSessionId: getGuestSessionId2 } = (init_session(), __toCommonJS(session_exports));
3559
+ const sessionId = getGuestSessionId2?.();
3560
+ if (sessionId) {
3561
+ config.headers["X-Session-Id"] = sessionId;
3562
+ }
3563
+ } catch {
3564
+ }
3352
3565
  }
3353
3566
  }
3354
3567
  return config;
@@ -4151,6 +4364,9 @@ var elementSelector = {
4151
4364
  */
4152
4365
  isActive: () => getElementSelectorState().active
4153
4366
  };
4367
+
4368
+ // src/index.ts
4369
+ init_session();
4154
4370
  export {
4155
4371
  AUTH_TOKEN_KEY,
4156
4372
  ClayxButton,
@@ -4169,6 +4385,7 @@ export {
4169
4385
  ThemeToggle,
4170
4386
  aiWorkflow,
4171
4387
  canAccessArtifact,
4388
+ clearGuestSession,
4172
4389
  createAIWorkflowClient,
4173
4390
  createAIWorkflowClientAxios,
4174
4391
  createArtifactsClient,
@@ -4183,10 +4400,12 @@ export {
4183
4400
  getEnvironment,
4184
4401
  getEnvs,
4185
4402
  getGlobalEnvironment,
4403
+ getGuestSessionId,
4186
4404
  getToken,
4187
4405
  client_default as howone,
4188
4406
  iframeNavigation,
4189
4407
  initIframeNavigation,
4408
+ isGuestMode,
4190
4409
  isTokenValid,
4191
4410
  loginWithEmailCode,
4192
4411
  onAuthStateChanged,
@@ -4197,6 +4416,8 @@ export {
4197
4416
  setEnvironment,
4198
4417
  setToken,
4199
4418
  showLimitUpgradeToast,
4419
+ showPremiumActionToast,
4420
+ showSignInRequiredToast,
4200
4421
  unifiedAuth,
4201
4422
  unifiedOAuth,
4202
4423
  useAuth,