@softize/opus 18.5.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 +275 -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 +298 -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 +16 -12
- package/src/ui/components/patterns/fill-region.ts +150 -0
- package/src/ui/components/patterns/heading-level.ts +16 -0
- package/src/ui/components/patterns/list.tsx +103 -73
- package/src/ui/components/patterns/page.tsx +20 -4
- package/src/ui/components/patterns/pane.tsx +294 -0
- package/src/ui/components/patterns/presentation.tsx +81 -54
- package/src/ui/components/patterns/sidebar.tsx +13 -72
- package/src/ui/components/patterns/split.tsx +51 -38
- package/src/ui/components/patterns/surface-anatomy.ts +246 -0
- package/src/ui/components/patterns/surface-header.tsx +51 -6
- package/src/ui/components/patterns/surface-media.tsx +69 -0
- 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 +91 -29
- 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 +14 -5
- package/src/ui/components/primitives/copyable.tsx +120 -10
- package/src/ui/components/primitives/detail.tsx +10 -13
- package/src/ui/components/primitives/dialog.tsx +179 -45
- package/src/ui/components/primitives/drawer.tsx +131 -24
- 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/metric-card.tsx +98 -39
- 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 +252 -35
- 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 +37 -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 +219 -28
- 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 +193 -22
- 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 +68 -21
- package/src/ui/docs/content/observability.md +10 -9
- package/src/ui/docs/content/page.md +125 -11
- package/src/ui/docs/content/pagination.md +13 -5
- package/src/ui/docs/content/pane.md +300 -0
- 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 +25 -45
- package/src/ui/docs/content/skeleton.md +13 -4
- 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 +34 -20
- 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 +14 -2
- package/src/ui/drivers/react.tsx +16 -8
- package/src/ui/meta.ts +38 -32
- package/src/ui/react.tsx +14 -0
- package/src/vite/design.ts +16 -4
|
@@ -10,20 +10,18 @@ as ferramentas usam essas definições sem exigir schemas e tipos paralelos.
|
|
|
10
10
|
|
|
11
11
|
## O modelo
|
|
12
12
|
|
|
13
|
-
> Comece pelo problema que o modelo compartilhado resolve antes de conhecer seus arquivos.
|
|
14
|
-
|
|
15
13
|
As regras de uma aplicação costumam aparecer em vários lugares: validação, transporte, API,
|
|
16
|
-
formulários e documentação. No Opus, entidades,
|
|
14
|
+
formulários e documentação. No Opus, entidades, dicionários e contratos de action descrevem essas
|
|
17
15
|
regras uma vez. A API e a web consomem a mesma definição, enquanto runtime, adapters, UI, CLI
|
|
18
16
|
e verificações ajudam a mantê-la consistente. Cada projeto acrescenta seu domínio sobre essa
|
|
19
17
|
base versionada.
|
|
20
18
|
|
|
21
19
|
## Começar do zero
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
Para um projeto novo, use `opus create`: ele gera o app com os pré-requisitos do protocolo, da UI e
|
|
22
|
+
do preview já configurados, e os gates passam desde o início.
|
|
25
23
|
|
|
26
|
-
O Opus e a Base ficam no npm público:
|
|
24
|
+
O Opus e a Base ficam no npm público: a instalação não exige token nem configuração de escopo.
|
|
27
25
|
Crie o projeto e materialize as duas camadas antes dos gates:
|
|
28
26
|
|
|
29
27
|
```bash
|
|
@@ -43,15 +41,21 @@ com `pnpm dlx @softize/opus@<versão> create meu-app` ou desative a quarentena a
|
|
|
43
41
|
com `pnpm --config.minimum-release-age=0 dlx …`. Dentro do projeto, o workspace exclui Opus e Base
|
|
44
42
|
da quarentena para preservar o par validado.
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
O app criado inclui:
|
|
45
|
+
|
|
46
|
+
- `opus.config.ts` e um domínio de exemplo documentado, sem violações no `opus check`;
|
|
47
|
+
- Vite, React e o tema do Opus sobre Tailwind v4, configurado por CSS;
|
|
48
|
+
- um dev server que respeita a variável `PORT`, para que um orquestrador de preview escolha a
|
|
49
|
+
porta;
|
|
50
|
+
- `opus.json`, com a versão adotada, e as instruções, skills e hooks gerenciados.
|
|
51
|
+
|
|
52
|
+
A Base cuida do método geral de trabalho, da memória e da revisão; o Opus acrescenta o conhecimento
|
|
53
|
+
específico do SDK.
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
detecta o `pnpm-workspace.yaml` e gera só
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
Em um monorepo, crie primeiro a raiz com `--monorepo` e depois cada app dentro dela. O `create`
|
|
56
|
+
detecta o `pnpm-workspace.yaml` e gera só os arquivos do app, sem um workspace aninhado. O que a raiz
|
|
57
|
+
precisa ter, como o glob de packages, `allowBuilds` e as exclusões de quarentena para Opus e Base,
|
|
58
|
+
aparece como aviso, sem alterar os arquivos da raiz:
|
|
55
59
|
|
|
56
60
|
```bash
|
|
57
61
|
pnpm dlx @softize/opus create meu-cliente --monorepo # a raiz do workspace
|
|
@@ -61,13 +65,10 @@ pnpm dlx @softize/opus create apps/portal # o app (modo detectado)
|
|
|
61
65
|
|
|
62
66
|
## Carregar o Opus em um projeto existente
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
o inventário de copy e as projeções específicas do SDK. O `base setup` materializa o
|
|
69
|
-
método geral, memória, agentes e revisão na raiz do repositório. Os componentes vêm do
|
|
70
|
-
barrel `@softize/opus/ui/react`; o tema, por CSS.
|
|
68
|
+
O `opus.json` registra a versão do Opus adotada pelo app; se ele ainda não existe, o setup o cria.
|
|
69
|
+
`opus setup` roda em cada app e grava o marcador, o inventário de copy e as projeções específicas do
|
|
70
|
+
SDK. `base setup` materializa na raiz do repositório o método geral, a memória, os agentes e a
|
|
71
|
+
revisão. Os componentes vêm de `@softize/opus/ui/react`, e o tema, de um arquivo CSS.
|
|
71
72
|
|
|
72
73
|
```bash
|
|
73
74
|
# Bootstrap idempotente de um projeto existente.
|
|
@@ -78,39 +79,48 @@ pnpm exec base setup
|
|
|
78
79
|
```
|
|
79
80
|
|
|
80
81
|
```css
|
|
81
|
-
/* index.css do app — o tema
|
|
82
|
+
/* index.css do app — o tema do Opus e os componentes do pacote no scan do Tailwind. */
|
|
82
83
|
@import '@softize/opus/ui/theme.css';
|
|
83
84
|
@source '../node_modules/@softize/opus/src/ui/**/*.{ts,tsx}';
|
|
84
85
|
```
|
|
85
86
|
|
|
86
|
-
##
|
|
87
|
+
## Montar o runtime
|
|
87
88
|
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
No servidor, `createRuntime` reúne as capacidades que o app usa. Cada capacidade, como banco,
|
|
90
|
+
autenticação ou auditoria, é um adapter que pode ser trocado sem alterar o domínio. Os providers da
|
|
91
|
+
interface estão em [Como consumir](/ui/como-consumir).
|
|
90
92
|
|
|
91
93
|
```ts
|
|
92
94
|
import { createRuntime } from '@softize/opus/core'
|
|
95
|
+
import { jwtAuth } from '@softize/opus/auth/jwt'
|
|
93
96
|
import { kyselyData } from '@softize/opus/data/kysely'
|
|
94
97
|
import { fastifyServer } from '@softize/opus/server/fastify'
|
|
95
98
|
import { pgAudit } from '@softize/opus/audit/pg'
|
|
99
|
+
import { workspaceDomain } from './domains/workspace/index.ts'
|
|
96
100
|
|
|
97
101
|
const runtime = createRuntime({
|
|
98
102
|
server: fastifyServer({ app }),
|
|
99
|
-
data: kyselyData({ db }), // Kysely
|
|
100
|
-
auth:
|
|
103
|
+
data: kyselyData({ db }), // Kysely e Postgres
|
|
104
|
+
auth: jwtAuth({ secret: process.env.JWT_SECRET!, mapUser: (p) => ({ id: String(p.sub) }) }),
|
|
101
105
|
audit: [pgAudit({ pool })], // trilha de auditoria
|
|
102
106
|
config: { env, i18n: { defaultLocale: 'pt-BR' } },
|
|
103
107
|
})
|
|
104
108
|
|
|
105
|
-
//
|
|
106
|
-
runtime.register([
|
|
109
|
+
// Só o que foi registrado existe para o runtime.
|
|
110
|
+
runtime.register([workspaceDomain])
|
|
107
111
|
await runtime.start()
|
|
108
112
|
```
|
|
109
113
|
|
|
110
|
-
|
|
114
|
+
Cada capacidade e o registro de domínios estão detalhados em [Runtime & adapters](/docs/runtime).
|
|
115
|
+
|
|
116
|
+
## Antes de alterar o projeto
|
|
111
117
|
|
|
112
|
-
|
|
118
|
+
A documentação do próprio repositório descreve o que é específico dele; esta página cobre só o que
|
|
119
|
+
vale para todo projeto Opus.
|
|
113
120
|
|
|
114
|
-
- `CLAUDE.md` do
|
|
115
|
-
-
|
|
116
|
-
|
|
121
|
+
- O `CLAUDE.md` do repositório e de cada app reúne o mapa do código, os gates e os cuidados locais.
|
|
122
|
+
- A `description` de entidades e actions registra a regra de negócio, que `opus gen` projeta no
|
|
123
|
+
manifest.
|
|
124
|
+
- Antes de entregar, rode `opus check` (convenções das actions e da UI), `opus copy --check` e
|
|
125
|
+
`base copy check` (inventário e política de copy) e, com banco, `opus db check` (divergência entre
|
|
126
|
+
entidades e banco).
|
|
@@ -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. |
|