@rendra-ui/web 2.2.2 → 2.4.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 (50) hide show
  1. package/README.md +94 -68
  2. package/bin/rendra.mjs +19 -7
  3. package/dist/base.css +1 -1
  4. package/dist/{button-BgSglLWN.js → button-C6rjowQi.js} +4 -4
  5. package/dist/{button-BgSglLWN.js.map → button-C6rjowQi.js.map} +1 -1
  6. package/dist/chart.js +5 -5
  7. package/dist/cli/auditar.js +66 -16
  8. package/dist/cli/auditar.js.map +1 -1
  9. package/dist/cli/codigos.js +2 -2
  10. package/dist/cli/executar-auditar.js +634 -0
  11. package/dist/cli/executar-auditar.js.map +1 -0
  12. package/dist/cli/help.js +7 -2
  13. package/dist/cli/help.js.map +1 -1
  14. package/dist/cli/trocar.js +2 -2
  15. package/dist/cli/typescript-loader.js +1 -1
  16. package/dist/{cn-Bo1YMupg.js → cn-DXDpTGsu.js} +2 -2
  17. package/dist/{cn-Bo1YMupg.js.map → cn-DXDpTGsu.js.map} +1 -1
  18. package/dist/{components-Dl15AjD-.js → components-hp7iWioq.js} +21 -4
  19. package/dist/components-hp7iWioq.js.map +1 -0
  20. package/dist/components.css +107 -1
  21. package/dist/document-viewer.js +4 -4
  22. package/dist/{empty-state-Be_tReTU.js → empty-state-CdaDLcsB.js} +50 -30
  23. package/dist/empty-state-CdaDLcsB.js.map +1 -0
  24. package/dist/index.js +135 -67
  25. package/dist/index.js.map +1 -1
  26. package/dist/{rendra-provider-DPulIoQB.js → rendra-provider-7jUgUHzR.js} +2 -2
  27. package/dist/{rendra-provider-DPulIoQB.js.map → rendra-provider-7jUgUHzR.js.map} +1 -1
  28. package/dist/rich-text-editor.js +3 -3
  29. package/dist/router-bridge.js +2 -2
  30. package/dist/tokens.css +11 -1
  31. package/dist/{tooltip-dC9gqkuv.js → tooltip-bdmbX6vC.js} +3 -3
  32. package/dist/{tooltip-dC9gqkuv.js.map → tooltip-bdmbX6vC.js.map} +1 -1
  33. package/dist/types/components/app-shell/app-shell.d.ts +22 -2
  34. package/dist/types/components/app-shell/shell-context.d.ts +7 -1
  35. package/dist/types/components/app-shell/types.d.ts +23 -0
  36. package/dist/types/components/layout/page-header.d.ts +17 -1
  37. package/dist/types/components/ui/brand-feedback-icon.d.ts +20 -3
  38. package/dist/types/components/ui/button-group.d.ts +8 -1
  39. package/dist/types/components/ui/empty-state.d.ts +4 -0
  40. package/dist/types/components/ui/error-page.d.ts +6 -1
  41. package/dist/types/components/ui/modal.d.ts +4 -0
  42. package/dist/types/components/ui/select.d.ts +4 -1
  43. package/dist/types/components/ui/wizard.d.ts +14 -1
  44. package/dist/types/lib/initials.d.ts +2 -0
  45. package/dist/{use-breakpoint-BUHd0Cbz.js → use-breakpoint-Dyp-0E_c.js} +2 -2
  46. package/dist/{use-breakpoint-BUHd0Cbz.js.map → use-breakpoint-Dyp-0E_c.js.map} +1 -1
  47. package/dist/widget-grid.js +2 -2
  48. package/package.json +7 -1
  49. package/dist/components-Dl15AjD-.js.map +0 -1
  50. package/dist/empty-state-Be_tReTU.js.map +0 -1
package/README.md CHANGED
@@ -1,18 +1,18 @@
1
1
  # Rendra Design System
2
2
 
3
- **Template de sistema e layout de sistema administrativo em React, gratuito e open source: design system completo e boilerplate com tokens, três templates, componentes, AppShell, telas prontas (dashboard, listagem, cadastro, CRM kanban, agenda e chat omnichannel), Storybook e testes de layout.** Feito para ser o ponto de partida de todos os projetos: layouts previsíveis, espaçamento equilibrado e funcionamento completo no celular. Para aplicar a outro sistema, você troca cores, fonte e ícones da marca, e nenhum componente muda.
3
+ **Template de sistema e layout de sistema administrativo em React, com código aberto sob a licença MIT: design system completo e boilerplate com tokens, três templates, componentes, AppShell, telas prontas (dashboard, listagem, cadastro, CRM kanban, agenda e chat omnichannel), Storybook e testes de layout.** Feito para ser o ponto de partida de todos os projetos: layouts previsíveis, espaçamento equilibrado e funcionamento completo no celular. Para aplicar a outro sistema, você troca cores, fonte e ícones da marca, e nenhum componente muda.
4
4
 
5
5
  ![React 19](https://img.shields.io/badge/React-19-149eca) ![TypeScript 5.9](https://img.shields.io/badge/TypeScript-5.9-3178c6) ![Tailwind CSS 4](https://img.shields.io/badge/Tailwind_CSS-4-38bdf8) ![Vite 8](https://img.shields.io/badge/Vite-8-646cff) ![Storybook 10](https://img.shields.io/badge/Storybook-10-ff4785) ![Playwright](https://img.shields.io/badge/testes-Vitest_e_Playwright-2ead33) [![CI](https://github.com/bsmagalhaes/rendra-ui-web/actions/workflows/ci.yml/badge.svg)](https://github.com/bsmagalhaes/rendra-ui-web/actions/workflows/ci.yml)
6
6
 
7
- **Veja funcionando, sem instalar nada:** [demo do app](https://bsmagalhaes.github.io/rendra-ui-web/) · [galeria com códigos de modelo](https://bsmagalhaes.github.io/rendra-ui-web/galeria/) · [Storybook](https://bsmagalhaes.github.io/rendra-ui-web/storybook/) · [vitrine de componentes](https://bsmagalhaes.github.io/rendra-ui-web/componentes/) · [atendimento](https://bsmagalhaes.github.io/rendra-ui-web/atendimento/) · [agenda](https://bsmagalhaes.github.io/rendra-ui-web/agenda/) · [kanban](https://bsmagalhaes.github.io/rendra-ui-web/kanban/). No demo, o menu do avatar troca modelo, paleta, modo e layout ao vivo.
7
+ **Veja funcionando, sem instalar nada:** [página de apresentação](https://bsmagalhaes.github.io/rendra-ui-web/) · [demo do app](https://bsmagalhaes.github.io/rendra-ui-web/demo/) · [galeria com códigos de modelo](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/) · [Storybook](https://bsmagalhaes.github.io/rendra-ui-web/storybook/) · [vitrine de componentes](https://bsmagalhaes.github.io/rendra-ui-web/demo/componentes/) · [atendimento](https://bsmagalhaes.github.io/rendra-ui-web/demo/atendimento/) · [agenda](https://bsmagalhaes.github.io/rendra-ui-web/demo/agenda/) · [kanban](https://bsmagalhaes.github.io/rendra-ui-web/demo/kanban/). No demo, o menu do avatar troca modelo, paleta, modo e layout ao vivo.
8
8
 
9
- | Atendimento omnichannel | Painel com widgets ajustáveis |
10
- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
11
- | [![Atendimento](docs/images/safira-atendimento.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=safira-atendimento) | [![Painel em widgets](docs/images/safira-dashboard-ajuste.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=safira-dashboard-ajuste) |
9
+ | Atendimento omnichannel | Painel com widgets ajustáveis |
10
+ | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
11
+ | [![Atendimento](docs/images/safira-atendimento.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=safira-atendimento) | [![Painel em widgets](docs/images/safira-dashboard-ajuste.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=safira-dashboard-ajuste) |
12
12
 
13
- | Calendário e agenda | Kanban |
14
- | ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
15
- | [![Calendário do mês](docs/images/safira-calendario.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=safira-calendario) | [![Kanban](docs/images/aurora-kanban.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=aurora-kanban) |
13
+ | Calendário e agenda | Kanban |
14
+ | ---------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
15
+ | [![Calendário do mês](docs/images/safira-calendario.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=safira-calendario) | [![Kanban](docs/images/aurora-kanban.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=aurora-kanban) |
16
16
 
17
17
  ---
18
18
 
@@ -41,11 +41,11 @@ E duas de boas práticas, verificadas pelo `npm run check:rules`: **nunca botão
41
41
 
42
42
  ## Galeria
43
43
 
44
- > **Clique em qualquer imagem** para abri-la em popup na [galeria do demo](https://bsmagalhaes.github.io/rendra-ui-web/galeria/), com setas para passar e Esc para fechar. (O GitHub não permite popup dentro do README; por isso as telas já aparecem em tamanho de leitura aqui e os grupos extras abrem na própria página.)
44
+ > **Clique em qualquer imagem** para abri-la em popup na [galeria do demo](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/), com setas para passar e Esc para fechar. (O GitHub não permite popup dentro do README; por isso as telas já aparecem em tamanho de leitura aqui e os grupos extras abrem na própria página.)
45
45
 
46
46
  ## Códigos de modelo
47
47
 
48
- Cada escolha visual tem um código curto: **T** para o tema (formato e fonte), **C** para as cores e **M** para o menu. `T1-C4-M5`, por exemplo, é o tema Safira com as cores Ardósia e o menu superior. Escolha na [galeria](https://bsmagalhaes.github.io/rendra-ui-web/galeria/), onde cada captura mostra seu código e o bloco "Monte seu código" abre o demo já aplicado, e informe o código no briefing: a IA já sabe o que aplicar e pula essas perguntas.
48
+ Cada escolha visual tem um código curto: **T** para o tema (formato e fonte), **C** para as cores e **M** para o menu. `T1-C4-M5`, por exemplo, é o tema Safira com as cores Ardósia e o menu superior. Escolha na [galeria](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/), onde cada captura mostra seu código e o bloco "Monte seu código" abre o demo já aplicado, e informe o código no briefing: a IA já sabe o que aplicar e pula essas perguntas.
49
49
 
50
50
  | Tema | Cores | Menu |
51
51
  | ------------------------------ | ---------------------------------------- | --------------------------------------------------- |
@@ -56,7 +56,7 @@ Cada escolha visual tem um código curto: **T** para o tema (formato e fonte), *
56
56
  | | | **M5** menu superior com lista suspensa |
57
57
  | | | **M6** menu superior com mega menu |
58
58
 
59
- No demo, o endereço também aplica um código: [`/?codigo=T1-C4-M5`](https://bsmagalhaes.github.io/rendra-ui-web/?codigo=T1-C4-M5). Os códigos ficam em [`src/config/presets.ts`](src/config/presets.ts).
59
+ No demo, o endereço também aplica um código: [`/?codigo=T1-C4-M5`](https://bsmagalhaes.github.io/rendra-ui-web/demo/?codigo=T1-C4-M5). Os códigos ficam em [`src/config/presets.ts`](src/config/presets.ts).
60
60
 
61
61
  ### Os três templates
62
62
 
@@ -64,44 +64,44 @@ Cada template tem formato, fonte, símbolo e paleta próprios.
64
64
 
65
65
  **Rendra Safira**: quadrado, como uma pedra lapidada. Azul #0B6FE0, verde #98D10A e fonte Poppins.
66
66
 
67
- | Painel | Listagem de clientes |
68
- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
69
- | [![Safira: painel](docs/images/safira-painel.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=safira-painel) | [![Safira: clientes](docs/images/safira-clientes.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=safira-clientes) |
67
+ | Painel | Listagem de clientes |
68
+ | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
69
+ | [![Safira: painel](docs/images/safira-painel.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=safira-painel) | [![Safira: clientes](docs/images/safira-clientes.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=safira-clientes) |
70
70
 
71
71
  **Rendra Equilíbrio**: o meio-termo, nem quadrado nem 100% arredondado. Violeta, ciano e fonte DM Sans.
72
72
 
73
- | Painel | Listagem de clientes |
74
- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
75
- | [![Equilíbrio: painel](docs/images/equilibrio-painel.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=equilibrio-painel) | [![Equilíbrio: clientes](docs/images/equilibrio-clientes.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=equilibrio-clientes) |
73
+ | Painel | Listagem de clientes |
74
+ | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
75
+ | [![Equilíbrio: painel](docs/images/equilibrio-painel.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=equilibrio-painel) | [![Equilíbrio: clientes](docs/images/equilibrio-clientes.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=equilibrio-clientes) |
76
76
 
77
77
  **Rendra Aurora**: 100% arredondado, como um novo dia. Verde-petróleo, laranja e fonte Inter.
78
78
 
79
- | Painel | Listagem de clientes |
80
- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
81
- | [![Aurora: painel](docs/images/aurora-painel.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=aurora-painel) | [![Aurora: clientes](docs/images/aurora-clientes.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=aurora-clientes) |
79
+ | Painel | Listagem de clientes |
80
+ | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
81
+ | [![Aurora: painel](docs/images/aurora-painel.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=aurora-painel) | [![Aurora: clientes](docs/images/aurora-clientes.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=aurora-clientes) |
82
82
 
83
83
  **Paleta Ardósia**: combinável com qualquer modelo. Azul-ardósia #2E414D e laranja #EA600D; com texto branco pedido, o gerador escurece o botão laranja para #C5510B, o tom mais próximo que passa AA (aqui no modelo Equilíbrio).
84
84
 
85
- | Painel | Listagem de clientes |
86
- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
87
- | [![Ardósia: painel](docs/images/ardosia-painel.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=ardosia-painel) | [![Ardósia: clientes](docs/images/ardosia-clientes.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=ardosia-clientes) |
85
+ | Painel | Listagem de clientes |
86
+ | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
87
+ | [![Ardósia: painel](docs/images/ardosia-painel.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=ardosia-painel) | [![Ardósia: clientes](docs/images/ardosia-clientes.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=ardosia-clientes) |
88
88
 
89
89
  ### Calendário, agenda e kanban
90
90
 
91
- | Agenda da semana (T2-C2) | Kanban no celular (T1-C1) |
92
- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
93
- | [![Agenda da semana](docs/images/equilibrio-agenda.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=equilibrio-agenda) | [![Kanban no celular](docs/images/safira-kanban-mobile.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=safira-kanban-mobile) |
91
+ | Agenda da semana (T2-C2) | Kanban no celular (T1-C1) |
92
+ | --------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
93
+ | [![Agenda da semana](docs/images/equilibrio-agenda.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=equilibrio-agenda) | [![Kanban no celular](docs/images/safira-kanban-mobile.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=safira-kanban-mobile) |
94
94
 
95
95
  <details>
96
96
  <summary><strong>Tipos de menu: M1 a M6</strong> (clique para abrir aqui mesmo)</summary>
97
97
 
98
- | M1: lateral recolhida, segunda barra | M2: lateral recolhida, submenu na sidebar |
99
- | ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
100
- | [![M1](docs/images/menu-m1.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=menu-m1) | [![M2](docs/images/menu-m2.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=menu-m2) |
101
- | **M3: lateral expandida, segunda barra** | **M4: lateral expandida, submenu na sidebar** |
102
- | [![M3](docs/images/menu-m3.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=menu-m3) | [![M4](docs/images/menu-m4.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=menu-m4) |
103
- | **M5: superior, lista suspensa** | **M6: superior, mega menu** |
104
- | [![M5](docs/images/menu-m5.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=menu-m5) | [![M6](docs/images/menu-m6.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=menu-m6) |
98
+ | M1: lateral recolhida, segunda barra | M2: lateral recolhida, submenu na sidebar |
99
+ | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
100
+ | [![M1](docs/images/menu-m1.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=menu-m1) | [![M2](docs/images/menu-m2.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=menu-m2) |
101
+ | **M3: lateral expandida, segunda barra** | **M4: lateral expandida, submenu na sidebar** |
102
+ | [![M3](docs/images/menu-m3.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=menu-m3) | [![M4](docs/images/menu-m4.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=menu-m4) |
103
+ | **M5: superior, lista suspensa** | **M6: superior, mega menu** |
104
+ | [![M5](docs/images/menu-m5.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=menu-m5) | [![M6](docs/images/menu-m6.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=menu-m6) |
105
105
 
106
106
  </details>
107
107
 
@@ -110,11 +110,11 @@ Cada template tem formato, fonte, símbolo e paleta próprios.
110
110
 
111
111
  O modelo (formato, fonte e símbolo) e a paleta (cores, degradês e sidebar) são camadas independentes: qualquer modelo aceita qualquer paleta. São 12 combinações (3 modelos × 4 paletas), todas na mesma tela de detalhe do cliente.
112
112
 
113
- | Modelo \ Paleta | Safira | Equilíbrio | Aurora | Ardósia |
114
- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
115
- | **Safira** (quadrado) | [![](docs/images/matriz-safira-safira.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-safira-safira) | [![](docs/images/matriz-safira-equilibrio.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-safira-equilibrio) | [![](docs/images/matriz-safira-aurora.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-safira-aurora) | [![](docs/images/matriz-safira-ardosia.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-safira-ardosia) |
116
- | **Equilíbrio** (meio-termo) | [![](docs/images/matriz-equilibrio-safira.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-equilibrio-safira) | [![](docs/images/matriz-equilibrio-equilibrio.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-equilibrio-equilibrio) | [![](docs/images/matriz-equilibrio-aurora.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-equilibrio-aurora) | [![](docs/images/matriz-equilibrio-ardosia.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-equilibrio-ardosia) |
117
- | **Aurora** (arredondado) | [![](docs/images/matriz-aurora-safira.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-aurora-safira) | [![](docs/images/matriz-aurora-equilibrio.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-aurora-equilibrio) | [![](docs/images/matriz-aurora-aurora.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-aurora-aurora) | [![](docs/images/matriz-aurora-ardosia.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=matriz-aurora-ardosia) |
113
+ | Modelo \ Paleta | Safira | Equilíbrio | Aurora | Ardósia |
114
+ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
115
+ | **Safira** (quadrado) | [![](docs/images/matriz-safira-safira.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-safira-safira) | [![](docs/images/matriz-safira-equilibrio.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-safira-equilibrio) | [![](docs/images/matriz-safira-aurora.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-safira-aurora) | [![](docs/images/matriz-safira-ardosia.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-safira-ardosia) |
116
+ | **Equilíbrio** (meio-termo) | [![](docs/images/matriz-equilibrio-safira.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-equilibrio-safira) | [![](docs/images/matriz-equilibrio-equilibrio.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-equilibrio-equilibrio) | [![](docs/images/matriz-equilibrio-aurora.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-equilibrio-aurora) | [![](docs/images/matriz-equilibrio-ardosia.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-equilibrio-ardosia) |
117
+ | **Aurora** (arredondado) | [![](docs/images/matriz-aurora-safira.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-aurora-safira) | [![](docs/images/matriz-aurora-equilibrio.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-aurora-equilibrio) | [![](docs/images/matriz-aurora-aurora.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-aurora-aurora) | [![](docs/images/matriz-aurora-ardosia.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=matriz-aurora-ardosia) |
118
118
 
119
119
  </details>
120
120
 
@@ -123,26 +123,26 @@ O modelo (formato, fonte e símbolo) e a paleta (cores, degradês e sidebar) sã
123
123
 
124
124
  Mesmo componente, mesma API: no celular a tabela vira cards, a sidebar vira gaveta e a navegação ganha uma barra inferior.
125
125
 
126
- | Safira | Equilíbrio | Aurora | Tabela em cards |
127
- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
128
- | [![](docs/images/safira-mobile.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=safira-mobile) | [![](docs/images/equilibrio-mobile.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=equilibrio-mobile) | [![](docs/images/aurora-mobile.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=aurora-mobile) | [![](docs/images/equilibrio-mobile-tabela.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=equilibrio-mobile-tabela) |
126
+ | Safira | Equilíbrio | Aurora | Tabela em cards |
127
+ | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
128
+ | [![](docs/images/safira-mobile.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=safira-mobile) | [![](docs/images/equilibrio-mobile.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=equilibrio-mobile) | [![](docs/images/aurora-mobile.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=aurora-mobile) | [![](docs/images/equilibrio-mobile-tabela.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=equilibrio-mobile-tabela) |
129
129
 
130
130
  </details>
131
131
 
132
132
  <details>
133
133
  <summary><strong>Modo escuro e outras telas</strong> (clique para abrir aqui mesmo)</summary>
134
134
 
135
- | Modo escuro (Safira) | Modo escuro (Equilíbrio) |
136
- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
137
- | [![](docs/images/safira-escuro.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=safira-escuro) | [![](docs/images/equilibrio-escuro.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=equilibrio-escuro) |
135
+ | Modo escuro (Safira) | Modo escuro (Equilíbrio) |
136
+ | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
137
+ | [![](docs/images/safira-escuro.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=safira-escuro) | [![](docs/images/equilibrio-escuro.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=equilibrio-escuro) |
138
138
 
139
- | Drawer com rodapé fixo (30/70) | Mega menu no menu superior |
140
- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
141
- | [![](docs/images/safira-drawer.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=safira-drawer) | [![](docs/images/aurora-mega-menu.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=aurora-mega-menu) |
139
+ | Drawer com rodapé fixo (30/70) | Mega menu no menu superior |
140
+ | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
141
+ | [![](docs/images/safira-drawer.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=safira-drawer) | [![](docs/images/aurora-mega-menu.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=aurora-mega-menu) |
142
142
 
143
- | Login (Aurora) |
144
- | ------------------------------------------------------------------------------------------------------------- |
145
- | [![](docs/images/aurora-login.png)](https://bsmagalhaes.github.io/rendra-ui-web/galeria/?imagem=aurora-login) |
143
+ | Login (Aurora) |
144
+ | ------------------------------------------------------------------------------------------------------------------- |
145
+ | [![](docs/images/aurora-login.webp)](https://bsmagalhaes.github.io/rendra-ui-web/demo/galeria/?imagem=aurora-login) |
146
146
 
147
147
  </details>
148
148
 
@@ -170,18 +170,18 @@ A marca fica isolada: as 4 cores e o degradê em `src/brand/palettes.ts`, o mode
170
170
 
171
171
  Todos em `src/components/ui`, um por finalidade, com o ícone de feedback da marca onde houver feedback.
172
172
 
173
- | Grupo | Componentes |
174
- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
175
- | **Ações** | Button (6 variantes, tamanhos, ícone, só ícone, carregando, largura total), ButtonGroup (agrupado ou segmentado), DropdownMenu e ActionBar (regra 100%, 30/70 e menu) |
176
- | **Formulário** | Input (máscaras de CPF, CNPJ, CPF ou CNPJ automático, telefone com seletor de DDI embutido e +55 por padrão, CEP, data, hora, moeda e percentual, com ícone, limpar e senha), Textarea com contador, Select (busca, múltiplo com chips, selecionar todos, contador, criar opção, busca remota), Checkbox com indeterminado e grupo, Radio em lista e em cards, Switch, DatePicker (data, período e horário, em pt-BR), Slider, Upload com arrastar e soltar e progresso, OtpInput (2FA), Field, Form, FormField e FormSection com React Hook Form e Zod, e validadores de CPF, CNPJ, telefone, CEP e data |
177
- | **Navegação** | Tabs (linha ou pílula, vira seletor quando não cabe), Breadcrumb, Pagination (completa, compacta ou "carregar mais") e Wizard/Stepper (etapas concluída, atual, pendente e com erro, com validação por etapa) |
178
- | **Dados** | Table com TanStack Table (seleção, expansão, ordenação, busca, colunas visíveis, ações em massa e por linha, densidade, estados vazio, carregando e erro, forma de cards no celular e **modo remoto**: 15 por página, carregando página por página, com busca e filtros em todos os registros), Card, StatCard, Badge, Avatar e grupo, List, Timeline, Accordion e Chart com Recharts (linha, barra, área e pizza) |
179
- | **Feedback** | BrandFeedbackIcon animado (check se desenhando, X se riscando), Toast com Sonner, Alert, Modal (confirmação, destrutiva, informativo e formulário), InfoHint (texto orientativo num ícone de informação que abre modal; também como `help` em PageHeader, CardTitle e FormSection), Drawer (header e rodapé fixos, confirmação de descarte, 30%, 40%, 50% ou 75% da tela), Popover, Tooltip, EmptyState, ErrorPage (404 e 500), Skeleton e Progress |
180
- | **Atendimento** | Chat omnichannel: ConversationList (foto com o logotipo do canal: WhatsApp, WhatsApp Web, Instagram, Facebook, TikTok, Google Meu Negócio e Reclame Aqui), ChatThread (cliente, atendente, robô e avisos; botão direito ou "…" para responder, reagir, editar e excluir; citação que leva à mensagem original; áudio em 1x, 1,5x e 2x; baixar anexos) e ChatComposer (textarea que cresce, anexos, emoji, mensagens rápidas, gravação de áudio, arrastar e soltar ou colar prints; no celular, campo, enviar e um botão de ações) |
181
- | **Conteúdo** | RichTextEditor (Tiptap): formatação completa, listas, alinhamento, links, tabela, imagem com 4 alças para redimensionar, colar print, arrastar imagens e modo HTML |
182
- | **Painel** | WidgetGrid: widgets que se arrastam e redimensionam no modo "Ajustar dashboard", com a arrumação salva; Chart com velocímetro de meta, funil com conversão, barras com linha, barras coloridas e empilhadas |
183
- | **Planejamento** | Calendar (mês, semana, dia e agenda em lista, no mesmo componente; no celular vira mês compacto com a lista do dia), Kanban (altura da tela, 5 etapas visíveis e rolagem lateral também pelo touchpad, rolagem infinita por etapa, (+) no título da etapa, totais em R$ de P&S e MRR por etapa e por cartão, arrastar no computador, menu "Mover para" no toque e no teclado, uma coluna por vez no celular, limite por coluna) e ImageViewer (imagens em popup, com setas, Esc, arrastar e pinça) |
184
- | **Layout** | Container (respiro igual em todos os lados), Stack, Inline, Grid (por tela ou por container query), Section e PageHeader |
173
+ | Grupo | Componentes |
174
+ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
175
+ | **Ações** | Button (6 variantes, tamanhos, ícone, só ícone, carregando, largura total), ButtonGroup (agrupado, na horizontal, vertical ou responsivo, ou segmentado), DropdownMenu e ActionBar (regra 100%, 30/70 e menu) |
176
+ | **Formulário** | Input (máscaras de CPF, CNPJ, CPF ou CNPJ automático, telefone com seletor de DDI embutido e +55 por padrão, CEP, data, hora, moeda e percentual, com ícone, limpar e senha), Textarea com contador, Select (busca, múltiplo com chips, selecionar todos, contador, criar opção, busca remota), Checkbox com indeterminado e grupo, Radio em lista e em cards, Switch, DatePicker (data, período e horário, em pt-BR), Slider, Upload com arrastar e soltar e progresso, OtpInput (2FA), Field, Form, FormField e FormSection com React Hook Form e Zod, e validadores de CPF, CNPJ, telefone, CEP e data |
177
+ | **Navegação** | Tabs (linha ou pílula, vira seletor quando não cabe), Breadcrumb, Pagination (completa, compacta ou "carregar mais") e Wizard/Stepper (rótulos próprios e etapa opcional com Pular em "Mais ações"; etapas concluída, atual, pendente e com erro, com validação por etapa) |
178
+ | **Dados** | Table com TanStack Table (seleção, expansão, ordenação, busca, colunas visíveis, ações em massa e por linha, densidade, estados vazio, carregando e erro, forma de cards no celular e **modo remoto**: 15 por página, carregando página por página, com busca e filtros em todos os registros), Card, StatCard, Badge, Avatar e grupo, List, Timeline, Accordion e Chart com Recharts (linha, barra, área e pizza) |
179
+ | **Feedback** | BrandFeedbackIcon animado (check se desenhando, X se riscando; cor da marca, selo ao lado e entrada `encaixe` por opção), Toast com Sonner, Alert, Modal (confirmação, destrutiva, informativo, com segundo botão opcional por `cancelLabel`, e formulário), InfoHint (texto orientativo num ícone de informação que abre modal; também como `help` em PageHeader, CardTitle e FormSection), Drawer (header e rodapé fixos, confirmação de descarte, 30%, 40%, 50% ou 75% da tela), Popover, Tooltip, EmptyState (`className="py-0 md:py-0"` zera o respiro vertical), ErrorPage (404 e 500, com `back={false}` para tirar o Voltar), Skeleton e Progress |
180
+ | **Atendimento** | Chat omnichannel: ConversationList (foto com o logotipo do canal: WhatsApp, WhatsApp Web, Instagram, Facebook, TikTok, Google Meu Negócio e Reclame Aqui), ChatThread (cliente, atendente, robô e avisos; botão direito ou "…" para responder, reagir, editar e excluir; citação que leva à mensagem original; áudio em 1x, 1,5x e 2x; baixar anexos) e ChatComposer (textarea que cresce, anexos, emoji, mensagens rápidas, gravação de áudio, arrastar e soltar ou colar prints; no celular, campo, enviar e um botão de ações) |
181
+ | **Conteúdo** | RichTextEditor (Tiptap): formatação completa, listas, alinhamento, links, tabela, imagem com 4 alças para redimensionar, colar print, arrastar imagens e modo HTML |
182
+ | **Painel** | WidgetGrid: widgets que se arrastam e redimensionam no modo "Ajustar dashboard", com a arrumação salva; Chart com velocímetro de meta, funil com conversão, barras com linha, barras coloridas e empilhadas |
183
+ | **Planejamento** | Calendar (mês, semana, dia e agenda em lista, no mesmo componente; no celular vira mês compacto com a lista do dia), Kanban (altura da tela, 5 etapas visíveis e rolagem lateral também pelo touchpad, rolagem infinita por etapa, (+) no título da etapa, totais em R$ de P&S e MRR por etapa e por cartão, arrastar no computador, menu "Mover para" no toque e no teclado, uma coluna por vez no celular, limite por coluna) e ImageViewer (imagens em popup, com setas, Esc, arrastar e pinça) |
184
+ | **Layout** | Container (respiro igual em todos os lados), Stack, Inline, Grid (por tela ou por container query), Section e PageHeader (título no corpo do celular por `bodyTitle`, sem reservar o bloco do título por `titleSpace`) |
185
185
 
186
186
  ### AppShell
187
187
 
@@ -191,6 +191,9 @@ Tudo configurável por props, com o padrão em `src/config/layout.ts`:
191
191
  - sidebar **recolhida** (só ícones, padrão) ou **expandida**, com opção de **abrir por cima do conteúdo** ao passar o mouse;
192
192
  - submenu em **segunda barra lateral** ou **dentro da sidebar**, e, no menu superior, **submenu navegável** ou **mega menu** com seções;
193
193
  - header sempre fixo, com título da página e trilha, busca global (**Ctrl+K**), notificações, tema e menu do usuário;
194
+ - logo no header do celular, no lugar do título e da trilha, pela prop `headerLogo`;
195
+ - seletor de espaço (empresa, unidade) no topo do menu do usuário, pela prop `workspaces`;
196
+ - menu do usuário enxuto: `userMenu` esconde Tema, Template ou Layout, um a um;
194
197
  - no celular, gaveta de navegação e barra inferior com até 4 itens.
195
198
 
196
199
  ### Telas base
@@ -206,13 +209,13 @@ Login, esqueci a senha, verificação em duas etapas (2FA), nova senha, cadastro
206
209
  - **Regressão visual** (`npm run test:visual`): 128 capturas comparadas com a referência aprovada. Pegam cor que mudou, espaçamento que quebrou e ícone que sumiu. As referências são geradas no Linux do CI; depois de uma mudança visual intencional, aplique o rótulo `atualizar-visual` no Pull Request.
207
210
  - **Testes unitários e de componente com Vitest e Testing Library** (`npm test`; `npm run test:coverage` com o piso por arquivo): comportamento de Table (ordenação, busca, paginação, seleção, ações em massa, modo remoto e cartões no celular), Select, Input (máscaras, centavos e busca de CEP e CNPJ), Modal, Drawer, campos de formulário e navegação, além de validadores, máscaras, buscas e o gerador de paletas (AA garantido em todas). Cada componente tem o teste ao lado, e ele vai junto quando você copia o componente para outro projeto.
208
211
  - **CI no GitHub Actions**: todo Pull Request passa por tipos, lint, formatação, regras, unitários, build, Storybook e os três testes no navegador. A `main` só aceita merge com tudo verde. Os alertas de segurança do GitHub avisam de dependência vulnerável; as atualizações de versão são feitas à mão (veja o `CONTRIBUTING.md`).
209
- - **Verificador de regras** (`npm run check:rules`): barra cor fixa, valor arbitrário, degrau fora da escala, estilo inline, fonte fixa, `100vh` e arquivos duplicados ou mobile.
212
+ - **Verificador de regras** (`npm run check:rules`): barra cor fixa, valor arbitrário, degrau fora da escala, estilo inline, fonte fixa, `100vh` e arquivos duplicados ou mobile. A mesma varredura, com as 17 regras, roda em qualquer projeto por `npx @rendra-ui/web auditar --all`.
210
213
 
211
214
  ---
212
215
 
213
216
  ## Stack
214
217
 
215
- React 19, TypeScript 5.9 (estrito), Vite 8, Tailwind CSS 4 (tema via `@theme`), shadcn/ui (copiado para o projeto), Radix UI, class-variance-authority, tailwind-merge com clsx, Lucide, React Router 8, TanStack Table 8, cmdk, Sonner, React Hook Form, Zod 4, IMask, React Day Picker 10, date-fns 4, Recharts 3, Storybook 10, Playwright com axe-core, Vitest, ESLint 9 (TypeScript, React Hooks e jsx-a11y) e Prettier com prettier-plugin-tailwindcss. Somente bibliotecas gratuitas e de código aberto.
218
+ React 19, TypeScript 5.9 (estrito), Vite 8, Tailwind CSS 4 (tema via `@theme`), shadcn/ui (copiado para o projeto), Radix UI, class-variance-authority, tailwind-merge com clsx, Lucide, React Router 8, TanStack Table 8, cmdk, Sonner, React Hook Form, Zod 4, IMask, React Day Picker 10, date-fns 4, Recharts 3, Storybook 10, Playwright com axe-core, Vitest, ESLint 9 (TypeScript, React Hooks e jsx-a11y) e Prettier com prettier-plugin-tailwindcss. Somente bibliotecas de código aberto.
216
219
 
217
220
  ---
218
221
 
@@ -274,6 +277,9 @@ npm run storybook # Storybook em http://localhost:6006
274
277
  | `npm run build-storybook` | Build estático do Storybook |
275
278
  | `npm run registry:build` | Gera o registry do shadcn (`registry.json`, `dist/r`) |
276
279
  | `npm run docs:images` | Regenera as imagens deste README (com o app rodando) |
280
+ | `npm run docs:og-image` | Regenera a imagem social do site (`og-image.png`) |
281
+ | `npm run pages:build` | Monta o site (página, demo, registry) em `.pages/` |
282
+ | `npm run test:site` | Testa a página de apresentação e a composição do site |
277
283
 
278
284
  No app, o menu do avatar troca **modelo**, **paleta**, **tema** e **layout**. As mesmas opções estão em Configurações.
279
285
 
@@ -356,6 +362,8 @@ import '@rendra-ui/web/components.css'
356
362
 
357
363
  O CSS já sai compilado (estratégia A: o host recebe `tokens.css`, `base.css` e `components.css` prontos, sem precisar ter o Tailwind instalado, e sem nenhuma variável do namespace do Tailwind vazar para o seu tema). `react-router` fica fora das dependências: quem usa React Router importa a ponte, `@rendra-ui/web/router-bridge`; quem não usa, não precisa dela. Os componentes pesados (`document-viewer`, `rich-text-editor`, `chart`, `widget-grid`) são subcaminhos próprios, para não engordar quem não usa.
358
364
 
365
+ **O que o `components.css` traz, e o que não traz.** Ele contém só as classes que os componentes do pacote usam por dentro e as `@utility` do Rendra. Classes de composição das suas próprias telas (`p-12`, `max-w-sm`, `flex-col`, `mb-0`) não estão garantidas: num host com Tailwind v4, deixe o seu Tailwind gerá-las e reproduza no `@theme` a escala do Rendra (espaço 0, px, 1, 2, 3, 4, 6, 8, 12, 16 e 24, raios por papel, cores `--rendra-*`); num host sem Tailwind, escreva o CSS de composição à mão com as variáveis `--rendra-*`. A receita completa e a lista de todas as `@utility` estão em [`docs/COMO_APLICAR.md`](docs/COMO_APLICAR.md), na seção "O CSS do pacote e as classes das suas telas".
366
+
359
367
  **Publicação:** uma tag `vX.Y.Z` empurrada para o repositório (`git push origin vX.Y.Z`) dispara o `.github/workflows/publish.yml`, que builda o pacote, roda o `verify:pack` e publica com `npm publish --provenance --access public`, depois de conferir que a tag bate com a `version` do `package.json`. Com o _trusted publishing_ do npm configurado para este repositório, o workflow dispensa o segredo `NPM_TOKEN`.
360
368
 
361
369
  ### CLI (`rendra`)
@@ -364,13 +372,31 @@ Três comandos. Forma segura, que não exige instalar nada: `npx @rendra-ui/web
364
372
 
365
373
  ```bash
366
374
  npx @rendra-ui/web codigos # lista o catálogo de códigos de componente
367
- npx @rendra-ui/web auditar [pasta] # regras genéricas de DESIGN_RULES.md no projeto de destino
375
+ npx @rendra-ui/web auditar [pasta...] [--all] [--ignore a,b] # regras de DESIGN_RULES.md no projeto de destino
368
376
  npx @rendra-ui/web trocar <DE> <PARA> --dry-run # simula a troca de uma variante do catálogo pela outra
369
377
  ```
370
378
 
371
379
  Nota: `npx rendra <comando>` só funciona com o pacote instalado neste projeto (ou instalado global, como `rendra <comando>` direto). Sem instalar, não use `npx rendra`: o nome `rendra` no npm pertence a outro pacote, não a este.
372
380
 
373
- `rendra auditar` aplica sete regras estáticas, sem IA (cor fixa, valor arbitrário, estilo inline, fonte fixa, `100vh`, degrau fora da escala, raio fixo), o mesmo tipo de checagem do `check:rules` deste repositório, aplicado a qualquer projeto. `rendra trocar` reescreve a prop literal que distingue duas variantes do catálogo (`ABA-001` para `ABA-002`, por exemplo), sempre com `--dry-run` primeiro: um elemento sem a prop conta como a variante padrão do componente (troca também esse caso, inserindo ou removendo a prop conforme o lado); prop dinâmica (`variant={x}`) nunca é reescrita, só listada para revisão manual, e troca entre componentes diferentes nunca edita, só aponta onde o componente aparece. Só `rendra trocar` precisa do `typescript` instalado no projeto de destino (`peerDependency` opcional do pacote), para ler e reescrever o JSX; sem ele, avisa e sai com erro.
381
+ `rendra auditar` aplica, por padrão, sete regras estáticas, sem IA (cor fixa, valor arbitrário, estilo inline, fonte fixa, `100vh`, degrau fora da escala, raio fixo), o mesmo tipo de checagem do `check:rules` deste repositório, aplicado a qualquer projeto. Sem flag e sem `rendra.config.json`, a saída e o código de saída são os de sempre (1 com violação, 0 sem).
382
+
383
+ **`--all`** liga as 17 regras do `check:rules`: as sete acima mais `var-inline`, `svg-marca`, `classe-dinamica`, `texto-estreito`, `primaria-como-texto`, `componente-duplicado`, `css-fora-do-lugar`, `botao-solto`, `texto-orientativo` e `variavel-sem-prefixo-rendra`. Use quando o projeto segue o vocabulário e as pastas do Rendra (`--rendra-*`, `src/brand`, `src/styles`, telas em `src/pages/app`); num projeto que não segue, desligue as regras que não fazem sentido em `rendra.config.json`. Com `--all`, pastas de marca e de estilos só passam pelo prefixo `--rendra-`, e `.test.`, `.stories.`, `node_modules`, `dist` e `build` não são varridos.
384
+
385
+ **`--ignore a,b`** pula pastas, por prefixo de pasta relativo ao projeto (sem glob): `src/brand` pula `src/brand` e tudo dentro, mas não `src/brand-novo`. Vale também `--ignore a --ignore b` e `--ignore=a,b`, com ou sem `--all`. **Várias pastas:** `auditar src extra` varre as duas. Com uma só pasta, ela é a base do projeto (o `file` da saída sai relativo a ela e o `rendra.config.json` é lido dela); com duas ou mais, a base é a pasta atual. Pasta fora da base dá erro claro, sem varrer nada.
386
+
387
+ **`rendra.config.json`** é opcional, fica na base do projeto e aceita cinco chaves, todas opcionais:
388
+
389
+ ```json
390
+ {
391
+ "pastas": ["src", "extra"],
392
+ "ignorar": ["src/gerado"],
393
+ "regras": { "botao-solto": false, "cor-fixa": false },
394
+ "pastasMarca": ["src/brand", "src/styles"],
395
+ "pastasTelas": ["src/pages/app"]
396
+ }
397
+ ```
398
+
399
+ `pastas` substitui o atalho para `src`; `ignorar` tem o efeito de `--ignore`; `regras` desliga qualquer um dos 17 identificadores (`false`), com ou sem `--all`; `pastasMarca` e `pastasTelas` valem com `--all`, e os padrões são os do exemplo. A flag vence o config e não soma: `--ignore` substitui `ignorar`, e duas ou mais pastas posicionais substituem `pastas`. JSON inválido, chave desconhecida, tipo errado ou regra desconhecida dão mensagem em português e código de saída 1, assim como flag desconhecida (`--foo`) e `--ignore` sem valor. `rendra auditar --help` mostra a ajuda geral. `rendra trocar` reescreve a prop literal que distingue duas variantes do catálogo (`ABA-001` para `ABA-002`, por exemplo), sempre com `--dry-run` primeiro: um elemento sem a prop conta como a variante padrão do componente (troca também esse caso, inserindo ou removendo a prop conforme o lado); prop dinâmica (`variant={x}`) nunca é reescrita, só listada para revisão manual, e troca entre componentes diferentes nunca edita, só aponta onde o componente aparece. Só `rendra trocar` precisa do `typescript` instalado no projeto de destino (`peerDependency` opcional do pacote), para ler e reescrever o JSX; sem ele, avisa e sai com erro.
374
400
 
375
401
  ### Skill de migração parcial
376
402
 
@@ -401,8 +427,8 @@ Nota: `npx rendra <comando>` só funciona com o pacote instalado neste projeto (
401
427
  **O que é o Rendra Design System?**
402
428
  Um template de sistema e design system open source em React, TypeScript e Tailwind CSS. Traz o layout de sistema administrativo pronto (menu, header fixo, rodapé de ações), telas base como dashboard, listagem, cadastro, CRM kanban, agenda e chat, e componentes acessíveis para criar sistemas novos ou migrar o layout de sistemas existentes.
403
429
 
404
- **É gratuito?**
405
- Sim. Licença MIT, só com bibliotecas gratuitas: React, Tailwind CSS, Radix, shadcn/ui, TanStack Table, Recharts e Tiptap. Nada de Tailwind Plus ou tema pago.
430
+ **Posso usar em projeto comercial?**
431
+ Sim. Licença MIT: você pode usar, copiar, alterar e distribuir, inclusive em projetos comerciais, mantendo o aviso de copyright e o arquivo `LICENSE`. As bibliotecas usadas são de código aberto: React, Tailwind CSS, Radix, shadcn/ui, TanStack Table, Recharts e Tiptap.
406
432
 
407
433
  **Funciona no celular?**
408
434
  Sim, de verdade: tudo é escrito primeiro para 360px, tabelas viram cartões, o menu vai para a barra inferior, não há rolagem horizontal e os alvos de toque têm pelo menos 44px. Os testes abrem cada tela em cinco larguras, nos três modelos, no modo claro e no escuro.
package/bin/rendra.mjs CHANGED
@@ -7,7 +7,9 @@
7
7
  *
8
8
  * Três subcomandos, mais `--help`/sem argumento (ver printHelp, `src/cli/help.ts`):
9
9
  * rendra codigos lista o catálogo de códigos de componente
10
- * rendra auditar [cwd] regras genéricas de DESIGN_RULES.md (padrão: cwd atual)
10
+ * rendra auditar [pasta...] [--all] [--ignore a,b]
11
+ * regras de DESIGN_RULES.md (padrão: cwd atual e as sete
12
+ * genéricas; --all liga as 17; rendra.config.json opcional)
11
13
  * rendra trocar <DE> <PARA> [--dry-run] troca a variante DE pela PARA no projeto
12
14
  */
13
15
  import { existsSync } from 'node:fs'
@@ -33,7 +35,7 @@ function printAudit(violations) {
33
35
  }
34
36
  for (const v of violations) {
35
37
  console.error(`\n${v.file}:${v.line} [${v.rule}] ${v.message}`)
36
- console.error(` ${v.source.slice(0, 160)}`)
38
+ if (v.source) console.error(` ${v.source.slice(0, 160)}`)
37
39
  }
38
40
  console.error(`\n${violations.length} violação(ões) das regras de design.`)
39
41
  }
@@ -71,11 +73,21 @@ async function main() {
71
73
  }
72
74
 
73
75
  if (command === 'auditar') {
74
- const cwd = rest.find((a) => !a.startsWith('--')) ?? process.cwd()
75
- const { auditar } = await importDist('auditar')
76
- const violations = auditar(cwd)
77
- printAudit(violations)
78
- process.exitCode = violations.length > 0 ? 1 : 0
76
+ // Toda a decisão (argumentos, base, config, precedência) mora em src/cli/executar-auditar.ts,
77
+ // com teste: aqui só se chama, imprime e define o código de saída.
78
+ const { executarAuditar } = await importDist('executar-auditar')
79
+ const resultado = executarAuditar(rest, process.cwd())
80
+ if ('erro' in resultado) {
81
+ console.error(resultado.erro)
82
+ process.exitCode = 1
83
+ return
84
+ }
85
+ if ('ajuda' in resultado) {
86
+ console.log(resultado.ajuda)
87
+ return
88
+ }
89
+ printAudit(resultado.violacoes)
90
+ process.exitCode = resultado.violacoes.length > 0 ? 1 : 0
79
91
  return
80
92
  }
81
93
 
package/dist/base.css CHANGED
@@ -1,4 +1,4 @@
1
- /*! Rendra Design System v2.2.2 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
1
+ /*! Rendra Design System v2.4.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
2
2
 
3
3
  @layer base {
4
4
  *,
@@ -1,6 +1,6 @@
1
- /*! Rendra Design System v2.2.2 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
2
- import { t as cn } from "./cn-Bo1YMupg.js";
3
- import { p as resolveCatalogCode } from "./components-Dl15AjD-.js";
1
+ /*! Rendra Design System v2.4.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
2
+ import { t as cn } from "./cn-DXDpTGsu.js";
3
+ import { p as resolveCatalogCode } from "./components-hp7iWioq.js";
4
4
  import { Loader2 } from "lucide-react";
5
5
  import { Slot } from "radix-ui";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -140,4 +140,4 @@ var Button = forwardRef(function Button({ className, variant, size, icon, iconRi
140
140
  //#endregion
141
141
  export { usePrefersReducedMotion as i, buttonVariants as n, Spinner as r, Button as t };
142
142
 
143
- //# sourceMappingURL=button-BgSglLWN.js.map
143
+ //# sourceMappingURL=button-C6rjowQi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"button-BgSglLWN.js","names":[],"sources":["../src/hooks/use-reduced-motion.ts","../src/components/ui/spinner.tsx","../src/components/ui/button.tsx"],"sourcesContent":["import { useSyncExternalStore } from 'react'\n\n/*\n * Único hook de leitura de \"menos movimento\" do sistema operacional (prefers-reduced-motion).\n * Usado pelo Spinner e pelo Progress indeterminado para parar a animação sem depender só do\n * CSS, e assim ficar testável (mocke matchMedia para simular a preferência).\n */\n\nfunction subscribe(cb: () => void) {\n const mq = matchMedia('(prefers-reduced-motion: reduce)')\n mq.addEventListener('change', cb)\n return () => mq.removeEventListener('change', cb)\n}\n\nfunction getCurrent() {\n return matchMedia('(prefers-reduced-motion: reduce)').matches\n}\n\nexport function usePrefersReducedMotion() {\n return useSyncExternalStore(subscribe, getCurrent, () => false)\n}\n","import { Loader2 } from 'lucide-react'\nimport { usePrefersReducedMotion } from '@/hooks/use-reduced-motion'\nimport { cn } from '@/lib/cn'\n\n/*\n * Indicador de carregamento único do sistema (A17 do plano da v2). Substitui qualquer\n * `Loader2 animate-spin` solto em Button, Input e Select. Sem label é decorativo\n * (aria-hidden); com label, anuncia o carregamento a quem usa leitor de tela. Para de girar\n * quando o sistema pede menos movimento.\n */\n\nexport interface SpinnerProps {\n size?: 'sm' | 'md' | 'lg'\n /** Nome do que está carregando. Vazio (padrão): decorativo, sem anúncio de leitor de tela. */\n label?: string\n className?: string\n}\n\nconst sizeClass: Record<NonNullable<SpinnerProps['size']>, string> = {\n sm: 'size-icon-sm',\n md: 'size-icon-md',\n lg: 'size-icon-lg',\n}\n\nexport function Spinner({ size = 'md', label, className }: SpinnerProps) {\n const reduced = usePrefersReducedMotion()\n const icon = (\n <Loader2 aria-hidden className={cn(sizeClass[size], reduced ? '' : 'animate-spin')} />\n )\n\n if (!label) {\n return (\n <span data-rendra=\"SPIN-001\" aria-hidden className={cn('inline-flex', className)}>\n {icon}\n </span>\n )\n }\n\n return (\n <span\n data-rendra=\"SPIN-001\"\n role=\"status\"\n className={cn('inline-flex items-center gap-2', className)}\n >\n {icon}\n <span className=\"sr-only\">{label}</span>\n </span>\n )\n}\n","import { cva, type VariantProps } from 'class-variance-authority'\nimport { Slot } from 'radix-ui'\nimport { forwardRef, type ButtonHTMLAttributes, type ReactNode } from 'react'\nimport { resolveCatalogCode } from '@/catalog/components'\nimport { Spinner } from '@/components/ui/spinner'\nimport { cn } from '@/lib/cn'\n\n/**\n * Botão único do sistema. Variantes, tamanho, ícone, só ícone, carregamento e\n * largura total são props: nunca crie outro arquivo de botão.\n * Altura vem de h-control-*: 44px ou mais no mobile, compacta a partir de md.\n */\nexport const buttonVariants = cva(\n 'inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-control font-medium whitespace-nowrap transition-[color,background-color,border-color,box-shadow,transform] duration-150 ease-out select-none active:scale-98 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 motion-reduce:active:scale-100 [&_svg]:pointer-events-none [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n // Hover troca para a cor de hover da marca e eleva um nível; pressionar comprime.\n primary:\n 'bg-primary text-primary-foreground shadow-sm hover:bg-primary-hover hover:text-primary-hover-foreground hover:shadow-md active:bg-primary-hover active:text-primary-hover-foreground active:shadow-sm',\n secondary:\n 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary-hover hover:text-secondary-hover-foreground hover:shadow-md active:bg-secondary-hover active:text-secondary-hover-foreground active:shadow-sm',\n outline:\n 'border border-input bg-card text-foreground hover:border-primary hover:bg-primary-soft hover:text-primary-soft-foreground active:bg-primary-soft',\n // Transparentes: no hover, assumem a cor primária do template.\n ghost:\n 'text-foreground hover:bg-primary-soft hover:text-primary-soft-foreground active:bg-primary-soft',\n destructive:\n 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive-hover hover:shadow-md active:bg-destructive-hover active:shadow-sm',\n link: 'min-h-touch min-w-touch text-primary-text underline-offset-4 hover:text-primary-hover hover:underline md:min-h-0 md:min-w-0',\n },\n size: {\n sm: 'h-control-sm px-3 text-sm [&_svg]:size-icon-sm',\n md: 'h-control-md px-4 text-sm [&_svg]:size-icon-sm',\n lg: 'h-control-lg px-6 text-base [&_svg]:size-icon-md',\n },\n iconOnly: { true: 'px-0', false: '' },\n fullWidth: { true: 'w-full', false: '' },\n },\n compoundVariants: [\n { iconOnly: true, size: 'sm', className: 'w-control-sm' },\n { iconOnly: true, size: 'md', className: 'w-control-md' },\n { iconOnly: true, size: 'lg', className: 'w-control-lg' },\n { variant: 'link', className: 'h-auto px-0' },\n ],\n defaultVariants: { variant: 'primary', size: 'md', iconOnly: false, fullWidth: false },\n },\n)\n\ntype Variants = VariantProps<typeof buttonVariants>\n\nexport interface ButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement>, Omit<Variants, 'iconOnly' | 'fullWidth'> {\n /** Ícone à esquerda do texto (ou o próprio conteúdo, com iconOnly). */\n icon?: ReactNode\n /** Ícone à direita do texto. */\n iconRight?: ReactNode\n /** Botão só com ícone: quadrado, e aria-label passa a ser obrigatório. */\n iconOnly?: boolean\n /** Mostra indicador, bloqueia cliques e marca aria-busy. */\n loading?: boolean\n /** Ocupa toda a largura do contêiner. */\n fullWidth?: boolean\n /** Renderiza o filho (ex.: <Link>) com a aparência de botão. */\n asChild?: boolean\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(\n {\n className,\n variant,\n size,\n icon,\n iconRight,\n iconOnly = false,\n loading = false,\n fullWidth = false,\n asChild = false,\n disabled,\n type = 'button',\n children,\n ...props\n },\n ref,\n) {\n if (import.meta.env.DEV && iconOnly && !props['aria-label']) {\n console.warn('Button com iconOnly precisa de aria-label.')\n }\n const classes = cn(buttonVariants({ variant, size, iconOnly, fullWidth }), className)\n const code = resolveCatalogCode('Button', { variant: variant ?? 'primary' })\n\n if (asChild) {\n return (\n <Slot.Root ref={ref} data-rendra={code} className={classes} {...props}>\n {children}\n </Slot.Root>\n )\n }\n\n // Ícone dentro do botão segue o tamanho do próprio botão (sm/md -> sm, lg -> md, como o\n // [&_svg]:size-icon-* de buttonVariants já fazia com o Loader2 solto).\n const leading = loading ? <Spinner size={size === 'lg' ? 'md' : 'sm'} /> : icon\n return (\n <button\n ref={ref}\n type={type}\n data-rendra={code}\n className={classes}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n {...props}\n >\n {leading}\n {iconOnly ? (loading ? null : children) : children}\n {!iconOnly && iconRight}\n </button>\n )\n})\n"],"mappings":";;;;;;;;;AAQA,SAAS,UAAU,IAAgB;CACjC,MAAM,KAAK,WAAW,kCAAkC;CACxD,GAAG,iBAAiB,UAAU,EAAE;CAChC,aAAa,GAAG,oBAAoB,UAAU,EAAE;AAClD;AAEA,SAAS,aAAa;CACpB,OAAO,WAAW,kCAAkC,CAAC,CAAC;AACxD;AAEA,SAAgB,0BAA0B;CACxC,OAAO,qBAAqB,WAAW,kBAAkB,KAAK;AAChE;;;ACFA,IAAM,YAA+D;CACnE,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,SAAgB,QAAQ,EAAE,OAAO,MAAM,OAAO,aAA2B;CACvE,MAAM,UAAU,wBAAwB;CACxC,MAAM,OACJ,oBAAC,SAAD;EAAS,eAAA;EAAY,WAAW,GAAG,UAAU,OAAO,UAAU,KAAK,cAAc;CAAI,CAAA;CAGvF,IAAI,CAAC,OACH,OACE,oBAAC,QAAD;EAAM,eAAY;EAAW,eAAA;EAAY,WAAW,GAAG,eAAe,SAAS;EAC5E,UAAA;CACG,CAAA;CAIV,OACE,qBAAC,QAAD;EACE,eAAY;EACZ,MAAK;EACL,WAAW,GAAG,kCAAkC,SAAS;EAH3D,UAAA,CAKG,MACD,oBAAC,QAAD;GAAM,WAAU;GAAW,UAAA;EAAY,CAAA,CACnC;;AAEV;;;;;;;;ACpCA,IAAa,iBAAiB,IAC5B,uaACA;CACE,UAAU;EACR,SAAS;GAEP,SACE;GACF,WACE;GACF,SACE;GAEF,OACE;GACF,aACE;GACF,MAAM;EACR;EACA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,UAAU;GAAE,MAAM;GAAQ,OAAO;EAAG;EACpC,WAAW;GAAE,MAAM;GAAU,OAAO;EAAG;CACzC;CACA,kBAAkB;EAChB;GAAE,UAAU;GAAM,MAAM;GAAM,WAAW;EAAe;EACxD;GAAE,UAAU;GAAM,MAAM;GAAM,WAAW;EAAe;EACxD;GAAE,UAAU;GAAM,MAAM;GAAM,WAAW;EAAe;EACxD;GAAE,SAAS;GAAQ,WAAW;EAAc;CAC9C;CACA,iBAAiB;EAAE,SAAS;EAAW,MAAM;EAAM,UAAU;EAAO,WAAW;CAAM;AACvF,CACF;AAoBA,IAAa,SAAS,WAA2C,SAAS,OACxE,EACE,WACA,SACA,MACA,MACA,WACA,WAAW,OACX,UAAU,OACV,YAAY,OACZ,UAAU,OACV,UACA,OAAO,UACP,UACA,GAAG,SAEL,KACA;CAIA,MAAM,UAAU,GAAG,eAAe;EAAE;EAAS;EAAM;EAAU;CAAU,CAAC,GAAG,SAAS;CACpF,MAAM,OAAO,mBAAmB,UAAU,EAAE,SAAS,WAAW,UAAU,CAAC;CAE3E,IAAI,SACF,OACE,oBAAC,KAAK,MAAN;EAAgB;EAAK,eAAa;EAAM,WAAW;EAAS,GAAI;EAC7D;CACQ,CAAA;CAMf,MAAM,UAAU,UAAU,oBAAC,SAAD,EAAS,MAAM,SAAS,OAAO,OAAO,KAAO,CAAA,IAAI;CAC3E,OACE,qBAAC,UAAD;EACO;EACC;EACN,eAAa;EACb,WAAW;EACX,UAAU,YAAY;EACtB,aAAW,WAAW,KAAA;EACtB,GAAI;EAPN,UAAA;GASG;GACA,WAAY,UAAU,OAAO,WAAY;GACzC,CAAC,YAAY;EACR;;AAEZ,CAAC"}
1
+ {"version":3,"file":"button-C6rjowQi.js","names":[],"sources":["../src/hooks/use-reduced-motion.ts","../src/components/ui/spinner.tsx","../src/components/ui/button.tsx"],"sourcesContent":["import { useSyncExternalStore } from 'react'\n\n/*\n * Único hook de leitura de \"menos movimento\" do sistema operacional (prefers-reduced-motion).\n * Usado pelo Spinner e pelo Progress indeterminado para parar a animação sem depender só do\n * CSS, e assim ficar testável (mocke matchMedia para simular a preferência).\n */\n\nfunction subscribe(cb: () => void) {\n const mq = matchMedia('(prefers-reduced-motion: reduce)')\n mq.addEventListener('change', cb)\n return () => mq.removeEventListener('change', cb)\n}\n\nfunction getCurrent() {\n return matchMedia('(prefers-reduced-motion: reduce)').matches\n}\n\nexport function usePrefersReducedMotion() {\n return useSyncExternalStore(subscribe, getCurrent, () => false)\n}\n","import { Loader2 } from 'lucide-react'\nimport { usePrefersReducedMotion } from '@/hooks/use-reduced-motion'\nimport { cn } from '@/lib/cn'\n\n/*\n * Indicador de carregamento único do sistema (A17 do plano da v2). Substitui qualquer\n * `Loader2 animate-spin` solto em Button, Input e Select. Sem label é decorativo\n * (aria-hidden); com label, anuncia o carregamento a quem usa leitor de tela. Para de girar\n * quando o sistema pede menos movimento.\n */\n\nexport interface SpinnerProps {\n size?: 'sm' | 'md' | 'lg'\n /** Nome do que está carregando. Vazio (padrão): decorativo, sem anúncio de leitor de tela. */\n label?: string\n className?: string\n}\n\nconst sizeClass: Record<NonNullable<SpinnerProps['size']>, string> = {\n sm: 'size-icon-sm',\n md: 'size-icon-md',\n lg: 'size-icon-lg',\n}\n\nexport function Spinner({ size = 'md', label, className }: SpinnerProps) {\n const reduced = usePrefersReducedMotion()\n const icon = (\n <Loader2 aria-hidden className={cn(sizeClass[size], reduced ? '' : 'animate-spin')} />\n )\n\n if (!label) {\n return (\n <span data-rendra=\"SPIN-001\" aria-hidden className={cn('inline-flex', className)}>\n {icon}\n </span>\n )\n }\n\n return (\n <span\n data-rendra=\"SPIN-001\"\n role=\"status\"\n className={cn('inline-flex items-center gap-2', className)}\n >\n {icon}\n <span className=\"sr-only\">{label}</span>\n </span>\n )\n}\n","import { cva, type VariantProps } from 'class-variance-authority'\nimport { Slot } from 'radix-ui'\nimport { forwardRef, type ButtonHTMLAttributes, type ReactNode } from 'react'\nimport { resolveCatalogCode } from '@/catalog/components'\nimport { Spinner } from '@/components/ui/spinner'\nimport { cn } from '@/lib/cn'\n\n/**\n * Botão único do sistema. Variantes, tamanho, ícone, só ícone, carregamento e\n * largura total são props: nunca crie outro arquivo de botão.\n * Altura vem de h-control-*: 44px ou mais no mobile, compacta a partir de md.\n */\nexport const buttonVariants = cva(\n 'inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-control font-medium whitespace-nowrap transition-[color,background-color,border-color,box-shadow,transform] duration-150 ease-out select-none active:scale-98 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 motion-reduce:active:scale-100 [&_svg]:pointer-events-none [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n // Hover troca para a cor de hover da marca e eleva um nível; pressionar comprime.\n primary:\n 'bg-primary text-primary-foreground shadow-sm hover:bg-primary-hover hover:text-primary-hover-foreground hover:shadow-md active:bg-primary-hover active:text-primary-hover-foreground active:shadow-sm',\n secondary:\n 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary-hover hover:text-secondary-hover-foreground hover:shadow-md active:bg-secondary-hover active:text-secondary-hover-foreground active:shadow-sm',\n outline:\n 'border border-input bg-card text-foreground hover:border-primary hover:bg-primary-soft hover:text-primary-soft-foreground active:bg-primary-soft',\n // Transparentes: no hover, assumem a cor primária do template.\n ghost:\n 'text-foreground hover:bg-primary-soft hover:text-primary-soft-foreground active:bg-primary-soft',\n destructive:\n 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive-hover hover:shadow-md active:bg-destructive-hover active:shadow-sm',\n link: 'min-h-touch min-w-touch text-primary-text underline-offset-4 hover:text-primary-hover hover:underline md:min-h-0 md:min-w-0',\n },\n size: {\n sm: 'h-control-sm px-3 text-sm [&_svg]:size-icon-sm',\n md: 'h-control-md px-4 text-sm [&_svg]:size-icon-sm',\n lg: 'h-control-lg px-6 text-base [&_svg]:size-icon-md',\n },\n iconOnly: { true: 'px-0', false: '' },\n fullWidth: { true: 'w-full', false: '' },\n },\n compoundVariants: [\n { iconOnly: true, size: 'sm', className: 'w-control-sm' },\n { iconOnly: true, size: 'md', className: 'w-control-md' },\n { iconOnly: true, size: 'lg', className: 'w-control-lg' },\n { variant: 'link', className: 'h-auto px-0' },\n ],\n defaultVariants: { variant: 'primary', size: 'md', iconOnly: false, fullWidth: false },\n },\n)\n\ntype Variants = VariantProps<typeof buttonVariants>\n\nexport interface ButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement>, Omit<Variants, 'iconOnly' | 'fullWidth'> {\n /** Ícone à esquerda do texto (ou o próprio conteúdo, com iconOnly). */\n icon?: ReactNode\n /** Ícone à direita do texto. */\n iconRight?: ReactNode\n /** Botão só com ícone: quadrado, e aria-label passa a ser obrigatório. */\n iconOnly?: boolean\n /** Mostra indicador, bloqueia cliques e marca aria-busy. */\n loading?: boolean\n /** Ocupa toda a largura do contêiner. */\n fullWidth?: boolean\n /** Renderiza o filho (ex.: <Link>) com a aparência de botão. */\n asChild?: boolean\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(\n {\n className,\n variant,\n size,\n icon,\n iconRight,\n iconOnly = false,\n loading = false,\n fullWidth = false,\n asChild = false,\n disabled,\n type = 'button',\n children,\n ...props\n },\n ref,\n) {\n if (import.meta.env.DEV && iconOnly && !props['aria-label']) {\n console.warn('Button com iconOnly precisa de aria-label.')\n }\n const classes = cn(buttonVariants({ variant, size, iconOnly, fullWidth }), className)\n const code = resolveCatalogCode('Button', { variant: variant ?? 'primary' })\n\n if (asChild) {\n return (\n <Slot.Root ref={ref} data-rendra={code} className={classes} {...props}>\n {children}\n </Slot.Root>\n )\n }\n\n // Ícone dentro do botão segue o tamanho do próprio botão (sm/md -> sm, lg -> md, como o\n // [&_svg]:size-icon-* de buttonVariants já fazia com o Loader2 solto).\n const leading = loading ? <Spinner size={size === 'lg' ? 'md' : 'sm'} /> : icon\n return (\n <button\n ref={ref}\n type={type}\n data-rendra={code}\n className={classes}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n {...props}\n >\n {leading}\n {iconOnly ? (loading ? null : children) : children}\n {!iconOnly && iconRight}\n </button>\n )\n})\n"],"mappings":";;;;;;;;;AAQA,SAAS,UAAU,IAAgB;CACjC,MAAM,KAAK,WAAW,kCAAkC;CACxD,GAAG,iBAAiB,UAAU,EAAE;CAChC,aAAa,GAAG,oBAAoB,UAAU,EAAE;AAClD;AAEA,SAAS,aAAa;CACpB,OAAO,WAAW,kCAAkC,CAAC,CAAC;AACxD;AAEA,SAAgB,0BAA0B;CACxC,OAAO,qBAAqB,WAAW,kBAAkB,KAAK;AAChE;;;ACFA,IAAM,YAA+D;CACnE,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,SAAgB,QAAQ,EAAE,OAAO,MAAM,OAAO,aAA2B;CACvE,MAAM,UAAU,wBAAwB;CACxC,MAAM,OACJ,oBAAC,SAAD;EAAS,eAAA;EAAY,WAAW,GAAG,UAAU,OAAO,UAAU,KAAK,cAAc;CAAI,CAAA;CAGvF,IAAI,CAAC,OACH,OACE,oBAAC,QAAD;EAAM,eAAY;EAAW,eAAA;EAAY,WAAW,GAAG,eAAe,SAAS;EAC5E,UAAA;CACG,CAAA;CAIV,OACE,qBAAC,QAAD;EACE,eAAY;EACZ,MAAK;EACL,WAAW,GAAG,kCAAkC,SAAS;EAH3D,UAAA,CAKG,MACD,oBAAC,QAAD;GAAM,WAAU;GAAW,UAAA;EAAY,CAAA,CACnC;;AAEV;;;;;;;;ACpCA,IAAa,iBAAiB,IAC5B,uaACA;CACE,UAAU;EACR,SAAS;GAEP,SACE;GACF,WACE;GACF,SACE;GAEF,OACE;GACF,aACE;GACF,MAAM;EACR;EACA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,UAAU;GAAE,MAAM;GAAQ,OAAO;EAAG;EACpC,WAAW;GAAE,MAAM;GAAU,OAAO;EAAG;CACzC;CACA,kBAAkB;EAChB;GAAE,UAAU;GAAM,MAAM;GAAM,WAAW;EAAe;EACxD;GAAE,UAAU;GAAM,MAAM;GAAM,WAAW;EAAe;EACxD;GAAE,UAAU;GAAM,MAAM;GAAM,WAAW;EAAe;EACxD;GAAE,SAAS;GAAQ,WAAW;EAAc;CAC9C;CACA,iBAAiB;EAAE,SAAS;EAAW,MAAM;EAAM,UAAU;EAAO,WAAW;CAAM;AACvF,CACF;AAoBA,IAAa,SAAS,WAA2C,SAAS,OACxE,EACE,WACA,SACA,MACA,MACA,WACA,WAAW,OACX,UAAU,OACV,YAAY,OACZ,UAAU,OACV,UACA,OAAO,UACP,UACA,GAAG,SAEL,KACA;CAIA,MAAM,UAAU,GAAG,eAAe;EAAE;EAAS;EAAM;EAAU;CAAU,CAAC,GAAG,SAAS;CACpF,MAAM,OAAO,mBAAmB,UAAU,EAAE,SAAS,WAAW,UAAU,CAAC;CAE3E,IAAI,SACF,OACE,oBAAC,KAAK,MAAN;EAAgB;EAAK,eAAa;EAAM,WAAW;EAAS,GAAI;EAC7D;CACQ,CAAA;CAMf,MAAM,UAAU,UAAU,oBAAC,SAAD,EAAS,MAAM,SAAS,OAAO,OAAO,KAAO,CAAA,IAAI;CAC3E,OACE,qBAAC,UAAD;EACO;EACC;EACN,eAAa;EACb,WAAW;EACX,UAAU,YAAY;EACtB,aAAW,WAAW,KAAA;EACtB,GAAI;EAPN,UAAA;GASG;GACA,WAAY,UAAU,OAAO,WAAY;GACzC,CAAC,YAAY;EACR;;AAEZ,CAAC"}
package/dist/chart.js CHANGED
@@ -1,8 +1,8 @@
1
- /*! Rendra Design System v2.2.2 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
2
- import { t as cn } from "./cn-Bo1YMupg.js";
3
- import { p as resolveCatalogCode } from "./components-Dl15AjD-.js";
4
- import { t as Button } from "./button-BgSglLWN.js";
5
- import { n as useBreakpoint } from "./use-breakpoint-BUHd0Cbz.js";
1
+ /*! Rendra Design System v2.4.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
2
+ import { t as cn } from "./cn-DXDpTGsu.js";
3
+ import { p as resolveCatalogCode } from "./components-hp7iWioq.js";
4
+ import { t as Button } from "./button-C6rjowQi.js";
5
+ import { n as useBreakpoint } from "./use-breakpoint-Dyp-0E_c.js";
6
6
  import { ArrowDown, BarChart3, List } from "lucide-react";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { useId, useRef, useState } from "react";