@djangocfg/layouts 2.1.101 → 2.1.102

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.
Files changed (49) hide show
  1. package/dist/AIChatWidget-LUPM7S2O.mjs +1644 -0
  2. package/dist/AIChatWidget-LUPM7S2O.mjs.map +1 -0
  3. package/dist/AIChatWidget-O23TJJ7C.mjs +3 -0
  4. package/dist/AIChatWidget-O23TJJ7C.mjs.map +1 -0
  5. package/dist/chunk-53YKWR6F.mjs +6 -0
  6. package/dist/chunk-53YKWR6F.mjs.map +1 -0
  7. package/dist/chunk-EI7TDN2G.mjs +1652 -0
  8. package/dist/chunk-EI7TDN2G.mjs.map +1 -0
  9. package/dist/components.cjs +925 -0
  10. package/dist/components.cjs.map +1 -0
  11. package/dist/components.d.mts +583 -0
  12. package/dist/components.d.ts +583 -0
  13. package/dist/components.mjs +879 -0
  14. package/dist/components.mjs.map +1 -0
  15. package/dist/index.cjs +7573 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.mts +2376 -0
  18. package/dist/index.d.ts +2376 -0
  19. package/dist/index.mjs +5673 -0
  20. package/dist/index.mjs.map +1 -0
  21. package/dist/layouts.cjs +6530 -0
  22. package/dist/layouts.cjs.map +1 -0
  23. package/dist/layouts.d.mts +748 -0
  24. package/dist/layouts.d.ts +748 -0
  25. package/dist/layouts.mjs +4741 -0
  26. package/dist/layouts.mjs.map +1 -0
  27. package/dist/pages.cjs +178 -0
  28. package/dist/pages.cjs.map +1 -0
  29. package/dist/pages.d.mts +57 -0
  30. package/dist/pages.d.ts +57 -0
  31. package/dist/pages.mjs +168 -0
  32. package/dist/pages.mjs.map +1 -0
  33. package/dist/snippets.cjs +3793 -0
  34. package/dist/snippets.cjs.map +1 -0
  35. package/dist/snippets.d.mts +1192 -0
  36. package/dist/snippets.d.ts +1192 -0
  37. package/dist/snippets.mjs +3738 -0
  38. package/dist/snippets.mjs.map +1 -0
  39. package/dist/utils.cjs +34 -0
  40. package/dist/utils.cjs.map +1 -0
  41. package/dist/utils.d.mts +40 -0
  42. package/dist/utils.d.ts +40 -0
  43. package/dist/utils.mjs +25 -0
  44. package/dist/utils.mjs.map +1 -0
  45. package/package.json +38 -47
  46. package/src/components/errors/ErrorsTracker/components/ErrorButtons.tsx +2 -1
  47. package/src/layouts/ProfileLayout/ProfileLayout.tsx +507 -86
  48. package/src/layouts/ProfileLayout/components/DeleteAccountSection.tsx +2 -2
  49. package/src/snippets/AuthDialog/useAuthDialog.ts +1 -1
@@ -0,0 +1,879 @@
1
+ import { createContext, useState, useEffect, Suspense as Suspense$1, Component, useCallback, useContext } from 'react';
2
+ import { Button, Preloader } from '@djangocfg/ui-nextjs/components';
3
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
4
+ import * as LucideIcons from 'lucide-react';
5
+ import { Copy, Terminal } from 'lucide-react';
6
+ import { cn } from '@djangocfg/ui-core/lib';
7
+ import { useAuth } from '@djangocfg/api/auth';
8
+ import { useCfgRouter } from '@djangocfg/ui-nextjs/hooks';
9
+ import { useCopy, toast } from '@djangocfg/ui-core/hooks';
10
+ import { Button as Button$1 } from '@djangocfg/ui-nextjs';
11
+ import consola from 'consola';
12
+
13
+ var __defProp = Object.defineProperty;
14
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
15
+ var defaultFallback = /* @__PURE__ */ jsx(
16
+ Preloader,
17
+ {
18
+ variant: "fullscreen",
19
+ text: "Loading...",
20
+ size: "lg",
21
+ backdrop: true,
22
+ backdropOpacity: 80
23
+ }
24
+ );
25
+ function ClientOnly({
26
+ children,
27
+ fallback = defaultFallback
28
+ }) {
29
+ const [mounted, setMounted] = useState(false);
30
+ useEffect(() => {
31
+ setMounted(true);
32
+ }, []);
33
+ if (!mounted) {
34
+ return /* @__PURE__ */ jsx(Fragment, { children: fallback });
35
+ }
36
+ return /* @__PURE__ */ jsx(Fragment, { children });
37
+ }
38
+ __name(ClientOnly, "ClientOnly");
39
+ function JsonLd({ data }) {
40
+ return /* @__PURE__ */ jsx(
41
+ "script",
42
+ {
43
+ type: "application/ld+json",
44
+ dangerouslySetInnerHTML: {
45
+ __html: JSON.stringify(data, null, 0)
46
+ }
47
+ }
48
+ );
49
+ }
50
+ __name(JsonLd, "JsonLd");
51
+ function getLucideIcon(icon, fallback = LucideIcons.CloudLightning) {
52
+ if (!icon) {
53
+ return fallback;
54
+ }
55
+ if (typeof icon === "string") {
56
+ const IconComponent = LucideIcons[icon];
57
+ return IconComponent || fallback;
58
+ }
59
+ return icon;
60
+ }
61
+ __name(getLucideIcon, "getLucideIcon");
62
+ function LucideIcon({
63
+ icon,
64
+ fallback = LucideIcons.CloudLightning,
65
+ className,
66
+ ...props
67
+ }) {
68
+ const IconComponent = getLucideIcon(icon, fallback);
69
+ return /* @__PURE__ */ jsx(IconComponent, { className: cn(className), ...props });
70
+ }
71
+ __name(LucideIcon, "LucideIcon");
72
+ var defaultFallback2 = /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
73
+ /* @__PURE__ */ jsx("div", { className: "inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]" }),
74
+ /* @__PURE__ */ jsx("p", { className: "mt-4 text-sm text-muted-foreground", children: "Loading..." })
75
+ ] }) });
76
+ function Suspense({ children, fallback = defaultFallback2 }) {
77
+ return /* @__PURE__ */ jsx(Suspense$1, { fallback, children });
78
+ }
79
+ __name(Suspense, "Suspense");
80
+ var _ErrorBoundary = class _ErrorBoundary extends Component {
81
+ constructor(props) {
82
+ super(props);
83
+ this.state = { hasError: false, error: null };
84
+ }
85
+ static getDerivedStateFromError(error) {
86
+ return { hasError: true, error };
87
+ }
88
+ componentDidCatch(error, errorInfo) {
89
+ if (this.props.onError) {
90
+ this.props.onError(error, errorInfo);
91
+ }
92
+ {
93
+ console.error("ErrorBoundary caught an error:", error, errorInfo);
94
+ }
95
+ }
96
+ render() {
97
+ if (this.state.hasError) {
98
+ return /* @__PURE__ */ jsx("div", { className: "flex min-h-screen items-center justify-center bg-background p-4", children: /* @__PURE__ */ jsxs("div", { className: "max-w-md w-full space-y-4 text-center", children: [
99
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: "Something went wrong" }),
100
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "We're sorry, but something unexpected happened. Please try refreshing the page." }),
101
+ this.props.supportEmail && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
102
+ "If the problem persists, please contact",
103
+ " ",
104
+ /* @__PURE__ */ jsx(
105
+ "a",
106
+ {
107
+ href: `mailto:${this.props.supportEmail}`,
108
+ className: "text-primary hover:underline",
109
+ children: this.props.supportEmail
110
+ }
111
+ )
112
+ ] }),
113
+ /* @__PURE__ */ jsx(
114
+ "button",
115
+ {
116
+ onClick: () => window.location.reload(),
117
+ className: "px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90",
118
+ children: "Refresh Page"
119
+ }
120
+ )
121
+ ] }) });
122
+ }
123
+ return this.props.children;
124
+ }
125
+ };
126
+ __name(_ErrorBoundary, "ErrorBoundary");
127
+ var ErrorBoundary = _ErrorBoundary;
128
+
129
+ // src/components/errors/errorConfig.ts
130
+ function getErrorContent(statusCode) {
131
+ const code = typeof statusCode === "string" ? parseInt(statusCode, 10) : statusCode;
132
+ switch (code) {
133
+ // 400 Bad Request
134
+ case 400:
135
+ return {
136
+ title: "Bad Request",
137
+ description: "The request could not be understood. Please check your input and try again."
138
+ };
139
+ // 401 Unauthorized
140
+ case 401:
141
+ return {
142
+ title: "Authentication Required",
143
+ description: "You need to sign in to access this page."
144
+ };
145
+ // 403 Forbidden
146
+ case 403:
147
+ return {
148
+ title: "Access Denied",
149
+ description: "You don't have permission to access this resource."
150
+ };
151
+ // 404 Not Found
152
+ case 404:
153
+ return {
154
+ title: "Page Not Found",
155
+ description: "The page you're looking for doesn't exist or has been moved."
156
+ };
157
+ // 408 Request Timeout
158
+ case 408:
159
+ return {
160
+ title: "Request Timeout",
161
+ description: "The request took too long to process. Please try again."
162
+ };
163
+ // 500 Internal Server Error
164
+ case 500:
165
+ return {
166
+ title: "Server Error",
167
+ description: "Something went wrong on our end. We're working to fix it."
168
+ };
169
+ // 502 Bad Gateway
170
+ case 502:
171
+ return {
172
+ title: "Bad Gateway",
173
+ description: "The server received an invalid response. Please try again later."
174
+ };
175
+ // 503 Service Unavailable
176
+ case 503:
177
+ return {
178
+ title: "Service Unavailable",
179
+ description: "The service is temporarily unavailable. Please try again later."
180
+ };
181
+ // 504 Gateway Timeout
182
+ case 504:
183
+ return {
184
+ title: "Gateway Timeout",
185
+ description: "The server took too long to respond. Please try again."
186
+ };
187
+ // Default / Unknown Error
188
+ default:
189
+ return {
190
+ title: "Something Went Wrong",
191
+ description: "An unexpected error occurred. Please try again or contact support."
192
+ };
193
+ }
194
+ }
195
+ __name(getErrorContent, "getErrorContent");
196
+ var ERROR_CODES = {
197
+ BAD_REQUEST: 400,
198
+ UNAUTHORIZED: 401,
199
+ FORBIDDEN: 403,
200
+ NOT_FOUND: 404,
201
+ TIMEOUT: 408,
202
+ SERVER_ERROR: 500,
203
+ BAD_GATEWAY: 502,
204
+ SERVICE_UNAVAILABLE: 503,
205
+ GATEWAY_TIMEOUT: 504
206
+ };
207
+ function getErrorIcon(code) {
208
+ const c = code ? String(code) : "";
209
+ switch (c) {
210
+ case "404":
211
+ return /* @__PURE__ */ jsx(
212
+ "svg",
213
+ {
214
+ className: "w-32 h-32 mx-auto text-foreground/80",
215
+ viewBox: "0 0 32 32",
216
+ fill: "currentColor",
217
+ "aria-hidden": "true",
218
+ children: /* @__PURE__ */ jsxs("g", { children: [
219
+ /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M19.889 21.734v-.947l-.631.947z" }),
220
+ /* @__PURE__ */ jsx("path", { d: "M15.484 19.636h1.032a.017.017 0 0 1 .017.017v3.1a.016.016 0 0 1-.016.016h-1.034a.016.016 0 0 1-.016-.016v-3.1a.017.017 0 0 1 .017-.017z" }),
221
+ /* @__PURE__ */ jsxs("g", { fillRule: "evenodd", children: [
222
+ /* @__PURE__ */ jsx("path", { d: "M12.402 21.734v-.947l-.631.947z" }),
223
+ /* @__PURE__ */ jsx("path", { d: "M16 1.5A14.5 14.5 0 1 0 30.5 16 14.507 14.507 0 0 0 16 1.5zm-2.324 21.234H13.4v.532a.5.5 0 0 1-1 0v-.532h-1.563a.5.5 0 0 1-.416-.778l2.067-3.1a.5.5 0 0 1 .914.28v2.6h.274a.5.5 0 0 1 0 1zm-2.137-9.9A4.14 4.14 0 0 1 15.545 9.8a.5.5 0 0 1 0 1 3.138 3.138 0 0 0-3.04 2.3.5.5 0 0 1-.966-.259zm5.994 9.911a1.017 1.017 0 0 1-1.017 1.016h-1.032a1.017 1.017 0 0 1-1.017-1.016v-3.1a1.017 1.017 0 0 1 1.017-1.016h1.032a1.017 1.017 0 0 1 1.017 1.016zm3.63-.016h-.274v.532a.5.5 0 0 1-1 0v-.532h-1.565a.5.5 0 0 1-.416-.778l2.067-3.1a.5.5 0 0 1 .914.28v2.6h.274a.5.5 0 0 1 0 1zm1.036-1.52a.5.5 0 1 1-.4-.917 3.263 3.263 0 0 0-1.337-6.266.5.5 0 0 1-.5-.5 4.6 4.6 0 0 0-9.2 0 4.45 4.45 0 0 0 .153 1.161.5.5 0 0 1-.411.625 2.633 2.633 0 0 0-.364 5.148.5.5 0 0 1-.278.961 3.63 3.63 0 0 1-.024-6.984 5.467 5.467 0 0 1-.076-.911 5.6 5.6 0 0 1 11.182-.474 4.258 4.258 0 0 1 1.256 8.162z" })
224
+ ] })
225
+ ] })
226
+ }
227
+ );
228
+ case "500":
229
+ return /* @__PURE__ */ jsx(
230
+ "svg",
231
+ {
232
+ className: "w-32 h-32 mx-auto text-foreground/80",
233
+ viewBox: "0 0 512 512",
234
+ fill: "currentColor",
235
+ "aria-hidden": "true",
236
+ children: /* @__PURE__ */ jsxs("g", { children: [
237
+ /* @__PURE__ */ jsx("path", { d: "M256 118c-76.1 0-138 61.88-138 138s61.9 138.05 138 138.05 138-61.93 138-138S332.1 118 256 118zm0 237.93a30.12 30.12 0 1 1 30.11-30.12A30.15 30.15 0 0 1 256 355.88zm30.11-80.31a8.48 8.48 0 0 1-8.47 8.48h-43.28a8.48 8.48 0 0 1-8.47-8.48v-111a8.47 8.47 0 0 1 8.47-8.47h43.28a8.47 8.47 0 0 1 8.47 8.47z" }),
238
+ /* @__PURE__ */ jsx("path", { d: "M256 312.6a13.17 13.17 0 1 0 13.16 13.16A13.17 13.17 0 0 0 256 312.6zM242.84 173.07h26.32v94.02h-26.32z" }),
239
+ /* @__PURE__ */ jsx("path", { d: "M256 0C114.62 0 0 114.62 0 256s114.62 256 256 256 256-114.62 256-256S397.38 0 256 0zm109.57 365.6A155 155 0 1 1 411 256a153.91 153.91 0 0 1-45.43 109.6z" })
240
+ ] })
241
+ }
242
+ );
243
+ case "403":
244
+ return /* @__PURE__ */ jsx(
245
+ "svg",
246
+ {
247
+ className: "w-32 h-32 mx-auto text-foreground/80",
248
+ viewBox: "0 0 24 24",
249
+ fill: "currentColor",
250
+ "aria-hidden": "true",
251
+ children: /* @__PURE__ */ jsx("path", { d: "M12 1a11 11 0 1 0 11 11A11.013 11.013 0 0 0 12 1zm4.242 13.829a1 1 0 1 1-1.414 1.414L12 13.414l-2.828 2.829a1 1 0 0 1-1.414-1.414L10.586 12 7.758 9.171a1 1 0 1 1 1.414-1.414L12 10.586l2.828-2.829a1 1 0 1 1 1.414 1.414L13.414 12z" })
252
+ }
253
+ );
254
+ default:
255
+ return null;
256
+ }
257
+ }
258
+ __name(getErrorIcon, "getErrorIcon");
259
+ function ErrorLayout({
260
+ code,
261
+ title,
262
+ description,
263
+ actions,
264
+ showDefaultActions = true,
265
+ illustration,
266
+ supportEmail = "support@example.com"
267
+ }) {
268
+ const autoContent = code && (!title || !description) ? getErrorContent(code) : null;
269
+ const finalTitle = title || autoContent?.title || "Error";
270
+ const finalDescription = description || autoContent?.description;
271
+ const finalIllustration = illustration ?? getErrorIcon(code);
272
+ const handleGoBack = /* @__PURE__ */ __name(() => {
273
+ if (document.referrer && document.referrer !== window.location.href) {
274
+ window.location.href = document.referrer;
275
+ } else if (window.history.length > 1) {
276
+ window.history.back();
277
+ } else {
278
+ window.location.href = "/";
279
+ }
280
+ }, "handleGoBack");
281
+ const handleGoHome = /* @__PURE__ */ __name(() => {
282
+ window.location.href = "/";
283
+ }, "handleGoHome");
284
+ return /* @__PURE__ */ jsx("div", { className: "min-h-screen flex items-center justify-center px-4 bg-background", children: /* @__PURE__ */ jsxs("div", { className: "max-w-2xl w-full text-center space-y-8", children: [
285
+ finalIllustration && /* @__PURE__ */ jsx("div", { className: "flex justify-center py-8", children: finalIllustration }),
286
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
287
+ /* @__PURE__ */ jsx("h2", { className: "text-4xl font-bold text-foreground", children: finalTitle }),
288
+ finalDescription && /* @__PURE__ */ jsx("p", { className: "text-lg text-muted-foreground max-w-md mx-auto", children: finalDescription })
289
+ ] }),
290
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-center justify-center gap-4 pt-4", children: [
291
+ actions,
292
+ showDefaultActions && !actions && /* @__PURE__ */ jsxs(Fragment, { children: [
293
+ /* @__PURE__ */ jsx(
294
+ Button,
295
+ {
296
+ variant: "outline",
297
+ size: "lg",
298
+ onClick: handleGoBack,
299
+ style: { minWidth: "140px", padding: "12px 32px" },
300
+ children: "Go Back"
301
+ }
302
+ ),
303
+ /* @__PURE__ */ jsx(
304
+ Button,
305
+ {
306
+ variant: "default",
307
+ size: "lg",
308
+ onClick: handleGoHome,
309
+ style: { minWidth: "140px", padding: "12px 32px" },
310
+ children: "Go Home"
311
+ }
312
+ )
313
+ ] })
314
+ ] }),
315
+ /* @__PURE__ */ jsx("div", { className: "pt-8 text-sm text-muted-foreground", children: /* @__PURE__ */ jsxs("p", { children: [
316
+ "Need help? Contact",
317
+ " ",
318
+ /* @__PURE__ */ jsx(
319
+ "a",
320
+ {
321
+ href: `mailto:${supportEmail}`,
322
+ className: "text-primary hover:underline",
323
+ children: "support"
324
+ }
325
+ )
326
+ ] }) })
327
+ ] }) });
328
+ }
329
+ __name(ErrorLayout, "ErrorLayout");
330
+ function RedirectPage({
331
+ authenticatedPath = "/private",
332
+ unauthenticatedPath = "/auth",
333
+ loadingText = "Loading..."
334
+ }) {
335
+ const { isAuthenticated } = useAuth();
336
+ const router = useCfgRouter();
337
+ useEffect(() => {
338
+ if (!isAuthenticated) {
339
+ router.hardPush(unauthenticatedPath);
340
+ } else {
341
+ router.hardPush(authenticatedPath);
342
+ }
343
+ }, [isAuthenticated, router, authenticatedPath, unauthenticatedPath]);
344
+ return /* @__PURE__ */ jsx(
345
+ Preloader,
346
+ {
347
+ variant: "fullscreen",
348
+ text: loadingText,
349
+ size: "lg"
350
+ }
351
+ );
352
+ }
353
+ __name(RedirectPage, "RedirectPage");
354
+
355
+ // src/components/errors/ErrorsTracker/utils/formatters.ts
356
+ function formatZodIssues(error, maxIssues = 3) {
357
+ const issues = error.issues.slice(0, maxIssues);
358
+ const formatted = issues.map((issue) => {
359
+ const path = issue.path.join(".") || "root";
360
+ return `${path}: ${issue.message}`;
361
+ });
362
+ if (error.issues.length > maxIssues) {
363
+ formatted.push(`... and ${error.issues.length - maxIssues} more`);
364
+ }
365
+ return formatted.join(", ");
366
+ }
367
+ __name(formatZodIssues, "formatZodIssues");
368
+ function formatValidationErrorForClipboard(detail) {
369
+ const errorData = {
370
+ type: "validation",
371
+ timestamp: detail.timestamp.toISOString(),
372
+ operation: detail.operation,
373
+ endpoint: {
374
+ method: detail.method,
375
+ path: detail.path
376
+ },
377
+ validation_errors: detail.error.issues.map((issue) => ({
378
+ path: issue.path.join(".") || "root",
379
+ message: issue.message,
380
+ code: issue.code,
381
+ ..."expected" in issue && { expected: issue.expected },
382
+ ..."received" in issue && { received: issue.received },
383
+ ..."minimum" in issue && { minimum: issue.minimum },
384
+ ..."maximum" in issue && { maximum: issue.maximum }
385
+ })),
386
+ response: detail.response,
387
+ total_errors: detail.error.issues.length
388
+ };
389
+ return JSON.stringify(errorData, null, 2);
390
+ }
391
+ __name(formatValidationErrorForClipboard, "formatValidationErrorForClipboard");
392
+ function formatCORSErrorForClipboard(detail) {
393
+ const errorData = {
394
+ type: "cors",
395
+ timestamp: detail.timestamp.toISOString(),
396
+ url: detail.url,
397
+ method: detail.method,
398
+ error: detail.error
399
+ };
400
+ return JSON.stringify(errorData, null, 2);
401
+ }
402
+ __name(formatCORSErrorForClipboard, "formatCORSErrorForClipboard");
403
+ function formatNetworkErrorForClipboard(detail) {
404
+ const errorData = {
405
+ type: "network",
406
+ timestamp: detail.timestamp.toISOString(),
407
+ url: detail.url,
408
+ method: detail.method,
409
+ error: detail.error,
410
+ ...detail.statusCode && { statusCode: detail.statusCode }
411
+ };
412
+ return JSON.stringify(errorData, null, 2);
413
+ }
414
+ __name(formatNetworkErrorForClipboard, "formatNetworkErrorForClipboard");
415
+ function formatCentrifugoErrorForClipboard(detail) {
416
+ const errorData = {
417
+ type: "centrifugo",
418
+ timestamp: detail.timestamp.toISOString(),
419
+ method: detail.method,
420
+ error: detail.error,
421
+ ...detail.code !== void 0 && { code: detail.code },
422
+ ...detail.data && { data: detail.data }
423
+ };
424
+ return JSON.stringify(errorData, null, 2);
425
+ }
426
+ __name(formatCentrifugoErrorForClipboard, "formatCentrifugoErrorForClipboard");
427
+ function extractDomain(url) {
428
+ try {
429
+ const urlObj = new URL(url);
430
+ return urlObj.origin;
431
+ } catch {
432
+ return url;
433
+ }
434
+ }
435
+ __name(extractDomain, "extractDomain");
436
+ function formatErrorTitle(detail) {
437
+ switch (detail.type) {
438
+ case "validation":
439
+ return `\u274C Validation Error in ${detail.operation}`;
440
+ case "cors":
441
+ return "\u{1F6AB} CORS Error";
442
+ case "network":
443
+ return detail.statusCode ? `\u26A0\uFE0F Network Error (${detail.statusCode})` : "\u26A0\uFE0F Network Error";
444
+ case "centrifugo":
445
+ return detail.code !== void 0 ? `\u{1F50C} Centrifugo Error (${detail.code})` : "\u{1F50C} Centrifugo Error";
446
+ default:
447
+ return "\u274C Error";
448
+ }
449
+ }
450
+ __name(formatErrorTitle, "formatErrorTitle");
451
+ function getAuthToken() {
452
+ if (typeof window === "undefined") return null;
453
+ try {
454
+ const token = localStorage.getItem("access_token") || localStorage.getItem("token") || localStorage.getItem("auth_token");
455
+ return token;
456
+ } catch (error) {
457
+ consola.error("Failed to get auth token:", error);
458
+ return null;
459
+ }
460
+ }
461
+ __name(getAuthToken, "getAuthToken");
462
+ function formatHeaders(headers) {
463
+ return Object.entries(headers).map(
464
+ ([key, value]) => `-H '${key}: ${value}'`
465
+ );
466
+ }
467
+ __name(formatHeaders, "formatHeaders");
468
+ function escapeShell(str) {
469
+ return str.replace(/'/g, "'\\''");
470
+ }
471
+ __name(escapeShell, "escapeShell");
472
+ function generateCurl(options) {
473
+ const {
474
+ method,
475
+ path,
476
+ token = getAuthToken() || void 0,
477
+ // Auto-fetch if not provided
478
+ body,
479
+ headers = {},
480
+ baseUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"
481
+ } = options;
482
+ const curlParts = ["curl"];
483
+ const url = `${baseUrl}${path}`;
484
+ curlParts.push(`'${url}'`);
485
+ if (method.toUpperCase() !== "GET") {
486
+ curlParts.push(`-X ${method.toUpperCase()}`);
487
+ }
488
+ const allHeaders = {
489
+ "Accept": "*/*",
490
+ "Content-Type": "application/json",
491
+ ...headers
492
+ };
493
+ if (token) {
494
+ allHeaders["Authorization"] = `Bearer ${token}`;
495
+ }
496
+ const headerStrings = formatHeaders(allHeaders);
497
+ curlParts.push(...headerStrings);
498
+ if (body && method.toUpperCase() !== "GET") {
499
+ const bodyJson = typeof body === "string" ? body : JSON.stringify(body, null, 2);
500
+ curlParts.push(`-d '${escapeShell(bodyJson)}'`);
501
+ }
502
+ return curlParts.join(" \\\n ");
503
+ }
504
+ __name(generateCurl, "generateCurl");
505
+ function generateCurlFromError(detail) {
506
+ return generateCurl({
507
+ method: detail.method,
508
+ path: detail.path
509
+ // token is auto-fetched in generateCurl
510
+ });
511
+ }
512
+ __name(generateCurlFromError, "generateCurlFromError");
513
+ function formatErrorForClipboard(detail) {
514
+ switch (detail.type) {
515
+ case "validation":
516
+ return formatValidationErrorForClipboard(detail);
517
+ case "cors":
518
+ return formatCORSErrorForClipboard(detail);
519
+ case "network":
520
+ return formatNetworkErrorForClipboard(detail);
521
+ case "centrifugo":
522
+ return formatCentrifugoErrorForClipboard(detail);
523
+ default:
524
+ return JSON.stringify(detail, null, 2);
525
+ }
526
+ }
527
+ __name(formatErrorForClipboard, "formatErrorForClipboard");
528
+ function supportsCurl(detail) {
529
+ return detail.type === "validation";
530
+ }
531
+ __name(supportsCurl, "supportsCurl");
532
+ function ErrorButtons({ detail }) {
533
+ const { copyToClipboard } = useCopy();
534
+ const handleCopyError = /* @__PURE__ */ __name(async (e) => {
535
+ e.preventDefault();
536
+ e.stopPropagation();
537
+ const formattedError = formatErrorForClipboard(detail);
538
+ await copyToClipboard(formattedError, "\u2705 Error details copied");
539
+ }, "handleCopyError");
540
+ const handleCopyCurl = /* @__PURE__ */ __name(async (e) => {
541
+ e.preventDefault();
542
+ e.stopPropagation();
543
+ if (detail.type === "validation") {
544
+ const curl = generateCurlFromError({
545
+ method: detail.method,
546
+ path: detail.path,
547
+ response: detail.response
548
+ });
549
+ await copyToClipboard(curl, "\u2705 cURL command copied");
550
+ }
551
+ }, "handleCopyCurl");
552
+ return /* @__PURE__ */ jsxs("div", { className: "flex gap-2 mt-2", children: [
553
+ /* @__PURE__ */ jsxs(
554
+ Button$1,
555
+ {
556
+ size: "sm",
557
+ variant: "secondary",
558
+ onClick: handleCopyError,
559
+ className: "h-8 text-xs bg-background hover:bg-background/80 text-foreground border border-border gap-1.5",
560
+ children: [
561
+ /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" }),
562
+ "Copy Error"
563
+ ]
564
+ }
565
+ ),
566
+ supportsCurl(detail) && /* @__PURE__ */ jsxs(
567
+ Button$1,
568
+ {
569
+ size: "sm",
570
+ variant: "secondary",
571
+ onClick: handleCopyCurl,
572
+ className: "h-8 text-xs bg-background hover:bg-background/80 text-foreground border border-border gap-1.5",
573
+ children: [
574
+ /* @__PURE__ */ jsx(Terminal, { className: "h-3.5 w-3.5" }),
575
+ "Copy cURL"
576
+ ]
577
+ }
578
+ )
579
+ ] });
580
+ }
581
+ __name(ErrorButtons, "ErrorButtons");
582
+ function buildValidationDescription(detail, config) {
583
+ const descriptionParts = [];
584
+ if (config.showPath) {
585
+ descriptionParts.push(`${detail.method} ${detail.path}`);
586
+ }
587
+ if (config.showErrorCount) {
588
+ const count = detail.error.issues.length;
589
+ const plural = count === 1 ? "error" : "errors";
590
+ descriptionParts.push(`${count} ${plural}`);
591
+ }
592
+ const issuesText = formatZodIssues(detail.error, config.maxIssuesInToast);
593
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 text-sm", children: [
594
+ descriptionParts.length > 0 && /* @__PURE__ */ jsx("div", { className: "font-mono text-xs opacity-90", children: descriptionParts.join(" \u2022 ") }),
595
+ /* @__PURE__ */ jsx("div", { className: "opacity-90", children: issuesText }),
596
+ /* @__PURE__ */ jsx(ErrorButtons, { detail })
597
+ ] });
598
+ }
599
+ __name(buildValidationDescription, "buildValidationDescription");
600
+ function buildCORSDescription(detail, config) {
601
+ const domain = extractDomain(detail.url);
602
+ const parts = [];
603
+ if (config.showMethod && config.showUrl) {
604
+ parts.push(`${detail.method} ${detail.url}`);
605
+ } else if (config.showUrl) {
606
+ parts.push(detail.url);
607
+ } else if (config.showMethod) {
608
+ parts.push(`${detail.method} request blocked`);
609
+ }
610
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 text-sm", children: [
611
+ parts.length > 0 && /* @__PURE__ */ jsx("div", { className: "font-mono text-xs opacity-90", children: parts.join(" \u2022 ") }),
612
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
613
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: "Request blocked by CORS policy" }),
614
+ /* @__PURE__ */ jsxs("div", { className: "text-xs opacity-75", children: [
615
+ "Check CORS configuration on ",
616
+ domain
617
+ ] })
618
+ ] }),
619
+ /* @__PURE__ */ jsx(ErrorButtons, { detail })
620
+ ] });
621
+ }
622
+ __name(buildCORSDescription, "buildCORSDescription");
623
+ function buildNetworkDescription(detail, config) {
624
+ const parts = [];
625
+ if (config.showMethod && config.showUrl) {
626
+ parts.push(`${detail.method} ${detail.url}`);
627
+ } else if (config.showUrl) {
628
+ parts.push(detail.url);
629
+ } else if (config.showMethod) {
630
+ parts.push(`${detail.method} request failed`);
631
+ }
632
+ if (config.showStatusCode && detail.statusCode) {
633
+ parts.push(`Status: ${detail.statusCode}`);
634
+ }
635
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 text-sm", children: [
636
+ parts.length > 0 && /* @__PURE__ */ jsx("div", { className: "font-mono text-xs opacity-90", children: parts.join(" \u2022 ") }),
637
+ /* @__PURE__ */ jsx("div", { className: "opacity-90", children: detail.error }),
638
+ /* @__PURE__ */ jsx(ErrorButtons, { detail })
639
+ ] });
640
+ }
641
+ __name(buildNetworkDescription, "buildNetworkDescription");
642
+ function buildCentrifugoDescription(detail, config) {
643
+ const parts = [];
644
+ if (config.showMethod) {
645
+ parts.push(`RPC: ${detail.method}`);
646
+ }
647
+ if (config.showCode && detail.code !== void 0) {
648
+ parts.push(`Code: ${detail.code}`);
649
+ }
650
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 text-sm", children: [
651
+ parts.length > 0 && /* @__PURE__ */ jsx("div", { className: "font-mono text-xs opacity-90", children: parts.join(" \u2022 ") }),
652
+ /* @__PURE__ */ jsx("div", { className: "opacity-90", children: detail.error }),
653
+ /* @__PURE__ */ jsx(ErrorButtons, { detail })
654
+ ] });
655
+ }
656
+ __name(buildCentrifugoDescription, "buildCentrifugoDescription");
657
+ function createErrorToast(detail, config) {
658
+ let description;
659
+ if (detail.type === "validation") {
660
+ description = buildValidationDescription(detail, config);
661
+ } else if (detail.type === "cors") {
662
+ description = buildCORSDescription(detail, config);
663
+ } else if (detail.type === "centrifugo") {
664
+ description = buildCentrifugoDescription(detail, config);
665
+ } else {
666
+ description = buildNetworkDescription(detail, config);
667
+ }
668
+ return {
669
+ title: formatErrorTitle(detail),
670
+ description,
671
+ variant: "destructive",
672
+ duration: config.duration
673
+ };
674
+ }
675
+ __name(createErrorToast, "createErrorToast");
676
+
677
+ // src/components/errors/ErrorsTracker/types.ts
678
+ var ERROR_EVENTS = {
679
+ VALIDATION: "zod-validation-error",
680
+ CORS: "cors-error",
681
+ NETWORK: "network-error",
682
+ /** Unified Centrifugo event - filter by detail.type === 'error' */
683
+ CENTRIFUGO: "centrifugo"
684
+ };
685
+ var DEFAULT_ERROR_CONFIG = {
686
+ enabled: true,
687
+ showToast: true,
688
+ maxErrors: 50,
689
+ duration: 8e3
690
+ };
691
+ var DEFAULT_VALIDATION_CONFIG = {
692
+ ...DEFAULT_ERROR_CONFIG,
693
+ showOperation: true,
694
+ showPath: true,
695
+ showErrorCount: true,
696
+ maxIssuesInToast: 3
697
+ };
698
+ var DEFAULT_CORS_CONFIG = {
699
+ ...DEFAULT_ERROR_CONFIG,
700
+ duration: 0,
701
+ // Don't auto-dismiss CORS errors
702
+ showUrl: true,
703
+ showMethod: true
704
+ };
705
+ var DEFAULT_NETWORK_CONFIG = {
706
+ ...DEFAULT_ERROR_CONFIG,
707
+ duration: 0,
708
+ // Don't auto-dismiss network errors
709
+ showUrl: true,
710
+ showMethod: true,
711
+ showStatusCode: true
712
+ };
713
+ var DEFAULT_CENTRIFUGO_CONFIG = {
714
+ ...DEFAULT_ERROR_CONFIG,
715
+ duration: 0,
716
+ // Don't auto-dismiss centrifugo errors
717
+ showMethod: true,
718
+ showCode: true
719
+ };
720
+ var ErrorTrackingContext = createContext(void 0);
721
+ var errorIdCounter = 0;
722
+ function generateErrorId(type) {
723
+ return `${type}-error-${Date.now()}-${++errorIdCounter}`;
724
+ }
725
+ __name(generateErrorId, "generateErrorId");
726
+ function ErrorTrackingProvider({
727
+ children,
728
+ validation: userValidationConfig,
729
+ cors: userCorsConfig,
730
+ network: userNetworkConfig,
731
+ centrifugo: userCentrifugoConfig,
732
+ onError
733
+ }) {
734
+ const [errors, setErrors] = useState([]);
735
+ const validationConfig = {
736
+ ...DEFAULT_VALIDATION_CONFIG,
737
+ ...userValidationConfig
738
+ };
739
+ const corsConfig = {
740
+ ...DEFAULT_CORS_CONFIG,
741
+ ...userCorsConfig
742
+ };
743
+ const networkConfig = {
744
+ ...DEFAULT_NETWORK_CONFIG,
745
+ ...userNetworkConfig
746
+ };
747
+ const centrifugoConfig = {
748
+ ...DEFAULT_CENTRIFUGO_CONFIG,
749
+ ...userCentrifugoConfig
750
+ };
751
+ const clearErrors = useCallback(() => {
752
+ setErrors([]);
753
+ }, []);
754
+ const clearErrorsByType = useCallback((type) => {
755
+ setErrors((prev) => prev.filter((error) => error.type !== type));
756
+ }, []);
757
+ const clearError = useCallback((id) => {
758
+ setErrors((prev) => prev.filter((error) => error.id !== id));
759
+ }, []);
760
+ const handleError = useCallback(
761
+ (detail, config) => {
762
+ const storedError = {
763
+ ...detail,
764
+ id: generateErrorId(detail.type)
765
+ };
766
+ setErrors((prev) => {
767
+ const updated = [storedError, ...prev];
768
+ return updated.slice(0, config.maxErrors);
769
+ });
770
+ const shouldShowToast = onError?.(detail) !== false;
771
+ if (config.showToast && shouldShowToast) {
772
+ const toastOptions = createErrorToast(detail, config);
773
+ toast.error(toastOptions.title, {
774
+ description: toastOptions.description,
775
+ duration: toastOptions.duration
776
+ });
777
+ }
778
+ },
779
+ [onError]
780
+ );
781
+ useEffect(() => {
782
+ if (typeof window === "undefined") return;
783
+ const handlers = [];
784
+ if (validationConfig.enabled) {
785
+ const handler = /* @__PURE__ */ __name((event) => {
786
+ if (!(event instanceof CustomEvent)) return;
787
+ const detail = {
788
+ ...event.detail,
789
+ type: "validation"
790
+ };
791
+ handleError(detail, validationConfig);
792
+ }, "handler");
793
+ window.addEventListener(ERROR_EVENTS.VALIDATION, handler);
794
+ handlers.push({ event: ERROR_EVENTS.VALIDATION, handler });
795
+ }
796
+ if (corsConfig.enabled) {
797
+ const handler = /* @__PURE__ */ __name((event) => {
798
+ if (!(event instanceof CustomEvent)) return;
799
+ const detail = {
800
+ ...event.detail,
801
+ type: "cors"
802
+ };
803
+ handleError(detail, corsConfig);
804
+ }, "handler");
805
+ window.addEventListener(ERROR_EVENTS.CORS, handler);
806
+ handlers.push({ event: ERROR_EVENTS.CORS, handler });
807
+ }
808
+ if (networkConfig.enabled) {
809
+ const handler = /* @__PURE__ */ __name((event) => {
810
+ if (!(event instanceof CustomEvent)) return;
811
+ const detail = {
812
+ ...event.detail,
813
+ type: "network"
814
+ };
815
+ handleError(detail, networkConfig);
816
+ }, "handler");
817
+ window.addEventListener(ERROR_EVENTS.NETWORK, handler);
818
+ handlers.push({ event: ERROR_EVENTS.NETWORK, handler });
819
+ }
820
+ if (centrifugoConfig.enabled) {
821
+ const handler = /* @__PURE__ */ __name((event) => {
822
+ if (!(event instanceof CustomEvent)) return;
823
+ if (event.detail?.type !== "error") return;
824
+ const detail = {
825
+ type: "centrifugo",
826
+ method: event.detail.data?.method || "unknown",
827
+ error: event.detail.data?.error || "Unknown error",
828
+ code: event.detail.data?.code,
829
+ data: event.detail.data?.data,
830
+ timestamp: event.detail.timestamp || /* @__PURE__ */ new Date()
831
+ };
832
+ handleError(detail, centrifugoConfig);
833
+ }, "handler");
834
+ window.addEventListener(ERROR_EVENTS.CENTRIFUGO, handler);
835
+ handlers.push({ event: ERROR_EVENTS.CENTRIFUGO, handler });
836
+ }
837
+ return () => {
838
+ handlers.forEach(({ event, handler }) => {
839
+ window.removeEventListener(event, handler);
840
+ });
841
+ };
842
+ }, [handleError, validationConfig, corsConfig, networkConfig, centrifugoConfig]);
843
+ const validationErrors = errors.filter((e) => e.type === "validation");
844
+ const corsErrors = errors.filter((e) => e.type === "cors");
845
+ const networkErrors = errors.filter((e) => e.type === "network");
846
+ const centrifugoErrors = errors.filter((e) => e.type === "centrifugo");
847
+ const value = {
848
+ errors,
849
+ validationErrors,
850
+ corsErrors,
851
+ networkErrors,
852
+ centrifugoErrors,
853
+ clearErrors,
854
+ clearErrorsByType,
855
+ clearError,
856
+ errorCount: errors.length,
857
+ latestError: errors[0] || null,
858
+ config: {
859
+ validation: validationConfig,
860
+ cors: corsConfig,
861
+ network: networkConfig,
862
+ centrifugo: centrifugoConfig
863
+ }
864
+ };
865
+ return /* @__PURE__ */ jsx(ErrorTrackingContext.Provider, { value, children });
866
+ }
867
+ __name(ErrorTrackingProvider, "ErrorTrackingProvider");
868
+ function useErrors() {
869
+ const context = useContext(ErrorTrackingContext);
870
+ if (context === void 0) {
871
+ throw new Error("useErrors must be used within ErrorTrackingProvider");
872
+ }
873
+ return context;
874
+ }
875
+ __name(useErrors, "useErrors");
876
+
877
+ export { ClientOnly, ERROR_CODES, ErrorBoundary, ErrorButtons, ErrorLayout, ErrorTrackingProvider, JsonLd, LucideIcon, RedirectPage, Suspense, createErrorToast, extractDomain, formatCORSErrorForClipboard, formatCentrifugoErrorForClipboard, formatErrorTitle, formatNetworkErrorForClipboard, formatValidationErrorForClipboard, formatZodIssues, generateCurl, generateCurlFromError, getAuthToken, getErrorContent, useErrors };
878
+ //# sourceMappingURL=components.mjs.map
879
+ //# sourceMappingURL=components.mjs.map