@softize/opus 19.0.0 → 20.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +239 -0
- package/bin/cli.mjs +5 -0
- package/bin/lib/check.mjs +198 -10
- package/bin/lib/copy.mjs +29 -0
- package/bin/lib/mcp.mjs +1 -1
- package/docs/adr/0020-icon-tiles-are-explicitly-composed.md +8 -0
- package/docs/adr/0021-content-carries-structure-and-semantic-element.md +7 -0
- package/docs/adr/0023-surfaces-share-one-anatomy-and-two-layouts.md +19 -1
- package/docs/adr/0024-fill-height-propagates-by-context.md +118 -0
- package/docs/adr/0025-content-frame-treatment-does-not-change-semantics.md +134 -0
- package/docs/data-products.md +15 -9
- package/docs/protocol.md +3 -4
- package/docs/releasing.md +2 -2
- package/package.json +2 -2
- package/registry/skills/create-opus-action/scripts/scaffold.mjs +2 -1
- package/registry/templates/app/package.json +1 -1
- package/src/core/runtime.ts +96 -8
- package/src/core/types.ts +5 -2
- package/src/ui/components/patterns/action-form-card.tsx +11 -1
- package/src/ui/components/patterns/content-header.tsx +109 -18
- package/src/ui/components/patterns/fill-region.ts +150 -0
- package/src/ui/components/patterns/list.tsx +91 -92
- package/src/ui/components/patterns/page.tsx +20 -4
- package/src/ui/components/patterns/presentation.tsx +52 -37
- package/src/ui/components/patterns/split.tsx +44 -4
- package/src/ui/components/patterns/surface-anatomy.ts +35 -8
- package/src/ui/components/patterns/surface-header.tsx +58 -25
- package/src/ui/components/patterns/trigger.tsx +12 -2
- package/src/ui/components/primitives/alert.tsx +9 -1
- package/src/ui/components/primitives/avatar.tsx +7 -3
- package/src/ui/components/primitives/card.tsx +1 -1
- package/src/ui/components/primitives/carousel.tsx +34 -5
- package/src/ui/components/primitives/checkbox.tsx +11 -3
- package/src/ui/components/primitives/command.tsx +2 -1
- package/src/ui/components/primitives/copyable.tsx +120 -10
- package/src/ui/components/primitives/dialog.tsx +42 -11
- package/src/ui/components/primitives/drawer.tsx +10 -2
- package/src/ui/components/primitives/empty.tsx +1 -1
- package/src/ui/components/primitives/icon-picker.tsx +6 -2
- package/src/ui/components/primitives/icon-tile.tsx +7 -0
- package/src/ui/components/primitives/input-group.tsx +9 -2
- package/src/ui/components/primitives/input-otp.tsx +1 -1
- package/src/ui/components/primitives/kbd.tsx +1 -1
- package/src/ui/components/primitives/label.tsx +3 -0
- package/src/ui/components/primitives/menu.tsx +5 -0
- package/src/ui/components/primitives/popover.tsx +1 -1
- package/src/ui/components/primitives/progress.tsx +9 -1
- package/src/ui/components/primitives/slider.tsx +62 -11
- package/src/ui/components/primitives/truncate.tsx +10 -1
- package/src/ui/docs/content/accordion.md +74 -27
- package/src/ui/docs/content/action-form-card.md +24 -15
- package/src/ui/docs/content/action-form-dialog.md +17 -7
- package/src/ui/docs/content/action-form.md +92 -77
- package/src/ui/docs/content/action-list-dialog.md +75 -38
- package/src/ui/docs/content/action-list.md +141 -58
- package/src/ui/docs/content/action-trigger.md +27 -10
- package/src/ui/docs/content/action-view.md +14 -14
- package/src/ui/docs/content/actions.md +161 -66
- package/src/ui/docs/content/ai.md +43 -44
- package/src/ui/docs/content/alert.md +83 -29
- package/src/ui/docs/content/ask.md +51 -26
- package/src/ui/docs/content/aspect-ratio.md +22 -24
- package/src/ui/docs/content/audit.md +23 -19
- package/src/ui/docs/content/auth.md +38 -19
- package/src/ui/docs/content/avatar.md +54 -5
- package/src/ui/docs/content/badge.md +29 -9
- package/src/ui/docs/content/breadcrumb.md +21 -8
- package/src/ui/docs/content/button.md +73 -43
- package/src/ui/docs/content/calendar.md +134 -26
- package/src/ui/docs/content/card.md +41 -15
- package/src/ui/docs/content/carousel.md +37 -6
- package/src/ui/docs/content/chat.md +118 -37
- package/src/ui/docs/content/checkbox.md +73 -7
- package/src/ui/docs/content/cli.md +94 -55
- package/src/ui/docs/content/collapsible.md +43 -19
- package/src/ui/docs/content/command.md +30 -8
- package/src/ui/docs/content/composer.md +23 -8
- package/src/ui/docs/content/content.md +119 -27
- package/src/ui/docs/content/copyable.md +39 -8
- package/src/ui/docs/content/customization.md +55 -46
- package/src/ui/docs/content/cycle.md +33 -18
- package/src/ui/docs/content/data-products.md +115 -0
- package/src/ui/docs/content/data-state.md +20 -6
- package/src/ui/docs/content/data.md +20 -19
- package/src/ui/docs/content/detail.md +12 -5
- package/src/ui/docs/content/dialog.md +107 -24
- package/src/ui/docs/content/dictionary-value.md +4 -4
- package/src/ui/docs/content/dock.md +54 -19
- package/src/ui/docs/content/dot.md +35 -5
- package/src/ui/docs/content/drawer.md +63 -19
- package/src/ui/docs/content/empty-value.md +20 -6
- package/src/ui/docs/content/empty.md +24 -3
- package/src/ui/docs/content/events.md +76 -16
- package/src/ui/docs/content/executions.md +9 -9
- package/src/ui/docs/content/field.md +21 -6
- package/src/ui/docs/content/getting-started.md +44 -34
- package/src/ui/docs/content/icon-picker.md +19 -13
- package/src/ui/docs/content/icon-tile.md +38 -15
- package/src/ui/docs/content/input-otp.md +58 -7
- package/src/ui/docs/content/input.md +22 -3
- package/src/ui/docs/content/item.md +53 -6
- package/src/ui/docs/content/kbd.md +5 -1
- package/src/ui/docs/content/label.md +13 -4
- package/src/ui/docs/content/log.md +5 -5
- package/src/ui/docs/content/markdown.md +5 -4
- package/src/ui/docs/content/mcp.md +49 -23
- package/src/ui/docs/content/menu.md +95 -10
- package/src/ui/docs/content/metric-card.md +12 -4
- package/src/ui/docs/content/observability.md +10 -9
- package/src/ui/docs/content/page.md +118 -12
- package/src/ui/docs/content/pagination.md +13 -5
- package/src/ui/docs/content/pane.md +55 -5
- package/src/ui/docs/content/popover.md +42 -5
- package/src/ui/docs/content/presentation.md +91 -47
- package/src/ui/docs/content/progress.md +27 -14
- package/src/ui/docs/content/queue.md +39 -21
- package/src/ui/docs/content/radio-group.md +26 -4
- package/src/ui/docs/content/router.md +29 -10
- package/src/ui/docs/content/runtime.md +90 -54
- package/src/ui/docs/content/scheduler.md +53 -21
- package/src/ui/docs/content/scroll-area.md +42 -35
- package/src/ui/docs/content/select.md +78 -33
- package/src/ui/docs/content/semantic-context.md +21 -2
- package/src/ui/docs/content/separator.md +15 -9
- package/src/ui/docs/content/sidebar.md +3 -2
- package/src/ui/docs/content/skeleton.md +6 -1
- package/src/ui/docs/content/slider.md +37 -9
- package/src/ui/docs/content/spinner.md +4 -3
- package/src/ui/docs/content/split.md +19 -0
- package/src/ui/docs/content/storage.md +8 -9
- package/src/ui/docs/content/switch.md +10 -7
- package/src/ui/docs/content/table.md +46 -8
- package/src/ui/docs/content/tabs.md +14 -4
- package/src/ui/docs/content/testing.md +76 -31
- package/src/ui/docs/content/textarea.md +5 -4
- package/src/ui/docs/content/toast.md +48 -7
- package/src/ui/docs/content/toggle.md +3 -3
- package/src/ui/docs/content/tokens.md +15 -26
- package/src/ui/docs/content/tooltip.md +18 -2
- package/src/ui/docs/content/truncate.md +36 -6
- package/src/ui/docs/content/ui.md +74 -22
- package/src/ui/docs/content/upgrading.md +45 -36
- package/src/ui/docs/plugin.ts +36 -2
- package/src/ui/docs/registry.tsx +6 -0
- package/src/ui/drivers/react.tsx +16 -8
- package/src/ui/meta.ts +32 -32
- package/src/ui/react.tsx +1 -0
- package/src/vite/design.ts +16 -4
package/src/ui/meta.ts
CHANGED
|
@@ -27,13 +27,13 @@ export const componentMeta = {
|
|
|
27
27
|
name: "alert",
|
|
28
28
|
ancestry: "opus",
|
|
29
29
|
whenToUse:
|
|
30
|
-
"
|
|
30
|
+
"Mantenha uma informação visível no contexto da página até que ela deixe de valer. `context` declara neutral, info, success, warning ou danger, e `variant` escolhe subtle ou outline. No caso comum, use a forma curta `<Alert title description icon context />`; para conteúdo rico, componha AlertMedia, AlertHeader (com AlertTitle e AlertDescription) e AlertActions. As ações partem de Button ghost; uma nova tentativa pode usar somente o ícone, com nome acessível e tooltip. A mídia mantém uma moldura tonal quadrada, mesmo com descrição de várias linhas, e o texto comunica o significado sem depender só da cor. Para cobrar uma decisão, use `dialog.confirm()`; para confirmar o resultado de uma ação sem ocupar espaço na página, use `toast`; para o erro de uma consulta, use DataState.",
|
|
31
31
|
},
|
|
32
32
|
badge: {
|
|
33
33
|
name: "badge",
|
|
34
34
|
ancestry: "shadcn",
|
|
35
35
|
whenToUse:
|
|
36
|
-
"
|
|
36
|
+
"Rotule um estado ou uma categoria com um texto curto que continua legível. `context` declara neutral, primary, info, success, warning ou danger, e `variant` escolhe solid, subtle ou outline. O Badge não é interativo: para uma ação, use Button; para navegar, use `asChild` com um `<a>`. Quando só a cor basta, ao lado de um texto que já nomeia o item, use Dot. Um valor de dicionário com papel declarado usa DictionaryValue em vez de escolher contexto ou variante na tela.",
|
|
37
37
|
},
|
|
38
38
|
"empty-value": {
|
|
39
39
|
name: "empty-value",
|
|
@@ -51,7 +51,7 @@ export const componentMeta = {
|
|
|
51
51
|
name: "dot",
|
|
52
52
|
ancestry: "opus",
|
|
53
53
|
whenToUse:
|
|
54
|
-
"
|
|
54
|
+
"Sinalize um estado com um ponto compacto quando o texto ao redor já dá o contexto. `context` declara neutral, primary, info, success, warning ou danger, e `variant` escolhe solid ou outline. Passe `label` quando a cor reforçar informação; sem `label`, o ponto é decorativo e fica oculto dos leitores de tela. Quando o estado precisar continuar legível sozinho, use Badge.",
|
|
55
55
|
},
|
|
56
56
|
"icon-tile": {
|
|
57
57
|
name: "icon-tile",
|
|
@@ -63,7 +63,7 @@ export const componentMeta = {
|
|
|
63
63
|
name: "detail",
|
|
64
64
|
ancestry: "opus",
|
|
65
65
|
whenToUse:
|
|
66
|
-
'
|
|
66
|
+
'Apresente dados somente leitura como pares de rótulo e valor. DetailGroup organiza os DetailField com a semântica de uma lista de definições; `columns` controla a grade, `orientation` posiciona rótulo e valor e, no modo horizontal, alinha os rótulos em uma coluna compartilhada. `variant="framed"` aplica a moldura e `dividers` acrescenta somente as divisórias internas. Para entrada, validação e erro, use Field; para uma coleção pesquisável, use ActionList.',
|
|
67
67
|
},
|
|
68
68
|
dock: {
|
|
69
69
|
name: "dock",
|
|
@@ -87,7 +87,7 @@ export const componentMeta = {
|
|
|
87
87
|
name: "metric-card",
|
|
88
88
|
ancestry: "opus",
|
|
89
89
|
whenToUse:
|
|
90
|
-
"
|
|
90
|
+
"Apresente uma medida resumida, como um total ou uma contagem, com rótulo, valor em destaque e descrição opcional. O consumidor calcula e formata os valores. Use `secondaryMetric` para uma segunda leitura da mesma dimensão, exibida como lâmina posterior com rótulo próprio; `context` realça somente o ícone, `action` acrescenta uma ação diretamente relacionada e `loading` substitui rótulo e valor durante a carga. Com `onActivate`, `active` e `activationLabel`, informados juntos, o card vira um controle que aplica o recorte que a medida resume e expõe o estado por `aria-pressed`. Para conteúdo geral ou estrutura livre, use Card.",
|
|
91
91
|
},
|
|
92
92
|
chat: {
|
|
93
93
|
name: "chat",
|
|
@@ -99,7 +99,7 @@ export const componentMeta = {
|
|
|
99
99
|
name: "checkbox",
|
|
100
100
|
ancestry: "shadcn",
|
|
101
101
|
whenToUse:
|
|
102
|
-
"
|
|
102
|
+
"Permita marcar uma opção que só vale ao salvar um formulário, como aceitar uma condição ou incluir uma etapa. Associe cada caixa a um Label e controle o estado com `checked` e `onCheckedChange`, ou defina o inicial com `defaultChecked`. Para uma preferência que entra em vigor no clique, use Switch; para uma escolha única entre várias opções, use RadioGroup ou Select.",
|
|
103
103
|
},
|
|
104
104
|
"icon-picker": {
|
|
105
105
|
name: "icon-picker",
|
|
@@ -111,7 +111,7 @@ export const componentMeta = {
|
|
|
111
111
|
name: "command",
|
|
112
112
|
ancestry: "shadcn",
|
|
113
113
|
whenToUse:
|
|
114
|
-
"
|
|
114
|
+
"Permita encontrar um item ou uma ação digitando parte do nome e escolhê-lo pelo teclado. A lista filtra enquanto a busca muda, organiza os itens em grupos e mostra um estado vazio quando nada corresponde. Para uma paleta de comandos em modal, use CommandDialog; o aplicativo registra o atalho que a abre, como ⌘K. Para escolher um valor em um formulário, use Select.",
|
|
115
115
|
},
|
|
116
116
|
composer: {
|
|
117
117
|
name: "composer",
|
|
@@ -123,7 +123,7 @@ export const componentMeta = {
|
|
|
123
123
|
name: "content-header",
|
|
124
124
|
ancestry: "opus",
|
|
125
125
|
whenToUse:
|
|
126
|
-
'Estruture uma região com título e corpo. No caso comum, declare título, descrição, contador e ações diretamente em Content; use `framed` quando a região precisar de limite próprio, `
|
|
126
|
+
'Estruture uma região com título e corpo. No caso comum, declare título, mídia, descrição, contador e ações diretamente em Content; use `framed` quando a região precisar de limite próprio, `frameVariant="legend"` para integrar visualmente o header à borda e `as="fieldset"` somente para agrupar campos sob uma legenda nativa. Componha ContentHeader apenas quando precisar controlar a anatomia.',
|
|
127
127
|
},
|
|
128
128
|
copyable: {
|
|
129
129
|
name: "copyable",
|
|
@@ -147,25 +147,25 @@ export const componentMeta = {
|
|
|
147
147
|
name: "label",
|
|
148
148
|
ancestry: "shadcn",
|
|
149
149
|
whenToUse:
|
|
150
|
-
"
|
|
150
|
+
"Nomeie um controle de formulário. Associe `htmlFor` ao `id` do controle: o rótulo passa a ser o nome acessível do campo, e clicar nele move o foco para o controle. Quando o campo também tiver ajuda e mensagem de erro, use Field.",
|
|
151
151
|
},
|
|
152
152
|
markdown: {
|
|
153
153
|
name: "markdown",
|
|
154
154
|
ancestry: "opus",
|
|
155
155
|
whenToUse:
|
|
156
|
-
"
|
|
156
|
+
"Exiba texto formatado que chega como Markdown, como a resposta de um agente no Chat ou uma descrição escrita por uma pessoa. Passe o texto em `content`; o resultado é HTML semântico com a tipografia do tema. HTML presente no texto é escapado, não interpretado, por isso o componente serve para conteúdo de pessoas ou de modelos, e endereços soltos viram links.",
|
|
157
157
|
},
|
|
158
158
|
menu: {
|
|
159
159
|
name: "menu",
|
|
160
160
|
ancestry: "opus",
|
|
161
161
|
whenToUse:
|
|
162
|
-
'
|
|
162
|
+
'Reúna ações relacionadas em uma lista flutuante aberta por um gatilho. Componha Menu > MenuTrigger + MenuContent com seus itens; `onSelect` executa a ação do item e fecha o menu, e `context="danger"` sinaliza um item com consequência perigosa. Para escolher um valor de formulário, use Select; para buscar pelo teclado, Command; para conteúdo livre ancorado, Popover.',
|
|
163
163
|
},
|
|
164
164
|
popover: {
|
|
165
165
|
name: "popover",
|
|
166
166
|
ancestry: "shadcn",
|
|
167
167
|
whenToUse:
|
|
168
|
-
"
|
|
168
|
+
"Apresente conteúdo livre junto a um gatilho sem abrir um modal, como um formulário curto ou detalhes. PopoverHeader agrupa PopoverTitle e PopoverDescription. Para uma lista de ações, use Menu; para uma dica curta ao passar o ponteiro, Tooltip; para uma tarefa que exige atenção exclusiva, Dialog.",
|
|
169
169
|
},
|
|
170
170
|
select: {
|
|
171
171
|
name: "select",
|
|
@@ -177,7 +177,7 @@ export const componentMeta = {
|
|
|
177
177
|
name: "separator",
|
|
178
178
|
ancestry: "shadcn",
|
|
179
179
|
whenToUse:
|
|
180
|
-
|
|
180
|
+
'Marque a fronteira entre blocos de conteúdo que não pertencem a uma superfície com regiões. A linha horizontal fica entre blocos empilhados; com `orientation="vertical"`, ela separa itens lado a lado e herda a altura do contêiner. A linha é decorativa por padrão e fica fora da árvore de acessibilidade; use `decorative={false}` quando a divisão tiver significado. Não use Separator entre cabeçalho, corpo e rodapé de Card, Dialog ou Drawer: nessas superfícies, os divisores são derivados das regiões com `layout="sectioned"`.',
|
|
181
181
|
},
|
|
182
182
|
skeleton: {
|
|
183
183
|
name: "skeleton",
|
|
@@ -195,7 +195,7 @@ export const componentMeta = {
|
|
|
195
195
|
name: "table",
|
|
196
196
|
ancestry: "shadcn",
|
|
197
197
|
whenToUse:
|
|
198
|
-
'
|
|
198
|
+
'Organize em linhas e colunas os dados que a tela já tem em mãos. Componha Table > (TableHeader > TableRow > TableHead, TableBody > TableRow > TableCell). `variant="plain"` vem sem borda externa; `variant="framed"` aplica a moldura, recorta a rolagem e destaca o cabeçalho. Para uma coleção com busca, filtros e paginação, use ActionList.',
|
|
199
199
|
},
|
|
200
200
|
tabs: {
|
|
201
201
|
name: "tabs",
|
|
@@ -207,7 +207,7 @@ export const componentMeta = {
|
|
|
207
207
|
name: "textarea",
|
|
208
208
|
ancestry: "shadcn",
|
|
209
209
|
whenToUse:
|
|
210
|
-
"
|
|
210
|
+
"Receba texto livre com várias linhas, como uma descrição ou um contexto. O campo aceita os atributos nativos de `<textarea>` e cresce com o conteúdo a partir da altura mínima. Associe um Label; para uma caixa de envio com botão integrado, use Composer; para uma única linha, use Input.",
|
|
211
211
|
},
|
|
212
212
|
toast: {
|
|
213
213
|
name: "toast",
|
|
@@ -231,7 +231,7 @@ export const componentMeta = {
|
|
|
231
231
|
name: "accordion",
|
|
232
232
|
ancestry: "shadcn",
|
|
233
233
|
whenToUse:
|
|
234
|
-
|
|
234
|
+
'Divida um conteúdo longo em painéis que a pessoa expande sob demanda, cada um com seu título. `type="single"` mantém um painel aberto por vez — combine com `collapsible` para permitir fechar todos — e `type="multiple"` permite vários abertos. Cada AccordionItem precisa de `value`, e o AccordionTrigger já traz o ícone de estado. Para um único bloco recolhível, use Collapsible; para alternar entre painéis do mesmo nível, Tabs.',
|
|
235
235
|
},
|
|
236
236
|
"aspect-ratio": {
|
|
237
237
|
name: "aspect-ratio",
|
|
@@ -249,25 +249,25 @@ export const componentMeta = {
|
|
|
249
249
|
name: "breadcrumb",
|
|
250
250
|
ancestry: "shadcn",
|
|
251
251
|
whenToUse:
|
|
252
|
-
"
|
|
252
|
+
"Mostre onde a pessoa está quando a página fica vários níveis abaixo da entrada da seção e permita voltar a um nível intermediário. Use BreadcrumbLink nos níveis navegáveis, BreadcrumbPage no nível atual, que não é clicável, BreadcrumbSeparator entre eles e BreadcrumbEllipsis para colapsar trilhas longas. Quando basta voltar ao nível imediatamente acima, use PageBack; para alternar painéis no mesmo nível, Tabs.",
|
|
253
253
|
},
|
|
254
254
|
calendar: {
|
|
255
255
|
name: "calendar",
|
|
256
256
|
ancestry: "shadcn",
|
|
257
257
|
whenToUse:
|
|
258
|
-
'
|
|
258
|
+
'Permita escolher datas vendo o mês inteiro, como a data de uma entrega ou o período de um relatório. `mode` define a seleção — `single`, `multiple` ou `range` — e o formato de `selected` e `onSelect` (Date, Date[] ou { from, to }). `captionLayout="dropdown"` troca o título do mês por seletores de mês e ano, útil para chegar a um período distante; `numberOfMonths` mostra meses lado a lado e `disabled` impede a escolha de datas específicas. Os textos usam pt-BR por padrão. Para abrir o calendário a partir de um campo, ancore-o em um Popover.',
|
|
259
259
|
},
|
|
260
260
|
carousel: {
|
|
261
261
|
name: "carousel",
|
|
262
262
|
ancestry: "shadcn",
|
|
263
263
|
whenToUse:
|
|
264
|
-
"
|
|
264
|
+
"Percorra uma sequência de itens do mesmo tipo em um espaço limitado, um ou alguns por vez. Componha Carousel > CarouselContent > CarouselItem com CarouselPrevious e CarouselNext; a largura de cada item define quantos cabem na área visível. `orientation` escolhe o eixo, `opts` configura o deslocamento, como `loop` e `align`, e `setApi` permite controlar o carrossel por código. Nomeie o carrossel com `aria-label`. Para consultar e comparar muitos registros, use ActionList; para navegar entre painéis, Tabs.",
|
|
265
265
|
},
|
|
266
266
|
collapsible: {
|
|
267
267
|
name: "collapsible",
|
|
268
268
|
ancestry: "shadcn",
|
|
269
269
|
whenToUse:
|
|
270
|
-
"
|
|
270
|
+
"Esconda um bloco secundário atrás de um gatilho, mantendo o restante da tela visível. Componha Collapsible > (CollapsibleTrigger + CollapsibleContent); o gatilho já renderiza o `<button>`. Use `defaultOpen` no modo não controlado e `open` com `onOpenChange` quando outra parte da tela precisar conhecer o estado; `disabled` trava o gatilho. Para vários painéis recolhíveis, use Accordion; para alternar entre painéis, Tabs; para ações ancoradas, Menu.",
|
|
271
271
|
},
|
|
272
272
|
drawer: {
|
|
273
273
|
name: "drawer",
|
|
@@ -291,7 +291,7 @@ export const componentMeta = {
|
|
|
291
291
|
name: "input-otp",
|
|
292
292
|
ancestry: "shadcn",
|
|
293
293
|
whenToUse:
|
|
294
|
-
"Receba um código
|
|
294
|
+
"Receba um código curto enviado por outro canal, como uma confirmação de acesso ou um segundo fator. `maxLength` define o comprimento, cada InputOTPSlot representa uma posição e InputOTPSeparator divide os blocos. Sem `pattern`, qualquer caractere é aceito; passe `pattern` para restringir a entrada, por exemplo a dígitos. Para texto livre, use Input.",
|
|
295
295
|
},
|
|
296
296
|
item: {
|
|
297
297
|
name: "item",
|
|
@@ -309,7 +309,7 @@ export const componentMeta = {
|
|
|
309
309
|
name: "pagination",
|
|
310
310
|
ancestry: "shadcn",
|
|
311
311
|
whenToUse:
|
|
312
|
-
"
|
|
312
|
+
"Permita saltar entre as páginas de uma coleção dividida em partes. Em uma listagem derivada de uma action, ActionList já monta esta paginação no rodapé; componha-a diretamente apenas em coleções próprias, com Pagination › PaginationContent › PaginationItem e PaginationLink, PaginationPrevious, PaginationNext e PaginationEllipsis. `page` fornece o número e o nome acessível (“Página N”), e `isActive` marca a página atual. Com `href`, o link é um `<a>`; sem `href`, vira `<button>` para o modo controlado, com foco e `disabled`. `label` localiza o texto das setas. Para rolagem infinita ou listas curtas, dispense a paginação.",
|
|
313
313
|
},
|
|
314
314
|
progress: {
|
|
315
315
|
name: "progress",
|
|
@@ -321,7 +321,7 @@ export const componentMeta = {
|
|
|
321
321
|
name: "radio-group",
|
|
322
322
|
ancestry: "shadcn",
|
|
323
323
|
whenToUse:
|
|
324
|
-
"
|
|
324
|
+
"Permita uma escolha única entre opções mutuamente exclusivas que precisam permanecer visíveis. Cada RadioGroupItem declara um `value` e se associa a um Label; o RadioGroup guarda a escolha em `value` com `onValueChange`, ou em `defaultValue` no modo não controlado. Com muitas opções, prefira Select; para ligar ou desligar um único item, use Checkbox ou Switch.",
|
|
325
325
|
},
|
|
326
326
|
split: {
|
|
327
327
|
name: "split",
|
|
@@ -339,25 +339,25 @@ export const componentMeta = {
|
|
|
339
339
|
name: "pane",
|
|
340
340
|
ancestry: "opus",
|
|
341
341
|
whenToUse:
|
|
342
|
-
"Estruture a coluna ou faixa encaixada
|
|
342
|
+
"Estruture a coluna ou faixa encaixada em um Split. PaneHeader nomeia a região e acomoda mídia e ações; ao lado desses slots, também aceita conteúdo livre, como uma busca ou a marca de uma barra lateral. PaneBody rola e PaneFooter mantém à vista o que não pode sair da tela. `layout` escolhe entre regiões seccionadas, com divisores derivados da vizinhança, e o fluxo contínuo. `inset` vale para o pane sem slots; com eles, o recuo pertence a cada região.",
|
|
343
343
|
},
|
|
344
344
|
"scroll-area": {
|
|
345
345
|
name: "scroll-area",
|
|
346
346
|
ancestry: "shadcn",
|
|
347
347
|
whenToUse:
|
|
348
|
-
'
|
|
348
|
+
'Mantenha a altura de um bloco, como uma lista, um log ou um histórico, e role o conteúdo que passar dela com a barra do tema no lugar da barra do sistema. Dê a altura ao ScrollArea por `className` e coloque o conteúdo dentro; a barra vertical já vem incluída. Para rolar na horizontal, acrescente `<ScrollBar orientation="horizontal" />` como filho. Quando a página inteira precisar rolar, deixe a rolagem com o navegador.',
|
|
349
349
|
},
|
|
350
350
|
slider: {
|
|
351
351
|
name: "slider",
|
|
352
352
|
ancestry: "shadcn",
|
|
353
353
|
whenToUse:
|
|
354
|
-
|
|
354
|
+
'Permita escolher um valor ou um intervalo dentro de uma faixa contínua, arrastando o controle (thumb). `min`, `max` e `step` delimitam a faixa; `value` com `onValueChange` controla o estado — `[n]` para um valor, `[a, b]` para um intervalo — e `defaultValue` atende o modo não controlado. Nomeie o controle com `aria-label` ou `aria-labelledby` no Slider, que os repassa ao thumb; o `htmlFor` de um Label não o alcança. Em um intervalo, passe `thumbLabels` com um nome por thumb, na ordem dos valores. Para digitar um número exato, use Input com `type="number"`; para ligar ou desligar, Switch.',
|
|
355
355
|
},
|
|
356
356
|
switch: {
|
|
357
357
|
name: "switch",
|
|
358
358
|
ancestry: "shadcn",
|
|
359
359
|
whenToUse:
|
|
360
|
-
"
|
|
360
|
+
"Permita ligar ou desligar uma preferência que entra em vigor imediatamente, como ativar um agente ou a sincronização. Associe o controle a um Label e controle o estado com `checked` e `onCheckedChange`, ou defina o inicial com `defaultChecked`. Quando a escolha só vale ao salvar um formulário, use Checkbox.",
|
|
361
361
|
},
|
|
362
362
|
toggle: {
|
|
363
363
|
name: "toggle",
|
|
@@ -376,13 +376,13 @@ export const componentMeta = {
|
|
|
376
376
|
name: "action-form",
|
|
377
377
|
ancestry: "opus",
|
|
378
378
|
whenToUse:
|
|
379
|
-
"Renderize e envie uma FormAction com validação, estado de envio e notificação consistentes. Sem filhos,
|
|
379
|
+
"Renderize e envie uma FormAction com validação, estado de envio e notificação consistentes. Sem filhos, o formulário monta um campo para cada entrada de `fields` do contrato, na ordem declarada; um campo do schema sem entrada em `fields` não aparece. Com ActionFormField, o consumidor controla o layout sem duplicar rótulos ou erros. Para uma ação sem campos, use ActionTrigger.",
|
|
380
380
|
},
|
|
381
381
|
"action-form-dialog": {
|
|
382
382
|
name: "action-form-dialog",
|
|
383
383
|
ancestry: "opus",
|
|
384
384
|
whenToUse:
|
|
385
|
-
"
|
|
385
|
+
"Apresente um formulário de action em um modal, sem levar a pessoa para outra página. O consumidor controla `open` e `onOpenChange`, e o modal fecha depois de uma execução bem-sucedida. O título nomeia a operação e o recurso, como `Criar {recurso}` ou `Editar {recurso}`, e a ação principal mantém `Salvar`; use `submitLabel` somente para outro efeito, como `Renomear`. Assim como ActionForm, aceita ActionFormField como filhos. Para um formulário na própria página, use ActionForm; para uma seção delimitada, ActionFormCard.",
|
|
386
386
|
},
|
|
387
387
|
"action-form-card": {
|
|
388
388
|
name: "action-form-card",
|
|
@@ -406,13 +406,13 @@ export const componentMeta = {
|
|
|
406
406
|
name: "action-view",
|
|
407
407
|
ancestry: "opus",
|
|
408
408
|
whenToUse:
|
|
409
|
-
"Carregue e apresente um recurso de uma ViewAction com estados de carregamento
|
|
409
|
+
"Carregue e apresente um recurso de uma ViewAction com estados de carregamento e erro consistentes. Os filhos definem o layout a partir dos dados e de `refetch`. O handler deve devolver um valor: represente um recurso ausente com o erro `not_found`, cuja frase aparece para a pessoa. Quando o recurso alimentar mais de uma região, use `useViewAction`; para uma coleção, use ActionList.",
|
|
410
410
|
},
|
|
411
411
|
page: {
|
|
412
412
|
name: "page",
|
|
413
413
|
ancestry: "opus",
|
|
414
414
|
whenToUse:
|
|
415
|
-
"
|
|
415
|
+
"Estruture uma página com cabeçalho, introdução, estado e conteúdo na mesma anatomia. Page renderiza o `<main>` com um container centralizado de até 80rem (`max-w-7xl`); PageHeader declara navegação e ações globais, PageIntro é a introdução opcional e PageBody recebe o conteúdo. PageShell mantém a barra persistente de 3.75rem e projeta nela os slots do PageHeader. Uma região interna pode fornecer o heading principal com Content. PageActionsTarget fica restrito a workspaces imersivos sem PageShell. PageState substitui o conteúdo inteiro durante carregamento, falha ou ausência e oculta PageIntro, por isso informações indispensáveis entram no corpo, como Alert ou texto. Para uma falha parcial, mantenha o estado na seção com DataState; para uma região disponível à criação ou vínculo, use Empty.",
|
|
416
416
|
},
|
|
417
417
|
presentation: {
|
|
418
418
|
name: "presentation",
|
|
@@ -430,7 +430,7 @@ export const componentMeta = {
|
|
|
430
430
|
name: "data-state",
|
|
431
431
|
ancestry: "opus",
|
|
432
432
|
whenToUse:
|
|
433
|
-
"Coordene carregamento, erro, vazio e conteúdo de uma consulta assíncrona
|
|
433
|
+
"Coordene carregamento, erro, vazio e conteúdo de uma consulta assíncrona na escala de uma seção. O carregamento mostra um Spinner; o vazio compõe Empty com moldura sólida e `emptyMessage`; o erro é um Alert danger com `errorMessage`, sem expor o texto técnico, e `onRetry` com `retryLabel` acrescenta a nova tentativa. Em uma tabela, `colSpan` ocupa uma linha inteira. Para o estado da página inteira, use PageState; uma coleção carregada por ActionList já trata esses estados; para uma região disponível à criação, use Empty. Ações em andamento pertencem ao estado `busy` do controle que as iniciou.",
|
|
434
434
|
},
|
|
435
435
|
"action-list-dialog": {
|
|
436
436
|
name: "action-list-dialog",
|
package/src/ui/react.tsx
CHANGED
package/src/vite/design.ts
CHANGED
|
@@ -15,10 +15,22 @@
|
|
|
15
15
|
* dos entries são IGNORADOS (não registrados), senão o `start()` exige
|
|
16
16
|
* eventbus/scheduler adapters que o design não tem por que montar.
|
|
17
17
|
*
|
|
18
|
-
* Uso (vite.config.ts do app):
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
18
|
+
* Uso (vite.config.ts do app, como no template de `opus create`):
|
|
19
|
+
* const DESIGN_RUN = process.argv.includes('--mode=design') ||
|
|
20
|
+
* process.argv.some((arg, i) => (arg === '--mode' || arg === '-m') && process.argv[i + 1] === 'design')
|
|
21
|
+
* const designPlugins: PluginOption[] = DESIGN_RUN
|
|
22
|
+
* ? [(await import('@softize/opus/vite')).opusDesign()]
|
|
23
|
+
* : []
|
|
24
|
+
* export default defineConfig({ plugins: [react(), ...designPlugins] })
|
|
25
|
+
* // vite --mode design --configLoader runner
|
|
26
|
+
*
|
|
27
|
+
* Não importe o plugin de forma estática: o pacote publica TypeScript, e o
|
|
28
|
+
* carregador padrão de config do Vite o externaliza, o que o Node 22+ recusa
|
|
29
|
+
* dentro de `node_modules` (ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING). O
|
|
30
|
+
* import dinâmico no top-level, condicionado ao modo design e carregado com
|
|
31
|
+
* `--configLoader runner`, deixa o Vite transformar o TypeScript; build e
|
|
32
|
+
* preview nem chegam a carregá-lo. Detalhes em "Prototipar com dados
|
|
33
|
+
* simulados", no guia de actions (src/ui/docs/content/actions.md).
|
|
22
34
|
*/
|
|
23
35
|
|
|
24
36
|
import { readdirSync } from 'node:fs'
|