@aspprev/versi-ds 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,461 +1,212 @@
1
- # @aspprev/versi-ds
1
+ # VERSI Design System
2
2
 
3
- Biblioteca de componentes React e fundamentos visuais da VERSI para construir interfaces consistentes. Reúne controles de formulário, navegação, tabelas, gráficos, diálogos, feedback, tipografia, tokens, temas e recursos de acessibilidade.
3
+ Biblioteca React de componentes, tokens, temas e utilitários para padronizar as interfaces dos produtos VERSI.
4
4
 
5
- Use o DS para compor a interface; a aplicação continua responsável por dados, validação de negócio, requisições, navegação e persistência das preferências do usuário.
5
+ O [Storybook](#storybook) é a documentação visual oficial: nele você pode explorar componentes, foundations, temas, padrões de composição e estados acessíveis.
6
6
 
7
- ## Por onde começar
7
+ Site oficial: [versitec.com.br](https://versitec.com.br/) · [Storybook online](https://versi-design-system.vercel.app/)
8
8
 
9
- 1. Instale o pacote e as dependências das camadas que vai usar.
10
- 2. Importe os estilos uma vez na entrada da aplicação.
11
- 3. Configure fonte, tema e preferências no elemento `html`.
12
- 4. Comece pelos exemplos de componentes e formulários abaixo.
13
- 5. Consulte o Storybook para explorar variantes, estados e propriedades.
14
-
15
- ## Instalação e consumo
16
-
17
- Depois da publicação:
9
+ ## Instalação
18
10
 
19
11
  ```bash
20
12
  npm install @aspprev/versi-ds react react-dom
21
13
  ```
22
14
 
23
- Durante a preparação, instale o `.tgz` produzido por `npm pack` em um consumidor piloto. O pacote fornece ESM e declarações TypeScript; não fornece uma distribuição CommonJS. Suporta React/React DOM 18.2 ou 19. Node >=20.19 é necessário para desenvolvimento/build.
24
-
25
- ```tsx
26
- import { Button } from "@aspprev/versi-ds/core";
27
- import "@aspprev/versi-ds/styles.css";
28
- import "@aspprev/versi-ds/themes.css"; // paletas opcionais, depois dos estilos
29
-
30
- export function Example() {
31
- return <Button>Continuar</Button>;
32
- }
33
- ```
34
-
35
- O CSS já está compilado: consumidores não precisam instalar Tailwind nem escanear o pacote. Importe-o uma vez na entrada da aplicação. Ele inclui estilos base/reset do Tailwind; carregue as personalizações da aplicação depois dos estilos do DS.
36
-
37
- Os componentes básicos não exigem um provider global. Alguns controles precisam de contexto específico, como Formik nos formulários. Se a aplicação já usa React, preserve a versão compatível instalada em vez de adicionar uma segunda cópia.
38
-
39
- ## Entrypoints públicos
40
-
41
- Todos os sufixos abaixo pertencem a `@aspprev/versi-ds`.
42
-
43
- | Entrada | Conteúdo | Peers adicionais |
44
- | ------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
45
- | raiz | API completa de compatibilidade | Instale todos os peers opcionais |
46
- | `/core` | Botões, tipografia, superfícies, avisos, avatares, imagens, tooltips, paginação, tabelas, status, layout e primitivas acessíveis | Nenhum |
47
- | `/forms` | Input/InputStandalone, InputSelect, TextArea, InputPhone, SelectCountry, SelectMulti, DatePicker, RadioGroup, RadioCardGroup | `formik`, `date-fns`, `react-number-format` |
48
- | `/charts` | LazyApexChart, TimeSeriesChart, InteractiveDonutChart, TimeRangeSelector e utilitários | `apexcharts`, `react-apexcharts` |
49
- | `/overlays` | Modal, InputSwitch, AccessibilityPreferencesPanel, HighContrastToggle | `@headlessui/react` |
50
- | `/documents` | BoletoBarCode e DocumentItem | `jsbarcode` |
51
- | `/countries` | COUNTRY_OPTIONS, PHONE_COUNTRY_OPTIONS, getCountryOptions, getCountryFlagUrl, filterCountryOptions e tipos | Nenhum |
52
- | `/styles.css` | Tokens, modos, componentes e utilitários compilados | — |
53
- | `/themes.css` | Presets de paletas | — |
15
+ Requisitos do pacote:
54
16
 
55
- Use as versões compatíveis declaradas em `peerDependencies`. Os peers opcionais permitem instalar somente `/core` e `/countries`; uma entrada de camada resolve todas as suas dependências estáticas, mesmo quando apenas um componente é importado. A raiz reexporta as camadas e não isola esses peers. ApexCharts é carregado dinamicamente no navegador.
17
+ - Node.js `>=20.19.0`;
18
+ - React `>=18.2.0 <20`;
19
+ - React DOM `>=18.2.0 <20`.
56
20
 
57
- Os controles integrados com Formik, incluindo SelectCountry e InputPhone, devem ficar dentro de `<Formik>`. `InputStandalone` dispensa contexto Formik, mas a entrada `/forms` ainda requer seus peers.
21
+ O identificador npm `@aspprev/versi-ds` é mantido por compatibilidade com as
22
+ aplicações consumidoras e não representa o nome visual atual da marca.
58
23
 
59
- Instale apenas as integrações utilizadas, respeitando as faixas do manifesto:
24
+ As integrações abaixo são opcionais e só precisam ser instaladas pelas entradas que as utilizam: `@headlessui/react`, `apexcharts`, `date-fns`, `formik`, `jsbarcode`, `react-apexcharts` e `react-number-format`.
60
25
 
61
- ```bash
62
- # Formulários
63
- npm install formik@^2.4.9 date-fns@^4.1.0 react-number-format@^5.4.4
64
-
65
- # Gráficos
66
- npm install apexcharts@5.3.6 react-apexcharts@^1.9.0
26
+ ## Uso
67
27
 
68
- # Diálogos e preferências
69
- npm install @headlessui/react@^2.2.9
28
+ Importe o CSS global uma vez na entrada da aplicação:
70
29
 
71
- # Código de barras
72
- npm install jsbarcode@^3.12.3
30
+ ```tsx
31
+ import "@aspprev/versi-ds/styles.css";
32
+ import "@aspprev/versi-ds/themes.css";
73
33
  ```
74
34
 
75
- Para gráficos, mantenha a versão de ApexCharts indicada: ela faz parte do contrato de dependências validado pelo pacote.
76
-
77
- `CountrySelect`, `MultiSelect`, `PhoneInput`, `Datepicker` e `CheckBox` permanecem aliases depreciados. Prefira `SelectCountry`, `SelectMulti`, `InputPhone`, `DatePicker` e `Checkbox`. Não use deep imports de componentes em `dist` ou `src`.
78
-
79
- ## Escolhendo os componentes
80
-
81
- | Necessidade | Componentes |
82
- | ----------------------------- | ----------------------------------------------------------------------------------------------------- |
83
- | Ações e navegação | Button, Pagination, PageTabsHeader |
84
- | Texto e hierarquia | Typography, PageHeading, TextGroup, Divider |
85
- | Estrutura | Surface, ModalCard, FormGrid, FormActions, InfoGrid, InfoItem, FilterBar |
86
- | Avisos, status e carregamento | Notice, StatusBadge, DomainStatusBadge, PageState, LoadingDots, CircularLoading |
87
- | Identidade e apoio visual | Avatar, ThemedImage, IconProvider, Tooltip |
88
- | Texto, seleção e datas | Input, InputStandalone, InputSelect, TextArea, SelectMulti, DatePicker |
89
- | Países e telefones | SelectCountry, InputPhone |
90
- | Opções e valores graduais | Checkbox, RadioGroup, RadioCardGroup, InputSwitch, Slider, InputSlider |
91
- | Dados tabulares | Table, MobileCardTable |
92
- | Visualizações | TimeSeriesChart, InteractiveDonutChart, TimeRangeSelector, LazyApexChart |
93
- | Diálogos e documentos | Modal, DocumentItem, BoletoBarCode |
94
- | Acessibilidade | SkipLink, FocusNavigationMode, FormErrorNavigation, AccessibilityPreferencesPanel, HighContrastToggle |
95
-
96
- Essa tabela organiza os componentes por finalidade. Consulte os entrypoints para escolher o import: Checkbox está em `/core`, RadioGroup em `/forms` e InputSwitch em `/overlays`, por exemplo.
97
-
98
- ## Componentes básicos na prática
35
+ Use componentes pela raiz ou por um entrypoint público:
99
36
 
100
37
  ```tsx
101
- import {
102
- Button,
103
- Notice,
104
- StatusBadge,
105
- Surface,
106
- Typography,
107
- } from "@aspprev/versi-ds/core";
38
+ import { Button, Surface, Typography } from "@aspprev/versi-ds";
39
+ import { Input, OtpCodeInput } from "@aspprev/versi-ds/forms";
40
+ import { FileDropzone, QRCode } from "@aspprev/versi-ds/documents";
108
41
 
109
42
  export function Resumo() {
110
43
  return (
111
- <Surface tone="card" padding="default" elevation="sm">
112
- <Typography element="h2" semanticRole="section-title">
113
- Dados do cadastro
44
+ <Surface tone="card" padding="default">
45
+ <Typography element="h1" semanticRole="section-title">
46
+ Meu cadastro
114
47
  </Typography>
115
- <Typography semanticRole="body">
116
- Confira as informações antes de continuar.
117
- </Typography>
118
- <StatusBadge tone="success" appearance="soft">
119
- Atualizado
120
- </StatusBadge>
121
- <Notice type="info">
122
- Você pode revisar os dados a qualquer momento.
123
- </Notice>
124
- <Button type="button" variant="outline" color="primary">
125
- Revisar
126
- </Button>
48
+ <Button type="button">Continuar</Button>
127
49
  </Surface>
128
50
  );
129
51
  }
130
52
  ```
131
53
 
132
- | Componente | Propriedades frequentes |
133
- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
134
- | Button | `variant`: flat/outline/plain; `color`: primary/secondary/tertiary/danger/warning; `size`: small/medium/large; `width`: auto/full; `loading`, `loadingLabel`, `disabled` |
135
- | Typography | `element`: elemento HTML; `semanticRole`: page-title/section-title/body/label/caption/helper; `size`, `weight`, `variant` |
136
- | Surface | `tone`: card/subtle/muted/disabled/info/success/warning/danger/transparent; `padding`: none/compact/default; `elevation`: none/sm/md; `radius`: none/sm/md |
137
- | Notice | `type`: info/primary/secondary/tertiary/gray/success/warning/danger; `onDismiss`, `icon`, `rounded` |
138
- | StatusBadge | `tone`: neutral/info/success/warning/danger; `appearance`: outline/soft/solid; `size`: sm/md |
139
-
140
- Em Typography, `semanticRole` define a apresentação; `element` define a semântica HTML. Use `element="h1"` para o título principal e níveis coerentes para as seções. Uma etiqueta de status precisa de texto compreensível, além da cor.
141
-
142
- Para uma ação em andamento, use `loading` e um `loadingLabel` descritivo no Button. Dentro de formulários, declare `type="submit"` para enviar e `type="button"` para as demais ações.
143
-
144
- ## Formulários
145
-
146
- Use Input quando o estado pertence ao Formik e InputStandalone quando a aplicação fornece `value` e `onChange` diretamente. A aplicação define a validação e o envio; o DS apresenta os controles e seus estados.
147
-
148
- ### Formulário com Formik
149
-
150
- ```tsx
151
- import { Form, Formik } from "formik";
152
- import { Button, FormActions, FormGrid } from "@aspprev/versi-ds/core";
153
- import { Input, InputSelect } from "@aspprev/versi-ds/forms";
154
-
155
- type Valores = { nome: string; categoria: string };
156
-
157
- export function Cadastro({
158
- salvar,
159
- }: {
160
- salvar: (values: Valores) => Promise<void>;
161
- }) {
162
- return (
163
- <Formik<Valores>
164
- initialValues={{ nome: "", categoria: "" }}
165
- validate={(values) => {
166
- const errors: Partial<Record<keyof Valores, string>> = {};
167
- if (!values.nome.trim()) errors.nome = "Informe seu nome.";
168
- if (!values.categoria) errors.categoria = "Selecione uma categoria.";
169
- return errors;
170
- }}
171
- onSubmit={salvar}
172
- >
173
- {({ isSubmitting }) => (
174
- <Form>
175
- <FormGrid columns={2}>
176
- <Input name="nome" label="Nome completo" autoComplete="name" />
177
- <InputSelect
178
- name="categoria"
179
- label="Categoria"
180
- options={[
181
- { label: "Pessoa física", value: "pessoa-fisica" },
182
- { label: "Pessoa jurídica", value: "pessoa-juridica" },
183
- ]}
184
- />
185
- </FormGrid>
186
- <FormActions align="end">
187
- <Button
188
- type="submit"
189
- loading={isSubmitting}
190
- loadingLabel="Salvando cadastro"
191
- >
192
- Salvar
193
- </Button>
194
- </FormActions>
195
- </Form>
196
- )}
197
- </Formik>
198
- );
199
- }
200
- ```
201
-
202
- O `name` deve corresponder à chave em `initialValues`. Os erros integrados aparecem quando o campo está marcado como tocado (`touched`). Forneça `label`; o placeholder é um exemplo de preenchimento, não substitui o rótulo.
203
-
204
- FormGrid usa uma coluna em telas menores e aplica `columns` a partir do breakpoint `tablet` (1024 px). FormActions organiza as ações em coluna no mobile e em linha nas telas maiores.
54
+ ### Entrypoints
205
55
 
206
- ### Campo controlado sem contexto Formik
56
+ | Entry point | Conteúdo |
57
+ | --- | --- |
58
+ | `@aspprev/versi-ds` | API principal e componentes mais usados |
59
+ | `/core` | componentes base, layout, status, tabela e hooks |
60
+ | `/forms` | campos Formik e controlados, seleção e OTP |
61
+ | `/documents` | documentos, upload, FileViewer e QRCode |
62
+ | `/overlays` | modal, preferências e camadas interativas |
63
+ | `/charts` | gráficos e seletores de período |
64
+ | `/countries` | países, telefones e bandeiras |
65
+ | `/styles.css` | estilos e tokens base |
66
+ | `/themes.css` | presets de tema |
207
67
 
208
- ```tsx
209
- import { useState } from "react";
210
- import { InputStandalone } from "@aspprev/versi-ds/forms";
211
-
212
- export function Busca() {
213
- const [termo, setTermo] = useState("");
214
- return (
215
- <InputStandalone
216
- name="busca"
217
- label="Buscar por nome"
218
- value={termo}
219
- onChange={(event) => setTermo(event.target.value)}
220
- />
221
- );
222
- }
223
- ```
224
-
225
- Input e InputStandalone oferecem máscaras como `cpf`, `cnpj`, `cep`, `phone`, `date` e `currency`. A máscara auxilia a digitação; a aplicação ainda deve validar e normalizar o valor exigido pela sua API. Use InputPhone para seleção internacional de país e DDI.
68
+ Evite deep imports. Use somente os entrypoints públicos documentados no `package.json`.
226
69
 
227
- ## Diálogos controlados
70
+ ### APIs desta versão
228
71
 
229
72
  ```tsx
230
- import { useState } from "react";
231
- import { Button } from "@aspprev/versi-ds/core";
232
- import { Modal } from "@aspprev/versi-ds/overlays";
233
-
234
- export function Detalhes() {
235
- const [aberto, setAberto] = useState(false);
236
- return (
237
- <>
238
- <Button type="button" onClick={() => setAberto(true)}>
239
- Ver detalhes
240
- </Button>
241
- <Modal
242
- isOpen={aberto}
243
- onClose={() => setAberto(false)}
244
- title="Detalhes do cadastro"
245
- showIcon={false}
246
- >
247
- <p>Informações complementares do cadastro.</p>
248
- <Button type="button" onClick={() => setAberto(false)}>
249
- Fechar
250
- </Button>
251
- </Modal>
252
- </>
253
- );
254
- }
255
- ```
256
-
257
- Mantenha o estado de abertura na aplicação e forneça um título significativo. ModalCard é uma superfície visual; use Modal quando precisar do comportamento de diálogo.
258
-
259
- ## Servidor e navegador
260
-
261
- As entradas de componentes, inclusive `/core` e a raiz, declaram `"use client"`: agrupam componentes com hooks/contexto. Podem participar de SSR em aplicações React, mas não são entradas exclusivas de React Server Components. Funções dessas entradas devem ser chamadas no contexto cliente em aplicações RSC. `/countries` permanece sem diretiva cliente e pode ser usado no servidor. Callbacks e estado devem ser definidos em um componente cliente.
262
-
263
- ## Temas, acessibilidade e fontes
264
-
265
- Os tokens canônicos ficam em `tokens/design-system.tokens.json`. Edite essa fonte e execute `npm run tokens:generate`; não edite os arquivos gerados manualmente.
266
-
267
- ```html
268
- <html
269
- data-color-scheme="dark"
270
- data-ds-theme="verde3"
271
- data-contrast="high"
272
- data-contrast-theme="dark"
273
- data-font-scale="large"
274
- data-motion="reduce"
275
- ></html>
73
+ import { DatePicker, DomainStatusBadge, Table } from "@aspprev/versi-ds";
74
+ import { OtpCodeInput } from "@aspprev/versi-ds/forms";
75
+ import {
76
+ FileDropzone,
77
+ FileList,
78
+ FileUploadProgress,
79
+ FileViewer,
80
+ QRCode,
81
+ validateFiles,
82
+ } from "@aspprev/versi-ds/documents";
276
83
  ```
277
84
 
278
- | Atributo | Valores |
279
- | --------------------- | ------------------------------------------------------------------------------------------------------------- |
280
- | `data-color-scheme` | `light`, `dark` |
281
- | `data-ds-theme` | `default`, `azul1`, `azul2`, `azul3`, `laranja1`, `laranja2`, `verde1`, `verde2`, `verde3`, `verde4`, `rosa1` |
282
- | `data-contrast` | `normal`, `high` |
283
- | `data-contrast-theme` | `light`, `dark` (esquema do alto contraste) |
284
- | `data-font-scale` | `default`, `large`, `extra-large` |
285
- | `data-motion` | `full`, `reduce` |
286
-
287
- As preferências são controladas pelo consumidor, que também cuida da persistência e sincronização. As classes legadas das paletas continuam disponíveis. Tokens de cores usam triplets RGB para aceitar opacidade.
85
+ - `OtpCodeInput` suporta `onComplete`, colagem de código, máscara, erro e controle por `value`/`values`.
86
+ - `QRCode` suporta `description`, `ariaLabel`, `loading`, `error`, `size` e nível de correção.
87
+ - Upload e `FileViewer` são controlados pelo consumidor; transporte, autenticação, persistência e download não fazem parte do pacote.
88
+ - `DatePicker` aceita `selectionMode="year"` e mantém `selectionMode="day"` como padrão.
89
+ - `DomainStatusBadge` aceita `statusMap` para vocabulário específico do produto.
90
+ - `Table` preserva os modos `fit`, `adaptive` e `scroll`; filtros e paginação respondem ao espaço do container.
288
91
 
289
- O pacote não distribui nem baixa fontes. Configure `--font-nunito-sans` ou sobrescreva `--font-family-base`; sem Nunito Sans disponível, o navegador usa `sans-serif`. O Storybook carrega Nunito Sans pelo Google Fonts e precisa de rede para reproduzir essa tipografia nas referências visuais existentes. O consumidor pode hospedar a própria fonte; não há dependência de `next/font`.
290
-
291
- ### Alterar o tema em execução
292
-
293
- No navegador, atualize os atributos do elemento raiz:
294
-
295
- ```ts
296
- const root = document.documentElement;
297
- root.dataset.colorScheme = "dark";
298
- root.dataset.dsTheme = "azul1";
299
- root.dataset.contrast = "normal";
300
- root.dataset.contrastTheme = "dark";
301
- root.dataset.fontScale = "large";
302
- root.dataset.motion = "reduce";
303
- ```
92
+ Consulte [`docs/API-NOVOS-COMPONENTES.md`](docs/API-NOVOS-COMPONENTES.md) e o Storybook para exemplos completos, estados de erro/carregamento e contratos de acessibilidade.
304
93
 
305
- Use o `html` para que diálogos e listas renderizados fora da árvore do componente recebam o mesmo tema. Aplique as preferências conhecidas antes da primeira pintura quando houver SSR. Para acompanhar o tema do sistema, a aplicação deve resolver a preferência para `light` ou `dark`.
94
+ ## Organização do Design System
306
95
 
307
- AccessibilityPreferencesPanel recebe `preferences` e entrega mudanças parciais em `onPreferencesChange`. Mescle essas mudanças com o estado atual e sincronize os atributos CSS. O valor `fontScale="standard"` do painel corresponde a `data-font-scale="default"`; `highContrast` corresponde a normal/high e `reduceMotion` a full/reduce. O painel não persiste nem aplica automaticamente as preferências no documento.
96
+ - **Components**: controles de ação, formulários, feedback, navegação, dados, documentos, overlays e layout.
97
+ - **Foundations**: cores, tipografia, espaçamento e sombras derivados dos tokens.
98
+ - **Themes**: esquema claro/escuro, contraste, escala tipográfica e presets de identidade.
99
+ - **Hooks e utilitários**: breakpoints, acessibilidade, preferências e posicionamento.
100
+ - **Countries e charts**: dados de países/bandeiras e integrações de gráficos.
308
101
 
309
- ### Usar tokens no CSS da aplicação
102
+ Os tokens canônicos ficam em `tokens/design-system.tokens.json`. Arquivos CSS gerados não devem ser editados manualmente.
310
103
 
311
- Prefira tokens semânticos, que expressam a função da cor, em vez de copiar valores de uma paleta:
104
+ ## Storybook
312
105
 
313
- ```css
314
- .resumo-cadastro {
315
- color: rgb(var(--content-primary));
316
- background-color: rgb(var(--surface-page));
317
- border: 1px solid rgb(var(--border-default));
318
- padding: var(--spacing-md);
319
- border-radius: var(--border-radius-md);
320
- }
106
+ Instale as dependências e inicie a documentação visual:
321
107
 
322
- .resumo-cadastro:focus-visible {
323
- outline: 2px solid rgb(var(--focus-ring));
324
- outline-offset: 2px;
325
- }
108
+ ```bash
109
+ npm install
110
+ npm run storybook
326
111
  ```
327
112
 
328
- Tokens de cor contêm os canais RGB, sem `#` e sem a função `rgb()`; tokens de espaço e raio já incluem a unidade. Ao personalizar cores, confira também os modos escuro e de alto contraste. Evite tamanhos de fonte fixos que impeçam a escala tipográfica do DS.
329
-
330
- O CSS distribuído inclui as classes necessárias aos componentes, não todas as classes possíveis do Tailwind. Para layouts próprios, use seu CSS ou o build Tailwind da aplicação; o `tailwind.config.cjs` deste repositório não é um export público.
331
-
332
- ### Configurar a família tipográfica
113
+ O servidor usa a porta `6006`. Para a configuração standalone:
333
114
 
334
- Depois de carregar a fonte escolhida, configure sua família no CSS global. Para uma alternativa sem download de fonte:
335
-
336
- ```css
337
- :root {
338
- --font-nunito-sans: system-ui;
339
- --font-family-base: var(--font-nunito-sans), sans-serif;
340
- }
115
+ ```bash
116
+ npm run storybook:standalone
341
117
  ```
342
118
 
343
- Configure também `--font-nunito-sans` porque Typography usa essa variável. Trocar apenas a família do `body` não alcança todos os componentes.
344
-
345
- ### Boas práticas de acessibilidade
346
-
347
- - Use títulos em ordem, rótulos de campos e texto que explique status e erros.
348
- - Mantenha foco visível e verifique Tab, Enter, Espaço e Escape nos controles interativos.
349
- - Teste claro, escuro e alto contraste, além de fonte ampliada e movimento reduzido.
350
- - Em ações com ícone sem texto, forneça um nome acessível, como `aria-label`.
351
- - Verifique o conteúdo da aplicação com leitor de tela; a composição e os textos também influenciam a acessibilidade.
352
-
353
- ## Países e bandeiras locais
354
-
355
- A lista contém 250 países/territórios. `COUNTRY_OPTIONS` e `PHONE_COUNTRY_OPTIONS` são a mesma lista; `getCountryOptions()` retorna uma cópia editável. Os componentes usam a lista automaticamente quando `options`/`countries` são omitidos. Por isso, `/forms` e a raiz incluem os dados; `/core` não os exige.
356
-
357
- ```tsx
358
- import { Formik } from "formik";
359
- import { SelectCountry, InputPhone } from "@aspprev/versi-ds/forms";
360
-
361
- <Formik
362
- initialValues={{ pais: "Brasil", telefone: { ddi: 55, ddd: "", numero: "" } }}
363
- onSubmit={() => {}}
364
- >
365
- <form>
366
- <SelectCountry
367
- name="pais"
368
- label="País"
369
- countryList={{ mode: "include", codes: ["BR", "PT", "US"] }}
370
- />
371
- <InputPhone
372
- name="telefone"
373
- label="Telefone"
374
- countryList={{ mode: "exclude", codes: ["US"] }}
375
- />
376
- </form>
377
- </Formik>;
119
+ A árvore da documentação é organizada assim:
120
+
121
+ ```text
122
+ Getting Started
123
+ ├── Introduction
124
+ ├── Installation
125
+ ├── Usage
126
+ └── Contributing
127
+
128
+ Foundations
129
+ ├── Overview
130
+ ├── Colors
131
+ ├── Typography
132
+ ├── Spacing
133
+ └── Shadows
134
+
135
+ Components
136
+ ├── Actions
137
+ ├── Forms
138
+ ├── Feedback
139
+ ├── Data Display
140
+ ├── Documents
141
+ ├── Navigation
142
+ ├── Overlay
143
+ ├── Layout
144
+ └── Accessibility
145
+
146
+ Patterns
147
+ ├── Forms
148
+ └── Feedback
149
+
150
+ Themes
151
+ ├── Overview
152
+ ├── Comparison
153
+ └── ThemeLab
154
+
155
+ Guidelines
156
+ ├── Accessibility
157
+ └── Usage
378
158
  ```
379
159
 
380
- `countryList` aceita `all` (padrão), `include` ou `exclude`; `codes` usa ISO-2. Na lista padrão, o **valor do SelectCountry é o nome** (`Brasil`), e `cca2` contém `BR`. O payload telefônico é `{ ddi, ddd, numero }`; países com o mesmo DDI não podem ser distinguidos ao restaurar apenas esse payload. A escolha explícita preserva o ISO-2 enquanto o componente estiver montado.
381
-
382
- As 250 bandeiras são incorporadas ao JavaScript como URLs `data:image/svg+xml;base64,...`. `getCountryFlagUrl("BR")` retorna o SVG do pacote; códigos desconhecidos retornam string vazia. Não copie `public/flags`: Next.js, Vite, Storybook, SSR e aplicações sob subpath usam o mesmo asset, sem CDN, rota estática ou postinstall.
383
-
384
- Opções customizadas com `flags.svg` não vazio têm prioridade; sem ele, o componente usa o ISO-2 e, se desconhecido, um placeholder. `flags.png` permanece como metadado legado e não é requisitado. Com CSP, permita `data:` em `img-src`. Use a URL em `<img>`; não é necessário `next/image`.
385
-
386
- O build gera `src/data/country-flags.json` deterministicamente a partir dos SVGs, e tsup incorpora esse mapa ao chunk compartilhado. Os 250 originais também permanecem em `dist/flags` para compatibilidade e auditoria. Isso aumenta o JavaScript de quem importa países ou formulários; não existe carregamento individual sob demanda. Consulte `docs/BANDEIRAS.md` e o fixture `examples/flags-consumer`.
160
+ A toolbar permite comparar esquema de cores, preset, contraste, escala de fonte e movimento reduzido. O addon de acessibilidade permanece disponível para inspeção manual e os testes automatizados usam Axe nos cenários visuais.
387
161
 
388
162
  ## Desenvolvimento e validação
389
163
 
390
164
  ```bash
391
- npm install
392
165
  npm run tokens:check
393
- npm run check:governance
394
- npm run check:security
395
166
  npm run typecheck
396
- npm run build
397
167
  npm test
398
- npm run check:size
168
+ npm run build
399
169
  npm run build-storybook
400
- npx playwright install chromium
401
170
  npm run test:visual
402
171
  npm run check:package
403
- npm run test:package
404
- npm pack --dry-run
172
+ npm run prepack
405
173
  ```
406
174
 
407
- `typecheck` inclui código, stories e configuração visual. `test:package` instala um tarball em diretório temporário fora do repositório, primeiro sem peers opcionais e depois com todos eles; verifica ESM, CSS, SSR e TypeScript strict/NodeNext. Requer acesso ao registro npm e limpa seu diretório temporário.
408
-
409
- Use `npm run storybook` (6006) ou `npm run storybook:standalone` (6007). Playwright inicia seu próprio servidor; `STORYBOOK_DS_PORT` altera a porta. As referências visuais existentes são Chromium/Windows, desktop e mobile. Revise diferenças antes de usar `npm run test:visual:update`. Axe e testes automatizados não substituem revisão manual com leitor de tela.
175
+ O script `prepack` valida tokens, governança, segurança, TypeScript, build, tamanho e conteúdo do pacote. O projeto não possui um script `lint` separado.
410
176
 
411
- No Storybook, abra o grupo `Design System` e escolha um componente. Use suas stories para comparar estados e variantes, e os controles para experimentar as propriedades disponíveis. A barra de ferramentas altera esquema de cores, paleta, contraste, escala da fonte e movimento. O `ThemeLab/Playground` reúne a exploração dos temas; o painel de acessibilidade ajuda na inspeção de cada cenário.
412
-
413
- `prepack` verifica tokens, governança, dependências (`npm audit`), TypeScript, build, tamanho e conteúdo antes de empacotar. O tarball inclui somente `dist/`, `README.md` e o `package.json` obrigatório do npm. Stories, testes, documentação interna e ferramentas não são publicados. Sourcemaps em `dist` são intencionais para diagnóstico.
414
-
415
- ## Aplicação de exemplo
416
-
417
- O repositório inclui uma aplicação React/Vite em `examples/pilot`, com cadastro,
418
- validação de formulário, países/telefone, tabela, modal e controles de aparência.
419
- Ela instala o DS a partir do tarball e usa apenas os entrypoints públicos.
420
-
421
- Na raiz do repositório:
177
+ Para testar o exemplo integrado:
422
178
 
423
179
  ```bash
424
180
  npm run pilot:prepare
425
- npm run pilot:dev
181
+ npm run test:pilot
426
182
  ```
427
183
 
428
- Abra `http://127.0.0.1:4175`. Para compilar e testar o piloto em produção, execute
429
- `npm run test:pilot`. As instruções completas estão em `examples/pilot/README.md`.
430
- O exemplo não faz parte do pacote npm e seus dados ficam somente na memória da página.
184
+ Antes de uma publicação, gere um tarball local com `npm pack` e valide sua instalação nos consumidores.
185
+
186
+ ## Temas
431
187
 
432
- ## Problemas comuns
188
+ As preferências são controladas pelo consumidor no elemento `html`:
433
189
 
434
- | Sintoma | O que conferir |
435
- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
436
- | Componentes sem estilo | Importe styles.css uma vez na entrada da aplicação e verifique regras que o sobrescrevem. |
437
- | Uma classe Tailwind própria não funciona | O CSS do pacote inclui as classes dos componentes; compile as classes da sua aplicação ou use CSS próprio. |
438
- | Erro ao resolver Formik, Headless UI ou outra integração | Instale os peers da camada importada. A entrada raiz precisa do conjunto completo. |
439
- | Erro de contexto Formik | Envolva os controles integrados em Formik; para Input controlado, use InputStandalone. |
440
- | Bandeiras não aparecem | Confira o pacote atualizado e permita data: em img-src quando houver CSP. |
441
- | SelectCountry não mostra o valor inicial | Na lista padrão, use Brasil como valor; BR é o código de filtragem ISO-2. |
442
- | Diálogo ou dropdown com tema diferente | Aplique os atributos de tema no html para alcançar também os elementos renderizados fora da árvore do componente. |
443
- | Fonte diferente do Storybook | Carregue a fonte desejada e configure --font-nunito-sans; a fonte não acompanha o pacote. |
444
- | Erro de hooks em aplicação RSC | Defina estado e callbacks em um componente cliente; consulte a seção sobre servidor e navegador. |
190
+ ```ts
191
+ const root = document.documentElement;
192
+ root.dataset.colorScheme = "dark";
193
+ root.dataset.dsTheme = "azul1";
194
+ root.dataset.contrast = "high";
195
+ root.dataset.fontScale = "large";
196
+ root.dataset.motion = "reduce";
197
+ ```
445
198
 
446
- ## Documentação do repositório
199
+ Os valores válidos estão documentados em **Themes/Overview** no Storybook. Prefira tokens semânticos, como `--surface-page`, `--content-primary`, `--border-default` e `--focus-ring`, em vez de copiar valores de uma paleta.
447
200
 
448
- Para aprofundar o uso e a manutenção, consulte os arquivos abaixo no checkout do projeto. Eles não acompanham o tarball npm.
201
+ ## Contribuição
449
202
 
450
- | Arquivo | Conteúdo |
451
- | --------------------------------- | ------------------------------------------------------- |
452
- | docs/API-PUBLICA-CONTROLES.md | Contratos dos controles, estado, teclado e dependências |
453
- | docs/COMPONENTES-CLIENT-SERVER.md | Fronteiras cliente e servidor |
454
- | docs/THEMELAB-E-GLOBALS-CSS.md | Temas e personalização do CSS |
455
- | tokens/README.md | Fonte e geração dos tokens |
456
- | docs/GOVERNANCA-DESIGN-SYSTEM.md | Contribuição, versionamento e publicação |
457
- | docs/EVOLUCAO-DESIGN-SYSTEM.md | Histórico de mudanças e validações |
203
+ Ao criar ou alterar um componente:
458
204
 
459
- O contexto específico do portal, o plano de migração e as pendências dessa transição ficam exclusivamente em `MIGRACAO-DO-PORTAL.md`.
460
- # versi-design-system
205
+ 1. reutilize tokens e componentes existentes;
206
+ 2. mantenha a API tipada e compatível com React;
207
+ 3. garanta foco visível, teclado, nomes acessíveis, erros e estados de carregamento;
208
+ 4. crie ou atualize stories com estados relevantes;
209
+ 5. adicione testes unitários, de interação e de acessibilidade quando aplicável;
210
+ 6. execute `npm run prepack` antes de gerar o pacote.
461
211
 
212
+ Detalhes de contratos, governança e segurança ficam na pasta `docs/`. A documentação de uso visual deve permanecer principalmente no Storybook.