forlogic-core 2.2.5 → 2.2.7

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 (69) hide show
  1. package/.note/memory/features/import/attachment-idempotency-registry.md +8 -8
  2. package/.note/memory/features/import/attachment-strategy.md +30 -30
  3. package/.note/memory/patterns/admin-i18n-policy.md +20 -20
  4. package/.note/memory/patterns/alias-url-resolution.md +69 -69
  5. package/.note/memory/patterns/doc-sync-rule.md +35 -35
  6. package/.note/memory/patterns/documentation-standard.md +17 -17
  7. package/.note/memory/patterns/dynamic-supabase-config.md +4 -4
  8. package/.note/memory/patterns/environment-detection-logic.md +35 -35
  9. package/.note/memory/patterns/i18n-architecture.md +3 -3
  10. package/README.md +120 -120
  11. package/dist/README.md +1079 -0
  12. package/dist/bin/bootstrap.js +40 -0
  13. package/dist/bin/pull-docs.js +186 -0
  14. package/dist/components/ui/color-picker.d.ts +2 -0
  15. package/dist/components/ui/combo-tree.d.ts +3 -1
  16. package/dist/components/ui/combobox.d.ts +2 -1
  17. package/dist/components/ui/select.d.ts +9 -2
  18. package/dist/docs/KNOWLEDGE.md +109 -0
  19. package/dist/index.css +1 -1
  20. package/dist/index.css.map +1 -1
  21. package/dist/index.esm.js +1 -1
  22. package/dist/index.js +1 -1
  23. package/docs/PUBLISH.md +168 -168
  24. package/docs/STORAGE_BUCKETS.md +456 -456
  25. package/docs/SUPABASE_SECRETS.md +122 -122
  26. package/docs/WORKSPACE_KNOWLEDGE.md +154 -154
  27. package/docs/design-system/buttons-actions.md +130 -130
  28. package/docs/design-system/charts-dashboards.md +301 -340
  29. package/docs/design-system/crud.md +114 -174
  30. package/docs/design-system/data-display.md +106 -106
  31. package/docs/design-system/dialogs.md +212 -212
  32. package/docs/design-system/domain.md +329 -319
  33. package/docs/design-system/examples.md +275 -275
  34. package/docs/design-system/foundation.md +1 -1
  35. package/docs/design-system/inputs.md +137 -132
  36. package/docs/design-system/layout.md +154 -202
  37. package/docs/design-system/navigation.md +331 -272
  38. package/docs/design-system/notifications-feedback.md +34 -34
  39. package/docs/design-system/patterns/README.md +53 -53
  40. package/docs/design-system/patterns/action-button.md +22 -22
  41. package/docs/design-system/patterns/alertdialog-deletion.md +46 -46
  42. package/docs/design-system/patterns/baseform-custom-fields.md +59 -59
  43. package/docs/design-system/patterns/baseform-usage.md +42 -42
  44. package/docs/design-system/patterns/body-content-scroll.md +56 -56
  45. package/docs/design-system/patterns/combo-tree.md +23 -23
  46. package/docs/design-system/patterns/components-registry.md +17 -17
  47. package/docs/design-system/patterns/core-providers.md +41 -41
  48. package/docs/design-system/patterns/crud-bulk-actions.md +12 -12
  49. package/docs/design-system/patterns/crud-config-props.md +16 -16
  50. package/docs/design-system/patterns/crud-defaults.md +17 -17
  51. package/docs/design-system/patterns/crud-toolbar.md +28 -28
  52. package/docs/design-system/patterns/delete-confirmation.md +40 -40
  53. package/docs/design-system/patterns/dialog-body-scroll.md +26 -26
  54. package/docs/design-system/patterns/dialog-structure.md +32 -32
  55. package/docs/design-system/patterns/dialog-variants.md +41 -41
  56. package/docs/design-system/patterns/feature-flags.md +81 -81
  57. package/docs/design-system/patterns/header-metadata.md +57 -57
  58. package/docs/design-system/patterns/i18n-setup.md +117 -117
  59. package/docs/design-system/patterns/pagination.md +27 -27
  60. package/docs/design-system/patterns/single-scroll.md +39 -39
  61. package/docs/design-system/patterns/vite-tailwind-setup.md +49 -49
  62. package/docs/design-system/platform.md +18 -18
  63. package/docs/design-system/selectors.md +287 -258
  64. package/docs/design-system/tables-grids.md +38 -95
  65. package/package.json +152 -152
  66. package/dist/assets/docs-BEwTKYu3.css +0 -1
  67. package/dist/assets/docs-Bgpz6ETN.js +0 -10752
  68. package/dist/assets/index-SqMwTzMJ.js +0 -97
  69. package/dist/index.html +0 -34
@@ -1,81 +1,81 @@
1
- # Padrão: Feature Flags (Variáveis de Ambiente)
2
-
3
- ## Variáveis disponíveis
4
-
5
- | Variável | Descrição | Padrão |
6
- |----------|-----------|--------|
7
- | `VITE_SHOW_USER_PREFERENCES` | Exibe "Preferências" no menu do usuário (idioma, timezone, formato de data) | Não exibe |
8
- | `VITE_I18N_DEBUG_MODE` | Modo debug de i18n (mostra chaves ao invés de traduções) | `"false"` |
9
- | `VITE_IS_QUALIEX` | Usa logos Qualiex ao invés de Forlogic | `"false"` |
10
- | `VITE_SHOW_EDIT_PROFILE` | Exibe "Editar Perfil" no menu do usuário (foto e idioma) | Não exibe |
11
- | `VITE_WIKI_URL` | Exibe botão "Wiki" no header da aplicação. O valor é a URL que será aberta ao clicar | Não exibe |
12
- | `VITE_SHOW_ADMIN_REPORTS` | Exibe relatórios administrativos | `"false"` |
13
- | `VITE_SUPABASE_PK_OVERRIDE` | **Obrigatória.** Publishable key correta do Supabase. Ver [seção abaixo](#vite_supabase_pk_override). | — |
14
-
15
- ## Uso
16
-
17
- ```env
18
- VITE_SHOW_USER_PREFERENCES=true
19
- VITE_I18N_DEBUG_MODE=false
20
- VITE_IS_QUALIEX=true
21
- VITE_WIKI_URL=https://wiki.example.com
22
- VITE_SHOW_ADMIN_REPORTS=false
23
- VITE_SUPABASE_PK_OVERRIDE="sb_publishable_w-TKU0hE4bjM_uOgt3fK1g_ewrXKJ8J"
24
- ```
25
-
26
- Variáveis Vite precisam do prefixo `VITE_` para serem expostas ao cliente.
27
-
28
- ---
29
-
30
- ## `VITE_SUPABASE_PK_OVERRIDE`
31
-
32
- ### Problema
33
-
34
- O Supabase desativou as legacy API keys (formato JWT `eyJhbGci...`). A integração Supabase do Lovable **sobrescreve automaticamente** `VITE_SUPABASE_PUBLISHABLE_KEY` no `.env` com a legacy anon key a cada prompt, causando `401 Unauthorized` em todas as requests.
35
-
36
- ### Solução
37
-
38
- A lib `forlogic-core` implementa um mecanismo de override:
39
-
40
- 1. Se `VITE_SUPABASE_PK_OVERRIDE` existir no `.env` → a lib usa essa key (ignora `VITE_SUPABASE_PUBLISHABLE_KEY`)
41
- 2. Se não existir → usa `VITE_SUPABASE_PUBLISHABLE_KEY` normalmente
42
- 3. Se a key ativa for uma JWT legada → exibe banner vermelho no preview (DEV) + erro no console
43
-
44
- O Lovable **nunca toca** em `VITE_SUPABASE_PK_OVERRIDE` porque só auto-popula estas 3 variáveis:
45
- - `VITE_SUPABASE_URL`
46
- - `VITE_SUPABASE_PUBLISHABLE_KEY`
47
- - `VITE_SUPABASE_PROJECT_ID`
48
-
49
- ### Configuração obrigatória
50
-
51
- **Todo projeto consumidor** que aponta para o Supabase `ccjfvpnndclajkleyqkc` deve adicionar no `.env`:
52
-
53
- ```env
54
- VITE_SUPABASE_PK_OVERRIDE="sb_publishable_w-TKU0hE4bjM_uOgt3fK1g_ewrXKJ8J"
55
- ```
56
-
57
- ### Como funciona internamente
58
-
59
- ```text
60
- VITE_SUPABASE_PK_OVERRIDE existe?
61
- ├─ SIM → usar ela (ignora VITE_SUPABASE_PUBLISHABLE_KEY)
62
- │ console.info: "✅ Usando VITE_SUPABASE_PK_OVERRIDE..."
63
- └─ NÃO → usar VITE_SUPABASE_PUBLISHABLE_KEY
64
- ├─ Formato sb_publishable_* → OK
65
- └─ Formato eyJ* (JWT legada) → ⛔ Erro
66
- ├─ console.error com diagnóstico completo
67
- └─ Banner vermelho fixo no topo (apenas DEV)
68
- ```
69
-
70
- ### Arquivos relevantes na lib
71
-
72
- | Arquivo | Responsabilidade |
73
- |---------|-----------------|
74
- | `lib/supabase/legacyKeyGuard.ts` | `resolvePublishableKey()`, `isLegacyAnonKey()`, `warnIfLegacyKey()` |
75
- | `lib/supabase/SupabaseSingleton.ts` | Usa `resolvePublishableKey()` para a key do client |
76
- | `lib/supabase/publicClient.ts` | Idem para o client público |
77
- | `lib/providers/CoreProviders.tsx` | Renderiza `LegacyKeyBanner` em DEV |
78
-
79
- ### ⚠️ Nunca remova esta variável do `.env`
80
-
81
- Mesmo que o Lovable corrija a integração no futuro, a presença do override não causa nenhum efeito colateral negativo — é um fallback seguro.
1
+ # Padrão: Feature Flags (Variáveis de Ambiente)
2
+
3
+ ## Variáveis disponíveis
4
+
5
+ | Variável | Descrição | Padrão |
6
+ |----------|-----------|--------|
7
+ | `VITE_SHOW_USER_PREFERENCES` | Exibe "Preferências" no menu do usuário (idioma, timezone, formato de data) | Não exibe |
8
+ | `VITE_I18N_DEBUG_MODE` | Modo debug de i18n (mostra chaves ao invés de traduções) | `"false"` |
9
+ | `VITE_IS_QUALIEX` | Usa logos Qualiex ao invés de Forlogic | `"false"` |
10
+ | `VITE_SHOW_EDIT_PROFILE` | Exibe "Editar Perfil" no menu do usuário (foto e idioma) | Não exibe |
11
+ | `VITE_WIKI_URL` | Exibe botão "Wiki" no header da aplicação. O valor é a URL que será aberta ao clicar | Não exibe |
12
+ | `VITE_SHOW_ADMIN_REPORTS` | Exibe relatórios administrativos | `"false"` |
13
+ | `VITE_SUPABASE_PK_OVERRIDE` | **Obrigatória.** Publishable key correta do Supabase. Ver [seção abaixo](#vite_supabase_pk_override). | — |
14
+
15
+ ## Uso
16
+
17
+ ```env
18
+ VITE_SHOW_USER_PREFERENCES=true
19
+ VITE_I18N_DEBUG_MODE=false
20
+ VITE_IS_QUALIEX=true
21
+ VITE_WIKI_URL=https://wiki.example.com
22
+ VITE_SHOW_ADMIN_REPORTS=false
23
+ VITE_SUPABASE_PK_OVERRIDE="sb_publishable_w-TKU0hE4bjM_uOgt3fK1g_ewrXKJ8J"
24
+ ```
25
+
26
+ Variáveis Vite precisam do prefixo `VITE_` para serem expostas ao cliente.
27
+
28
+ ---
29
+
30
+ ## `VITE_SUPABASE_PK_OVERRIDE`
31
+
32
+ ### Problema
33
+
34
+ O Supabase desativou as legacy API keys (formato JWT `eyJhbGci...`). A integração Supabase do Lovable **sobrescreve automaticamente** `VITE_SUPABASE_PUBLISHABLE_KEY` no `.env` com a legacy anon key a cada prompt, causando `401 Unauthorized` em todas as requests.
35
+
36
+ ### Solução
37
+
38
+ A lib `forlogic-core` implementa um mecanismo de override:
39
+
40
+ 1. Se `VITE_SUPABASE_PK_OVERRIDE` existir no `.env` → a lib usa essa key (ignora `VITE_SUPABASE_PUBLISHABLE_KEY`)
41
+ 2. Se não existir → usa `VITE_SUPABASE_PUBLISHABLE_KEY` normalmente
42
+ 3. Se a key ativa for uma JWT legada → exibe banner vermelho no preview (DEV) + erro no console
43
+
44
+ O Lovable **nunca toca** em `VITE_SUPABASE_PK_OVERRIDE` porque só auto-popula estas 3 variáveis:
45
+ - `VITE_SUPABASE_URL`
46
+ - `VITE_SUPABASE_PUBLISHABLE_KEY`
47
+ - `VITE_SUPABASE_PROJECT_ID`
48
+
49
+ ### Configuração obrigatória
50
+
51
+ **Todo projeto consumidor** que aponta para o Supabase `ccjfvpnndclajkleyqkc` deve adicionar no `.env`:
52
+
53
+ ```env
54
+ VITE_SUPABASE_PK_OVERRIDE="sb_publishable_w-TKU0hE4bjM_uOgt3fK1g_ewrXKJ8J"
55
+ ```
56
+
57
+ ### Como funciona internamente
58
+
59
+ ```text
60
+ VITE_SUPABASE_PK_OVERRIDE existe?
61
+ ├─ SIM → usar ela (ignora VITE_SUPABASE_PUBLISHABLE_KEY)
62
+ │ console.info: "✅ Usando VITE_SUPABASE_PK_OVERRIDE..."
63
+ └─ NÃO → usar VITE_SUPABASE_PUBLISHABLE_KEY
64
+ ├─ Formato sb_publishable_* → OK
65
+ └─ Formato eyJ* (JWT legada) → ⛔ Erro
66
+ ├─ console.error com diagnóstico completo
67
+ └─ Banner vermelho fixo no topo (apenas DEV)
68
+ ```
69
+
70
+ ### Arquivos relevantes na lib
71
+
72
+ | Arquivo | Responsabilidade |
73
+ |---------|-----------------|
74
+ | `lib/supabase/legacyKeyGuard.ts` | `resolvePublishableKey()`, `isLegacyAnonKey()`, `warnIfLegacyKey()` |
75
+ | `lib/supabase/SupabaseSingleton.ts` | Usa `resolvePublishableKey()` para a key do client |
76
+ | `lib/supabase/publicClient.ts` | Idem para o client público |
77
+ | `lib/providers/CoreProviders.tsx` | Renderiza `LegacyKeyBanner` em DEV |
78
+
79
+ ### ⚠️ Nunca remova esta variável do `.env`
80
+
81
+ Mesmo que o Lovable corrija a integração no futuro, a presença do override não causa nenhum efeito colateral negativo — é um fallback seguro.
@@ -1,57 +1,57 @@
1
- # Padrão: Título, Subtítulo e Breadcrumbs via Header (usePageMetadata)
2
-
3
- ## Regra
4
-
5
- **O padrão da aplicação é exibir título, subtítulo e breadcrumbs no header** usando `usePageMetadata()`.
6
-
7
- - **NÃO** usar `BodyContent` ou `ContentContainer` com título/subtítulo internos por padrão.
8
- - Breadcrumbs, títulos e subtítulos internos ao conteúdo são **exceções** e devem ser usados **somente quando explicitamente solicitados**.
9
-
10
- ## Uso Padrão
11
-
12
- ```tsx
13
- import { usePageMetadata } from 'forlogic-core';
14
-
15
- export function MinhaPage() {
16
- usePageMetadata({ title: 'Título', subtitle: 'Subtítulo descritivo' });
17
-
18
- return (
19
- <div className="flex flex-col h-full p-4 gap-4">
20
- {/* conteúdo direto, sem BodyContent/ContentContainer */}
21
- </div>
22
- );
23
- }
24
- ```
25
-
26
- ## Com Breadcrumbs
27
-
28
- ```tsx
29
- usePageMetadata({
30
- title: 'Editar Usuário',
31
- subtitle: 'Atualize os dados cadastrais',
32
- breadcrumbs: [
33
- { label: 'Usuários', href: '/users' },
34
- { label: 'João Silva' }
35
- ]
36
- });
37
- ```
38
-
39
- ## Subtitle com ReactNode
40
-
41
- ```tsx
42
- usePageMetadata({
43
- title: 'Detalhes',
44
- subtitle: <span>Veja a <Link to="/docs">documentação</Link></span>
45
- });
46
- ```
47
-
48
- ## ❌ Evitar (exceto quando pedido)
49
-
50
- ```tsx
51
- // NÃO fazer por padrão:
52
- <BodyContent breadcrumbs={[{ label: 'Página' }]}>
53
- <ContentContainer title="Título" subtitle="Subtítulo">
54
- ...
55
- </ContentContainer>
56
- </BodyContent>
57
- ```
1
+ # Padrão: Título, Subtítulo e Breadcrumbs via Header (usePageMetadata)
2
+
3
+ ## Regra
4
+
5
+ **O padrão da aplicação é exibir título, subtítulo e breadcrumbs no header** usando `usePageMetadata()`.
6
+
7
+ - **NÃO** usar `BodyContent` ou `ContentContainer` com título/subtítulo internos por padrão.
8
+ - Breadcrumbs, títulos e subtítulos internos ao conteúdo são **exceções** e devem ser usados **somente quando explicitamente solicitados**.
9
+
10
+ ## Uso Padrão
11
+
12
+ ```tsx
13
+ import { usePageMetadata } from 'forlogic-core';
14
+
15
+ export function MinhaPage() {
16
+ usePageMetadata({ title: 'Título', subtitle: 'Subtítulo descritivo' });
17
+
18
+ return (
19
+ <div className="flex flex-col h-full p-4 gap-4">
20
+ {/* conteúdo direto, sem BodyContent/ContentContainer */}
21
+ </div>
22
+ );
23
+ }
24
+ ```
25
+
26
+ ## Com Breadcrumbs
27
+
28
+ ```tsx
29
+ usePageMetadata({
30
+ title: 'Editar Usuário',
31
+ subtitle: 'Atualize os dados cadastrais',
32
+ breadcrumbs: [
33
+ { label: 'Usuários', href: '/users' },
34
+ { label: 'João Silva' }
35
+ ]
36
+ });
37
+ ```
38
+
39
+ ## Subtitle com ReactNode
40
+
41
+ ```tsx
42
+ usePageMetadata({
43
+ title: 'Detalhes',
44
+ subtitle: <span>Veja a <Link to="/docs">documentação</Link></span>
45
+ });
46
+ ```
47
+
48
+ ## ❌ Evitar (exceto quando pedido)
49
+
50
+ ```tsx
51
+ // NÃO fazer por padrão:
52
+ <BodyContent breadcrumbs={[{ label: 'Página' }]}>
53
+ <ContentContainer title="Título" subtitle="Subtítulo">
54
+ ...
55
+ </ContentContainer>
56
+ </BodyContent>
57
+ ```
@@ -1,117 +1,117 @@
1
- # Padrão: Setup de Traduções (i18n)
2
-
3
- ## Arquitetura de namespaces
4
-
5
- - `core` — traduções base da lib (save, cancel, delete, etc.)
6
- - `app` — traduções do projeto consumidor (injetadas via `CoreProviders`)
7
- - Resolução: `app` → `core` → fallback `pt-BR`
8
-
9
- ## Setup em projetos consumidores
10
-
11
- ### Projeto simples (poucas chaves)
12
-
13
- 1. Criar JSON flat em `src/i18n/pt-BR.json`: `{ "key": "value" }` (sem nesting)
14
- 2. Passar para CoreProviders:
15
-
16
- ```tsx
17
- <CoreProviders appTranslations={{ 'pt-BR': ptBR, 'en-US': enUS }}>
18
- ```
19
-
20
- 3. Usar `useTranslation` de `forlogic-core` (nunca de `react-i18next`)
21
-
22
- ### Projeto modular (múltiplas features)
23
-
24
- Para módulos com muitas chaves, dividir traduções por feature:
25
-
26
- ```text
27
- src/i18n/
28
- ├── pt-BR/
29
- │ ├── common.json ← chaves gerais do módulo
30
- │ ├── matrices.json ← feature: matrizes
31
- │ ├── requirements.json ← feature: requisitos
32
- │ └── reports.json ← feature: relatórios
33
- ├── en-US/
34
- │ ├── common.json
35
- │ ├── matrices.json
36
- │ ├── requirements.json
37
- │ └── reports.json
38
- └── index.ts ← merge automático
39
- ```
40
-
41
- #### Arquivo `src/i18n/index.ts`
42
-
43
- ```ts
44
- import { mergeTranslationFiles } from 'forlogic-core/i18n';
45
-
46
- import ptCommon from './pt-BR/common.json';
47
- import ptMatrices from './pt-BR/matrices.json';
48
- import ptRequirements from './pt-BR/requirements.json';
49
- import ptReports from './pt-BR/reports.json';
50
-
51
- import enCommon from './en-US/common.json';
52
- import enMatrices from './en-US/matrices.json';
53
- import enRequirements from './en-US/requirements.json';
54
- import enReports from './en-US/reports.json';
55
-
56
- export const appTranslations = {
57
- 'pt-BR': mergeTranslationFiles(ptCommon, ptMatrices, ptRequirements, ptReports),
58
- 'en-US': mergeTranslationFiles(enCommon, enMatrices, enRequirements, enReports),
59
- };
60
- ```
61
-
62
- #### Uso no App
63
-
64
- ```tsx
65
- import { CoreProviders } from 'forlogic-core';
66
- import { appTranslations } from './i18n';
67
-
68
- function App() {
69
- return (
70
- <CoreProviders appTranslations={appTranslations}>
71
- <BrowserRouter><Routes /></BrowserRouter>
72
- </CoreProviders>
73
- );
74
- }
75
- ```
76
-
77
- ## Regras dos JSONs
78
-
79
- - Formato **flat** (sem nesting): `{ "key": "value" }`
80
- - Chaves duplicadas entre arquivos: o último spread vence (common → features)
81
- - Chaves do `app` sobrescrevem chaves do `core` com mesmo nome
82
-
83
- ## Resolução de chaves
84
-
85
- ```
86
- t('save') → app: não encontra → core: "Salvar"
87
- t('objective') → app: "Objetivo"
88
- t('save') com override no app → app: "Gravar" (sobrescreve core)
89
- ```
90
-
91
- ## Helper `mergeTranslationFiles`
92
-
93
- Utilitário exportado pela lib para facilitar o merge:
94
-
95
- ```ts
96
- import { mergeTranslationFiles } from 'forlogic-core/i18n';
97
-
98
- const ptBR = mergeTranslationFiles(common, matrices, requirements);
99
- // Equivalente a: { ...common, ...matrices, ...requirements }
100
- ```
101
-
102
- ## Debug
103
-
104
- ```ts
105
- import { i18n } from 'forlogic-core';
106
- console.log('Resources:', i18n.store.data);
107
- ```
108
-
109
- ## Troubleshooting
110
-
111
- | Causa | Solução |
112
- |-------|---------|
113
- | Chaves aparecem ao invés de traduções | Instalar peer deps `i18next` e `react-i18next` |
114
- | Import de `react-i18next` direto | Usar import de `forlogic-core` |
115
- | `appTranslations` não passado | Adicionar prop no CoreProviders |
116
- | JSON com formato errado | Deve ser flat, sem nesting |
117
- | Chave duplicada entre features | Último arquivo no merge vence |
1
+ # Padrão: Setup de Traduções (i18n)
2
+
3
+ ## Arquitetura de namespaces
4
+
5
+ - `core` — traduções base da lib (save, cancel, delete, etc.)
6
+ - `app` — traduções do projeto consumidor (injetadas via `CoreProviders`)
7
+ - Resolução: `app` → `core` → fallback `pt-BR`
8
+
9
+ ## Setup em projetos consumidores
10
+
11
+ ### Projeto simples (poucas chaves)
12
+
13
+ 1. Criar JSON flat em `src/i18n/pt-BR.json`: `{ "key": "value" }` (sem nesting)
14
+ 2. Passar para CoreProviders:
15
+
16
+ ```tsx
17
+ <CoreProviders appTranslations={{ 'pt-BR': ptBR, 'en-US': enUS }}>
18
+ ```
19
+
20
+ 3. Usar `useTranslation` de `forlogic-core` (nunca de `react-i18next`)
21
+
22
+ ### Projeto modular (múltiplas features)
23
+
24
+ Para módulos com muitas chaves, dividir traduções por feature:
25
+
26
+ ```text
27
+ src/i18n/
28
+ ├── pt-BR/
29
+ │ ├── common.json ← chaves gerais do módulo
30
+ │ ├── matrices.json ← feature: matrizes
31
+ │ ├── requirements.json ← feature: requisitos
32
+ │ └── reports.json ← feature: relatórios
33
+ ├── en-US/
34
+ │ ├── common.json
35
+ │ ├── matrices.json
36
+ │ ├── requirements.json
37
+ │ └── reports.json
38
+ └── index.ts ← merge automático
39
+ ```
40
+
41
+ #### Arquivo `src/i18n/index.ts`
42
+
43
+ ```ts
44
+ import { mergeTranslationFiles } from 'forlogic-core/i18n';
45
+
46
+ import ptCommon from './pt-BR/common.json';
47
+ import ptMatrices from './pt-BR/matrices.json';
48
+ import ptRequirements from './pt-BR/requirements.json';
49
+ import ptReports from './pt-BR/reports.json';
50
+
51
+ import enCommon from './en-US/common.json';
52
+ import enMatrices from './en-US/matrices.json';
53
+ import enRequirements from './en-US/requirements.json';
54
+ import enReports from './en-US/reports.json';
55
+
56
+ export const appTranslations = {
57
+ 'pt-BR': mergeTranslationFiles(ptCommon, ptMatrices, ptRequirements, ptReports),
58
+ 'en-US': mergeTranslationFiles(enCommon, enMatrices, enRequirements, enReports),
59
+ };
60
+ ```
61
+
62
+ #### Uso no App
63
+
64
+ ```tsx
65
+ import { CoreProviders } from 'forlogic-core';
66
+ import { appTranslations } from './i18n';
67
+
68
+ function App() {
69
+ return (
70
+ <CoreProviders appTranslations={appTranslations}>
71
+ <BrowserRouter><Routes /></BrowserRouter>
72
+ </CoreProviders>
73
+ );
74
+ }
75
+ ```
76
+
77
+ ## Regras dos JSONs
78
+
79
+ - Formato **flat** (sem nesting): `{ "key": "value" }`
80
+ - Chaves duplicadas entre arquivos: o último spread vence (common → features)
81
+ - Chaves do `app` sobrescrevem chaves do `core` com mesmo nome
82
+
83
+ ## Resolução de chaves
84
+
85
+ ```
86
+ t('save') → app: não encontra → core: "Salvar"
87
+ t('objective') → app: "Objetivo"
88
+ t('save') com override no app → app: "Gravar" (sobrescreve core)
89
+ ```
90
+
91
+ ## Helper `mergeTranslationFiles`
92
+
93
+ Utilitário exportado pela lib para facilitar o merge:
94
+
95
+ ```ts
96
+ import { mergeTranslationFiles } from 'forlogic-core/i18n';
97
+
98
+ const ptBR = mergeTranslationFiles(common, matrices, requirements);
99
+ // Equivalente a: { ...common, ...matrices, ...requirements }
100
+ ```
101
+
102
+ ## Debug
103
+
104
+ ```ts
105
+ import { i18n } from 'forlogic-core';
106
+ console.log('Resources:', i18n.store.data);
107
+ ```
108
+
109
+ ## Troubleshooting
110
+
111
+ | Causa | Solução |
112
+ |-------|---------|
113
+ | Chaves aparecem ao invés de traduções | Instalar peer deps `i18next` e `react-i18next` |
114
+ | Import de `react-i18next` direto | Usar import de `forlogic-core` |
115
+ | `appTranslations` não passado | Adicionar prop no CoreProviders |
116
+ | JSON com formato errado | Deve ser flat, sem nesting |
117
+ | Chave duplicada entre features | Último arquivo no merge vence |
@@ -1,27 +1,27 @@
1
- # Padrão: Paginação
2
-
3
- **SEMPRE** usar `Pagination` ou `CrudPrimitivePagination` da lib. NUNCA implementar manualmente.
4
-
5
- ```tsx
6
- // ❌ PROIBIDO - paginação manual
7
- <div className="flex gap-2">
8
- <Button onClick={() => setPage(p => p - 1)}>Anterior</Button>
9
- <span>Página {page}</span>
10
- <Button onClick={() => setPage(p => p + 1)}>Próxima</Button>
11
- </div>
12
-
13
- // ✅ CORRETO - componente padronizado
14
- import { CrudPrimitivePagination } from 'forlogic-core';
15
-
16
- <CrudPrimitivePagination
17
- currentPage={page}
18
- totalPages={totalPages}
19
- pageSize={pageSize}
20
- totalItems={total}
21
- onPageChange={setPage}
22
- onPageSizeChange={setPageSize}
23
- variant="full"
24
- />
25
- ```
26
-
27
- **Obrigatório**: `variant="full"` inclui seletor de itens por página e "X-Y de Z itens".
1
+ # Padrão: Paginação
2
+
3
+ **SEMPRE** usar `Pagination` ou `CrudPrimitivePagination` da lib. NUNCA implementar manualmente.
4
+
5
+ ```tsx
6
+ // ❌ PROIBIDO - paginação manual
7
+ <div className="flex gap-2">
8
+ <Button onClick={() => setPage(p => p - 1)}>Anterior</Button>
9
+ <span>Página {page}</span>
10
+ <Button onClick={() => setPage(p => p + 1)}>Próxima</Button>
11
+ </div>
12
+
13
+ // ✅ CORRETO - componente padronizado
14
+ import { CrudPrimitivePagination } from 'forlogic-core';
15
+
16
+ <CrudPrimitivePagination
17
+ currentPage={page}
18
+ totalPages={totalPages}
19
+ pageSize={pageSize}
20
+ totalItems={total}
21
+ onPageChange={setPage}
22
+ onPageSizeChange={setPageSize}
23
+ variant="full"
24
+ />
25
+ ```
26
+
27
+ **Obrigatório**: `variant="full"` inclui seletor de itens por página e "X-Y de Z itens".
@@ -1,39 +1,39 @@
1
- # Padrão: Scroll Único no Viewport
2
-
3
- O padrão de Scroll Único evita barras de rolagem duplicadas na aplicação.
4
-
5
- ## Cadeia de layout do AppLayout
6
-
7
- ```text
8
- div.h-screen.overflow-hidden ← preso ao viewport, sem scroll
9
- ├─ header (sticky top-0) ← cabeçalho fixo
10
- └─ div.sidebar-container.flex-1.overflow-hidden
11
- ├─ AppSidebar ← sidebar com scroll próprio
12
- └─ main.flex-1.overflow-hidden
13
- └─ div.flex-1.min-h-0.overflow-y-auto ← SCROLL ATIVO aqui
14
- └─ BodyContent (h-full)
15
- └─ ContentContainer (overflow-visible) ← delega scroll para cima
16
- ```
17
-
18
- | Componente | Classes | Responsabilidade |
19
- |------------|---------|------------------|
20
- | `AppLayout` raiz | `h-screen overflow-hidden` | Prende layout ao viewport |
21
- | Container de conteúdo | `flex-1 min-h-0 overflow-y-auto` | Gerencia scroll da página |
22
- | `BodyContent` | `h-full` | Container flexível |
23
- | `ContentContainer` | `overflow-visible` | Delega scroll para o pai |
24
-
25
- **Regra**: Apenas UM nível da hierarquia deve ter scroll ativo — o `div.overflow-y-auto` dentro do `<main>`.
26
-
27
- ```tsx
28
- // ❌ ERRADO - min-h-screen permite crescer além do viewport
29
- <div className="min-h-screen overflow-auto">
30
-
31
- // ✅ CORRETO - h-screen trava no viewport
32
- <div className="h-screen overflow-hidden">
33
- ...
34
- <div className="flex-1 min-h-0 overflow-y-auto">
35
- <BodyContent>...</BodyContent>
36
- </div>
37
- ```
38
-
39
- **`min-h-0`** é essencial no container com `overflow-y-auto` — sem ele, flex items não encolhem abaixo do tamanho do conteúdo.
1
+ # Padrão: Scroll Único no Viewport
2
+
3
+ O padrão de Scroll Único evita barras de rolagem duplicadas na aplicação.
4
+
5
+ ## Cadeia de layout do AppLayout
6
+
7
+ ```text
8
+ div.h-screen.overflow-hidden ← preso ao viewport, sem scroll
9
+ ├─ header (sticky top-0) ← cabeçalho fixo
10
+ └─ div.sidebar-container.flex-1.overflow-hidden
11
+ ├─ AppSidebar ← sidebar com scroll próprio
12
+ └─ main.flex-1.overflow-hidden
13
+ └─ div.flex-1.min-h-0.overflow-y-auto ← SCROLL ATIVO aqui
14
+ └─ BodyContent (h-full)
15
+ └─ ContentContainer (overflow-visible) ← delega scroll para cima
16
+ ```
17
+
18
+ | Componente | Classes | Responsabilidade |
19
+ |------------|---------|------------------|
20
+ | `AppLayout` raiz | `h-screen overflow-hidden` | Prende layout ao viewport |
21
+ | Container de conteúdo | `flex-1 min-h-0 overflow-y-auto` | Gerencia scroll da página |
22
+ | `BodyContent` | `h-full` | Container flexível |
23
+ | `ContentContainer` | `overflow-visible` | Delega scroll para o pai |
24
+
25
+ **Regra**: Apenas UM nível da hierarquia deve ter scroll ativo — o `div.overflow-y-auto` dentro do `<main>`.
26
+
27
+ ```tsx
28
+ // ❌ ERRADO - min-h-screen permite crescer além do viewport
29
+ <div className="min-h-screen overflow-auto">
30
+
31
+ // ✅ CORRETO - h-screen trava no viewport
32
+ <div className="h-screen overflow-hidden">
33
+ ...
34
+ <div className="flex-1 min-h-0 overflow-y-auto">
35
+ <BodyContent>...</BodyContent>
36
+ </div>
37
+ ```
38
+
39
+ **`min-h-0`** é essencial no container com `overflow-y-auto` — sem ele, flex items não encolhem abaixo do tamanho do conteúdo.