@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
|
@@ -53,3 +53,14 @@ render(
|
|
|
53
53
|
/>,
|
|
54
54
|
)
|
|
55
55
|
```
|
|
56
|
+
|
|
57
|
+
## Propriedades de IconPicker
|
|
58
|
+
|
|
59
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `value` | `string` | | Nome do ícone selecionado (chave da paleta); `''` é nenhum. |
|
|
62
|
+
| `onChange` | `(name: string) => void` | | Recebe o nome escolhido. |
|
|
63
|
+
| `icons` | `Record<string, LucideIcon>` | `iconPickerIcons` | Paleta nome → componente. |
|
|
64
|
+
| `placeholder` | `string` | `'Selecione um ícone…'` | Texto do gatilho sem seleção. |
|
|
65
|
+
| `disabled` | `boolean` | | Desabilita o gatilho. |
|
|
66
|
+
| `id`, `aria-invalid`, `aria-describedby` | | | Integração com `Field`/`ActionForm`: o gatilho recebe a identidade e o estado de erro do campo. |
|
|
@@ -166,7 +166,7 @@ Com `InputGroupTextarea`, um addon em `block-end` forma uma região de ações a
|
|
|
166
166
|
|
|
167
167
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
168
168
|
|---|---|---|---|
|
|
169
|
-
| `size` | `'xs' \| 'sm' \| 'icon-xs' \| 'icon-sm'` | `'xs'` |
|
|
169
|
+
| `size` | `'xs' \| 'sm' \| 'icon-xs' \| 'icon-sm'` | `'xs'` | O subconjunto da escala única que cabe num campo (1.5 · 2 · 1.5 · 1.75rem); os `icon-*` são quadrados. |
|
|
170
170
|
| `context` | `'neutral' \| 'primary' \| 'danger'` | `'primary'` | Contexto semântico herdado de Button. |
|
|
171
171
|
| `variant` | `'solid' \| 'subtle' \| 'outline' \| 'ghost' \| 'link'` | `'ghost'` | Tratamento visual; use `solid` quando a ação precisar de ênfase. |
|
|
172
172
|
|
|
@@ -105,7 +105,7 @@ usa `ItemHeader` ou `ItemBody` conforme o papel do conteúdo.
|
|
|
105
105
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
106
106
|
|---|---|---|---|
|
|
107
107
|
| `variant` | `'default' \| 'outline' \| 'muted'` | `'default'` | O fundo da linha: transparente, com borda ou levemente tingido. |
|
|
108
|
-
| `size` | `'default' \| 'sm'` | `'default'` | O respiro interno; `sm` atende listas densas. |
|
|
108
|
+
| `size` | `'default' \| 'sm'` | `'default'` | O respiro interno, com os nomes da escala única; `sm` atende listas densas. |
|
|
109
109
|
| `asChild` | `boolean` | `false` | Funde o Item no filho para que a linha inteira assuma sua semântica. |
|
|
110
110
|
|
|
111
111
|
## Propriedades de ItemGroup
|
|
@@ -32,3 +32,10 @@ uma classe adicional.
|
|
|
32
32
|
<Label htmlFor="archive-workspace">Arquivar o workspace</Label>
|
|
33
33
|
</div>
|
|
34
34
|
```
|
|
35
|
+
|
|
36
|
+
## Propriedades de Label
|
|
37
|
+
|
|
38
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `htmlFor` | `string` | | O `id` do controle rotulado; clicar no rótulo foca o controle. |
|
|
41
|
+
| `className` | `string` | | Compõe sobre o estilo padrão; o rótulo esmaece com `peer-disabled` e dentro de `group[data-disabled]`. |
|
|
@@ -111,6 +111,12 @@ MenuSub aninha um nível; inset alinha itens sem ícone com os que têm.
|
|
|
111
111
|
| `context` | `'neutral' \| 'danger'` | `'neutral'` | `danger` sinaliza uma ação com consequência perigosa. |
|
|
112
112
|
| `inset` | `boolean` | | Alinha um item sem ícone com os itens que possuem ícone. |
|
|
113
113
|
|
|
114
|
+
## Propriedades de MenuGroup
|
|
115
|
+
|
|
116
|
+
`MenuGroup` agrupa itens relacionados para leitores de tela (`role="group"`); combine com
|
|
117
|
+
`MenuLabel` para nomear o grupo e `MenuSeparator` para separá-lo do próximo. Não tem props
|
|
118
|
+
próprias além das de DOM.
|
|
119
|
+
|
|
114
120
|
## Propriedades de MenuContent
|
|
115
121
|
|
|
116
122
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
@@ -39,3 +39,16 @@ tecnologias assistivas. O contêiner da coleção continua responsável pela men
|
|
|
39
39
|
```tsx preview col
|
|
40
40
|
<MetricCard loading />
|
|
41
41
|
```
|
|
42
|
+
|
|
43
|
+
## Propriedades de MetricCard
|
|
44
|
+
|
|
45
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
46
|
+
|---|---|---|---|
|
|
47
|
+
| `label` | `ReactNode` | | O nome da medida. |
|
|
48
|
+
| `value` | `ReactNode` | | O valor já formatado pelo consumidor. |
|
|
49
|
+
| `loading` | `boolean` | `false` | Substitui rótulo e valor por skeletons e marca `aria-busy`. |
|
|
50
|
+
| `labelAction` | `ReactNode` | | Controle ao lado do rótulo, como uma explicação em tooltip. |
|
|
51
|
+
| `description` | `ReactNode` | | Contexto que explica recorte, proporção ou significado do valor. |
|
|
52
|
+
| `icon` | `ReactNode` | | Ícone decorativo que identifica a natureza da medida. |
|
|
53
|
+
| `context` | `'neutral' \| 'info' \| 'success' \| 'warning' \| 'danger'` | `'neutral'` | Contexto semântico do ícone; não altera a superfície do card. |
|
|
54
|
+
| `action` | `ReactNode` | | Ação relacionada diretamente à medida. |
|
|
@@ -8,7 +8,9 @@ contexto. O container é centralizado e ocupa a largura disponível até `80rem`
|
|
|
8
8
|
abaixo do cabeçalho permanece livre para tabelas, cards ou outras composições.
|
|
9
9
|
|
|
10
10
|
A forma curta é o padrão para páginas comuns. Ela cria internamente `PageHeader` e `PageBody`;
|
|
11
|
-
portanto, não produz uma estrutura visual ou semântica diferente da forma explícita.
|
|
11
|
+
portanto, não produz uma estrutura visual ou semântica diferente da forma explícita. O cabeçalho é a
|
|
12
|
+
mesma anatomia de `Content` (título, contador, descrição e ações): o que muda entre os dois é o nível
|
|
13
|
+
do heading e a hierarquia visual.
|
|
12
14
|
|
|
13
15
|
`Page` é o esqueleto de páginas e recursos delimitados. Ele também pode ocupar o painel principal
|
|
14
16
|
de um shell com sidebar; a navegação lateral não exige remover o teto nem reconstruir o cabeçalho.
|
|
@@ -41,6 +43,14 @@ render(
|
|
|
41
43
|
)
|
|
42
44
|
```
|
|
43
45
|
|
|
46
|
+
## Ações no chrome do shell
|
|
47
|
+
|
|
48
|
+
Quando o shell reserva uma barra própria para contexto e ações, envolva sua região de conteúdo com
|
|
49
|
+
`PageActionsTarget` e passe o elemento de destino em `target`. As ações declaradas em `Page`
|
|
50
|
+
continuam pertencendo semanticamente ao cabeçalho da página, mas são projetadas nesse elemento.
|
|
51
|
+
Com `target={null}`, elas permanecem na posição padrão; isso permite montar o alvo por `ref` sem
|
|
52
|
+
uma renderização intermediária inconsistente.
|
|
53
|
+
|
|
44
54
|
## Composição explícita
|
|
45
55
|
|
|
46
56
|
Use os slots quando a página precisar compor o header diretamente. Não misture propriedades da
|
|
@@ -82,8 +92,10 @@ altura e semântica acessível consistentes.
|
|
|
82
92
|
</Page>
|
|
83
93
|
```
|
|
84
94
|
|
|
85
|
-
`loading` centraliza o `Spinner
|
|
86
|
-
os filhos sem
|
|
95
|
+
`loading` centraliza o `Spinner` num contêiner `role="status"`; `error` compõe `Alert` com o botão
|
|
96
|
+
de recuperação quando há `onRetry`; `empty` compõe `Empty`; e `ready` entrega os filhos sem
|
|
97
|
+
acrescentar uma superfície. São as mesmas superfícies de `DataState`, na escala da página: `title`
|
|
98
|
+
e `description` nomeiam a situação e, sem `title`, valem `errorMessage` e `emptyMessage`.
|
|
87
99
|
|
|
88
100
|
```tsx preview col
|
|
89
101
|
<Page title="Relatórios">
|
|
@@ -118,5 +130,9 @@ estado na própria seção com `DataState`, `ActionView`, `ActionList` ou `Alert
|
|
|
118
130
|
| `title` | `ReactNode` | Texto seguro por estado | Situação reconhecível pela pessoa. |
|
|
119
131
|
| `description` | `ReactNode` | | Impacto ou próximo passo aplicável. |
|
|
120
132
|
| `icon` | `ReactNode` | Alerta no erro | Ícone decorativo do estado. |
|
|
121
|
-
| `action` | `ReactNode` | |
|
|
133
|
+
| `action` | `ReactNode` | | Seleção ou criação aplicável ao estado. |
|
|
134
|
+
| `emptyMessage` | `string` | `'Nada por aqui'` | Título do vazio quando `title` não é informado. |
|
|
135
|
+
| `errorMessage` | `string` | `'Não foi possível carregar esta página'` | Título do erro quando `title` não é informado. |
|
|
136
|
+
| `onRetry` | `() => void \| Promise<void>` | | Recuperação do erro: acrescenta o botão de tentar de novo ao lado de `action`. |
|
|
137
|
+
| `retryLabel` | `string` | `'Tentar de novo'` | Rótulo do botão de recuperação. |
|
|
122
138
|
| `children` | `ReactNode` | | Conteúdo renderizado somente em `ready`. |
|
|
@@ -29,21 +29,21 @@ rodapé.
|
|
|
29
29
|
|
|
30
30
|
## Números longos
|
|
31
31
|
|
|
32
|
-
A largura mínima é quadrada e cresce conforme o conteúdo. Na escala densa de um rodapé,
|
|
33
|
-
`
|
|
34
|
-
|
|
32
|
+
A largura mínima é quadrada e cresce conforme o conteúdo. Na escala densa de um rodapé, as setas e a
|
|
33
|
+
elipse usam `size="icon-sm"` (o quadrado de 1.75rem da escala única, com o glifo de 0.875rem); os
|
|
34
|
+
números, que não têm um degrau de 1.75rem na escala, ajustam por `className` (`h-7 min-w-7 text-xs`).
|
|
35
35
|
|
|
36
36
|
```tsx preview
|
|
37
37
|
<Pagination>
|
|
38
38
|
<PaginationContent className="gap-0.5">
|
|
39
39
|
<PaginationItem>
|
|
40
|
-
<PaginationPrevious href="#" iconOnly
|
|
40
|
+
<PaginationPrevious href="#" iconOnly size="icon-sm" />
|
|
41
41
|
</PaginationItem>
|
|
42
42
|
<PaginationItem>
|
|
43
43
|
<PaginationLink href="#" page={1} className="h-7 min-w-7 text-xs" />
|
|
44
44
|
</PaginationItem>
|
|
45
45
|
<PaginationItem>
|
|
46
|
-
<PaginationEllipsis
|
|
46
|
+
<PaginationEllipsis size="icon-sm" />
|
|
47
47
|
</PaginationItem>
|
|
48
48
|
<PaginationItem>
|
|
49
49
|
<PaginationLink href="#" page={5726} className="h-7 min-w-7 text-xs" />
|
|
@@ -52,7 +52,7 @@ setas com `iconOnly`).
|
|
|
52
52
|
<PaginationLink href="#" page={5727} isActive className="h-7 min-w-7 text-xs" />
|
|
53
53
|
</PaginationItem>
|
|
54
54
|
<PaginationItem>
|
|
55
|
-
<PaginationNext href="#" iconOnly
|
|
55
|
+
<PaginationNext href="#" iconOnly size="icon-sm" />
|
|
56
56
|
</PaginationItem>
|
|
57
57
|
</PaginationContent>
|
|
58
58
|
</Pagination>
|
|
@@ -61,7 +61,8 @@ setas com `iconOnly`).
|
|
|
61
61
|
## Com elipse
|
|
62
62
|
|
|
63
63
|
`PaginationEllipsis` marca, de forma decorativa e com `aria-hidden`, uma sequência de páginas que
|
|
64
|
-
não cabe na barra.
|
|
64
|
+
não cabe na barra. `size` aceita os quadrados da escala (`icon-xs`, `icon-sm`, `icon`, `icon-lg`) para
|
|
65
|
+
parear com as setas.
|
|
65
66
|
|
|
66
67
|
```tsx preview
|
|
67
68
|
<Pagination>
|
|
@@ -130,7 +131,7 @@ render(
|
|
|
130
131
|
| `page` | `number` | | Número usado como conteúdo, quando `children` não é informado, e no nome acessível “Página N”. |
|
|
131
132
|
| `isActive` | `boolean` | `false` | Marca a página atual com `aria-current="page"` e tratamento `outline`. |
|
|
132
133
|
| `href` | `string` | | Renderiza um `<a>`. Sem `href`, o componente usa `<button>` e aceita `onClick` e `disabled`. |
|
|
133
|
-
| `size` | `'
|
|
134
|
+
| `size` | `ButtonProps['size']` | `'default'` | A escala única, via `Button`. A largura mínima cresce para acomodar números longos; os `icon-*` são quadrados. |
|
|
134
135
|
|
|
135
136
|
## Propriedades de PaginationPrevious e PaginationNext
|
|
136
137
|
|
|
@@ -138,4 +139,5 @@ render(
|
|
|
138
139
|
|---|---|---|---|
|
|
139
140
|
| `label` | `string` | `'Página anterior'` ou `'Próxima página'` | Nome acessível e texto visível da ação. |
|
|
140
141
|
| `iconOnly` | `boolean` | `false` | Exibe somente a seta; `label` continua disponível para leitura assistiva. |
|
|
141
|
-
| `
|
|
142
|
+
| `size` | `ButtonProps['size']` | `'default'`; `'icon'` com `iconOnly` | A escala única; `icon-sm` para o rodapé denso. |
|
|
143
|
+
| `iconClassName` | `string` | | Classes aplicadas ao ícone da seta, quando o glifo da escala não servir. |
|
|
@@ -49,6 +49,12 @@ detalhes.
|
|
|
49
49
|
| `open` | `boolean` | | Estado no modo controlado. |
|
|
50
50
|
| `onOpenChange` | `(open: boolean) => void` | | Atualiza o estado para permitir abertura ou fechamento por código. |
|
|
51
51
|
|
|
52
|
+
## Propriedades de PopoverAnchor
|
|
53
|
+
|
|
54
|
+
`PopoverAnchor` posiciona o painel em relação a um elemento que não é o gatilho — útil quando o
|
|
55
|
+
clique acontece num item de linha, mas o painel deve alinhar-se ao contêiner. Aceita `asChild` para
|
|
56
|
+
não introduzir um nó extra; sem ele, o `PopoverTrigger` é a âncora.
|
|
57
|
+
|
|
52
58
|
## Propriedades de PopoverContent
|
|
53
59
|
|
|
54
60
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
@@ -40,25 +40,21 @@ render(
|
|
|
40
40
|
)
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
## Altura e
|
|
43
|
+
## Altura e contexto
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
`context` diz o que o andamento comunica — `success` para meta atingida, `warning` ou `danger`
|
|
46
|
+
para atenção — e tinge trilha e preenchimento com a família semântica. `className` compõe sobre o
|
|
47
|
+
padrão para ajustar a altura.
|
|
46
48
|
|
|
47
49
|
```tsx preview col
|
|
48
50
|
<div className="w-full max-w-sm space-y-4">
|
|
49
51
|
<div className="space-y-1.5">
|
|
50
52
|
<span className="text-sm">Cobertura de testes</span>
|
|
51
|
-
<Progress
|
|
52
|
-
value={92}
|
|
53
|
-
className="h-1.5 [&_[data-slot=progress-indicator]]:bg-emerald-500"
|
|
54
|
-
/>
|
|
53
|
+
<Progress value={92} context="success" className="h-1.5" />
|
|
55
54
|
</div>
|
|
56
55
|
<div className="space-y-1.5">
|
|
57
56
|
<span className="text-sm">Skills cobertas pelo revisor</span>
|
|
58
|
-
<Progress
|
|
59
|
-
value={45}
|
|
60
|
-
className="h-3 [&_[data-slot=progress-indicator]]:bg-amber-500"
|
|
61
|
-
/>
|
|
57
|
+
<Progress value={45} context="warning" className="h-3" />
|
|
62
58
|
</div>
|
|
63
59
|
</div>
|
|
64
60
|
```
|
|
@@ -68,4 +64,5 @@ className compõe sobre o padrão: ajuste a altura no Progress e tinja o preench
|
|
|
68
64
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
69
65
|
|---|---|---|---|
|
|
70
66
|
| `value` | `number \| null` | | O progresso de 0 a 100. O preenchimento anima a cada mudança; null/ausente deixa a barra vazia. |
|
|
71
|
-
| `
|
|
67
|
+
| `context` | `'neutral' \| 'primary' \| 'info' \| 'success' \| 'warning' \| 'danger'` | `'primary'` | O que o andamento comunica; tinge trilha e preenchimento pela família `--context-*`. |
|
|
68
|
+
| `className` | `string` | | Compõe sobre o padrão — ajuste a altura (h-1.5/h-3). |
|
|
@@ -40,7 +40,7 @@ render(
|
|
|
40
40
|
id="issue"
|
|
41
41
|
value={issue}
|
|
42
42
|
onChange={setIssue}
|
|
43
|
-
placeholder="Buscar
|
|
43
|
+
placeholder="Buscar item…"
|
|
44
44
|
options={[
|
|
45
45
|
{ value: '412', label: 'Ajustar microcopy do handoff', hint: 'SOF-412' },
|
|
46
46
|
{ value: '418', label: 'Preview da sessão cai após deploy', hint: 'SOF-418' },
|
|
@@ -69,7 +69,7 @@ render(
|
|
|
69
69
|
id="agent-skills"
|
|
70
70
|
value={skills}
|
|
71
71
|
onChange={setSkills}
|
|
72
|
-
placeholder="Adicionar
|
|
72
|
+
placeholder="Adicionar habilidade…"
|
|
73
73
|
options={[
|
|
74
74
|
{ value: 'clean-code', label: 'clean-code' },
|
|
75
75
|
{ value: 'code-style', label: 'code-style' },
|
|
@@ -181,7 +181,7 @@ render(
|
|
|
181
181
|
icon={<Ticket />}
|
|
182
182
|
value={task}
|
|
183
183
|
onChange={setTask}
|
|
184
|
-
placeholder="Vincular
|
|
184
|
+
placeholder="Vincular tarefa"
|
|
185
185
|
options={[
|
|
186
186
|
{ value: 'gra-2', label: 'Nova tela anotações', hint: 'GRA-2' },
|
|
187
187
|
{ value: 'gra-7', label: 'Filtro por filial', hint: 'GRA-7' },
|
|
@@ -227,8 +227,8 @@ function Demo() {
|
|
|
227
227
|
value={values}
|
|
228
228
|
onChange={setValues}
|
|
229
229
|
options={[
|
|
230
|
-
{ value: 'developer', label: '
|
|
231
|
-
{ value: 'reviewer', label: '
|
|
230
|
+
{ value: 'developer', label: 'Desenvolvedor' },
|
|
231
|
+
{ value: 'reviewer', label: 'Revisor' },
|
|
232
232
|
{ value: 'designer', label: 'Designer' },
|
|
233
233
|
]}
|
|
234
234
|
placeholder="Papéis…"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Contexto
|
|
2
|
+
title: Contexto e variante
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
# Contexto
|
|
5
|
+
# Contexto e variante
|
|
6
6
|
|
|
7
7
|
Componentes semânticos separam significado de aparência. `context` responde por que o elemento
|
|
8
8
|
recebe destaque; `variant` escolhe como esse significado aparece. Essa ordem evita que nomes como
|
|
@@ -59,5 +59,6 @@ const status = t.dict(
|
|
|
59
59
|
|
|
60
60
|
## Compatibilidade
|
|
61
61
|
|
|
62
|
-
`tone` em dicionários
|
|
63
|
-
|
|
62
|
+
`tone` em dicionários continua aceito durante a migração; código novo usa `context`. As variantes
|
|
63
|
+
semânticas antigas dos componentes (`default`, `secondary`, `destructive`, `success`, `warning`,
|
|
64
|
+
`info`) saíram na 14.0.0: `variant` só descreve tratamento visual e o significado é sempre `context`.
|
|
@@ -61,7 +61,7 @@ uma sidebar fixa, redimensionável ou recolhida.
|
|
|
61
61
|
| `PaneHeader` | Mantém identidade, contexto ou ações no topo. |
|
|
62
62
|
| `PaneBody` | Ocupa o espaço restante e concentra a rolagem vertical. |
|
|
63
63
|
| `PaneFooter` | Mantém ações persistentes no rodapé. |
|
|
64
|
-
| `SidebarNav`
|
|
64
|
+
| `SidebarNav` | Apresenta e controla os destinos de navegação. |
|
|
65
65
|
|
|
66
66
|
`PaneContent` permanece como alias temporário de `PaneBody` durante a versão 12. Código novo usa
|
|
67
67
|
`PaneBody`.
|
|
@@ -134,28 +134,16 @@ render(
|
|
|
134
134
|
Esse é o padrão usado pelo `DocBrowser`: seções são rótulos, grupos nomeados são nós expansíveis e
|
|
135
135
|
páginas são folhas. Um grupo começa aberto e volta a abrir quando contém a página ativa.
|
|
136
136
|
|
|
137
|
-
Use `ShellNav` para uma navegação plana que precisa de cabeçalho próprio e grupos ancorados no
|
|
138
|
-
rodapé. Ele gerencia a rolagem internamente e se adapta quando estiver dentro de uma `Sidebar`
|
|
139
|
-
recolhida.
|
|
140
|
-
|
|
141
|
-
```tsx
|
|
142
|
-
<Sidebar collapsed={collapsed}>
|
|
143
|
-
<ShellNav
|
|
144
|
-
heading={<ShellNavHeading title="Relatórios" action={<CreateReportButton />} />}
|
|
145
|
-
groups={reportGroups}
|
|
146
|
-
footer={settingsGroups}
|
|
147
|
-
activeId={activeId}
|
|
148
|
-
onSelect={navigateToReport}
|
|
149
|
-
/>
|
|
150
|
-
</Sidebar>
|
|
151
|
-
```
|
|
152
|
-
|
|
153
137
|
## Recolher a coluna
|
|
154
138
|
|
|
155
|
-
`collapsed` pertence à `Sidebar`. Nesse estado, `SidebarItem
|
|
139
|
+
`collapsed` pertence à `Sidebar`. Nesse estado, `SidebarItem` e `SidebarNav` mantêm
|
|
156
140
|
somente os ícones e expõem os rótulos em tooltips. Por isso, todo destino que aparece no modo
|
|
157
141
|
recolhido precisa de um ícone reconhecível e de um `label` completo.
|
|
158
142
|
|
|
143
|
+
O slot de ícone do `SidebarItem` ocupa `1rem` nos dois estados e normaliza SVGs para essa medida.
|
|
144
|
+
O consumidor escolhe o símbolo e sua cor sem precisar repetir largura ou altura em ícones SVG.
|
|
145
|
+
Outros tipos de `ReactNode` continuam responsáveis pelas próprias dimensões.
|
|
146
|
+
|
|
159
147
|
```tsx preview
|
|
160
148
|
const [collapsed, setCollapsed] = useState(false)
|
|
161
149
|
|
|
@@ -216,12 +204,13 @@ estrutura evita botões aninhados e permite que cada controle receba foco de for
|
|
|
216
204
|
}
|
|
217
205
|
onClick={() => {}}
|
|
218
206
|
/>
|
|
219
|
-
<
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
207
|
+
<SidebarTreeGroup>
|
|
208
|
+
<SidebarItem
|
|
209
|
+
label="Criar workspace"
|
|
210
|
+
icon={<FilePlus2 />}
|
|
211
|
+
onClick={() => {}}
|
|
212
|
+
/>
|
|
213
|
+
</SidebarTreeGroup>
|
|
225
214
|
</div>
|
|
226
215
|
```
|
|
227
216
|
|
|
@@ -323,26 +312,3 @@ O driver de drag-and-drop continua externo e fornece seus atributos por `dragPro
|
|
|
323
312
|
|---|---|---|---|
|
|
324
313
|
| `className` | `string` | | Ajusta o grupo sem substituir o recuo, o espaçamento e a guia vertical padrão. |
|
|
325
314
|
| `children` | `ReactNode` | | Itens ou grupos que descendem do nó anterior. |
|
|
326
|
-
|
|
327
|
-
## Propriedades de ShellNav
|
|
328
|
-
|
|
329
|
-
| Propriedade | Tipo | Padrão | Descrição |
|
|
330
|
-
|---|---|---|---|
|
|
331
|
-
| `groups` | `ShellNavGroup[]` | | Grupos planos exibidos na região rolável. Grupos vazios são omitidos. |
|
|
332
|
-
| `activeId` | `string` | | Identificador do destino atual. |
|
|
333
|
-
| `onSelect` | `(id: string) => void` | | Recebe o identificador selecionado. |
|
|
334
|
-
| `heading` | `ReactNode` | | Conteúdo fixo acima da navegação; fica oculto no modo recolhido. |
|
|
335
|
-
| `footer` | `ShellNavGroup[]` | | Grupos ancorados abaixo da região rolável. |
|
|
336
|
-
| `navLabel` | `string` | `'Navegação'` | Nome acessível da landmark `nav`. |
|
|
337
|
-
| `className` | `string` | | Ajusta a coluna da navegação. A largura vem do contêiner. |
|
|
338
|
-
|
|
339
|
-
Cada `ShellNavGroup` recebe `label` opcional e `items`. Um `ShellNavItem` declara `id`, `label`,
|
|
340
|
-
`icon`, `badge` e `disabled`.
|
|
341
|
-
|
|
342
|
-
## Propriedades de ShellNavHeading
|
|
343
|
-
|
|
344
|
-
| Propriedade | Tipo | Padrão | Descrição |
|
|
345
|
-
|---|---|---|---|
|
|
346
|
-
| `title` | `ReactNode` | | Título da navegação. |
|
|
347
|
-
| `action` | `ReactNode` | | Ação relacionada apresentada no extremo oposto. |
|
|
348
|
-
| `className` | `string` | | Ajusta a faixa de cabeçalho. |
|
|
@@ -33,3 +33,9 @@ O esqueleto reproduz o layout final do card — título, descrição, conteúdo
|
|
|
33
33
|
</CardFooter>
|
|
34
34
|
</Card>
|
|
35
35
|
```
|
|
36
|
+
|
|
37
|
+
## Propriedades de Skeleton
|
|
38
|
+
|
|
39
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
40
|
+
|---|---|---|---|
|
|
41
|
+
| `className` | `string` | | Dá forma ao placeholder (`h-4 w-40`, `size-10 rounded-full`); o componente só traz o pulso e o fundo. |
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
## Carregamento sem progresso conhecido
|
|
2
2
|
|
|
3
|
-
Use `Spinner` quando a duração ou o progresso da espera não forem conhecidos. `
|
|
4
|
-
|
|
3
|
+
Use `Spinner` quando a duração ou o progresso da espera não forem conhecidos. `size` usa os nomes da
|
|
4
|
+
escala dos controles e mede o glifo do controle homônimo: `sm` é o ícone de um `Button` `sm`, `lg` o
|
|
5
|
+
de um `lg`. O ícone é decorativo; quem nomeia a espera é o contêiner (`role="status"`, como fazem
|
|
6
|
+
`DataState` e `PageState`) ou o texto ao lado.
|
|
5
7
|
|
|
6
8
|
```tsx preview
|
|
9
|
+
<Spinner size="xs" />
|
|
7
10
|
<Spinner size="sm" />
|
|
8
11
|
<Spinner />
|
|
9
12
|
<Spinner size="lg" />
|
|
@@ -20,11 +23,11 @@ andamento.
|
|
|
20
23
|
|
|
21
24
|
## Em carga de conteúdo
|
|
22
25
|
|
|
23
|
-
Espera curta sem forma definida
|
|
24
|
-
Skeleton.
|
|
26
|
+
Espera curta sem forma definida; o contêiner nomeia o estado. Para uma consulta inteira, `DataState`
|
|
27
|
+
já monta esse contêiner. Quando o conteúdo tem forma conhecida (lista, card), prefira Skeleton.
|
|
25
28
|
|
|
26
29
|
```tsx preview
|
|
27
|
-
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
30
|
+
<div role="status" className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
28
31
|
<Spinner />
|
|
29
32
|
<span>Carregando sessões…</span>
|
|
30
33
|
</div>
|
|
@@ -34,4 +37,4 @@ Skeleton.
|
|
|
34
37
|
|
|
35
38
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
36
39
|
|---|---|---|---|
|
|
37
|
-
| `size` | `'sm' \| 'default' \| 'lg'` | `'default'` | O
|
|
40
|
+
| `size` | `'xs' \| 'sm' \| 'default' \| 'lg'` | `'default'` | O glifo do controle homônimo na escala única (0.875 · 0.875 · 1 · 1.25rem). |
|
|
@@ -74,3 +74,24 @@ const defaultLayout = readLayout('workspace-layout')
|
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
Em aplicações renderizadas no servidor, leia o armazenamento somente no cliente. `onLayoutChanged` também permite usar `sessionStorage` ou uma camada própria quando o layout precisa acompanhar outro escopo.
|
|
77
|
+
|
|
78
|
+
## Propriedades de Split
|
|
79
|
+
|
|
80
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
81
|
+
|---|---|---|---|
|
|
82
|
+
| `direction` | `'horizontal' \| 'vertical'` | `'horizontal'` | Sentido em que os panes se alinham. |
|
|
83
|
+
| `resizable` | `boolean` | `false` | Cada fronteira ganha um separador acessível e arrastável. |
|
|
84
|
+
| `handle` | `boolean` | `false` | Mostra a alça visual no separador. |
|
|
85
|
+
| `id` | `string` | | Identidade estável do grupo redimensionável. |
|
|
86
|
+
| `defaultLayout` | `Record<string, number>` | | Layout percentual restaurado, indexado pelos ids dos panes. |
|
|
87
|
+
| `onLayoutChanged` | `(layout, { isUserInteraction }) => void` | | Chamado ao concluir uma mudança de layout; persista onde fizer sentido. |
|
|
88
|
+
|
|
89
|
+
## Propriedades de Pane
|
|
90
|
+
|
|
91
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
92
|
+
|---|---|---|---|
|
|
93
|
+
| `id` | `string` | | Identidade estável usada pelo layout redimensionável e persistido. |
|
|
94
|
+
| `initialSize` | `number \| string` | | Tamanho inicial; número é porcentagem, string aceita `%`, `rem`, `em`, `vh`, `vw` e `px`. |
|
|
95
|
+
| `minSize` / `maxSize` | `number \| string` | | Limites quando o split é redimensionável. |
|
|
96
|
+
| `grow` | `boolean` | `false` | Ocupa o espaço remanescente no layout simples. |
|
|
97
|
+
| `inset` | `'none' \| 'sm' \| 'md' \| 'lg'` | `'md'` | Respiro interno; `none` para chrome, navegação ou conteúdo com inset próprio. |
|
|
@@ -66,5 +66,5 @@ disabled esmaece e bloqueia a chave — ligada ou desligada — e o rótulo em p
|
|
|
66
66
|
| `checked` | `boolean` | | O estado, no modo controlado — parear com onCheckedChange. |
|
|
67
67
|
| `onCheckedChange` | `(checked: boolean) => void` | | Chamado a cada alternância, com o novo estado. |
|
|
68
68
|
| `defaultChecked` | `boolean` | `false` | Estado inicial no modo não controlado. |
|
|
69
|
-
| `size` | `'sm' \| 'default'` | `'default'` | Tamanho da chave — sm para densidade em linha de lista. |
|
|
69
|
+
| `size` | `'sm' \| 'default'` | `'default'` | Tamanho da chave, com os nomes da escala única — sm para densidade em linha de lista. |
|
|
70
70
|
| `disabled` | `boolean` | `false` | Esmaece e bloqueia — o Label em par esmaece junto (peer-disabled). |
|
|
@@ -92,7 +92,7 @@ lateral do gatilho.
|
|
|
92
92
|
| `defaultValue` | `string` | | Aba inicial no modo não controlado. |
|
|
93
93
|
| `value` | `string` | | Aba ativa no modo controlado. Use com `onValueChange`. |
|
|
94
94
|
| `onValueChange` | `(value: string) => void` | | Chamado quando a pessoa seleciona outra aba. |
|
|
95
|
-
| `size` | `'default' \| 'sm'` | `'default'` |
|
|
95
|
+
| `size` | `'default' \| 'sm'` | `'default'` | Altura da lista na escala única dos controles (2.25 e 2rem), aplicada em `TabsList`. |
|
|
96
96
|
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Direção da lista de abas. |
|
|
97
97
|
|
|
98
98
|
## Propriedades de TabsList
|
|
@@ -29,3 +29,10 @@ Associe `htmlFor` no `Label` ao `id` do campo para manter o rótulo acessível.
|
|
|
29
29
|
<Textarea aria-invalid placeholder="Conte o contexto da mudança." />
|
|
30
30
|
<Textarea disabled defaultValue="Sessão encerrada — o brief não pode mais ser editado." />
|
|
31
31
|
```
|
|
32
|
+
|
|
33
|
+
## Propriedades de Textarea
|
|
34
|
+
|
|
35
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
36
|
+
|---|---|---|---|
|
|
37
|
+
| `…props` | `ComponentProps<'textarea'>` | | Todos os atributos nativos (`value`, `defaultValue`, `rows`, `disabled`, `aria-invalid`…). A altura acompanha o conteúdo (`field-sizing-content`) a partir de `min-h-16`. |
|
|
38
|
+
| `className` | `string` | | Compõe sobre o estilo padrão. |
|
|
@@ -70,7 +70,7 @@ disabled esmaece e bloqueia o clique — o estado pressed permanece visível.
|
|
|
70
70
|
| `onPressedChange` | `(pressed: boolean) => void` | | Chamado a cada alternância, com o novo estado. |
|
|
71
71
|
| `defaultPressed` | `boolean` | `false` | Estado inicial no modo não controlado. |
|
|
72
72
|
| `variant` | `'default' \| 'outline'` | `'default'` | default não tem borda (fundo só quando ativo); outline carrega a borda. |
|
|
73
|
-
| `size` | `'sm' \| 'default' \| 'lg'` | `'default'` | Altura
|
|
73
|
+
| `size` | `'sm' \| 'default' \| 'lg'` | `'default'` | Altura na escala única dos controles (2 · 2.25 · 2.5rem) — sm para toolbar densa, lg para alvo mais confortável. |
|
|
74
74
|
| `disabled` | `boolean` | `false` | Esmaece e bloqueia o clique, preservando o estado visual. |
|
|
75
75
|
|
|
76
76
|
## ToggleGroup
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Tokens
|
|
2
|
+
title: Tokens e tema
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
# Tokens
|
|
5
|
+
# Tokens e tema
|
|
6
6
|
|
|
7
7
|
O tema canônico vive no Opus (`theme.css`): tokens com a cor inteira na var, mapeados para o
|
|
8
8
|
Tailwind via `@theme inline`. Os swatches abaixo leem as vars **ao vivo** — troque o tema do app
|
|
@@ -73,8 +73,8 @@ render(
|
|
|
73
73
|
|
|
74
74
|
## Linhas e foco
|
|
75
75
|
|
|
76
|
-
> Bordas e o anel de foco também são tokens — nada de cinza hardcoded.
|
|
77
|
-
>
|
|
76
|
+
> Bordas e o anel de foco também são tokens — nada de cinza hardcoded. Superfícies elevadas usam
|
|
77
|
+
> a mesma `border-border`; o que muda entre elas é a sombra, descrita na seção Escala de elevação.
|
|
78
78
|
|
|
79
79
|
```tsx preview
|
|
80
80
|
const LINES = [
|
|
@@ -60,3 +60,11 @@ quando o texto completo ainda não oferecer contexto suficiente.
|
|
|
60
60
|
|
|
61
61
|
Requer `TooltipProvider` na raiz (o esqueleto do `opus create` já monta). Largura vem do
|
|
62
62
|
container ou de `className` (`max-w-*`) — o span é `block truncate`.
|
|
63
|
+
|
|
64
|
+
## Propriedades de Truncate
|
|
65
|
+
|
|
66
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| `tooltip` | `ReactNode` | os próprios `children` | Conteúdo da dica quando o texto transborda. |
|
|
69
|
+
| `fade` | `boolean` | `false` | Sinaliza o corte esmaecendo o fim da linha, no lugar das reticências. |
|
|
70
|
+
| `className` | `string` | | Largura (`max-w-*`) e demais ajustes; o span é `block truncate`. |
|
|
@@ -30,6 +30,20 @@ import { Button, Dialog, useAction } from '@softize/opus/ui/react'
|
|
|
30
30
|
@source '../node_modules/@softize/opus/src/ui';
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
## Prebundle do Vite
|
|
34
|
+
|
|
35
|
+
A entrada `@softize/opus/ui/react` é um `.tsx`, e o prebundle do Vite só considera entradas
|
|
36
|
+
`.js`/`.ts`. Sem ajuste, o dev server avisa `Cannot optimize dependency` e serve a árvore do Opus
|
|
37
|
+
arquivo a arquivo na carga fria. Há duas saídas, cada uma com um custo conhecido:
|
|
38
|
+
|
|
39
|
+
- `optimizeDeps.include: ['@softize/opus/ui/react']` com `extensions: ['.tsx']` pré-empacota o
|
|
40
|
+
Opus, mas pode duplicar `@tanstack/react-query` quando o app também o importa direto (dois
|
|
41
|
+
`QueryClient`, hooks fora do provider).
|
|
42
|
+
- `optimizeDeps.exclude: ['@softize/opus/ui/react']` evita a duplicação e infla a carga fria.
|
|
43
|
+
|
|
44
|
+
Escolha pelo sintoma que aparece no seu app e registre a decisão no `vite.config.ts`. A saída
|
|
45
|
+
definitiva (entrada `.ts` no pacote) está no radar do Opus.
|
|
46
|
+
|
|
33
47
|
## Origem e anti-drift
|
|
34
48
|
|
|
35
49
|
> Cada componente declara de onde veio — e a regra de sincronização vem junto.
|
|
@@ -8,7 +8,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
|
8
8
|
import { z } from 'zod'
|
|
9
9
|
import { attachLogicalType, defineContract, error } from '../../core/index.ts'
|
|
10
10
|
import type { ActionDef, ActionResult, ClientAdapter, LogicalTypeMeta, Paginated } from '../../core/index.ts'
|
|
11
|
-
import {
|
|
11
|
+
import { OpusProvider } from '../react.tsx'
|
|
12
12
|
|
|
13
13
|
// — Dados enlatados (domínio da casa) —
|
|
14
14
|
export interface DocBrowserWorkspace {
|
|
@@ -37,7 +37,7 @@ export const docWorkspaceStatus: LogicalTypeMeta = {
|
|
|
37
37
|
keys: [...STATUS],
|
|
38
38
|
entries: {
|
|
39
39
|
active: { label: 'Ativo', context: 'success', description: 'Agentes em operação para o cliente.' },
|
|
40
|
-
onboarding: { label: '
|
|
40
|
+
onboarding: { label: 'Em integração', context: 'warning' },
|
|
41
41
|
paused: { label: 'Pausado' },
|
|
42
42
|
},
|
|
43
43
|
presentation: 'status',
|
|
@@ -59,7 +59,7 @@ export const docWorkspaceCreate = defineContract({
|
|
|
59
59
|
}),
|
|
60
60
|
output: z.object({ id: z.string() }),
|
|
61
61
|
fields: {
|
|
62
|
-
name: { label: 'Nome', placeholder: 'Ex.: Empresa X',
|
|
62
|
+
name: { label: 'Nome', placeholder: 'Ex.: Empresa X', help: 'Digite “Softize” para ver o erro de servidor.' },
|
|
63
63
|
status: { label: 'Status' },
|
|
64
64
|
contact: { label: 'Contato', placeholder: 'email@cliente.com' },
|
|
65
65
|
notes: { label: 'Observações', placeholder: 'Contexto do onboarding…' },
|
|
@@ -100,7 +100,7 @@ export const docWorkspaceList = defineContract({
|
|
|
100
100
|
kind: 'static',
|
|
101
101
|
items: [
|
|
102
102
|
{ value: 'active', label: 'Ativo' },
|
|
103
|
-
{ value: 'onboarding', label: '
|
|
103
|
+
{ value: 'onboarding', label: 'Em integração' },
|
|
104
104
|
{ value: 'paused', label: 'Pausado' },
|
|
105
105
|
],
|
|
106
106
|
},
|
|
@@ -225,7 +225,7 @@ const queryClient = new QueryClient()
|
|
|
225
225
|
export function DocBrowserActionProvider({ children }: { children: React.ReactNode }): React.ReactElement {
|
|
226
226
|
return (
|
|
227
227
|
<QueryClientProvider client={queryClient}>
|
|
228
|
-
<
|
|
228
|
+
<OpusProvider client={docClient}>{children}</OpusProvider>
|
|
229
229
|
</QueryClientProvider>
|
|
230
230
|
)
|
|
231
231
|
}
|