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
@@ -403,11 +403,11 @@ O projeto já tem excelentes exemplos do padrão headless hook que devem servir
403
403
 
404
404
  ### Fase 1 — Correções Críticas (1-2 dias)
405
405
 
406
- | # | Tarefa | Arquivo(s) | Esforço |
407
- | --- | ------------------------------------------------------------- | ----------------- | ------- |
408
- | ~~1.1~~ | ~~Corrigir `ThemeToggle` para usar `useTheme()`~~ | ✅ Resolvido em v2.2.0 | — |
409
- | 1.2 | Criar `types.ts` compartilhado para o assistente | `types.ts` (novo) | 1h |
410
- | 1.3 | Atualizar imports em `AssistenteContext` e `use-assistant.ts` | 2 arquivos | 30min |
406
+ | # | Tarefa | Arquivo(s) | Esforço |
407
+ | ------- | ------------------------------------------------------------- | ---------------------- | ------- |
408
+ | ~~1.1~~ | ~~Corrigir `ThemeToggle` para usar `useTheme()`~~ | ✅ Resolvido em v2.2.0 | — |
409
+ | 1.2 | Criar `types.ts` compartilhado para o assistente | `types.ts` (novo) | 1h |
410
+ | 1.3 | Atualizar imports em `AssistenteContext` e `use-assistant.ts` | 2 arquivos | 30min |
411
411
 
412
412
  ### Fase 2 — Eliminação de Duplicações (2-3 dias)
413
413
 
@@ -12,14 +12,14 @@ The library underwent a **complete architectural modularization**. The flat `com
12
12
 
13
13
  ### Component Domains
14
14
 
15
- | Domain | Path | Contains |
16
- | ----------- | ----------------------- | ---------------------------------------------------------------- |
17
- | `ui` | `components/ui/[name]/` | Design system primitives (Button, Card, Calendar, Chart, etc.) |
18
- | `layout` | `components/layout/` | Sidebar, Header, SidebarPrimitive |
19
- | `blocks` | `components/blocks/` | High-level composed components built from `ui/` primitives |
20
- | `assistant` | `components/assistant/` | XerticaAssistant, MarkdownMessage, CodeBlock, etc. |
21
- | `brand` | `components/brand/` | XerticaLogo, ThemeToggle, LanguageSelector, XerticaProvider |
22
- | `pages` | `components/pages/` | LoginPage, HomePage, TemplatePage, etc. |
15
+ | Domain | Path | Contains |
16
+ | ----------- | ----------------------- | ------------------------------------------------------------------------------------------------------------ |
17
+ | `ui` | `components/ui/[name]/` | Design system primitives (Button, Card, Calendar, Chart, etc.) |
18
+ | `layout` | `components/layout/` | Sidebar, Header, SidebarPrimitive |
19
+ | `blocks` | `components/blocks/` | High-level composed components built from `ui/` primitives |
20
+ | `assistant` | `components/assistant/` | XerticaAssistant, MarkdownMessage, CodeBlock, etc. |
21
+ | `brand` | `components/brand/` | XerticaLogo, ThemeToggle, LanguageSelector, XerticaProvider |
22
+ | `pages` | `components/pages/` | LoginPage, HomePage, TemplatePage, etc. |
23
23
  | `shared` | `components/shared/` | utils.ts, use-mobile.ts, layout-constants.ts, navigation.ts, **error-boundary.tsx**, **error-fallbacks.tsx** |
24
24
 
25
25
  ### State Layer — `features/`
@@ -117,6 +117,7 @@ components/shared/
117
117
  ```
118
118
 
119
119
  Placement in `App.tsx`:
120
+
120
121
  ```
121
122
  AppErrorBoundary (outermost — before QueryClientProvider)
122
123
  └─ QueryClientProvider
@@ -139,6 +140,7 @@ contexts/
139
140
  ```
140
141
 
141
142
  `AuthProvider` must be rendered **inside** `<BrowserRouter>` (it uses `useNavigate`). It:
143
+
142
144
  - Hydrates session from `localStorage` on mount (`isLoading` flag prevents flash redirects)
143
145
  - Exposes `user`, `login(email, password) → boolean`, `logout()`
144
146
  - Redirects authenticated users away from auth-only pages automatically
@@ -158,7 +160,9 @@ const HomePage = React.lazy(() =>
158
160
  ### Provider Stack
159
161
 
160
162
  ```tsx
161
- <QueryClientProvider client={queryClient}> // ← TanStack React Query
163
+ <QueryClientProvider client={queryClient}>
164
+ {' '}
165
+ // ← TanStack React Query
162
166
  <ApiKeyProvider>
163
167
  <GoogleMapsLoaderProvider>
164
168
  <LanguageProvider>
@@ -167,7 +171,9 @@ const HomePage = React.lazy(() =>
167
171
  <AssistenteProvider>
168
172
  <LayoutProvider>
169
173
  <Router>
170
- <AuthProvider> // ← must be inside Router
174
+ <AuthProvider>
175
+ {' '}
176
+ // ← must be inside Router
171
177
  <Suspense fallback={null}>
172
178
  <AppRoutes />
173
179
  </Suspense>
@@ -362,14 +362,14 @@ import { Briefcase, Users, BarChart2 } from 'lucide-react';
362
362
 
363
363
  Every card pattern ships with a matching `*Skeleton` companion that mirrors its layout with pulsing placeholders. Use them while data is loading to avoid layout shift and provide visual feedback.
364
364
 
365
- | Card | Skeleton companion | Configurable props |
366
- | ------------------- | -------------------------- | ---------------------------------------- |
367
- | `ActivityCard` | `ActivityCardSkeleton` | `rows` (default `5`) |
368
- | `ProfileCard` | `ProfileCardSkeleton` | `showStats`, `showActions` |
369
- | `ProjectCard` | `ProjectCardSkeleton` | `memberCount` (default `3`) |
370
- | `NotificationCard` | `NotificationCardSkeleton` | `rows` (default `4`), `showViewAll` |
371
- | `QuickActionCard` | `QuickActionCardSkeleton` | — |
372
- | `FeatureCard` | `FeatureCardSkeleton` | `showAction` |
365
+ | Card | Skeleton companion | Configurable props |
366
+ | ------------------ | -------------------------- | ----------------------------------- |
367
+ | `ActivityCard` | `ActivityCardSkeleton` | `rows` (default `5`) |
368
+ | `ProfileCard` | `ProfileCardSkeleton` | `showStats`, `showActions` |
369
+ | `ProjectCard` | `ProjectCardSkeleton` | `memberCount` (default `3`) |
370
+ | `NotificationCard` | `NotificationCardSkeleton` | `rows` (default `4`), `showViewAll` |
371
+ | `QuickActionCard` | `QuickActionCardSkeleton` | — |
372
+ | `FeatureCard` | `FeatureCardSkeleton` | `showAction` |
373
373
 
374
374
  > A matching `StatsCardSkeleton` is also available from `xertica-ui` (lives in `ui/stats-card/`, with props `showIcon` and `showTrend`).
375
375
 
@@ -390,15 +390,17 @@ function ActivityFeed() {
390
390
  For grids, render one skeleton per expected card:
391
391
 
392
392
  ```tsx
393
- {isLoading ? (
394
- <>
395
- <FeatureCardSkeleton showAction />
396
- <FeatureCardSkeleton showAction />
397
- <FeatureCardSkeleton showAction />
398
- </>
399
- ) : (
400
- data.map(item => <FeatureCard key={item.id} {...item} />)
401
- )}
393
+ {
394
+ isLoading ? (
395
+ <>
396
+ <FeatureCardSkeleton showAction />
397
+ <FeatureCardSkeleton showAction />
398
+ <FeatureCardSkeleton showAction />
399
+ </>
400
+ ) : (
401
+ data.map(item => <FeatureCard key={item.id} {...item} />)
402
+ );
403
+ }
402
404
  ```
403
405
 
404
406
  ### Examples
@@ -1,191 +1,201 @@
1
- # ErrorBoundary — Xertica UI
2
-
3
- React Error Boundaries catch JavaScript errors in the component tree, log them, and render a fallback UI instead of crashing the application. Xertica UI ships a single reusable `ErrorBoundary` class with **three pre-configured wrapper variants** covering every granularity of protection.
4
-
5
- ---
6
-
7
- ## Import
8
-
9
- ```tsx
10
- // Pre-configured wrappers (recommended)
11
- import {
12
- AppErrorBoundary,
13
- PageErrorBoundary,
14
- SectionErrorBoundary,
15
- } from '@/components/shared/error-boundary';
16
-
17
- // Base class (for custom fallbacks)
18
- import { ErrorBoundary } from '@/components/shared/error-boundary';
19
- import type { FallbackProps } from '@/components/shared/error-boundary';
20
- ```
21
-
22
- ---
23
-
24
- ## The Three Variants
25
-
26
- | Variant | Fallback UI | Placement | Purpose |
27
- |---|---|---|---|
28
- | `AppErrorBoundary` | Full-screen, inline-styled | Outside `QueryClientProvider`, wraps entire `App` | Catches provider/context crashes; works even if Tailwind/CSS fails |
29
- | `PageErrorBoundary` | Half-height, Tailwind-styled | Wraps `<Routes>` / `<AuthGuard>` inside the router | Catches lazy-chunk load failures and page render errors; app chrome stays alive |
30
- | `SectionErrorBoundary` | Compact inline badge | Wraps individual sections (table, chart, assistant) | Catches isolated data-rendering errors; page layout stays intact |
31
-
32
- ---
33
-
34
- ## Provider Stack Placement
35
-
36
- ```tsx
37
- <AppErrorBoundary> {/* ← catches: provider init, context crashes */}
38
- <QueryClientProvider client={queryClient}>
39
- <XerticaProvider>
40
- <Router>
41
- <AuthProvider>
42
- <PageErrorBoundary> {/* ← catches: lazy chunk failures, route renders */}
43
- <Suspense fallback={null}>
44
- <Routes>
45
- <Route path="/home" element={
46
- <ProtectedRoute>
47
- <HomePage /> {/* ← page internals */}
48
- </ProtectedRoute>
49
- } />
50
- </Routes>
51
- </Suspense>
52
- </PageErrorBoundary>
53
- </AuthProvider>
54
- </Router>
55
- </XerticaProvider>
56
- </QueryClientProvider>
57
- </AppErrorBoundary>
58
- ```
59
-
60
- ---
61
-
62
- ## Props
63
-
64
- ### `AppErrorBoundary` / `PageErrorBoundary` / `SectionErrorBoundary`
65
-
66
- | Prop | Type | Default | Description |
67
- |---|---|---|---|
68
- | `children` | `ReactNode` | — | **Required.** Content to protect |
69
- | `onError` | `(error: Error, info: React.ErrorInfo) => void` | — | Called when an error is caught. Wire to Sentry, Datadog, etc. |
70
- | `resetKeys` | `unknown[]` | — | When any value in this array changes, the boundary auto-resets. Pass `[location.pathname]` to reset on navigation |
71
-
72
- ### Base `ErrorBoundary`
73
-
74
- Same props plus:
75
-
76
- | Prop | Type | Description |
77
- |---|---|---|
78
- | `fallback` | `React.ComponentType<FallbackProps>` | **Required.** The component to render when an error is caught |
79
-
80
- ### `FallbackProps` interface
81
-
82
- ```ts
83
- interface FallbackProps {
84
- error: Error; // The caught error
85
- reset: () => void; // Call to clear the error and re-render children
86
- }
87
- ```
88
-
89
- ---
90
-
91
- ## Usage Examples
92
-
93
- ### Protecting a data table section
94
-
95
- ```tsx
96
- import { SectionErrorBoundary } from '@/components/shared/error-boundary';
97
-
98
- function TeamSection() {
99
- return (
100
- <SectionErrorBoundary>
101
- <TeamDataTable />
102
- </SectionErrorBoundary>
103
- );
104
- }
105
- ```
106
-
107
- ### Resetting on route change
108
-
109
- ```tsx
110
- import { PageErrorBoundary } from '@/components/shared/error-boundary';
111
- import { useLocation } from 'react-router-dom';
112
-
113
- function AppRoutes() {
114
- const location = useLocation();
115
- return (
116
- <PageErrorBoundary resetKeys={[location.pathname]}>
117
- <Suspense fallback={null}>
118
- <Routes>{/* ... */}</Routes>
119
- </Suspense>
120
- </PageErrorBoundary>
121
- );
122
- }
123
- ```
124
-
125
- ### Logging to an error monitoring service
126
-
127
- ```tsx
128
- import { AppErrorBoundary } from '@/components/shared/error-boundary';
129
- import * as Sentry from '@sentry/react';
130
-
131
- <AppErrorBoundary onError={(error, info) => Sentry.captureException(error, { extra: info })}>
132
- <App />
133
- </AppErrorBoundary>
134
- ```
135
-
136
- ### Custom fallback with base `ErrorBoundary`
137
-
138
- ```tsx
139
- import { ErrorBoundary } from '@/components/shared/error-boundary';
140
- import type { FallbackProps } from '@/components/shared/error-boundary';
141
-
142
- function MyFallback({ error, reset }: FallbackProps) {
143
- return (
144
- <div role="alert">
145
- <p>Erro: {error.message}</p>
146
- <button onClick={reset}>Tentar novamente</button>
147
- </div>
148
- );
149
- }
150
-
151
- <ErrorBoundary fallback={MyFallback}>
152
- <MyComponent />
153
- </ErrorBoundary>
154
- ```
155
-
156
- ---
157
-
158
- ## Fallback UIs
159
-
160
- ### `AppErrorFallback`
161
- - Full-screen centered layout using **inline styles** (no Tailwind dependency)
162
- - Shows a destructive info icon, error title, and message
163
- - Two buttons: "Tentar novamente" (calls `reset()`) and "Ir para o início" (`window.location.assign('/')`)
164
- - In `DEV` mode: displays the full error stack trace in a `<pre>` block
165
-
166
- ### `PageErrorFallback`
167
- - Uses Tailwind / xertica-ui token classes
168
- - Centered within the page content area (sidebar and header remain visible)
169
- - Triangle warning icon + descriptive message
170
- - Same two action buttons
171
-
172
- ### `SectionErrorFallback`
173
- - Compact `rounded-lg` card with `destructive/30` border
174
- - Circle info icon + short message
175
- - Single "Tentar novamente" button
176
- - In `DEV` mode: shows `error.message` in a mono paragraph
177
-
178
- ---
179
-
180
- ## AI Rules
181
-
182
- > [!IMPORTANT]
183
- >
184
- > - **ALWAYS** place `<AppErrorBoundary>` as the **outermost** element in `App.tsx`, before `QueryClientProvider`. If the query client itself crashes, the app must still show something.
185
- > - **ALWAYS** place `<PageErrorBoundary>` around `<Routes>` / `<AuthGuard>`. This is the primary protection against lazy-chunk load failures (network errors, chunk not found).
186
- > - **USE** `<SectionErrorBoundary>` around any section that fetches data or renders complex content (tables, charts, the assistant panel, embedded maps). An error in one section must not crash the page.
187
- > - **DO NOT** place `<AppErrorBoundary>` inside `<Router>` — it must be outside the router so `AppErrorFallback` can use `window.location.assign` (not `useNavigate`).
188
- > - **DO NOT** use `try/catch` as a substitute for `ErrorBoundary` — try/catch does not catch render-time errors in React component trees. Both are needed for different error classes.
189
- > - **Pass `onError`** to the `AppErrorBoundary` in production to send errors to Sentry, Datadog, or another observability service.
190
- > - **Pass `resetKeys={[location.pathname]}`** to `PageErrorBoundary` if you want errors to auto-clear when the user navigates to a different route.
191
- > - Error boundaries do **not** catch: errors in event handlers (use try/catch there), async errors outside render (use React Query's `onError`), errors in server-side rendering, and errors thrown in the boundary itself.
1
+ # ErrorBoundary — Xertica UI
2
+
3
+ React Error Boundaries catch JavaScript errors in the component tree, log them, and render a fallback UI instead of crashing the application. Xertica UI ships a single reusable `ErrorBoundary` class with **three pre-configured wrapper variants** covering every granularity of protection.
4
+
5
+ ---
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ // Pre-configured wrappers (recommended)
11
+ import {
12
+ AppErrorBoundary,
13
+ PageErrorBoundary,
14
+ SectionErrorBoundary,
15
+ } from '@/components/shared/error-boundary';
16
+
17
+ // Base class (for custom fallbacks)
18
+ import { ErrorBoundary } from '@/components/shared/error-boundary';
19
+ import type { FallbackProps } from '@/components/shared/error-boundary';
20
+ ```
21
+
22
+ ---
23
+
24
+ ## The Three Variants
25
+
26
+ | Variant | Fallback UI | Placement | Purpose |
27
+ | ---------------------- | ---------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------- |
28
+ | `AppErrorBoundary` | Full-screen, inline-styled | Outside `QueryClientProvider`, wraps entire `App` | Catches provider/context crashes; works even if Tailwind/CSS fails |
29
+ | `PageErrorBoundary` | Half-height, Tailwind-styled | Wraps `<Routes>` / `<AuthGuard>` inside the router | Catches lazy-chunk load failures and page render errors; app chrome stays alive |
30
+ | `SectionErrorBoundary` | Compact inline badge | Wraps individual sections (table, chart, assistant) | Catches isolated data-rendering errors; page layout stays intact |
31
+
32
+ ---
33
+
34
+ ## Provider Stack Placement
35
+
36
+ ```tsx
37
+ <AppErrorBoundary>
38
+ {' '}
39
+ {/* ← catches: provider init, context crashes */}
40
+ <QueryClientProvider client={queryClient}>
41
+ <XerticaProvider>
42
+ <Router>
43
+ <AuthProvider>
44
+ <PageErrorBoundary>
45
+ {' '}
46
+ {/* ← catches: lazy chunk failures, route renders */}
47
+ <Suspense fallback={null}>
48
+ <Routes>
49
+ <Route
50
+ path="/home"
51
+ element={
52
+ <ProtectedRoute>
53
+ <HomePage /> {/* ← page internals */}
54
+ </ProtectedRoute>
55
+ }
56
+ />
57
+ </Routes>
58
+ </Suspense>
59
+ </PageErrorBoundary>
60
+ </AuthProvider>
61
+ </Router>
62
+ </XerticaProvider>
63
+ </QueryClientProvider>
64
+ </AppErrorBoundary>
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Props
70
+
71
+ ### `AppErrorBoundary` / `PageErrorBoundary` / `SectionErrorBoundary`
72
+
73
+ | Prop | Type | Default | Description |
74
+ | ----------- | ----------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------- |
75
+ | `children` | `ReactNode` | — | **Required.** Content to protect |
76
+ | `onError` | `(error: Error, info: React.ErrorInfo) => void` | — | Called when an error is caught. Wire to Sentry, Datadog, etc. |
77
+ | `resetKeys` | `unknown[]` | — | When any value in this array changes, the boundary auto-resets. Pass `[location.pathname]` to reset on navigation |
78
+
79
+ ### Base `ErrorBoundary`
80
+
81
+ Same props plus:
82
+
83
+ | Prop | Type | Description |
84
+ | ---------- | ------------------------------------ | ------------------------------------------------------------- |
85
+ | `fallback` | `React.ComponentType<FallbackProps>` | **Required.** The component to render when an error is caught |
86
+
87
+ ### `FallbackProps` interface
88
+
89
+ ```ts
90
+ interface FallbackProps {
91
+ error: Error; // The caught error
92
+ reset: () => void; // Call to clear the error and re-render children
93
+ }
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Usage Examples
99
+
100
+ ### Protecting a data table section
101
+
102
+ ```tsx
103
+ import { SectionErrorBoundary } from '@/components/shared/error-boundary';
104
+
105
+ function TeamSection() {
106
+ return (
107
+ <SectionErrorBoundary>
108
+ <TeamDataTable />
109
+ </SectionErrorBoundary>
110
+ );
111
+ }
112
+ ```
113
+
114
+ ### Resetting on route change
115
+
116
+ ```tsx
117
+ import { PageErrorBoundary } from '@/components/shared/error-boundary';
118
+ import { useLocation } from 'react-router-dom';
119
+
120
+ function AppRoutes() {
121
+ const location = useLocation();
122
+ return (
123
+ <PageErrorBoundary resetKeys={[location.pathname]}>
124
+ <Suspense fallback={null}>
125
+ <Routes>{/* ... */}</Routes>
126
+ </Suspense>
127
+ </PageErrorBoundary>
128
+ );
129
+ }
130
+ ```
131
+
132
+ ### Logging to an error monitoring service
133
+
134
+ ```tsx
135
+ import { AppErrorBoundary } from '@/components/shared/error-boundary';
136
+ import * as Sentry from '@sentry/react';
137
+
138
+ <AppErrorBoundary onError={(error, info) => Sentry.captureException(error, { extra: info })}>
139
+ <App />
140
+ </AppErrorBoundary>;
141
+ ```
142
+
143
+ ### Custom fallback with base `ErrorBoundary`
144
+
145
+ ```tsx
146
+ import { ErrorBoundary } from '@/components/shared/error-boundary';
147
+ import type { FallbackProps } from '@/components/shared/error-boundary';
148
+
149
+ function MyFallback({ error, reset }: FallbackProps) {
150
+ return (
151
+ <div role="alert">
152
+ <p>Erro: {error.message}</p>
153
+ <button onClick={reset}>Tentar novamente</button>
154
+ </div>
155
+ );
156
+ }
157
+
158
+ <ErrorBoundary fallback={MyFallback}>
159
+ <MyComponent />
160
+ </ErrorBoundary>;
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Fallback UIs
166
+
167
+ ### `AppErrorFallback`
168
+
169
+ - Full-screen centered layout using **inline styles** (no Tailwind dependency)
170
+ - Shows a destructive info icon, error title, and message
171
+ - Two buttons: "Tentar novamente" (calls `reset()`) and "Ir para o início" (`window.location.assign('/')`)
172
+ - In `DEV` mode: displays the full error stack trace in a `<pre>` block
173
+
174
+ ### `PageErrorFallback`
175
+
176
+ - Uses Tailwind / xertica-ui token classes
177
+ - Centered within the page content area (sidebar and header remain visible)
178
+ - Triangle warning icon + descriptive message
179
+ - Same two action buttons
180
+
181
+ ### `SectionErrorFallback`
182
+
183
+ - Compact `rounded-lg` card with `destructive/30` border
184
+ - Circle info icon + short message
185
+ - Single "Tentar novamente" button
186
+ - In `DEV` mode: shows `error.message` in a mono paragraph
187
+
188
+ ---
189
+
190
+ ## AI Rules
191
+
192
+ > [!IMPORTANT]
193
+ >
194
+ > - **ALWAYS** place `<AppErrorBoundary>` as the **outermost** element in `App.tsx`, before `QueryClientProvider`. If the query client itself crashes, the app must still show something.
195
+ > - **ALWAYS** place `<PageErrorBoundary>` around `<Routes>` / `<AuthGuard>`. This is the primary protection against lazy-chunk load failures (network errors, chunk not found).
196
+ > - **USE** `<SectionErrorBoundary>` around any section that fetches data or renders complex content (tables, charts, the assistant panel, embedded maps). An error in one section must not crash the page.
197
+ > - **DO NOT** place `<AppErrorBoundary>` inside `<Router>` — it must be outside the router so `AppErrorFallback` can use `window.location.assign` (not `useNavigate`).
198
+ > - **DO NOT** use `try/catch` as a substitute for `ErrorBoundary` — try/catch does not catch render-time errors in React component trees. Both are needed for different error classes.
199
+ > - **Pass `onError`** to the `AppErrorBoundary` in production to send errors to Sentry, Datadog, or another observability service.
200
+ > - **Pass `resetKeys={[location.pathname]}`** to `PageErrorBoundary` if you want errors to auto-clear when the user navigates to a different route.
201
+ > - Error boundaries do **not** catch: errors in event handlers (use try/catch there), async errors outside render (use React Query's `onError`), errors in server-side rendering, and errors thrown in the boundary itself.
@@ -65,12 +65,12 @@ Accesses and controls the current UI language preference, plus the list of avail
65
65
 
66
66
  ### Return Value
67
67
 
68
- | Property | Type | Description |
69
- | -------------------- | ----------------------------- | ------------------------------------------------------------------------------------ |
70
- | `language` | `string` | Current language code (e.g. `'pt-BR'`, `'en'`, `'fr'`) |
68
+ | Property | Type | Description |
69
+ | -------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------- |
70
+ | `language` | `string` | Current language code (e.g. `'pt-BR'`, `'en'`, `'fr'`) |
71
71
  | `setLanguage` | `(language: Language) => void` | Changes the language: persists to localStorage, calls `i18n.changeLanguage`, and invalidates React Query cache |
72
- | `availableLanguages` | `LanguageDefinition[]` | The full list of languages configured via `availableLanguages` prop on `<XerticaProvider>` |
73
- | `isMonolingual` | `boolean` | `true` when only one language is configured. The `LanguageSelector` uses this to auto-hide |
72
+ | `availableLanguages` | `LanguageDefinition[]` | The full list of languages configured via `availableLanguages` prop on `<XerticaProvider>` |
73
+ | `isMonolingual` | `boolean` | `true` when only one language is configured. The `LanguageSelector` uses this to auto-hide |
74
74
 
75
75
  ### Usage
76
76
 
@@ -83,7 +83,9 @@ function LanguageDisplay() {
83
83
  return (
84
84
  <select value={language} onChange={e => setLanguage(e.target.value)}>
85
85
  {availableLanguages.map(lang => (
86
- <option key={lang.code} value={lang.code}>{lang.label}</option>
86
+ <option key={lang.code} value={lang.code}>
87
+ {lang.label}
88
+ </option>
87
89
  ))}
88
90
  </select>
89
91
  );
@@ -139,13 +141,13 @@ Accesses the global AI Assistant context — conversation list, current conversa
139
141
 
140
142
  ### Return Value
141
143
 
142
- | Property | Type | Description |
143
- | ------------------ | --------------------------------- | ---------------------------------------------- |
144
- | `conversas` | `Conversation[]` | List of all conversations |
145
- | `conversaAtual` | `string \| null` | ID of the currently active conversation |
146
- | `setConversaAtual` | `(id: string \| null) => void` | Selects a conversation |
147
- | `sugestoes` | `Suggestion[]` | Quick-reply suggestions for the welcome screen |
148
- | `setSugestoes` | `(s: Suggestion[]) => void` | Replaces the suggestion list |
144
+ | Property | Type | Description |
145
+ | ------------------ | ------------------------------ | ---------------------------------------------- |
146
+ | `conversas` | `Conversation[]` | List of all conversations |
147
+ | `conversaAtual` | `string \| null` | ID of the currently active conversation |
148
+ | `setConversaAtual` | `(id: string \| null) => void` | Selects a conversation |
149
+ | `sugestoes` | `Suggestion[]` | Quick-reply suggestions for the welcome screen |
150
+ | `setSugestoes` | `(s: Suggestion[]) => void` | Replaces the suggestion list |
149
151
 
150
152
  ### Usage
151
153