@wellingtonhlc/shared-ui 0.26.12 → 0.26.14

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,405 +1,405 @@
1
- # Wellington Shared UI
2
-
3
- Conjunto de componentes visuais padronizados, criado por Wellington Henrique para aplicacoes React.
4
-
5
- O objetivo deste pacote e concentrar componentes base, tokens, presets e helpers de UI reutilizaveis, sem regras de negocio de dominio.
6
-
7
- ## Pacote
8
-
9
- ```bash
10
- npm install @wellingtonhlc/shared-ui
11
- ```
12
-
13
- Uso basico:
14
-
15
- ```tsx
16
- import { Button, Card, Page, Table } from '@wellingtonhlc/shared-ui';
17
-
18
- export function ExamplePage() {
19
- return (
20
- <Page.Root>
21
- <Card.Root>
22
- <Card.Header>
23
- <Card.Title>Registros</Card.Title>
24
- <Card.Description>Consulta de dados</Card.Description>
25
- </Card.Header>
26
- <Card.Body>
27
- <Button>Salvar</Button>
28
- </Card.Body>
29
- </Card.Root>
30
- </Page.Root>
31
- );
32
- }
33
- ```
34
-
35
- ## Principios
36
-
37
- Este pacote foi desenhado para oferecer infraestrutura visual generica:
38
-
39
- - componentes base de interface;
40
- - campos de formulario reutilizaveis;
41
- - primitivas de acao;
42
- - tokens, estilos e presets;
43
- - helpers sem dependencia de dominio;
44
- - composicao por slots quando o componente possui partes internas.
45
-
46
- ## Validacao de Page Actions
47
-
48
- O pacote publica o CLI `shared-ui-check-page-actions` para validar o contrato de actions em uma aplicacao.
49
-
50
- Contrato esperado:
51
-
52
- - `AppLayout.actions` e somente o slot de layout.
53
- - `Page.Actions` e o root visual da barra.
54
- - Props como `helpContent`, `helpLabel`, `position`, `align` e `size` pertencem ao `Page.Actions`.
55
- - Nao usar `ActionBar.*`, `Page.Root actions=...` dentro de `AppLayout`, Fragment, `div` ou `Page.ActionButton` solto como root de `AppLayout.actions`.
56
-
57
- Uso recomendado:
58
-
59
- ```json
60
- {
61
- "scripts": {
62
- "check:page-actions": "shared-ui-check-page-actions"
63
- }
64
- }
65
- ```
66
-
67
- Tambem e possivel apontar um diretorio explicitamente:
68
-
69
- ```bash
70
- shared-ui-check-page-actions ./src
71
- ```
72
-
73
- ## Page Actions
74
-
75
- `Page.Actions` e a raiz visual das acoes de tela. O pacote suporta `left`, `top`, `right` e
76
- `bottom`, com `left` como padrao desktop e `bottom` como fallback mobile quando permitido.
77
-
78
- Persistencia de preferencia continua sendo responsabilidade do consumidor. Use
79
- `Page.ActionsProvider` para fornecer a preferencia global sem acoplar o pacote a
80
- `localStorage`:
81
-
82
- ```tsx
83
- import { useCallback, useMemo, useState } from 'react';
84
- import { Page, type PageActionsPosition, type PageActionsPreferences } from '@wellingtonhlc/shared-ui';
85
-
86
- const storageKey = '@my-app/preference/page-actions-position';
87
- const positions: PageActionsPosition[] = ['left', 'top', 'right', 'bottom'];
88
-
89
- function readStoredPosition() {
90
- const stored = window.localStorage.getItem(storageKey);
91
- return positions.includes(stored as PageActionsPosition) ? (stored as PageActionsPosition) : undefined;
92
- }
93
-
94
- export function AppLayout({ children }: { children: React.ReactNode }) {
95
- const [position, setPosition] = useState<PageActionsPosition | undefined>(readStoredPosition);
96
-
97
- const handlePositionChange = useCallback(function handlePositionChange(nextPosition: PageActionsPosition) {
98
- setPosition(nextPosition);
99
- window.localStorage.setItem(storageKey, nextPosition);
100
- }, []);
101
-
102
- const preferences = useMemo<PageActionsPreferences>(
103
- () => ({
104
- mobilePosition: 'bottom',
105
- movable: true,
106
- onPositionChange: handlePositionChange,
107
- position,
108
- }),
109
- [handlePositionChange, position],
110
- );
111
-
112
- return (
113
- <Page.ActionsProvider preferences={preferences}>
114
- <Page.ActionsSlot position="left" />
115
- <main>{children}</main>
116
- <Page.ActionsSlot position="right" />
117
- <Page.ActionsSlot position="top" />
118
- <Page.ActionsSlot position="bottom" />
119
- </Page.ActionsProvider>
120
- );
121
- }
122
- ```
123
-
124
- Acoes de uma tela devem continuar usando `Page.Actions`; o provider apenas controla onde elas serao exibidas:
125
-
126
- ```tsx
127
- import { Page } from '@wellingtonhlc/shared-ui/components/Page';
128
- import { Save } from 'lucide-react';
129
-
130
- export function EditPageActions() {
131
- return (
132
- <Page.Actions helpLabel="Ajuda" helpContent="Revise os dados antes de salvar.">
133
- <Page.ActionButton icon={<Save />} label="Salvar" />
134
- </Page.Actions>
135
- );
136
- }
137
- ```
138
-
139
- Telas podem limitar o contrato localmente:
140
-
141
- ```tsx
142
- <Page.Actions allowedPositions={['top', 'bottom']} movable={false}>
143
- <Page.ActionButton label="Salvar" />
144
- </Page.Actions>
145
- ```
146
-
147
- Acoes auxiliares podem ser passadas por `helpContent`, `metaActions` ou por componentes
148
- marcados como meta. Em barras verticais, o grupo meta e renderizado em modo compacto
149
- e alinhado na borda externa da barra para preservar leitura visual; as labels continuam
150
- obrigatorias no contrato e sao usadas para acessibilidade e tooltip.
151
-
152
- ## Exportacoes
153
-
154
- Entrada principal:
155
-
156
- ```tsx
157
- import { Button, Card, Modal, Table, cn } from '@wellingtonhlc/shared-ui';
158
- ```
159
-
160
- Subpaths recomendados para telas grandes ou rotas lazy-loaded:
161
-
162
- ```tsx
163
- import { Button } from '@wellingtonhlc/shared-ui/components/Button';
164
- import { Table } from '@wellingtonhlc/shared-ui/components/Table';
165
- import { cn } from '@wellingtonhlc/shared-ui/utils/cn';
166
- ```
167
-
168
- Estilos:
169
-
170
- ```tsx
171
- import '@wellingtonhlc/shared-ui/styles.css';
172
- ```
173
-
174
- Preset Tailwind:
175
-
176
- ```ts
177
- import sharedUiPreset from '@wellingtonhlc/shared-ui/tailwind-preset';
178
- ```
179
-
180
- ## Componentes
181
-
182
- Componentes disponiveis na API publica:
183
-
184
- | Grupo | Componentes |
185
- |-------|-------------|
186
- | Layout | `AppShell`, `Page`, `Sidebar`, `Card`, `StatCard` |
187
- | Acoes | `Button`, `ActionPrimitives`, `AppShellActions`, `ConfirmationDialog` |
188
- | Feedback | `Badge`, `EmptyState`, `PageMessage`, `Tooltip`, `CopyableField` |
189
- | Formularios | `FieldControl`, `FieldGroup`, `TextField`, `TextareaField`, `SelectField`, `SelectionField`, `DateField`, `DecimalField`, `MultiSelectField`, `PasswordInput`, `Switch`, `RadioGroup` |
190
- | Consulta | `Filter`, `Workspace` |
191
- | Dados | `Table`, `Pagination`, `TabsUnderlined` |
192
- | Controle de renderizacao | `RenderIf`, `RenderCase` |
193
- | Tema | `ThemePreferencesSelector` |
194
-
195
- ## DateField
196
-
197
- `DateField` centraliza entrada de data, data e hora, ou apenas hora. Use `mode`
198
- para declarar o formato esperado pelo campo:
199
-
200
- ```tsx
201
- <DateField label="Data" value="2026-06-16" onChange={setDate} mode="date" />
202
- <DateField label="Data e hora" value="2026-06-16T14:30" onChange={setDateTime} mode="dateTime" />
203
- <DateField label="Hora" value="14:30" onChange={setTime} mode="time" />
204
- ```
205
-
206
- `enableTime` permanece suportado como alias legado para `mode="dateTime"`.
207
-
208
- ## FieldGroup
209
-
210
- `FieldGroup` renderiza um grupo visual de campos com legenda. A borda vem ativa por
211
- padrao; use `bordered={false}` quando o consumidor precisar manter a semantica de
212
- grupo sem adicionar contorno visual.
213
-
214
- ```tsx
215
- import { FieldGroup, TextField } from '@wellingtonhlc/shared-ui';
216
-
217
- <FieldGroup title="Endereco" bordered={false}>
218
- <TextField label="CEP" />
219
- <TextField label="Cidade" />
220
- </FieldGroup>;
221
- ```
222
-
223
- ## RadioGroup
224
-
225
- `RadioGroup` segue a mesma escala de altura dos campos base (`xs`, `sm`, `md`,
226
- `lg`) para alinhar visualmente com `TextField`, `SelectField` e demais controles
227
- na mesma linha de formulario.
228
-
229
- O padrao `boxed` renderiza um `fieldset` com legenda, fazendo a borda contornar
230
- o grupo a partir da label. Use `variant="plain"` quando precisar do grupo sem
231
- borda.
232
-
233
- ```tsx
234
- import { RadioGroup } from '@wellingtonhlc/shared-ui';
235
-
236
- <RadioGroup label="Tipo Pessoa" value={1} onChange={setType}>
237
- <RadioGroup.Item value={1} label="Fisica" />
238
- <RadioGroup.Item value={2} label="Juridica" />
239
- </RadioGroup>;
240
- ```
241
-
242
- ## AppShell.Topbar.Button
243
-
244
- Use `AppShell.Topbar.Button` para acoes de icone na barra superior, como notificacoes,
245
- configuracoes e atalhos globais. O componente reutiliza o mesmo contrato visual dos
246
- primitivos de acao, mas aplica o tamanho esperado para a topbar.
247
-
248
- ```tsx
249
- import { AppShell } from '@wellingtonhlc/shared-ui';
250
- import { Bell, Settings } from 'lucide-react';
251
-
252
- <AppShell.Actions>
253
- <AppShell.Topbar.Button icon={<Bell />} tooltip="Notificacoes" />
254
- <AppShell.Topbar.Button icon={<Settings />} tooltip="Configuracoes" />
255
- </AppShell.Actions>
256
- ```
257
-
258
- ## TabsUnderlined
259
-
260
- `TabsUnderlined` renderiza abas sublinhadas com conteudo controlado ou nao controlado.
261
- As abas ja possuem tamanho minimo padrao e padding horizontal para comportar labels
262
- medias, como `Configuracoes` e `Fornecedor`, sem ficarem apertadas.
263
-
264
- Quando houver labels longas, use `tabWidth` e `truncateLabels` para manter abas
265
- uniformes e aplicar ellipsis no texto que exceder o limite.
266
-
267
- ```tsx
268
- import { TabsUnderlined } from '@wellingtonhlc/shared-ui';
269
-
270
- <TabsUnderlined
271
- items={items}
272
- tabWidth="12rem"
273
- truncateLabels
274
- />;
275
- ```
276
-
277
- Quando a largura puder variar dentro de uma faixa, use `tabMinWidth` e `tabMaxWidth`.
278
- `truncateLabels` nao altera o comportamento sozinho; defina tambem `tabWidth` ou
279
- `tabMaxWidth` para que o navegador saiba quando abreviar o texto.
280
-
281
- ## ThemePreferencesSelector
282
-
283
- `ThemePreferencesSelector` centraliza a escolha de cor e aparencia (`system`, `light`, `dark`) usada pelos consumidores.
284
-
285
- Contrato minimo:
286
-
287
- ```tsx
288
- import { ThemePreferencesSelector, type ThemePreferencesValue } from '@wellingtonhlc/shared-ui';
289
-
290
- const value: ThemePreferencesValue = {
291
- color: 'indigo',
292
- appearance: 'system',
293
- };
294
-
295
- <ThemePreferencesSelector
296
- value={value}
297
- options={[
298
- { key: 'indigo', label: 'Indigo', primary: '#5b5cff' },
299
- { key: 'emerald', label: 'Emerald', primary: '#059669' },
300
- ]}
301
- onChange={setValue}
302
- />;
303
- ```
304
-
305
- Pontos de validacao:
306
-
307
- - O botao de aparencia selecionado deve ficar perceptivelmente destacado sem depender de hover.
308
- - Opcoes de cor bloqueadas usam `locked` e podem informar `requiredPlan`.
309
- - Use `showColorSelector={false}` ou `showAppearanceSelector={false}` quando o consumidor precisar exibir apenas uma parte do controle.
310
- - A story `AppearanceStates` mostra as tres aparencias ja selecionadas para validacao visual rapida.
311
-
312
- ## SelectionField
313
-
314
- `SelectionField` padroniza campos de selecao que exibem um registro, abrem uma busca externa e permitem limpar o valor selecionado. O componente nao gerencia modal nem estado interno do registro; o consumidor controla `value`, `onClick` e `onClear`.
315
-
316
- Contrato minimo:
317
-
318
- ```tsx
319
- import { SelectionField, type SelectionDisplayValue } from '@wellingtonhlc/shared-ui';
320
- import { UserCheck } from 'lucide-react';
321
-
322
- const value: SelectionDisplayValue = {
323
- title: 'Registro selecionado',
324
- subtitle: 'Descricao complementar',
325
- meta: 'COD-1024',
326
- };
327
-
328
- <SelectionField
329
- label="Registro"
330
- value={value}
331
- icon={<UserCheck />}
332
- clearable
333
- size="sm"
334
- selectTooltip="Selecionar registro"
335
- clearTooltip="Limpar registro"
336
- onClick={openSearch}
337
- onClear={clearSelection}
338
- />;
339
- ```
340
-
341
- Pontos de validacao:
342
-
343
- - `size` segue a mesma escala visual dos campos base (`xs`, `sm`, `md`, `lg`).
344
- - Use `triggerSlot` quando o consumidor precisar injetar um botao proprio para abrir a selecao.
345
- - `clearable` exibe a acao de limpar somente quando ha `value` e `onClear`.
346
- - `shortcutHint` pode exibir atalhos de teclado, como `F1`.
347
-
348
- ## Filter (contrato legado)
349
-
350
- `Filter.Root` organiza filtros compactos, ocupando apenas o espaço necessário. Quando houver muitos filtros, somente o corpo do painel rola e as ações continuam visíveis.
351
-
352
- ```tsx
353
- import { Button, Filter, TextField } from '@wellingtonhlc/shared-ui';
354
-
355
- export function CustomersFilters() {
356
- return (
357
- <Filter.Root description="Refine os critérios antes de consultar os resultados.">
358
- <TextField label="Buscar" size="sm" />
359
- <Filter.Footer>
360
- <Button type="submit" size="sm">
361
- Pesquisar
362
- </Button>
363
- </Filter.Footer>
364
- </Filter.Root>
365
- );
366
- }
367
- ```
368
-
369
- Padrões do painel:
370
-
371
- - Usa `h-fit` e `w-fit` por padrão, sem ocupar a altura inteira da tela.
372
- - Limita a altura com `maxHeightClassName`; o default é `max-h-[calc(100vh-12rem)]`.
373
- - Aplica rolagem apenas na área de filtros.
374
- - Use `Filter.Footer` para manter botões sempre visíveis no rodapé do painel.
375
- - Em interfaces densas, campos dentro do painel devem preferir `size="sm"` e nao devem usar formato `rounded-full`.
376
-
377
- ## Filter atual
378
-
379
- `Filter.Root` usa descrição vazia por padrão e rola apenas o viewport dos campos. Informe `onSubmit` e `onClear` para obter as ações automáticas `Pesquisar` e `Redefinir`; o submit cria um único `<form>` interno. `submitLabel`, `clearLabel`, `isSubmitting`, `actionsDisabled` e `fieldsClassName` são opcionais. Um `Filter.Footer` explícito substitui as ações automáticas e continua indicado para formulários externos.
380
-
381
- `Filter.Visibility` oferece estado controlado ou não controlado. `Filter.Trigger` aceita o botão padrão ou clona um `Page.ActionButton` via `triggerSlot`, preservando seu estilo e handler. Dentro de `Workspace.Root`, o estado fechado recolhe a coluna de filtros.
382
-
383
- `Workspace.Root appearance="joined"` compõe filtros e resultados sem gap em uma moldura única. O padrão continua `separated`; `Table.Root` permanece responsável por viewport, moldura e paginação.
384
-
385
- ```tsx
386
- <Filter.Root onSubmit={handleSearch} onClear={handleClear} isSubmitting={isLoading}>
387
- <TextField label="Buscar" size="sm" />
388
- </Filter.Root>
389
- ```
390
-
391
- ## Contrato publico 0.1.0
392
-
393
- A API pública pré-v1 foi limpa para evitar compatibilidade artificial em produção.
394
-
395
- Exports removidos:
396
-
397
- - `ActionBar`: use `Page.Actions`, `Page.ActionButton` e `Page.ActionsSeparator`.
398
- - `Dialog`: use `Modal`.
399
- - `ChoiceGroup`: use `RadioGroup`.
400
- - `ConditionalCase`: use `RenderCase`.
401
- - `ConditionalRender`: use `RenderIf`.
402
- - `ToggleSwitch`: use `Switch`.
403
- - `SearchFilter`: use `Filter`.
404
- - `SearchWorkspace`: componha layout no consumidor ou com componentes genéricos.
405
- - `TabsUnderline` e `UnderlinedTabs`: use `TabsUnderlined`.
1
+ # Wellington Shared UI
2
+
3
+ Conjunto de componentes visuais padronizados, criado por Wellington Henrique para aplicacoes React.
4
+
5
+ O objetivo deste pacote e concentrar componentes base, tokens, presets e helpers de UI reutilizaveis, sem regras de negocio de dominio.
6
+
7
+ ## Pacote
8
+
9
+ ```bash
10
+ npm install @wellingtonhlc/shared-ui
11
+ ```
12
+
13
+ Uso basico:
14
+
15
+ ```tsx
16
+ import { Button, Card, Page, Table } from '@wellingtonhlc/shared-ui';
17
+
18
+ export function ExamplePage() {
19
+ return (
20
+ <Page.Root>
21
+ <Card.Root>
22
+ <Card.Header>
23
+ <Card.Title>Registros</Card.Title>
24
+ <Card.Description>Consulta de dados</Card.Description>
25
+ </Card.Header>
26
+ <Card.Body>
27
+ <Button>Salvar</Button>
28
+ </Card.Body>
29
+ </Card.Root>
30
+ </Page.Root>
31
+ );
32
+ }
33
+ ```
34
+
35
+ ## Principios
36
+
37
+ Este pacote foi desenhado para oferecer infraestrutura visual generica:
38
+
39
+ - componentes base de interface;
40
+ - campos de formulario reutilizaveis;
41
+ - primitivas de acao;
42
+ - tokens, estilos e presets;
43
+ - helpers sem dependencia de dominio;
44
+ - composicao por slots quando o componente possui partes internas.
45
+
46
+ ## Validacao de Page Actions
47
+
48
+ O pacote publica o CLI `shared-ui-check-page-actions` para validar o contrato de actions em uma aplicacao.
49
+
50
+ Contrato esperado:
51
+
52
+ - `AppLayout.actions` e somente o slot de layout.
53
+ - `Page.Actions` e o root visual da barra.
54
+ - Props como `helpContent`, `helpLabel`, `position`, `align` e `size` pertencem ao `Page.Actions`.
55
+ - Nao usar `ActionBar.*`, `Page.Root actions=...` dentro de `AppLayout`, Fragment, `div` ou `Page.ActionButton` solto como root de `AppLayout.actions`.
56
+
57
+ Uso recomendado:
58
+
59
+ ```json
60
+ {
61
+ "scripts": {
62
+ "check:page-actions": "shared-ui-check-page-actions"
63
+ }
64
+ }
65
+ ```
66
+
67
+ Tambem e possivel apontar um diretorio explicitamente:
68
+
69
+ ```bash
70
+ shared-ui-check-page-actions ./src
71
+ ```
72
+
73
+ ## Page Actions
74
+
75
+ `Page.Actions` e a raiz visual das acoes de tela. O pacote suporta `left`, `top`, `right` e
76
+ `bottom`, com `left` como padrao desktop e `bottom` como fallback mobile quando permitido.
77
+
78
+ Persistencia de preferencia continua sendo responsabilidade do consumidor. Use
79
+ `Page.ActionsProvider` para fornecer a preferencia global sem acoplar o pacote a
80
+ `localStorage`:
81
+
82
+ ```tsx
83
+ import { useCallback, useMemo, useState } from 'react';
84
+ import { Page, type PageActionsPosition, type PageActionsPreferences } from '@wellingtonhlc/shared-ui';
85
+
86
+ const storageKey = '@my-app/preference/page-actions-position';
87
+ const positions: PageActionsPosition[] = ['left', 'top', 'right', 'bottom'];
88
+
89
+ function readStoredPosition() {
90
+ const stored = window.localStorage.getItem(storageKey);
91
+ return positions.includes(stored as PageActionsPosition) ? (stored as PageActionsPosition) : undefined;
92
+ }
93
+
94
+ export function AppLayout({ children }: { children: React.ReactNode }) {
95
+ const [position, setPosition] = useState<PageActionsPosition | undefined>(readStoredPosition);
96
+
97
+ const handlePositionChange = useCallback(function handlePositionChange(nextPosition: PageActionsPosition) {
98
+ setPosition(nextPosition);
99
+ window.localStorage.setItem(storageKey, nextPosition);
100
+ }, []);
101
+
102
+ const preferences = useMemo<PageActionsPreferences>(
103
+ () => ({
104
+ mobilePosition: 'bottom',
105
+ movable: true,
106
+ onPositionChange: handlePositionChange,
107
+ position,
108
+ }),
109
+ [handlePositionChange, position],
110
+ );
111
+
112
+ return (
113
+ <Page.ActionsProvider preferences={preferences}>
114
+ <Page.ActionsSlot position="left" />
115
+ <main>{children}</main>
116
+ <Page.ActionsSlot position="right" />
117
+ <Page.ActionsSlot position="top" />
118
+ <Page.ActionsSlot position="bottom" />
119
+ </Page.ActionsProvider>
120
+ );
121
+ }
122
+ ```
123
+
124
+ Acoes de uma tela devem continuar usando `Page.Actions`; o provider apenas controla onde elas serao exibidas:
125
+
126
+ ```tsx
127
+ import { Page } from '@wellingtonhlc/shared-ui/components/Page';
128
+ import { Save } from 'lucide-react';
129
+
130
+ export function EditPageActions() {
131
+ return (
132
+ <Page.Actions helpLabel="Ajuda" helpContent="Revise os dados antes de salvar.">
133
+ <Page.ActionButton icon={<Save />} label="Salvar" />
134
+ </Page.Actions>
135
+ );
136
+ }
137
+ ```
138
+
139
+ Telas podem limitar o contrato localmente:
140
+
141
+ ```tsx
142
+ <Page.Actions allowedPositions={['top', 'bottom']} movable={false}>
143
+ <Page.ActionButton label="Salvar" />
144
+ </Page.Actions>
145
+ ```
146
+
147
+ Acoes auxiliares podem ser passadas por `helpContent`, `metaActions` ou por componentes
148
+ marcados como meta. Em barras verticais, o grupo meta e renderizado em modo compacto
149
+ e alinhado na borda externa da barra para preservar leitura visual; as labels continuam
150
+ obrigatorias no contrato e sao usadas para acessibilidade e tooltip.
151
+
152
+ ## Exportacoes
153
+
154
+ Entrada principal:
155
+
156
+ ```tsx
157
+ import { Button, Card, Modal, Table, cn } from '@wellingtonhlc/shared-ui';
158
+ ```
159
+
160
+ Subpaths recomendados para telas grandes ou rotas lazy-loaded:
161
+
162
+ ```tsx
163
+ import { Button } from '@wellingtonhlc/shared-ui/components/Button';
164
+ import { Table } from '@wellingtonhlc/shared-ui/components/Table';
165
+ import { cn } from '@wellingtonhlc/shared-ui/utils/cn';
166
+ ```
167
+
168
+ Estilos:
169
+
170
+ ```tsx
171
+ import '@wellingtonhlc/shared-ui/styles.css';
172
+ ```
173
+
174
+ Preset Tailwind:
175
+
176
+ ```ts
177
+ import sharedUiPreset from '@wellingtonhlc/shared-ui/tailwind-preset';
178
+ ```
179
+
180
+ ## Componentes
181
+
182
+ Componentes disponiveis na API publica:
183
+
184
+ | Grupo | Componentes |
185
+ |-------|-------------|
186
+ | Layout | `AppShell`, `Page`, `Sidebar`, `Card`, `StatCard` |
187
+ | Acoes | `Button`, `ActionPrimitives`, `AppShellActions`, `ConfirmationDialog` |
188
+ | Feedback | `Badge`, `EmptyState`, `PageMessage`, `Tooltip`, `CopyableField` |
189
+ | Formularios | `FieldControl`, `FieldGroup`, `TextField`, `TextareaField`, `SelectField`, `SelectionField`, `DateField`, `DecimalField`, `MultiSelectField`, `PasswordInput`, `Switch`, `RadioGroup` |
190
+ | Consulta | `Filter`, `Workspace` |
191
+ | Dados | `Table`, `Pagination`, `TabsUnderlined` |
192
+ | Controle de renderizacao | `RenderIf`, `RenderCase` |
193
+ | Tema | `ThemePreferencesSelector` |
194
+
195
+ ## DateField
196
+
197
+ `DateField` centraliza entrada de data, data e hora, ou apenas hora. Use `mode`
198
+ para declarar o formato esperado pelo campo:
199
+
200
+ ```tsx
201
+ <DateField label="Data" value="2026-06-16" onChange={setDate} mode="date" />
202
+ <DateField label="Data e hora" value="2026-06-16T14:30" onChange={setDateTime} mode="dateTime" />
203
+ <DateField label="Hora" value="14:30" onChange={setTime} mode="time" />
204
+ ```
205
+
206
+ `enableTime` permanece suportado como alias legado para `mode="dateTime"`.
207
+
208
+ ## FieldGroup
209
+
210
+ `FieldGroup` renderiza um grupo visual de campos com legenda. A borda vem ativa por
211
+ padrao; use `bordered={false}` quando o consumidor precisar manter a semantica de
212
+ grupo sem adicionar contorno visual.
213
+
214
+ ```tsx
215
+ import { FieldGroup, TextField } from '@wellingtonhlc/shared-ui';
216
+
217
+ <FieldGroup title="Endereco" bordered={false}>
218
+ <TextField label="CEP" />
219
+ <TextField label="Cidade" />
220
+ </FieldGroup>;
221
+ ```
222
+
223
+ ## RadioGroup
224
+
225
+ `RadioGroup` segue a mesma escala de altura dos campos base (`xs`, `sm`, `md`,
226
+ `lg`) para alinhar visualmente com `TextField`, `SelectField` e demais controles
227
+ na mesma linha de formulario.
228
+
229
+ O padrao `boxed` renderiza um `fieldset` com legenda, fazendo a borda contornar
230
+ o grupo a partir da label. Use `variant="plain"` quando precisar do grupo sem
231
+ borda.
232
+
233
+ ```tsx
234
+ import { RadioGroup } from '@wellingtonhlc/shared-ui';
235
+
236
+ <RadioGroup label="Tipo Pessoa" value={1} onChange={setType}>
237
+ <RadioGroup.Item value={1} label="Fisica" />
238
+ <RadioGroup.Item value={2} label="Juridica" />
239
+ </RadioGroup>;
240
+ ```
241
+
242
+ ## AppShell.Topbar.Button
243
+
244
+ Use `AppShell.Topbar.Button` para acoes de icone na barra superior, como notificacoes,
245
+ configuracoes e atalhos globais. O componente reutiliza o mesmo contrato visual dos
246
+ primitivos de acao, mas aplica o tamanho esperado para a topbar.
247
+
248
+ ```tsx
249
+ import { AppShell } from '@wellingtonhlc/shared-ui';
250
+ import { Bell, Settings } from 'lucide-react';
251
+
252
+ <AppShell.Actions>
253
+ <AppShell.Topbar.Button icon={<Bell />} tooltip="Notificacoes" />
254
+ <AppShell.Topbar.Button icon={<Settings />} tooltip="Configuracoes" />
255
+ </AppShell.Actions>
256
+ ```
257
+
258
+ ## TabsUnderlined
259
+
260
+ `TabsUnderlined` renderiza abas sublinhadas com conteudo controlado ou nao controlado.
261
+ As abas ja possuem tamanho minimo padrao e padding horizontal para comportar labels
262
+ medias, como `Configuracoes` e `Fornecedor`, sem ficarem apertadas.
263
+
264
+ Quando houver labels longas, use `tabWidth` e `truncateLabels` para manter abas
265
+ uniformes e aplicar ellipsis no texto que exceder o limite.
266
+
267
+ ```tsx
268
+ import { TabsUnderlined } from '@wellingtonhlc/shared-ui';
269
+
270
+ <TabsUnderlined
271
+ items={items}
272
+ tabWidth="12rem"
273
+ truncateLabels
274
+ />;
275
+ ```
276
+
277
+ Quando a largura puder variar dentro de uma faixa, use `tabMinWidth` e `tabMaxWidth`.
278
+ `truncateLabels` nao altera o comportamento sozinho; defina tambem `tabWidth` ou
279
+ `tabMaxWidth` para que o navegador saiba quando abreviar o texto.
280
+
281
+ ## ThemePreferencesSelector
282
+
283
+ `ThemePreferencesSelector` centraliza a escolha de cor e aparencia (`system`, `light`, `dark`) usada pelos consumidores.
284
+
285
+ Contrato minimo:
286
+
287
+ ```tsx
288
+ import { ThemePreferencesSelector, type ThemePreferencesValue } from '@wellingtonhlc/shared-ui';
289
+
290
+ const value: ThemePreferencesValue = {
291
+ color: 'indigo',
292
+ appearance: 'system',
293
+ };
294
+
295
+ <ThemePreferencesSelector
296
+ value={value}
297
+ options={[
298
+ { key: 'indigo', label: 'Indigo', primary: '#5b5cff' },
299
+ { key: 'emerald', label: 'Emerald', primary: '#059669' },
300
+ ]}
301
+ onChange={setValue}
302
+ />;
303
+ ```
304
+
305
+ Pontos de validacao:
306
+
307
+ - O botao de aparencia selecionado deve ficar perceptivelmente destacado sem depender de hover.
308
+ - Opcoes de cor bloqueadas usam `locked` e podem informar `requiredPlan`.
309
+ - Use `showColorSelector={false}` ou `showAppearanceSelector={false}` quando o consumidor precisar exibir apenas uma parte do controle.
310
+ - A story `AppearanceStates` mostra as tres aparencias ja selecionadas para validacao visual rapida.
311
+
312
+ ## SelectionField
313
+
314
+ `SelectionField` padroniza campos de selecao que exibem um registro, abrem uma busca externa e permitem limpar o valor selecionado. O componente nao gerencia modal nem estado interno do registro; o consumidor controla `value`, `onClick` e `onClear`.
315
+
316
+ Contrato minimo:
317
+
318
+ ```tsx
319
+ import { SelectionField, type SelectionDisplayValue } from '@wellingtonhlc/shared-ui';
320
+ import { UserCheck } from 'lucide-react';
321
+
322
+ const value: SelectionDisplayValue = {
323
+ title: 'Registro selecionado',
324
+ subtitle: 'Descricao complementar',
325
+ meta: 'COD-1024',
326
+ };
327
+
328
+ <SelectionField
329
+ label="Registro"
330
+ value={value}
331
+ icon={<UserCheck />}
332
+ clearable
333
+ size="sm"
334
+ selectTooltip="Selecionar registro"
335
+ clearTooltip="Limpar registro"
336
+ onClick={openSearch}
337
+ onClear={clearSelection}
338
+ />;
339
+ ```
340
+
341
+ Pontos de validacao:
342
+
343
+ - `size` segue a mesma escala visual dos campos base (`xs`, `sm`, `md`, `lg`).
344
+ - Use `triggerSlot` quando o consumidor precisar injetar um botao proprio para abrir a selecao.
345
+ - `clearable` exibe a acao de limpar somente quando ha `value` e `onClear`.
346
+ - `shortcutHint` pode exibir atalhos de teclado, como `F1`.
347
+
348
+ ## Filter (contrato legado)
349
+
350
+ `Filter.Root` organiza filtros compactos, ocupando apenas o espaço necessário. Quando houver muitos filtros, somente o corpo do painel rola e as ações continuam visíveis.
351
+
352
+ ```tsx
353
+ import { Button, Filter, TextField } from '@wellingtonhlc/shared-ui';
354
+
355
+ export function CustomersFilters() {
356
+ return (
357
+ <Filter.Root description="Refine os critérios antes de consultar os resultados.">
358
+ <TextField label="Buscar" size="sm" />
359
+ <Filter.Footer>
360
+ <Button type="submit" size="sm">
361
+ Pesquisar
362
+ </Button>
363
+ </Filter.Footer>
364
+ </Filter.Root>
365
+ );
366
+ }
367
+ ```
368
+
369
+ Padrões do painel:
370
+
371
+ - Usa `h-fit` e `w-fit` por padrão, sem ocupar a altura inteira da tela.
372
+ - Limita a altura com `maxHeightClassName`; o default é `max-h-[calc(100vh-12rem)]`.
373
+ - Aplica rolagem apenas na área de filtros.
374
+ - Use `Filter.Footer` para manter botões sempre visíveis no rodapé do painel.
375
+ - Em interfaces densas, campos dentro do painel devem preferir `size="sm"` e nao devem usar formato `rounded-full`.
376
+
377
+ ## Filter atual
378
+
379
+ `Filter.Root` usa descrição vazia por padrão e rola apenas o viewport dos campos. Informe `onSubmit` e `onClear` para obter as ações automáticas `Pesquisar` e `Redefinir`; o submit cria um único `<form>` interno. `submitLabel`, `clearLabel`, `isSubmitting`, `actionsDisabled` e `fieldsClassName` são opcionais. Um `Filter.Footer` explícito substitui as ações automáticas e continua indicado para formulários externos.
380
+
381
+ `Filter.Visibility` oferece estado controlado ou não controlado. `Filter.Trigger` aceita o botão padrão ou clona um `Page.ActionButton` via `triggerSlot`, preservando seu estilo e handler. Dentro de `Workspace.Root`, o estado fechado recolhe a coluna de filtros.
382
+
383
+ `Workspace.Root appearance="joined"` compõe filtros e resultados sem gap em uma moldura única. O padrão continua `separated`; `Table.Root` permanece responsável por viewport, moldura e paginação.
384
+
385
+ ```tsx
386
+ <Filter.Root onSubmit={handleSearch} onClear={handleClear} isSubmitting={isLoading}>
387
+ <TextField label="Buscar" size="sm" />
388
+ </Filter.Root>
389
+ ```
390
+
391
+ ## Contrato publico 0.1.0
392
+
393
+ A API pública pré-v1 foi limpa para evitar compatibilidade artificial em produção.
394
+
395
+ Exports removidos:
396
+
397
+ - `ActionBar`: use `Page.Actions`, `Page.ActionButton` e `Page.ActionsSeparator`.
398
+ - `Dialog`: use `Modal`.
399
+ - `ChoiceGroup`: use `RadioGroup`.
400
+ - `ConditionalCase`: use `RenderCase`.
401
+ - `ConditionalRender`: use `RenderIf`.
402
+ - `ToggleSwitch`: use `Switch`.
403
+ - `SearchFilter`: use `Filter`.
404
+ - `SearchWorkspace`: componha layout no consumidor ou com componentes genéricos.
405
+ - `TabsUnderline` e `UnderlinedTabs`: use `TabsUnderlined`.