forlogic-core 2.2.6 → 2.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.note/memory/features/import/attachment-idempotency-registry.md +8 -8
- package/.note/memory/features/import/attachment-strategy.md +30 -30
- package/.note/memory/patterns/admin-i18n-policy.md +20 -20
- package/.note/memory/patterns/alias-url-resolution.md +69 -69
- package/.note/memory/patterns/doc-sync-rule.md +35 -35
- package/.note/memory/patterns/documentation-standard.md +17 -17
- package/.note/memory/patterns/dynamic-supabase-config.md +4 -4
- package/.note/memory/patterns/environment-detection-logic.md +35 -35
- package/.note/memory/patterns/i18n-architecture.md +3 -3
- package/README.md +120 -120
- package/dist/README.md +1079 -0
- package/dist/bin/bootstrap.js +40 -0
- package/dist/bin/pull-docs.js +186 -0
- package/dist/components/ui/color-picker.d.ts +2 -0
- package/dist/components/ui/combo-tree.d.ts +3 -1
- package/dist/components/ui/combobox.d.ts +2 -1
- package/dist/components/ui/icon-picker.d.ts +2 -0
- package/dist/components/ui/select.d.ts +9 -2
- package/dist/docs/KNOWLEDGE.md +109 -0
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/docs/PUBLISH.md +168 -168
- package/docs/STORAGE_BUCKETS.md +456 -456
- package/docs/SUPABASE_SECRETS.md +122 -122
- package/docs/WORKSPACE_KNOWLEDGE.md +154 -154
- package/docs/design-system/buttons-actions.md +130 -130
- package/docs/design-system/charts-dashboards.md +301 -340
- package/docs/design-system/crud.md +114 -174
- package/docs/design-system/data-display.md +106 -106
- package/docs/design-system/dialogs.md +212 -212
- package/docs/design-system/domain.md +329 -319
- package/docs/design-system/examples.md +275 -275
- package/docs/design-system/foundation.md +1 -1
- package/docs/design-system/inputs.md +137 -132
- package/docs/design-system/layout.md +154 -202
- package/docs/design-system/navigation.md +331 -272
- package/docs/design-system/notifications-feedback.md +34 -34
- package/docs/design-system/patterns/README.md +53 -53
- package/docs/design-system/patterns/action-button.md +22 -22
- package/docs/design-system/patterns/alertdialog-deletion.md +46 -46
- package/docs/design-system/patterns/baseform-custom-fields.md +59 -59
- package/docs/design-system/patterns/baseform-usage.md +42 -42
- package/docs/design-system/patterns/body-content-scroll.md +56 -56
- package/docs/design-system/patterns/combo-tree.md +23 -23
- package/docs/design-system/patterns/components-registry.md +17 -17
- package/docs/design-system/patterns/core-providers.md +41 -41
- package/docs/design-system/patterns/crud-bulk-actions.md +12 -12
- package/docs/design-system/patterns/crud-config-props.md +16 -16
- package/docs/design-system/patterns/crud-defaults.md +17 -17
- package/docs/design-system/patterns/crud-toolbar.md +28 -28
- package/docs/design-system/patterns/delete-confirmation.md +40 -40
- package/docs/design-system/patterns/dialog-body-scroll.md +26 -26
- package/docs/design-system/patterns/dialog-structure.md +32 -32
- package/docs/design-system/patterns/dialog-variants.md +41 -41
- package/docs/design-system/patterns/feature-flags.md +81 -81
- package/docs/design-system/patterns/header-metadata.md +57 -57
- package/docs/design-system/patterns/i18n-setup.md +117 -117
- package/docs/design-system/patterns/pagination.md +27 -27
- package/docs/design-system/patterns/single-scroll.md +39 -39
- package/docs/design-system/patterns/vite-tailwind-setup.md +49 -49
- package/docs/design-system/platform.md +18 -18
- package/docs/design-system/selectors.md +296 -260
- package/docs/design-system/tables-grids.md +38 -95
- package/package.json +152 -152
- package/dist/assets/docs-BEwTKYu3.css +0 -1
- package/dist/assets/docs-Bgpz6ETN.js +0 -10752
- package/dist/assets/index-SqMwTzMJ.js +0 -97
- 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.
|