@softize/opus 15.2.2 → 16.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 +51 -18
- package/bin/lib/check.mjs +98 -15
- package/bin/lib/copy.mjs +811 -314
- package/bin/lib/gen-manifest.mjs +24 -23
- package/bin/lib/gen-runner.mjs +188 -148
- package/docs/adr/0010-page-header-owns-page-chrome.md +3 -4
- package/docs/adr/0011-page-shell-coordinates-persistent-page-chrome.md +5 -3
- package/docs/adr/0012-modal-header-only-names-the-surface.md +45 -0
- package/docs/adr/0013-presentation-is-a-portable-action-oriented-artifact.md +92 -0
- package/docs/code-style.md +24 -19
- package/package.json +5 -1
- package/registry/skills/build-opus-ui/references/ui-patterns.md +43 -26
- package/src/core/presentation.ts +512 -0
- package/src/presentation/index.ts +1 -0
- package/src/ui/components/patterns/action-list-dialog.tsx +26 -9
- package/src/ui/components/patterns/confirm.tsx +34 -29
- package/src/ui/components/patterns/form-dialog.tsx +20 -8
- package/src/ui/components/patterns/list.tsx +26 -9
- package/src/ui/components/patterns/page.tsx +99 -139
- package/src/ui/components/patterns/presentation.tsx +316 -0
- package/src/ui/components/patterns/sidebar.tsx +3 -3
- package/src/ui/components/patterns/trigger.tsx +38 -17
- package/src/ui/components/primitives/button-group.tsx +53 -43
- package/src/ui/components/primitives/command.tsx +30 -72
- package/src/ui/components/primitives/dialog.tsx +23 -89
- package/src/ui/components/primitives/drawer.tsx +8 -34
- package/src/ui/docs/content/action-form-dialog.md +12 -10
- package/src/ui/docs/content/action-list-dialog.md +22 -17
- package/src/ui/docs/content/button.md +52 -35
- package/src/ui/docs/content/communication.md +26 -26
- package/src/ui/docs/content/dialog.md +173 -154
- package/src/ui/docs/content/drawer.md +12 -11
- package/src/ui/docs/content/page.md +72 -91
- package/src/ui/docs/content/presentation.md +158 -0
- package/src/ui/docs/registry.tsx +6 -0
- package/src/ui/meta.ts +8 -2
- package/src/ui/react.tsx +10 -3
|
@@ -5,10 +5,9 @@ Use `Page` para manter título, ações, estado e conteúdo na mesma anatomia. S
|
|
|
5
5
|
com `PageShell`: o shell fornece a navegação, a página fornece as ações e o título passa a
|
|
6
6
|
`PageIntro` dentro do conteúdo.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
ou largura total.
|
|
8
|
+
`PageHeader` mantém navegação, título e ações na mesma linha. O container é centralizado e ocupa a
|
|
9
|
+
largura disponível até `80rem` (`max-w-7xl`). Use `className` somente quando a composição pedir
|
|
10
|
+
outro teto ou largura total.
|
|
12
11
|
|
|
13
12
|
A forma curta é o padrão para páginas comuns. Fora de `PageShell`, ela cria `PageHeader` e
|
|
14
13
|
`PageBody`. Dentro dele, cria `PageIntro` e `PageBody`, enquanto envia as ações para a barra. A forma
|
|
@@ -48,7 +47,7 @@ render(
|
|
|
48
47
|
|
|
49
48
|
Use `PageBack` em uma subpágina simples. O destino é explícito para continuar correto após refresh ou
|
|
50
49
|
acesso por link direto; não derive esse retorno do histórico do navegador. No header padrão, o
|
|
51
|
-
controle aparece
|
|
50
|
+
controle aparece antes do título como ícone com nome acessível e tooltip derivados do destino.
|
|
52
51
|
|
|
53
52
|
```tsx preview col
|
|
54
53
|
<Page>
|
|
@@ -116,31 +115,6 @@ Na composição explícita dentro do shell, use `PageIntro` e `PageBody`:
|
|
|
116
115
|
</PageShell>
|
|
117
116
|
```
|
|
118
117
|
|
|
119
|
-
## Cabeçalho em barra da própria Page
|
|
120
|
-
|
|
121
|
-
Use `PageHeader variant="bar"` quando uma página autocontida conhecer título, retorno e ações. Essa
|
|
122
|
-
forma continua útil fora de um shell persistente. `PageBack` vira icon-only e recebe tooltip e nome
|
|
123
|
-
acessível “Voltar para {destino}”. Use `sm` em botões com texto e `icon-sm` em botões somente com
|
|
124
|
-
ícone.
|
|
125
|
-
|
|
126
|
-
```tsx preview col
|
|
127
|
-
<Page className="max-w-none">
|
|
128
|
-
<PageHeader variant="bar">
|
|
129
|
-
<PageBack href="/customers">Clientes</PageBack>
|
|
130
|
-
<PageTitle>Qualidade da base</PageTitle>
|
|
131
|
-
<PageActions>
|
|
132
|
-
<Button variant="ghost" size="icon-sm" aria-label="Mais ações">
|
|
133
|
-
<Ellipsis />
|
|
134
|
-
</Button>
|
|
135
|
-
</PageActions>
|
|
136
|
-
</PageHeader>
|
|
137
|
-
<PageBody>Conteúdo da análise.</PageBody>
|
|
138
|
-
</Page>
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Não aninhe essa variante em `PageShell`, que já possui a barra. `PageActionsTarget` continua
|
|
142
|
-
disponível para um workspace imersivo que tenha chrome próprio e não use `PageShell`.
|
|
143
|
-
|
|
144
118
|
## Composição explícita
|
|
145
119
|
|
|
146
120
|
Use os slots quando a página precisar compor o header diretamente. Não misture propriedades da
|
|
@@ -228,40 +202,39 @@ estado na própria seção com `DataState`, `ActionView`, `ActionList` ou `Alert
|
|
|
228
202
|
|
|
229
203
|
## Propriedades de PageShell
|
|
230
204
|
|
|
231
|
-
| Propriedade | Tipo | Descrição
|
|
232
|
-
| ----------------- | ----------------------------- |
|
|
233
|
-
| `navigation` | `ReactNode` | Navegação contextual da barra, normalmente um `Breadcrumb`.
|
|
234
|
-
| `actions` | `ReactNode` | Ações conhecidas pelo shell, antes das ações declaradas pela `Page`.
|
|
235
|
-
| `children` | `ReactNode` | Rota que renderiza uma `Page` descendente.
|
|
236
|
-
| `headerClassName` | `string` | Classes adicionais do container interno da barra.
|
|
237
|
-
| `className` | `string` | Classes adicionais da moldura.
|
|
238
|
-
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados à moldura.
|
|
205
|
+
| Propriedade | Tipo | Descrição |
|
|
206
|
+
| ----------------- | ----------------------------- | -------------------------------------------------------------------- |
|
|
207
|
+
| `navigation` | `ReactNode` | Navegação contextual da barra, normalmente um `Breadcrumb`. |
|
|
208
|
+
| `actions` | `ReactNode` | Ações conhecidas pelo shell, antes das ações declaradas pela `Page`. |
|
|
209
|
+
| `children` | `ReactNode` | Rota que renderiza uma `Page` descendente. |
|
|
210
|
+
| `headerClassName` | `string` | Classes adicionais do container interno da barra. |
|
|
211
|
+
| `className` | `string` | Classes adicionais da moldura. |
|
|
212
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados à moldura. |
|
|
239
213
|
|
|
240
214
|
## Propriedades de PageIntro
|
|
241
215
|
|
|
242
|
-
| Propriedade | Tipo | Descrição
|
|
243
|
-
| ----------- | ----------------------------- |
|
|
244
|
-
| `children` | `ReactNode` | Um `PageTitle` e, opcionalmente, descrição e ações
|
|
245
|
-
| `className` | `string` | Classes adicionais da região introdutória.
|
|
246
|
-
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados à região introdutória.
|
|
216
|
+
| Propriedade | Tipo | Descrição |
|
|
217
|
+
| ----------- | ----------------------------- | ------------------------------------------------------------- |
|
|
218
|
+
| `children` | `ReactNode` | Um `PageTitle` e, opcionalmente, `PageBack` ou `PageNavigation`, descrição e ações. |
|
|
219
|
+
| `className` | `string` | Classes adicionais da região introdutória. |
|
|
220
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados à região introdutória. |
|
|
247
221
|
|
|
248
222
|
## Propriedades de PageHeader
|
|
249
223
|
|
|
250
|
-
| Propriedade | Tipo
|
|
251
|
-
| ----------- |
|
|
252
|
-
| `
|
|
253
|
-
| `
|
|
254
|
-
| `children` | `ReactNode` | | Um `PageTitle` e, opcionalmente, `PageBack` ou `PageNavigation`, descrição e ações. |
|
|
224
|
+
| Propriedade | Tipo | Descrição |
|
|
225
|
+
| ----------- | ----------- | ----------------------------------------------------------------------------------- |
|
|
226
|
+
| `className` | `string` | Classes adicionais da região externa do cabeçalho. |
|
|
227
|
+
| `children` | `ReactNode` | Um `PageTitle` e, opcionalmente, `PageBack` ou `PageNavigation`, descrição e ações. |
|
|
255
228
|
|
|
256
229
|
## Propriedades de PageBack
|
|
257
230
|
|
|
258
|
-
| Propriedade | Tipo
|
|
259
|
-
| ------------ |
|
|
260
|
-
| `href` | `string`
|
|
261
|
-
| `children` | `ReactNode`
|
|
262
|
-
| `aria-label` | `string`
|
|
263
|
-
| `onClick` | `MouseEventHandler<HTMLAnchorElement>` |
|
|
264
|
-
| `className` | `string`
|
|
231
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
232
|
+
| ------------ | -------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------ |
|
|
233
|
+
| `href` | `string` | obrigatório | Destino explícito da página pai. Sem ele o retorno não é tabulável nem tem nome acessível. |
|
|
234
|
+
| `children` | `ReactNode` | | Nome do destino pai usado no rótulo acessível e no tooltip. |
|
|
235
|
+
| `aria-label` | `string` | `Voltar para {children}` | Nome acessível; informe-o quando `children` não for texto simples. |
|
|
236
|
+
| `onClick` | `MouseEventHandler<HTMLAnchorElement>` | | Integração opcional com o roteador do consumidor, junto do `href`, nunca no lugar dele. |
|
|
237
|
+
| `className` | `string` | | Classes adicionais do link renderizado como botão `ghost`. |
|
|
265
238
|
|
|
266
239
|
## Propriedades de PageNavigation
|
|
267
240
|
|
|
@@ -269,59 +242,67 @@ estado na própria seção com `DataState`, `ActionView`, `ActionList` ou `Alert
|
|
|
269
242
|
| ----------- | ----------------------------- | ----------------------------------------------- |
|
|
270
243
|
| `children` | `ReactNode` | Trilha estrutural, normalmente um `Breadcrumb`. |
|
|
271
244
|
| `className` | `string` | Classes adicionais do container introdutório. |
|
|
272
|
-
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container.
|
|
245
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
273
246
|
|
|
274
247
|
## Propriedades de PageTitle
|
|
275
248
|
|
|
276
|
-
| Propriedade | Tipo | Descrição
|
|
277
|
-
| ----------- | --------------------------------- |
|
|
278
|
-
| `children` | `ReactNode` | Título principal `h1`;
|
|
279
|
-
| `className` | `string` | Classes adicionais do título.
|
|
280
|
-
| demais | Atributos de `HTMLHeadingElement` | Atributos nativos repassados ao heading.
|
|
249
|
+
| Propriedade | Tipo | Descrição |
|
|
250
|
+
| ----------- | --------------------------------- | ----------------------------------------------- |
|
|
251
|
+
| `children` | `ReactNode` | Título principal `h1`; ampliado em `PageIntro`. |
|
|
252
|
+
| `className` | `string` | Classes adicionais do título. |
|
|
253
|
+
| demais | Atributos de `HTMLHeadingElement` | Atributos nativos repassados ao heading. |
|
|
281
254
|
|
|
282
255
|
## Propriedades de PageDescription
|
|
283
256
|
|
|
284
|
-
| Propriedade | Tipo | Descrição
|
|
285
|
-
| ----------- | ----------------------------------- |
|
|
286
|
-
| `children` | `ReactNode` | Contexto apresentado abaixo do título.
|
|
287
|
-
| `className` | `string` | Classes adicionais da descrição.
|
|
257
|
+
| Propriedade | Tipo | Descrição |
|
|
258
|
+
| ----------- | ----------------------------------- | ------------------------------------------ |
|
|
259
|
+
| `children` | `ReactNode` | Contexto apresentado abaixo do título. |
|
|
260
|
+
| `className` | `string` | Classes adicionais da descrição. |
|
|
288
261
|
| demais | Atributos de `HTMLParagraphElement` | Atributos nativos repassados ao parágrafo. |
|
|
289
262
|
|
|
290
263
|
## Propriedades de PageActions
|
|
291
264
|
|
|
292
|
-
| Propriedade | Tipo
|
|
293
|
-
| ----------- |
|
|
294
|
-
| `children` | `ReactNode`
|
|
295
|
-
| `className` | `string`
|
|
296
|
-
| demais | Atributos de `HTMLDivElement`
|
|
265
|
+
| Propriedade | Tipo | Descrição |
|
|
266
|
+
| ----------- | ----------------------------- | ------------------------------------------ |
|
|
267
|
+
| `children` | `ReactNode` | Ações no extremo oposto do cabeçalho. |
|
|
268
|
+
| `className` | `string` | Classes adicionais da região de ações. |
|
|
269
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
270
|
+
|
|
271
|
+
## Propriedades de PageFooter
|
|
272
|
+
|
|
273
|
+
| Propriedade | Tipo | Descrição |
|
|
274
|
+
| ----------- | ----------------------------- | ------------------------------------------------------------- |
|
|
275
|
+
| `children` | `ReactNode` | Conteúdo persistente após o body, normalmente ações de etapa. |
|
|
276
|
+
| `className` | `string` | Classes adicionais do rodapé. |
|
|
277
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao rodapé. |
|
|
297
278
|
|
|
298
279
|
## Propriedades de PageBody
|
|
299
280
|
|
|
300
|
-
| Propriedade | Tipo | Descrição
|
|
301
|
-
| ----------- | ----------------------------- |
|
|
302
|
-
| `children` | `ReactNode` | Conteúdo principal
|
|
303
|
-
| `className` | `string` | Classes adicionais da região principal.
|
|
304
|
-
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container.
|
|
281
|
+
| Propriedade | Tipo | Descrição |
|
|
282
|
+
| ----------- | ----------------------------- | ------------------------------------------ |
|
|
283
|
+
| `children` | `ReactNode` | Conteúdo principal da página. |
|
|
284
|
+
| `className` | `string` | Classes adicionais da região principal. |
|
|
285
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
305
286
|
|
|
306
287
|
## Propriedades de PageActionsTarget
|
|
307
288
|
|
|
308
|
-
| Propriedade | Tipo
|
|
309
|
-
| ----------- |
|
|
310
|
-
| `target` | `HTMLElement \| null` | Destino externo das ações; `null` mantém as ações no header.
|
|
311
|
-
| `children` | `ReactNode`
|
|
289
|
+
| Propriedade | Tipo | Descrição |
|
|
290
|
+
| ----------- | --------------------- | ------------------------------------------------------------ |
|
|
291
|
+
| `target` | `HTMLElement \| null` | Destino externo das ações; `null` mantém as ações no header. |
|
|
292
|
+
| `children` | `ReactNode` | Árvore de página que poderá declarar `PageActions`. |
|
|
312
293
|
|
|
313
294
|
## Propriedades de PageState
|
|
314
295
|
|
|
315
|
-
| Propriedade | Tipo | Padrão | Descrição
|
|
316
|
-
| -------------- | -------------------------------------------- | ----------------------------------------- |
|
|
317
|
-
| `status` | `'loading' \| 'error' \| 'empty' \| 'ready'` | | Estado integral do conteúdo.
|
|
318
|
-
| `title` | `ReactNode` | Texto seguro por estado | Situação reconhecível pela pessoa.
|
|
319
|
-
| `description` | `ReactNode` | | Impacto ou próximo passo aplicável.
|
|
320
|
-
| `icon` | `ReactNode` | Alerta no erro | Ícone decorativo do estado.
|
|
296
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
297
|
+
| -------------- | -------------------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
298
|
+
| `status` | `'loading' \| 'error' \| 'empty' \| 'ready'` | | Estado integral do conteúdo. |
|
|
299
|
+
| `title` | `ReactNode` | Texto seguro por estado | Situação reconhecível pela pessoa. |
|
|
300
|
+
| `description` | `ReactNode` | | Impacto ou próximo passo aplicável. |
|
|
301
|
+
| `icon` | `ReactNode` | Alerta no erro | Ícone decorativo do estado. |
|
|
321
302
|
| `action` | `ReactNode` | | Seleção, criação ou saída aplicável ao estado — inclusive o retorno ao pai, já que o cabeçalho está oculto. |
|
|
322
|
-
| `emptyMessage` | `string` | `'Nada por aqui'` | Título do vazio quando `title` não é informado.
|
|
323
|
-
| `errorMessage` | `string` | `'Não foi possível carregar esta página'` | Título do erro quando `title` não é informado.
|
|
324
|
-
| `onRetry` | `() => void \| Promise<void>` | | Recuperação do erro: acrescenta um botão `outline` textual ao lado de `action`.
|
|
325
|
-
| `retryLabel` | `string` | `'Tentar de novo'` | Texto do botão de recuperação.
|
|
326
|
-
| `children` | `ReactNode` | | Conteúdo renderizado somente em `ready`.
|
|
327
|
-
| `className` | `string` | | Classes da superfície de estado.
|
|
303
|
+
| `emptyMessage` | `string` | `'Nada por aqui'` | Título do vazio quando `title` não é informado. |
|
|
304
|
+
| `errorMessage` | `string` | `'Não foi possível carregar esta página'` | Título do erro quando `title` não é informado. |
|
|
305
|
+
| `onRetry` | `() => void \| Promise<void>` | | Recuperação do erro: acrescenta um botão `outline` textual ao lado de `action`. |
|
|
306
|
+
| `retryLabel` | `string` | `'Tentar de novo'` | Texto do botão de recuperação. |
|
|
307
|
+
| `children` | `ReactNode` | | Conteúdo renderizado somente em `ready`. |
|
|
308
|
+
| `className` | `string` | | Classes da superfície de estado. |
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
`Presentation` preserva a identidade de um recurso quando a experiência pede uma página, um dialog ou
|
|
2
|
+
um drawer. A superfície decide quanto espaço ocupar; o recurso continua com a mesma navegação,
|
|
3
|
+
cabeçalho, body e rodapé.
|
|
4
|
+
|
|
5
|
+
Nas três superfícies, o cabeçalho usa a mesma ordem horizontal: navegação ou retorno, título e ações.
|
|
6
|
+
Dialog e Drawer acrescentam o fechamento ao final. Uma Page pode apresentar um `PageIntro` separado
|
|
7
|
+
no body quando o conteúdo realmente precisar de uma introdução; ele não substitui nem duplica o
|
|
8
|
+
título estrutural da Presentation.
|
|
9
|
+
|
|
10
|
+
Use esse padrão quando uma lista puder abrir um detalhe lateral, quando a mesma edição precisar
|
|
11
|
+
funcionar em modal e em rota própria ou quando um fluxo começar compacto e crescer sem ganhar uma
|
|
12
|
+
segunda implementação.
|
|
13
|
+
|
|
14
|
+
Dentro de `PageShell`, a superfície `page` usa a anatomia real da aplicação: o shell preserva sua
|
|
15
|
+
barra, e a Presentation compõe `Page`, `PageIntro`, `PageBody` e, quando necessário, `PageFooter`.
|
|
16
|
+
Fora do shell, ela materializa o `PageHeader` completo para exemplos e superfícies independentes.
|
|
17
|
+
Não envolva a Presentation em um card para simular a página; valide proporção, rolagem e ações no
|
|
18
|
+
shell que efetivamente hospeda a rota.
|
|
19
|
+
|
|
20
|
+
```tsx live
|
|
21
|
+
function Example() {
|
|
22
|
+
const [surface, setSurface] = React.useState("page");
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className="space-y-4">
|
|
26
|
+
<ButtonGroup mode="spaced">
|
|
27
|
+
{["page", "dialog", "drawer"].map((value) => (
|
|
28
|
+
<Button
|
|
29
|
+
key={value}
|
|
30
|
+
size="sm"
|
|
31
|
+
variant={surface === value ? "solid" : "outline"}
|
|
32
|
+
onClick={() => setSurface(value)}
|
|
33
|
+
>
|
|
34
|
+
{value}
|
|
35
|
+
</Button>
|
|
36
|
+
))}
|
|
37
|
+
</ButtonGroup>
|
|
38
|
+
|
|
39
|
+
<Presentation
|
|
40
|
+
surface={surface}
|
|
41
|
+
title="Workspace"
|
|
42
|
+
headerActions={
|
|
43
|
+
<Button size="sm" variant="ghost">
|
|
44
|
+
Arquivar
|
|
45
|
+
</Button>
|
|
46
|
+
}
|
|
47
|
+
footerActions={
|
|
48
|
+
<>
|
|
49
|
+
<Button variant="outline">Cancelar</Button>
|
|
50
|
+
<Button context="primary">Salvar</Button>
|
|
51
|
+
</>
|
|
52
|
+
}
|
|
53
|
+
>
|
|
54
|
+
<Content title="Dados gerais">
|
|
55
|
+
O renderer injeta aqui o formulário, a lista ou a visualização ligada
|
|
56
|
+
à action.
|
|
57
|
+
</Content>
|
|
58
|
+
</Presentation>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
render(<Example />);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## A declaração
|
|
67
|
+
|
|
68
|
+
`definePresentation` cria o artefato serializável. O body recebe uma action `form`, `list` ou
|
|
69
|
+
`view`; uma action `simple` aparece como comando no cabeçalho ou no rodapé. Actions que precisam de
|
|
70
|
+
interface abrem outra Presentation. Bindings fornecem valores vindos da rota, do registro, da
|
|
71
|
+
seleção, da sessão ou do resultado anterior sem guardar callbacks no JSON.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const workspaceList = definePresentation({
|
|
75
|
+
schemaVersion: 1,
|
|
76
|
+
id: "workspace.list",
|
|
77
|
+
title: "Workspaces",
|
|
78
|
+
body: {
|
|
79
|
+
action: "workspace.list",
|
|
80
|
+
open: {
|
|
81
|
+
presentation: "workspace.view",
|
|
82
|
+
input: { workspaceId: { source: "item", field: "id" } },
|
|
83
|
+
surface: "drawer",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
actions: [
|
|
87
|
+
{
|
|
88
|
+
action: "workspace.create",
|
|
89
|
+
placement: "header",
|
|
90
|
+
target: { presentation: "workspace.create", surface: "dialog" },
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Registre as declarações em `presentations` no `opus.config.ts`. `opus gen` valida as referências e
|
|
97
|
+
projeta o JSON no manifest; a Lens pode então exibir o artefato completo sem reconstruí-lo a partir
|
|
98
|
+
do JSX.
|
|
99
|
+
|
|
100
|
+
## A invocação
|
|
101
|
+
|
|
102
|
+
`definePresentationInvocation` cria o estado vivo de uma exibição. Ele contém somente valores JSON,
|
|
103
|
+
a surface atual e a pilha necessária para voltar. A definição continua estática no manifest; input
|
|
104
|
+
de rota, sessão e resultado existe apenas na invocação.
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
const invocation = definePresentationInvocation({
|
|
108
|
+
schemaVersion: 1,
|
|
109
|
+
presentationId: "workspace.view",
|
|
110
|
+
surface: "drawer",
|
|
111
|
+
input: { workspaceId: "workspace-1" },
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`openPresentation` empilha a exibição atual; `backPresentation` restaura o frame anterior.
|
|
116
|
+
`closePresentation` encerra dialog ou drawer e recusa page. Efeitos `navigate` escolhem `push` ou
|
|
117
|
+
`replace`. A aplicação sincroniza a invocação com a URL apenas quando ela precisar sobreviver a
|
|
118
|
+
refresh, deep link ou histórico.
|
|
119
|
+
|
|
120
|
+
## Inspecionar o JSON
|
|
121
|
+
|
|
122
|
+
`PresentationInspector` renderiza um botão somente com ícone. Ao acioná-lo, reúne definição,
|
|
123
|
+
invocação, bindings resolvidos e diagnósticos em um único JSON e oferece a cópia do conteúdo. Chaves
|
|
124
|
+
sensíveis são mascaradas. Use a ferramenta em ambientes de desenvolvimento ou no Studio; a Lens
|
|
125
|
+
expõe somente a definição estática e a ferramenta não faz parte da navegação do recurso para a
|
|
126
|
+
pessoa usuária.
|
|
127
|
+
|
|
128
|
+
Use `floating` quando o inspetor precisar ficar disponível sem ocupar o cabeçalho. O componente
|
|
129
|
+
aplica tamanho, forma, borda e elevação de FAB; `className` define a âncora na superfície consumidora.
|
|
130
|
+
Reserve espaço para outros controles flutuantes do shell em vez de sobrepô-los.
|
|
131
|
+
|
|
132
|
+
## Propriedades de Presentation
|
|
133
|
+
|
|
134
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
135
|
+
| --------------- | -------------------------------- | ------ | --------------------------------------------------------------------- |
|
|
136
|
+
| `surface` | `'page' \| 'dialog' \| 'drawer'` | | Superfície que hospeda o recurso. |
|
|
137
|
+
| `title` | `ReactNode` | | Nome da Presentation no cabeçalho. |
|
|
138
|
+
| `navigation` | `ReactNode` | | Voltar ou navegação relativa, quando existir. |
|
|
139
|
+
| `headerActions` | `ReactNode` | | Comandos contextuais no cabeçalho. |
|
|
140
|
+
| `footerActions` | `ReactNode` | | Comandos de progressão; Dialog e Drawer dividem a largura disponível. |
|
|
141
|
+
| `children` | `ReactNode` | | Formulário, lista ou visualização do body. |
|
|
142
|
+
| `open` | `boolean` | | Estado controlado de Dialog ou Drawer; omitido, começa aberto e fecha internamente. |
|
|
143
|
+
| `onOpenChange` | `(open: boolean) => void` | | Notifica abertura e fechamento da superfície modal. |
|
|
144
|
+
| `className` | `string` | | Classes adicionais da superfície. |
|
|
145
|
+
| `bodyClassName` | `string` | | Classes adicionais do body. |
|
|
146
|
+
|
|
147
|
+
## Propriedades de PresentationInspector
|
|
148
|
+
|
|
149
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
150
|
+
| -------------- | -------------------------- | -------------------------- | ----------------------------------------- |
|
|
151
|
+
| `definition` | `unknown` | | Definição estática exibida no snapshot. |
|
|
152
|
+
| `invocation` | `unknown` | | Estado vivo serializável, quando existir. |
|
|
153
|
+
| `resolved` | `unknown` | | Bindings resolvidos pelo renderer. |
|
|
154
|
+
| `diagnostics` | `PresentationDiagnostic[]` | | Diagnósticos da definição ou execução. |
|
|
155
|
+
| `triggerLabel` | `string` | `Ver JSON da Presentation` | Nome acessível e tooltip do botão. |
|
|
156
|
+
| `title` | `string` | `JSON da Presentation` | Título do dialog de inspeção. |
|
|
157
|
+
| `floating` | `boolean` | `false` | Apresenta o gatilho com aparência de FAB. |
|
|
158
|
+
| `className` | `string` | | Classes adicionais do gatilho. |
|
package/src/ui/docs/registry.tsx
CHANGED
|
@@ -117,6 +117,7 @@ import actionViewMd from "./content/action-view.md?raw";
|
|
|
117
117
|
import actionTriggerMd from "./content/action-trigger.md?raw";
|
|
118
118
|
import actionSearchDialogMd from "./content/action-list-dialog.md?raw";
|
|
119
119
|
import pageMd from "./content/page.md?raw";
|
|
120
|
+
import presentationMd from "./content/presentation.md?raw";
|
|
120
121
|
import contentMd from "./content/content.md?raw";
|
|
121
122
|
import sidebarMd from "./content/sidebar.md?raw";
|
|
122
123
|
import splitMd from "./content/split.md?raw";
|
|
@@ -402,6 +403,11 @@ export const UI_SECTIONS: DocSection[] = [
|
|
|
402
403
|
title: "Page",
|
|
403
404
|
render: pattern("Page", "page", pageMd),
|
|
404
405
|
},
|
|
406
|
+
{
|
|
407
|
+
slug: "presentation",
|
|
408
|
+
title: "Presentation",
|
|
409
|
+
render: pattern("Presentation", "presentation", presentationMd),
|
|
410
|
+
},
|
|
405
411
|
{
|
|
406
412
|
slug: "content",
|
|
407
413
|
title: "Content",
|
package/src/ui/meta.ts
CHANGED
|
@@ -400,7 +400,13 @@ export const componentMeta = {
|
|
|
400
400
|
name: "page",
|
|
401
401
|
ancestry: "opus",
|
|
402
402
|
whenToUse:
|
|
403
|
-
"O esqueleto de página do back-office: <main> + container centralizado com teto padrão de 80rem (`max-w-7xl`). O shorthand cobre título, descrição e ações. Quando shell e rota conhecem partes diferentes da página, PageShell mantém a barra de 3rem, recebe a navegação e projeta as ações da Page; título e descrição formam PageIntro no conteúdo. Fora dele, a forma explícita escolhe PageHeader para o cabeçalho completo ou PageIntro para uma introdução sem navegação
|
|
403
|
+
"O esqueleto de página do back-office: <main> + container centralizado com teto padrão de 80rem (`max-w-7xl`). O shorthand cobre título, descrição e ações. Quando shell e rota conhecem partes diferentes da página, PageShell mantém a barra de 3rem, recebe a navegação e projeta as ações da Page; título e descrição formam PageIntro no conteúdo. Fora dele, a forma explícita escolhe PageHeader para o cabeçalho completo ou PageIntro para uma introdução sem navegação. PageActionsTarget fica restrito a workspaces imersivos sem PageShell. PageState oculta o header da Page isolada ou somente PageIntro dentro de PageShell. Para uma região disponível à criação ou vínculo, use Empty.",
|
|
404
|
+
},
|
|
405
|
+
presentation: {
|
|
406
|
+
name: "presentation",
|
|
407
|
+
ancestry: "opus",
|
|
408
|
+
whenToUse:
|
|
409
|
+
"Descreva um recurso que precisa manter a mesma anatomia ao aparecer como Page, Dialog ou Drawer. Presentation organiza navegação, título, ações de cabeçalho, body e ações de rodapé sem redefinir o conteúdo para cada superfície. A definição persistente liga esses slots a actions Opus; a invocação carrega o estado JSON da execução. PresentationInspector reúne definição, invocação, bindings resolvidos e diagnósticos com dados sensíveis mascarados.",
|
|
404
410
|
},
|
|
405
411
|
router: {
|
|
406
412
|
name: "router",
|
|
@@ -418,7 +424,7 @@ export const componentMeta = {
|
|
|
418
424
|
name: "action-list-dialog",
|
|
419
425
|
ancestry: "opus",
|
|
420
426
|
whenToUse:
|
|
421
|
-
"Apresente uma ListAction dentro de um modal com título,
|
|
427
|
+
"Apresente uma ListAction dentro de um modal com título, total e ação relacionada. Contexto realmente necessário entra no início do corpo por `intro`. Os filhos recebem itens e `refetch` para definir a composição da lista. Para uma coleção na página, use ActionList; para um formulário modal, use ActionFormDialog.",
|
|
422
428
|
},
|
|
423
429
|
} as const satisfies Record<string, ComponentMeta>;
|
|
424
430
|
|
package/src/ui/react.tsx
CHANGED
|
@@ -135,7 +135,6 @@ export {
|
|
|
135
135
|
DialogBody,
|
|
136
136
|
DialogFooter,
|
|
137
137
|
DialogTitle,
|
|
138
|
-
DialogDescription,
|
|
139
138
|
} from "./components/primitives/dialog.tsx";
|
|
140
139
|
export type {
|
|
141
140
|
DialogProps,
|
|
@@ -272,7 +271,6 @@ export {
|
|
|
272
271
|
Drawer,
|
|
273
272
|
DrawerClose,
|
|
274
273
|
DrawerContent,
|
|
275
|
-
DrawerDescription,
|
|
276
274
|
DrawerFooter,
|
|
277
275
|
DrawerHeader,
|
|
278
276
|
DrawerBody,
|
|
@@ -420,6 +418,15 @@ export type { ActionListDialogProps } from "./components/patterns/action-list-di
|
|
|
420
418
|
export { DataState } from "./components/patterns/data-state.tsx";
|
|
421
419
|
export type { DataStateProps } from "./components/patterns/data-state.tsx";
|
|
422
420
|
|
|
421
|
+
export {
|
|
422
|
+
Presentation,
|
|
423
|
+
PresentationInspector,
|
|
424
|
+
} from "./components/patterns/presentation.tsx";
|
|
425
|
+
export type {
|
|
426
|
+
PresentationProps,
|
|
427
|
+
PresentationInspectorProps,
|
|
428
|
+
} from "./components/patterns/presentation.tsx";
|
|
429
|
+
|
|
423
430
|
// Esqueleto de página do back-office (main + container + header título/descrição/ação).
|
|
424
431
|
export {
|
|
425
432
|
PageShell,
|
|
@@ -433,13 +440,13 @@ export {
|
|
|
433
440
|
PageActions,
|
|
434
441
|
PageActionsTarget,
|
|
435
442
|
PageBody,
|
|
443
|
+
PageFooter,
|
|
436
444
|
} from "./components/patterns/page.tsx";
|
|
437
445
|
export type {
|
|
438
446
|
PageProps,
|
|
439
447
|
PageShellProps,
|
|
440
448
|
PageBackProps,
|
|
441
449
|
PageHeaderProps,
|
|
442
|
-
PageHeaderVariant,
|
|
443
450
|
} from "./components/patterns/page.tsx";
|
|
444
451
|
|
|
445
452
|
// Estado integral do conteúdo de Page (loading/error/empty/ready), sem acoplar Page a dados.
|