@snksergio/design-system 0.62.0 → 0.63.0
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-lib/ai/blocos/chart/budget-breakdown.tsx +174 -0
- package/dist-lib/ai/blocos/indice.md +43 -0
- package/dist-lib/ai/blocos/paneldetail/detalhe-com-tabela.tsx +450 -0
- package/dist-lib/ai/blocos/paneldetail/detalhe-de-tarefa-com-abas.tsx +570 -0
- package/dist-lib/ai/blocos/paneldetail/detalhe-do-registro.tsx +555 -0
- package/dist-lib/ai/exemplos/app-shell/app-shell-example.tsx +140 -0
- package/dist-lib/ai/exemplos/app-shell/index.ts +3 -0
- package/dist-lib/ai/exemplos/app-shell/nav-data.ts +97 -0
- package/dist-lib/ai/exemplos/app-shell/routes.tsx +75 -0
- package/dist-lib/ai/exemplos/chat/chat-screen.tsx +152 -0
- package/dist-lib/ai/exemplos/chat/chat-v2-mocks.ts +171 -0
- package/dist-lib/ai/exemplos/chat/chat-v2.styles.ts +23 -0
- package/dist-lib/ai/exemplos/chat/chat-v2.types.ts +81 -0
- package/dist-lib/ai/exemplos/chat/components/ChannelDot/channel-dot.tsx +28 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationActionsMenu/conversation-actions-menu.tsx +83 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationActionsMenu/index.ts +4 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.styles.ts +22 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.tsx +203 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.types.ts +10 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationColumn/index.ts +2 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.styles.ts +55 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.tsx +52 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.types.ts +7 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationListItem/index.ts +2 -0
- package/dist-lib/ai/exemplos/chat/components/DateSeparator/date-separator.tsx +18 -0
- package/dist-lib/ai/exemplos/chat/components/DetailField/detail-field.tsx +23 -0
- package/dist-lib/ai/exemplos/chat/components/DetailSection/detail-section.tsx +41 -0
- package/dist-lib/ai/exemplos/chat/components/DetailSection/index.ts +1 -0
- package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.styles.ts +30 -0
- package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.tsx +142 -0
- package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.types.ts +16 -0
- package/dist-lib/ai/exemplos/chat/components/DetailsColumn/index.ts +5 -0
- package/dist-lib/ai/exemplos/chat/components/FilterRow/filter-row.styles.ts +37 -0
- package/dist-lib/ai/exemplos/chat/components/FilterRow/filter-row.tsx +45 -0
- package/dist-lib/ai/exemplos/chat/components/FilterRow/index.ts +1 -0
- package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.styles.ts +27 -0
- package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.tsx +66 -0
- package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.types.ts +13 -0
- package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-rail.tsx +38 -0
- package/dist-lib/ai/exemplos/chat/components/FiltersColumn/index.ts +6 -0
- package/dist-lib/ai/exemplos/chat/components/MessageBubble/index.ts +2 -0
- package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.styles.ts +37 -0
- package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.tsx +29 -0
- package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.types.ts +5 -0
- package/dist-lib/ai/exemplos/chat/components/PersonAvatar/index.ts +5 -0
- package/dist-lib/ai/exemplos/chat/components/PersonAvatar/person-avatar.tsx +31 -0
- package/dist-lib/ai/exemplos/chat/components/QueueColumn/index.ts +2 -0
- package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.styles.ts +19 -0
- package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.tsx +140 -0
- package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.types.ts +13 -0
- package/dist-lib/ai/exemplos/chat/components/RailItem/index.ts +1 -0
- package/dist-lib/ai/exemplos/chat/components/RailItem/rail-item.styles.ts +30 -0
- package/dist-lib/ai/exemplos/chat/components/RailItem/rail-item.tsx +42 -0
- package/dist-lib/ai/exemplos/chat/hooks/use-resizable.ts +98 -0
- package/dist-lib/ai/exemplos/chat/index.ts +1 -0
- package/dist-lib/ai/exemplos/clientes/_table-data.ts +59 -0
- package/dist-lib/ai/exemplos/clientes/clientes-screen.tsx +505 -0
- package/dist-lib/ai/exemplos/clientes/clientes-showcase-mocks.ts +117 -0
- package/dist-lib/ai/exemplos/clientes/clientes-showcase.styles.ts +13 -0
- package/dist-lib/ai/exemplos/clientes/clientes-showcase.types.ts +16 -0
- package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.styles.ts +28 -0
- package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.tsx +303 -0
- package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.types.ts +14 -0
- package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/index.ts +2 -0
- package/dist-lib/ai/exemplos/clientes/components/NovoClienteDrawer/index.ts +2 -0
- package/dist-lib/ai/exemplos/clientes/components/NovoClienteDrawer/novo-cliente-drawer.tsx +207 -0
- package/dist-lib/ai/exemplos/clientes/index.ts +1 -0
- package/dist-lib/ai/exemplos/edit-page/components/StepNav.tsx +81 -0
- package/dist-lib/ai/exemplos/edit-page/components/section-card.tsx +85 -0
- package/dist-lib/ai/exemplos/edit-page/edit-page-screen.tsx +234 -0
- package/dist-lib/ai/exemplos/edit-page/index.ts +1 -0
- package/dist-lib/ai/exemplos/finance/_table-data.ts +57 -0
- package/dist-lib/ai/exemplos/finance/clientes-financeiro-mocks.ts +227 -0
- package/dist-lib/ai/exemplos/finance/clientes-financeiro.types.ts +75 -0
- package/dist-lib/ai/exemplos/finance/clientes-showcase-mocks.ts +117 -0
- package/dist-lib/ai/exemplos/finance/clientes-showcase.styles.ts +13 -0
- package/dist-lib/ai/exemplos/finance/clientes-showcase.types.ts +16 -0
- package/dist-lib/ai/exemplos/finance/components/EditarFinanceDrawer/editar-finance-drawer.tsx +241 -0
- package/dist-lib/ai/exemplos/finance/components/EditarFinanceDrawer/index.ts +5 -0
- package/dist-lib/ai/exemplos/finance/components/ExtratoExpansion/extrato-expansion.tsx +172 -0
- package/dist-lib/ai/exemplos/finance/components/ExtratoExpansion/index.ts +1 -0
- package/dist-lib/ai/exemplos/finance/components/FinanceDetailPanel/finance-detail-panel.tsx +241 -0
- package/dist-lib/ai/exemplos/finance/components/FinanceDetailPanel/index.ts +2 -0
- package/dist-lib/ai/exemplos/finance/components/NovoClienteDrawer/index.ts +2 -0
- package/dist-lib/ai/exemplos/finance/components/NovoClienteDrawer/novo-cliente-drawer.tsx +207 -0
- package/dist-lib/ai/exemplos/finance/components/SacarDialog/index.ts +2 -0
- package/dist-lib/ai/exemplos/finance/components/SacarDialog/sacar-dialog.tsx +346 -0
- package/dist-lib/ai/exemplos/finance/finance-screen.tsx +821 -0
- package/dist-lib/ai/exemplos/finance/index.ts +1 -0
- package/dist-lib/ai/exemplos/gantt/_gantt-data.tsx +402 -0
- package/dist-lib/ai/exemplos/gantt/gantt-screen.tsx +512 -0
- package/dist-lib/ai/exemplos/gantt/index.ts +1 -0
- package/dist-lib/ai/exemplos/login/index.ts +1 -0
- package/dist-lib/ai/exemplos/login/login-screen.tsx +246 -0
- package/dist-lib/ai/exemplos/mapa-rede/components/ConsultorDetailPanel/consultor-detail-panel.tsx +158 -0
- package/dist-lib/ai/exemplos/mapa-rede/components/ConsultorDetailPanel/index.ts +2 -0
- package/dist-lib/ai/exemplos/mapa-rede/index.ts +1 -0
- package/dist-lib/ai/exemplos/mapa-rede/mapa-de-rede-mocks.ts +655 -0
- package/dist-lib/ai/exemplos/mapa-rede/mapa-de-rede.types.ts +53 -0
- package/dist-lib/ai/exemplos/mapa-rede/mapa-rede-screen.tsx +227 -0
- package/dist-lib/ai/exemplos/order-detail/components/ActivityTab.tsx +77 -0
- package/dist-lib/ai/exemplos/order-detail/components/AttachmentsTab.tsx +45 -0
- package/dist-lib/ai/exemplos/order-detail/components/CommentsTab.tsx +111 -0
- package/dist-lib/ai/exemplos/order-detail/components/DetailsTab.tsx +189 -0
- package/dist-lib/ai/exemplos/order-detail/components/OverviewTab.tsx +200 -0
- package/dist-lib/ai/exemplos/order-detail/components/section-card.tsx +85 -0
- package/dist-lib/ai/exemplos/order-detail/index.ts +1 -0
- package/dist-lib/ai/exemplos/order-detail/order-detail-screen.tsx +119 -0
- package/dist-lib/ai/exemplos/order-detail/order-mocks.ts +186 -0
- package/dist-lib/ai/exemplos/order-detail/order.types.ts +118 -0
- package/dist-lib/ai/indice.json +30 -15
- package/dist-lib/ai/manifest.json +31 -5
- package/dist-lib/ai/roteiros/app-builder/roteiro.md +155 -0
- package/dist-lib/ai/roteiros/auth-builder/roteiro.md +42 -0
- package/dist-lib/ai/roteiros/cards/roteiro.md +34 -0
- package/dist-lib/ai/roteiros/charts/roteiro.md +32 -0
- package/dist-lib/ai/roteiros/chat/roteiro.md +31 -0
- package/dist-lib/ai/roteiros/crud-builder/blueprint.md +63 -0
- package/dist-lib/ai/roteiros/crud-builder/entrevista.md +139 -0
- package/dist-lib/ai/roteiros/crud-builder/geracao.md +113 -0
- package/dist-lib/ai/roteiros/crud-builder/roteiro.md +89 -0
- package/dist-lib/ai/roteiros/drawers/roteiro.md +41 -0
- package/dist-lib/ai/roteiros/list-builder/blueprint.md +94 -0
- package/dist-lib/ai/roteiros/list-builder/entrevista.md +188 -0
- package/dist-lib/ai/roteiros/list-builder/geracao.md +63 -0
- package/dist-lib/ai/roteiros/list-builder/roteiro.md +91 -0
- package/dist-lib/ai/roteiros/module-replicator/roteiro.md +56 -0
- package/dist-lib/ai/roteiros/page-detail/roteiro.md +32 -0
- package/dist-lib/ai/roteiros/page-edit/roteiro.md +31 -0
- package/dist-lib/ai/roteiros/screen-composer/roteiro.md +95 -0
- package/package.json +1 -1
- /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/blueprint.md +0 -0
- /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/entrevista.md +0 -0
- /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/geracao.md +0 -0
- /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/roteiro.md +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
> **Nota de portabilidade.** Este roteiro foi extraído do pipeline do iGreen DS
|
|
2
|
+
> para Claude Code. Menções a slash command (`/ds-create-…`), a `.claude/` e a
|
|
3
|
+
> ferramentas daquele ambiente descrevem **como ele é acionado lá** — aqui o
|
|
4
|
+
> equivalente é carregar este roteiro pelo `indice.json`. O conteúdo de decisão
|
|
5
|
+
> (entrevista, blueprint, regras de composição) vale igual.
|
|
6
|
+
|
|
7
|
+
> **Modo submódulo (`ds-link`).** Existe `.claude/ds-config.json` com `"mode": "submodule"`?
|
|
8
|
+
> Então **NÃO rode `igreen:add`** — esse script não existe no seu projeto. Os componentes e
|
|
9
|
+
> exemplos já estão no disco em `<dsPath>/src`: importe pelo `importBase` do config
|
|
10
|
+
> (compostos) e pelo `primitivesBase` (primitivos shadcn), e **leia** o exemplo direto de
|
|
11
|
+
> `<dsPath>/src/examples/`.
|
|
12
|
+
|
|
13
|
+
# CRUD Builder — Blueprint [GATE]
|
|
14
|
+
|
|
15
|
+
Consolide a entrevista num preview ÚNICO e **pare** pra aprovação. Nenhuma edição
|
|
16
|
+
em disco antes do "aprovar".
|
|
17
|
+
|
|
18
|
+
## Apresente ao usuário
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
Entidade: <Nome> (tipo <NomeRow>)
|
|
22
|
+
Modo: client | server (endpoint: ...)
|
|
23
|
+
Onde: <PAGES_DIR>/<Arquivo>.tsx · registro: <REGISTRO>
|
|
24
|
+
Wrapper: AppShell + PageHeader | puro (chrome do print entregue? sim/não)
|
|
25
|
+
Colunas: <campo:tipo[:sortable][:editável]>, ... (primária: <campo>)
|
|
26
|
+
Busca/Filtros: busca=<sim/não> · filtros=<col:tipo, ...>
|
|
27
|
+
Ações linha: <editar, excluir(confirm AlertModal), ...> · seleção/bulk: <...>
|
|
28
|
+
Export: <não | escopo tudo/filtrado/selecionado · csv>
|
|
29
|
+
Views: presets=<nome → filtro>, ... · do usuário=<sim/não · savedViewsService+persistId>
|
|
30
|
+
Paginação/virt: <pageSize / virtualize> · totalizadores: <colunas>
|
|
31
|
+
Drawers: criar/editar=<sim/não> · campos=<campo:obrigatório?:máscara?> · detalhe=<sim/não>
|
|
32
|
+
Estados: loading=<skeleton> · vazio=<msg + CTA> · sem-resultado=<msg + limpar>
|
|
33
|
+
Kanban: <não | campo de agrupamento>
|
|
34
|
+
Componentes a puxar: data-table[, example-finance p/ drawers][, alert-modal p/ excluir][, ...]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## ⚠️ Decisões inferidas — vete se discordar
|
|
38
|
+
|
|
39
|
+
Depois do bloco acima, liste **só** o que o usuário não disse e você decidiu sozinho —
|
|
40
|
+
uma linha cada, com o que muda se ele vetar. Sem inferência → `nenhuma`; não apague a
|
|
41
|
+
seção: é a ausência dela que faz a decisão passar aprovada em pacote.
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
⚠️ Inferido (não perguntei):
|
|
45
|
+
• wrapper = puro → a tela nasce SEM rail/menu/header
|
|
46
|
+
• tema = light → a referência mostrava dark
|
|
47
|
+
• <coluna> = <tipo> → confiança baixa (inferido só pelo nome do campo)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Pré-validações (rode ANTES de pedir aprovação)
|
|
51
|
+
- Todo filtro tem operador compatível com o filterType (multiSelect⇒isAnyOf, text⇒contains, date⇒between, number⇒gte/lte/between, boolean⇒equals).
|
|
52
|
+
- `virtualize` ⇒ paginação off + container com altura. `groupBy`/kanban ⇒ paginação off.
|
|
53
|
+
- Kanban: cada lane mapeia uma option do campo de agrupamento.
|
|
54
|
+
- Coluna `actions` se há ações por linha; cada action tem `id` único.
|
|
55
|
+
- **Ação `destructive` (excluir) ⇒ tem `AlertModal` de confirmação no plano.**
|
|
56
|
+
- **Os 3 estados (loading/vazio/sem-resultado) estão definidos** (mesmo que com default).
|
|
57
|
+
- Nome/rota da página sem colisão.
|
|
58
|
+
|
|
59
|
+
Liste qualquer ajuste necessário. Só depois pergunte: **"Aprovar e gerar?"**
|
|
60
|
+
|
|
61
|
+
- `aprovar` → carregue `generate.md`.
|
|
62
|
+
- pedir mudança → ajuste o blueprint e reapresente.
|
|
63
|
+
- `cancelar` → encerre (zero edições).
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
> **Nota de portabilidade.** Este roteiro foi extraído do pipeline do iGreen DS
|
|
2
|
+
> para Claude Code. Menções a slash command (`/ds-create-…`), a `.claude/` e a
|
|
3
|
+
> ferramentas daquele ambiente descrevem **como ele é acionado lá** — aqui o
|
|
4
|
+
> equivalente é carregar este roteiro pelo `indice.json`. O conteúdo de decisão
|
|
5
|
+
> (entrevista, blueprint, regras de composição) vale igual.
|
|
6
|
+
|
|
7
|
+
> **Modo submódulo (`ds-link`).** Existe `.claude/ds-config.json` com `"mode": "submodule"`?
|
|
8
|
+
> Então **NÃO rode `igreen:add`** — esse script não existe no seu projeto. Os componentes e
|
|
9
|
+
> exemplos já estão no disco em `<dsPath>/src`: importe pelo `importBase` do config
|
|
10
|
+
> (compostos) e pelo `primitivesBase` (primitivos shadcn), e **leia** o exemplo direto de
|
|
11
|
+
> `<dsPath>/src/examples/`.
|
|
12
|
+
|
|
13
|
+
# CRUD Builder — Entrevista
|
|
14
|
+
|
|
15
|
+
Pergunte em fases, **uma pergunta de cada vez quando possível**, acumulando as
|
|
16
|
+
escolhas. NÃO edite arquivo nenhum aqui. Ao fim, vá pro `blueprint.md`.
|
|
17
|
+
|
|
18
|
+
## ⛔ Perguntas obrigatórias (NUNCA pular, mesmo que dê pra inferir)
|
|
19
|
+
|
|
20
|
+
A IA tende a inferir tudo e ir direto pro blueprint — **não faça isso**. Estas duas
|
|
21
|
+
são sempre explícitas:
|
|
22
|
+
|
|
23
|
+
1. **Colunas** — mesmo que dê pra inferir do nome da entidade, **LISTE** as colunas
|
|
24
|
+
inferidas (campo · rótulo · tipo) e **confirme** (adicionar/remover/reordenar) +
|
|
25
|
+
pergunte se **alguma tem particularidade** (ordenável, editável inline, alinhamento,
|
|
26
|
+
fixar/pin, largura, filtro, totalizador). Nunca gere com colunas só inferidas.
|
|
27
|
+
2. **Views salvas** — **sempre OFEREÇA e explique** (não trate como "off" silencioso):
|
|
28
|
+
|
|
29
|
+
> "Quer **views salvas**? São abas com filtros + ordenação + colunas/densidade
|
|
30
|
+
> pré-configurados (ex.: _Ativos_, _Alto valor_, _Atrasados_). O usuário troca de
|
|
31
|
+
> recorte num clique — sem precisar de uma tela nova pra cada um."
|
|
32
|
+
|
|
33
|
+
Pergunte quais (nome + filtro + sort). Default = nenhuma, **mas só depois de perguntar**.
|
|
34
|
+
|
|
35
|
+
## Fase 0 — Entidade & origem dos dados
|
|
36
|
+
|
|
37
|
+
- Qual entidade? (ex.: Clientes, Pedidos, Faturas) → vira o nome da tela/tipo.
|
|
38
|
+
- Dados **client-side** (array em memória/mock) ou **server-side** (fetch paginado da API)?
|
|
39
|
+
- Server: qual o endpoint/forma de buscar? (vira `fetchData` em `useCallback`).
|
|
40
|
+
- Onde a página vai morar e como registra a rota? (`PAGES_DIR`/`REGISTRO`).
|
|
41
|
+
|
|
42
|
+
## Fase 1 — Página e shell
|
|
43
|
+
|
|
44
|
+
| Pergunta | Default |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| Título da página | plural da entidade |
|
|
47
|
+
| Descrição (1-2 frases) | gerada do domínio, confirmar |
|
|
48
|
+
| **Wrapper** | ver abaixo |
|
|
49
|
+
| Onde mora + como registra a rota | `PAGES_DIR` / `REGISTRO` do seu projeto |
|
|
50
|
+
|
|
51
|
+
**Antes de perguntar o wrapper, VERIFIQUE** — as duas respostas costumam decidir sozinhas:
|
|
52
|
+
|
|
53
|
+
1. existe `AppShell` no projeto? (grep em `src/`)
|
|
54
|
+
2. a referência que o usuário deu — print, Figma, tela existente — mostra rail/menu/header?
|
|
55
|
+
|
|
56
|
+
- **`AppShell` + `PageHeader`** → chrome na referência **e** shell disponível. Sem perguntar.
|
|
57
|
+
- **componente puro** (no seu `PAGES_DIR`) → sem referência visual, ou app sem shell e sem
|
|
58
|
+
chrome na referência.
|
|
59
|
+
- **chrome na referência e SEM shell no projeto** → **pare e ofereça `/ds-create-app` junto**.
|
|
60
|
+
Se o usuário recusar, o blueprint diz em **linha destacada** o que do print não vai ser
|
|
61
|
+
entregue.
|
|
62
|
+
|
|
63
|
+
> Print de app inteiro + pedido de "uma tela" é **`shell + tela`**, não `tela`. Foi este
|
|
64
|
+
> recorte que fez uma tela nascer sem o menu que o print mostrava. A regra de o que é da
|
|
65
|
+
> referência e o que é do DS está em `_claude/rules/ds-design.md`.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Fase 2 — Colunas
|
|
70
|
+
|
|
71
|
+
Pra cada coluna: campo, rótulo, **tipo** (text, number, currency, percentage, date,
|
|
72
|
+
datetime, email, phone, url, status/badge, boolean, user, tags, actions), e se é
|
|
73
|
+
sortable / editável (inline). Pergunte quais colunas o usuário quer e em que ordem.
|
|
74
|
+
Marque a coluna "primária" (a que abre detalhe / leva avatar).
|
|
75
|
+
|
|
76
|
+
**`copyable` é inferido, não perguntado** — marque nas colunas cujo valor a pessoa
|
|
77
|
+
**cola em outro lugar** (documento, e-mail, telefone, conta/chave PIX, protocolo/NF/
|
|
78
|
+
rastreio, token, ID externo) e **só** nelas; nome, status, data, valor e quantidade
|
|
79
|
+
ficam de fora. Não abra pergunta própria pra isso: **declare** as colunas marcadas
|
|
80
|
+
quando apresentar a lista de colunas, junto do tipo e do filtro, pra o usuário tirar
|
|
81
|
+
em lote ("CNPJ sem copyable"). Critério completo e limites: `generate.md` item 4.
|
|
82
|
+
|
|
83
|
+
## Fase 3 — Busca, filtros & ações
|
|
84
|
+
|
|
85
|
+
> ⛔ **Anti-pattern — NUNCA gerar form/selects soltos ACIMA da tabela.** Intenção de
|
|
86
|
+
> "adicionar filtro" (select de status em cima, campo de período, "filtrar por X") →
|
|
87
|
+
> **sugira o padrão certo** (a tabela já filtra reativo, com chips clicáveis/editáveis):
|
|
88
|
+
>
|
|
89
|
+
> - **Filtro por COLUNA** (status/categoria/tipo/data…) → `enableColumnFilter` +
|
|
90
|
+
> `filterType`. Quer abrir já filtrado? **pré-aplique** (`defaultViews`/`presetView`
|
|
91
|
+
> ou `filterModel`) → abre com o **chip aplicado**, editável, reativo. Pode pré-setar
|
|
92
|
+
> **vários** (id/período/status/…), sem campos.
|
|
93
|
+
> - **toolbar.actions é SÓ pra caso pequeno e simples que NÃO reage com coluna** (ex.:
|
|
94
|
+
> data/período, escopo) — **label curta**, **máx ~2**. Se mexe com coluna, é grande, ou
|
|
95
|
+
> são muitos → **NÃO use o toolbar.**
|
|
96
|
+
> - **Muitos filtros, ou ligados a coluna** → SEMPRE os nativos **pré-aplicados** (chips no
|
|
97
|
+
> load) + drawer "Filtros". Nunca empilhar selects.
|
|
98
|
+
>
|
|
99
|
+
> Regra de ouro: **filtro é recurso da tabela (reativo), não UI montada na unha.**
|
|
100
|
+
|
|
101
|
+
- Busca global? (`enableSearch`)
|
|
102
|
+
- Filtros por coluna? **Default = TODAS as colunas de dados filtram** (`enableColumnFilter: true` + `filterType` por tipo) — pergunte só "alguma NÃO deve filtrar?". O funil/drawer só lista colunas com `enableColumnFilter`; marcar só 2 = bug. (Ver §Regras de coluna em `generate.md`.)
|
|
103
|
+
- Ações por linha (editar, excluir, ...)? (coluna `actions`, `getActions`) — vai por **último**; o DataTable ancora à direita/estreita sozinho (sem `pinned`/`width`). NÃO setar `width` nas demais (autoFit distribui).
|
|
104
|
+
**Toda ação destrutiva (Excluir) → confirmação OBRIGATÓRIA via `AlertModal`** (nunca
|
|
105
|
+
deletar direto). Pergunte o texto do confirm.
|
|
106
|
+
- Seleção + ações em massa (exportar, etc.)? (`selectionConfig` + bulk actions).
|
|
107
|
+
- Export: escopo (tudo / filtrado / selecionado) + formato (csv)? (`toolbar.enableExport`).
|
|
108
|
+
- Ação custom no toolbar (ex.: seletor de período/mês, botão extra)? `toolbar.actions: ToolbarAction[]` (`button`/`dropdown`/`input`) — inline no desktop, colapsa no ⋯ no mobile. Oferecer só se o usuário pedir.
|
|
109
|
+
|
|
110
|
+
## Fase 4 — Views, paginação & densidade
|
|
111
|
+
|
|
112
|
+
- Views (ver bloco obrigatório). Dois sabores, pergunte os dois:
|
|
113
|
+
- **Presets fixos** que VOCÊ define (`defaultViews`/`presetView`, ex.: "Ativos", "Alto valor").
|
|
114
|
+
- **Views do usuário**: ele cria/salva/persiste as próprias (`savedViewsService` + `persistId`).
|
|
115
|
+
- Paginação (tamanho inicial, opções) ou virtualização (10k+ linhas)?
|
|
116
|
+
- Totalizadores no rodapé? (`showTotalizers` + `aggregate`).
|
|
117
|
+
|
|
118
|
+
## Fase 5 — Criar/editar/detalhe (drawers)
|
|
119
|
+
|
|
120
|
+
- Precisa criar/editar registro? → drawer estilo `NovoClienteDrawer` (Panel + FormField).
|
|
121
|
+
- **Quais campos no form?** (default: espelha as colunas editáveis). Pra cada campo:
|
|
122
|
+
**obrigatório?** **máscara** (CNPJ / telefone / CEP / moeda)? **validação** (formato,
|
|
123
|
+
min/max)? Todo label via `<FormField>` (nunca `<label>` cru) + `gap-form-gap`.
|
|
124
|
+
- Precisa ver detalhe ao clicar na linha? → `FinanceDetailPanel` (FloatingPanel).
|
|
125
|
+
- (Puxar `example-finance` na geração pra reusar esses padrões.)
|
|
126
|
+
|
|
127
|
+
## Fase 6 — Kanban (opcional)
|
|
128
|
+
|
|
129
|
+
- Quer alternar tabela↔kanban? Se sim: qual campo agrupa as colunas (ex.: status)?
|
|
130
|
+
Cada lane = uma option desse campo. (`viewMode` controlado + `kanbanConfig`.)
|
|
131
|
+
|
|
132
|
+
## Fase 7 — Estados (SEMPRE perguntar — sai faltando se não)
|
|
133
|
+
|
|
134
|
+
- **Loading** (`loading` + `renderLoading`): skeleton enquanto carrega — obrigatório em server mode.
|
|
135
|
+
- **Vazio** (`renderEmpty`): sem nenhum registro → "Nenhuma `<entidade>` ainda" + CTA _Adicionar_.
|
|
136
|
+
- **Sem resultado** (`renderNoResults`): filtro/busca sem match → "Nenhum resultado" + _Limpar filtros_.
|
|
137
|
+
- (Aceite defaults sensatos se o usuário não quiser customizar — mas **sempre wire os três**.)
|
|
138
|
+
|
|
139
|
+
Ao terminar: resuma as escolhas e siga pro `blueprint.md` (gate).
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
> **Nota de portabilidade.** Este roteiro foi extraído do pipeline do iGreen DS
|
|
2
|
+
> para Claude Code. Menções a slash command (`/ds-create-…`), a `.claude/` e a
|
|
3
|
+
> ferramentas daquele ambiente descrevem **como ele é acionado lá** — aqui o
|
|
4
|
+
> equivalente é carregar este roteiro pelo `indice.json`. O conteúdo de decisão
|
|
5
|
+
> (entrevista, blueprint, regras de composição) vale igual.
|
|
6
|
+
|
|
7
|
+
> **Modo submódulo (`ds-link`).** Existe `.claude/ds-config.json` com `"mode": "submodule"`?
|
|
8
|
+
> Então **NÃO rode `igreen:add`** — esse script não existe no seu projeto. Os componentes e
|
|
9
|
+
> exemplos já estão no disco em `<dsPath>/src`: importe pelo `importBase` do config
|
|
10
|
+
> (compostos) e pelo `primitivesBase` (primitivos shadcn), e **leia** o exemplo direto de
|
|
11
|
+
> `<dsPath>/src/examples/`.
|
|
12
|
+
|
|
13
|
+
# CRUD Builder — Geração
|
|
14
|
+
|
|
15
|
+
Só entre aqui após o gate aprovado. Ordem obrigatória:
|
|
16
|
+
|
|
17
|
+
## 1. Puxar do registry (componentes + exemplo canônico)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm run igreen:add -- data-table example-clientes
|
|
21
|
+
# + example-finance (se houver drawers de criar/editar/detalhe)
|
|
22
|
+
# + outros componentes citados no blueprint (chip, avatar-ig, etc — o registry resolve deps)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 2. LER antes de escrever (precedência de fontes)
|
|
26
|
+
|
|
27
|
+
1. `src/examples/clientes/clientes-screen.tsx` — o molde real (colunas via `textColumn/currencyColumn/dateColumn/statusColumn/actionColumn`, `useMemo`, toolbar, paginação, seleção).
|
|
28
|
+
2. `src/components/ui/DataTable/USAGE.md` + types ao lado — API exata.
|
|
29
|
+
3. Pra drawers: `src/examples/finance/components/NovoClienteDrawer` e `.../FinanceDetailPanel`.
|
|
30
|
+
|
|
31
|
+
Nunca gere props de memória — copie a forma do exemplo.
|
|
32
|
+
|
|
33
|
+
## 3. Criar a página
|
|
34
|
+
|
|
35
|
+
- Caminho/rota conforme o blueprint (`PAGES_DIR`/`REGISTRO`).
|
|
36
|
+
- Wrapper: `<div className="flex flex-col h-full min-h-0 gap-gp-2xl">` → `<PageHeader .../>` → `<DataTable className="flex-1 min-h-0" .../>`.
|
|
37
|
+
- `columns` em `useMemo`; server mode ⇒ `fetchData` em `useCallback`.
|
|
38
|
+
|
|
39
|
+
### Regras de coluna (OBRIGATÓRIO — pega bugs comuns)
|
|
40
|
+
|
|
41
|
+
1. **Filtro em TODAS as colunas de dados**: cada coluna ganha `enableColumnFilter: true` + `filterType` (text→`"text"`, number/currency/percentage→`"number"`, date→`"date"`, badge/status/select→`"select"`, multiSelect/tags→`"multiSelect"`). Só ficam de fora `actions` e render-custom sem valor. ⚠️ O funil/drawer de filtros só lista colunas com `enableColumnFilter` — marcar só 2 = bug "filtra só 2 colunas".
|
|
42
|
+
2. **Coluna `actions` por ÚLTIMO**, `type: "actions"` (via `actionColumn`/`getActions`). É o **`type`** que dá as 3 garantias — vai pro fim (mesmo declarada no meio), **ancora à direita** (`pinned: "right"` é redundante) e **não entra no rateio** do autoFit. Coluna de botões montada na unha (`render` sem `type`) não recebe nenhuma das três: fica no meio da tabela e cresce no rateio. ⚠️ **NÃO passe `width`** (lib 0.42.0+): a largura é **derivada do nº de ações** — 1→44px, 2→74px, 3→104px, **4+ colapsam no "…"** (44px). Até a 0.41.x esta linha mandava espelhar `width: 64`; era inútil, porque o cálculo **ignorava `col.width`** nesta coluna. Agora vale, e 64px cabe **1** ícone. Split manual: `showInMenu: true` nos itens que devem ir pro menu (desliga o automático, sem limite de inline).
|
|
43
|
+
3. **Prefira NÃO setar `width`** nas colunas de dados — `autoFit` (default ON) distribui pra preencher o container (sem 1ª coluna esticada, sem scroll). Nunca `autoFit: false` sem motivo. **(v0.22.0+)** `col.width` virou **base/piso** (não trava fixa): o autoFit usa como mínimo e ainda distribui a sobra proporcionalmente — setar `width` em várias colunas **não** deixa mais sobra à direita. Travar de fato = `width`+`maxWidth` iguais (ou `type` fixo). Título do header **nunca trunca** (a largura mínima já inclui o `headerName`).
|
|
44
|
+
4. **Copiar valor** (`copyable`) — **infira, não espere que peçam**; ícone de copiar no **hover/foco** da célula + feedback "Copiado!" (~2s, `navigator.clipboard`). Critério: **o valor é um identificador que a pessoa cola em outro lugar**. ✅ documento (CPF/CNPJ/RG/IE), e-mail, telefone/WhatsApp, conta/agência/chave PIX, código de rastreio/protocolo/contrato/NF/pedido, token/hash, ID **externo**. ❌ nome de pessoa/empresa, status, data, valor monetário, quantidade, percentual, endereço em prosa. ⚠️ `id` sequencial curto (1, 2, 3) **não**; UUID/protocolo/NF **sim** — decide servir fora da tela, não a coluna se chamar "id". **Limites (verificados no código):** inerte em `actions`, na coluna de árvore e na célula em edição — marcar lá não dá erro, só não aparece; **`readMore` vence `copyable`** na mesma coluna (escolha um); copia o texto **formatado**, então numa coluna `currency` sai `R$ 1.234,56` e não `1234.56` — pro valor cru use `copyable: { value: (row) => String(row.x) }`. Texto/rótulo diferentes: `copyable: { value: (row) => "...", label: "Copiar conta" }`. **Declare no gate** as colunas em que você inferiu, pra o usuário recusar em lote — inferência silenciosa de recurso que ele não sabe que existe é surpresa, não conveniência.
|
|
45
|
+
5. **Grab-to-scroll é NATIVO** (`grabToScroll` default `true`, v0.26.0+): toda tabela já rola lateral ao arrastar o corpo (mouse/pen, threshold ~6px, clique/seleção preservados). Não configure — só `grabToScroll={false}` pra desligar.
|
|
46
|
+
6. **Filtro visível na tabela** (`showEmptyFilterChips`, v0.6.0+): pros filtros que o usuário mais usa (status, categoria, tipo, graduação…), passe `showEmptyFilterChips={["status", "categoria"]}` no `<DataTable>` → os chips nascem **vazios e clicáveis** já no load, sem abrir o menu de filtros. É o que faz o filtro **aparecer** na tela — sem isso o usuário não vê a afordância e acaba pedindo select na unha (⛔ **proibido** montar form/select acima da tabela — ver `.claude/rules/ds-components.md`). Status/segmento como eixo de navegação (poucos valores) → alternativa: **uma visão por valor** em `defaultViews` (ver item de visões abaixo). Regra de ouro: se a informação está numa coluna, **chip nativo primeiro**.
|
|
47
|
+
|
|
48
|
+
**Formato de data.** `type: "date"` renderiza `14/03/2023` e `type: "datetime"` renderiza `14/03/2023 09:30` — **com ano** (lib 0.43.0+). Precisa de outro formato (mês escrito, relativo, ISO)? Passe **`valueFormatter`** na coluna: ele vence o formato do tipo e vale na célula, no export e no clipboard. **NÃO** escreva `render` próprio só pra formatar data. ⚠️ Até a 0.42.1 esses tipos mostravam a data **sem ano** e o `valueFormatter` não chegava na célula — se você viu `render` de data em código antigo, era contorno disso.
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
### Padrões de CÉLULA (consistência finance — OBRIGATÓRIO)
|
|
52
|
+
|
|
53
|
+
Espelhar `finance-screen.tsx` (puxe `example-finance`). **Componente do DS sempre antes de markup manual**:
|
|
54
|
+
|
|
55
|
+
- **Coluna primária (nome)**: `isPrimary` + `render` com `<Avatar size="md">` + nome `text-body-sm font-medium` + secundária `text-caption-md text-fg-muted` (email/ID/doc) + ícone "abrir detalhe" (`<SquareArrowOutUpRight>` num `size-[24px] rounded-radius-sm border bg-bg-canvas shadow-sh-sm`) quando o row click abre painel.
|
|
56
|
+
- **Status / badge**: `type: "badge"` + `render` com `<Chip variant="soft" size="sm" shape="pill">` (cor semântica). Nunca pill na unha com `<span>` estilizado.
|
|
57
|
+
- **Avatar**: use **`avatar-ig`** (`@/components/ui/avatar-ig`), não o `avatar` (Radix puro, sem `colorHex`/`size`). `size="md"` na tabela (não `sm`). **Números/moeda/%**: `tabular-nums` + `type` (`currency`/`percentage`) + `align: "right"`. **Tags**: `type: "tags"` + `<Chip soft sm rounded>`. **Código/identificador/valor técnico** (chave de env, ID, hash, slug, path): preset **`text-code-sm`** — nunca `font-mono text-body-sm` + `tracking-*` na unha.
|
|
58
|
+
|
|
59
|
+
### Detail panel (row click → painel)
|
|
60
|
+
|
|
61
|
+
**Cite o bloco `dsgreen-paneldetail-1`** — a estrutura inteira já está resolvida e
|
|
62
|
+
referenciável por ID (`npm run igreen:add -- dsgreen-paneldetail-1`, ou peça
|
|
63
|
+
*"use a referência dsgreen-paneldetail-1"*).
|
|
64
|
+
|
|
65
|
+
A referência anterior era "espelhe o `FinanceDetailPanel`", e ela funciona — o
|
|
66
|
+
`example-finance` distribui esse arquivo. O bloco é melhor por dois motivos, não porque o
|
|
67
|
+
outro esteja quebrado: **não exige puxar uma tela inteira** só pra ver um painel, e o arquivo
|
|
68
|
+
dele traz **o porquê de cada decisão** (com as medições) em vez de só o resultado.
|
|
69
|
+
|
|
70
|
+
**Sempre** `<FloatingPanel>`, nunca markup solto. O que o bloco carrega:
|
|
71
|
+
|
|
72
|
+
- `titleSlot`: `<Avatar size="lg">` + nome (`text-body-md font-semibold`) + linha
|
|
73
|
+
`código · <Chip status>`. ⚠️ Se você usar `Panel` em vez de `FloatingPanel`, esse header é
|
|
74
|
+
impossível: lá `title`/`description` são **string**.
|
|
75
|
+
- `headerActions`: 1–2 ações de ícone, **todas `variant="soft"`** (`secondary` neutro,
|
|
76
|
+
`success` contato, `critical` destrutivo). `ghost` no meio da fileira fica sem container e lê
|
|
77
|
+
como desabilitada ao lado do maximize/close, que o componente renderiza como `soft`.
|
|
78
|
+
`aria-label` obrigatório — botão de ícone não tem texto.
|
|
79
|
+
- `bodyPadded={false}` + **agrupar por assunto** em `<FloatingPanelSection title>`.
|
|
80
|
+
- 1ª seção = **métricas do registro**, em cards compactos (ícone + valor 18px + rótulo), 2 por
|
|
81
|
+
linha. ⛔ **Não use `Kpi`**: ele é card de dashboard (144px de altura por célula) e come a
|
|
82
|
+
primeira dobra do painel antes de qualquer campo.
|
|
83
|
+
- Cada dado simples = **uma linha** `<FloatingPanelField label value/>`.
|
|
84
|
+
- Dado que **não é** `label: valor` sai do Field: entidade com marca (banco, gestor) vira linha
|
|
85
|
+
de largura cheia com `Avatar`; vários valores viram `<Chip>`; e-mail/telefone viram
|
|
86
|
+
`mailto:`/`tel:` com cor de link.
|
|
87
|
+
- `footer`: Fechar + ação primária.
|
|
88
|
+
- ⛔ **Sem aba.** Se o corpo já é pilha de seções colapsáveis, o colapso **é** o mecanismo de
|
|
89
|
+
esconder — ter os dois faz o usuário procurar o dado em dois lugares.
|
|
90
|
+
|
|
91
|
+
- **Tabela + Lista (toggle)**: se o usuário quer alternar entre tabela e uma **lista de cards** (não kanban), use `viewMode` + `listConfig={{ renderItem(row), paginated?, hierarchical?, getPath?, getMenuItems? }}` no próprio `<DataTable>` — mesma toolbar, toggle Tabela/Lista automático. NÃO monte um `<DataList>` paralelo + toggle na mão.
|
|
92
|
+
- **Lista flat paginada**: `listConfig.paginated: true` — a lista usa a MESMA paginação da tabela + mostra o footer. Default `false` (mostra todas, sem footer); ignorado em `hierarchical`. Use quando a lista flat puder ter muitas linhas.
|
|
93
|
+
- ⛔ **No MÁXIMO 2 presets, e NUNCA um preset "Todos"/"Todas"**: `maxTabs` default é 3 e a aba **Default** (nativa, que já É a visão sem filtro) consome 1 slot — sobram 2. O excedente é cortado por `.slice(0, maxTabs - 1)` — em DEV o componente avisa no console qual visão foi engolida (v0.43.1), em produção não. Precisa de mais? `maxViewTabs={N + 1}` no `<DataTable>` (o `+1` é a Default) — mas 2 é o default por um motivo: barra de visões não é menu. Um preset "Todos" duplica a Default e gasta um slot com nada.
|
|
94
|
+
- **Visões pré-definidas read-only (`allowCreateView={false}`, v0.23.0+)**: passe `defaultViews={[presetView({ id, name, filters?, sort?, viewMode? })]}` + `persistId` pras abas nativas da tela. `allowCreateView={false}` esconde o botão "+" (o usuário não salva visões próprias — só usa as suas). Default `true`. **viewMode "sticky"**: trocar de visão só muda Tabela↔Lista↔Kanban se o preset declarar `viewMode` explícito; sem isso, mantém a view que o usuário está vendo (só declare `viewMode` no preset que DEVE forçar uma view).
|
|
95
|
+
- Lista árvore **+ tabela árvore**: `hierarchical` + `getTreeDataPath` (tabela não pagina).
|
|
96
|
+
- **Tabela FLAT paginada + lista em ÁRVORE**: `hierarchical` + **`listConfig.getPath`** e NÃO passe `getTreeDataPath` (senão a tabela vira tree-data e perde paginação).
|
|
97
|
+
- Drawers de criar/editar: espelhe `NovoClienteDrawer` (Panel + FormField + `gap-form-gap`), ligados via estado da página (igual ao `finance-screen.tsx`).
|
|
98
|
+
- Tokens/spacing/typography conforme `.claude/rules/ds-design.md` + `DESIGN.md`.
|
|
99
|
+
|
|
100
|
+
## 4. Registrar a rota
|
|
101
|
+
|
|
102
|
+
No ponto que o usuário indicou (router / App). Página órfã = incompleto.
|
|
103
|
+
|
|
104
|
+
## 5. Validar
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npx tsc --noEmit # abort se falhar — corrija antes do handoff
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 6. Handoff
|
|
111
|
+
|
|
112
|
+
`CRUD_PRONTO: <Entidade>` + onde foi registrada + como rodar (`npm run dev`).
|
|
113
|
+
Sugira ao usuário abrir a tela e conferir; ofereça ajustes finos (larguras de coluna, filtros).
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
> **Nota de portabilidade.** Este roteiro foi extraído do pipeline do iGreen DS
|
|
2
|
+
> para Claude Code. Menções a slash command (`/ds-create-…`), a `.claude/` e a
|
|
3
|
+
> ferramentas daquele ambiente descrevem **como ele é acionado lá** — aqui o
|
|
4
|
+
> equivalente é carregar este roteiro pelo `indice.json`. O conteúdo de decisão
|
|
5
|
+
> (entrevista, blueprint, regras de composição) vale igual.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# CRUD Builder (consumidor) — Router
|
|
9
|
+
|
|
10
|
+
Você guia a criação de uma tela de tabela que consome `<DataTable>` **sem fugir
|
|
11
|
+
do exemplo e da documentação do projeto**. NÃO inventa API de props, NÃO gera
|
|
12
|
+
código de memória, NÃO toca em arquivo antes do gate aprovado.
|
|
13
|
+
|
|
14
|
+
> **Kanban / board / funil / pipeline de vendas** caem AQUI: kanban é uma `viewMode`
|
|
15
|
+
> do DataTable (mesmos dados/colunas/filtros, só muda a exibição). "Quero um kanban/
|
|
16
|
+
> funil" → esta skill; a Fase 6 do interview configura as lanes pela coluna de
|
|
17
|
+
> status/etapa. Funil = board agrupado por etapa. Ref. visual: `example-finance`.
|
|
18
|
+
|
|
19
|
+
## Ambiente (este é um projeto CONSUMIDOR, copy-in)
|
|
20
|
+
|
|
21
|
+
| Variável | Valor |
|
|
22
|
+
| ------------------------ | --------------------------------------------------------------------------------------------------------------- |
|
|
23
|
+
| `IMPORT_PATH` | `@/components/ui/DataTable`, `@/components/ui/Button`, etc (copy-in via alias) |
|
|
24
|
+
| `EXEMPLO_CANÔNICO` | `example-clientes` → `npm run igreen:add -- example-clientes` → ler `src/examples/clientes/clientes-screen.tsx` |
|
|
25
|
+
| `DOC` | `src/components/ui/DataTable/USAGE.md` (após `igreen:add data-table`) + types ao lado |
|
|
26
|
+
| `PAGES_DIR` / `REGISTRO` | perguntar ao usuário (onde mora a página + como registra rota) |
|
|
27
|
+
|
|
28
|
+
Se o componente/exemplo ainda não está no disco, **puxe via `igreen:add`** antes de ler — nunca gere de memória.
|
|
29
|
+
|
|
30
|
+
> **Modo submódulo (ds-link).** Se existe `.claude/ds-config.json` com `"mode": "submodule"`,
|
|
31
|
+
> o DS é consumido como **submódulo** (não copy-in): os componentes/exemplos JÁ estão no disco
|
|
32
|
+
> em `<dsPath>/src` e **não** há registry. Use `importBase` do config (ex.: `@ds/components/ui/<Nome>`)
|
|
33
|
+
> e leia o exemplo canônico direto em `<dsPath>/src/examples/clientes/clientes-screen.tsx` —
|
|
34
|
+
> **NÃO** rode `igreen:add`. `PAGES_DIR`/`REGISTRO` continuam do projeto pai.
|
|
35
|
+
|
|
36
|
+
## Fluxo — 3 estágios
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
/ds-create-crud
|
|
40
|
+
▼ interview.md
|
|
41
|
+
1. ENTREVISTA (fases 0-6) — acumula escolhas, ZERO edição em disco
|
|
42
|
+
▼ blueprint.md
|
|
43
|
+
2. BLUEPRINT [GATE] — preview consolidado + pré-validações → aguarda "aprovar"
|
|
44
|
+
▼ generate.md
|
|
45
|
+
3. GERAÇÃO — igreen:add → ler exemplo → criar página → registrar → tsc → handoff
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Carregue cada sub-arquivo só no estágio correspondente: `interview.md` agora, `blueprint.md` ao fim da entrevista, `generate.md` só após o gate.
|
|
49
|
+
|
|
50
|
+
## ⚠️ Precedência de fontes (anti-drift)
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
1. src/examples/clientes/clientes-screen.tsx (exemplo real, vence tudo)
|
|
54
|
+
2. src/components/ui/DataTable/USAGE.md + types ao lado
|
|
55
|
+
3. Snippets desta skill
|
|
56
|
+
4. Memória da IA ← NUNCA confiar sozinha
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Se USAGE.md divergir do exemplo/types, o exemplo + types vencem.
|
|
60
|
+
|
|
61
|
+
## Guardrails (não-negociáveis)
|
|
62
|
+
|
|
63
|
+
1. `columns` SEMPRE em `useMemo`; `fetchData` (server mode) SEMPRE em `useCallback` (senão loop de refetch).
|
|
64
|
+
2. Operador de filtro válido pro filterType (multiSelect⇒`isAnyOf`, text⇒`contains`, date⇒`between`...).
|
|
65
|
+
3. `virtualize: true` ⇒ paginação desligada + container com altura (`flex-1 min-h-0` num pai `h-full`).
|
|
66
|
+
4. `groupBy`/kanban ativo ⇒ paginação desligada (avisar).
|
|
67
|
+
5. Forms em drawers/modais usam `<FormField>` (nunca `<label>` cru) + `gap-form-gap`.
|
|
68
|
+
6. Classes DS antes de Tailwind literal; zero hardcode de cor/tamanho (ver `.claude/rules/ds-design.md`).
|
|
69
|
+
7. Wrapper da tela: `flex flex-col h-full min-h-0 gap-gp-2xl` (PageHeader → 16px → tabela). Ver `DESIGN.md`.
|
|
70
|
+
8. Página registrada no roteador do usuário — página órfã = tarefa incompleta.
|
|
71
|
+
9. `npx tsc --noEmit` limpo antes do handoff (abort-on-error).
|
|
72
|
+
10. LER o exemplo canônico ANTES de gerar — nunca de memória.
|
|
73
|
+
11. Ação destrutiva (excluir) ⇒ **confirmação via `AlertModal`** — nunca deletar direto.
|
|
74
|
+
12. Sempre wire os 3 estados: `loading`/`renderLoading` (skeleton), `renderEmpty` (sem
|
|
75
|
+
registros + CTA _Adicionar_), `renderNoResults` (filtro sem match). **O default
|
|
76
|
+
embutido conta como wirado — desde que declarado no blueprint** (linha `Estados:`).
|
|
77
|
+
Faltou = incompleto: o que não vale é o estado nunca ter sido decidido.
|
|
78
|
+
|
|
79
|
+
## Drawers (criar/editar/detalhe) — ligado ao CRUD
|
|
80
|
+
|
|
81
|
+
Se o CRUD precisa de criar/editar/ver-detalhe, espelhe o padrão do `example-finance`:
|
|
82
|
+
`NovoClienteDrawer` (criar/editar via `Panel` + `FormField`) e `FinanceDetailPanel`
|
|
83
|
+
(detalhe via `FloatingPanel`). Puxe `example-finance`, leia esses componentes e
|
|
84
|
+
reuse a estrutura — mesmo design de drawer do DS.
|
|
85
|
+
|
|
86
|
+
## Handoff
|
|
87
|
+
|
|
88
|
+
- Entrevista pronta → `BLUEPRINT_PRONTO: <Entidade> — aguardando gate`
|
|
89
|
+
- Pós-geração → `CRUD_PRONTO: <Entidade>` (+ onde foi registrada)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
> **Nota de portabilidade.** Este roteiro foi extraído do pipeline do iGreen DS
|
|
2
|
+
> para Claude Code. Menções a slash command (`/ds-create-…`), a `.claude/` e a
|
|
3
|
+
> ferramentas daquele ambiente descrevem **como ele é acionado lá** — aqui o
|
|
4
|
+
> equivalente é carregar este roteiro pelo `indice.json`. O conteúdo de decisão
|
|
5
|
+
> (entrevista, blueprint, regras de composição) vale igual.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# drawers — Criar / Editar / Detalhe
|
|
9
|
+
|
|
10
|
+
Padrão de drawer do DS, ligado ao CRUD/detalhe. Três variantes, mesma família visual.
|
|
11
|
+
|
|
12
|
+
## Fluxo
|
|
13
|
+
1. `npm run igreen:add -- example-finance` (traz os drawers + `Panel`, `FloatingPanel`, `FormField`).
|
|
14
|
+
2. **Leia** os componentes-modelo:
|
|
15
|
+
- Criar/editar → `src/examples/finance/components/NovoClienteDrawer` e `.../EditarFinanceDrawer` (base: `Panel` + `FormField`).
|
|
16
|
+
- Ver detalhe → `src/examples/finance/components/FinanceDetailPanel` (base: `FloatingPanel`, não-modal).
|
|
17
|
+
3. Adapte os campos/conteúdo ao caso. Ligue ao estado da página (igual `finance-screen.tsx`: `open`/`onOpenChange` + registro selecionado).
|
|
18
|
+
|
|
19
|
+
> **Modo submódulo (ds-link).** Se existe `.claude/ds-config.json` com `"mode": "submodule"`,
|
|
20
|
+
> o DS é consumido como **submódulo** (não copy-in): os componentes/exemplos JÁ estão no disco
|
|
21
|
+
> em `<dsPath>/src` e **não** há registry. Use `importBase` do config (ex.: `@ds/components/ui/Panel`)
|
|
22
|
+
> e leia os drawers-modelo direto em `<dsPath>/src/examples/finance/components/` —
|
|
23
|
+
> **NÃO** rode `igreen:add`.
|
|
24
|
+
|
|
25
|
+
## Gotchas do tipo
|
|
26
|
+
- **Criar/Editar** = `Panel` (drawer modal lateral) com form em `<FormField>` + `gap-form-gap`. Footer sticky com Cancelar/Salvar.
|
|
27
|
+
- **Detalhe** = `FloatingPanel` (não-modal, não bloqueia a página; pode coexistir com a tabela). `shadow-sh-aside`.
|
|
28
|
+
- Largura: `Panel` default é `size="md"` = **560px**. O token `max-w-drawer-md` (480px) é outra coisa — não confunda. Mobile (<1024px): vira Sheet full.
|
|
29
|
+
- Nunca `<label>` cru; nunca `<button onClick>` como "card de seleção" (use label/FormField nativo).
|
|
30
|
+
- Abrir detalhe no click da linha (`onRowClick`); abrir editar via ação da linha.
|
|
31
|
+
|
|
32
|
+
Aplique `DESIGN.md` + regras. Handoff: `DRAWER_PRONTO: <criar|editar|detalhe> de <Entidade>`.
|
|
33
|
+
|
|
34
|
+
## Aba dentro do drawer/painel
|
|
35
|
+
|
|
36
|
+
`<Tabs fullWidth>` com a variante **default** (`segmented`) — nunca `line`. Estas superfícies
|
|
37
|
+
são estreitas por construção (`Panel` 560px, `FloatingPanel` 320–720 e **redimensionável**),
|
|
38
|
+
e ali o `line` vira um trilho curto que lê como fragmento. Sem `fullWidth` as abas ficam num
|
|
39
|
+
canto. ⛔ Não escreva `w-full` no `TabsList` nem `flex-1` nos triggers: a prop faz as três
|
|
40
|
+
camadas (root + list + triggers), e `w-full` só no list estica o container e agrupa as abas
|
|
41
|
+
na esquerda.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
> **Nota de portabilidade.** Este roteiro foi extraído do pipeline do iGreen DS
|
|
2
|
+
> para Claude Code. Menções a slash command (`/ds-create-…`), a `.claude/` e a
|
|
3
|
+
> ferramentas daquele ambiente descrevem **como ele é acionado lá** — aqui o
|
|
4
|
+
> equivalente é carregar este roteiro pelo `indice.json`. O conteúdo de decisão
|
|
5
|
+
> (entrevista, blueprint, regras de composição) vale igual.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
> **Modo submódulo (`ds-link`).** Existe `.claude/ds-config.json` com `"mode": "submodule"`?
|
|
9
|
+
> Então **NÃO rode `igreen:add`** — esse script não existe no seu projeto. Os componentes e
|
|
10
|
+
> exemplos já estão no disco em `<dsPath>/src`: importe pelo `importBase` do config
|
|
11
|
+
> (compostos) e pelo `primitivesBase` (primitivos shadcn), e **leia** o exemplo direto de
|
|
12
|
+
> `<dsPath>/src/examples/`.
|
|
13
|
+
|
|
14
|
+
# List Builder — Blueprint [GATE]
|
|
15
|
+
|
|
16
|
+
## Pré-validações automáticas (ANTES de exibir)
|
|
17
|
+
|
|
18
|
+
Corrigir silenciosamente (ou reportar se exigir decisão):
|
|
19
|
+
|
|
20
|
+
1. **Excludências de escala** — `virtualized` + `enableDnD` → desligar DnD;
|
|
21
|
+
`virtualized` + `onLoadMore` → escolher um; `fillHeight` + `virtualized` →
|
|
22
|
+
`fillHeight` off. Anotar `← corrigido`.
|
|
23
|
+
2. **branchHighlight** só com `layout="hierarchical"` — em outro layout, ignorar
|
|
24
|
+
e avisar.
|
|
25
|
+
3. **Coerência de layout** — `grouped` tem `groups`; `hierarchical` tem itens com
|
|
26
|
+
`children` (ou `onLoadChildren`).
|
|
27
|
+
4. **filterFields** — cada um tem `accessor`; `select` tem `options`. Operador de
|
|
28
|
+
view/filtro pré-aplicado válido pro `type` (multiSelect⇒`isAnyOf`,
|
|
29
|
+
select⇒`equals`, text⇒`contains`, number⇒`equals`, date⇒`between`,
|
|
30
|
+
boolean⇒`equals`).
|
|
31
|
+
5. **Colisão de rota** — o id/rota proposto não pode já existir no router **deste
|
|
32
|
+
projeto**. Colisão → propor sufixo. (Onde ficam as rotas varia: React Router,
|
|
33
|
+
TanStack Router, file-based do Next… **pergunte** se não for óbvio pelo repo.)
|
|
34
|
+
6. **Card** — `title` presente (slots) OU `renderItem` definido. Excluir
|
|
35
|
+
(destructive) tem `AlertModal` no plano (se houver form).
|
|
36
|
+
|
|
37
|
+
## Formato do blueprint (apresentar TUDO de uma vez)
|
|
38
|
+
|
|
39
|
+
```markdown
|
|
40
|
+
## Blueprint — Lista <Entidade>
|
|
41
|
+
|
|
42
|
+
**Página**: <Título> · id `<page-id>` · wrapper <ExamplePageLayout|AppShell|puro> · nav "List Components"
|
|
43
|
+
**Dados**: <client|server> mode · fonte: <sample|interface|endpoint|manual> · ~<N> itens · id: `<campo>`
|
|
44
|
+
|
|
45
|
+
### ⚠️ Decisões inferidas — vete se discordar
|
|
46
|
+
|
|
47
|
+
Só o que o usuário NÃO disse e você decidiu sozinho (wrapper, tema, tipo de campo com
|
|
48
|
+
confiança baixa…) — uma linha cada, com o que muda se ele vetar. Sem inferência →
|
|
49
|
+
`nenhuma`; não apague a seção: é a ausência dela que faz a decisão passar aprovada
|
|
50
|
+
em pacote junto com o resto.
|
|
51
|
+
|
|
52
|
+
### Card (<slots|renderItem>)
|
|
53
|
+
- leading: <avatar/ícone|—> · title: `<campo>` · subtitle: `<campo|—>`
|
|
54
|
+
- meta: [<label:campo(align)>, ...] · trailing: <badge|—> · description: <campo|—>
|
|
55
|
+
- (ou renderItem custom: <descrição do card rico>)
|
|
56
|
+
- densidade <comfortable|compact> · menu por card [<Editar·Excluir>|—]
|
|
57
|
+
|
|
58
|
+
### Layout
|
|
59
|
+
<standard | grouped (groups: <id(cor)>...; DnD <on|off>; surface <on|off>)
|
|
60
|
+
| hierarchical (branchHighlight <none|block|active>; expand inicial <...>; lazy <on|off>)>
|
|
61
|
+
|
|
62
|
+
### Toolbar
|
|
63
|
+
título OU views[<abas>] · busca <on|off> · refresh <on|off> · moreActions [<...>]
|
|
64
|
+
filterFields: [<id:label:type>, ...]
|
|
65
|
+
|
|
66
|
+
### Seleção / escala
|
|
67
|
+
selectable <on|off> + bulk [<actions>] · onItemClick <nada|detalhe|nav>
|
|
68
|
+
escala: <nenhuma | virtualized (estimate <N>) | infinite (onLoadMore/hasMore/loadingMore)>
|
|
69
|
+
fillHeight <on|off>
|
|
70
|
+
|
|
71
|
+
### Estados
|
|
72
|
+
loading <skeletonCount> · vazio <emptyState msg/CTA>
|
|
73
|
+
|
|
74
|
+
### Arquivos
|
|
75
|
+
- CRIAR <PAGES_DIR><Nome>.tsx (~<N> linhas)
|
|
76
|
+
- EDITAR <REGISTRO> (rota + entrada de navegação do SEU projeto — ver Fase 0)
|
|
77
|
+
|
|
78
|
+
### Referências canônicas que serão lidas antes de gerar
|
|
79
|
+
<lista da matriz do generate.md, só os cenários presentes>
|
|
80
|
+
|
|
81
|
+
⛔ Nenhum arquivo será tocado antes da aprovação.
|
|
82
|
+
Responda **aprovar** · **ajustar <o quê>** · **cancelar**.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Protocolo do gate
|
|
86
|
+
|
|
87
|
+
- Enunciar a **Assumption** central junto do blueprint (ex.: "o sample é
|
|
88
|
+
representativo; `status` tem exatamente os N valores mapeados") — é o que torna a
|
|
89
|
+
decisão reversível depois. **Não** há audit log a preencher neste projeto.
|
|
90
|
+
- `aprovar` → carregar `generate.md` e executar.
|
|
91
|
+
- `ajustar X` → re-montar → re-apresentar (novo gate).
|
|
92
|
+
- `cancelar` → abortar; nota de cancelamento. Zero disco.
|
|
93
|
+
|
|
94
|
+
Sinal junto com o preview: `BLUEPRINT_PRONTO: <Entidade> (lista) — aguardando gate`
|