forlogic-core 2.0.3 → 2.0.4
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/README.md +187 -917
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/dist/types/sidebar.d.ts +2 -1
- package/docs/AUDIT_PROMPT.md +74 -0
- package/docs/PROJECT_KNOWLEDGE_TEMPLATE.md +117 -0
- package/docs/PROMPT_TEMPLATE.md +77 -0
- package/docs/STARTER_TEMPLATE.md +114 -0
- package/docs/design-system/README.md +45 -0
- package/docs/design-system/buttons-actions.md +427 -0
- package/docs/design-system/charts-dashboards.md +547 -0
- package/docs/design-system/crud.md +243 -0
- package/docs/design-system/data-display.md +360 -0
- package/docs/design-system/dialogs.md +588 -0
- package/docs/design-system/domain.md +651 -0
- package/docs/design-system/examples.md +275 -0
- package/docs/design-system/foundation.md +82 -0
- package/docs/design-system/infra-utils.md +36 -0
- package/docs/design-system/inputs.md +536 -0
- package/docs/design-system/layout.md +351 -0
- package/docs/design-system/navigation.md +599 -0
- package/docs/design-system/notifications-feedback.md +137 -0
- package/docs/design-system/platform.md +95 -0
- package/docs/design-system/selectors.md +424 -0
- package/docs/design-system/tables-grids.md +114 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,1033 +1,303 @@
|
|
|
1
|
-
#
|
|
1
|
+
# forlogic-core — Knowledge Base
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **Documento de referência** para projetos que consomem `forlogic-core`.
|
|
4
|
+
> Cole este conteúdo como Custom Knowledge no Lovable ou use como README.md com Claude Code.
|
|
4
5
|
|
|
5
6
|
---
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## 🔗 Cross-Project: Projeto Admin (DS + Lib)
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
> **Para consultar componentes, props, tipos, exemplos e implementação**: use cross-project (`@Admin`) para ler arquivos do projeto **"Admin"** (`qualiex-admin`).
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
### Caminhos úteis no projeto Admin
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
npm install forlogic-core
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
**Nota**: O npm/yarn irá alertar automaticamente se alguma peer dependency estiver faltando ou com versão incompatível.
|
|
29
|
-
|
|
30
|
-
### ⚠️ IMPORTANTE: Imports de i18n
|
|
31
|
-
|
|
32
|
-
**Sempre** importe hooks de internacionalização do `forlogic-core`, nunca diretamente de `react-i18next`:
|
|
33
|
-
|
|
34
|
-
```tsx
|
|
35
|
-
// ❌ ERRADO - Causa conflito de instâncias (erro NO_I18NEXT_INSTANCE)
|
|
36
|
-
import { useTranslation } from 'react-i18next';
|
|
37
|
-
|
|
38
|
-
// ✅ CORRETO - Usa a mesma instância configurada pelo CoreProviders
|
|
39
|
-
import { useTranslation } from 'forlogic-core';
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Isso garante que todos os componentes compartilhem a mesma instância do i18next configurada pelo `CoreProviders`.
|
|
14
|
+
| O que procurar | Caminho no Admin |
|
|
15
|
+
|----------------|------------------|
|
|
16
|
+
| Código-fonte dos componentes UI | `lib/components/ui/` |
|
|
17
|
+
| Sistema CRUD | `lib/crud/` |
|
|
18
|
+
| Barrel exports (lista completa) | `lib/exports/ui.ts`, `lib/exports/index.ts` |
|
|
19
|
+
| Documentação MD do Design System | `docs/design-system/` |
|
|
20
|
+
| Docs interativos (código-fonte) | `src/design-system/docs/` |
|
|
21
|
+
| Hooks compartilhados | `lib/hooks/` |
|
|
22
|
+
| Providers (CoreProviders) | `lib/providers/` |
|
|
23
|
+
| Serviços (Base, Email, Error) | `lib/services/` |
|
|
24
|
+
| Config Vite/Tailwind | `lib/vite/`, `lib/tailwind/` |
|
|
43
25
|
|
|
44
26
|
---
|
|
45
27
|
|
|
46
|
-
##
|
|
47
|
-
|
|
48
|
-
> **⚠️ REGRA FUNDAMENTAL**: Antes de criar qualquer componente, serviço ou utilitário no projeto, VERIFIQUE se já existe na `forlogic-core`.
|
|
49
|
-
|
|
50
|
-
### 🤔 Por Quê?
|
|
51
|
-
|
|
52
|
-
A `forlogic-core` é a **biblioteca central** de componentes, serviços e utilitários compartilhados entre todos os projetos. Quando você cria um componente local que já existe na lib:
|
|
28
|
+
## 0. Schema do Projeto
|
|
53
29
|
|
|
54
|
-
|
|
55
|
-
2. **❌ Duplicação de Código** - Aumenta tamanho do bundle e manutenção
|
|
56
|
-
3. **❌ Inconsistência** - UI/UX diferente entre projetos
|
|
57
|
-
4. **❌ Retrabalho** - Correções de bugs precisam ser feitas em múltiplos lugares
|
|
30
|
+
> ⚠️ **Substitua `SCHEMA_PADRAO` pelo schema do SEU projeto.**
|
|
58
31
|
|
|
59
|
-
|
|
32
|
+
```ts
|
|
33
|
+
// ✅ CORRETO
|
|
34
|
+
supabase.schema('SCHEMA_PADRAO').from('tabela').select('*');
|
|
60
35
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- [ ] Verifiquei a documentação do Design System (/design_system)?
|
|
64
|
-
- [ ] Confirmei que a funcionalidade não pode ser alcançada com props/variantes existentes?
|
|
65
|
-
- [ ] Se não existe, solicitei a inclusão na lib para beneficiar todos os projetos?
|
|
36
|
+
// ❌ ERRADO (vai falhar)
|
|
37
|
+
supabase.from('tabela').select('*');
|
|
66
38
|
```
|
|
67
39
|
|
|
68
|
-
### ✅ CORRETO: Usar da Lib
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
// ✅ Sempre importe da forlogic-core
|
|
72
|
-
import {
|
|
73
|
-
Button,
|
|
74
|
-
Input,
|
|
75
|
-
Dialog,
|
|
76
|
-
Combobox,
|
|
77
|
-
SplitButton,
|
|
78
|
-
RichTextEditor,
|
|
79
|
-
createCrudPage,
|
|
80
|
-
cn,
|
|
81
|
-
formatDatetime
|
|
82
|
-
} from 'forlogic-core';
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### ❌ PROIBIDO: Criar Localmente (se existe na lib)
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
// ❌ NUNCA crie pastas/arquivos que já existem na lib
|
|
89
|
-
src/components/ui/button.tsx // Existe na lib
|
|
90
|
-
src/components/ui/dialog.tsx // Existe na lib
|
|
91
|
-
src/lib/utils.ts // cn() existe na lib
|
|
92
|
-
src/components/SplitButton.tsx // Existe na lib (a partir de v1.12.2)
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### 🔄 Processo Quando Precisa de Customização
|
|
96
|
-
|
|
97
|
-
| Cenário | Ação Correta |
|
|
98
|
-
| ----------------------------------- | ---------------------------------------------------- |
|
|
99
|
-
| Componente não existe na lib | ✅ Criar localmente E solicitar inclusão na lib |
|
|
100
|
-
| Precisa de variante nova | ✅ Solicitar variante na lib (PR ou pedido) |
|
|
101
|
-
| Precisa de comportamento específico | ✅ Usar composição/wrapper ao invés de recriar |
|
|
102
|
-
| Bug no componente da lib | ✅ Reportar e corrigir na lib, não criar cópia local |
|
|
103
|
-
|
|
104
|
-
### 📖 Onde Verificar Componentes Disponíveis
|
|
105
|
-
|
|
106
|
-
| Recurso | Descrição |
|
|
107
|
-
| --------------------------------- | --------------------------------------------------- |
|
|
108
|
-
| `/design_system` | Design System com todos os componentes documentados |
|
|
109
|
-
| `forlogic-core/lib/exports/ui.ts` | Lista de exports de UI |
|
|
110
|
-
| `forlogic-core/lib/index.ts` | Index principal com todos os exports |
|
|
111
|
-
|
|
112
|
-
### ⚠️ Exceções (quando PODE criar localmente)
|
|
113
|
-
|
|
114
|
-
1. **Componente específico de negócio** - Ex: `InvoiceCard`, `UserProfileWidget`
|
|
115
|
-
2. **Composição de componentes da lib** - Ex: wrapper que combina Dialog + Form
|
|
116
|
-
3. **Componente temporário** - Protótipo que será migrado para a lib depois
|
|
117
|
-
4. **Funcionalidade não generalizável** - Algo tão específico que não faz sentido na lib
|
|
118
|
-
|
|
119
|
-
> **📝 Mesmo nas exceções, avalie se o componente poderia ser generalizado e incluído na lib para beneficiar outros projetos.**
|
|
120
|
-
|
|
121
40
|
---
|
|
122
41
|
|
|
123
|
-
##
|
|
42
|
+
## 1. Regras Invioláveis
|
|
124
43
|
|
|
125
|
-
|
|
44
|
+
| Regra | Detalhe |
|
|
45
|
+
|-------|---------|
|
|
46
|
+
| Schema obrigatório | `.schema('SCHEMA_PADRAO')` em toda query Supabase |
|
|
47
|
+
| Sem DELETE físico | Soft delete com `deleted_at` + policy `FOR UPDATE` |
|
|
48
|
+
| Sem índices automáticos | Apenas com aprovação explícita + EXPLAIN ANALYZE |
|
|
49
|
+
| Sem modificar `.env` | Apenas com autorização do usuário |
|
|
50
|
+
| Sem hardcoded admin | Nunca localStorage/sessionStorage para roles |
|
|
51
|
+
| Lib-first | Usar `forlogic-core` antes de criar componente |
|
|
52
|
+
| Import do Supabase | Sempre `getSupabaseClient()` de `forlogic-core` |
|
|
53
|
+
| Import de i18n | Sempre `useTranslation` de `forlogic-core`, nunca de `react-i18next` |
|
|
126
54
|
|
|
127
|
-
|
|
55
|
+
---
|
|
128
56
|
|
|
129
|
-
|
|
57
|
+
## 2. RLS — Políticas de Segurança
|
|
130
58
|
|
|
131
|
-
|
|
132
|
-
// ❌ ERRADO
|
|
133
|
-
.from('table')
|
|
59
|
+
### Sintaxe obrigatória
|
|
134
60
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
61
|
+
- `SELECT` → `USING` | `INSERT` → `WITH CHECK` | `UPDATE` → `USING` + `WITH CHECK`
|
|
62
|
+
- **Nunca** `FOR DELETE`
|
|
63
|
+
- **Sempre** `(SELECT auth.jwt())` com parênteses (evita re-execução por linha)
|
|
138
64
|
|
|
139
|
-
|
|
65
|
+
### Padrão JWT alias (multi-tenancy)
|
|
140
66
|
|
|
141
67
|
```sql
|
|
142
|
-
|
|
143
|
-
CREATE POLICY "Users view own" ON seu_schema.table
|
|
144
|
-
FOR SELECT WITH CHECK (auth.uid() = id_user);
|
|
145
|
-
|
|
146
|
-
-- ✅ CORRETO: USING para SELECT
|
|
147
|
-
CREATE POLICY "Users view own" ON seu_schema.table
|
|
68
|
+
CREATE POLICY "table_select" ON SCHEMA_PADRAO.tabela
|
|
148
69
|
FOR SELECT USING (
|
|
149
70
|
((SELECT auth.jwt()) ->> 'alias'::text) = alias
|
|
150
71
|
);
|
|
151
|
-
```
|
|
152
72
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
CREATE POLICY "table_delete" ON seu_schema.table
|
|
158
|
-
FOR DELETE USING (...);
|
|
73
|
+
CREATE POLICY "table_insert" ON SCHEMA_PADRAO.tabela
|
|
74
|
+
FOR INSERT WITH CHECK (
|
|
75
|
+
((SELECT auth.jwt()) ->> 'alias'::text) = alias
|
|
76
|
+
);
|
|
159
77
|
|
|
160
|
-
|
|
161
|
-
|
|
78
|
+
CREATE POLICY "table_update" ON SCHEMA_PADRAO.tabela
|
|
79
|
+
FOR UPDATE
|
|
80
|
+
USING (((SELECT auth.jwt()) ->> 'alias'::text) = alias)
|
|
81
|
+
WITH CHECK (((SELECT auth.jwt()) ->> 'alias'::text) = alias);
|
|
162
82
|
```
|
|
163
83
|
|
|
164
|
-
|
|
84
|
+
### Soft delete (padrão obrigatório)
|
|
165
85
|
|
|
166
86
|
```sql
|
|
167
|
-
|
|
168
|
-
CREATE INDEX idx_table_user ON seu_schema.table(id_user);
|
|
87
|
+
ALTER TABLE SCHEMA_PADRAO.tabela ADD COLUMN deleted_at TIMESTAMP WITH TIME ZONE;
|
|
169
88
|
|
|
170
|
-
|
|
89
|
+
CREATE POLICY "table_select" ON SCHEMA_PADRAO.tabela
|
|
90
|
+
FOR SELECT USING (
|
|
91
|
+
deleted_at IS NULL
|
|
92
|
+
AND ((SELECT auth.jwt()) ->> 'alias'::text) = alias
|
|
93
|
+
);
|
|
171
94
|
```
|
|
172
95
|
|
|
173
96
|
---
|
|
174
97
|
|
|
175
|
-
##
|
|
176
|
-
|
|
177
|
-
### ⚠️ PADRÕES OBRIGATÓRIOS
|
|
178
|
-
|
|
179
|
-
**Foreign Keys (Chaves Estrangeiras):**
|
|
180
|
-
|
|
181
|
-
```typescript
|
|
182
|
-
// ❌ ERRADO
|
|
183
|
-
process_id: string
|
|
184
|
-
user_id: string
|
|
185
|
-
|
|
186
|
-
// ✅ CORRETO - Sempre prefixo id_
|
|
187
|
-
id_process: string
|
|
188
|
-
id_user: string
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
**Booleans:**
|
|
98
|
+
## 3. Convenções SQL
|
|
192
99
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
is_active: boolean
|
|
200
|
-
is_removed: boolean
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**Timestamps:**
|
|
204
|
-
|
|
205
|
-
```typescript
|
|
206
|
-
// ❌ ERRADO
|
|
207
|
-
creation_date: string
|
|
208
|
-
update_time: string
|
|
209
|
-
|
|
210
|
-
// ✅ CORRETO - Sempre sufixo _at
|
|
211
|
-
created_at: string
|
|
212
|
-
updated_at: string
|
|
213
|
-
deleted_at: string
|
|
214
|
-
```
|
|
100
|
+
| Tipo | Padrão | Exemplo |
|
|
101
|
+
|------|--------|---------|
|
|
102
|
+
| FK | `id_<singular>` | `id_process`, `id_user` |
|
|
103
|
+
| Boolean | `is_` / `has_` | `is_active`, `has_access` |
|
|
104
|
+
| Timestamps | `created_at`, `updated_at`, `deleted_at` | — |
|
|
105
|
+
| Tabelas | plural, snake_case | `processes`, `user_roles` |
|
|
215
106
|
|
|
216
107
|
---
|
|
217
108
|
|
|
218
|
-
##
|
|
219
|
-
|
|
220
|
-
### ⚠️ REGRA DE OURO
|
|
221
|
-
|
|
222
|
-
**NUNCA, EM HIPÓTESE ALGUMA, criar índices automaticamente em migrations!**
|
|
109
|
+
## 4. Lib-First — forlogic-core
|
|
223
110
|
|
|
224
|
-
|
|
111
|
+
> Antes de criar qualquer componente, verificar se já existe em `forlogic-core`.
|
|
225
112
|
|
|
226
|
-
|
|
227
|
-
2. **Performance de Escrita**: Cada índice adiciona overhead em INSERTs/UPDATEs
|
|
228
|
-
3. **Otimização Prematura**: 99% dos índices criados "por precaução" nunca são usados
|
|
229
|
-
4. **Manutenção**: Índices desnecessários dificultam manutenção e análise de queries
|
|
113
|
+
### Import correto
|
|
230
114
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
CREATE INDEX idx_process_title ON processes(title);
|
|
239
|
-
|
|
240
|
-
-- ❌ PROIBIDO: Índice composto "por precaução"
|
|
241
|
-
CREATE INDEX idx_deliverable_status ON deliverables(id_subprocess, is_completed);
|
|
115
|
+
```ts
|
|
116
|
+
import {
|
|
117
|
+
Button, Dialog, Input, Combobox, SplitButton, RichTextEditor,
|
|
118
|
+
createCrudPage, CrudTable, CrudActionBar, BaseForm,
|
|
119
|
+
ActionButton, EmptyState, LoadingState, StepSelector,
|
|
120
|
+
cn, formatDatetime, useTranslation
|
|
121
|
+
} from 'forlogic-core';
|
|
242
122
|
```
|
|
243
123
|
|
|
244
|
-
###
|
|
124
|
+
### Checklist
|
|
245
125
|
|
|
246
|
-
|
|
126
|
+
- [ ] Pesquisei se existe na forlogic-core?
|
|
127
|
+
- [ ] Verifiquei o Design System (`@Admin docs/design-system/`)?
|
|
128
|
+
- [ ] Pode ser alcançado com props/variantes existentes?
|
|
247
129
|
|
|
248
|
-
|
|
249
|
-
2. ✅ **Análise de performance** comprovou necessidade (EXPLAIN ANALYZE)
|
|
250
|
-
3. ✅ **Aprovação prévia** do usuário para incluir na migration
|
|
130
|
+
### Exceções (pode criar localmente)
|
|
251
131
|
|
|
252
|
-
|
|
132
|
+
1. Componente específico de negócio (ex: `InvoiceCard`)
|
|
133
|
+
2. Composição de componentes da lib (wrapper Dialog + Form)
|
|
134
|
+
3. Protótipo temporário que será migrado para a lib
|
|
253
135
|
|
|
254
|
-
|
|
255
|
-
- [ ] A migration NÃO contém NENHUM `CREATE INDEX`?
|
|
256
|
-
- [ ] A migration NÃO contém políticas DELETE?
|
|
257
|
-
- [ ] Se contém índice, o usuário solicitou EXPLICITAMENTE?
|
|
258
|
-
- [ ] Se contém índice, foi feita análise de performance (EXPLAIN ANALYZE)?
|
|
259
|
-
- [ ] Se contém índice, o usuário APROVOU adicionar à migration?
|
|
260
|
-
- [ ] Estou usando soft delete ao invés de DELETE físico?
|
|
261
|
-
- [ ] Especifiquei o schema correto em todas as tabelas?
|
|
262
|
-
- [ ] Usei sintaxe correta nas políticas RLS (USING vs WITH CHECK)?
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
### 🔧 Processo Correto Para Criar Índices
|
|
266
|
-
|
|
267
|
-
1. **Usuário solicita** OU problemas de performance são detectados
|
|
268
|
-
2. **Rodar EXPLAIN ANALYZE** para confirmar necessidade
|
|
269
|
-
3. **Perguntar ao usuário**: "Posso criar o índice X na coluna Y? Isso vai melhorar a query Z mas adiciona overhead."
|
|
270
|
-
4. **Aguardar aprovação** do usuário
|
|
271
|
-
5. **Criar migration separada** apenas com os índices aprovados
|
|
272
|
-
|
|
273
|
-
### 📝 Template de Migration de Índices (quando aprovado)
|
|
274
|
-
|
|
275
|
-
```sql
|
|
276
|
-
-- Migration: [TIMESTAMP]_add_performance_indexes.sql
|
|
277
|
-
-- Aprovado em: [DATA]
|
|
278
|
-
-- Justificativa: [RAZÃO ESPECÍFICA]
|
|
136
|
+
---
|
|
279
137
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
138
|
+
## 5. Design System — Categorias
|
|
139
|
+
|
|
140
|
+
> Para ver props e exemplos: `@Admin docs/design-system/<arquivo>.md`
|
|
141
|
+
|
|
142
|
+
| Categoria | Arquivo |
|
|
143
|
+
|-----------|---------|
|
|
144
|
+
| Fundação | `foundation.md` |
|
|
145
|
+
| Botões & Ações | `buttons-actions.md` |
|
|
146
|
+
| Inputs | `inputs.md` |
|
|
147
|
+
| Seletores | `selectors.md` |
|
|
148
|
+
| Data Display | `data-display.md` |
|
|
149
|
+
| Data Grid | `tables-grids.md` |
|
|
150
|
+
| Gráficos & Dashboards | `charts-dashboards.md` |
|
|
151
|
+
| Navegação | `navigation.md` |
|
|
152
|
+
| Dialogs | `dialogs.md` |
|
|
153
|
+
| Notifications & Feedback | `notifications-feedback.md` |
|
|
154
|
+
| Layout | `layout.md` |
|
|
155
|
+
| CRUD | `crud.md` |
|
|
156
|
+
| Plataforma | `platform.md` |
|
|
157
|
+
| Business Components | `domain.md` |
|
|
158
|
+
| Developer Tools | `infra-utils.md` |
|
|
159
|
+
|
|
160
|
+
### Aliases disponíveis
|
|
161
|
+
|
|
162
|
+
| Original | Alias(es) |
|
|
163
|
+
|----------|-----------|
|
|
164
|
+
| Combobox | SelectSearch, MultiSelect, EntitySelect, AutoComplete |
|
|
165
|
+
| ComboTree | TreeSelect |
|
|
166
|
+
| StepSelector | Stepper |
|
|
167
|
+
| ActionButton | ActionMenu, RowActions |
|
|
168
|
+
| TruncatedCell | EllipsisText |
|
|
169
|
+
| CrudPrimitiveTable | DataTable |
|
|
170
|
+
| CrudPrimitivePagination | DataPagination |
|
|
171
|
+
| CrudPrimitiveFilterBar | DataFilterBar |
|
|
283
172
|
|
|
284
173
|
---
|
|
285
174
|
|
|
286
|
-
##
|
|
175
|
+
## 6. Padrões CRUD
|
|
287
176
|
|
|
288
|
-
|
|
177
|
+
### Toolbar — Layout obrigatório de 3 zonas
|
|
289
178
|
|
|
290
|
-
|
|
179
|
+
| Zona | Posição | Conteúdo |
|
|
180
|
+
|------|---------|----------|
|
|
181
|
+
| Esquerda | `justify-start` | Botão "Novo" + Dropdown ações em lote |
|
|
182
|
+
| Centro | `flex-1 max-w-md` | Campo de busca |
|
|
183
|
+
| Direita | `justify-end` | Filtros + Toggle view |
|
|
291
184
|
|
|
292
|
-
|
|
293
|
-
// Configurações Vite (headers de segurança, CSP, CORS)
|
|
294
|
-
import { createSecurityHeadersPlugin, createForlogicViteConfig } from 'forlogic-core/vite';
|
|
185
|
+
### Defaults
|
|
295
186
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
187
|
+
- Column resize/manager: ativados por padrão
|
|
188
|
+
- Paginação: 25 itens/página
|
|
189
|
+
- Busca: no header (na action bar com `showSearch=true`)
|
|
190
|
+
- Ações de linha: sempre usar `ActionButton` da lib
|
|
299
191
|
|
|
300
192
|
---
|
|
301
193
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
O plugin configura automaticamente:
|
|
305
|
-
|
|
306
|
-
- **Content Security Policy (CSP)** - Proteção contra XSS e injeção de scripts
|
|
307
|
-
- **CORS seguro** - Origens confiáveis sem usar `*`
|
|
308
|
-
- **Headers OWASP** - HSTS, X-Content-Type-Options, X-Frame-Options, etc.
|
|
309
|
-
- **Permissions Policy** - Controle de APIs do navegador
|
|
310
|
-
|
|
311
|
-
#### Uso Básico
|
|
194
|
+
## 7. Padrões Deprecated
|
|
312
195
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
196
|
+
| ❌ Não usar | ✅ Usar |
|
|
197
|
+
|------------|--------|
|
|
198
|
+
| `BulkActionBar` separado | Dropdown no `CrudActionBar` |
|
|
199
|
+
| `<MoreHorizontal>` genérico | `ActionButton` |
|
|
200
|
+
| Paginação manual | `CrudPrimitivePagination` |
|
|
201
|
+
| `StatusSelect` | `Combobox` |
|
|
202
|
+
| `DeleteConfirmationDialog` | `Dialog` |
|
|
203
|
+
| `Searchbar` | `Input` com ícone |
|
|
204
|
+
| `public` schema | `.schema('SCHEMA_PADRAO')` |
|
|
318
205
|
|
|
319
|
-
|
|
320
|
-
plugins: [
|
|
321
|
-
react(),
|
|
322
|
-
createSecurityHeadersPlugin(mode === 'development', {
|
|
323
|
-
supabaseUrls: ['https://seu-projeto.supabase.co'],
|
|
324
|
-
}),
|
|
325
|
-
],
|
|
326
|
-
}));
|
|
327
|
-
```
|
|
206
|
+
---
|
|
328
207
|
|
|
329
|
-
|
|
208
|
+
## 8. Configuração — Vite
|
|
330
209
|
|
|
331
|
-
```
|
|
332
|
-
// vite.config.ts
|
|
333
|
-
import { defineConfig } from 'vite';
|
|
334
|
-
import react from '@vitejs/plugin-react-swc';
|
|
210
|
+
```ts
|
|
335
211
|
import { createSecurityHeadersPlugin } from 'forlogic-core/vite';
|
|
336
212
|
|
|
337
213
|
export default defineConfig(({ mode }) => ({
|
|
338
214
|
plugins: [
|
|
339
215
|
react(),
|
|
340
216
|
createSecurityHeadersPlugin(mode === 'development', {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
'https://seu-projeto-dev.supabase.co',
|
|
344
|
-
'https://seu-projeto-prod.supabase.co',
|
|
345
|
-
],
|
|
346
|
-
|
|
347
|
-
// Origens confiáveis adicionais para CORS
|
|
348
|
-
trustedOrigins: [
|
|
349
|
-
'https://meu-app.com',
|
|
350
|
-
'https://admin.meu-app.com',
|
|
351
|
-
],
|
|
352
|
-
|
|
353
|
-
// APIs externas para connect-src
|
|
354
|
-
additionalConnectSrc: [
|
|
355
|
-
'https://api.exemplo.com',
|
|
356
|
-
'wss://websocket.exemplo.com',
|
|
357
|
-
],
|
|
358
|
-
|
|
359
|
-
// CDNs de scripts/estilos/fontes adicionais
|
|
360
|
-
additionalScriptSrc: ['https://cdn.analytics.com'],
|
|
361
|
-
additionalStyleSrc: ['https://fonts.custom.com'],
|
|
362
|
-
additionalFontSrc: ['https://fonts.gstatic.com'],
|
|
363
|
-
|
|
364
|
-
// URI para reportar violações CSP
|
|
365
|
-
cspReportUri: 'https://seu-projeto.supabase.co/functions/v1/csp-report',
|
|
366
|
-
|
|
367
|
-
// Opções de produção (defaults: true)
|
|
368
|
-
enableTrustedTypes: true,
|
|
369
|
-
upgradeInsecureRequests: true,
|
|
217
|
+
supabaseUrls: ['https://SEU_PROJETO.supabase.co'],
|
|
218
|
+
additionalConnectSrc: ['https://*.qualiex.com'],
|
|
370
219
|
}),
|
|
371
220
|
],
|
|
221
|
+
resolve: { alias: { '@': path.resolve(__dirname, './src') } },
|
|
222
|
+
optimizeDeps: { force: true },
|
|
372
223
|
}));
|
|
373
224
|
```
|
|
374
225
|
|
|
375
|
-
#### Opções do Plugin
|
|
376
|
-
|
|
377
|
-
| Opção | Tipo | Padrão | Descrição |
|
|
378
|
-
| ------------------------- | ---------- | ------ | --------------------------------------- |
|
|
379
|
-
| `supabaseUrls` | `string[]` | `[]` | URLs do Supabase permitidas |
|
|
380
|
-
| `trustedOrigins` | `string[]` | `[]` | Origens confiáveis adicionais para CORS |
|
|
381
|
-
| `additionalScriptSrc` | `string[]` | `[]` | Fontes de script adicionais para CSP |
|
|
382
|
-
| `additionalStyleSrc` | `string[]` | `[]` | Fontes de estilo adicionais para CSP |
|
|
383
|
-
| `additionalConnectSrc` | `string[]` | `[]` | APIs/WebSockets adicionais para CSP |
|
|
384
|
-
| `additionalFontSrc` | `string[]` | `[]` | Fontes de font adicionais para CSP |
|
|
385
|
-
| `cspReportUri` | `string` | - | URI para relatório de violações CSP |
|
|
386
|
-
| `enableTrustedTypes` | `boolean` | `true` | Habilitar Trusted Types em produção |
|
|
387
|
-
| `upgradeInsecureRequests` | `boolean` | `true` | Upgrade HTTP→HTTPS em produção |
|
|
388
|
-
|
|
389
226
|
---
|
|
390
227
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
Para projetos que desejam usar a configuração padronizada com segurança:
|
|
394
|
-
|
|
395
|
-
```typescript
|
|
396
|
-
// vite.config.ts
|
|
397
|
-
import { defineConfig } from 'vite';
|
|
398
|
-
import react from '@vitejs/plugin-react-swc';
|
|
399
|
-
import path from 'path';
|
|
400
|
-
import { createForlogicViteConfig } from 'forlogic-core/vite';
|
|
401
|
-
|
|
402
|
-
const forlogicConfig = createForlogicViteConfig({
|
|
403
|
-
security: {
|
|
404
|
-
supabaseUrls: ['https://seu-projeto.supabase.co'],
|
|
405
|
-
trustedOrigins: ['https://meu-app.com'],
|
|
406
|
-
},
|
|
407
|
-
server: { host: '::', port: 8080 },
|
|
408
|
-
build: { chunkSizeWarningLimit: 4000 },
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
export default defineConfig(({ mode }) => {
|
|
412
|
-
const isDev = mode === 'development';
|
|
413
|
-
const baseConfig = forlogicConfig(isDev);
|
|
414
|
-
|
|
415
|
-
return {
|
|
416
|
-
...baseConfig,
|
|
417
|
-
plugins: [react(), ...baseConfig.plugins],
|
|
418
|
-
// IMPORTANTE: resolve.alias deve usar caminhos absolutos
|
|
419
|
-
resolve: {
|
|
420
|
-
alias: {
|
|
421
|
-
'@': path.resolve(__dirname, './src'),
|
|
422
|
-
},
|
|
423
|
-
},
|
|
424
|
-
};
|
|
425
|
-
});
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
> **⚠️ IMPORTANTE**: A factory **não** configura `resolve.alias` porque caminhos relativos não funcionam corretamente no build. Cada projeto deve definir seus próprios aliases com `path.resolve(__dirname, './caminho')` para garantir caminhos absolutos.
|
|
429
|
-
|
|
430
|
-
---
|
|
431
|
-
|
|
432
|
-
### 📋 Template Completo para Projetos Consumidores
|
|
433
|
-
|
|
434
|
-
Copie e adapte este template para novos projetos:
|
|
435
|
-
|
|
436
|
-
```typescript
|
|
437
|
-
// vite.config.ts
|
|
438
|
-
import { defineConfig } from 'vite';
|
|
439
|
-
import react from '@vitejs/plugin-react-swc';
|
|
440
|
-
import path from 'path';
|
|
441
|
-
import { createSecurityHeadersPlugin } from 'forlogic-core/vite';
|
|
442
|
-
|
|
443
|
-
export default defineConfig(({ mode }) => {
|
|
444
|
-
const isDev = mode === 'development';
|
|
445
|
-
|
|
446
|
-
return {
|
|
447
|
-
server: {
|
|
448
|
-
host: '::',
|
|
449
|
-
port: 8080,
|
|
450
|
-
},
|
|
451
|
-
|
|
452
|
-
// Força re-bundle quando atualizar forlogic-core
|
|
453
|
-
optimizeDeps: {
|
|
454
|
-
force: true,
|
|
455
|
-
},
|
|
456
|
-
|
|
457
|
-
plugins: [
|
|
458
|
-
react(),
|
|
459
|
-
// Headers de segurança (CSP, CORS, etc.)
|
|
460
|
-
createSecurityHeadersPlugin(isDev, {
|
|
461
|
-
supabaseUrls: [
|
|
462
|
-
'https://SEU_PROJETO.supabase.co',
|
|
463
|
-
],
|
|
464
|
-
additionalConnectSrc: [
|
|
465
|
-
'https://*.qualiex.com',
|
|
466
|
-
],
|
|
467
|
-
// Opcional: URI para relatório de violações CSP
|
|
468
|
-
cspReportUri: isDev
|
|
469
|
-
? 'https://SEU_PROJETO_DEV.supabase.co/functions/v1/csp-report'
|
|
470
|
-
: 'https://SEU_PROJETO_PROD.supabase.co/functions/v1/csp-report',
|
|
471
|
-
}),
|
|
472
|
-
],
|
|
473
|
-
|
|
474
|
-
// CRÍTICO: Aliases devem usar caminhos absolutos
|
|
475
|
-
resolve: {
|
|
476
|
-
alias: {
|
|
477
|
-
'@': path.resolve(__dirname, './src'),
|
|
478
|
-
},
|
|
479
|
-
},
|
|
480
|
-
|
|
481
|
-
publicDir: false,
|
|
482
|
-
|
|
483
|
-
esbuild: {
|
|
484
|
-
sourcemap: true,
|
|
485
|
-
target: 'es2020',
|
|
486
|
-
},
|
|
487
|
-
|
|
488
|
-
build: {
|
|
489
|
-
chunkSizeWarningLimit: 4000,
|
|
490
|
-
},
|
|
491
|
-
};
|
|
492
|
-
});
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
#### Checklist de Configuração
|
|
496
|
-
|
|
497
|
-
```markdown
|
|
498
|
-
- [ ] Substituiu `SEU_PROJETO` pelas URLs do Supabase
|
|
499
|
-
- [ ] Adicionou origens confiáveis em `additionalConnectSrc` se necessário
|
|
500
|
-
- [ ] Verificou que `resolve.alias` usa `path.resolve(__dirname, ...)`
|
|
501
|
-
- [ ] Reiniciou o servidor após modificar o arquivo
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
---
|
|
505
|
-
|
|
506
|
-
### 🔄 Forçar Re-bundle de Dependências
|
|
507
|
-
|
|
508
|
-
Se você atualizar a `forlogic-core` e as mudanças não aparecerem no preview:
|
|
509
|
-
|
|
510
|
-
```typescript
|
|
511
|
-
// vite.config.ts
|
|
512
|
-
export default defineConfig(({ mode }) => ({
|
|
513
|
-
optimizeDeps: {
|
|
514
|
-
force: true, // Força re-otimização a cada restart do dev server
|
|
515
|
-
},
|
|
516
|
-
// ...
|
|
517
|
-
}));
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
> **⚠️ IMPORTANTE**: Após adicionar `force: true`, reinicie o servidor completamente (pare e inicie novamente).
|
|
521
|
-
|
|
522
|
-
---
|
|
523
|
-
|
|
524
|
-
### 🎨 Preset Tailwind CSS
|
|
525
|
-
|
|
526
|
-
O preset inclui:
|
|
527
|
-
|
|
528
|
-
- **Cores semânticas** - primary, secondary, destructive, success, warning, etc.
|
|
529
|
-
- **Border radius** - lg, md, sm padronizados
|
|
530
|
-
- **Animações** - accordion, fade, slide, scale
|
|
531
|
-
- **Gradientes** - primary, secondary, accent
|
|
532
|
-
- **Sombras** - xs até 2xl, inner, primary
|
|
533
|
-
|
|
534
|
-
#### Uso Básico
|
|
535
|
-
|
|
536
|
-
```typescript
|
|
537
|
-
// tailwind.config.ts
|
|
538
|
-
import type { Config } from 'tailwindcss';
|
|
539
|
-
import { forlogicTailwindPreset, forlogicContentPaths } from 'forlogic-core/tailwind';
|
|
540
|
-
|
|
541
|
-
export default {
|
|
542
|
-
presets: [forlogicTailwindPreset],
|
|
543
|
-
content: [
|
|
544
|
-
...forlogicContentPaths,
|
|
545
|
-
// Paths adicionais específicos do seu projeto
|
|
546
|
-
],
|
|
547
|
-
} satisfies Config;
|
|
548
|
-
```
|
|
549
|
-
|
|
550
|
-
#### Uso com Extensões
|
|
228
|
+
## 9. Configuração — Tailwind
|
|
551
229
|
|
|
552
|
-
```
|
|
553
|
-
// tailwind.config.ts
|
|
554
|
-
import type { Config } from 'tailwindcss';
|
|
230
|
+
```ts
|
|
555
231
|
import { forlogicTailwindPreset, forlogicContentPaths } from 'forlogic-core/tailwind';
|
|
556
232
|
|
|
557
233
|
export default {
|
|
558
234
|
presets: [forlogicTailwindPreset],
|
|
559
|
-
content: [
|
|
560
|
-
...forlogicContentPaths,
|
|
561
|
-
],
|
|
562
|
-
theme: {
|
|
563
|
-
extend: {
|
|
564
|
-
// Extensões específicas do seu projeto
|
|
565
|
-
colors: {
|
|
566
|
-
brand: {
|
|
567
|
-
50: 'hsl(var(--brand-50))',
|
|
568
|
-
// ...
|
|
569
|
-
},
|
|
570
|
-
},
|
|
571
|
-
},
|
|
572
|
-
},
|
|
573
|
-
plugins: [
|
|
574
|
-
require('tailwindcss-animate'),
|
|
575
|
-
// Plugins adicionais
|
|
576
|
-
],
|
|
235
|
+
content: [...forlogicContentPaths],
|
|
577
236
|
} satisfies Config;
|
|
578
237
|
```
|
|
579
238
|
|
|
580
|
-
#### Content Paths Padrão
|
|
581
|
-
|
|
582
|
-
O `forlogicContentPaths` inclui:
|
|
583
|
-
|
|
584
|
-
```typescript
|
|
585
|
-
[
|
|
586
|
-
'./pages/**/*.{ts,tsx}',
|
|
587
|
-
'./components/**/*.{ts,tsx}',
|
|
588
|
-
'./app/**/*.{ts,tsx}',
|
|
589
|
-
'./src/**/*.{ts,tsx}',
|
|
590
|
-
'./lib/**/*.{ts,tsx}',
|
|
591
|
-
'./node_modules/forlogic-core/dist/**/*.{js,ts,jsx,tsx}',
|
|
592
|
-
]
|
|
593
|
-
```
|
|
594
|
-
|
|
595
|
-
---
|
|
596
|
-
|
|
597
|
-
### 📋 Checklist de Configuração
|
|
598
|
-
|
|
599
|
-
```markdown
|
|
600
|
-
- [ ] Instalou `forlogic-core` no projeto?
|
|
601
|
-
- [ ] Configurou `vite.config.ts` com `createSecurityHeadersPlugin`?
|
|
602
|
-
- [ ] Adicionou URLs do Supabase em `supabaseUrls`?
|
|
603
|
-
- [ ] Configurou `tailwind.config.ts` com `forlogicTailwindPreset`?
|
|
604
|
-
- [ ] Adicionou `forlogicContentPaths` ao content?
|
|
605
|
-
- [ ] Definiu variáveis CSS no `index.css` (--primary, --background, etc.)?
|
|
606
|
-
```
|
|
607
|
-
|
|
608
239
|
---
|
|
609
240
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
Para projetos que estão **publicando** a `forlogic-core`, adicione os exports condicionais:
|
|
613
|
-
|
|
614
|
-
```json
|
|
615
|
-
{
|
|
616
|
-
"exports": {
|
|
617
|
-
".": {
|
|
618
|
-
"import": "./dist/index.esm.js",
|
|
619
|
-
"require": "./dist/index.js",
|
|
620
|
-
"types": "./dist/index.d.ts"
|
|
621
|
-
},
|
|
622
|
-
"./vite": {
|
|
623
|
-
"import": "./dist/vite/index.esm.js",
|
|
624
|
-
"require": "./dist/vite/index.js",
|
|
625
|
-
"types": "./dist/vite/index.d.ts"
|
|
626
|
-
},
|
|
627
|
-
"./tailwind": {
|
|
628
|
-
"import": "./dist/tailwind/index.esm.js",
|
|
629
|
-
"require": "./dist/tailwind/index.js",
|
|
630
|
-
"types": "./dist/tailwind/index.d.ts"
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
---
|
|
637
|
-
|
|
638
|
-
## 🚩 Feature Flags (Variáveis de Ambiente)
|
|
639
|
-
|
|
640
|
-
A biblioteca suporta feature flags para habilitar/desabilitar funcionalidades opcionais.
|
|
641
|
-
|
|
642
|
-
### Variáveis Disponíveis
|
|
643
|
-
|
|
644
|
-
| Variável | Descrição | Valores | Padrão |
|
|
645
|
-
| ---------------------------- | ------------------------------------------------------------------------------------ | -------------------- | --------- |
|
|
646
|
-
| `VITE_SHOW_USER_PREFERENCES` | Exibe opção de "Preferências" no menu do usuário (idioma, timezone, formato de data) | `"true"` / `"false"` | Não exibe |
|
|
647
|
-
| `VITE_I18N_DEBUG_MODE` | Modo debug de internacionalização (mostra chaves ao invés de traduções) | `"true"` / `"false"` | `"false"` |
|
|
648
|
-
| `VITE_IS_QUALIEX` | Define se usa logos Qualiex ou Forlogic | `"true"` / `"false"` | `"false"` |
|
|
649
|
-
|
|
650
|
-
### Configuração
|
|
651
|
-
|
|
652
|
-
Adicione no seu arquivo `.env`:
|
|
653
|
-
|
|
654
|
-
```env
|
|
655
|
-
# Habilitar opção de preferências no perfil do usuário
|
|
656
|
-
VITE_SHOW_USER_PREFERENCES=true
|
|
657
|
-
|
|
658
|
-
# Modo debug de i18n (mostra chaves com ícones)
|
|
659
|
-
VITE_I18N_DEBUG_MODE=false
|
|
660
|
-
|
|
661
|
-
# Usar logos Qualiex
|
|
662
|
-
VITE_IS_QUALIEX=true
|
|
663
|
-
```
|
|
664
|
-
|
|
665
|
-
> **Nota**: Variáveis de ambiente em Vite precisam ter o prefixo `VITE_` para serem expostas ao cliente.
|
|
666
|
-
|
|
667
|
-
---
|
|
668
|
-
|
|
669
|
-
## 🌐 Setup de Traduções para Projetos Consumidores
|
|
670
|
-
|
|
671
|
-
O sistema de i18n usa **namespaces**: a lib fornece traduções base no namespace `core` e cada projeto injeta suas traduções no namespace `app`. A resolução é: `app` → `core` → fallback `pt-BR`.
|
|
672
|
-
|
|
673
|
-
### Requisitos
|
|
674
|
-
|
|
675
|
-
| Requisito | Descrição |
|
|
676
|
-
| ------------------ | ----------------------------------------- |
|
|
677
|
-
| `i18next` | Peer dependency instalada |
|
|
678
|
-
| `react-i18next` | Peer dependency instalada |
|
|
679
|
-
| `CoreProviders` | Wrapper no App.tsx |
|
|
680
|
-
|
|
681
|
-
### Passo 1: Instalar Peer Dependencies
|
|
682
|
-
|
|
683
|
-
```bash
|
|
684
|
-
npm install i18next@^25.0.0 react-i18next@^16.0.0
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
### Passo 2: Criar JSONs de Tradução do Projeto
|
|
688
|
-
|
|
689
|
-
Crie arquivos JSON flat (um por idioma) com as traduções específicas do seu projeto:
|
|
690
|
-
|
|
691
|
-
```json
|
|
692
|
-
// src/i18n/pt-BR.json
|
|
693
|
-
{
|
|
694
|
-
"objective": "Objetivo",
|
|
695
|
-
"key_result": "Resultado-chave",
|
|
696
|
-
"cycle": "Ciclo"
|
|
697
|
-
}
|
|
698
|
-
```
|
|
699
|
-
|
|
700
|
-
### Passo 3: Passar para CoreProviders via `appTranslations`
|
|
241
|
+
## 10. Configuração — CoreProviders
|
|
701
242
|
|
|
702
243
|
```tsx
|
|
703
|
-
// src/App.tsx
|
|
704
244
|
import { CoreProviders } from 'forlogic-core';
|
|
705
|
-
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
706
245
|
import ptBR from './i18n/pt-BR.json';
|
|
707
|
-
// import enUS from './i18n/en-US.json'; // quando tiver
|
|
708
246
|
|
|
709
247
|
function App() {
|
|
710
248
|
return (
|
|
711
|
-
<CoreProviders
|
|
712
|
-
|
|
713
|
-
appTranslations={{
|
|
714
|
-
'pt-BR': ptBR,
|
|
715
|
-
// 'en-US': enUS,
|
|
716
|
-
}}
|
|
717
|
-
>
|
|
718
|
-
<BrowserRouter>
|
|
719
|
-
<Routes>
|
|
720
|
-
{/* Suas rotas */}
|
|
721
|
-
</Routes>
|
|
722
|
-
</BrowserRouter>
|
|
249
|
+
<CoreProviders moduleAlias="seu-modulo" appTranslations={{ 'pt-BR': ptBR }}>
|
|
250
|
+
<BrowserRouter><Routes>{/* ... */}</Routes></BrowserRouter>
|
|
723
251
|
</CoreProviders>
|
|
724
252
|
);
|
|
725
253
|
}
|
|
726
|
-
|
|
727
|
-
export default App;
|
|
728
254
|
```
|
|
729
255
|
|
|
730
|
-
###
|
|
731
|
-
|
|
732
|
-
```tsx
|
|
733
|
-
// ❌ ERRADO - Cria instância separada (erro NO_I18NEXT_INSTANCE)
|
|
734
|
-
import { useTranslation } from 'react-i18next';
|
|
735
|
-
|
|
736
|
-
// ✅ CORRETO - Usa mesma instância configurada
|
|
737
|
-
import { useTranslation } from 'forlogic-core';
|
|
738
|
-
|
|
739
|
-
function MeuComponente() {
|
|
740
|
-
const { t } = useTranslation();
|
|
741
|
-
return (
|
|
742
|
-
<div>
|
|
743
|
-
<h1>{t('objective')}</h1> {/* namespace app → "Objetivo" */}
|
|
744
|
-
<Button>{t('save')}</Button> {/* app → não encontra → core → "Salvar" */}
|
|
745
|
-
</div>
|
|
746
|
-
);
|
|
747
|
-
}
|
|
748
|
-
```
|
|
749
|
-
|
|
750
|
-
### Como funciona a resolução de namespaces
|
|
751
|
-
|
|
752
|
-
```
|
|
753
|
-
t('save')
|
|
754
|
-
1. Busca em namespace 'app' (projeto) → não encontrou
|
|
755
|
-
2. Busca em namespace 'core' (lib) → "Salvar" ✅
|
|
756
|
-
|
|
757
|
-
t('objective')
|
|
758
|
-
1. Busca em namespace 'app' (projeto) → "Objetivo" ✅
|
|
759
|
-
|
|
760
|
-
t('save') com override no app
|
|
761
|
-
1. Busca em namespace 'app' → "Gravar" ✅ (sobrescreve o core)
|
|
762
|
-
```
|
|
763
|
-
|
|
764
|
-
### Troubleshooting
|
|
765
|
-
|
|
766
|
-
#### Traduções mostram apenas as chaves
|
|
767
|
-
|
|
768
|
-
| Causa | Solução |
|
|
769
|
-
| ------------------------------------ | ------------------------------------------------------ |
|
|
770
|
-
| Peer dependencies faltando | Instalar `i18next` e `react-i18next` |
|
|
771
|
-
| Import de `react-i18next` direto | Usar import de `forlogic-core` |
|
|
772
|
-
| `appTranslations` não passado | Adicionar prop no `CoreProviders` |
|
|
773
|
-
| JSON com formato errado | Deve ser flat: `{ "key": "value" }`, sem nesting |
|
|
774
|
-
|
|
775
|
-
#### Debug: Verificar se traduções foram carregadas
|
|
776
|
-
|
|
777
|
-
```tsx
|
|
778
|
-
import { i18n } from 'forlogic-core';
|
|
779
|
-
|
|
780
|
-
console.log('i18n initialized:', i18n.isInitialized);
|
|
781
|
-
console.log('Current language:', i18n.language);
|
|
782
|
-
console.log('Loaded resources:', i18n.store.data);
|
|
783
|
-
// Deve mostrar: { 'pt-BR': { core: {...}, app: {...} } }
|
|
784
|
-
```
|
|
785
|
-
|
|
786
|
-
### Checklist de Configuração
|
|
787
|
-
|
|
788
|
-
```markdown
|
|
789
|
-
- [ ] Instalou `i18next@^25.0.0` e `react-i18next@^16.0.0`?
|
|
790
|
-
- [ ] Criou JSONs de tradução em `src/i18n/pt-BR.json`?
|
|
791
|
-
- [ ] Passou `appTranslations` para o `CoreProviders`?
|
|
792
|
-
- [ ] Todos os imports de `useTranslation` são de `forlogic-core` (nunca de `react-i18next`)?
|
|
793
|
-
- [ ] O `App.tsx` usa `CoreProviders`?
|
|
794
|
-
```
|
|
256
|
+
### i18n — Resolução: `t('key')` → app → core → fallback
|
|
795
257
|
|
|
796
258
|
---
|
|
797
259
|
|
|
798
|
-
##
|
|
799
|
-
|
|
800
|
-
O `CoreProviders` é um componente que encapsula todos os providers essenciais da biblioteca, simplificando drasticamente a configuração de novos projetos.
|
|
801
|
-
|
|
802
|
-
### O que está incluído
|
|
260
|
+
## 11. Feature Flags
|
|
803
261
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
|
807
|
-
|
|
|
808
|
-
| `
|
|
809
|
-
| `I18nextProvider` | Sistema de internacionalização (i18n) |
|
|
810
|
-
| `QueryClientProvider` | Cache e gerenciamento de queries (React Query) |
|
|
811
|
-
| `AuthProvider` | Autenticação e gerenciamento de sessão |
|
|
812
|
-
| `LocaleProvider` | Gerenciamento de locale (idioma, timezone, formato de data) |
|
|
813
|
-
| `TranslationLoader` | Carregamento dinâmico de traduções do banco de dados |
|
|
814
|
-
|
|
815
|
-
### Uso Básico
|
|
816
|
-
|
|
817
|
-
```tsx
|
|
818
|
-
import { CoreProviders } from 'forlogic-core';
|
|
819
|
-
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
820
|
-
|
|
821
|
-
function App() {
|
|
822
|
-
return (
|
|
823
|
-
<CoreProviders>
|
|
824
|
-
<BrowserRouter>
|
|
825
|
-
<Routes>
|
|
826
|
-
{/* Suas rotas aqui */}
|
|
827
|
-
</Routes>
|
|
828
|
-
</BrowserRouter>
|
|
829
|
-
</CoreProviders>
|
|
830
|
-
);
|
|
831
|
-
}
|
|
832
|
-
```
|
|
833
|
-
|
|
834
|
-
### Com QueryClient Customizado
|
|
835
|
-
|
|
836
|
-
Se você precisar de configurações específicas para o React Query:
|
|
837
|
-
|
|
838
|
-
```tsx
|
|
839
|
-
import { CoreProviders } from 'forlogic-core';
|
|
840
|
-
import { QueryClient } from '@tanstack/react-query';
|
|
841
|
-
import { BrowserRouter } from 'react-router-dom';
|
|
842
|
-
|
|
843
|
-
const queryClient = new QueryClient({
|
|
844
|
-
defaultOptions: {
|
|
845
|
-
queries: {
|
|
846
|
-
staleTime: 10 * 60 * 1000, // 10 minutos
|
|
847
|
-
retry: 2,
|
|
848
|
-
refetchOnWindowFocus: false,
|
|
849
|
-
},
|
|
850
|
-
},
|
|
851
|
-
});
|
|
852
|
-
|
|
853
|
-
function App() {
|
|
854
|
-
return (
|
|
855
|
-
<CoreProviders queryClient={queryClient}>
|
|
856
|
-
<BrowserRouter>
|
|
857
|
-
{/* Suas rotas */}
|
|
858
|
-
</BrowserRouter>
|
|
859
|
-
</CoreProviders>
|
|
860
|
-
);
|
|
861
|
-
}
|
|
862
|
-
```
|
|
863
|
-
|
|
864
|
-
### Props
|
|
865
|
-
|
|
866
|
-
| Prop | Tipo | Obrigatório | Descrição |
|
|
867
|
-
| ------------- | ------------- | ----------- | --------------------------------------------------------------------------- |
|
|
868
|
-
| `children` | `ReactNode` | ✅ | Componentes filhos a serem envolvidos |
|
|
869
|
-
| `queryClient` | `QueryClient` | ❌ | Instância customizada do QueryClient. Se não fornecido, um default é criado |
|
|
870
|
-
|
|
871
|
-
### QueryClient Default
|
|
872
|
-
|
|
873
|
-
Se você não fornecer um `queryClient`, o `CoreProviders` cria um com as seguintes configurações:
|
|
874
|
-
|
|
875
|
-
```typescript
|
|
876
|
-
{
|
|
877
|
-
defaultOptions: {
|
|
878
|
-
queries: {
|
|
879
|
-
staleTime: 5 * 60 * 1000, // 5 minutos
|
|
880
|
-
retry: 1,
|
|
881
|
-
},
|
|
882
|
-
},
|
|
883
|
-
}
|
|
884
|
-
```
|
|
885
|
-
|
|
886
|
-
### Benefícios
|
|
887
|
-
|
|
888
|
-
- ✅ **Zero configuração de i18n** - Traduções funcionam automaticamente
|
|
889
|
-
- ✅ **Autenticação pronta** - `useAuth()` disponível em qualquer componente filho
|
|
890
|
-
- ✅ **Tratamento de erros** - ErrorBoundary captura erros de renderização
|
|
891
|
-
- ✅ **React Query configurado** - Cache e queries prontos para uso
|
|
892
|
-
- ✅ **Locale gerenciado** - Preferências de idioma, timezone e formato de data
|
|
893
|
-
- ✅ **Atualizações centralizadas** - Novos providers são adicionados automaticamente
|
|
262
|
+
| Variável | Descrição |
|
|
263
|
+
|----------|-----------|
|
|
264
|
+
| `VITE_SHOW_USER_PREFERENCES` | Preferências no menu do usuário |
|
|
265
|
+
| `VITE_I18N_DEBUG_MODE` | Debug de i18n (mostra chaves) |
|
|
266
|
+
| `VITE_IS_QUALIEX` | Logos Qualiex vs Forlogic |
|
|
894
267
|
|
|
895
268
|
---
|
|
896
269
|
|
|
897
|
-
##
|
|
898
|
-
|
|
899
|
-
O `SidebarActionTrigger` permite adicionar ações principais de módulo no sidebar, diferenciadas visualmente da navegação. São gatilhos de ação, não destinos de navegação.
|
|
900
|
-
|
|
901
|
-
### Conceito
|
|
902
|
-
|
|
903
|
-
| Característica | Descrição |
|
|
904
|
-
| ------------------- | ----------------------------------------------------------- |
|
|
905
|
-
| **Ação de módulo** | Válida apenas dentro do contexto do módulo ao qual pertence |
|
|
906
|
-
| **Não global** | Não aplicável a todo o sistema |
|
|
907
|
-
| **Não contextual** | Não depende de seleção de item específico |
|
|
908
|
-
| **Destaque visual** | Exibida com aparência diferenciada da navegação |
|
|
909
|
-
|
|
910
|
-
### Uso Básico
|
|
911
|
-
|
|
912
|
-
```tsx
|
|
913
|
-
import { AppSidebar, SidebarConfig } from 'forlogic-core';
|
|
914
|
-
import { Plus, FileText, Folder } from 'lucide-react';
|
|
915
|
-
|
|
916
|
-
const sidebarConfig: SidebarConfig = {
|
|
917
|
-
appName: 'Meu Módulo',
|
|
918
|
-
|
|
919
|
-
// Ações principais do módulo
|
|
920
|
-
moduleActions: {
|
|
921
|
-
triggerLabel: 'Criar',
|
|
922
|
-
triggerIcon: Plus,
|
|
923
|
-
actions: [
|
|
924
|
-
{
|
|
925
|
-
id: 'create-item',
|
|
926
|
-
label: 'Novo Item',
|
|
927
|
-
icon: FileText,
|
|
928
|
-
onClick: () => openCreateDialog()
|
|
929
|
-
},
|
|
930
|
-
{
|
|
931
|
-
id: 'create-folder',
|
|
932
|
-
label: 'Nova Pasta',
|
|
933
|
-
icon: Folder,
|
|
934
|
-
onClick: () => openFolderDialog()
|
|
935
|
-
},
|
|
936
|
-
]
|
|
937
|
-
},
|
|
938
|
-
|
|
939
|
-
// Navegação
|
|
940
|
-
navigation: [
|
|
941
|
-
{ label: 'Visão Geral', path: '/', icon: Home },
|
|
942
|
-
{ label: 'Configurações', path: '/settings', icon: Settings },
|
|
943
|
-
]
|
|
944
|
-
};
|
|
945
|
-
|
|
946
|
-
<AppSidebar config={sidebarConfig} />
|
|
947
|
-
```
|
|
270
|
+
## 12. Instrução para IA
|
|
948
271
|
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
| Cenário | Comportamento |
|
|
952
|
-
| --------------------- | --------------------------------- |
|
|
953
|
-
| **Uma ação** | Clique executa a ação diretamente |
|
|
954
|
-
| **Múltiplas ações** | Clique exibe dropdown com opções |
|
|
955
|
-
| **Modal aberto** | Gatilho fica desabilitado |
|
|
956
|
-
| **Sidebar colapsada** | Exibe apenas ícone com tooltip |
|
|
957
|
-
|
|
958
|
-
### Props do SidebarActionTrigger
|
|
959
|
-
|
|
960
|
-
| Prop | Tipo | Obrigatório | Descrição |
|
|
961
|
-
| ------------- | ---------------------- | ----------- | --------------------------- |
|
|
962
|
-
| `config` | `SidebarActionsConfig` | ✅ | Configuração das ações |
|
|
963
|
-
| `isCollapsed` | `boolean` | ❌ | Se a sidebar está colapsada |
|
|
964
|
-
| `isDisabled` | `boolean` | ❌ | Desabilita o gatilho |
|
|
965
|
-
|
|
966
|
-
### Interface SidebarModuleAction
|
|
967
|
-
|
|
968
|
-
```typescript
|
|
969
|
-
interface SidebarModuleAction {
|
|
970
|
-
id: string; // Identificador único
|
|
971
|
-
label: string; // Texto do botão/opção
|
|
972
|
-
icon?: LucideIcon; // Ícone opcional
|
|
973
|
-
onClick: () => void; // Callback de execução
|
|
974
|
-
disabled?: boolean; // Estado desabilitado
|
|
975
|
-
permissionCheck?: () => Promise<boolean>;
|
|
976
|
-
}
|
|
977
|
-
```
|
|
272
|
+
**QUANDO** criar ou modificar qualquer arquivo `.tsx` com JSX:
|
|
978
273
|
|
|
979
|
-
|
|
274
|
+
- **SE** contém tabela, listagem ou CRUD → **LER** `@Admin docs/design-system/crud.md` e `@Admin docs/design-system/tables-grids.md` ANTES de gerar código
|
|
275
|
+
- **SE** contém formulário, input ou campo → **LER** `@Admin docs/design-system/inputs.md` e `@Admin docs/design-system/selectors.md` ANTES
|
|
276
|
+
- **SE** contém modal ou confirmação → **LER** `@Admin docs/design-system/dialogs.md` ANTES
|
|
277
|
+
- **SE** contém botões ou ações de linha → **LER** `@Admin docs/design-system/buttons-actions.md` ANTES
|
|
278
|
+
- **SE** é estrutura de página/layout → **LER** `@Admin docs/design-system/layout.md` ANTES
|
|
980
279
|
|
|
981
|
-
|
|
982
|
-
interface SidebarActionsConfig {
|
|
983
|
-
triggerLabel?: string; // Rótulo do gatilho (padrão: 'Criar')
|
|
984
|
-
triggerIcon?: LucideIcon; // Ícone do gatilho (padrão: Plus)
|
|
985
|
-
actions: SidebarModuleAction[];
|
|
986
|
-
}
|
|
987
|
-
```
|
|
280
|
+
**SEMPRE** consultar `@Admin docs/design-system/examples.md` como referência de implementação.
|
|
988
281
|
|
|
989
|
-
|
|
282
|
+
**PROIBIDO** gerar JSX sem ter lido a documentação aplicável acima.
|
|
990
283
|
|
|
991
|
-
|
|
284
|
+
**VALIDAÇÃO pós-geração**: Todo import de componente visual DEVE vir de `forlogic-core`. Se criou componente local que existe na lib, refatore imediatamente.
|
|
992
285
|
|
|
993
|
-
|
|
994
|
-
import { CoreProviders, ModalStateProvider, useModalState } from 'forlogic-core';
|
|
995
|
-
|
|
996
|
-
// No App.tsx (opcional - CoreProviders não inclui por padrão)
|
|
997
|
-
<CoreProviders>
|
|
998
|
-
<ModalStateProvider>
|
|
999
|
-
<AppLayout />
|
|
1000
|
-
</ModalStateProvider>
|
|
1001
|
-
</CoreProviders>
|
|
1002
|
-
|
|
1003
|
-
// Em componentes com modal
|
|
1004
|
-
function MeuDialog({ open, onOpenChange }) {
|
|
1005
|
-
const { registerModal, unregisterModal } = useModalState();
|
|
1006
|
-
|
|
1007
|
-
useEffect(() => {
|
|
1008
|
-
if (open) {
|
|
1009
|
-
registerModal('meu-dialog');
|
|
1010
|
-
} else {
|
|
1011
|
-
unregisterModal('meu-dialog');
|
|
1012
|
-
}
|
|
1013
|
-
}, [open]);
|
|
1014
|
-
|
|
1015
|
-
return <Dialog open={open} onOpenChange={onOpenChange}>...</Dialog>;
|
|
1016
|
-
}
|
|
1017
|
-
```
|
|
1018
|
-
|
|
1019
|
-
### Diretriz para Uso via Prompt
|
|
1020
|
-
|
|
1021
|
-
#### ✅ Prompts corretos:
|
|
1022
|
-
|
|
1023
|
-
- "Adicione uma ação principal 'Criar Processo' no sidebar do módulo"
|
|
1024
|
-
- "Configure o módulo para ter duas ações principais: 'Novo Item' e 'Nova Pasta'"
|
|
1025
|
-
- "Adicione o botão de criar no topo do sidebar como ação de módulo"
|
|
1026
|
-
|
|
1027
|
-
#### ❌ Prompts ambíguos (evitar):
|
|
1028
|
-
|
|
1029
|
-
- "Coloque um botão de criar no menu" (ambíguo - qual menu?)
|
|
1030
|
-
- "Adicione navegação para criar" (ação ≠ navegação)
|
|
1031
|
-
- "Crie um link para nova entidade" (link = navegação, não ação)
|
|
286
|
+
---
|
|
1032
287
|
|
|
1033
|
-
|
|
288
|
+
## 13. Fontes de Contexto (Cross-Project)
|
|
289
|
+
|
|
290
|
+
| O que | Onde buscar via `@Admin` |
|
|
291
|
+
|-------|--------------------------|
|
|
292
|
+
| Props e tipos de componentes | `lib/components/ui/<componente>.tsx` |
|
|
293
|
+
| Implementação CRUD | `lib/crud/` |
|
|
294
|
+
| Documentação MD (para IA) | `docs/design-system/*.md` |
|
|
295
|
+
| Exemplos interativos (código) | `src/design-system/docs/*Doc.tsx` |
|
|
296
|
+
| Design System visual | Rota `/ds` no app Admin |
|
|
297
|
+
| Hooks compartilhados | `lib/hooks/` |
|
|
298
|
+
| Configuração de exports | `lib/exports/` |
|
|
299
|
+
| Prompt template | `docs/PROMPT_TEMPLATE.md` |
|
|
300
|
+
| Project Knowledge template | `docs/PROJECT_KNOWLEDGE_TEMPLATE.md` |
|
|
301
|
+
| Starter template | `docs/STARTER_TEMPLATE.md` |
|
|
302
|
+
| Prompt de auditoria | `docs/AUDIT_PROMPT.md` |
|
|
303
|
+
| Golden snippets | `docs/design-system/examples.md` |
|