@topjoao/top-design-system 0.1.0-beta.9 → 0.1.1-beta.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 (39) hide show
  1. package/README.md +750 -52
  2. package/dist/TopToast-BI4cWWtd.js +3024 -0
  3. package/dist/TopToast-BI4cWWtd.js.map +1 -0
  4. package/dist/TopToast-tPhTQRza.cjs +2 -0
  5. package/dist/TopToast-tPhTQRza.cjs.map +1 -0
  6. package/dist/components/TopAccordion.vue.d.ts +48 -0
  7. package/dist/components/TopAccordionNavigator.vue.d.ts +35 -0
  8. package/dist/components/TopAccordionPanel.vue.d.ts +42 -0
  9. package/dist/components/TopAccordionSummary.vue.d.ts +23 -0
  10. package/dist/components/TopButton.vue.d.ts +4 -1
  11. package/dist/components/TopConfirmDialog.vue.d.ts +1 -1
  12. package/dist/components/TopDatePicker.vue.d.ts +81 -0
  13. package/dist/components/TopFileUpload.vue.d.ts +88 -0
  14. package/dist/components/TopInputNumber.vue.d.ts +89 -0
  15. package/dist/components/TopNavBar.vue.d.ts +288 -0
  16. package/dist/components/TopSelect.vue.d.ts +4 -4
  17. package/dist/components/TopTabs.vue.d.ts +34 -0
  18. package/dist/components/TopToast.vue.d.ts +2 -10
  19. package/dist/components/internal/TopNavMobileTree.vue.d.ts +20 -0
  20. package/dist/components/internal/topAccordion.d.ts +14 -0
  21. package/dist/index.cjs +1 -1
  22. package/dist/index.d.ts +18 -1
  23. package/dist/index.js +10 -10
  24. package/dist/nuxt.cjs +1 -1
  25. package/dist/nuxt.cjs.map +1 -1
  26. package/dist/nuxt.js +40 -0
  27. package/dist/nuxt.js.map +1 -1
  28. package/dist/plugin.cjs +1 -1
  29. package/dist/plugin.cjs.map +1 -1
  30. package/dist/plugin.d.ts +18 -0
  31. package/dist/plugin.js +4 -4
  32. package/dist/plugin.js.map +1 -1
  33. package/dist/style.css +1 -1
  34. package/dist/types/toast.d.ts +17 -0
  35. package/package.json +4 -2
  36. package/dist/TopToast-B376KudO.cjs +0 -2
  37. package/dist/TopToast-B376KudO.cjs.map +0 -1
  38. package/dist/TopToast-YNoWv10q.js +0 -673
  39. package/dist/TopToast-YNoWv10q.js.map +0 -1
package/README.md CHANGED
@@ -1,12 +1,36 @@
1
1
  # TopSolutions Design System
2
2
 
3
3
  Biblioteca de componentes Vue 3, estilos e tokens visuais compartilhados pela
4
- TopSolutions.
4
+ TopSolutions.
5
+
6
+ ## Índice
7
+
8
+ - [Instalação e configuração](#instalação)
9
+ - [Tema e tokens](#tema-topsolutions)
10
+ - [Integração com Nuxt e Vue 3](#uso-com-nuxt)
11
+ - [Componentes](#componentes-publicos)
12
+ - [Tipos e exports públicos](#tipos-e-exports-públicos)
13
+ - [Desenvolvimento da biblioteca](#desenvolvimento-da-biblioteca)
14
+
15
+ ## Componentes públicos
16
+
17
+ | Componente | Finalidade | `v-model` |
18
+ |---|---|---|
19
+ | `TopButton` | Botão com estilos e estados da marca. | — |
20
+ | `TopConfirmDialog` | Confirmação modal controlada pela aplicação. | `boolean` |
21
+ | `TopDatePicker` | Campo de data, múltiplas datas ou intervalo. | `Date`/array de `Date` |
22
+ | `TopFileUpload` | Escolha, validação e prévia de arquivos; não faz upload. | `File`/`File[]`/`null` |
23
+ | `TopInputText` | Campo textual com label, erro e acessibilidade. | `string` |
24
+ | `TopInputNumber` | Campo numérico localizado, com moeda, limites e incrementos. | `number \| null` |
25
+ | `TopNavBar` | Navegação responsiva, breadcrumbs, favoritos e Drawer. | `searchValue` e `mobileOpen` opcionais |
26
+ | `TopSelect` | Autocomplete pesquisável com paginação virtual. | opção/opções |
27
+ | `TopTabs` | Abas com painéis nomeados. | `string \| number` |
28
+ | `TopToast` | Renderizador de notificações do serviço Toast do PrimeVue. | — |
5
29
 
6
30
  ## Instalação
7
31
 
8
32
  ```bash
9
- npm install @topjoao/top-design-system@beta
33
+ npm install @topjoao/top-design-system
10
34
  ```
11
35
 
12
36
  A aplicação consumidora deve possuir Vue 3, PrimeVue, PrimeIcons e
@@ -29,6 +53,16 @@ app.use(PrimeVue, {
29
53
  })
30
54
  ```
31
55
 
56
+ Para ativar o modo escuro, adicione ou remova `.dark` uma única vez no elemento
57
+ `<html>` da aplicação. Os componentes usam tokens semânticos de superfície, texto e
58
+ borda fornecidos por `style.css`; não é necessário passar classes `dark:` em cada
59
+ uso. A aplicação pode substituir esses tokens após importar o CSS da biblioteca.
60
+
61
+ Os tokens públicos de campos são `--top-field-background`,
62
+ `--top-field-background-readonly`, `--top-field-background-disabled`,
63
+ `--top-field-text`, `--top-field-label`, `--top-field-placeholder`,
64
+ `--top-field-border`, `--top-field-border-hover` e `--top-field-icon`.
65
+
32
66
  O preset é independente dos ajustes de layout próprios do TopLicita; ele
33
67
  contém apenas tokens semânticos compartilháveis, como cores primárias, neutras,
34
68
  sucesso, alerta e erro.
@@ -99,6 +133,264 @@ createApp(App).use(TopSolutionsDesignSystem).mount('#app')
99
133
  Após o registro, os componentes podem ser utilizados sem importação manual. A
100
134
  entrada `/plugin` também fornece as declarações globais usadas pela IDE.
101
135
 
136
+ ## TopNavBar
137
+
138
+ Barra de navegação responsiva inspirada no AppSidebar do TopLicita. O
139
+ componente fornece apenas layout e interação: a aplicação consumidora continua
140
+ responsável por rotas, permissões, sessão, cliente/órgão, busca remota,
141
+ favoritos, Aia, suporte e integrações. Nenhuma dessas ações é executada pela
142
+ biblioteca; todas são comunicadas por eventos.
143
+
144
+ ```vue
145
+ <script setup lang="ts">
146
+ import { ref } from 'vue'
147
+ import {
148
+ TopNavBar,
149
+ type TopNavAction,
150
+ type TopNavItem,
151
+ type TopNavSection,
152
+ } from '@topjoao/top-design-system'
153
+
154
+ const clienteAtual = ref('prefeitura-a')
155
+ const favorito = ref(false)
156
+
157
+ const secoes: TopNavSection[] = [
158
+ {
159
+ id: 'planejamento',
160
+ label: 'Planejamento',
161
+ icon: 'pi pi-book',
162
+ children: [
163
+ {
164
+ id: 'programacao',
165
+ label: 'Programação',
166
+ children: [
167
+ { id: 'calendario', label: 'Calendário', to: '/programacao/calendario' },
168
+ ],
169
+ },
170
+ ],
171
+ },
172
+ ]
173
+
174
+ function navegar(item: TopNavItem) {
175
+ if (item.to) router.push(item.to)
176
+ }
177
+
178
+ function executarIntegracao(action: TopNavAction) {
179
+ // Abra a integração identificada por action.id.
180
+ }
181
+ </script>
182
+
183
+ <template>
184
+ <TopNavBar
185
+ :sections="secoes"
186
+ active-item-id="calendario"
187
+ searchable
188
+ show-aia
189
+ show-support
190
+ show-favorite-toggle
191
+ :favorite-active="favorito"
192
+ :actions="[
193
+ { id: 'integracoes', label: 'Integrações', icon: 'pi pi-th-large' },
194
+ ]"
195
+ :user="{ name: 'João Silva', subtitle: 'Administrador', initials: 'JS' }"
196
+ :user-menu-items="[
197
+ { id: 'perfil', label: 'Meu perfil', icon: 'pi pi-user' },
198
+ { id: 'sair', label: 'Sair', icon: 'pi pi-sign-out' },
199
+ ]"
200
+ @navigate="navegar"
201
+ @search="consultarMenusPermitidos"
202
+ @toggle-aia="alternarAia"
203
+ @open-support="abrirCentralSuporte"
204
+ @toggle-favorite="favorito = !favorito"
205
+ @action="executarIntegracao"
206
+ @user-action="executarAcaoDaSessao"
207
+ >
208
+ <template #brand="{ compact }">
209
+ <img src="/logo.svg" alt="Minha organização">
210
+ <span v-if="!compact">Sistema de Contratações</span>
211
+ </template>
212
+
213
+ <template #context="{ compact }">
214
+ <select v-model="clienteAtual" aria-label="Cliente atual">
215
+ <option value="prefeitura-a">Prefeitura A</option>
216
+ <option value="prefeitura-b">Prefeitura B</option>
217
+ </select>
218
+ <span v-if="!compact">Poder Executivo</span>
219
+ </template>
220
+ </TopNavBar>
221
+ </template>
222
+ ```
223
+
224
+ ### Menu e breadcrumbs
225
+
226
+ `sections` aceita uma árvore de profundidade arbitrária. Cada nó usa
227
+ `TopNavItem` (`id`, `label`, `to?`, `icon?`, `disabled?`, `children?`, `data?`).
228
+ Seções sem filhos são removidas e um `children: []` nunca cria um painel vazio.
229
+ No desktop, a primeira coluna do painel mestre–detalhe tem `16rem`; os itens de
230
+ cada nível são repartidos em colunas de `18rem`, no máximo dez por coluna.
231
+ Subníveis aparecem sempre à direita do nível de origem.
232
+
233
+ Breadcrumbs estão habilitados por padrão e começam por `Início / Navegação`.
234
+ Há duas formas de fornecer a trilha:
235
+
236
+ - informe `breadcrumbs` com itens `TopNavBreadcrumb`; `sectionId` liga o item a
237
+ uma seção e `menuId` liga a qualquer nó com filhos;
238
+ - omita `breadcrumbs` e informe `activeItemId`; a trilha é derivada da árvore.
239
+
240
+ Por exemplo, `calendario` dentro de `Programação` em `Planejamento` gera
241
+ `Início / Navegação / Planejamento / Programação / Calendário`. A rota ativa
242
+ não recebe fundo permanente nos menus desktop; somente hover e o ramo que está
243
+ sendo explorado recebem destaque.
244
+
245
+ ### Props
246
+
247
+ | Prop | Tipo / padrão | Finalidade |
248
+ |---|---|---|
249
+ | `sections` | `TopNavSection[]` / `[]` | Árvore de navegação já filtrada pela aplicação. |
250
+ | `breadcrumbs` | `TopNavBreadcrumb[]` / `[]` | Trilha explícita; vazia permite derivação por `activeItemId`. |
251
+ | `homeItem` | `TopNavItem` / `Início` | Item inicial emitido ao clicar em Início. |
252
+ | `navigationLabel` | `string` / `Navegação` | Rótulo do menu mestre. |
253
+ | `activeItemId` | `string` | Nó atual, usado no breadcrumb e no Drawer. |
254
+ | `searchable` | `boolean` / `false` | Habilita busca desktop e busca própria do Drawer. |
255
+ | `searchValue` | `string` | Valor opcionalmente controlado com `v-model:search-value`. |
256
+ | `searchResults` | `TopNavItem[]` | Resultados controlados; sem a prop, a árvore é filtrada localmente. |
257
+ | `searchPlaceholder` | `string` | Placeholder das duas buscas. |
258
+ | `showAia`, `showSupport` | `boolean` / `false` | Exibem as ações opcionais. |
259
+ | `aiaActive` | `boolean` / `false` | Estado visual do botão Aia. |
260
+ | `aiaLabel`, `supportLabel` | `string` | Textos acessíveis e rótulos do Drawer. |
261
+ | `actions` | `TopNavAction[]` / `[]` | Ações genéricas, como integrações, emitidas por `action`. |
262
+ | `client` | `TopNavClient` | Organização, cliente ou escopo ativo exibido no cabeçalho e como contexto do usuário no rodapé do Drawer; não cria ação nem seletor. |
263
+ | `user` | `TopNavUser` | Dados exclusivamente visuais do usuário. |
264
+ | `userMenuItems` | `TopNavUserMenuItem[]` | Opções emitidas por `user-action`; suporta separadores. |
265
+ | `favoriteItems` | `TopNavItem[]` / `[]` | Favoritos fornecidos pelo pai para dropdown e Drawer. |
266
+ | `showFavoriteToggle` | `boolean` / `false` | Exibe a estrela da página atual. |
267
+ | `favoriteActive` | `boolean` / `false` | Estado visual da estrela atual. |
268
+ | `mobileOpen` | `boolean` | Controle opcional com `v-model:mobile-open`. |
269
+ | `appearance` | `TopNavBarAppearance` | Tokens visuais locais descritos abaixo. |
270
+
271
+ ### Eventos
272
+
273
+ | Evento | Payload | Quando ocorre |
274
+ |---|---|---|
275
+ | `navigate` | `TopNavItem` | Início, menu, resultado ou favorito é selecionado. |
276
+ | `search` | `string` | A consulta muda no desktop ou no Drawer. |
277
+ | `update:searchValue` | `string` | Atualização de `v-model:search-value`. |
278
+ | `update:mobileOpen` | `boolean` | Atualização de `v-model:mobile-open`. |
279
+ | `toggle-aia` | — | A ação Aia é acionada. |
280
+ | `open-support` | — | A ação de suporte é acionada. |
281
+ | `toggle-favorite` | — | A estrela da página atual é acionada. |
282
+ | `action` | `TopNavAction` | Uma ação genérica/integração é acionada. |
283
+ | `user-action` | `TopNavUserMenuItem` | Uma opção de usuário é selecionada. |
284
+ | `user-click` | `TopNavUser \| undefined` | A área de usuário sem menu é acionada. |
285
+
286
+ `Ctrl+K` e `Cmd+K` abrem/focam a busca. Em telas menores que `1024px`, o
287
+ atalho abre primeiro o Drawer e foca a busca móvel. `Escape` fecha os painéis.
288
+
289
+ ### Slots
290
+
291
+ | Slot | Uso |
292
+ |---|---|
293
+ | `brand` | Marca; recebe `{ compact }`. |
294
+ | `context`, `scope` ou `client` | Contexto operacional; aliases com prioridade nessa ordem, recebem `{ client, compact }`. O slot `client` substitui a apresentação padrão da prop `client`. |
295
+ | `context-compact` | Variante explícita usada no último estágio de overflow. |
296
+ | `actions` | Conteúdo adicional do cabeçalho; recebe `{ compact, close }`. |
297
+ | `aia-icon`, `support-icon` | Ícones customizados das ações quadradas. |
298
+ | `user` | Conteúdo do gatilho de usuário; recebe `{ user, compact }`. |
299
+ | `user-menu` | Painel de usuário; recebe `{ items, select }`. |
300
+ | `search-results` | Resultados customizados; recebe `{ items, select }`. |
301
+ | `breadcrumb-actions` | Ações adicionais no fim da segunda faixa. |
302
+ | `drawer-header` | Cabeçalho inteiro; recebe `{ close }`. |
303
+ | `drawer-brand` | Marca do Drawer; por padrão reutiliza `brand`. |
304
+ | `drawer-search` | Busca inteira; recebe `{ query, update, clear }`. |
305
+ | `drawer-actions` | Ações; recebe `{ actions, select, close }`. |
306
+ | `drawer-before-menu`, `drawer-after-menu` | Conteúdo antes/depois do trilho rolável. |
307
+ | `drawer-menu` | Substitui a árvore; recebe `{ sections, select, close }`. |
308
+ | `drawer-user` | Rodapé de usuário; recebe `{ user, client, open, toggle }`. |
309
+ | `drawer-footer` | Conteúdo final adicional; recebe `{ close }`. |
310
+
311
+ ### Faixa de favoritos
312
+
313
+ No desktop, `favoriteItems` aparece primeiro em uma faixa horizontal abaixo dos
314
+ breadcrumbs. A biblioteca mede uma cópia invisível da faixa com
315
+ `ResizeObserver`: se a largura real não couber, ela é substituída pelo dropdown
316
+ `Favoritos`. O mesmo dropdown é usado depois que a página passa de `120px` de
317
+ scroll e a faixa retorna apenas ao chegar a `24px` ou menos. Os valores evitam
318
+ oscilações perto do topo e reproduzem o comportamento do AppSidebar.
319
+
320
+ ### Aparência e responsividade
321
+
322
+ `appearance` é propositalmente pequeno e semântico. Use `colors` para
323
+ `navigation`, `text`, `mutedText`, `accent`, `border`, `menuText`,
324
+ `mobileActiveText` e `favoritesText`; `surfaces` para `breadcrumb`, `drawer`,
325
+ `drawerFooter`, `menu`, `menuHover`, `menuExplored`, `mobileActive`,
326
+ `favorites` e `currentPage`; `borders` para `menu` (a borda externa de 6px),
327
+ `menuOutline`, `mobileDivider`, `favorites` e `currentPage`; `shape` para
328
+ `radius`, `drawerRadius`, `shadow` e `favoritesShadow`; e `focus` para
329
+ `onDark` e `onLight`.
330
+
331
+ ```ts
332
+ const appearance = {
333
+ colors: { navigation: '#09090b', text: '#f4f4f5', border: 'rgb(255 255 255 / 14%)' },
334
+ surfaces: { drawer: '#09090b', menu: '#18181b', menuHover: '#27272a' },
335
+ shape: { radius: '8px', shadow: '0 12px 30px rgb(0 0 0 / 25%)' },
336
+ }
337
+ ```
338
+
339
+ A biblioteca não fixa tipografia inline. Por padrão, família, tamanho, peso e
340
+ altura de linha são herdados da aplicação consumidora. Além disso, `appearance`
341
+ só cria variáveis inline para propriedades que foram realmente informadas; os
342
+ valores fiéis ao AppSidebar existem apenas como *fallbacks* no CSS. Assim, um
343
+ tema global pode controlar o componente sem precisar usar `!important`:
344
+
345
+ ```css
346
+ :root {
347
+ --top-nav-font-family: var(--app-font-family);
348
+ --top-nav-font-size: var(--app-font-size);
349
+ --top-nav-strong-font-weight: 600;
350
+ --top-nav-action-size: 2.5rem;
351
+ --top-nav-header-padding: 0.625rem 1.5rem;
352
+ --top-nav-menu-item-padding: 0.5rem 0.75rem;
353
+ --top-nav-section-width: 16rem;
354
+ --top-nav-column-width: 18rem;
355
+ --top-nav-mobile-active-bg: #fff;
356
+ --top-nav-mobile-active-fg: #025a84;
357
+ --top-nav-mobile-divider: rgb(255 255 255 / 20%);
358
+ --top-nav-mobile-item-gap: 0.25rem;
359
+ --top-nav-mobile-submenu-padding: 0.5rem 0 0.375rem 0.35rem;
360
+ --top-nav-favorites-bg: #f8fafc;
361
+ --top-nav-favorites-fg: #0f172a;
362
+ --top-nav-favorites-border: #e2e8f0;
363
+ --top-nav-favorites-shadow: 0 1px 2px rgb(15 23 42 / 6%);
364
+ --top-nav-focus-ring: #dbeafe;
365
+ --top-nav-focus-ring-light: #1d4ed8;
366
+ --top-nav-current-bg: rgb(255 255 255 / 10%);
367
+ --top-nav-current-border: rgb(255 255 255 / 15%);
368
+ --top-nav-menu-scrollbar-thumb: #94a3b8;
369
+ }
370
+ ```
371
+
372
+ As variáveis globais também alcançam o Drawer teleportado. Use-as para ajustes
373
+ estruturais — tipografia, larguras, alturas, padding e espaçamentos do menu —
374
+ em vez de props no componente. Um valor passado por `appearance` tem precedência
375
+ local e não altera os demais tokens do tema.
376
+
377
+ O breakpoint móvel é `1024px`. No desktop, um `ResizeObserver` reaplica a mesma
378
+ sequência progressiva do AppSidebar: ações colapsam abaixo de `1440px`, busca
379
+ vira ícone abaixo de `1320px`, nome do usuário some abaixo de `1180px` e, se o
380
+ conteúdo ainda transbordar, o contexto recebe `compact: true`. O último estágio
381
+ também limita o contêiner do contexto a `3.25rem`; use `context-compact` quando
382
+ quiser controlar exatamente o que permanece visível.
383
+
384
+ Abaixo de `1024px`, a navegação desktop desaparece e o Drawer do PrimeVue assume.
385
+ Ele mantém cabeçalho, busca, ações, trilho translúcido rolável, árvore recursiva,
386
+ favoritos e usuário. No rodapé, a foto e o nome do usuário formam a primeira
387
+ linha; o cliente atual aparece abaixo e o subtítulo do cliente recebe uma
388
+ etiqueta quando houver. A transição `menu-expand` existe somente dentro do Drawer;
389
+ os dropdowns desktop abrem sem animação e suas áreas de hover incluem o espaço
390
+ entre gatilho e painel. Nessa largura, os breadcrumbs deixam de rolar
391
+ horizontalmente: eles quebram em linhas e o bloco da página atual ocupa sua
392
+ própria linha para permanecer legível.
393
+
102
394
  ## TopButton
103
395
 
104
396
  Exemplo
@@ -107,6 +399,7 @@ Exemplo
107
399
  <template>
108
400
  <TopButton label="Salvar" icon="pi pi-save" @click="salvar" />
109
401
  <TopButton label="Cancelar" secondary />
402
+ <TopButton label="Excluir" severity="danger" />
110
403
 
111
404
  <TopButton label="Consultar" outlined>
112
405
  <template #icon>
@@ -125,12 +418,16 @@ Exemplo
125
418
  | `loading` | `boolean` | `false` |
126
419
  | `class` | `string` | `''` |
127
420
  | `outlined` | `boolean` | `false` |
421
+ | `severity` | `'primary' \| 'secondary' \| 'success' \| 'warn' \| 'danger'` | `'primary'` |
128
422
  | `secondary` | `boolean` | `false` |
129
423
  | `disabled` | `boolean` | `false` |
130
424
  | `unstyled` | `boolean` | `false` |
131
425
  | `type` | `'button' \| 'submit' \| 'reset'` | `'button'` |
132
426
 
133
- O componente emite `click` sem payload e oferece o slot nomeado `icon`.
427
+ O componente emite `click` sem payload. O slot nomeado `icon` não recebe
428
+ parâmetros e substitui a prop `icon` — útil para SVGs, `HugeiconsIcon` ou um
429
+ ícone com estado próprio. `secondary` permanece como atalho compatível para
430
+ `severity="secondary"` e tem precedência sobre `severity`.
134
431
 
135
432
  ## TopConfirmDialog
136
433
 
@@ -179,48 +476,277 @@ não fecha automaticamente o diálogo, permitindo que a aplicação aguarde uma
179
476
  operação assíncrona. Os slots `message` e default permitem substituir a mensagem
180
477
  textual.
181
478
 
182
- ## TopInputText
479
+ ## TopDatePicker
480
+
481
+ Seletor de datas baseado no `DatePicker` do PrimeVue. O valor permanece como
482
+ `Date` (ou arrays de `Date` nos modos `multiple` e `range`); `dateFormat` altera
483
+ somente a apresentação no campo e não converte o `v-model` para texto.
484
+ No modo padrão (`single` com `dd/mm/yy`), a digitação recebe automaticamente a
485
+ máscara brasileira `dd/mm/aaaa`.
486
+
487
+ ```vue
488
+ <script setup lang="ts">
489
+ import { ref } from 'vue'
490
+ import { TopDatePicker } from '@topjoao/top-design-system'
491
+
492
+ const dataNascimento = ref<Date | null>(null)
493
+ </script>
494
+
495
+ <template>
496
+ <TopDatePicker
497
+ v-model="dataNascimento"
498
+ label="Data de nascimento"
499
+ placeholder="Selecione a data"
500
+ :max-date="new Date()"
501
+ required
502
+ error="Informe uma data válida."
503
+ @date-select="validarData"
504
+ />
505
+ </template>
506
+ ```
507
+
508
+ | Prop | Tipo | Padrão |
509
+ |---|---|---|
510
+ | `modelValue` | `Date \| Date[] \| (Date \| null)[] \| null` | `null` |
511
+ | `label` | `string` | `''` |
512
+ | `placeholder` | `string` | `'dd/mm/aaaa'` |
513
+ | `required` | `boolean` | `false` |
514
+ | `error` | `string` | `''` |
515
+ | `invalid` | `boolean` | `false` |
516
+ | `disabled` | `boolean` | `false` |
517
+ | `readonly` | `boolean` | `false` |
518
+ | `selectionMode` | `'single' \| 'multiple' \| 'range'` | `'single'` |
519
+ | `dateFormat` | `string` | `'dd/mm/yy'` |
520
+ | `minDate` / `maxDate` | `Date` | `undefined` |
521
+ | `showIcon` | `boolean` | `true` |
522
+ | `iconDisplay` | `'button' \| 'input'` | `'input'` |
523
+ | `manualInput` | `boolean` | `true` |
524
+ | `showButtonBar` | `boolean` | `false` |
525
+ | `appendTo` | `'body' \| 'self' \| HTMLElement` | `'body'` |
526
+
527
+ Eventos: `update:modelValue`, `input`, `change`, `date-select`, `show`, `hide`,
528
+ `today-click`, `clear-click`, `month-change`, `year-change`, `focus`, `blur` e
529
+ `keydown`. Os slots do `DatePicker` do PrimeVue são repassados pelo wrapper,
530
+ incluindo `date`, `header`, `footer`, `buttonbar`, `inputicon`, `dropdownicon`,
531
+ `previcon` e `nexticon`.
183
532
 
184
- Campo textual baseado no `InputText` do PrimeVue. O `v-model` é sempre
185
- `string`, inclusive para códigos, documentos e identificadores compostos
186
- somente por dígitos; por exemplo, `"001234"` preserva os zeros à esquerda.
533
+ O slot `date` recebe as props de dia disponibilizadas pelo `DatePicker`; os
534
+ slots de ícone recebem as props correspondentes do PrimeVue. Os slots `header`,
535
+ `footer` e `buttonbar` permitem substituir essas regiões. Todos são apenas
536
+ repassados: o wrapper preserva as props e o comportamento do componente-base.
537
+
538
+ `required` adiciona o atributo nativo e o asterisco visual; a validação continua
539
+ sob responsabilidade da aplicação. `error` ativa o estado inválido, associa a
540
+ mensagem ao input com atributos ARIA e a exibe abaixo do campo. `readonly`
541
+ impede edição e seleção sem desabilitar o controle, enquanto `disabled` remove a
542
+ interação. No modo escuro, o campo usa os tokens públicos `--top-field-*`.
543
+
544
+ ## TopFileUpload
545
+
546
+ Seletor de arquivos baseado no `FileUpload` do PrimeVue. O componente valida e
547
+ apresenta os arquivos, mas não os envia: a aplicação consumidora controla o
548
+ upload por `v-model` e pelos eventos.
549
+
550
+ ```vue
551
+ <script setup lang="ts">
552
+ import { ref } from 'vue'
553
+ import { TopFileUpload } from '@topjoao/top-design-system'
554
+
555
+ const anexos = ref<File[]>([])
556
+
557
+ function enviarArquivos(files: File[]) {
558
+ // Envie os arquivos usando o serviço da aplicação.
559
+ }
560
+ </script>
561
+
562
+ <template>
563
+ <TopFileUpload
564
+ v-model="anexos"
565
+ label="Anexos"
566
+ accept=".pdf,image/*"
567
+ multiple
568
+ :max-file-size="5 * 1024 * 1024"
569
+ :max-files="5"
570
+ required
571
+ @select="enviarArquivos"
572
+ />
573
+ </template>
574
+ ```
575
+
576
+ | Prop | Tipo | Padrão |
577
+ |---|---|---|
578
+ | `modelValue` | `File \| File[] \| null` | `null` |
579
+ | `label` | `string` | `''` |
580
+ | `placeholder` | `string` | `'Arraste e solte o arquivo aqui'` |
581
+ | `required` | `boolean` | `false` |
582
+ | `disabled` | `boolean` | `false` |
583
+ | `accept` | `string` | `''` |
584
+ | `multiple` | `boolean` | `false` |
585
+ | `maxFileSize` | `number \| null` (bytes) | `null` |
586
+ | `maxFiles` | `number \| null` | `null` |
587
+ | `error` | `string` | `''` |
588
+ | `selectLabel` | `string` | `'Selecionar arquivo'` |
589
+ | `removeLabel` | `string` | `'Remover'` |
590
+ | `loading` | `boolean` | `false` |
591
+
592
+ Eventos: `update:modelValue`, `select`, `change`, `remove`, `clear` e `error`.
593
+ Erros de tipo, tamanho e quantidade possuem `code`, `message` e o `file`
594
+ relacionado. Os slots `empty` e `preview` permitem customizar a área vazia e a
595
+ pré-visualização. Os métodos `choose()` e `clear()` ficam disponíveis pela ref
596
+ do componente.
597
+
598
+ | Slot | Parâmetros recebidos | Uso |
599
+ |---|---|---|
600
+ | `empty` | `{ choose, disabled }` | Substitui a área vazia. Chame `choose()` para abrir o seletor nativo. |
601
+ | `preview` | `{ file, index, url }` | Substitui a miniatura. `url` é uma object URL apenas para imagens; nos demais casos, é `''`. |
602
+
603
+ ```vue
604
+ <TopFileUpload ref="upload" v-model="anexos" multiple>
605
+ <template #empty="{ choose, disabled }">
606
+ <button type="button" :disabled="disabled" @click="choose()">Anexar documentos</button>
607
+ </template>
608
+ <template #preview="{ file, url }">
609
+ <img v-if="url" :src="url" :alt="file.name">
610
+ <span v-else>{{ file.name }}</span>
611
+ </template>
612
+ </TopFileUpload>
613
+ ```
614
+
615
+ `accept` aceita extensões (`.pdf`), MIME types (`application/pdf`) e curingas
616
+ MIME (`image/*`), separados por vírgula. `maxFileSize` é contado em bytes. Em
617
+ modo simples, a última seleção válida substitui a anterior; com `multiple`,
618
+ arquivos válidos são acumulados sem duplicar nome, tipo e tamanho.
619
+
620
+ ## TopInputNumber
621
+
622
+ Campo numérico baseado no `InputNumber` do PrimeVue, com a mesma estrutura de
623
+ label, erro e acessibilidade dos demais campos. Por padrão usa `pt-BR`. No modo
624
+ `decimal`, o usuário informa explicitamente o separador decimal; no modo
625
+ `currency`, a máscara de centavos vem habilitada e transforma `12345` em
626
+ `R$ 123,45`. O `v-model` permanece sempre numérico (`number`) ou `null` quando
627
+ vazio.
187
628
 
188
629
  ```vue
189
630
  <script setup lang="ts">
190
631
  import { ref } from 'vue'
191
- import { TopInputText } from '@topjoao/top-design-system'
632
+ import { TopInputNumber } from '@topjoao/top-design-system'
192
633
 
193
- const codigo = ref('001234')
634
+ const quantidade = ref<number | null>(null)
635
+ const valorUnitario = ref<number | null>(null)
194
636
  </script>
195
637
 
196
638
  <template>
197
- <TopInputText
198
- id="codigo"
199
- v-model="codigo"
200
- label="Código"
201
- placeholder="Digite o código"
639
+ <TopInputNumber
640
+ v-model="quantidade"
641
+ label="Quantidade"
642
+ :min="1"
643
+ :min-fraction-digits="2"
644
+ :max-fraction-digits="4"
202
645
  required
203
- maxlength="10"
204
- autocomplete="off"
646
+ />
647
+
648
+ <TopInputNumber
649
+ v-model="valorUnitario"
650
+ label="Valor unitário"
651
+ mode="currency"
652
+ currency="BRL"
653
+ :min-fraction-digits="2"
654
+ :max-fraction-digits="2"
205
655
  />
206
656
  </template>
207
657
  ```
208
658
 
209
- | Prop | Tipo | Padrão |
210
- |---|---|---|
211
- | `modelValue` | `string` | `''` |
212
- | `label` | `string` | `''` |
213
- | `placeholder` | `string` | `''` |
214
- | `required` | `boolean` | `false` |
215
- | `error` | `string` | `''` |
216
- | `disabled` | `boolean` | `false` |
217
- | `readonly` | `boolean` | `false` |
659
+ | Prop | Tipo | Padrão | Finalidade |
660
+ |---|---|---|---|
661
+ | `modelValue` | `number \| null` | `null` | Valor numérico controlado. |
662
+ | `label` / `placeholder` | `string` | `''` / `''` | Rótulo e texto auxiliar do campo. |
663
+ | `required` | `boolean` | `false` | Asterisco visual e atributo nativo obrigatório. |
664
+ | `error` | `string` | `''` | Mensagem e estado inválido. |
665
+ | `invalid` | `boolean` | `false` | Força estado inválido sem mostrar mensagem. |
666
+ | `disabled` / `readonly` | `boolean` | `false` / `false` | Remove interação / preserva leitura sem desabilitar. |
667
+ | `locale` | `string` | `'pt-BR'` | Locale para separadores e moeda. |
668
+ | `mode` | `'decimal' \| 'currency'` | `'decimal'` | Formatação decimal ou monetária. |
669
+ | `currency` / `currencyDisplay` | `string` / `'symbol' \| 'code' \| 'name'` | `undefined` / `'symbol'` | Código ISO 4217 e modo de exibição da moeda. |
670
+ | `currencyInputMode` | `'decimal' \| 'cents'` | `'cents'` | Controla a entrada monetária; `decimal` desliga a máscara mesmo quando `cents` é `true`. Não afeta `mode="decimal"`. |
671
+ | `cents` | `boolean` | `true` | Habilita a máscara automática somente em `mode="currency"`; `false` usa o `InputNumber` padrão. |
672
+ | `centsFractionDigits` | `number` | `undefined` (efetivo: `2`) | Primeira opção para definir as casas da máscara monetária. |
673
+ | `currencyFractionDigits` | `number` | `undefined` | Fallback de casas da máscara, usado depois de `centsFractionDigits`. |
674
+ | `useGrouping` / `format` | `boolean` | `true` / `true` | Separadores de milhar e formatação do valor. |
675
+ | `minFractionDigits` / `maxFractionDigits` | `number` | `undefined` | Precisão do PrimeVue. Sem `maxFractionDigits`, o modo decimal aceita até 20 casas; a máscara monetária usa esse valor como último fallback antes de `2`. |
676
+ | `min` / `max` / `step` | `number` | `undefined` / `undefined` / `1` | Limites e passo dos botões/teclado. |
677
+ | `showButtons` / `buttonLayout` | `boolean` / `'stacked' \| 'horizontal' \| 'vertical'` | `false` / `'stacked'` | Exibe e organiza os controles de incremento. |
678
+ | `allowEmpty` / `showClear` / `highlightOnFocus` | `boolean` | `true` / `false` / `false` | Permite limpar, mostra ícone de limpeza e seleciona valor ao focar. |
679
+
680
+ Eventos: `update:modelValue` (`number | null`), `input`, `focus` e `blur`. No
681
+ fluxo padrão do `InputNumber`, o componente também repassa `value-change`.
682
+ Atributos adicionais, como `name`, `autocomplete`, `aria-*` e `data-*`, são
683
+ repassados ao controle interno.
684
+
685
+ Quando a máscara de centavos não está ativa, os slots do `InputNumber` também
686
+ são repassados: `incrementbutton` e
687
+ `decrementbutton` recebem `{ listeners }`; `incrementicon` e `decrementicon`
688
+ substituem os ícones; `clearicon` recebe `{ clearCallback }`.
218
689
 
219
- Atributos e eventos nativos adicionais, como `name`, `maxlength`,
220
- `autocomplete`, `inputmode`, `pattern`, `aria-*`, `data-*`, `focus` e `blur`,
221
- são repassados ao elemento `input` interno.
690
+ Para reproduzir a digitação monetária do TopLicita, a máscara de centavos já
691
+ vem ativa em `mode="currency"`. O usuário digita somente dígitos: `12345`
692
+ resulta em `R$ 123,45` e o `v-model` recebe `123.45`. Para exigir a vírgula
693
+ decimal digitada pelo usuário, passe `:cents="false"` ou
694
+ `currency-input-mode="decimal"`.
695
+ Como a máscara controla o texto enquanto o usuário digita, nesse modo os
696
+ botões incrementais, o ícone de limpeza e seus slots do `InputNumber` não são
697
+ renderizados.
222
698
 
223
- ## TopSelect
699
+ ```vue
700
+ <TopInputNumber
701
+ v-model="valorUnitario"
702
+ label="Valor unitário"
703
+ mode="currency"
704
+ currency="BRL"
705
+ />
706
+ ```
707
+
708
+ ## TopInputText
709
+
710
+ Campo textual baseado no `InputText` do PrimeVue. O `v-model` é sempre
711
+ `string`, inclusive para códigos, documentos e identificadores compostos
712
+ somente por dígitos; por exemplo, `"001234"` preserva os zeros à esquerda.
713
+
714
+ ```vue
715
+ <script setup lang="ts">
716
+ import { ref } from 'vue'
717
+ import { TopInputText } from '@topjoao/top-design-system'
718
+
719
+ const codigo = ref('001234')
720
+ </script>
721
+
722
+ <template>
723
+ <TopInputText
724
+ id="codigo"
725
+ v-model="codigo"
726
+ label="Código"
727
+ placeholder="Digite o código"
728
+ required
729
+ maxlength="10"
730
+ autocomplete="off"
731
+ />
732
+ </template>
733
+ ```
734
+
735
+ | Prop | Tipo | Padrão |
736
+ |---|---|---|
737
+ | `modelValue` | `string` | `''` |
738
+ | `label` | `string` | `''` |
739
+ | `placeholder` | `string` | `''` |
740
+ | `required` | `boolean` | `false` |
741
+ | `error` | `string` | `''` |
742
+ | `disabled` | `boolean` | `false` |
743
+ | `readonly` | `boolean` | `false` |
744
+
745
+ Atributos e eventos nativos adicionais, como `name`, `maxlength`,
746
+ `autocomplete`, `inputmode`, `pattern`, `aria-*`, `data-*`, `focus` e `blur`,
747
+ são repassados ao elemento `input` interno.
748
+
749
+ ## TopSelect
224
750
 
225
751
  Seletor pesquisável baseado no `AutoComplete` do PrimeVue. Ele é genérico: a
226
752
  aplicação fornece os itens, executa a busca e decide qualquer apresentação de
@@ -260,33 +786,201 @@ function searchCustomers({ query }: { query: string }) {
260
786
  </template>
261
787
  ```
262
788
 
263
- | Prop | Tipo | Padrão |
264
- |---|---|---|
265
- | `options` | `array` | `[]` |
789
+ | Prop | Tipo | Padrão |
790
+ |---|---|---|
791
+ | `modelValue` | `SelectOption \| SelectOption[] \| null` | `null` |
792
+ | `options` | `array` | `[]` |
266
793
  | `optionLabel` | `string \| function` | `'label'` |
267
794
  | `optionKey` | `string` | `'id'` |
268
795
  | `optionPrefix` | `string` | `''` |
269
796
  | `showOptionPrefix` | `boolean` | `false` |
270
797
  | `showSelectedPrefix` | `boolean` | `false` |
271
798
  | `loading` / `disabled` / `invalid` | `boolean` | `false` |
272
- | `placeholder` | `string` | `'Search...'` |
799
+ | `placeholder` | `string` | `'Pesquisar...'` |
273
800
  | `minQueryLength` | `number` | `1` |
274
801
  | `multiple` / `forceSelection` | `boolean` | `false` / `true` |
275
802
  | `panelWidth` / `scrollHeight` | `string` | `null` / `'250px'` |
276
- | `emptyMessage` / `loadingMessage` | `string` | mensagens padrão em inglês |
803
+ | `emptyMessage` / `loadingMessage` | `string` | `'Nenhum resultado encontrado.'` / `'Carregando...'` |
277
804
  | `closeOnSelect` | `boolean` | `false` |
278
805
 
279
806
  Eventos: `update:modelValue`, `search`, `loadMore`, `clear`, `select` e
280
807
  `change`.
281
808
 
282
- Slots: `icon`, `option`, `selected-item`, `chip`, `empty`, `option-group` e
283
- `footer`. O slot `icon` recebe `loading`; sem ele, o componente mostra uma lupa
284
- ou um indicador de carregamento. Quando um slot não é informado, o componente usa sua apresentação padrão.
285
- O texto das opções é limitado visualmente pela largura disponível do painel,
286
- sem corte por quantidade fixa de caracteres; o tooltip padrão exibe o valor
287
- completo quando `showTooltip` está ativo.
809
+ Slots: `icon`, `option`, `selected-item`, `chip`, `empty`, `option-group` e
810
+ `footer`. O slot `icon` recebe `loading`; sem ele, o componente mostra uma lupa
811
+ ou um indicador de carregamento. Quando um slot não é informado, o componente usa sua apresentação padrão.
812
+ O texto das opções é limitado visualmente pela largura disponível do painel,
813
+ sem corte por quantidade fixa de caracteres; o tooltip padrão exibe o valor
814
+ completo quando `showTooltip` está ativo.
815
+
816
+ | Slot | Parâmetros recebidos | Uso |
817
+ |---|---|---|
818
+ | `icon` | `{ loading }` | Ícone à esquerda do campo. |
819
+ | `option` | Props nativas, mais `{ option, label, prefix, query }` | Linha de uma opção. |
820
+ | `selected-item` | Props nativas, incluindo `item` | Valor único escolhido. |
821
+ | `chip` | Props nativas, incluindo `value` e `removeCallback` | Tag no modo múltiplo. |
822
+ | `empty` | — | Conteúdo quando não há opções; também substitui o loading padrão. |
823
+ | `option-group` | Props nativas, incluindo `option` | Cabeçalho de um grupo. |
824
+ | `footer` | Props nativas do AutoComplete | Rodapé do painel. |
825
+
826
+ `search` recebe `{ originalEvent, query }` a cada consulta; atualize `options`
827
+ com os resultados. `loadMore` repassa o evento do virtual scroller para busca
828
+ paginar. Pela ref, `hideDropdown()` fecha o painel.
829
+
830
+ ## TopTabs
831
+
832
+ Navegação em abas baseada em `Tabs`, `TabList`, `Tab`, `TabPanels` e `TabPanel`
833
+ do PrimeVue, com estrutura simplificada e estilos dos temas claro e escuro do
834
+ Design System.
288
835
 
289
- ## Desenvolvimento da biblioteca
836
+ ```vue
837
+ <script setup lang="ts">
838
+ import { ref } from 'vue'
839
+ import {
840
+ TopTabs,
841
+ type TopTabItem,
842
+ type TopTabValue,
843
+ } from '@topjoao/top-design-system'
844
+
845
+ const activeTab = ref<TopTabValue>('dados')
846
+ const tabs: TopTabItem[] = [
847
+ { value: 'dados', label: 'Dados' },
848
+ { value: 'documentos', label: 'Documentos' },
849
+ { value: 'auditoria', label: 'Auditoria', disabled: true },
850
+ ]
851
+ </script>
852
+
853
+ <template>
854
+ <TopTabs v-model="activeTab" :tabs="tabs">
855
+ <template #dados>
856
+ Dados gerais do processo
857
+ </template>
858
+
859
+ <template #documentos>
860
+ Documentos anexados
861
+ </template>
862
+
863
+ <template #auditoria>
864
+ Histórico de auditoria
865
+ </template>
866
+ </TopTabs>
867
+ </template>
868
+ ```
869
+
870
+ | Prop | Tipo | Padrão |
871
+ |---|---|---|
872
+ | `modelValue` | `string \| number` | obrigatório |
873
+ | `tabs` | `TopTabItem[]` | obrigatório |
874
+ | `lazy` | `boolean` | `false` |
875
+ | `scrollable` | `boolean` | `true` |
876
+
877
+ Cada `TopTabItem` possui `value`, `label` e `disabled?`. O `value` deve ser
878
+ único e identifica tanto a seleção quanto o slot do painel; por exemplo,
879
+ `value: 'documentos'` utiliza `#documentos`. Cada slot recebe `tab` e `active`.
880
+ O componente emite somente `update:modelValue`. Atributos adicionais, incluindo
881
+ as opções de passthrough do PrimeVue, são repassados ao componente `Tabs`.
882
+
883
+ ## TopToast
884
+
885
+ `TopToast` personaliza o renderizador do serviço `Toast` do PrimeVue. Registre
886
+ `ToastService` uma vez, renderize um único `TopToast` perto da raiz e dispare
887
+ mensagens com `useToast`. Ele não recebe uma lista de mensagens por prop.
888
+
889
+ ```ts
890
+ // main.ts
891
+ import PrimeVue from 'primevue/config'
892
+ import ToastService from 'primevue/toastservice'
893
+ import { createApp } from 'vue'
894
+ import App from './App.vue'
895
+
896
+ createApp(App).use(PrimeVue).use(ToastService).mount('#app')
897
+ ```
898
+
899
+ ```vue
900
+ <script setup lang="ts">
901
+ import { useToast } from 'primevue/usetoast'
902
+ import { TopButton, TopToast } from '@topjoao/top-design-system'
903
+
904
+ const toast = useToast()
905
+ const abrirCadastro = () => { /* navegue para o cadastro */ }
906
+
907
+ function salvar() {
908
+ toast.add({
909
+ severity: 'success', summary: 'Cadastro concluído', detail: 'As alterações foram salvas.', life: 5000,
910
+ data: {
911
+ footer: 'Protocolo: CAD-2026-0042',
912
+ action: { label: 'Ver cadastro', icon: 'pi pi-arrow-right', onClick: () => abrirCadastro() },
913
+ },
914
+ })
915
+ }
916
+ </script>
917
+
918
+ <template>
919
+ <TopToast :base-z-index="30000" />
920
+ <TopButton label="Salvar" @click="salvar" />
921
+ </template>
922
+ ```
923
+
924
+ | Prop | Tipo | Padrão | Finalidade |
925
+ |---|---|---|---|
926
+ | `baseZIndex` | `number` | `30000` | Camada base das notificações. |
927
+
928
+ Além das opções usuais de `ToastMessageOptions` do PrimeVue (`severity`,
929
+ `summary`, `detail`, `life`, `closable` etc.), `data` aceita `TopToastData`:
930
+
931
+ | Campo | Tipo | Efeito |
932
+ |---|---|---|
933
+ | `data.footer` | `string \| number` | Texto discreto abaixo da mensagem. |
934
+ | `data.action.label` | `string` | Rótulo da ação. |
935
+ | `data.action.icon` | `string` opcional | Classe de ícone PrimeIcons. |
936
+ | `data.action.onClick` | `() => void` opcional | Função chamada ao clicar na ação. |
937
+
938
+ | Slot | Parâmetros recebidos | Uso |
939
+ |---|---|---|
940
+ | `action` | `{ action, message, run }` | Substitui o botão; execute `run()` para chamar `action.onClick`. |
941
+ | `footer` | `{ message, footer }` | Substitui o rodapé. |
942
+
943
+ ## Tipos e exports públicos
944
+
945
+ O pacote raiz exporta todos os componentes, `TopSolutionsPreset`, `colors` e
946
+ os tipos abaixo. Use `import type` para não acrescentar código ao bundle.
947
+
948
+ ```ts
949
+ import {
950
+ colors,
951
+ TopSolutionsPreset,
952
+ type TopButtonSeverity,
953
+ type TopDatePickerSelectionMode,
954
+ type TopDatePickerValue,
955
+ type TopFileUploadError,
956
+ type TopFileUploadValue,
957
+ type TopInputNumberValue,
958
+ type TopInputNumberMode,
959
+ type TopInputNumberButtonLayout,
960
+ type TopInputNumberCurrencyInputMode,
961
+ type TopNavItem,
962
+ type TopNavSection,
963
+ type TopTabItem,
964
+ type TopToastData,
965
+ } from '@topjoao/top-design-system'
966
+ ```
967
+
968
+ `TopNavItem` descreve um nó (`id`, `label`, `to?`, `icon?`, `disabled?`,
969
+ `children?`, `data?`); `TopNavSection` é o mesmo contrato com `children`
970
+ obrigatório. `TopNavAction`, `TopNavUser`, `TopNavClient` e
971
+ `TopNavUserMenuItem` correspondem às props de mesmo nome. A aparência da barra
972
+ é definida por `TopNavBarAppearance` e seus subtipos exportados:
973
+ `TopNavBarColors`, `TopNavBarSurfaces`, `TopNavBarBorders`, `TopNavBarShape` e
974
+ `TopNavBarFocus`.
975
+
976
+ `TopInputNumberValue`, `TopInputNumberMode`, `TopInputNumberButtonLayout` e
977
+ `TopInputNumberCurrencyInputMode`
978
+ tipam, respectivamente, o valor, o modo de formatação, o layout dos botões e o
979
+ modo de entrada monetária do campo numérico. `colors` expõe as escalas
980
+ imutáveis `primary`, `secondary`, `success`, `warn` e
981
+ `danger`, cada uma com tons de `50` a `950`.
982
+
983
+ ## Desenvolvimento da biblioteca
290
984
 
291
985
  ```bash
292
986
  npm install
@@ -311,10 +1005,10 @@ publicado.
311
1005
  npm run storybook
312
1006
  ```
313
1007
 
314
- Abra `http://localhost:6006` para acessar as histórias de `TopButton`,
315
- `TopConfirmDialog`, `TopInputText` e `TopSelect`. Use o botão de contraste na
316
- barra superior para alternar o preview entre tema claro e escuro. Para gerar a
317
- versão estática da documentação, execute:
1008
+ Abra `http://localhost:6006` para acessar as histórias de `TopButton`,
1009
+ `TopConfirmDialog`, `TopDatePicker`, `TopInputText`, `TopInputNumber`, `TopSelect` e `TopTabs`. Use o botão de
1010
+ contraste na barra superior para alternar o preview entre tema claro e escuro.
1011
+ Para gerar a versão estática da documentação, execute:
318
1012
 
319
1013
  ```bash
320
1014
  npm run build-storybook
@@ -326,10 +1020,14 @@ Para gerar um pacote local instalável:
326
1020
  npm pack
327
1021
  ```
328
1022
 
329
- Para publicar uma nova versão beta, primeiro altere a versão; versões
330
- publicadas no npm não podem ser sobrescritas.
331
-
332
- ```bash
333
- npm version prerelease --preid=beta --no-git-tag-version
334
- npm publish --access public --tag beta
335
- ```
1023
+ Para publicar uma nova versão estável, primeiro incremente a versão seguindo o
1024
+ versionamento semântico; versões já publicadas no npm não podem ser
1025
+ sobrescritas. Use `patch`, `minor` ou `major` conforme o impacto da mudança.
1026
+
1027
+ ```bash
1028
+ npm version patch --no-git-tag-version
1029
+ npm publish --access public --tag latest
1030
+ ```
1031
+
1032
+ A tag `latest` é a padrão do npm. Assim, consumidores instalam a versão estável
1033
+ simplesmente com `npm install @topjoao/top-design-system`.