ads-nuxt 0.1.1 → 0.1.2

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 (74) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +567 -546
  3. package/app/app.config.ts +25 -25
  4. package/app/assets/ads/checkbox-check.svg +5 -5
  5. package/app/assets/ads/checkbox-minus.svg +5 -5
  6. package/app/assets/brand/farmarcas.svg +6 -6
  7. package/app/assets/brand/radar.svg +9 -9
  8. package/app/assets/css/component-tokens.css +403 -403
  9. package/app/assets/css/main.css +617 -617
  10. package/app/components/AdsBadge.vue +48 -48
  11. package/app/components/AdsBroadcast.vue +45 -45
  12. package/app/components/AdsButton.vue +569 -569
  13. package/app/components/AdsButtonGroup.vue +39 -39
  14. package/app/components/AdsButtonMenu.vue +48 -48
  15. package/app/components/AdsCard.vue +117 -117
  16. package/app/components/AdsCharttip.vue +78 -78
  17. package/app/components/AdsCheckbox.vue +77 -77
  18. package/app/components/AdsDatePicker.vue +473 -473
  19. package/app/components/AdsDropdownMenu.vue +19 -19
  20. package/app/components/AdsEmptyState.vue +58 -58
  21. package/app/components/AdsFarmarcasPill.vue +74 -74
  22. package/app/components/AdsFeatureCard.vue +217 -217
  23. package/app/components/AdsFileCard.vue +101 -101
  24. package/app/components/AdsFilterDropdown.vue +174 -174
  25. package/app/components/AdsFilterOption.vue +72 -72
  26. package/app/components/AdsFilterSelect.vue +202 -202
  27. package/app/components/AdsFooter.vue +25 -25
  28. package/app/components/AdsInput.vue +143 -143
  29. package/app/components/AdsListDropdown.vue +44 -44
  30. package/app/components/AdsLoading.vue +109 -109
  31. package/app/components/AdsMenuBar.vue +103 -103
  32. package/app/components/AdsMetricCard.vue +119 -119
  33. package/app/components/AdsMiniPill.vue +40 -40
  34. package/app/components/AdsModal.vue +157 -157
  35. package/app/components/AdsMonthPicker.vue +80 -80
  36. package/app/components/AdsNavbarApp.vue +67 -67
  37. package/app/components/AdsNavbarDesk.vue +62 -62
  38. package/app/components/AdsNotabilityPill.vue +27 -27
  39. package/app/components/AdsNumberInput.vue +166 -166
  40. package/app/components/AdsPagination.vue +91 -91
  41. package/app/components/AdsProductTag.vue +61 -61
  42. package/app/components/AdsRadio.vue +70 -70
  43. package/app/components/AdsSearchInput.vue +113 -113
  44. package/app/components/AdsSegmentedTabs.vue +28 -28
  45. package/app/components/AdsSideMenu.vue +101 -101
  46. package/app/components/AdsSmalltip.vue +44 -44
  47. package/app/components/AdsSteptip.vue +101 -101
  48. package/app/components/AdsSwitch.vue +59 -59
  49. package/app/components/AdsTable.vue +100 -100
  50. package/app/components/AdsTableToolbar.vue +44 -44
  51. package/app/components/AdsTabs.vue +51 -51
  52. package/app/components/AdsTextarea.vue +109 -109
  53. package/app/components/AdsToast.vue +181 -181
  54. package/app/components/AdsTooltip.vue +66 -66
  55. package/app/components/InvertedTooltip.vue +40 -40
  56. package/app/components/OverlayLoading.vue +173 -173
  57. package/app/components/ProgressBarLoading.vue +256 -256
  58. package/app/composables/useOverlayLoading.ts +66 -66
  59. package/app/locale/pt-br.ts +6 -6
  60. package/app/plugins/ads-toast.client.ts +24 -24
  61. package/app/theme/ads-theme.ts +370 -370
  62. package/app/theme/component-tokens.json +402 -402
  63. package/app/theme/component-tokens.ts +815 -815
  64. package/app/types/overlay-loading.types.ts +26 -26
  65. package/app/utils/ads-filter-select.ts +172 -172
  66. package/app/utils/ads-table.ts +204 -204
  67. package/app/utils/calendar-date.ts +128 -128
  68. package/app/utils/category-role.ts +45 -45
  69. package/app/utils/money.ts +77 -77
  70. package/app/utils/notability.ts +8 -8
  71. package/app/utils/parser.ts +134 -134
  72. package/app/utils/percentage.ts +54 -54
  73. package/nuxt.config.ts +31 -32
  74. package/package.json +48 -46
package/README.md CHANGED
@@ -1,546 +1,567 @@
1
- # ads-nuxt
2
-
3
- **Alquimia Design System (ADS)** para Nuxt, construído sobre o [Nuxt UI](https://ui.nuxt.com) v4 e o Tailwind CSS v4.
4
-
5
- O pacote é uma **Nuxt Layer**: ao estendê-lo, seu projeto recebe de uma vez os componentes `Ads*`, os tokens de design (cores, espaçamento, raios, sombras, tipografia), o tema do Nuxt UI customizado, os utilitários de formatação em pt-BR e a fonte Inter.
6
-
7
- [![npm](https://img.shields.io/npm/v/ads-nuxt.svg)](https://www.npmjs.com/package/ads-nuxt)
8
- [![license](https://img.shields.io/npm/l/ads-nuxt.svg)](./LICENSE)
9
-
10
- ---
11
-
12
- ## Sumário
13
-
14
- - [Recursos](#recursos)
15
- - [Requisitos](#requisitos)
16
- - [Instalação](#instalação)
17
- - [Configuração](#configuração)
18
- - [Uso rápido](#uso-rápido)
19
- - [Componentes](#componentes)
20
- - [Exemplos](#exemplos)
21
- - [Tokens de design](#tokens-de-design)
22
- - [Tema do Nuxt UI](#tema-do-nuxt-ui)
23
- - [Composables](#composables)
24
- - [Utilitários](#utilitários)
25
- - [Localização (pt-BR)](#localização-pt-br)
26
- - [Desenvolvimento](#desenvolvimento)
27
- - [Estrutura do projeto](#estrutura-do-projeto)
28
- - [Licença](#licença)
29
-
30
- ---
31
-
32
- ## Recursos
33
-
34
- - **Mais de 50 componentes** prontos para produção, com prefixo `Ads` (auto-importados pelo Nuxt).
35
- - **Tokens em três camadas** (primitivos → semânticos → de componente), expostos como variáveis CSS `--ads-*` e como cores do Tailwind (`ads-*`).
36
- - **Tema do Nuxt UI** pré-configurado: botão, input, calendário, select, toast e tooltip já seguem o visual ADS.
37
- - **Fonte Inter** configurada via `@nuxt/fonts`.
38
- - **Ícones Lucide** via `@nuxt/icon` (use `i-lucide-*`).
39
- - **Utilitários pt-BR**: moeda (BRL), porcentagem, datas, notabilidade e filtros.
40
- - **Playground** com documentação viva de todos os componentes e tokens.
41
- - Estados “congeláveis” (`state`) nos componentes, pensados para documentação e testes visuais.
42
-
43
- ## Requisitos
44
-
45
- | Dependência | Versão |
46
- | ----------- | --------- |
47
- | Node.js | 20+ (recomendado 22) |
48
- | Nuxt | `^4.0.0` |
49
- | Vue | `^3.5.18` |
50
-
51
- `nuxt` e `vue` são *peer dependencies*. As demais (`@nuxt/ui`, `@nuxt/fonts`, `@nuxt/icon`, `@vueuse/nuxt`, `tailwindcss`, ícones Lucide) já vêm como dependências do pacote.
52
-
53
- ## Instalação
54
-
55
- ```bash
56
- # pnpm
57
- pnpm add ads-nuxt
58
-
59
- # npm
60
- npm install ads-nuxt
61
-
62
- # yarn
63
- yarn add ads-nuxt
64
- ```
65
-
66
- ## Configuração
67
-
68
- Estenda a layer no `nuxt.config.ts` do seu projeto:
69
-
70
- ```ts
71
- // nuxt.config.ts
72
- export default defineNuxtConfig({
73
- extends: ["ads-nuxt"],
74
- });
75
- ```
76
-
77
- Isso já registra automaticamente:
78
-
79
- - os módulos `@nuxt/ui`, `@nuxt/fonts`, `@nuxt/icon` e `@vueuse/nuxt`;
80
- - o CSS global (Tailwind, Nuxt UI, cores e tokens de componente);
81
- - a fonte **Inter** (pesos 300, 400, 500, 700 e 800);
82
- - a coleção de ícones **lucide**;
83
- - o `app.config.ts` com o tema ADS para o Nuxt UI;
84
- - o plugin de toast e o locale pt-BR.
85
-
86
- > **Modo de cor:** a layer define `ui.colorMode: false` — o ADS é um sistema de tema claro. Se precisar sobrescrever, redefina no `nuxt.config.ts` do seu projeto.
87
-
88
- ### Envolva o app com `UApp`
89
-
90
- O Nuxt UI exige o componente `UApp` para toasts, tooltips e overlays funcionarem:
91
-
92
- ```vue
93
- <!-- app/app.vue -->
94
- <template>
95
- <UApp :locale="uiLocale" :tooltip="{ delayDuration: 400 }" :toaster="adsToaster">
96
- <NuxtPage />
97
- </UApp>
98
- </template>
99
-
100
- <script setup lang="ts">
101
- import { uiLocale } from "ads-nuxt/app/locale/pt-br";
102
- import { adsToaster } from "ads-nuxt/app/theme/ads-theme";
103
- </script>
104
- ```
105
-
106
- `adsToaster` posiciona os toasts no canto superior direito, sem barra de progresso, no padrão ADS.
107
-
108
- ## Uso rápido
109
-
110
- Os componentes são auto-importados, sem `import` manual:
111
-
112
- ```vue
113
- <template>
114
- <AdsCard title="Cadastro" description="Preencha os dados abaixo.">
115
- <div class="flex flex-col gap-4">
116
- <AdsInput v-model="nome" label="Nome" placeholder="Digite seu nome" />
117
- <AdsButton type="filled" label="Salvar" leading icon="i-lucide-save" />
118
- </div>
119
- </AdsCard>
120
- </template>
121
-
122
- <script setup lang="ts">
123
- const nome = ref("");
124
- </script>
125
- ```
126
-
127
- ## Componentes
128
-
129
- ### Ações
130
-
131
- | Componente | Descrição |
132
- | ---------------- | --------- |
133
- | `AdsButton` | Botão (`filled`, `outline`, `unfilled`, `secondary`, `ia`) em 2 tamanhos e 8 cores. Suporta ícones, `loading` e `to` (vira link). |
134
- | `AdsButtonGroup` | Agrupa botões. |
135
- | `AdsButtonMenu` | Botão com menu de ações. |
136
-
137
- ### Formulários
138
-
139
- | Componente | Descrição |
140
- | ----------------- | --------- |
141
- | `AdsInput` | Campo de texto/número com label, hint, erro, info, ícone e sufixo. |
142
- | `AdsNumberInput` | Campo numérico dedicado. |
143
- | `AdsTextarea` | Área de texto. |
144
- | `AdsSearchInput` | Campo de busca. |
145
- | `AdsCheckbox` | Checkbox com estado indeterminado. |
146
- | `AdsRadio` | Botão de rádio. |
147
- | `AdsSwitch` | Alternador (toggle). |
148
- | `AdsDatePicker` | Seletor de data ou intervalo, com `min`, `max` e `maximumDays`. |
149
- | `AdsMonthPicker` | Seletor de mês. |
150
- | `AdsFilterSelect` | Filtro com seleção (checkbox, radio ou mês). |
151
- | `AdsFilterDropdown` / `AdsFilterOption` | Dropdown de filtros e suas opções. |
152
-
153
- ### Navegação
154
-
155
- | Componente | Descrição |
156
- | ----------------- | --------- |
157
- | `AdsNavbarDesk` / `AdsNavbarApp` | Barra de navegação desktop e mobile. |
158
- | `AdsSideMenu` | Menu lateral. |
159
- | `AdsMenuBar` | Barra de menu. |
160
- | `AdsTabs` | Abas em formato de link. |
161
- | `AdsSegmentedTabs`| Abas segmentadas. |
162
- | `AdsPagination` | Paginação com reticências automáticas (`v-model:page`). |
163
- | `AdsDropdownMenu` / `AdsListDropdown` | Menus suspensos. |
164
- | `AdsFooter` | Rodapé. |
165
-
166
- ### Exibição de dados
167
-
168
- | Componente | Descrição |
169
- | ----------------- | --------- |
170
- | `AdsTable` | Tabela baseada no `UTable`, com densidade, zebra, bordas, degradê por nível, `sticky`, loading e estado vazio. |
171
- | `AdsTableToolbar` | Barra de ferramentas da tabela. |
172
- | `AdsCard` | Cartão genérico. |
173
- | `AdsMetricCard` | Cartão de métrica/indicador. |
174
- | `AdsFeatureCard` | Cartão de funcionalidade. |
175
- | `AdsFileCard` | Cartão de arquivo. |
176
- | `AdsEmptyState` | Estado vazio. |
177
-
178
- ### Indicadores e status
179
-
180
- | Componente | Descrição |
181
- | -------------------- | --------- |
182
- | `AdsBadge` | Contador ou ponto (`mini`) em 7 cores. |
183
- | `AdsPill` | Pílula de status (`default`, `success`, `attention`, `warning`, `new`, `blocked`, `innovation`, `neutral`) em tom `primary` ou `secondary`. |
184
- | `AdsMiniPill` | Versão compacta da pílula. |
185
- | `AdsNotabilityPill` | Pílula de notabilidade. |
186
- | `AdsFarmarcasPill` | Pílula de marca Farmarcas. |
187
- | `AdsProductTag` | Tag de produto. |
188
-
189
- ### Feedback e overlays
190
-
191
- | Componente | Descrição |
192
- | ----------------- | --------- |
193
- | `AdsModal` | Modal (`dialog` ou `sheet`) com 5 tamanhos, ações padrão e slots. |
194
- | `AdsToast` | Aviso em faixa (`banner`) ou reporte escuro (`status`). |
195
- | `AdsBroadcast` | Comunicado em destaque. |
196
- | `AdsTooltip` | Tooltip. |
197
- | `AdsSmalltip` / `AdsSteptip` / `AdsCharttip` | Variações de tooltip (compacta, em passos e para gráficos). |
198
- | `AdsLoading` | Indicador de carregamento. |
199
- | `ProgressBarLoading` | Barra de progresso. |
200
- | `OverlayLoading` | Overlay de carregamento/sucesso/erro (usado por `useOverlayLoading`). |
201
-
202
- ## Exemplos
203
-
204
- ### Botões
205
-
206
- ```vue
207
- <AdsButton type="filled" label="Salvar" />
208
- <AdsButton type="outline" color="success" label="Aprovar" />
209
- <AdsButton type="unfilled" size="sm" label="Cancelar" />
210
- <AdsButton type="ia" label="Gerar com IA" leading icon="i-lucide-sparkles" />
211
- <AdsButton type="filled" label="Enviando" loading />
212
- <AdsButton type="filled" label="Ir para o painel" to="/painel" />
213
- ```
214
-
215
- | Prop | Valores |
216
- | ------------ | ------- |
217
- | `type` | `filled` \| `outline` \| `unfilled` \| `secondary` \| `ia` |
218
- | `color` | `primary` \| `success` \| `attention` \| `warning` \| `new` \| `innovation` \| `blocked` \| `neutral` |
219
- | `size` | `md` \| `sm` |
220
- | `nativeType` | `button` \| `submit` \| `reset` (a prop `type` é o visual do ADS) |
221
-
222
- ### Campos de formulário
223
-
224
- ```vue
225
- <AdsInput
226
- v-model="preco"
227
- label="Preço"
228
- hint="Valor unitário"
229
- suffix="R$"
230
- type="number"
231
- :error="erro"
232
- />
233
- ```
234
-
235
- Estados disponíveis via `state` (útil para documentação): `default`, `active`, `focus`, `error`, `disabled` e `ai`.
236
-
237
- ### Modal
238
-
239
- ```vue
240
- <template>
241
- <AdsButton label="Excluir" color="warning" @click="aberto = true" />
242
-
243
- <AdsModal
244
- v-model:open="aberto"
245
- title="Excluir item"
246
- description="Essa ação não pode ser desfeita."
247
- cancel-label="Cancelar"
248
- confirm-label="Excluir"
249
- @confirm="excluir"
250
- @cancel="aberto = false"
251
- />
252
- </template>
253
-
254
- <script setup lang="ts">
255
- const aberto = ref(false);
256
- const excluir = () => {
257
- /* ... */
258
- aberto.value = false;
259
- };
260
- </script>
261
- ```
262
-
263
- Eventos: `confirm`, `cancel` e `dismiss` (com o motivo `"esc"` ou `"outside"`). Slots: `default`, `title` e `footer`.
264
-
265
- ### Toast
266
-
267
- Como componente em linha:
268
-
269
- ```vue
270
- <AdsToast status="success" title="Tudo certo" message="Alterações salvas." />
271
- <AdsToast status="error" message="Falha ao salvar." action-label="Tentar novamente" />
272
- <AdsToast appearance="status" status="neutral" title="Relatório" subtitle="Explicação opcional" />
273
- ```
274
-
275
- Como toast flutuante, usando o `useToast` do Nuxt UI (as cores de status e os ícones do ADS são aplicados automaticamente pelo plugin da layer):
276
-
277
- ```ts
278
- const toast = useToast();
279
-
280
- toast.add({
281
- title: "Salvo",
282
- description: "Suas alterações foram salvas.",
283
- color: "success",
284
- });
285
- ```
286
-
287
- ### Pílulas e badges
288
-
289
- ```vue
290
- <AdsPill status="success" label="Ativo" />
291
- <AdsPill status="warning" tone="secondary" label="Atrasado" icon="i-lucide-alert-triangle" />
292
- <AdsBadge color="primary" :value="5" />
293
- <AdsBadge color="warning" mini />
294
- ```
295
-
296
- ### Paginação e abas
297
-
298
- ```vue
299
- <AdsPagination v-model:page="pagina" :total-pages="20" />
300
-
301
- <AdsTabs v-model="aba" :items="itens" />
302
- ```
303
-
304
- ### Tabela
305
-
306
- ```vue
307
- <AdsTable
308
- :data="linhas"
309
- :columns="colunas"
310
- density="md"
311
- striped
312
- :loading="carregando"
313
- empty-label="Nenhum resultado encontrado"
314
- />
315
- ```
316
-
317
- Para montar colunas, a layer exporta helpers em `app/utils/ads-table.ts`, como `adsTableColumn`, `adsTablePinned`, `adsTableGroup`, `adsTableVariationClass` e `adsTableTreeIndent`.
318
-
319
- ### Seletor de datas
320
-
321
- ```vue
322
- <!-- Data única -->
323
- <AdsDatePicker v-model="data" min="2026-01-01" />
324
-
325
- <!-- Intervalo (máximo de 31 dias) -->
326
- <AdsDatePicker range v-model:start="inicio" v-model:end="fim" :maximum-days="31" />
327
- ```
328
-
329
- As datas trafegam como string `YYYY-MM-DD`.
330
-
331
- ## Tokens de design
332
-
333
- Os tokens vêm do Figma do ADS e estão organizados em três camadas:
334
-
335
- 1. **Primitivos** — valores brutos (escalas de cor, espaçamentos).
336
- 2. **Semânticos** — intenção de uso (`--ads-surface-*`, `--ads-text-*`, `--ads-border-*`, `--ads-status-*`).
337
- 3. **De componente** — ajustes finos por componente (`--ads-button-*`, `--ads-modal-*`, `--ads-tooltip-*`…).
338
-
339
- ### Variáveis CSS
340
-
341
- ```css
342
- .meu-card {
343
- background: var(--ads-surface-main);
344
- color: var(--ads-text-secondary);
345
- border-radius: var(--ads-button-radius);
346
- box-shadow: var(--ads-shadow-level-3);
347
- }
348
- ```
349
-
350
- ### Classes Tailwind
351
-
352
- As variáveis semânticas também estão mapeadas como cores do Tailwind (`--color-ads-*`):
353
-
354
- ```html
355
- <div class="bg-ads-surface-main border-ads-border-width-thin"></div>
356
- ```
357
-
358
- ### Escalas de cor
359
-
360
- | Escala | Uso |
361
- | ------------------ | --- |
362
- | `primary` / `secondary` | Azul do Radar Pricing, de 50 a 950 (base `#006ff7`). |
363
- | `success` | Verde de sucesso (base `#15c57e`). |
364
- | Neutros | `neutralLight`, `neutralMid` e `neutralDark`. |
365
- | Status | `success`, `attention`, `warning`, `new`, `innovation`, `blocked`. |
366
-
367
- ### Espaçamento
368
-
369
- | Token | px | Token | px | Token | px |
370
- | ------ | --- | ------ | --- | ------ | --- |
371
- | quark | 4 | sm | 32 | xxxl | 120 |
372
- | nano | 8 | rg | 40 | huge | 160 |
373
- | xxxs | 12 | md | 48 | giant | 200 |
374
- | xxs | 16 | lg | 56 | | |
375
- | xs | 24 | xl / xxl | 64 / 80 | | |
376
-
377
- Os mesmos valores estão disponíveis em TypeScript, em `app/theme/ads-tokens.ts` (`adsSpacing`, `adsRadarPricing`, `adsRadarBase`, `adsNeutralLight`, `adsNeutralMid`, `adsNeutralDark`, `adsSuccess`…).
378
-
379
- ### Personalizando tokens de componente
380
-
381
- Os tokens de componente são gerados a partir de `app/theme/component-tokens.json` para `component-tokens.css`. Para ajustar no seu projeto sem editar o pacote, sobrescreva a variável CSS depois do CSS da layer:
382
-
383
- ```css
384
- :root {
385
- --ads-button-radius: 4px;
386
- --ads-button-primary: #0050b3;
387
- }
388
- ```
389
-
390
- ## Tema do Nuxt UI
391
-
392
- O `app.config.ts` da layer customiza os seguintes componentes do Nuxt UI para seguir o ADS:
393
-
394
- `button`, `input`, `inputDate`, `calendar`, `select`, `selectMenu`, `toast`, `toaster` e `tooltip`.
395
-
396
- Por ser uma layer, você pode estender ou sobrescrever no `app.config.ts` do seu projeto:
397
-
398
- ```ts
399
- // app/app.config.ts
400
- export default defineAppConfig({
401
- ui: {
402
- button: {
403
- slots: {
404
- base: "rounded-md",
405
- },
406
- },
407
- },
408
- });
409
- ```
410
-
411
- ## Composables
412
-
413
- ### `useOverlayLoading`
414
-
415
- Exibe um overlay de tela cheia para carregamento, sucesso, erro, busca ou informação, com barra de progresso opcional.
416
-
417
- ```ts
418
- const overlay = useOverlayLoading();
419
-
420
- overlay.show({
421
- variant: "loading",
422
- title: "Processando",
423
- description: "Isso pode levar alguns segundos.",
424
- showProgress: true,
425
- progress: 10,
426
- });
427
-
428
- overlay.update({ progress: 60 });
429
-
430
- overlay.update({ variant: "success", title: "Concluído!" });
431
-
432
- overlay.close();
433
- ```
434
-
435
- | Método | Descrição |
436
- | ----------------- | --------- |
437
- | `show(options)` | Abre o overlay (fecha o anterior, se houver) e retorna o id. |
438
- | `update(options)` | Mescla novas props no overlay aberto. |
439
- | `close()` | Fecha o overlay. |
440
- | `isOpen()` | Indica se há overlay aberto. |
441
- | `getCurrentId()` | Retorna o id do overlay atual. |
442
-
443
- Opções (`OverlayLoadingOptions`):
444
-
445
- | Opção | Tipo |
446
- | ----------------- | ---- |
447
- | `variant` | `"loading"` \| `"success"` \| `"error"` \| `"search"` \| `"info"` |
448
- | `title`, `description`, `hint` | `string` |
449
- | `showProgress`, `progress` | `boolean`, `number` |
450
- | `iconSrc` | `string` |
451
- | `actionLabel`, `onAction` | rótulo e callback de ação |
452
- | `onUserClose` | callback ao usuário fechar |
453
- | `closableVariants`| `("success" \| "error")[]` — variantes que o usuário pode fechar |
454
-
455
- ## Utilitários
456
-
457
- Todos ficam em `app/utils` e são auto-importados pelo Nuxt.
458
-
459
- | Arquivo | Funções principais |
460
- | --------------------- | ------------------ |
461
- | `money.ts` | `numberToBRL`, `numberToCompactBRL`, `parseStringMoneyToFloat`, `formatPriceInput`, `parsePriceInput` |
462
- | `percentage.ts` | `formatPercentage`, `formatPercentageWithDecimals`, `formatPercentagePtBr` |
463
- | `parser.ts` | `parseToPercentage`, `parsePercentageToFloat`, `getTodayDateString`, `formatDateOnlyToPtBr`, `formatDateToPtBr`, `daysBetweenDateOnly`, `daysFromTodayToDateOnly`, `normalizePercentage` |
464
- | `calendar-date.ts` | Conversão entre `string` e `CalendarDate` (`@internationalized/date`) e helpers de intervalo |
465
- | `notability.ts` | `formatNotability` |
466
- | `category-role.ts` | `CATEGORY_ROLES`, `formatCategoryRole`, `parseCategoryRole` |
467
- | `ads-filter-select.ts`| Helpers para `AdsFilterSelect` (agrupamento, seleção, rótulos, meses) |
468
- | `ads-table.ts` | Helpers e tipos para `AdsTable` |
469
-
470
- ```ts
471
- numberToBRL(1234.5); // "R$ 1.234,50"
472
- numberToBRL(-10); // "R$ -10,00"
473
- numberToBRL(null); // "-"
474
- numberToCompactBRL(2_500_000); // valor compacto em milhões
475
- ```
476
-
477
- ## Localização (pt-BR)
478
-
479
- A layer inclui `app/locale/pt-br.ts`, que exporta o locale do Nuxt UI para português do Brasil (calendário, meses e rótulos):
480
-
481
- ```ts
482
- import { uiLocale, UI_LOCALE_CODE } from "ads-nuxt/app/locale/pt-br";
483
- // UI_LOCALE_CODE === "pt-BR"
484
- ```
485
-
486
- Passe-o ao `UApp` como mostrado em [Configuração](#configuração).
487
-
488
- ## Desenvolvimento
489
-
490
- Este repositório usa **pnpm** e contém um **playground** Nuxt com a documentação interativa dos componentes e dos tokens.
491
-
492
- ```bash
493
- git clone https://github.com/jbfarmarcas/alquimia-design-system.git
494
- cd alquimia-design-system
495
- pnpm install
496
-
497
- pnpm dev # playground em http://localhost:3010
498
- pnpm build # build do playground
499
- pnpm preview # preview do build
500
- ```
501
-
502
- Páginas do playground:
503
-
504
- | Rota | Conteúdo |
505
- | ------------------------- | -------- |
506
- | `/design-system` | Catálogo de componentes com demos e código |
507
- | `/design-system/tabelas` | Variações de tabela |
508
- | `/design-system/tokens` | Editor visual dos tokens de componente |
509
-
510
- ### Docker
511
-
512
- ```bash
513
- docker compose up
514
- ```
515
-
516
- ### Publicação
517
-
518
- O pacote publica apenas `app/` e `nuxt.config.ts` (campo `files`), com acesso público:
519
-
520
- ```bash
521
- pnpm publish
522
- ```
523
-
524
- ## Estrutura do projeto
525
-
526
- ```
527
- .
528
- ├── app/ # Conteúdo publicado no npm (a layer)
529
- │ ├── app.config.ts # Tema do Nuxt UI
530
- │ ├── assets/ # CSS, SVGs de marca e animações
531
- │ ├── components/ # Componentes Ads*
532
- │ ├── composables/ # useOverlayLoading
533
- │ ├── constants/ # Constantes (swatches de cor)
534
- │ ├── locale/ # Locale pt-BR
535
- │ ├── plugins/ # Plugin de toast
536
- │ ├── theme/ # Tokens e temas (TS/JSON)
537
- │ ├── types/ # Tipos compartilhados
538
- │ └── utils/ # Utilitários de formatação e helpers
539
- ├── playground/ # App de documentação (não publicado)
540
- ├── nuxt.config.ts # Entrada da layer
541
- └── package.json
542
- ```
543
-
544
- ## Licença
545
-
546
- [MIT](./LICENSE) © 2026 Farmarcas
1
+ # ads-nuxt
2
+
3
+ **Alquimia Design System (ADS)** para Nuxt, construído sobre o [Nuxt UI](https://ui.nuxt.com) v4 e o Tailwind CSS v4.
4
+
5
+ O pacote é uma **Nuxt Layer**: ao estendê-lo, seu projeto recebe de uma vez os componentes `Ads*`, os tokens de design (cores, espaçamento, raios, sombras, tipografia), o tema do Nuxt UI customizado, os utilitários de formatação em pt-BR e a fonte Inter.
6
+
7
+ [![npm](https://img.shields.io/npm/v/ads-nuxt.svg)](https://www.npmjs.com/package/ads-nuxt)
8
+ [![license](https://img.shields.io/npm/l/ads-nuxt.svg)](./LICENSE)
9
+
10
+ ---
11
+
12
+ ## Sumário
13
+
14
+ - [Recursos](#recursos)
15
+ - [Requisitos](#requisitos)
16
+ - [Instalação](#instalação)
17
+ - [Configuração](#configuração)
18
+ - [Uso rápido](#uso-rápido)
19
+ - [Componentes](#componentes)
20
+ - [Exemplos](#exemplos)
21
+ - [Tokens de design](#tokens-de-design)
22
+ - [Tema do Nuxt UI](#tema-do-nuxt-ui)
23
+ - [Composables](#composables)
24
+ - [Utilitários](#utilitários)
25
+ - [Localização (pt-BR)](#localização-pt-br)
26
+ - [Desenvolvimento](#desenvolvimento)
27
+ - [Estrutura do projeto](#estrutura-do-projeto)
28
+ - [Licença](#licença)
29
+
30
+ ---
31
+
32
+ ## Recursos
33
+
34
+ - **Mais de 50 componentes** prontos para produção, com prefixo `Ads` (auto-importados pelo Nuxt).
35
+ - **Tokens em três camadas** (primitivos → semânticos → de componente), expostos como variáveis CSS `--ads-*` e como cores do Tailwind (`ads-*`).
36
+ - **Tema do Nuxt UI** pré-configurado: botão, input, calendário, select, toast e tooltip já seguem o visual ADS.
37
+ - **Fonte Inter** configurada via `@nuxt/fonts`.
38
+ - **Ícones Lucide** via `@nuxt/icon` (use `i-lucide-*`).
39
+ - **Utilitários pt-BR**: moeda (BRL), porcentagem, datas, notabilidade e filtros.
40
+ - **Playground** com documentação viva de todos os componentes e tokens.
41
+ - Estados “congeláveis” (`state`) nos componentes, pensados para documentação e testes visuais.
42
+
43
+ ## Requisitos
44
+
45
+ | Dependência | Versão |
46
+ | ----------- | --------- |
47
+ | Node.js | 20+ (recomendado 22) |
48
+ | Nuxt | `^4.0.0` |
49
+ | Vue | `^3.5.18` |
50
+
51
+ `nuxt` e `vue` são *peer dependencies*. As demais (`@nuxt/ui`, `@nuxt/fonts`, `@nuxt/icon`, `@vueuse/nuxt`, `tailwindcss`, ícones Lucide) já vêm como dependências do pacote.
52
+
53
+ ## Instalação
54
+
55
+ ```bash
56
+ # pnpm
57
+ pnpm add ads-nuxt
58
+
59
+ # npm
60
+ npm install ads-nuxt
61
+
62
+ # yarn
63
+ yarn add ads-nuxt
64
+ ```
65
+
66
+ ### Skill para o agente de IA (opcional)
67
+
68
+ O repositório traz a skill `ads-nuxt`, que ensina o agente do seu projeto (Cursor, Claude Code e outros) a usar o ADS: componentes, tokens, utilitários e armadilhas conhecidas.
69
+
70
+ ```bash
71
+ npx skills add jbfarmarcas/alquimia-design-system --skill ads-nuxt # instalar
72
+ npx skills update ads-nuxt # atualizar
73
+ npx skills remove ads-nuxt # remover
74
+ ```
75
+
76
+ Rode na raiz do projeto que usa o `ads-nuxt`. A skill entra em `.agents/skills/ads-nuxt` e o projeto ganha um `skills-lock.json`. Faça commit dos dois e rode `update` depois de atualizar o pacote.
77
+
78
+ ## Configuração
79
+
80
+ Estenda a layer no `nuxt.config.ts` do seu projeto:
81
+
82
+ ```ts
83
+ // nuxt.config.ts
84
+ export default defineNuxtConfig({
85
+ extends: ["ads-nuxt"],
86
+ });
87
+ ```
88
+
89
+ Isso já registra automaticamente:
90
+
91
+ - os módulos `@nuxt/ui`, `@nuxt/fonts`, `@nuxt/icon` e `@vueuse/nuxt`;
92
+ - o CSS global (Tailwind, Nuxt UI, cores e tokens de componente);
93
+ - a fonte **Inter** (pesos 300, 400, 500, 700 e 800);
94
+ - a coleção de ícones **lucide**;
95
+ - o `app.config.ts` com o tema ADS para o Nuxt UI;
96
+ - o plugin de toast e o locale pt-BR.
97
+
98
+ > **Modo de cor:** a layer define `ui.colorMode: false` — o ADS é um sistema de tema claro. Se precisar sobrescrever, redefina no `nuxt.config.ts` do seu projeto.
99
+
100
+ ### Envolva o app com `UApp`
101
+
102
+ O Nuxt UI exige o componente `UApp` para toasts, tooltips e overlays funcionarem:
103
+
104
+ ```vue
105
+ <!-- app/app.vue -->
106
+ <template>
107
+ <UApp :locale="uiLocale" :tooltip="{ delayDuration: 400 }" :toaster="adsToaster">
108
+ <NuxtPage />
109
+ </UApp>
110
+ </template>
111
+
112
+ <script setup lang="ts">
113
+ import { uiLocale } from "ads-nuxt/app/locale/pt-br";
114
+ import { adsToaster } from "ads-nuxt/app/theme/ads-theme";
115
+ </script>
116
+ ```
117
+
118
+ `adsToaster` posiciona os toasts no canto superior direito, sem barra de progresso, no padrão ADS.
119
+
120
+ ## Uso rápido
121
+
122
+ Os componentes são auto-importados, sem `import` manual:
123
+
124
+ ```vue
125
+ <template>
126
+ <AdsCard title="Cadastro">
127
+ <div class="flex flex-col gap-4">
128
+ <AdsInput v-model="nome" label="Nome" placeholder="Digite seu nome" />
129
+ <AdsButton type="filled" label="Salvar" leading icon="i-lucide-save" />
130
+ </div>
131
+ </AdsCard>
132
+ </template>
133
+
134
+ <script setup lang="ts">
135
+ const nome = ref("");
136
+ </script>
137
+ ```
138
+
139
+ ## Componentes
140
+
141
+ ### Ações
142
+
143
+ | Componente | Descrição |
144
+ | ---------------- | --------- |
145
+ | `AdsButton` | Botão (`filled`, `outline`, `unfilled`, `secondary`, `ia`) em 2 tamanhos e 8 cores. Suporta ícones, `loading` e `to` (vira link). |
146
+ | `AdsButtonGroup` | Agrupa botões. |
147
+ | `AdsButtonMenu` | Botão com menu de ações. |
148
+
149
+ ### Formulários
150
+
151
+ | Componente | Descrição |
152
+ | ----------------- | --------- |
153
+ | `AdsInput` | Campo de texto/número com label, hint, erro, info, ícone e sufixo. |
154
+ | `AdsNumberInput` | Campo numérico dedicado. |
155
+ | `AdsTextarea` | Área de texto. |
156
+ | `AdsSearchInput` | Campo de busca. |
157
+ | `AdsCheckbox` | Checkbox com estado indeterminado. |
158
+ | `AdsRadio` | Botão de rádio. |
159
+ | `AdsSwitch` | Alternador (toggle). |
160
+ | `AdsDatePicker` | Seletor de data ou intervalo, com `min`, `max` e `maximumDays`. |
161
+ | `AdsMonthPicker` | Seletor de mês. |
162
+ | `AdsFilterSelect` | Filtro com seleção (checkbox, radio ou mês). |
163
+ | `AdsFilterDropdown` / `AdsFilterOption` | Dropdown de filtros e suas opções. |
164
+
165
+ ### Navegação
166
+
167
+ | Componente | Descrição |
168
+ | ----------------- | --------- |
169
+ | `AdsNavbarDesk` / `AdsNavbarApp` | Barra de navegação desktop e mobile. |
170
+ | `AdsSideMenu` | Menu lateral. |
171
+ | `AdsMenuBar` | Barra de menu. |
172
+ | `AdsTabs` | Abas em formato de link. |
173
+ | `AdsSegmentedTabs`| Abas segmentadas. |
174
+ | `AdsPagination` | Paginação com reticências automáticas (`v-model:page`). |
175
+ | `AdsDropdownMenu` / `AdsListDropdown` | Menus suspensos. |
176
+ | `AdsFooter` | Rodapé. |
177
+
178
+ ### Exibição de dados
179
+
180
+ | Componente | Descrição |
181
+ | ----------------- | --------- |
182
+ | `AdsTable` | Tabela baseada no `UTable`, com densidade, zebra, bordas, degradê por nível, `sticky`, loading e estado vazio. |
183
+ | `AdsTableToolbar` | Barra de ferramentas da tabela. |
184
+ | `AdsCard` | Cartão genérico. |
185
+ | `AdsMetricCard` | Cartão de métrica/indicador. |
186
+ | `AdsFeatureCard` | Cartão de funcionalidade. |
187
+ | `AdsFileCard` | Cartão de arquivo. |
188
+ | `AdsEmptyState` | Estado vazio. |
189
+
190
+ ### Indicadores e status
191
+
192
+ | Componente | Descrição |
193
+ | -------------------- | --------- |
194
+ | `AdsBadge` | Contador ou ponto (`mini`) em 7 cores. |
195
+ | `AdsPill` | Pílula de status (`default`, `success`, `attention`, `warning`, `new`, `blocked`, `innovation`, `neutral`) em tom `primary` ou `secondary`. |
196
+ | `AdsMiniPill` | Versão compacta da pílula. |
197
+ | `AdsNotabilityPill` | Pílula de notabilidade. |
198
+ | `AdsFarmarcasPill` | Pílula de marca Farmarcas. |
199
+ | `AdsProductTag` | Tag de produto. |
200
+
201
+ ### Feedback e overlays
202
+
203
+ | Componente | Descrição |
204
+ | ----------------- | --------- |
205
+ | `AdsModal` | Modal (`dialog` ou `sheet`) com 5 tamanhos, ações padrão e slots. |
206
+ | `AdsToast` | Aviso em faixa (`banner`) ou reporte escuro (`status`). |
207
+ | `AdsBroadcast` | Comunicado em destaque. |
208
+ | `AdsTooltip` | Tooltip. |
209
+ | `AdsSmalltip` / `AdsSteptip` / `AdsCharttip` | Variações de tooltip (compacta, em passos e para gráficos). |
210
+ | `AdsLoading` | Indicador de carregamento. |
211
+ | `ProgressBarLoading` | Barra de progresso. |
212
+ | `OverlayLoading` | Overlay de carregamento/sucesso/erro (usado por `useOverlayLoading`). |
213
+
214
+ ## Exemplos
215
+
216
+ ### Botões
217
+
218
+ ```vue
219
+ <AdsButton type="filled" label="Salvar" />
220
+ <AdsButton type="outline" color="success" label="Aprovar" />
221
+ <AdsButton type="unfilled" size="sm" label="Cancelar" />
222
+ <AdsButton type="ia" label="Gerar com IA" leading icon="i-lucide-sparkles" />
223
+ <AdsButton type="filled" label="Enviando" loading />
224
+ <AdsButton type="filled" label="Ir para o painel" to="/painel" />
225
+ ```
226
+
227
+ | Prop | Valores |
228
+ | ------------ | ------- |
229
+ | `type` | `filled` \| `outline` \| `unfilled` \| `secondary` \| `ia` |
230
+ | `color` | `primary` \| `success` \| `attention` \| `warning` \| `new` \| `innovation` \| `blocked` \| `neutral` |
231
+ | `size` | `md` \| `sm` |
232
+ | `nativeType` | `button` \| `submit` \| `reset` (a prop `type` é o visual do ADS) |
233
+
234
+ ### Campos de formulário
235
+
236
+ ```vue
237
+ <AdsInput
238
+ v-model="preco"
239
+ label="Preço"
240
+ hint="Valor unitário"
241
+ suffix="R$"
242
+ type="number"
243
+ :error="erro"
244
+ />
245
+ ```
246
+
247
+ Estados disponíveis via `state` (útil para documentação): `default`, `active`, `focus`, `error`, `disabled` e `ai`.
248
+
249
+ ### Modal
250
+
251
+ ```vue
252
+ <template>
253
+ <AdsButton label="Excluir" color="warning" @click="aberto = true" />
254
+
255
+ <AdsModal
256
+ v-model:open="aberto"
257
+ title="Excluir item"
258
+ description="Essa ação não pode ser desfeita."
259
+ cancel-label="Cancelar"
260
+ confirm-label="Excluir"
261
+ @confirm="excluir"
262
+ @cancel="aberto = false"
263
+ />
264
+ </template>
265
+
266
+ <script setup lang="ts">
267
+ const aberto = ref(false);
268
+ const excluir = () => {
269
+ /* ... */
270
+ aberto.value = false;
271
+ };
272
+ </script>
273
+ ```
274
+
275
+ Eventos: `confirm`, `cancel` e `dismiss` (com o motivo `"esc"` ou `"outside"`). Slots: `default`, `title` e `footer`.
276
+
277
+ ### Toast
278
+
279
+ Como componente em linha:
280
+
281
+ ```vue
282
+ <AdsToast status="success" title="Tudo certo" message="Alterações salvas." />
283
+ <AdsToast status="error" message="Falha ao salvar." action-label="Tentar novamente" />
284
+ <AdsToast appearance="status" status="neutral" title="Relatório" subtitle="Explicação opcional" />
285
+ ```
286
+
287
+ Como toast flutuante, usando o `useToast` do Nuxt UI (as cores de status e os ícones do ADS são aplicados automaticamente pelo plugin da layer):
288
+
289
+ ```ts
290
+ const toast = useToast();
291
+
292
+ toast.add({
293
+ title: "Salvo",
294
+ description: "Suas alterações foram salvas.",
295
+ color: "success",
296
+ });
297
+ ```
298
+
299
+ ### Pílulas e badges
300
+
301
+ ```vue
302
+ <AdsPill status="success" label="Ativo" />
303
+ <AdsPill status="warning" tone="secondary" label="Atrasado" icon="i-lucide-alert-triangle" />
304
+ <AdsBadge color="primary" :value="5" />
305
+ <AdsBadge color="warning" mini />
306
+ ```
307
+
308
+ ### Paginação e abas
309
+
310
+ ```vue
311
+ <AdsPagination v-model:page="pagina" :total-pages="20" />
312
+
313
+ <AdsTabs v-model="aba" :items="itens" />
314
+ ```
315
+
316
+ ### Tabela
317
+
318
+ ```vue
319
+ <AdsTable
320
+ :data="linhas"
321
+ :columns="colunas"
322
+ density="md"
323
+ striped
324
+ :loading="carregando"
325
+ empty-label="Nenhum resultado encontrado"
326
+ />
327
+ ```
328
+
329
+ Para montar colunas, a layer exporta helpers em `app/utils/ads-table.ts`, como `adsTableColumn`, `adsTablePinned`, `adsTableGroup`, `adsTableVariationClass` e `adsTableTreeIndent`.
330
+
331
+ ### Seletor de datas
332
+
333
+ ```vue
334
+ <!-- Data única -->
335
+ <AdsDatePicker v-model="data" min="2026-01-01" />
336
+
337
+ <!-- Intervalo (máximo de 31 dias) -->
338
+ <AdsDatePicker range v-model:start="inicio" v-model:end="fim" :maximum-days="31" />
339
+ ```
340
+
341
+ As datas trafegam como string `YYYY-MM-DD`.
342
+
343
+ ## Tokens de design
344
+
345
+ Os tokens vêm do Figma do ADS e estão organizados em três camadas:
346
+
347
+ 1. **Primitivos** — valores brutos (escalas de cor, espaçamentos).
348
+ 2. **Semânticos** — intenção de uso (`--ads-surface-*`, `--ads-text-*`, `--ads-border-*`, `--ads-status-*`).
349
+ 3. **De componente** — ajustes finos por componente (`--ads-button-*`, `--ads-modal-*`, `--ads-tooltip-*`…).
350
+
351
+ ### Variáveis CSS
352
+
353
+ ```css
354
+ .meu-card {
355
+ background: var(--ads-surface-main);
356
+ color: var(--ads-text-secondary);
357
+ border-radius: var(--ads-button-radius);
358
+ box-shadow: var(--ads-shadow-level-3);
359
+ }
360
+ ```
361
+
362
+ ### Classes Tailwind
363
+
364
+ As variáveis semânticas também estão mapeadas como cores do Tailwind (`--color-ads-*`):
365
+
366
+ ```html
367
+ <div class="bg-ads-surface-main border-ads-border-width-thin"></div>
368
+ ```
369
+
370
+ ### Escalas de cor
371
+
372
+ | Escala | Uso |
373
+ | ------------------ | --- |
374
+ | `primary` / `secondary` | Azul do Radar Pricing, de 50 a 950 (base `#006ff7`). |
375
+ | `success` | Verde de sucesso (base `#15c57e`). |
376
+ | Neutros | `neutralLight`, `neutralMid` e `neutralDark`. |
377
+ | Status | `success`, `attention`, `warning`, `new`, `innovation`, `blocked`. |
378
+
379
+ ### Espaçamento
380
+
381
+ | Token | px | Token | px | Token | px |
382
+ | ------ | --- | ------ | --- | ------ | --- |
383
+ | quark | 4 | sm | 32 | xxxl | 120 |
384
+ | nano | 8 | rg | 40 | huge | 160 |
385
+ | xxxs | 12 | md | 48 | giant | 200 |
386
+ | xxs | 16 | lg | 56 | | |
387
+ | xs | 24 | xl / xxl | 64 / 80 | | |
388
+
389
+ Os mesmos valores estão disponíveis em TypeScript, em `app/theme/ads-tokens.ts` (`adsSpacing`, `adsRadarPricing`, `adsRadarBase`, `adsNeutralLight`, `adsNeutralMid`, `adsNeutralDark`, `adsSuccess`…).
390
+
391
+ ### Personalizando tokens de componente
392
+
393
+ Os tokens de componente são gerados a partir de `app/theme/component-tokens.json` para `component-tokens.css`. Para ajustar no seu projeto sem editar o pacote, sobrescreva a variável CSS depois do CSS da layer:
394
+
395
+ ```css
396
+ :root {
397
+ --ads-button-radius: 4px;
398
+ --ads-button-primary: #0050b3;
399
+ }
400
+ ```
401
+
402
+ ## Tema do Nuxt UI
403
+
404
+ O `app.config.ts` da layer customiza os seguintes componentes do Nuxt UI para seguir o ADS:
405
+
406
+ `button`, `input`, `inputDate`, `calendar`, `select`, `selectMenu`, `toast`, `toaster` e `tooltip`.
407
+
408
+ Por ser uma layer, você pode estender ou sobrescrever no `app.config.ts` do seu projeto:
409
+
410
+ ```ts
411
+ // app/app.config.ts
412
+ export default defineAppConfig({
413
+ ui: {
414
+ button: {
415
+ slots: {
416
+ base: "rounded-md",
417
+ },
418
+ },
419
+ },
420
+ });
421
+ ```
422
+
423
+ ## Composables
424
+
425
+ ### `useOverlayLoading`
426
+
427
+ Exibe um overlay de tela cheia para carregamento, sucesso, erro, busca ou informação, com barra de progresso opcional.
428
+
429
+ ```ts
430
+ const overlay = useOverlayLoading();
431
+
432
+ overlay.show({
433
+ variant: "loading",
434
+ title: "Processando",
435
+ description: "Isso pode levar alguns segundos.",
436
+ showProgress: true,
437
+ progress: 10,
438
+ });
439
+
440
+ overlay.update({ progress: 60 });
441
+
442
+ overlay.update({ variant: "success", title: "Concluído!" });
443
+
444
+ overlay.close();
445
+ ```
446
+
447
+ | Método | Descrição |
448
+ | ----------------- | --------- |
449
+ | `show(options)` | Abre o overlay (fecha o anterior, se houver) e retorna o id. |
450
+ | `update(options)` | Mescla novas props no overlay aberto. |
451
+ | `close()` | Fecha o overlay. |
452
+ | `isOpen()` | Indica se há overlay aberto. |
453
+ | `getCurrentId()` | Retorna o id do overlay atual. |
454
+
455
+ Opções (`OverlayLoadingOptions`):
456
+
457
+ | Opção | Tipo |
458
+ | ----------------- | ---- |
459
+ | `variant` | `"loading"` \| `"success"` \| `"error"` \| `"search"` \| `"info"` |
460
+ | `title`, `description`, `hint` | `string` |
461
+ | `showProgress`, `progress` | `boolean`, `number` |
462
+ | `iconSrc` | `string` |
463
+ | `actionLabel`, `onAction` | rótulo e callback de ação |
464
+ | `onUserClose` | callback ao usuário fechar |
465
+ | `closableVariants`| `("success" \| "error")[]` — variantes que o usuário pode fechar |
466
+
467
+ ## Utilitários
468
+
469
+ Todos ficam em `app/utils` e são auto-importados pelo Nuxt.
470
+
471
+ | Arquivo | Funções principais |
472
+ | --------------------- | ------------------ |
473
+ | `money.ts` | `numberToBRL`, `numberToCompactBRL`, `parseStringMoneyToFloat`, `formatPriceInput`, `parsePriceInput` |
474
+ | `percentage.ts` | `formatPercentage`, `formatPercentageWithDecimals`, `formatPercentagePtBr` |
475
+ | `parser.ts` | `parseToPercentage`, `parsePercentageToFloat`, `getTodayDateString`, `formatDateOnlyToPtBr`, `formatDateToPtBr`, `daysBetweenDateOnly`, `daysFromTodayToDateOnly`, `normalizePercentage` |
476
+ | `calendar-date.ts` | Conversão entre `string` e `CalendarDate` (`@internationalized/date`) e helpers de intervalo |
477
+ | `notability.ts` | `formatNotability` |
478
+ | `category-role.ts` | `CATEGORY_ROLES`, `formatCategoryRole`, `parseCategoryRole` |
479
+ | `ads-filter-select.ts`| Helpers para `AdsFilterSelect` (agrupamento, seleção, rótulos, meses) |
480
+ | `ads-table.ts` | Helpers e tipos para `AdsTable` |
481
+
482
+ ```ts
483
+ numberToBRL(1234.5); // "R$ 1.234,50"
484
+ numberToBRL(-10); // "R$ -10,00"
485
+ numberToBRL(null); // "-"
486
+ numberToCompactBRL(2_500_000); // valor compacto em milhões
487
+ ```
488
+
489
+ ## Localização (pt-BR)
490
+
491
+ A layer inclui `app/locale/pt-br.ts`, que exporta o locale do Nuxt UI para português do Brasil (calendário, meses e rótulos):
492
+
493
+ ```ts
494
+ import { uiLocale, UI_LOCALE_CODE } from "ads-nuxt/app/locale/pt-br";
495
+ // UI_LOCALE_CODE === "pt-BR"
496
+ ```
497
+
498
+ Passe-o ao `UApp` como mostrado em [Configuração](#configuração).
499
+
500
+ ## Desenvolvimento
501
+
502
+ Este repositório usa **pnpm** e contém um **playground** Nuxt com a documentação interativa dos componentes e dos tokens.
503
+
504
+ ```bash
505
+ git clone https://github.com/jbfarmarcas/alquimia-design-system.git
506
+ cd alquimia-design-system
507
+ pnpm install
508
+
509
+ pnpm dev # playground em http://localhost:3010
510
+ pnpm build # build do playground
511
+ pnpm preview # preview do build
512
+
513
+ pnpm skill:reference # regenera skills/ads-nuxt/reference.md a partir de app/
514
+ pnpm skill:check # falha se o reference.md estiver desatualizado
515
+ ```
516
+
517
+ Páginas do playground:
518
+
519
+ | Rota | Conteúdo |
520
+ | ------------------------- | -------- |
521
+ | `/design-system/instalacao` | Manual de instalação da biblioteca |
522
+ | `/design-system` | Catálogo de componentes com demos e código |
523
+ | `/design-system/tabelas` | Variações de tabela |
524
+ | `/design-system/tokens` | Editor visual dos tokens de componente |
525
+
526
+ ### Docker
527
+
528
+ ```bash
529
+ docker compose up
530
+ ```
531
+
532
+ ### Publicação
533
+
534
+ O pacote publica apenas `app/` e `nuxt.config.ts` (campo `files`), com acesso público:
535
+
536
+ A publicação é feita pelo GitHub Actions (`.github/workflows/publish.yml`), com Trusted Publishing (sem token). Para lançar uma versão:
537
+
538
+ ```bash
539
+ npm version patch --ignore-scripts # ou minor / major: cria o commit e a tag vX.Y.Z
540
+ git push --follow-tags
541
+ ```
542
+
543
+ ## Estrutura do projeto
544
+
545
+ ```
546
+ .
547
+ ├── app/ # Conteúdo publicado no npm (a layer)
548
+ │ ├── app.config.ts # Tema do Nuxt UI
549
+ │ ├── assets/ # CSS, SVGs de marca e animações
550
+ │ ├── components/ # Componentes Ads*
551
+ │ ├── composables/ # useOverlayLoading
552
+ │ ├── constants/ # Constantes (swatches de cor)
553
+ │ ├── locale/ # Locale pt-BR
554
+ │ ├── plugins/ # Plugin de toast
555
+ │ ├── theme/ # Tokens e temas (TS/JSON)
556
+ │ ├── types/ # Tipos compartilhados
557
+ │ └── utils/ # Utilitários de formatação e helpers
558
+ ├── playground/ # App de documentação (não publicado)
559
+ ├── skills/ads-nuxt/ # Skill para agentes de IA (SKILL.md + reference.md gerado)
560
+ ├── scripts/ # generate-skill-reference.mjs (pnpm skill:reference)
561
+ ├── nuxt.config.ts # Entrada da layer
562
+ └── package.json
563
+ ```
564
+
565
+ ## Licença
566
+
567
+ [MIT](./LICENSE) © 2026 Farmarcas