@snksergio/design-system 0.62.0 → 0.64.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.
Files changed (149) hide show
  1. package/dist-lib/ai/blocos/chart/budget-breakdown.tsx +174 -0
  2. package/dist-lib/ai/blocos/indice.md +43 -0
  3. package/dist-lib/ai/blocos/paneldetail/detalhe-com-tabela.tsx +450 -0
  4. package/dist-lib/ai/blocos/paneldetail/detalhe-de-tarefa-com-abas.tsx +570 -0
  5. package/dist-lib/ai/blocos/paneldetail/detalhe-do-registro.tsx +555 -0
  6. package/dist-lib/ai/componentes/DataTable.md +2 -1
  7. package/dist-lib/ai/componentes/TableToolbar.md +1 -1
  8. package/dist-lib/ai/exemplos/app-shell/app-shell-example.tsx +140 -0
  9. package/dist-lib/ai/exemplos/app-shell/index.ts +3 -0
  10. package/dist-lib/ai/exemplos/app-shell/nav-data.ts +97 -0
  11. package/dist-lib/ai/exemplos/app-shell/routes.tsx +75 -0
  12. package/dist-lib/ai/exemplos/chat/chat-screen.tsx +152 -0
  13. package/dist-lib/ai/exemplos/chat/chat-v2-mocks.ts +171 -0
  14. package/dist-lib/ai/exemplos/chat/chat-v2.styles.ts +23 -0
  15. package/dist-lib/ai/exemplos/chat/chat-v2.types.ts +81 -0
  16. package/dist-lib/ai/exemplos/chat/components/ChannelDot/channel-dot.tsx +28 -0
  17. package/dist-lib/ai/exemplos/chat/components/ConversationActionsMenu/conversation-actions-menu.tsx +83 -0
  18. package/dist-lib/ai/exemplos/chat/components/ConversationActionsMenu/index.ts +4 -0
  19. package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.styles.ts +22 -0
  20. package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.tsx +203 -0
  21. package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.types.ts +10 -0
  22. package/dist-lib/ai/exemplos/chat/components/ConversationColumn/index.ts +2 -0
  23. package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.styles.ts +55 -0
  24. package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.tsx +52 -0
  25. package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.types.ts +7 -0
  26. package/dist-lib/ai/exemplos/chat/components/ConversationListItem/index.ts +2 -0
  27. package/dist-lib/ai/exemplos/chat/components/DateSeparator/date-separator.tsx +18 -0
  28. package/dist-lib/ai/exemplos/chat/components/DetailField/detail-field.tsx +23 -0
  29. package/dist-lib/ai/exemplos/chat/components/DetailSection/detail-section.tsx +41 -0
  30. package/dist-lib/ai/exemplos/chat/components/DetailSection/index.ts +1 -0
  31. package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.styles.ts +30 -0
  32. package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.tsx +142 -0
  33. package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.types.ts +16 -0
  34. package/dist-lib/ai/exemplos/chat/components/DetailsColumn/index.ts +5 -0
  35. package/dist-lib/ai/exemplos/chat/components/FilterRow/filter-row.styles.ts +37 -0
  36. package/dist-lib/ai/exemplos/chat/components/FilterRow/filter-row.tsx +45 -0
  37. package/dist-lib/ai/exemplos/chat/components/FilterRow/index.ts +1 -0
  38. package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.styles.ts +27 -0
  39. package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.tsx +66 -0
  40. package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.types.ts +13 -0
  41. package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-rail.tsx +38 -0
  42. package/dist-lib/ai/exemplos/chat/components/FiltersColumn/index.ts +6 -0
  43. package/dist-lib/ai/exemplos/chat/components/MessageBubble/index.ts +2 -0
  44. package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.styles.ts +37 -0
  45. package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.tsx +29 -0
  46. package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.types.ts +5 -0
  47. package/dist-lib/ai/exemplos/chat/components/PersonAvatar/index.ts +5 -0
  48. package/dist-lib/ai/exemplos/chat/components/PersonAvatar/person-avatar.tsx +31 -0
  49. package/dist-lib/ai/exemplos/chat/components/QueueColumn/index.ts +2 -0
  50. package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.styles.ts +19 -0
  51. package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.tsx +140 -0
  52. package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.types.ts +13 -0
  53. package/dist-lib/ai/exemplos/chat/components/RailItem/index.ts +1 -0
  54. package/dist-lib/ai/exemplos/chat/components/RailItem/rail-item.styles.ts +30 -0
  55. package/dist-lib/ai/exemplos/chat/components/RailItem/rail-item.tsx +42 -0
  56. package/dist-lib/ai/exemplos/chat/hooks/use-resizable.ts +98 -0
  57. package/dist-lib/ai/exemplos/chat/index.ts +1 -0
  58. package/dist-lib/ai/exemplos/clientes/_table-data.ts +59 -0
  59. package/dist-lib/ai/exemplos/clientes/clientes-screen.tsx +505 -0
  60. package/dist-lib/ai/exemplos/clientes/clientes-showcase-mocks.ts +117 -0
  61. package/dist-lib/ai/exemplos/clientes/clientes-showcase.styles.ts +13 -0
  62. package/dist-lib/ai/exemplos/clientes/clientes-showcase.types.ts +16 -0
  63. package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.styles.ts +28 -0
  64. package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.tsx +303 -0
  65. package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.types.ts +14 -0
  66. package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/index.ts +2 -0
  67. package/dist-lib/ai/exemplos/clientes/components/NovoClienteDrawer/index.ts +2 -0
  68. package/dist-lib/ai/exemplos/clientes/components/NovoClienteDrawer/novo-cliente-drawer.tsx +207 -0
  69. package/dist-lib/ai/exemplos/clientes/index.ts +1 -0
  70. package/dist-lib/ai/exemplos/edit-page/components/StepNav.tsx +81 -0
  71. package/dist-lib/ai/exemplos/edit-page/components/section-card.tsx +85 -0
  72. package/dist-lib/ai/exemplos/edit-page/edit-page-screen.tsx +234 -0
  73. package/dist-lib/ai/exemplos/edit-page/index.ts +1 -0
  74. package/dist-lib/ai/exemplos/finance/_table-data.ts +57 -0
  75. package/dist-lib/ai/exemplos/finance/clientes-financeiro-mocks.ts +227 -0
  76. package/dist-lib/ai/exemplos/finance/clientes-financeiro.types.ts +75 -0
  77. package/dist-lib/ai/exemplos/finance/clientes-showcase-mocks.ts +117 -0
  78. package/dist-lib/ai/exemplos/finance/clientes-showcase.styles.ts +13 -0
  79. package/dist-lib/ai/exemplos/finance/clientes-showcase.types.ts +16 -0
  80. package/dist-lib/ai/exemplos/finance/components/EditarFinanceDrawer/editar-finance-drawer.tsx +241 -0
  81. package/dist-lib/ai/exemplos/finance/components/EditarFinanceDrawer/index.ts +5 -0
  82. package/dist-lib/ai/exemplos/finance/components/ExtratoExpansion/extrato-expansion.tsx +172 -0
  83. package/dist-lib/ai/exemplos/finance/components/ExtratoExpansion/index.ts +1 -0
  84. package/dist-lib/ai/exemplos/finance/components/FinanceDetailPanel/finance-detail-panel.tsx +241 -0
  85. package/dist-lib/ai/exemplos/finance/components/FinanceDetailPanel/index.ts +2 -0
  86. package/dist-lib/ai/exemplos/finance/components/NovoClienteDrawer/index.ts +2 -0
  87. package/dist-lib/ai/exemplos/finance/components/NovoClienteDrawer/novo-cliente-drawer.tsx +207 -0
  88. package/dist-lib/ai/exemplos/finance/components/SacarDialog/index.ts +2 -0
  89. package/dist-lib/ai/exemplos/finance/components/SacarDialog/sacar-dialog.tsx +346 -0
  90. package/dist-lib/ai/exemplos/finance/finance-screen.tsx +821 -0
  91. package/dist-lib/ai/exemplos/finance/index.ts +1 -0
  92. package/dist-lib/ai/exemplos/gantt/_gantt-data.tsx +402 -0
  93. package/dist-lib/ai/exemplos/gantt/gantt-screen.tsx +512 -0
  94. package/dist-lib/ai/exemplos/gantt/index.ts +1 -0
  95. package/dist-lib/ai/exemplos/login/index.ts +1 -0
  96. package/dist-lib/ai/exemplos/login/login-screen.tsx +246 -0
  97. package/dist-lib/ai/exemplos/mapa-rede/components/ConsultorDetailPanel/consultor-detail-panel.tsx +158 -0
  98. package/dist-lib/ai/exemplos/mapa-rede/components/ConsultorDetailPanel/index.ts +2 -0
  99. package/dist-lib/ai/exemplos/mapa-rede/index.ts +1 -0
  100. package/dist-lib/ai/exemplos/mapa-rede/mapa-de-rede-mocks.ts +655 -0
  101. package/dist-lib/ai/exemplos/mapa-rede/mapa-de-rede.types.ts +53 -0
  102. package/dist-lib/ai/exemplos/mapa-rede/mapa-rede-screen.tsx +227 -0
  103. package/dist-lib/ai/exemplos/order-detail/components/ActivityTab.tsx +77 -0
  104. package/dist-lib/ai/exemplos/order-detail/components/AttachmentsTab.tsx +45 -0
  105. package/dist-lib/ai/exemplos/order-detail/components/CommentsTab.tsx +111 -0
  106. package/dist-lib/ai/exemplos/order-detail/components/DetailsTab.tsx +189 -0
  107. package/dist-lib/ai/exemplos/order-detail/components/OverviewTab.tsx +200 -0
  108. package/dist-lib/ai/exemplos/order-detail/components/section-card.tsx +85 -0
  109. package/dist-lib/ai/exemplos/order-detail/index.ts +1 -0
  110. package/dist-lib/ai/exemplos/order-detail/order-detail-screen.tsx +119 -0
  111. package/dist-lib/ai/exemplos/order-detail/order-mocks.ts +186 -0
  112. package/dist-lib/ai/exemplos/order-detail/order.types.ts +118 -0
  113. package/dist-lib/ai/global/componentes.md +7 -0
  114. package/dist-lib/ai/indice.json +30 -15
  115. package/dist-lib/ai/manifest.json +32 -6
  116. package/dist-lib/ai/roteiros/app-builder/roteiro.md +155 -0
  117. package/dist-lib/ai/roteiros/auth-builder/roteiro.md +42 -0
  118. package/dist-lib/ai/roteiros/cards/roteiro.md +34 -0
  119. package/dist-lib/ai/roteiros/charts/roteiro.md +32 -0
  120. package/dist-lib/ai/roteiros/chat/roteiro.md +31 -0
  121. package/dist-lib/ai/roteiros/crud-builder/blueprint.md +63 -0
  122. package/dist-lib/ai/roteiros/crud-builder/entrevista.md +146 -0
  123. package/dist-lib/ai/roteiros/crud-builder/geracao.md +113 -0
  124. package/dist-lib/ai/roteiros/crud-builder/roteiro.md +89 -0
  125. package/dist-lib/ai/roteiros/drawers/roteiro.md +41 -0
  126. package/dist-lib/ai/roteiros/list-builder/blueprint.md +94 -0
  127. package/dist-lib/ai/roteiros/list-builder/entrevista.md +193 -0
  128. package/dist-lib/ai/roteiros/list-builder/geracao.md +63 -0
  129. package/dist-lib/ai/roteiros/list-builder/roteiro.md +91 -0
  130. package/dist-lib/ai/roteiros/module-replicator/roteiro.md +56 -0
  131. package/dist-lib/ai/roteiros/page-detail/roteiro.md +32 -0
  132. package/dist-lib/ai/roteiros/page-edit/roteiro.md +31 -0
  133. package/dist-lib/ai/roteiros/screen-composer/roteiro.md +95 -0
  134. package/dist-lib/chunks/{panel-B-liPlxr.mjs → panel-CN0ChoHM.mjs} +5 -2
  135. package/dist-lib/chunks/{panel-B-liPlxr.mjs.map → panel-CN0ChoHM.mjs.map} +1 -1
  136. package/dist-lib/chunks/{panel-DoNbjeqX.cjs → panel-Cpq1xHck.cjs} +5 -2
  137. package/dist-lib/chunks/{panel-DoNbjeqX.cjs.map → panel-Cpq1xHck.cjs.map} +1 -1
  138. package/dist-lib/index.cjs +1 -1
  139. package/dist-lib/index.mjs +2 -2
  140. package/dist-lib/preview/clientes.cjs +1 -1
  141. package/dist-lib/preview/clientes.mjs +1 -1
  142. package/dist-lib/src/components/ui/DataTable/data-table.d.ts.map +1 -1
  143. package/dist-lib/src/components/ui/DataTable/data-table.types.d.ts +20 -2
  144. package/dist-lib/src/components/ui/DataTable/data-table.types.d.ts.map +1 -1
  145. package/package.json +1 -1
  146. /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/blueprint.md +0 -0
  147. /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/entrevista.md +0 -0
  148. /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/geracao.md +0 -0
  149. /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,146 @@
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
+ > - **Componente na barra → `toolbar.customLeft`, não `actions`.** Os kinds de
94
+ > `ToolbarAction` são `button`/`dropdown`/`input` e nenhum recebe componente; pra um
95
+ > `DatePicker mode="range"` de período use `customLeft`, que renderiza entre o refresh e
96
+ > a busca. ⚠️ **Exige o DS `0.64.0` ou mais novo** — em `0.63.0` e anteriores a
97
+ > prop existe no tipo, o TS aceita e **nada renderiza**. Confira a versão antes de
98
+ > prometer o controle.
99
+ > - **toolbar.actions é SÓ pra caso pequeno e simples que NÃO reage com coluna** (ex.:
100
+ > data/período, escopo) — **label curta**, **máx ~2**. Se mexe com coluna, é grande, ou
101
+ > são muitos → **NÃO use o toolbar.**
102
+ > - **Muitos filtros, ou ligados a coluna** → SEMPRE os nativos **pré-aplicados** (chips no
103
+ > load) + drawer "Filtros". Nunca empilhar selects.
104
+ >
105
+ > Regra de ouro: **filtro é recurso da tabela (reativo), não UI montada na unha.**
106
+
107
+ - Busca global? (`enableSearch`)
108
+ - 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`.)
109
+ - 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).
110
+ **Toda ação destrutiva (Excluir) → confirmação OBRIGATÓRIA via `AlertModal`** (nunca
111
+ deletar direto). Pergunte o texto do confirm.
112
+ - Seleção + ações em massa (exportar, etc.)? (`selectionConfig` + bulk actions).
113
+ - Export: escopo (tudo / filtrado / selecionado) + formato (csv)? (`toolbar.enableExport`).
114
+ - Ação custom no toolbar (ex.: seletor de período por dropdown de meses, botão extra)? `toolbar.actions: ToolbarAction[]` (`button`/`dropdown`/`input`) — inline no desktop, colapsa no ⋯ no mobile. Oferecer só se o usuário pedir.
115
+ - **Componente** na barra (calendário de período, `Select` composto)? `toolbar.customLeft: ReactNode` — entre o refresh e a busca, antes das `actions`. É o único caminho: `ToolbarAction` não tem kind que receba componente. ⚠️ Exige o DS `0.64.0`+; antes dele a prop é inerte e falha em silêncio.
116
+
117
+ ## Fase 4 — Views, paginação & densidade
118
+
119
+ - Views (ver bloco obrigatório). Dois sabores, pergunte os dois:
120
+ - **Presets fixos** que VOCÊ define (`defaultViews`/`presetView`, ex.: "Ativos", "Alto valor").
121
+ - **Views do usuário**: ele cria/salva/persiste as próprias (`savedViewsService` + `persistId`).
122
+ - Paginação (tamanho inicial, opções) ou virtualização (10k+ linhas)?
123
+ - Totalizadores no rodapé? (`showTotalizers` + `aggregate`).
124
+
125
+ ## Fase 5 — Criar/editar/detalhe (drawers)
126
+
127
+ - Precisa criar/editar registro? → drawer estilo `NovoClienteDrawer` (Panel + FormField).
128
+ - **Quais campos no form?** (default: espelha as colunas editáveis). Pra cada campo:
129
+ **obrigatório?** **máscara** (CNPJ / telefone / CEP / moeda)? **validação** (formato,
130
+ min/max)? Todo label via `<FormField>` (nunca `<label>` cru) + `gap-form-gap`.
131
+ - Precisa ver detalhe ao clicar na linha? → `FinanceDetailPanel` (FloatingPanel).
132
+ - (Puxar `example-finance` na geração pra reusar esses padrões.)
133
+
134
+ ## Fase 6 — Kanban (opcional)
135
+
136
+ - Quer alternar tabela↔kanban? Se sim: qual campo agrupa as colunas (ex.: status)?
137
+ Cada lane = uma option desse campo. (`viewMode` controlado + `kanbanConfig`.)
138
+
139
+ ## Fase 7 — Estados (SEMPRE perguntar — sai faltando se não)
140
+
141
+ - **Loading** (`loading` + `renderLoading`): skeleton enquanto carrega — obrigatório em server mode.
142
+ - **Vazio** (`renderEmpty`): sem nenhum registro → "Nenhuma `<entidade>` ainda" + CTA _Adicionar_.
143
+ - **Sem resultado** (`renderNoResults`): filtro/busca sem match → "Nenhum resultado" + _Limpar filtros_.
144
+ - (Aceite defaults sensatos se o usuário não quiser customizar — mas **sempre wire os três**.)
145
+
146
+ 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`