@softize/opus 13.0.0 → 14.0.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 +81 -0
- package/PROMOTED.md +46 -0
- package/README.md +28 -19
- package/bin/cli.mjs +87 -216
- package/bin/lib/cli-shared.mjs +131 -0
- package/bin/lib/copy.mjs +276 -6
- package/bin/lib/db.mjs +16 -74
- package/bin/lib/gen-openapi.mjs +3 -3
- package/bin/lib/gen-runner.mjs +1 -1
- package/bin/lib/gen.mjs +14 -69
- package/bin/lib/mcp.mjs +3 -1
- package/bin/lib/seed.mjs +5 -62
- package/docs/code-style.md +4 -1
- package/docs/ownership-vs-shadcn-lock.md +2 -3
- package/docs/protocol.md +7 -7
- package/docs/releasing.md +8 -2
- package/package.json +7 -3
- package/registry/instructions/opus.md +3 -3
- package/registry/templates/app/package.json +1 -1
- package/registry/templates/app/src/App.tsx +11 -6
- package/registry/templates/app/src/main.tsx +4 -4
- package/src/audit/drivers/console.ts +1 -0
- package/src/auth/drivers/better-auth.ts +1 -0
- package/src/auth/drivers/jwt.ts +1 -0
- package/src/cache/drivers/memory.ts +1 -0
- package/src/client/drivers/fetch.ts +2 -1
- package/src/core/actions.ts +6 -1
- package/src/core/audit.ts +9 -3
- package/src/core/contracts.ts +7 -0
- package/src/core/domain.ts +1 -1
- package/src/core/errors.ts +18 -15
- package/src/core/index.ts +4 -2
- package/src/core/package-version.ts +26 -0
- package/src/core/reactions.ts +1 -1
- package/src/core/runtime.ts +33 -23
- package/src/core/schedules.ts +1 -1
- package/src/core/types.ts +5 -6
- package/src/dsl/eval.ts +2 -2
- package/src/dsl/kysely.ts +2 -2
- package/src/dsl/loads.ts +1 -1
- package/src/dsl/parser.ts +5 -5
- package/src/events/drivers/mitt.ts +1 -0
- package/src/mcp/index.ts +2 -1
- package/src/observability/drivers/opentelemetry.ts +1 -0
- package/src/queue/drivers/bullmq.ts +3 -3
- package/src/scheduler/drivers/node-cron.ts +3 -2
- package/src/scheduler/every.ts +7 -7
- package/src/schema/openapi.ts +3 -3
- package/src/seed/index.ts +29 -0
- package/src/server/drivers/fastify.ts +5 -2
- package/src/server/drivers/node.ts +9 -6
- package/src/server/index.ts +3 -1
- package/src/storage/drivers/fs.ts +1 -0
- package/src/testing/index.ts +3 -3
- package/src/ui/components/patterns/action-list-dialog.tsx +10 -3
- package/src/ui/components/patterns/confirm.tsx +2 -31
- package/src/ui/components/patterns/content-header.tsx +44 -137
- package/src/ui/components/patterns/data-state.tsx +42 -68
- package/src/ui/components/patterns/dock.tsx +20 -3
- package/src/ui/components/patterns/form.tsx +26 -22
- package/src/ui/components/patterns/list.tsx +18 -12
- package/src/ui/components/patterns/page-state.tsx +39 -51
- package/src/ui/components/patterns/page.tsx +37 -54
- package/src/ui/components/patterns/sidebar.tsx +17 -6
- package/src/ui/components/patterns/state-surface.tsx +148 -0
- package/src/ui/components/patterns/surface-header.tsx +119 -0
- package/src/ui/components/patterns/trigger.tsx +21 -25
- package/src/ui/components/patterns/view.tsx +29 -22
- package/src/ui/components/primitives/alert.tsx +1 -27
- package/src/ui/components/primitives/ask.tsx +3 -3
- package/src/ui/components/primitives/avatar.tsx +15 -5
- package/src/ui/components/primitives/badge.tsx +5 -41
- package/src/ui/components/primitives/breadcrumb.tsx +2 -2
- package/src/ui/components/primitives/button.tsx +39 -30
- package/src/ui/components/primitives/calendar.tsx +28 -2
- package/src/ui/components/primitives/carousel.tsx +3 -3
- package/src/ui/components/primitives/chat.tsx +1 -1
- package/src/ui/components/primitives/checkbox.tsx +1 -1
- package/src/ui/components/primitives/command.tsx +2 -2
- package/src/ui/components/primitives/control.ts +72 -0
- package/src/ui/components/primitives/copyable.tsx +1 -1
- package/src/ui/components/primitives/dialog.tsx +12 -7
- package/src/ui/components/primitives/dot.tsx +1 -25
- package/src/ui/components/primitives/drawer.tsx +10 -3
- package/src/ui/components/primitives/field.tsx +3 -3
- package/src/ui/components/primitives/icon-picker.tsx +3 -1
- package/src/ui/components/primitives/input-group.tsx +12 -9
- package/src/ui/components/primitives/input-otp.tsx +1 -1
- package/src/ui/components/primitives/input.tsx +2 -2
- package/src/ui/components/primitives/item.tsx +3 -1
- package/src/ui/components/primitives/menu.tsx +1 -7
- package/src/ui/components/primitives/pagination.tsx +16 -8
- package/src/ui/components/primitives/progress.tsx +32 -3
- package/src/ui/components/primitives/radio-group.tsx +1 -1
- package/src/ui/components/primitives/resizable.tsx +3 -1
- package/src/ui/components/primitives/select.tsx +6 -6
- package/src/ui/components/primitives/slider.tsx +5 -1
- package/src/ui/components/primitives/sonner.tsx +3 -0
- package/src/ui/components/primitives/spinner.tsx +13 -16
- package/src/ui/components/primitives/switch.tsx +5 -1
- package/src/ui/components/primitives/tabs.tsx +6 -3
- package/src/ui/components/primitives/textarea.tsx +1 -1
- package/src/ui/components/primitives/toggle.tsx +9 -4
- package/src/ui/components/primitives/tooltip.tsx +1 -0
- package/src/ui/docs/changelog.tsx +1 -1
- package/src/ui/docs/content/action-form.md +36 -3
- package/src/ui/docs/content/action-list-dialog.md +2 -2
- package/src/ui/docs/content/action-list.md +13 -2
- package/src/ui/docs/content/action-trigger.md +12 -5
- package/src/ui/docs/content/action-view.md +11 -3
- package/src/ui/docs/content/ask.md +11 -0
- package/src/ui/docs/content/avatar.md +7 -3
- package/src/ui/docs/content/button.md +30 -14
- package/src/ui/docs/content/calendar.md +13 -0
- package/src/ui/docs/content/card.md +26 -0
- package/src/ui/docs/content/chat.md +20 -0
- package/src/ui/docs/content/cli.md +71 -19
- package/src/ui/docs/content/communication.md +36 -0
- package/src/ui/docs/content/composer.md +15 -0
- package/src/ui/docs/content/content.md +17 -1
- package/src/ui/docs/content/copyable.md +8 -0
- package/src/ui/docs/content/data-state.md +17 -13
- package/src/ui/docs/content/detail.md +19 -1
- package/src/ui/docs/content/dialog.md +1 -4
- package/src/ui/docs/content/dictionary-value.md +9 -2
- package/src/ui/docs/content/dock.md +8 -0
- package/src/ui/docs/content/dot.md +8 -0
- package/src/ui/docs/content/empty.md +2 -2
- package/src/ui/docs/content/getting-started.md +2 -2
- package/src/ui/docs/content/icon-picker.md +11 -0
- package/src/ui/docs/content/input.md +1 -1
- package/src/ui/docs/content/item.md +1 -1
- package/src/ui/docs/content/label.md +7 -0
- package/src/ui/docs/content/menu.md +6 -0
- package/src/ui/docs/content/metric-card.md +13 -0
- package/src/ui/docs/content/page.md +20 -4
- package/src/ui/docs/content/pagination.md +11 -9
- package/src/ui/docs/content/popover.md +6 -0
- package/src/ui/docs/content/progress.md +8 -11
- package/src/ui/docs/content/select.md +5 -5
- package/src/ui/docs/content/semantic-context.md +5 -4
- package/src/ui/docs/content/sidebar.md +13 -47
- package/src/ui/docs/content/skeleton.md +6 -0
- package/src/ui/docs/content/spinner.md +9 -6
- package/src/ui/docs/content/split.md +21 -0
- package/src/ui/docs/content/switch.md +1 -1
- package/src/ui/docs/content/tabs.md +1 -1
- package/src/ui/docs/content/textarea.md +7 -0
- package/src/ui/docs/content/toggle.md +1 -1
- package/src/ui/docs/content/tokens.md +4 -4
- package/src/ui/docs/content/truncate.md +8 -0
- package/src/ui/docs/content/ui.md +14 -0
- package/src/ui/docs/doc-client.tsx +5 -5
- package/src/ui/docs/doc.tsx +26 -14
- package/src/ui/docs/registry.tsx +5 -5
- package/src/ui/docs/standalone.tsx +2 -2
- package/src/ui/drivers/react.tsx +12 -12
- package/src/ui/lib/action-errors.ts +45 -0
- package/src/ui/lib/zod-pt-br.ts +31 -4
- package/src/ui/meta.ts +8 -8
- package/src/ui/react.tsx +10 -16
- package/src/ui/theme.css +10 -8
- package/src/vite/design.ts +6 -18
- package/src/ui/components/patterns/shell-nav.tsx +0 -147
|
@@ -28,10 +28,14 @@ para agente.
|
|
|
28
28
|
|
|
29
29
|
## Tamanhos
|
|
30
30
|
|
|
31
|
-
size
|
|
32
|
-
|
|
31
|
+
`size` usa a escala única dos controles: o avatar de uma linha mede o mesmo que o controle ao lado
|
|
32
|
+
(`sm` 2rem, `default` 2.25rem, `lg` 2.5rem); `xs` (1.5rem) é a lista densa. O fallback e o selo
|
|
33
|
+
acompanham o tamanho.
|
|
33
34
|
|
|
34
35
|
```tsx preview
|
|
36
|
+
<Avatar size="xs">
|
|
37
|
+
<AvatarFallback>AL</AvatarFallback>
|
|
38
|
+
</Avatar>
|
|
35
39
|
<Avatar size="sm">
|
|
36
40
|
<AvatarFallback>AL</AvatarFallback>
|
|
37
41
|
</Avatar>
|
|
@@ -86,7 +90,7 @@ excedente — os membros do workspace Empresa X.
|
|
|
86
90
|
|
|
87
91
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
88
92
|
|---|---|---|---|
|
|
89
|
-
| `size` | `'sm' \| 'default' \| 'lg'` | `'default'` | Diâmetro do retrato; o fallback e o selo acompanham
|
|
93
|
+
| `size` | `'xs' \| 'sm' \| 'default' \| 'lg'` | `'default'` | Diâmetro do retrato na escala única dos controles (1.5 · 2 · 2.25 · 2.5rem); o fallback e o selo acompanham. |
|
|
90
94
|
|
|
91
95
|
## Propriedades de AvatarImage
|
|
92
96
|
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`context` declara a hierarquia ou o risco da ação; `variant` escolhe o tratamento visual. Use
|
|
4
4
|
`primary` para a ação principal, `neutral` para ações de apoio e `danger` quando a ação tiver uma
|
|
5
|
-
consequência perigosa.
|
|
6
|
-
compatibilidade.
|
|
5
|
+
consequência perigosa.
|
|
7
6
|
|
|
8
7
|
```tsx preview
|
|
9
8
|
<Button>Criar workspace</Button>
|
|
@@ -16,28 +15,45 @@ compatibilidade.
|
|
|
16
15
|
|
|
17
16
|
## Tamanhos
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
`size` usa a escala única dos controles: o mesmo nome tem a mesma medida em `Button`, `Select`,
|
|
19
|
+
`Tabs`, `Toggle`, `Switch`, `Avatar`, `Spinner` e nos botões embutidos. Os tamanhos de texto dão a
|
|
20
|
+
altura da linha; os `icon-*` são quadrados para botões só de ícone, que exigem `aria-label` porque não
|
|
21
|
+
há texto visível. O glifo dentro do controle acompanha o tamanho (0.875rem em `xs` e `sm`, 1rem em
|
|
22
|
+
`default`, 1.25rem em `lg`), a menos que o ícone traga um `size-*` próprio.
|
|
23
|
+
|
|
24
|
+
| Nome | Medida | Uso |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `xs` | 1.5rem | Ação dentro de um campo (`InputGroupButton`). |
|
|
27
|
+
| `sm` | 2rem | Toolbar e cabeçalho densos, ao lado de `Select` e `Tabs` `sm`. |
|
|
28
|
+
| `default` | 2.25rem | A linha padrão, a mesma de `Input`. |
|
|
29
|
+
| `lg` | 2.5rem | Chamada principal com mais área de toque. |
|
|
30
|
+
| `icon-xs` | 1.5rem | Ação só de ícone dentro de um campo, como o `trailing` de Input ou Select. |
|
|
31
|
+
| `icon-sm` | 1.75rem | Ação só de ícone dentro de uma linha ou card; é o quadrado de `ActionTrigger` com `icon` e das setas do pager de `ActionList`. |
|
|
32
|
+
| `icon` | 2.25rem | Ação só de ícone na linha padrão. |
|
|
33
|
+
| `icon-lg` | 2.5rem | Ação só de ícone ao lado de um `lg`. |
|
|
20
34
|
|
|
21
35
|
```tsx preview
|
|
36
|
+
<Button size="xs">Mínimo</Button>
|
|
22
37
|
<Button size="sm">Pequeno</Button>
|
|
23
38
|
<Button>Padrão</Button>
|
|
24
39
|
<Button size="lg">Grande</Button>
|
|
25
|
-
<Button size="icon" aria-label="Novo"><Plus /></Button>
|
|
26
|
-
<Button size="icon-sm" variant="ghost" aria-label="Novo"><Plus /></Button>
|
|
27
40
|
<Button size="icon-xs" variant="ghost" aria-label="Novo"><Plus /></Button>
|
|
41
|
+
<Button size="icon-sm" variant="ghost" aria-label="Novo"><Plus /></Button>
|
|
42
|
+
<Button size="icon" aria-label="Novo"><Plus /></Button>
|
|
43
|
+
<Button size="icon-lg" aria-label="Novo"><Plus /></Button>
|
|
28
44
|
```
|
|
29
45
|
|
|
30
46
|
## Estados
|
|
31
47
|
|
|
32
|
-
busy = ação em andamento (DEPOIS do clique): o Spinner e o disabled vêm do botão.
|
|
33
|
-
Spinner TROCA o ícone (não soma). Não
|
|
34
|
-
|
|
48
|
+
busy = ação em andamento (DEPOIS do clique): o Spinner e o disabled vêm do botão. `icon` recebe o
|
|
49
|
+
elemento do ícone e o dimensiona pelo `size`; com icon, o Spinner TROCA o ícone (não soma). Não
|
|
50
|
+
confunda com carregar conteúdo (ANTES) — isso é `DataState` ou `Skeleton` em um nível de página.
|
|
35
51
|
|
|
36
52
|
```tsx preview
|
|
37
53
|
<Button disabled>Desabilitado</Button>
|
|
38
54
|
<Button busy>Salvando…</Button>
|
|
39
|
-
<Button icon={Plus}>Novo</Button>
|
|
40
|
-
<Button icon={Plus} busy>Novo</Button>
|
|
55
|
+
<Button icon={<Plus />}>Novo</Button>
|
|
56
|
+
<Button icon={<Plus />} busy>Novo</Button>
|
|
41
57
|
```
|
|
42
58
|
|
|
43
59
|
## Como outro elemento (asChild)
|
|
@@ -57,10 +73,10 @@ buttonVariants serve para o caso sem filho único.
|
|
|
57
73
|
|---|---|---|---|
|
|
58
74
|
| `context` | `'neutral' \| 'primary' \| 'danger'` | `'primary'` | A hierarquia ou o risco comunicado pela ação. |
|
|
59
75
|
| `variant` | `'solid' \| 'subtle' \| 'outline' \| 'ghost' \| 'link'` | `'solid'` | O tratamento visual aplicado ao contexto. |
|
|
60
|
-
| `size` | `'
|
|
76
|
+
| `size` | `'xs' \| 'sm' \| 'default' \| 'lg' \| 'icon-xs' \| 'icon-sm' \| 'icon' \| 'icon-lg'` | `'default'` | A medida na escala única dos controles (tabela acima). Os `icon-*` são quadrados para botões só de ícone, com `aria-label`. |
|
|
61
77
|
| `asChild` | `boolean` | `false` | Renderiza como o filho (Radix Slot) em vez de `<button>` — para âncoras e afins. |
|
|
62
78
|
| `busy` | `boolean` | `false` | Ação em andamento (depois do clique): mostra Spinner + desabilita. Não é "carregando" de conteúdo (que é Spinner/Skeleton em um nível de página). |
|
|
63
|
-
| `icon` | `React.
|
|
79
|
+
| `icon` | `React.ReactNode` | | Ícone à esquerda, como nó (ex.: `icon={<Plus />}`); o glifo segue o `size`. No busy é trocado pelo Spinner — não soma. |
|
|
64
80
|
|
|
65
81
|
## ButtonGroup
|
|
66
82
|
|
|
@@ -83,7 +99,7 @@ variações.
|
|
|
83
99
|
|
|
84
100
|
```tsx preview
|
|
85
101
|
<ButtonGroup>
|
|
86
|
-
<Button icon={Play}>Rodar agente developer</Button>
|
|
102
|
+
<Button icon={<Play />}>Rodar agente developer</Button>
|
|
87
103
|
<ButtonGroupSeparator />
|
|
88
104
|
<Button size="icon" aria-label="Mais opções">
|
|
89
105
|
<ChevronDown />
|
|
@@ -102,7 +118,7 @@ semântica de outro elemento, como `label`.
|
|
|
102
118
|
<GitBranch />
|
|
103
119
|
empresa-x-api
|
|
104
120
|
</ButtonGroupText>
|
|
105
|
-
<Button variant="outline" icon={RotateCw}>Sincronizar</Button>
|
|
121
|
+
<Button variant="outline" icon={<RotateCw />}>Sincronizar</Button>
|
|
106
122
|
</ButtonGroup>
|
|
107
123
|
```
|
|
108
124
|
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
O calendário fala pt-BR por padrão: nomes de mês e de dia vêm do `locale` (`ptBR` de
|
|
2
|
+
`date-fns/locale`) e os controles de navegação têm rótulos acessíveis em português. Passe outro
|
|
3
|
+
`locale` para trocar o idioma; `labels` sobrescreve rótulos individualmente.
|
|
4
|
+
|
|
1
5
|
## Dia único
|
|
2
6
|
|
|
3
7
|
mode=single guarda uma Date — controle por selected/onSelect. defaultMonth abre o calendário no mês certo sem mexer na seleção.
|
|
@@ -60,3 +64,12 @@ captionLayout=dropdown troca o título do mês por seletores de mês e ano — b
|
|
|
60
64
|
| `disabled` | `Matcher` | | Datas não selecionáveis — uma Date, um array, um { from, to } ou um predicado (date) => boolean. |
|
|
61
65
|
| `buttonVariant` | `Button['variant']` | `'ghost'` | A variante dos botões de navegação (anterior/próximo). |
|
|
62
66
|
| `showOutsideDays` | `boolean` | `true` | Mostra os dias do mês vizinho que completam a primeira e a última semana. |
|
|
67
|
+
| `locale` | `Locale` | `ptBR` | Idioma dos nomes de mês e de dia (um locale do date-fns). |
|
|
68
|
+
| `labels` | `Partial<Labels>` | rótulos em pt-BR | Rótulos acessíveis da navegação e dos seletores; mescla sobre o padrão. |
|
|
69
|
+
|
|
70
|
+
## CalendarDayButton
|
|
71
|
+
|
|
72
|
+
Cada dia é um `CalendarDayButton` — um `Button` ghost quadrado que recebe os modificadores do
|
|
73
|
+
dia (`selected`, `range-start`, `today`…). Use `components={{ DayButton: … }}` para
|
|
74
|
+
decorar o dia (um marcador de evento, por exemplo) partindo dele em vez de reimplementar o
|
|
75
|
+
foco e a seleção.
|
|
@@ -47,3 +47,29 @@ Para painel com estrutura: cada slot é dono do próprio padding (como o Dialog)
|
|
|
47
47
|
</CardFooter>
|
|
48
48
|
</Card>
|
|
49
49
|
```
|
|
50
|
+
|
|
51
|
+
## Ação no cabeçalho
|
|
52
|
+
|
|
53
|
+
`CardAction` é o slot de ação do header (um botão ou menu). Quem compõe posiciona — em geral um
|
|
54
|
+
`CardHeader` em `flex-row` com o título de um lado e a ação do outro.
|
|
55
|
+
|
|
56
|
+
```tsx preview col
|
|
57
|
+
<Card>
|
|
58
|
+
<CardHeader className="flex-row items-start justify-between">
|
|
59
|
+
<div>
|
|
60
|
+
<CardTitle>Empresa X</CardTitle>
|
|
61
|
+
<CardDescription>3 agentes vinculados.</CardDescription>
|
|
62
|
+
</div>
|
|
63
|
+
<CardAction>
|
|
64
|
+
<Button size="sm" variant="outline">Editar</Button>
|
|
65
|
+
</CardAction>
|
|
66
|
+
</CardHeader>
|
|
67
|
+
</Card>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Propriedades de Card
|
|
71
|
+
|
|
72
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
73
|
+
|---|---|---|---|
|
|
74
|
+
| `asChild` | `boolean` | `false` | Renderiza o filho com a superfície do Card (ex.: um `<button>` clicável inteiro). |
|
|
75
|
+
| `className` | `string` | | Compõe sobre a superfície; os slots (`CardHeader`, `CardBody`, `CardContent`, `CardFooter`, `CardAction`) são donos do próprio padding. |
|
|
@@ -91,3 +91,23 @@ continua valendo — é o caso degenerado do protocolo.
|
|
|
91
91
|
Reidratação: passe `initialMessages` com o histórico persistido e troque a `key` do
|
|
92
92
|
componente ao trocar de conversa. O rótulo do indicador é customizável por
|
|
93
93
|
`humanizeTool={(name) => '…'}`.
|
|
94
|
+
|
|
95
|
+
## Propriedades de Chat
|
|
96
|
+
|
|
97
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
98
|
+
|---|---|---|---|
|
|
99
|
+
| `send` | `(messages: ChatMessage[]) => Promise<string> \| AsyncIterable<ChatEvent>` | | Modo autogerenciado: envia o histórico e devolve a resposta inteira ou um stream de eventos. Ignorado no modo controlado. |
|
|
100
|
+
| `messages` | `ChatTranscriptItem[]` | | Modo controlado: o transcript vem do app; com ele, `onSend`, `busy` e `activity` assumem. |
|
|
101
|
+
| `onSend` | `(text: string) => void \| boolean \| Promise<void \| boolean>` | | Modo controlado: recebe o texto enviado; retornar `false` devolve o texto ao composer. |
|
|
102
|
+
| `busy` | `boolean` | | Modo controlado: trava o composer enquanto o turno corre. |
|
|
103
|
+
| `activity` | `string \| null` | `undefined` | Indicador vivo: `null` mostra “Pensando…”, string mostra o rótulo; `undefined` esconde. |
|
|
104
|
+
| `notice` | `ReactNode` | | Aviso do app acima do composer (credencial, agente desatualizado…). |
|
|
105
|
+
| `composerActions` | `ReactNode` | | Seletores discretos na barra do composer (agente, app, escopo). |
|
|
106
|
+
| `composerClassName` | `string` | | Ajusta o contêiner externo do composer sem alcançar o DOM interno. |
|
|
107
|
+
| `greeting` | `string` | | Texto do estado vazio; some quando a conversa começa. |
|
|
108
|
+
| `empty` | `ReactNode` | | Estado vazio composto pelo app; vence `greeting` quando os dois existem. |
|
|
109
|
+
| `initialMessages` | `ChatMessage[]` | | Histórico inicial do modo autogerenciado; troque a `key` ao trocar de conversa. |
|
|
110
|
+
| `kickoff` | `() => Promise<string> \| AsyncIterable<ChatEvent>` | | Conversa que começa pelo assistente, uma vez, quando o transcript nasce vazio. |
|
|
111
|
+
| `renderArtifact` | `(artifact: ChatArtifact) => ReactNode` | link com o título | Render do evento `artifact`. |
|
|
112
|
+
| `humanizeTool` | `(name: string, detail?: string) => string` | pt-BR embutido | Rótulo humano do tool em uso no indicador vivo. |
|
|
113
|
+
| `placeholder` | `string` | `'Escreva uma mensagem…'` | Placeholder do composer. |
|
|
@@ -5,18 +5,39 @@ title: CLI opus
|
|
|
5
5
|
# CLI opus
|
|
6
6
|
|
|
7
7
|
O Opus traz um CLI que cobre o ciclo: faz o bootstrap, gera artefatos a partir das declarações,
|
|
8
|
-
valida as convenções e expõe o estado vivo para os agentes via MCP.
|
|
8
|
+
valida as convenções e expõe o estado vivo para os agentes via MCP. `opus --help` lista os
|
|
9
|
+
comandos e `opus <comando> --help` detalha cada um.
|
|
9
10
|
|
|
10
11
|
## Gates
|
|
11
12
|
|
|
12
|
-
> Use
|
|
13
|
-
>
|
|
13
|
+
> Use os gates no CI e antes de entregar uma mudança. Cada um informa o que precisa de ajuste e
|
|
14
|
+
> encerra com sucesso (exit 0) quando não encontra violação.
|
|
14
15
|
|
|
15
16
|
```bash
|
|
16
|
-
opus check src
|
|
17
|
-
opus
|
|
18
|
-
opus db
|
|
19
|
-
opus seed check
|
|
17
|
+
opus check src # convenções das actions e da UI (exit ≠ 0 se violar)
|
|
18
|
+
opus copy --check # inventário de copy ausente ou desatualizado
|
|
19
|
+
opus db check # drift entidade ↔ banco (read-only)
|
|
20
|
+
opus seed check # bindings, dependências, ciclos e scripts paralelos de seed
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`opus check` lê o source sem executar nada e aplica nove regras: cinco sobre as actions
|
|
24
|
+
(`action-name`, `kind`, `field-order`, `export`, `requires-sem-authorize`) e quatro sobre a UI
|
|
25
|
+
(`ui-structure`, `ui-semantic-api`, `removed-ui-token`, `unpaired-ui-surface`). Um projeto
|
|
26
|
+
marcado com `opus.json` e ainda sem actions passa vacuamente; sem o marcador, zero actions
|
|
27
|
+
falha, porque um gate vazio não é aprovação. `opus check --help` descreve cada regra.
|
|
28
|
+
|
|
29
|
+
### Hook de pré-push
|
|
30
|
+
|
|
31
|
+
O hook Git que `opus setup` instala roda, antes de cada push: `opus copy --check`; depois
|
|
32
|
+
`opus pre-push materialization` na raiz, para confirmar que os artefatos Opus materializados
|
|
33
|
+
(skills, hooks, instruções) correspondem à versão adotada; e `opus check` em cada app com
|
|
34
|
+
`opus.json`. Qualquer um com exit ≠ 0 bloqueia o push. Os mesmos comandos podem ser executados à
|
|
35
|
+
mão para antecipar o resultado:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
opus pre-push # o mesmo opus check no diretório atual
|
|
39
|
+
opus pre-push apps/portal # o check de um app específico
|
|
40
|
+
opus pre-push materialization # só a freshness dos artefatos materializados
|
|
20
41
|
```
|
|
21
42
|
|
|
22
43
|
## Seeds de desenvolvimento e teste
|
|
@@ -31,9 +52,11 @@ opus seed apply customers.scenarios --profile smoke --scope local
|
|
|
31
52
|
opus seed verify customers.scenarios --profile smoke --scope local
|
|
32
53
|
```
|
|
33
54
|
|
|
34
|
-
`
|
|
35
|
-
|
|
36
|
-
|
|
55
|
+
`--profile` escolhe o perfil (default: o `defaultProfile` do seed) e `--scope` declara o escopo
|
|
56
|
+
dos dados (a variável `OPUS_SEED_SCOPE` é a alternativa). `--json` devolve o resultado
|
|
57
|
+
estruturado, inclusive em caso de erro. `apply` converge quando repetido; não há reset ou
|
|
58
|
+
truncate no contrato. A skill `$create-opus-seed` estrutura um novo dataset, e
|
|
59
|
+
`$apply-opus-seed` opera um seed registrado pela mesma CLI.
|
|
37
60
|
|
|
38
61
|
## Geração e introspecção
|
|
39
62
|
|
|
@@ -41,23 +64,52 @@ mesma CLI.
|
|
|
41
64
|
> é um lockfile versionado. A diferença do manifest torna a revisão objetiva.
|
|
42
65
|
|
|
43
66
|
```bash
|
|
44
|
-
opus gen
|
|
45
|
-
opus
|
|
67
|
+
opus gen # manifest / openapi / docs / stubs a partir do opus.config.ts
|
|
68
|
+
opus gen --config ./apps/api/opus.config.ts # config fora do diretório atual
|
|
69
|
+
opus gen --output ./custom/gen # pasta de saída (default: a do config, ou ./.gen)
|
|
70
|
+
opus copy # inventário semântico de copy dos contratos
|
|
71
|
+
opus introspect # modelo da estrutura (actions/reactions/schedules + wiring)
|
|
46
72
|
opus introspect --json
|
|
47
73
|
```
|
|
48
74
|
|
|
49
|
-
|
|
75
|
+
`opus copy` projeta os textos de `defineAction`/`defineContract` no inventário que a política de
|
|
76
|
+
copy da `@softize/base` valida. O caminho vem de `base.json` (`copy.inventory`; default
|
|
77
|
+
`.base/copy-inventory.json` na raiz Git), a escrita é atômica e o arquivo gerado deve ser
|
|
78
|
+
versionado. `--check` compara sem escrever e falha quando o inventário está ausente,
|
|
79
|
+
desatualizado ou contém copy dinâmica não declarada.
|
|
80
|
+
|
|
81
|
+
`--config` vale para `gen`, `db` e `seed` e sempre aponta para um caminho dentro do projeto. O
|
|
82
|
+
`gen` aceita `--force` por compatibilidade, mas a flag não altera nada: a saída mora em um
|
|
83
|
+
diretório dedicado e é sempre sobrescrita.
|
|
84
|
+
|
|
85
|
+
## Banco
|
|
86
|
+
|
|
87
|
+
> Os comandos `db` carregam o `opus.config.ts` e abrem conexão; por isso rodam num runner isolado
|
|
88
|
+
> via `tsx`. O padrão é um schema idempotente: um script SQL evolutivo re-rodável, não migrations
|
|
89
|
+
> versionadas.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
opus db check # compara o schema do banco com as entidades (read-only)
|
|
93
|
+
opus db migrate # aplica o schema idempotente e roda o drift-check na sequência
|
|
94
|
+
opus db scaffold # rascunho kysely a partir do diff, como referência para escrever o SQL
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`db scaffold` gera um rascunho para revisão à mão; a verdade continua sendo o script. `db migrate
|
|
98
|
+
down` está aposentado e encerra com erro: sem histórico de migrations não há o que reverter —
|
|
99
|
+
rollback é editar o schema e rodar `opus db migrate` de novo. O `opus.config.ts` precisa expor a
|
|
100
|
+
factory lazy `database`, as entidades (ou domínios) e, opcionalmente, `schema` e `migrations`;
|
|
101
|
+
`opus db --help` detalha.
|
|
102
|
+
|
|
103
|
+
## Bootstrap
|
|
50
104
|
|
|
51
105
|
> `create` scaffolda um app novo com os pré-requisitos plugados; `setup` é per-app
|
|
52
|
-
> (idempotente, nunca sobrescreve o seu)
|
|
106
|
+
> (idempotente, nunca sobrescreve o seu).
|
|
53
107
|
|
|
54
108
|
```bash
|
|
55
|
-
opus create meu-app
|
|
109
|
+
opus create meu-app # app canônico do zero: protocolo + UI + preview + automação
|
|
56
110
|
opus create meu-cliente --monorepo # a RAIZ de um workspace (apps/* + packages/*)
|
|
57
|
-
opus create apps/portal
|
|
58
|
-
opus setup
|
|
59
|
-
opus list # lista os templates disponíveis
|
|
60
|
-
opus add action-form # copia um template do catálogo para o projeto
|
|
111
|
+
opus create apps/portal # dentro de um workspace: só o app (modo detectado)
|
|
112
|
+
opus setup # grava opus.json e materializa a camada específica do SDK
|
|
61
113
|
```
|
|
62
114
|
|
|
63
115
|
O esqueleto do `create` versiona com o Opus (sai do mesmo pacote que o SDK que ele
|
|
@@ -50,6 +50,42 @@ frase. Não copie as regras da Base para cá.
|
|
|
50
50
|
| placeholder de campo ou busca | `placeholder` |
|
|
51
51
|
| `Select.emptyText` e grupos de opção | `empty-state` e `heading` |
|
|
52
52
|
| confirmação local do `ActionTrigger` | `title`, `dialog-body` e `button` |
|
|
53
|
+
| `dialog.alert/confirm/prompt/choose` — `title`, `description`/`body`, `action`/`cancel`, `actions[].label` | `title`, `dialog-body`, `button` (e `placeholder` no `prompt`) |
|
|
54
|
+
| filhos de `TooltipContent` | `label` |
|
|
55
|
+
| `LabelHelp.help` | `helper-text` |
|
|
56
|
+
| `emptyMessage`, `errorMessage`, `retryLabel` de `DataState`, `PageState`, `ActionList`, `ActionListDialog` e `ActionView` | `empty-state`, `error`, `button` |
|
|
57
|
+
|
|
58
|
+
O tooltip entra como `label` porque nomeia um controle icon-only: é um fragmento curto, sem
|
|
59
|
+
ponto final, e a Base não define um papel próprio para tooltip. Texto de ajuda que precisa de
|
|
60
|
+
frase completa pertence ao `help` de um campo (contrato ou `LabelHelp`), não ao tooltip.
|
|
61
|
+
|
|
62
|
+
## Alcance do inventário além das props
|
|
63
|
+
|
|
64
|
+
Quem vê o gate reprovar ou precisa de uma dispensa deve saber o que o extrator alcança sem
|
|
65
|
+
declaração adicional:
|
|
66
|
+
|
|
67
|
+
- **Diálogos imperativos.** `dialog.confirm({ title, description, action })` e as demais
|
|
68
|
+
respostas (`alert`, `prompt`, `choose`) entram no inventário como se fossem props de um
|
|
69
|
+
`ActionFormDialog`; o campo do diagnóstico é `dialog.confirm().title`,
|
|
70
|
+
`dialog.choose().actions[0].label` etc. Constantes locais resolvem normalmente. Uma função
|
|
71
|
+
que devolve template (`description: describe(nome)`) gera o diagnóstico `content` habitual e
|
|
72
|
+
se declara em `copy.dynamic` como `message-template`. Opções construídas em tempo de execução
|
|
73
|
+
ou mutadas depois de declaradas reprovam como estrutura, porque nenhum texto pode ser
|
|
74
|
+
atribuído a elas.
|
|
75
|
+
- **`LabelHelp` como filho.** `<FieldLabel>Nome<LabelHelp help="…" /></FieldLabel>` inventaria
|
|
76
|
+
`Nome` como label e a ajuda como helper-text; o ícone não torna o label opaco. Um wrapper
|
|
77
|
+
local com o mesmo nome continua opaco, porque o extrator não infere o que ele renderiza.
|
|
78
|
+
- **Rótulos em array literal local.** Quando um componente mapeado lê `item.label` (ou a chave
|
|
79
|
+
destruturada) dentro de `map`, `forEach`, `filter` ou `for…of` sobre um array literal do
|
|
80
|
+
mesmo arquivo, cada literal do array vira um texto na linha em que foi escrito, em vez de um
|
|
81
|
+
diagnóstico sobre a prop. `filter`, `slice`, `toSorted` e `toReversed` podem ficar entre o
|
|
82
|
+
array e a iteração. O limite é deliberado: o array precisa ser literal e declarado no mesmo
|
|
83
|
+
arquivo; o elemento só pode ser lido (`item.chave`), nunca passado adiante, espalhado ou
|
|
84
|
+
atribuído; o callback não pode receber o próprio array como terceiro parâmetro; e nenhum
|
|
85
|
+
elemento pode ter a chave dinâmica. Arrays importados, derivados por spread ou por
|
|
86
|
+
concatenação continuam gerando o diagnóstico da prop.
|
|
87
|
+
- **Elementos JSX genéricos.** `<ActionList<Input, Row> emptyMessage="…">` extrai igual a
|
|
88
|
+
`<ActionList emptyMessage="…">`.
|
|
53
89
|
|
|
54
90
|
Copy visual e nome acessível são superfícies cumulativas. Um `aria-label` estático nomeia
|
|
55
91
|
um controle icon-only, mas não torna aceitável nem invisível ao gate um texto visual opaco.
|
|
@@ -48,3 +48,18 @@ render(
|
|
|
48
48
|
/>,
|
|
49
49
|
)
|
|
50
50
|
```
|
|
51
|
+
|
|
52
|
+
## Propriedades de Composer
|
|
53
|
+
|
|
54
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
55
|
+
|---|---|---|---|
|
|
56
|
+
| `value` | `string` | | Texto controlado; o dono do estado é quem compõe. |
|
|
57
|
+
| `onChange` | `(value: string) => void` | | Recebe cada alteração do texto. |
|
|
58
|
+
| `onSubmit` | `() => void` | | Enter (sem Shift) ou o botão enviar; só dispara quando dá para enviar. |
|
|
59
|
+
| `onHistoryPrevious` / `onHistoryNext` | `() => boolean` | | Navegação por ↑/↓ no histórico do dono; retorne `true` quando a tecla foi consumida. |
|
|
60
|
+
| `busy` | `boolean` | `false` | Trava o composer enquanto o turno corre; o enviar vira spinner. |
|
|
61
|
+
| `submitDisabled` | `boolean` | `false` | Gate extra de envio além de vazio e `busy` (ex.: falta escolher o app). |
|
|
62
|
+
| `placeholder` | `string` | `'Escreva uma mensagem…'` | Texto de orientação do campo. |
|
|
63
|
+
| `rows` | `number` | `1` | Linhas iniciais do textarea; ele cresce com o conteúdo. |
|
|
64
|
+
| `autoFocus` | `boolean` | | Foca o campo ao montar. |
|
|
65
|
+
| `actions` | `ReactNode` | | Controles discretos à esquerda do enviar; presente, o composer vira duas linhas. |
|
|
@@ -22,7 +22,8 @@ render(
|
|
|
22
22
|
|
|
23
23
|
Use os slots quando o header precisar de composição própria. A árvore aceita exatamente um
|
|
24
24
|
`ContentHeader` e um `ContentBody` como filhos diretos. O header exige um `ContentTitle` e aceita
|
|
25
|
-
uma descrição, um
|
|
25
|
+
uma descrição, um contador (`ContentMeta`) e uma região de ações — a mesma anatomia de `PageHeader`,
|
|
26
|
+
com os mesmos slots e o mesmo layout; só o nível do heading e a hierarquia visual mudam.
|
|
26
27
|
|
|
27
28
|
```tsx preview col
|
|
28
29
|
render(
|
|
@@ -42,3 +43,18 @@ render(
|
|
|
42
43
|
|
|
43
44
|
As duas formas geram os mesmos elementos, estilos e `data-slot`. `opus check` reprova slots fora
|
|
44
45
|
do pai correto, filhos estruturais indiretos e a mistura de shorthand com composição explícita.
|
|
46
|
+
|
|
47
|
+
## Propriedades de Content
|
|
48
|
+
|
|
49
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
50
|
+
|---|---|---|---|
|
|
51
|
+
| `title` | `ReactNode` | | Forma curta: título da região (vira o heading ligado à `section`). |
|
|
52
|
+
| `count` | `number` | | Forma curta: total de itens ao lado do título — o mesmo `count` de `Page`. |
|
|
53
|
+
| `description` | `ReactNode` | | Forma curta: frase de apoio sob o título. |
|
|
54
|
+
| `actions` | `ReactNode` | | Forma curta: ações alinhadas à direita do header. |
|
|
55
|
+
| `level` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | herdado | Nível semântico do heading, independente do destaque visual. |
|
|
56
|
+
| `variant` | `'page' \| 'section'` | `'section'` | Hierarquia visual: `page` reproduz o cabeçalho de `Page`; `section` é a região dentro de uma superfície. |
|
|
57
|
+
|
|
58
|
+
Na composição explícita, `ContentHeader` recebe `ContentTitle`, `ContentMeta`, `ContentDescription` e
|
|
59
|
+
`ContentActions`, e `ContentBody` recebe o conteúdo; nenhum desses slots aceita `title` ou `level`
|
|
60
|
+
próprios — a hierarquia é declarada em `Content`. `ContentHeader` não existe fora de `Content`.
|
|
@@ -29,3 +29,11 @@ Com filhos, o valor visível fica à esquerda e o ícone à direita — clicar n
|
|
|
29
29
|
copiar (3s)
|
|
30
30
|
</Copyable>
|
|
31
31
|
```
|
|
32
|
+
|
|
33
|
+
## Propriedades de Copyable
|
|
34
|
+
|
|
35
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
36
|
+
|---|---|---|---|
|
|
37
|
+
| `value` | `string` | | O texto que vai para a área de transferência no clique. |
|
|
38
|
+
| `feedbackMs` | `number` | `1500` | Duração do estado “copiado”, em milissegundos. |
|
|
39
|
+
| `children` | `ReactNode` | | Rótulo ao lado do ícone; sem ele, o controle é só o ícone com nome acessível. |
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
## Estados
|
|
2
2
|
|
|
3
|
-
Use `DataState` para apresentar carregamento, erro, vazio e conteúdo de uma mesma consulta.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
`
|
|
3
|
+
Use `DataState` para apresentar carregamento, erro, vazio e conteúdo de uma mesma consulta. As
|
|
4
|
+
superfícies são as mesmas de `PageState`, na escala de uma seção: o carregamento é um contêiner
|
|
5
|
+
`role="status"` com o `Spinner`; o vazio compõe `Empty` com moldura sólida e `emptyMessage` como
|
|
6
|
+
título; o erro é um `Alert` de contexto `danger` com uma mensagem segura, sem expor detalhes
|
|
7
|
+
técnicos, e o botão de recuperação quando há `onRetry`. Para uma ação em andamento depois do
|
|
8
|
+
clique, use `busy` em `Button`.
|
|
7
9
|
|
|
8
10
|
```tsx preview col
|
|
9
11
|
<div className="w-full space-y-3">
|
|
10
12
|
<DataState loading>
|
|
11
13
|
<div />
|
|
12
14
|
</DataState>
|
|
13
|
-
<DataState empty
|
|
15
|
+
<DataState empty emptyMessage="Nenhum papel.">
|
|
14
16
|
<div />
|
|
15
17
|
</DataState>
|
|
16
|
-
<DataState error={{ message: 'detalhe técnico fica no console' }}>
|
|
18
|
+
<DataState error={{ message: 'detalhe técnico fica no console' }} onRetry={() => undefined}>
|
|
17
19
|
<div />
|
|
18
20
|
</DataState>
|
|
19
21
|
</div>
|
|
@@ -22,13 +24,13 @@ segura, sem expor detalhes técnicos. Para uma ação em andamento depois do cli
|
|
|
22
24
|
## Dentro de uma tabela
|
|
23
25
|
|
|
24
26
|
Em uma tabela já emoldurada, passe `colSpan` para ocupar uma linha inteira dentro de `<tbody>`. A
|
|
25
|
-
tabela continua responsável pela borda
|
|
26
|
-
|
|
27
|
+
tabela continua responsável pela borda: o `Empty` dentro dela vem sem moldura. Para uma região
|
|
28
|
+
disponível para criação ou vínculo, use `Empty` diretamente, com a moldura tracejada.
|
|
27
29
|
|
|
28
30
|
```tsx preview col
|
|
29
31
|
<table className="w-full overflow-hidden rounded-lg border border-border text-sm">
|
|
30
32
|
<tbody>
|
|
31
|
-
<DataState empty
|
|
33
|
+
<DataState empty emptyMessage="Nenhum usuário." colSpan={3}>
|
|
32
34
|
<tr>
|
|
33
35
|
<td />
|
|
34
36
|
</tr>
|
|
@@ -42,8 +44,10 @@ região disponível para criação ou vínculo, use `Empty`.
|
|
|
42
44
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
43
45
|
|---|---|---|---|
|
|
44
46
|
| `loading` | `boolean` | | Carregando (antes do conteúdo) — mostra o Spinner centralizado. |
|
|
45
|
-
| `empty` | `boolean` | | Sem itens —
|
|
46
|
-
| `
|
|
47
|
-
| `error` | `{ message?: string } \| null` | | Erro da carga — aviso calmo. A mensagem técnica não vai para tela (use
|
|
48
|
-
| `
|
|
47
|
+
| `empty` | `boolean` | | Sem itens — compõe `Empty` com o `emptyMessage`. |
|
|
48
|
+
| `emptyMessage` | `string` | `'Nada por aqui.'` | Frase do vazio (ex.: "Nenhum papel."). |
|
|
49
|
+
| `error` | `{ message?: string } \| null` | | Erro da carga — aviso calmo. A mensagem técnica não vai para tela (use `errorMessage`). |
|
|
50
|
+
| `errorMessage` | `string` | `'Não foi possível carregar.'` | Título do aviso de erro, orientado à pessoa. |
|
|
51
|
+
| `onRetry` | `() => void \| Promise<void>` | | Recuperação: mostra o botão de tentar de novo no estado de erro. |
|
|
52
|
+
| `retryLabel` | `string` | `'Tentar de novo'` | Rótulo do botão de recuperação. |
|
|
49
53
|
| `colSpan` | `number` | | Em tabela: renderiza o estado como `<tr><td colSpan>` (cabe direto no tbody). |
|
|
@@ -9,7 +9,7 @@ validação, use `Field`.
|
|
|
9
9
|
label="Estágio"
|
|
10
10
|
value={
|
|
11
11
|
<DictionaryValue
|
|
12
|
-
dict={{ keys: ['prospect', 'customer'], entries: { prospect: { label: '
|
|
12
|
+
dict={{ keys: ['prospect', 'customer'], entries: { prospect: { label: 'Prospecto' }, customer: { label: 'Cliente', context: 'success' } }, presentation: 'stage' }}
|
|
13
13
|
value="prospect"
|
|
14
14
|
/>
|
|
15
15
|
}
|
|
@@ -56,3 +56,21 @@ mais espaço para os rótulos, ajuste a variável no grupo, por exemplo com
|
|
|
56
56
|
/>
|
|
57
57
|
</DetailGroup>
|
|
58
58
|
```
|
|
59
|
+
|
|
60
|
+
## Propriedades de DetailGroup
|
|
61
|
+
|
|
62
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
63
|
+
|---|---|---|---|
|
|
64
|
+
| `variant` | `'plain' \| 'framed'` | `'plain'` | `framed` aplica a superfície e a moldura canônicas ao conjunto. |
|
|
65
|
+
| `dividers` | `boolean` | `false` | Hairlines somente entre os campos, sem exigir moldura externa. |
|
|
66
|
+
| `columns` | `1 \| 2 \| 3 \| 4 \| 'auto'` | `1` | Colunas responsivas ou distribuição automática por largura mínima. |
|
|
67
|
+
| `orientation` | `'vertical' \| 'horizontal'` | `'vertical'` | Chave sobre o valor ou ao lado dele em cada campo. |
|
|
68
|
+
|
|
69
|
+
## Propriedades de DetailField
|
|
70
|
+
|
|
71
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| `label` | `ReactNode` | | A chave do par. |
|
|
74
|
+
| `value` | `ReactNode` | | O valor; `null`, `undefined` e string vazia renderizam a ausência, `0` e `false` seguem como valores. |
|
|
75
|
+
| `icon` | `ReactNode` | | Ícone decorativo antes do par chave/valor. |
|
|
76
|
+
| `empty` | `ReactNode` | `“Não informado”` | O que a ausência significa neste campo: um rótulo ou um nó próprio. |
|
|
@@ -305,7 +305,7 @@ avançada; ele recebe `children` e `container` conforme o portal do Radix.
|
|
|
305
305
|
## Propriedades de DialogHost
|
|
306
306
|
|
|
307
307
|
`DialogHost` não recebe propriedades. Monte uma instância no shell para atender toda a API
|
|
308
|
-
imperativa.
|
|
308
|
+
imperativa.
|
|
309
309
|
|
|
310
310
|
## Opções de dialog.alert
|
|
311
311
|
|
|
@@ -363,6 +363,3 @@ imperativa. `ConfirmHost` permanece como alias de migração.
|
|
|
363
363
|
| `context` | `ButtonContext` | Última ação: `primary`; demais: `neutral` | Define o significado semântico. |
|
|
364
364
|
| `variant` | `ButtonVariant` | Última ação: `solid`; demais: `ghost` | Define o tratamento visual. |
|
|
365
365
|
| `disabled` | `boolean` | `false` | Impede a escolha desta ação. |
|
|
366
|
-
|
|
367
|
-
`confirm()` e `ConfirmHost` continuam disponíveis apenas como aliases de migração para
|
|
368
|
-
`dialog.confirm()` e `DialogHost`.
|
|
@@ -8,7 +8,7 @@ sem perder o rótulo visível.
|
|
|
8
8
|
value="pj"
|
|
9
9
|
/>
|
|
10
10
|
<DictionaryValue
|
|
11
|
-
dict={{ keys: ['prospect', 'customer'], entries: { prospect: { label: '
|
|
11
|
+
dict={{ keys: ['prospect', 'customer'], entries: { prospect: { label: 'Prospecto' }, customer: { label: 'Cliente', context: 'success' } }, presentation: 'stage' }}
|
|
12
12
|
value="customer"
|
|
13
13
|
/>
|
|
14
14
|
<DictionaryValue
|
|
@@ -37,7 +37,7 @@ export const customerKindDict = t.dict(
|
|
|
37
37
|
|
|
38
38
|
export const customerStageDict = t.dict(
|
|
39
39
|
{
|
|
40
|
-
prospect: { label: '
|
|
40
|
+
prospect: { label: 'Prospecto', description: 'Relacionamento ainda em prospecção.' },
|
|
41
41
|
customer: { label: 'Cliente', context: 'success' },
|
|
42
42
|
},
|
|
43
43
|
{ doc: 'Estágio comercial atual da parte.', presentation: 'stage' },
|
|
@@ -106,6 +106,13 @@ dicionário registrado no provider: `{ key: 'source', label: 'Fonte', dictionary
|
|
|
106
106
|
Dimensões independentes (tipo e estágio, por exemplo) ficam em colunas distintas; não empilhar
|
|
107
107
|
uma sob a outra como texto secundário.
|
|
108
108
|
|
|
109
|
+
## useDicts
|
|
110
|
+
|
|
111
|
+
`useDicts()` devolve os dicionários registrados em `OpusProvider` (`dicts`), chaveados pela `ref`.
|
|
112
|
+
É o que `ActionList`, `ActionForm` e `DictionaryValue` consultam para resolver
|
|
113
|
+
`options: { kind: 'dictionary', ref }` e colunas nomeadas por `dictionary`; fora do provider, o
|
|
114
|
+
resultado é vazio e a resolução cai na meta do `t.dict` que viaja no schema.
|
|
115
|
+
|
|
109
116
|
## Propriedades de DictionaryValue
|
|
110
117
|
|
|
111
118
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
@@ -67,3 +67,11 @@ já monta.
|
|
|
67
67
|
| --- | --- | --- | --- |
|
|
68
68
|
| `position` | `'bottom' \| 'bottom-left' \| 'bottom-right'` | `'bottom'` | Aresta do contêiner onde a barra se ancora. |
|
|
69
69
|
| `label` | `string` | | Nome acessível da barra. |
|
|
70
|
+
|
|
71
|
+
## Propriedades de SurfaceStatus
|
|
72
|
+
|
|
73
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
74
|
+
| --- | --- | --- | --- |
|
|
75
|
+
| `position` | `'top-right' \| 'top-left'` | `'top-right'` | Canto da superfície onde o estado se ancora. |
|
|
76
|
+
| `context` | `'neutral' \| 'info' \| 'success' \| 'warning' \| 'danger'` | `'neutral'` | O que o estado comunica; tinge borda e texto pela família semântica. |
|
|
77
|
+
| `actions` | `ReactNode` | | Ações do recurso aberto, fora da região viva. |
|
|
@@ -15,3 +15,11 @@ acessível. Sem `label`, o ponto é decorativo.
|
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Use `Badge` quando o estado precisar permanecer legível sem depender do contexto ao redor.
|
|
18
|
+
|
|
19
|
+
## Propriedades de Dot
|
|
20
|
+
|
|
21
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| `context` | `'neutral' \| 'primary' \| 'info' \| 'success' \| 'warning' \| 'danger'` | `'neutral'` | O significado da cor. |
|
|
24
|
+
| `variant` | `'solid' \| 'outline'` | `'solid'` | Ponto preenchido ou só contornado. |
|
|
25
|
+
| `label` | `string` | | Nome acessível quando a cor comunica estado; sem ele o ponto é decorativo (`aria-hidden`). |
|
|
@@ -53,8 +53,8 @@ título e descrição agrupados no centro.
|
|
|
53
53
|
|
|
54
54
|
## Mídia sem moldura
|
|
55
55
|
|
|
56
|
-
`EmptyMedia variant
|
|
57
|
-
tenham presença visual própria.
|
|
56
|
+
`EmptyMedia` sem `variant` (o padrão, `default`) não desenha fundo. Use essa forma para ilustrações
|
|
57
|
+
ou mídias que tenham presença visual própria.
|
|
58
58
|
|
|
59
59
|
```tsx preview col
|
|
60
60
|
<Empty>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
2
|
+
title: Primeiros passos
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
#
|
|
5
|
+
# Primeiros passos
|
|
6
6
|
|
|
7
7
|
O Opus ajuda cliente e servidor a preservar as mesmas regras à medida que uma aplicação
|
|
8
8
|
evolui. Entidades e contratos de action ficam em uma camada compartilhada; o runtime, a UI e
|