xertica-ui 2.3.0 → 2.4.1

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 (105) hide show
  1. package/CHANGELOG.md +22 -2
  2. package/README.md +33 -22
  3. package/bin/cli.ts +136 -47
  4. package/bin/language-config.ts +5 -8
  5. package/components/assistant/modern-chat-input/ModernChatInput.tsx +17 -7
  6. package/components/assistant/xertica-assistant/parts/AssistantConversationList.tsx +1 -3
  7. package/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.tsx +13 -3
  8. package/components/assistant/xertica-assistant/parts/AssistantMessageBubble.tsx +10 -6
  9. package/components/assistant/xertica-assistant/xertica-assistant.tsx +1 -3
  10. package/components/blocks/card-patterns/FeatureCardSkeleton.tsx +1 -6
  11. package/components/blocks/card-patterns/ProfileCard.tsx +1 -3
  12. package/components/blocks/card-patterns/ProjectCardSkeleton.tsx +1 -6
  13. package/components/brand/language-selector/language-selector.stories.tsx +1 -4
  14. package/components/brand/theme-toggle/ThemeToggle.tsx +5 -1
  15. package/components/brand/xertica-provider/XerticaProvider.tsx +1 -4
  16. package/components/index.ts +1 -5
  17. package/components/layout/sidebar/sidebar.tsx +9 -3
  18. package/components/media/audio-player/AudioPlayer.tsx +4 -2
  19. package/components/pages/forgot-password-page/ForgotPasswordPage.tsx +188 -188
  20. package/components/pages/home-content/HomeContent.tsx +55 -55
  21. package/components/pages/home-page/HomePage.tsx +5 -1
  22. package/components/pages/login-page/LoginPage.tsx +4 -2
  23. package/components/pages/reset-password-page/ResetPasswordPage.tsx +7 -3
  24. package/components/pages/template-content/TemplateContent.tsx +268 -149
  25. package/components/pages/verify-email-page/VerifyEmailPage.tsx +9 -9
  26. package/components/shared/error-boundary.stories.tsx +114 -132
  27. package/components/shared/error-boundary.tsx +150 -154
  28. package/components/shared/error-fallbacks.tsx +222 -226
  29. package/components/ui/stats-card/stats-card-skeleton.tsx +1 -3
  30. package/components/ui/stats-card/stats-card.stories.tsx +18 -0
  31. package/components/ui/stats-card/stats-card.tsx +18 -2
  32. package/components.json +512 -892
  33. package/contexts/AuthContext.tsx +121 -118
  34. package/contexts/LanguageContext.tsx +1 -2
  35. package/dist/AssistantChart-BKVtGUKF.js +3383 -0
  36. package/dist/AssistantChart-WeycT5Pd.cjs +3551 -0
  37. package/dist/VerifyEmailPage-Bp1XXl3H.cjs +3305 -0
  38. package/dist/VerifyEmailPage-DGhuIqkb.js +3296 -0
  39. package/dist/XerticaProvider-BErr83Bg.js +42 -0
  40. package/dist/XerticaProvider-CwOkHxiT.cjs +44 -0
  41. package/dist/XerticaXLogo-BX3ueACh.js +255 -0
  42. package/dist/XerticaXLogo-qBPhwK3g.cjs +260 -0
  43. package/dist/assistant.cjs.js +1 -1
  44. package/dist/assistant.es.js +1 -1
  45. package/dist/brand.cjs.js +2 -2
  46. package/dist/brand.es.js +2 -2
  47. package/dist/cli.js +90 -37
  48. package/dist/components/brand/theme-toggle/ThemeToggle.d.ts +1 -1
  49. package/dist/components/index.d.ts +1 -1
  50. package/dist/components/ui/stats-card/stats-card.d.ts +10 -0
  51. package/dist/index.cjs.js +6 -6
  52. package/dist/index.es.js +6 -6
  53. package/dist/layout.cjs.js +1 -1
  54. package/dist/layout.es.js +1 -1
  55. package/dist/pages.cjs.js +1 -1
  56. package/dist/pages.es.js +1 -1
  57. package/dist/sidebar-B4ZWaMrE.js +792 -0
  58. package/dist/sidebar-BS1p2V7t.cjs +795 -0
  59. package/dist/ui.cjs.js +1 -1
  60. package/dist/ui.es.js +1 -1
  61. package/dist/xertica-assistant-B1NaSFFj.js +2173 -0
  62. package/dist/xertica-assistant-CIaUlbIt.cjs +2180 -0
  63. package/dist/xertica-ui.css +1 -1
  64. package/docs/architecture-improvements.md +5 -5
  65. package/docs/architecture.md +16 -10
  66. package/docs/components/card-patterns.md +19 -17
  67. package/docs/components/error-boundary.md +201 -191
  68. package/docs/components/hooks.md +15 -13
  69. package/docs/components/language-selector.md +20 -16
  70. package/docs/components/pages.md +323 -309
  71. package/docs/components/stats-card.md +20 -2
  72. package/docs/doc-audit.md +12 -11
  73. package/docs/getting-started.md +41 -28
  74. package/docs/guidelines.md +14 -12
  75. package/docs/i18n.md +61 -57
  76. package/docs/installation.md +268 -267
  77. package/docs/llms.md +17 -17
  78. package/docs/state-management.md +17 -17
  79. package/guidelines/Guidelines.md +17 -14
  80. package/llms-compact.txt +1 -1
  81. package/llms-full.txt +11553 -7133
  82. package/llms.txt +1 -1
  83. package/package.json +1 -1
  84. package/styles/xertica/base.css +90 -84
  85. package/templates/CLAUDE.md +16 -1
  86. package/templates/guidelines/Guidelines.md +42 -18
  87. package/templates/package.json +3 -3
  88. package/templates/src/app/components/AuthGuard.tsx +131 -82
  89. package/templates/src/features/auth/ui/AuthPageShell.tsx +32 -32
  90. package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +1 -3
  91. package/templates/src/features/auth/ui/ResetPasswordContent.tsx +6 -2
  92. package/templates/src/features/auth/ui/VerifyEmailContent.tsx +2 -6
  93. package/templates/src/features/home/data/mock.ts +41 -35
  94. package/templates/src/features/home/ui/HomeContent.tsx +62 -64
  95. package/templates/src/features/template/ui/CrudTemplate.tsx +1 -4
  96. package/templates/src/features/template/ui/LoginTemplate.tsx +1 -1
  97. package/templates/src/features/template/ui/TemplateContent.tsx +28 -20
  98. package/templates/src/locales/en/pages/templates.json +17 -17
  99. package/templates/src/locales/es/pages/templates.json +17 -17
  100. package/templates/src/locales/pt-BR/pages/templates.json +17 -17
  101. package/templates/src/pages/AssistantPage.tsx +26 -20
  102. package/templates/src/pages/HomePage.tsx +5 -1
  103. package/templates/src/shared/error-boundary.tsx +150 -154
  104. package/templates/src/shared/error-fallbacks.tsx +222 -226
  105. package/templates/vite.config.ts +12 -9
@@ -1,118 +1,121 @@
1
- import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
2
- import { useNavigate } from 'react-router-dom';
3
-
4
- // ─────────────────────────────────────────────────────────────────────────────
5
- // Types
6
- // ─────────────────────────────────────────────────────────────────────────────
7
-
8
- export interface AuthUser {
9
- email: string;
10
- name?: string;
11
- avatar?: string;
12
- }
13
-
14
- interface AuthContextValue {
15
- /** Currently authenticated user, or null when logged out */
16
- user: AuthUser | null;
17
- /** True while the initial session hydration from localStorage is pending */
18
- isLoading: boolean;
19
- /** Attempt login — returns true on success, false on invalid credentials */
20
- login: (email: string, password: string) => boolean;
21
- /** Clear session and redirect to /login */
22
- logout: () => void;
23
- }
24
-
25
- // ─────────────────────────────────────────────────────────────────────────────
26
- // Context
27
- // ─────────────────────────────────────────────────────────────────────────────
28
-
29
- const AuthContext = createContext<AuthContextValue | null>(null);
30
-
31
- const STORAGE_KEY = 'xertica_user';
32
- const AUTH_PATHS = ['/login', '/forgot-password', '/verify-email', '/reset-password'];
33
-
34
- // ─────────────────────────────────────────────────────────────────────────────
35
- // Provider
36
- // ─────────────────────────────────────────────────────────────────────────────
37
-
38
- /**
39
- * `AuthProvider` — manages authentication state for the devops app.
40
- *
41
- * Must be rendered **inside** `<BrowserRouter>` so that `useNavigate` is available.
42
- * Wrap your `<Routes>` tree with this provider to give all pages access to
43
- * `user`, `login`, and `logout` via `useAuth()` without prop-drilling.
44
- *
45
- * @example
46
- * ```tsx
47
- * <Router>
48
- * <AuthProvider>
49
- * <AppRoutes />
50
- * </AuthProvider>
51
- * </Router>
52
- * ```
53
- */
54
- export function AuthProvider({ children }: { children: React.ReactNode }) {
55
- const [user, setUser] = useState<AuthUser | null>(null);
56
- const [isLoading, setIsLoading] = useState(true);
57
- const navigate = useNavigate();
58
-
59
- // Hydrate session from localStorage on mount
60
- useEffect(() => {
61
- try {
62
- const raw = localStorage.getItem(STORAGE_KEY);
63
- if (raw) setUser(JSON.parse(raw));
64
- } catch {
65
- localStorage.removeItem(STORAGE_KEY);
66
- } finally {
67
- setIsLoading(false);
68
- }
69
- }, []);
70
-
71
- // Redirect authenticated users away from auth-only pages
72
- useEffect(() => {
73
- if (!isLoading && user && AUTH_PATHS.includes(window.location.pathname)) {
74
- navigate('/home', { replace: true });
75
- }
76
- }, [isLoading, user, navigate]);
77
-
78
- const login = useCallback((email: string, password: string): boolean => {
79
- if (!email.trim() || !password.trim()) return false;
80
- const userData: AuthUser = { email };
81
- setUser(userData);
82
- localStorage.setItem(STORAGE_KEY, JSON.stringify(userData));
83
- navigate('/home');
84
- return true;
85
- }, [navigate]);
86
-
87
- const logout = useCallback(() => {
88
- setUser(null);
89
- localStorage.removeItem(STORAGE_KEY);
90
- navigate('/login');
91
- }, [navigate]);
92
-
93
- return (
94
- <AuthContext.Provider value={{ user, isLoading, login, logout }}>
95
- {children}
96
- </AuthContext.Provider>
97
- );
98
- }
99
-
100
- // ─────────────────────────────────────────────────────────────────────────────
101
- // Hook
102
- // ─────────────────────────────────────────────────────────────────────────────
103
-
104
- /**
105
- * `useAuth` — consume authentication state anywhere inside `<AuthProvider>`.
106
- *
107
- * @throws if called outside `<AuthProvider>`
108
- *
109
- * @example
110
- * ```tsx
111
- * const { user, logout } = useAuth();
112
- * ```
113
- */
114
- export function useAuth(): AuthContextValue {
115
- const ctx = useContext(AuthContext);
116
- if (!ctx) throw new Error('useAuth must be used within <AuthProvider>');
117
- return ctx;
118
- }
1
+ import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // Types
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+
8
+ export interface AuthUser {
9
+ email: string;
10
+ name?: string;
11
+ avatar?: string;
12
+ }
13
+
14
+ interface AuthContextValue {
15
+ /** Currently authenticated user, or null when logged out */
16
+ user: AuthUser | null;
17
+ /** True while the initial session hydration from localStorage is pending */
18
+ isLoading: boolean;
19
+ /** Attempt login — returns true on success, false on invalid credentials */
20
+ login: (email: string, password: string) => boolean;
21
+ /** Clear session and redirect to /login */
22
+ logout: () => void;
23
+ }
24
+
25
+ // ─────────────────────────────────────────────────────────────────────────────
26
+ // Context
27
+ // ─────────────────────────────────────────────────────────────────────────────
28
+
29
+ const AuthContext = createContext<AuthContextValue | null>(null);
30
+
31
+ const STORAGE_KEY = 'xertica_user';
32
+ const AUTH_PATHS = ['/login', '/forgot-password', '/verify-email', '/reset-password'];
33
+
34
+ // ─────────────────────────────────────────────────────────────────────────────
35
+ // Provider
36
+ // ─────────────────────────────────────────────────────────────────────────────
37
+
38
+ /**
39
+ * `AuthProvider` — manages authentication state for the devops app.
40
+ *
41
+ * Must be rendered **inside** `<BrowserRouter>` so that `useNavigate` is available.
42
+ * Wrap your `<Routes>` tree with this provider to give all pages access to
43
+ * `user`, `login`, and `logout` via `useAuth()` without prop-drilling.
44
+ *
45
+ * @example
46
+ * ```tsx
47
+ * <Router>
48
+ * <AuthProvider>
49
+ * <AppRoutes />
50
+ * </AuthProvider>
51
+ * </Router>
52
+ * ```
53
+ */
54
+ export function AuthProvider({ children }: { children: React.ReactNode }) {
55
+ const [user, setUser] = useState<AuthUser | null>(null);
56
+ const [isLoading, setIsLoading] = useState(true);
57
+ const navigate = useNavigate();
58
+
59
+ // Hydrate session from localStorage on mount
60
+ useEffect(() => {
61
+ try {
62
+ const raw = localStorage.getItem(STORAGE_KEY);
63
+ if (raw) setUser(JSON.parse(raw));
64
+ } catch {
65
+ localStorage.removeItem(STORAGE_KEY);
66
+ } finally {
67
+ setIsLoading(false);
68
+ }
69
+ }, []);
70
+
71
+ // Redirect authenticated users away from auth-only pages
72
+ useEffect(() => {
73
+ if (!isLoading && user && AUTH_PATHS.includes(window.location.pathname)) {
74
+ navigate('/home', { replace: true });
75
+ }
76
+ }, [isLoading, user, navigate]);
77
+
78
+ const login = useCallback(
79
+ (email: string, password: string): boolean => {
80
+ if (!email.trim() || !password.trim()) return false;
81
+ const userData: AuthUser = { email };
82
+ setUser(userData);
83
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(userData));
84
+ navigate('/home');
85
+ return true;
86
+ },
87
+ [navigate]
88
+ );
89
+
90
+ const logout = useCallback(() => {
91
+ setUser(null);
92
+ localStorage.removeItem(STORAGE_KEY);
93
+ navigate('/login');
94
+ }, [navigate]);
95
+
96
+ return (
97
+ <AuthContext.Provider value={{ user, isLoading, login, logout }}>
98
+ {children}
99
+ </AuthContext.Provider>
100
+ );
101
+ }
102
+
103
+ // ─────────────────────────────────────────────────────────────────────────────
104
+ // Hook
105
+ // ─────────────────────────────────────────────────────────────────────────────
106
+
107
+ /**
108
+ * `useAuth` — consume authentication state anywhere inside `<AuthProvider>`.
109
+ *
110
+ * @throws if called outside `<AuthProvider>`
111
+ *
112
+ * @example
113
+ * ```tsx
114
+ * const { user, logout } = useAuth();
115
+ * ```
116
+ */
117
+ export function useAuth(): AuthContextValue {
118
+ const ctx = useContext(AuthContext);
119
+ if (!ctx) throw new Error('useAuth must be used within <AuthProvider>');
120
+ return ctx;
121
+ }
@@ -160,8 +160,7 @@ export function LanguageProvider({
160
160
  const resolvedDefault = defaultLanguage ?? languages[0].code;
161
161
 
162
162
  const [language, setLanguageState] = useState<Language>(() => {
163
- const saved =
164
- typeof window !== 'undefined' ? window.localStorage?.getItem(STORAGE_KEY) : null;
163
+ const saved = typeof window !== 'undefined' ? window.localStorage?.getItem(STORAGE_KEY) : null;
165
164
 
166
165
  // Direct match against configured languages
167
166
  if (saved && languages.some(l => l.code === saved)) {