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