@softize/opus 19.0.0 → 20.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 +193 -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/0023-surfaces-share-one-anatomy-and-two-layouts.md +5 -0
- package/docs/adr/0024-fill-height-propagates-by-context.md +118 -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 +15 -3
- package/src/ui/components/patterns/fill-region.ts +150 -0
- package/src/ui/components/patterns/list.tsx +89 -78
- 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/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/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 +41 -10
- package/src/ui/components/primitives/drawer.tsx +9 -1
- 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 +134 -52
- 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 +31 -7
- 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 +28 -5
- 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 +31 -31
- package/src/vite/design.ts +16 -4
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Use `IconPicker` para selecionar um ícone por seu nome em kebab-case. O consumidor renderiza o
|
|
2
|
-
valor com a mesma paleta, por exemplo `iconPickerIcons[name] ?? FallbackIcon`. Selecionar novamente o
|
|
3
|
-
ícone atual limpa o valor.
|
|
4
|
-
|
|
5
1
|
## Escolher na paleta padrão
|
|
6
2
|
|
|
3
|
+
Use `IconPicker` quando a pessoa puder escolher o ícone que identifica um registro, como um
|
|
4
|
+
relatório ou um painel. A lista abre em um popover com busca, e o valor guardado é o nome do ícone em
|
|
5
|
+
kebab-case, como `chart-line`. Selecionar novamente o ícone atual limpa o valor.
|
|
6
|
+
|
|
7
7
|
```tsx preview col md
|
|
8
8
|
const [icon, setIcon] = useState('chart-line')
|
|
9
9
|
|
|
@@ -15,10 +15,11 @@ render(
|
|
|
15
15
|
)
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## Apresentar o ícone escolhido
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
O valor é somente um nome: quem apresenta o registro renderiza o ícone com a mesma paleta. A paleta
|
|
21
|
+
padrão é exportada como `iconPickerIcons`; use-a em listas, cards e árvores, com um ícone de reserva
|
|
22
|
+
para nomes que não existam mais, como em `iconPickerIcons[name] ?? FileText`.
|
|
22
23
|
|
|
23
24
|
```tsx preview col md
|
|
24
25
|
const [icon, setIcon] = useState('store')
|
|
@@ -27,10 +28,14 @@ const SelectedIcon = iconPickerIcons[icon] ?? FileText
|
|
|
27
28
|
render(
|
|
28
29
|
<div className="flex items-center gap-3">
|
|
29
30
|
<IconPicker value={icon} onChange={setIcon} className="w-56" />
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
<Item variant="outline" size="sm">
|
|
32
|
+
<ItemMedia variant="icon">
|
|
33
|
+
<SelectedIcon />
|
|
34
|
+
</ItemMedia>
|
|
35
|
+
<ItemHeader>
|
|
36
|
+
<ItemTitle>Painel comercial</ItemTitle>
|
|
37
|
+
</ItemHeader>
|
|
38
|
+
</Item>
|
|
34
39
|
</div>,
|
|
35
40
|
)
|
|
36
41
|
```
|
|
@@ -62,5 +67,6 @@ render(
|
|
|
62
67
|
| `onChange` | `(name: string) => void` | | Recebe o nome escolhido. |
|
|
63
68
|
| `icons` | `Record<string, LucideIcon>` | `iconPickerIcons` | Paleta nome → componente. |
|
|
64
69
|
| `placeholder` | `string` | `'Selecione um ícone…'` | Texto do gatilho sem seleção. |
|
|
65
|
-
| `disabled` | `boolean` | | Desabilita o gatilho. |
|
|
66
|
-
| `
|
|
70
|
+
| `disabled` | `boolean` | `false` | Desabilita o gatilho. |
|
|
71
|
+
| `className` | `string` | | Classes do gatilho, em geral para ajustar a largura. Sem elas, o gatilho ocupa toda a largura disponível. |
|
|
72
|
+
| `id`, `aria-invalid`, `aria-describedby` | `string`, `boolean`, `string` | | Integração com `Field` e `ActionForm`: o gatilho recebe a identidade do campo, o estado inválido e a mensagem associada. Com `aria-invalid`, a moldura assume o contexto de erro, como no `Input`. |
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
## Moldura decorativa para ícone
|
|
2
2
|
|
|
3
3
|
Use `IconTile` quando um ícone precisar de uma pequena superfície para ganhar hierarquia em uma
|
|
4
|
-
legenda, item ou resumo. O componente não é interativo; para uma ação, use `Button`
|
|
5
|
-
ícone e um nome acessível.
|
|
4
|
+
legenda, item ou resumo. O componente não é interativo; para uma ação, use [`Button`](/ui/button)
|
|
5
|
+
com tamanho de ícone e um nome acessível.
|
|
6
6
|
|
|
7
7
|
```tsx preview row
|
|
8
8
|
<IconTile size="xs"><UserRound /></IconTile>
|
|
@@ -16,7 +16,7 @@ uma classe `size-*` preserva a própria medida.
|
|
|
16
16
|
## Em uma legenda
|
|
17
17
|
|
|
18
18
|
Slots de ícone não criam a moldura automaticamente. Componha `IconTile` somente quando ela fizer
|
|
19
|
-
sentido para a superfície.
|
|
19
|
+
sentido para a superfície, como na legenda de um [`Content`](/ui/content) emoldurado.
|
|
20
20
|
|
|
21
21
|
```tsx preview col md
|
|
22
22
|
<Content
|
|
@@ -32,11 +32,16 @@ sentido para a superfície.
|
|
|
32
32
|
</span>
|
|
33
33
|
}
|
|
34
34
|
>
|
|
35
|
-
<FieldGroup
|
|
35
|
+
<FieldGroup>
|
|
36
|
+
<Field>
|
|
37
|
+
<FieldLabel htmlFor="icon-tile-plate">Placa</FieldLabel>
|
|
38
|
+
<Input id="icon-tile-plate" />
|
|
39
|
+
</Field>
|
|
40
|
+
</FieldGroup>
|
|
36
41
|
</Content>
|
|
37
42
|
```
|
|
38
43
|
|
|
39
|
-
## Propriedades
|
|
44
|
+
## Propriedades de IconTile
|
|
40
45
|
|
|
41
46
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
42
47
|
| ----------- | ------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------- |
|
|
@@ -45,3 +50,21 @@ sentido para a superfície.
|
|
|
45
50
|
| `variant` | `'subtle' \| 'outline'` | `'subtle'` | Usa preenchimento tonal ou acrescenta borda. |
|
|
46
51
|
|
|
47
52
|
As demais propriedades são as propriedades nativas de `span`.
|
|
53
|
+
|
|
54
|
+
## Função iconTileVariants
|
|
55
|
+
|
|
56
|
+
`iconTileVariants({ context, variant, size })` retorna as classes da moldura para um elemento que
|
|
57
|
+
não é renderizado pelo `IconTile`. Os padrões são os mesmos do componente: `neutral`, `subtle` e
|
|
58
|
+
`default`.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
function iconTileVariants(options?: {
|
|
62
|
+
context?: IconTileContext | null
|
|
63
|
+
variant?: IconTileVariant | null
|
|
64
|
+
size?: IconTileSize | null
|
|
65
|
+
}): string
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`resolveIconTileStyle` continua exportado, mas está depreciado e sai em uma próxima versão maior. Ele
|
|
69
|
+
só preenche os padrões acima, que `IconTile` e `iconTileVariants` já aplicam. Código novo usa um dos
|
|
70
|
+
dois.
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
## Código em uma sequência
|
|
2
2
|
|
|
3
|
-
`
|
|
4
|
-
|
|
3
|
+
Use `InputOTP` quando a pessoa precisar digitar um código curto recebido por outro canal, como a
|
|
4
|
+
confirmação de acesso enviada por e-mail ou por um aplicativo autenticador. Cada caractere ocupa uma
|
|
5
|
+
posição própria, e o foco avança sozinho durante a digitação ou ao colar o código inteiro.
|
|
6
|
+
|
|
7
|
+
`maxLength` define o comprimento. Cada `InputOTPSlot` recebe o índice de uma posição, e
|
|
8
|
+
`InputOTPGroup` reúne as posições em um bloco. `pattern` restringe os caracteres aceitos; no
|
|
9
|
+
exemplo, somente dígitos.
|
|
5
10
|
|
|
6
11
|
```tsx preview
|
|
7
|
-
<InputOTP maxLength={6}>
|
|
12
|
+
<InputOTP maxLength={6} pattern="^\d+$">
|
|
8
13
|
<InputOTPGroup>
|
|
9
14
|
<InputOTPSlot index={0} />
|
|
10
15
|
<InputOTPSlot index={1} />
|
|
@@ -40,14 +45,14 @@ Use `InputOTPSeparator` entre grupos para dividir visualmente o código. Os índ
|
|
|
40
45
|
## Controlado
|
|
41
46
|
|
|
42
47
|
Use `value` e `onChange` quando o estado externo precisar validar o comprimento antes de liberar a
|
|
43
|
-
próxima ação.
|
|
48
|
+
próxima ação. `onComplete` é chamado quando todas as posições estão preenchidas.
|
|
44
49
|
|
|
45
50
|
```tsx preview col-start
|
|
46
51
|
const [code, setCode] = useState('')
|
|
47
52
|
|
|
48
53
|
render(
|
|
49
54
|
<>
|
|
50
|
-
<InputOTP maxLength={6} value={code} onChange={setCode}>
|
|
55
|
+
<InputOTP maxLength={6} pattern="^\d+$" value={code} onChange={setCode}>
|
|
51
56
|
<InputOTPGroup>
|
|
52
57
|
<InputOTPSlot index={0} />
|
|
53
58
|
<InputOTPSlot index={1} />
|
|
@@ -64,6 +69,41 @@ render(
|
|
|
64
69
|
)
|
|
65
70
|
```
|
|
66
71
|
|
|
72
|
+
## Código recusado
|
|
73
|
+
|
|
74
|
+
Quando o código for recusado, declare `aria-invalid` no `InputOTP`, que o repassa ao campo que
|
|
75
|
+
recebe a digitação, para que leitores de tela anunciem o erro. Declare-o também em cada
|
|
76
|
+
`InputOTPSlot` para aplicar a borda de erro e explique o problema em um texto associado por
|
|
77
|
+
`aria-describedby`. `disabled` no `InputOTP` bloqueia a digitação e
|
|
78
|
+
esmaece o conjunto, por exemplo enquanto o código é conferido.
|
|
79
|
+
|
|
80
|
+
```tsx preview col-start
|
|
81
|
+
const [code, setCode] = useState('1234')
|
|
82
|
+
|
|
83
|
+
render(
|
|
84
|
+
<>
|
|
85
|
+
<InputOTP
|
|
86
|
+
maxLength={4}
|
|
87
|
+
pattern="^\d+$"
|
|
88
|
+
value={code}
|
|
89
|
+
onChange={setCode}
|
|
90
|
+
aria-invalid
|
|
91
|
+
aria-describedby="otp-error"
|
|
92
|
+
>
|
|
93
|
+
<InputOTPGroup>
|
|
94
|
+
<InputOTPSlot index={0} aria-invalid />
|
|
95
|
+
<InputOTPSlot index={1} aria-invalid />
|
|
96
|
+
<InputOTPSlot index={2} aria-invalid />
|
|
97
|
+
<InputOTPSlot index={3} aria-invalid />
|
|
98
|
+
</InputOTPGroup>
|
|
99
|
+
</InputOTP>
|
|
100
|
+
<p id="otp-error" className="text-sm text-context-danger-emphasis">
|
|
101
|
+
Código expirado. Peça um novo código para continuar.
|
|
102
|
+
</p>
|
|
103
|
+
</>,
|
|
104
|
+
)
|
|
105
|
+
```
|
|
106
|
+
|
|
67
107
|
## Propriedades de InputOTP
|
|
68
108
|
|
|
69
109
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
@@ -72,11 +112,22 @@ render(
|
|
|
72
112
|
| `value` | `string` | | Código no modo controlado. Use com `onChange`. |
|
|
73
113
|
| `onChange` | `(value: string) => void` | | Chamado a cada entrada com o código acumulado. |
|
|
74
114
|
| `onComplete` | `(value: string) => void` | | Chamado quando o código atinge `maxLength`. |
|
|
75
|
-
| `pattern` | `string` | | Expressão regular que o código precisa satisfazer; entradas que não casam são descartadas. Sem `pattern`, qualquer caractere é aceito, inclusive letras. Para somente dígitos, use `'^\\d+$'`. |
|
|
76
|
-
| `disabled` | `boolean` | `false` | Desabilita a digitação
|
|
115
|
+
| `pattern` | `string` | | Expressão regular que o código precisa satisfazer; entradas que não casam são descartadas. Sem `pattern`, qualquer caractere é aceito, inclusive letras. Para somente dígitos, use `pattern="^\d+$"` em JSX; em uma string JavaScript, a barra é escapada: `'^\\d+$'`. |
|
|
116
|
+
| `disabled` | `boolean` | `false` | Desabilita a digitação e esmaece todo o conjunto. |
|
|
117
|
+
| `containerClassName` | `string` | | Classes do contêiner que alinha grupos e separadores. `className` vai para o campo de texto oculto que recebe a digitação. |
|
|
77
118
|
|
|
78
119
|
## Propriedades de InputOTPSlot
|
|
79
120
|
|
|
80
121
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
81
122
|
|---|---|---|---|
|
|
82
123
|
| `index` | `number` | | Posição do caractere, começando em zero. |
|
|
124
|
+
| `aria-invalid` | `boolean` | | Aplica a borda de erro à posição. |
|
|
125
|
+
|
|
126
|
+
## Propriedades de InputOTPGroup
|
|
127
|
+
|
|
128
|
+
`InputOTPGroup` não tem propriedades próprias e aceita as props nativas de `<div>`.
|
|
129
|
+
|
|
130
|
+
## Propriedades de InputOTPSeparator
|
|
131
|
+
|
|
132
|
+
`InputOTPSeparator` desenha um traço com `role="separator"` entre grupos. Não tem propriedades
|
|
133
|
+
próprias e aceita as props nativas de `<div>`.
|
|
@@ -99,8 +99,8 @@ Use `InputGroup` quando o campo precisar combinar vários adornos, prefixos, suf
|
|
|
99
99
|
|
|
100
100
|
### Com ícone e ação
|
|
101
101
|
|
|
102
|
-
`InputGroupAddon` ancora os adornos nas extremidades.
|
|
103
|
-
o foco para o campo
|
|
102
|
+
`InputGroupAddon` ancora os adornos nas extremidades. Um clique em uma área inerte do addon, fora
|
|
103
|
+
dos botões, transfere o foco para o campo, seja `InputGroupInput` ou `InputGroupTextarea`.
|
|
104
104
|
|
|
105
105
|
```tsx preview col
|
|
106
106
|
<InputGroup>
|
|
@@ -149,11 +149,30 @@ Com `InputGroupTextarea`, um addon em `block-end` forma uma região de ações a
|
|
|
149
149
|
</InputGroup>
|
|
150
150
|
```
|
|
151
151
|
|
|
152
|
+
### Estados do grupo
|
|
153
|
+
|
|
154
|
+
`aria-invalid` no controle interno aplica o contexto de erro à moldura inteira. Para desabilitar,
|
|
155
|
+
basta declarar `disabled` no controle: o campo esmaece pelo próprio estado e os addons acompanham.
|
|
156
|
+
Um `InputGroupButton` desabilitado não apaga o grupo. Quando os addons precisarem esmaecer com o
|
|
157
|
+
controle ativo, declare `data-disabled="true"` no `InputGroup`.
|
|
158
|
+
|
|
159
|
+
```tsx preview col
|
|
160
|
+
<InputGroup>
|
|
161
|
+
<InputGroupAddon><AtSign /></InputGroupAddon>
|
|
162
|
+
<InputGroupInput aria-invalid defaultValue="joao@" placeholder="E-mail do responsável" />
|
|
163
|
+
</InputGroup>
|
|
164
|
+
<InputGroup>
|
|
165
|
+
<InputGroupAddon><AtSign /></InputGroupAddon>
|
|
166
|
+
<InputGroupInput disabled defaultValue="joao@softize.com.br" />
|
|
167
|
+
</InputGroup>
|
|
168
|
+
```
|
|
169
|
+
|
|
152
170
|
### Propriedades de InputGroup
|
|
153
171
|
|
|
154
172
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
155
173
|
|---|---|---|---|
|
|
156
174
|
| `shape` | `'default' \| 'pill'` | `'default'` | Geometria da moldura compartilhada. |
|
|
175
|
+
| `data-disabled` | `'true' \| 'false'` | | Com `true`, esmaece os addons mesmo com o controle ativo. Com o controle desabilitado, os addons já esmaecem sem ele. |
|
|
157
176
|
|
|
158
177
|
### Propriedades de InputGroupAddon
|
|
159
178
|
|
|
@@ -165,7 +184,7 @@ Com `InputGroupTextarea`, um addon em `block-end` forma uma região de ações a
|
|
|
165
184
|
|
|
166
185
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
167
186
|
|---|---|---|---|
|
|
168
|
-
| `size` | `'xs' \| 'sm' \| 'icon-xs' \| 'icon-sm'` | `'xs'` | O subconjunto da escala única que cabe
|
|
187
|
+
| `size` | `'xs' \| 'sm' \| 'icon-xs' \| 'icon-sm'` | `'xs'` | O subconjunto da escala única que cabe em um campo (1.5 · 2 · 1.5 · 1.75rem); os `icon-*` são quadrados. |
|
|
169
188
|
| `context` | `'neutral' \| 'primary' \| 'danger'` | `'neutral'` | Contexto semântico herdado de Button. Com `variant` `solid` ou `subtle` sem contexto declarado, o padrão passa a `'primary'`. |
|
|
170
189
|
| `variant` | `'solid' \| 'subtle' \| 'outline' \| 'ghost' \| 'link'` | `'ghost'` | Tratamento visual; use `solid` quando a ação precisar de ênfase. |
|
|
171
190
|
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
## Linha composta
|
|
2
2
|
|
|
3
|
+
Use `Item` para uma linha de lista que identifica algo — um repositório, uma pessoa, uma
|
|
4
|
+
configuração — e oferece o que fazer com ele. Para dados em colunas comparáveis, use
|
|
5
|
+
[`Table`](/ui/table); para uma coleção carregada por uma action `kind: 'list'`, use
|
|
6
|
+
[`ActionList`](/ui/action-list).
|
|
7
|
+
|
|
3
8
|
A composição completa usa `ItemMedia` à esquerda, `ItemHeader` (`ItemTitle` +
|
|
4
|
-
`ItemDescription`) no meio e `ItemActions` à direita.
|
|
9
|
+
`ItemDescription`) no meio e `ItemActions` à direita. A descrição mostra no máximo duas linhas e
|
|
10
|
+
termina em reticências quando passa disso. Ícone e imagem mantêm uma moldura quadrada
|
|
5
11
|
alinhada ao topo, mesmo quando a descrição ocupa mais linhas. `variant="outline"` desenha a borda.
|
|
6
12
|
O tamanho padrão usa corpo produtivo, `0.75rem` de padding e `0.75rem` entre regiões. `size="sm"`
|
|
7
13
|
mantém o padding horizontal, reduz o padding vertical para `0.5rem` e o espaço entre regiões para
|
|
@@ -28,7 +34,10 @@ mantém o padding horizontal, reduz o padding vertical para `0.5rem` e o espaço
|
|
|
28
34
|
|
|
29
35
|
## Lista emoldurada
|
|
30
36
|
|
|
31
|
-
`ItemGroup variant="framed"` aplica a superfície canônica. Os divisores continuam explícitos com
|
|
37
|
+
`ItemGroup variant="framed"` aplica a superfície canônica. Os divisores continuam explícitos com
|
|
38
|
+
`ItemSeparator`, tanto no modo `framed` quanto no `plain` — o padrão para listas de repositórios,
|
|
39
|
+
agentes ou sessões. O grupo é anunciado como lista, e cada `Item` dentro dele, como um item da
|
|
40
|
+
lista.
|
|
32
41
|
|
|
33
42
|
```tsx preview col
|
|
34
43
|
<ItemGroup variant="framed">
|
|
@@ -38,7 +47,7 @@ mantém o padding horizontal, reduz o padding vertical para `0.5rem` e o espaço
|
|
|
38
47
|
</ItemMedia>
|
|
39
48
|
<ItemHeader>
|
|
40
49
|
<ItemTitle>empresa-x-web</ItemTitle>
|
|
41
|
-
<ItemDescription>
|
|
50
|
+
<ItemDescription>Frontend do workspace Empresa X.</ItemDescription>
|
|
42
51
|
</ItemHeader>
|
|
43
52
|
<ItemActions>
|
|
44
53
|
<Badge context="success">Sincronizado</Badge>
|
|
@@ -62,7 +71,9 @@ mantém o padding horizontal, reduz o padding vertical para `0.5rem` e o espaço
|
|
|
62
71
|
|
|
63
72
|
## Clicável e compacto
|
|
64
73
|
|
|
65
|
-
`asChild` funde o Item em um `<a
|
|
74
|
+
`asChild` funde o Item em um `<a>`: a linha inteira vira alvo e o fundo muda ao passar o ponteiro.
|
|
75
|
+
`size="sm"` aperta o respiro; `ItemMedia` na variante padrão recebe um [`Avatar`](/ui/avatar), que
|
|
76
|
+
já traz a própria moldura.
|
|
66
77
|
|
|
67
78
|
```tsx preview col
|
|
68
79
|
<Item asChild size="sm" variant="outline">
|
|
@@ -103,6 +114,36 @@ Use `ItemBody` quando a linha também apresenta um valor ou controle que não pe
|
|
|
103
114
|
`ItemContent` permanece exportado apenas por compatibilidade e está obsoleto. Código novo
|
|
104
115
|
usa `ItemHeader` ou `ItemBody` conforme o papel do conteúdo.
|
|
105
116
|
|
|
117
|
+
## Rodapé
|
|
118
|
+
|
|
119
|
+
`ItemFooter` ocupa uma linha inteira abaixo das demais regiões, com o conteúdo distribuído entre as
|
|
120
|
+
pontas. Use-o para metadados ou estado que complementam a linha.
|
|
121
|
+
|
|
122
|
+
```tsx preview col
|
|
123
|
+
<Item variant="outline">
|
|
124
|
+
<ItemMedia variant="icon">
|
|
125
|
+
<FolderGit2 />
|
|
126
|
+
</ItemMedia>
|
|
127
|
+
<ItemHeader>
|
|
128
|
+
<ItemTitle>empresa-x-api</ItemTitle>
|
|
129
|
+
<ItemDescription>Repositório do backend do workspace Empresa X.</ItemDescription>
|
|
130
|
+
</ItemHeader>
|
|
131
|
+
<ItemActions>
|
|
132
|
+
<Button size="sm" variant="outline">Abrir</Button>
|
|
133
|
+
</ItemActions>
|
|
134
|
+
<ItemFooter>
|
|
135
|
+
<span className="text-xs text-muted-foreground">Atualizado há 2 horas</span>
|
|
136
|
+
<Badge context="success">Sincronizado</Badge>
|
|
137
|
+
</ItemFooter>
|
|
138
|
+
</Item>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Composições que lançam erro
|
|
142
|
+
|
|
143
|
+
As partes conferem o próprio lugar ao renderizar. `ItemMedia`, `ItemHeader`, `ItemBody`,
|
|
144
|
+
`ItemActions` e `ItemFooter` lançam erro fora de um `Item`; `ItemTitle` e `ItemDescription` lançam
|
|
145
|
+
erro fora de um `ItemHeader` ou do `ItemContent` obsoleto. A mensagem nomeia o pai esperado.
|
|
146
|
+
|
|
106
147
|
## Propriedades de Item
|
|
107
148
|
|
|
108
149
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
@@ -117,12 +158,18 @@ usa `ItemHeader` ou `ItemBody` conforme o papel do conteúdo.
|
|
|
117
158
|
|---|---|---|---|
|
|
118
159
|
| `variant` | `'plain' \| 'framed'` | `'plain'` | `framed` aplica moldura e superfície; os divisores permanecem explícitos nos dois modos. |
|
|
119
160
|
|
|
161
|
+
O grupo renderiza um `div` com `role="list"` e aceita as props nativas desse elemento.
|
|
162
|
+
|
|
120
163
|
## Propriedades de ItemMedia
|
|
121
164
|
|
|
122
165
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
123
166
|
|---|---|---|---|
|
|
124
167
|
| `variant` | `'default' \| 'icon' \| 'image'` | `'default'` | Define mídia livre ou uma moldura quadrada para ícone ou imagem. |
|
|
125
168
|
|
|
169
|
+
## Propriedades das demais partes
|
|
170
|
+
|
|
126
171
|
`ItemHeader`, `ItemTitle`, `ItemDescription`, `ItemBody`, `ItemActions`, `ItemFooter` e
|
|
127
|
-
`ItemSeparator`
|
|
128
|
-
|
|
172
|
+
`ItemSeparator` não têm props próprias. Cada um aceita as props nativas do elemento que renderiza:
|
|
173
|
+
`div`, exceto `ItemDescription`, que renderiza `p`, e `ItemSeparator`, que aceita as props de
|
|
174
|
+
[`Separator`](/ui/separator). O `ItemContent` obsoleto preserva esse mesmo contrato por
|
|
175
|
+
compatibilidade.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
## Uma tecla
|
|
2
2
|
|
|
3
3
|
Use um `Kbd` para representar cada tecla. O componente apresenta o atalho; a captura do teclado
|
|
4
|
-
continua no handler do aplicativo.
|
|
4
|
+
continua no handler do aplicativo. Em um item de [`Menu`](/ui/menu), o atalho usa `MenuShortcut`.
|
|
5
5
|
|
|
6
6
|
```tsx preview
|
|
7
7
|
<Kbd>Esc</Kbd>
|
|
@@ -29,6 +29,7 @@ reconhecível que o nome da tecla.
|
|
|
29
29
|
<Kbd>
|
|
30
30
|
<CommandIcon />
|
|
31
31
|
</Kbd>
|
|
32
|
+
<span className="text-xs text-muted-foreground">+</span>
|
|
32
33
|
<Kbd>
|
|
33
34
|
<CornerDownLeft />
|
|
34
35
|
</Kbd>
|
|
@@ -69,3 +70,6 @@ ação antes de informar seu atalho.
|
|
|
69
70
|
|---|---|---|---|
|
|
70
71
|
| `children` | `React.ReactNode` | | Teclas da combinação e conectores, como `+`, entre elas. |
|
|
71
72
|
| `className` | `string` | | Classes adicionais aplicadas ao agrupador. |
|
|
73
|
+
|
|
74
|
+
`KbdGroup` renderiza um `kbd` que envolve as teclas, a marcação HTML de uma combinação, e aceita as
|
|
75
|
+
props desse elemento.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
## Com campo de texto
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use `Label` para nomear um controle de formulário. Associe `htmlFor` ao `id` do controle: o rótulo
|
|
4
|
+
passa a ser o nome acessível do campo, e clicar nele move o foco para o controle. Em formulários
|
|
5
|
+
com ajuda e erro, [`Field`](/ui/field) organiza o rótulo junto dos demais elementos.
|
|
4
6
|
|
|
5
7
|
```tsx preview col md
|
|
6
8
|
<div className="grid gap-2">
|
|
@@ -23,8 +25,11 @@ também alterna a seleção.
|
|
|
23
25
|
|
|
24
26
|
## Par desabilitado
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
O rótulo esmaece junto com um controle desabilitado quando é escrito logo depois dele, no mesmo
|
|
29
|
+
contêiner, como nos pares com `Checkbox`, `Switch` e `RadioGroupItem`. Nessa posição, o estilo lê o
|
|
30
|
+
estado do controle vizinho. Um rótulo escrito antes do controle, como acima de um `Input`, não
|
|
31
|
+
acompanha o estado dessa forma; nesse caso, coloque o par em um [`Field`](/ui/field) com
|
|
32
|
+
`data-disabled="true"`. `Label` e `FieldLabel` esmaecem com ele.
|
|
28
33
|
|
|
29
34
|
```tsx preview
|
|
30
35
|
<div className="flex items-center gap-2">
|
|
@@ -38,4 +43,8 @@ uma classe adicional.
|
|
|
38
43
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
39
44
|
|---|---|---|---|
|
|
40
45
|
| `htmlFor` | `string` | | O `id` do controle rotulado; clicar no rótulo foca o controle. |
|
|
41
|
-
| `className` | `string` | |
|
|
46
|
+
| `className` | `string` | | Classes somadas ao estilo padrão. |
|
|
47
|
+
|
|
48
|
+
`Label` aceita as props nativas de `<label>`. Ele esmaece quando vem logo depois de um controle
|
|
49
|
+
desabilitado, dentro de um `Field` com `data-disabled="true"` ou quando um ancestral com a classe
|
|
50
|
+
`group` declara `data-disabled="true"`.
|
|
@@ -31,8 +31,8 @@ import { pinoLogger } from '@softize/opus/log/pino'
|
|
|
31
31
|
const logger = pinoLogger({ logger: pino({ level: 'info' }) })
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
O `pino`
|
|
35
|
-
|
|
34
|
+
O app configura o `pino` (nível, transport e redact), e o driver apenas o conecta ao runtime. `pino`
|
|
35
|
+
é dependência opcional: só precisa ser instalado por quem usa o driver.
|
|
36
36
|
|
|
37
37
|
## No runtime
|
|
38
38
|
|
|
@@ -42,7 +42,7 @@ const runtime = createRuntime({
|
|
|
42
42
|
logger,
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
-
// No handler: ctx.log já
|
|
45
|
+
// No handler: ctx.log já traz o request ID e a action, adicionados com child().
|
|
46
46
|
handler: async (ctx, input) => {
|
|
47
47
|
ctx.log.info('emitindo nota', { valor: input.valor })
|
|
48
48
|
return repo.create(input)
|
|
@@ -51,5 +51,5 @@ handler: async (ctx, input) => {
|
|
|
51
51
|
|
|
52
52
|
## Limites atuais
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
O contrato cobre os níveis e `child`. Amostragem e transports ficam no `pino` que o app configura.
|
|
55
|
+
O único driver disponível é o `pino`.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
## Fonte e resultado
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Use `Markdown` para exibir texto formatado que chega como Markdown, como a resposta de um agente
|
|
4
|
+
no [`Chat`](/ui/chat) ou uma descrição escrita por uma pessoa. Passe o texto em `content`. O
|
|
5
|
+
exemplo mostra primeiro o resultado renderizado e, depois, o Markdown que o produziu.
|
|
5
6
|
|
|
6
7
|
```tsx preview col 2xl
|
|
7
8
|
const sample = [
|
|
@@ -38,5 +39,5 @@ render(<Markdown content={sample} />)
|
|
|
38
39
|
|
|
39
40
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
40
41
|
|---|---|---|---|
|
|
41
|
-
| `content` | `string` | | O
|
|
42
|
-
| `className` | `string` | | Classes do
|
|
42
|
+
| `content` | `string` | obrigatório | O texto em Markdown (CommonMark e tabelas do GFM, via markdown-it). HTML no texto é escapado, não interpretado, por isso o componente serve para texto escrito por pessoas ou gerado por modelos. Endereços soltos, como `https://…`, viram links. |
|
|
43
|
+
| `className` | `string` | | Classes do contêiner. |
|
|
@@ -4,45 +4,71 @@ title: MCP
|
|
|
4
4
|
|
|
5
5
|
# MCP
|
|
6
6
|
|
|
7
|
-
Use o servidor MCP para disponibilizar actions
|
|
8
|
-
aplicação. A chamada
|
|
9
|
-
auditoria; o MCP fornece apenas o transporte.
|
|
7
|
+
Use o servidor MCP do runtime para disponibilizar actions do app a agentes que executam fora da
|
|
8
|
+
aplicação, como o Claude Desktop ou o agente de um parceiro. A chamada passa por `runtime.execute`,
|
|
9
|
+
com a mesma validação, autorização e auditoria de qualquer outra; o MCP fornece apenas o transporte.
|
|
10
|
+
|
|
11
|
+
Este servidor é diferente de `opus mcp`, que atende o agente que trabalha no código do projeto
|
|
12
|
+
durante o desenvolvimento e não executa actions. Veja [CLI opus](/docs/cli).
|
|
10
13
|
|
|
11
14
|
## Montar
|
|
12
15
|
|
|
16
|
+
`createOpusMcpServer` recebe o runtime e devolve um servidor MCP; o app escolhe o transporte e o
|
|
17
|
+
conecta. `resolveContext` recebe os dados da requisição MCP e devolve o contexto do runtime, com
|
|
18
|
+
usuário, tenant e `can`. No transporte HTTP do SDK MCP, os headers da requisição chegam em
|
|
19
|
+
`requestInfo`, e o adapter de autenticação do app pode lê-los:
|
|
20
|
+
|
|
13
21
|
```ts
|
|
14
22
|
import { createOpusMcpServer } from '@softize/opus/mcp'
|
|
15
|
-
import {
|
|
23
|
+
import { jwtAuth } from '@softize/opus/auth/jwt'
|
|
24
|
+
|
|
25
|
+
const auth = jwtAuth({
|
|
26
|
+
secret: process.env.JWT_SECRET!,
|
|
27
|
+
mapUser: (payload) => ({ id: String(payload.sub) }),
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
type McpRequestExtra = {
|
|
31
|
+
requestInfo?: { headers: Record<string, string | string[] | undefined> }
|
|
32
|
+
}
|
|
16
33
|
|
|
17
34
|
const server = createOpusMcpServer(runtime, {
|
|
18
35
|
name: 'meu-app',
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
36
|
+
resolveContext: async (extra) => {
|
|
37
|
+
const request = (extra as McpRequestExtra).requestInfo ?? { headers: {} }
|
|
38
|
+
const { user, tenantId, can } = await auth.resolveContext(request)
|
|
39
|
+
return { user, tenantId: tenantId ?? null, can }
|
|
40
|
+
},
|
|
22
41
|
})
|
|
23
42
|
|
|
24
|
-
await server.connect(
|
|
43
|
+
await server.connect(transport) // StreamableHTTPServerTransport, por exemplo
|
|
25
44
|
```
|
|
26
45
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
46
|
+
Sem `resolveContext`, a chamada é anônima: não há usuário, `can` nega tudo e só actions `public`
|
|
47
|
+
executam. Com ele, o agente age como o usuário identificado. No transporte stdio não há headers;
|
|
48
|
+
a identidade precisa vir do próprio processo, como um token de serviço lido do ambiente.
|
|
49
|
+
|
|
50
|
+
## O que fica disponível
|
|
51
|
+
|
|
52
|
+
Só actions expostas à IA ficam disponíveis, tanto para listar quanto para executar: as que declaram
|
|
53
|
+
`ai: true` ou um objeto `ai` sem `enabled: false`. `ListTools` devolve cada uma com `name` (o
|
|
54
|
+
identificador técnico), `title` (a `label` legível, quando existe), descrição e JSON Schema da
|
|
55
|
+
entrada. Em `_meta`, cada tool traz os
|
|
56
|
+
[Produtos de Dados](/docs/data-products) relacionados: `com.softize.opus/data-products` lista os
|
|
57
|
+
identificadores e `com.softize.opus/data-product-labels`, o nome legível de cada um.
|
|
58
|
+
|
|
59
|
+
`CallTool` recusa com erro qualquer nome fora dessa lista; os demais seguem por `runtime.execute`.
|
|
60
|
+
A exposição declarada em `ai` decide o que o cliente MCP pode executar, e a autorização do contexto
|
|
61
|
+
continua valendo sobre ela. Para um acesso somente de leitura, exponha apenas actions de leitura.
|
|
36
62
|
|
|
37
63
|
## Escolher entre integração interna e MCP
|
|
38
64
|
|
|
39
65
|
- **Agente dentro da aplicação:** use `runtime.aiFor(base).run()` para chamar as actions no mesmo
|
|
40
|
-
processo.
|
|
41
|
-
- **Agente em outro serviço:** use MCP para oferecer a mesma coleção de ferramentas por
|
|
42
|
-
interface interoperável.
|
|
66
|
+
processo. Veja [IA generativa](/docs/ai).
|
|
67
|
+
- **Agente em outro serviço:** use o servidor MCP para oferecer a mesma coleção de ferramentas por
|
|
68
|
+
uma interface interoperável.
|
|
43
69
|
|
|
44
70
|
## Limites atuais
|
|
45
71
|
|
|
46
|
-
O
|
|
47
|
-
|
|
48
|
-
leitura.
|
|
72
|
+
O servidor MCP não pede confirmação: uma action com `ai.destructive` ou `ai.requiresConfirmation`
|
|
73
|
+
executa como qualquer outra ferramenta anunciada. Como a mesma exposição em `ai` alimenta o agente
|
|
74
|
+
do app e o MCP, ao montar o servidor MCP exponha à IA somente operações de leitura.
|