@softize/opus 12.10.0 → 12.11.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/bin/lib/check.mjs +1103 -310
  3. package/bin/lib/copy.mjs +11 -0
  4. package/docs/adr/0003-dictionary-presentation-is-declared.md +3 -0
  5. package/docs/adr/0004-page-content-state-is-composed.md +65 -0
  6. package/docs/adr/0005-structural-surfaces-share-an-explicit-anatomy.md +97 -0
  7. package/docs/adr/0006-semantic-context-precedes-visual-variant.md +182 -0
  8. package/package.json +1 -1
  9. package/registry/instructions/opus.md +5 -0
  10. package/registry/skills/build-opus-ui/SKILL.md +27 -16
  11. package/registry/skills/build-opus-ui/references/evaluations.md +16 -5
  12. package/registry/skills/build-opus-ui/references/ui-patterns.md +38 -15
  13. package/registry/skills/model-opus-dictionary/SKILL.md +4 -2
  14. package/registry/skills/model-opus-dictionary/references/evaluations.md +4 -3
  15. package/registry/templates/app/src/App.tsx +1 -1
  16. package/src/core/dictionary.ts +52 -14
  17. package/src/core/index.ts +10 -0
  18. package/src/core/ui-context.ts +29 -0
  19. package/src/schema/drivers/zod.ts +17 -8
  20. package/src/ui/components/patterns/action-form-card.tsx +18 -12
  21. package/src/ui/components/patterns/confirm.tsx +26 -3
  22. package/src/ui/components/patterns/content-header.tsx +335 -61
  23. package/src/ui/components/patterns/data-state.tsx +23 -10
  24. package/src/ui/components/patterns/list.tsx +1096 -777
  25. package/src/ui/components/patterns/page-state.tsx +115 -0
  26. package/src/ui/components/patterns/page.tsx +231 -41
  27. package/src/ui/components/patterns/sidebar.tsx +354 -80
  28. package/src/ui/components/patterns/trigger.tsx +13 -9
  29. package/src/ui/components/patterns/view.tsx +7 -11
  30. package/src/ui/components/primitives/alert-dialog.tsx +7 -5
  31. package/src/ui/components/primitives/alert.tsx +298 -110
  32. package/src/ui/components/primitives/ask.tsx +2 -1
  33. package/src/ui/components/primitives/badge.tsx +91 -30
  34. package/src/ui/components/primitives/button.tsx +99 -60
  35. package/src/ui/components/primitives/calendar.tsx +39 -39
  36. package/src/ui/components/primitives/card.tsx +96 -23
  37. package/src/ui/components/primitives/detail.tsx +2 -2
  38. package/src/ui/components/primitives/dictionary-value.tsx +9 -14
  39. package/src/ui/components/primitives/dot.tsx +74 -21
  40. package/src/ui/components/primitives/drawer.tsx +33 -20
  41. package/src/ui/components/primitives/item.tsx +137 -81
  42. package/src/ui/components/primitives/menu.tsx +11 -3
  43. package/src/ui/components/primitives/metric-card.tsx +133 -0
  44. package/src/ui/components/primitives/table.tsx +2 -2
  45. package/src/ui/docs/DocBrowser.tsx +3 -3
  46. package/src/ui/docs/changelog.tsx +1 -1
  47. package/src/ui/docs/content/action-form-card.md +1 -1
  48. package/src/ui/docs/content/alert-dialog.md +8 -8
  49. package/src/ui/docs/content/alert.md +49 -25
  50. package/src/ui/docs/content/badge.md +18 -19
  51. package/src/ui/docs/content/button.md +12 -9
  52. package/src/ui/docs/content/card.md +5 -5
  53. package/src/ui/docs/content/content.md +44 -0
  54. package/src/ui/docs/content/customization.md +2 -2
  55. package/src/ui/docs/content/detail.md +5 -2
  56. package/src/ui/docs/content/dialog.md +2 -2
  57. package/src/ui/docs/content/dictionary-value.md +11 -10
  58. package/src/ui/docs/content/dot.md +7 -7
  59. package/src/ui/docs/content/drawer.md +6 -3
  60. package/src/ui/docs/content/input-group.md +3 -2
  61. package/src/ui/docs/content/item.md +47 -21
  62. package/src/ui/docs/content/menu.md +5 -4
  63. package/src/ui/docs/content/metric-card.md +41 -0
  64. package/src/ui/docs/content/page-state.md +45 -0
  65. package/src/ui/docs/content/page.md +48 -10
  66. package/src/ui/docs/content/semantic-context.md +63 -0
  67. package/src/ui/docs/content/sidebar.md +4 -4
  68. package/src/ui/docs/content/skeleton.md +2 -2
  69. package/src/ui/docs/content/table.md +3 -3
  70. package/src/ui/docs/content/tokens.md +28 -0
  71. package/src/ui/docs/doc-client.tsx +2 -2
  72. package/src/ui/docs/registry.tsx +596 -228
  73. package/src/ui/lib/semantic-context.ts +30 -0
  74. package/src/ui/meta.ts +292 -270
  75. package/src/ui/react.tsx +378 -111
  76. package/src/ui/theme.css +66 -0
@@ -10,96 +10,98 @@
10
10
  * componente ganham o cabeçalho (título + badge de origem + whenToUse) do `meta` central via o
11
11
  * helper `comp`; páginas conceituais renderizam o markdown direto (o próprio md traz o H1/lead).
12
12
  */
13
- import { useEffect } from 'react'
14
- import * as lucideIcons from 'lucide-react'
15
- import * as opusUi from '../react.tsx'
16
- import { componentMeta } from '../meta.ts'
17
- import { navigate } from '../router.ts'
18
- import { DocPage } from './doc.tsx'
19
- import { DocMarkdown } from './markdown.tsx'
20
- import { OpusChangelog } from './changelog.tsx'
13
+ import { useEffect } from "react";
14
+ import * as lucideIcons from "lucide-react";
15
+ import * as opusUi from "../react.tsx";
16
+ import { componentMeta } from "../meta.ts";
17
+ import { navigate } from "../router.ts";
18
+ import { DocPage } from "./doc.tsx";
19
+ import { DocMarkdown } from "./markdown.tsx";
20
+ import { OpusChangelog } from "./changelog.tsx";
21
21
 
22
22
  // — Conceituais (Começar/Framework/Design/Introdução) —
23
- import gettingStartedMd from './content/getting-started.md?raw'
24
- import upgradingMd from './content/upgrading.md?raw'
25
- import cycleMd from './content/cycle.md?raw'
26
- import authMd from './content/auth.md?raw'
27
- import auditMd from './content/audit.md?raw'
28
- import eventsMd from './content/events.md?raw'
29
- import logMd from './content/log.md?raw'
30
- import queueMd from './content/queue.md?raw'
31
- import schedulerMd from './content/scheduler.md?raw'
32
- import actionsMd from './content/actions.md?raw'
33
- import dataMd from './content/data.md?raw'
34
- import storageMd from './content/storage.md?raw'
35
- import aiMd from './content/ai.md?raw'
36
- import mcpMd from './content/mcp.md?raw'
37
- import testingMd from './content/testing.md?raw'
38
- import runtimeMd from './content/runtime.md?raw'
39
- import uiMd from './content/ui.md?raw'
40
- import cliMd from './content/cli.md?raw'
41
- import tokensMd from './content/tokens.md?raw'
42
- import communicationMd from './content/communication.md?raw'
43
- import customizationMd from './content/customization.md?raw'
23
+ import gettingStartedMd from "./content/getting-started.md?raw";
24
+ import upgradingMd from "./content/upgrading.md?raw";
25
+ import cycleMd from "./content/cycle.md?raw";
26
+ import authMd from "./content/auth.md?raw";
27
+ import auditMd from "./content/audit.md?raw";
28
+ import eventsMd from "./content/events.md?raw";
29
+ import logMd from "./content/log.md?raw";
30
+ import queueMd from "./content/queue.md?raw";
31
+ import schedulerMd from "./content/scheduler.md?raw";
32
+ import actionsMd from "./content/actions.md?raw";
33
+ import dataMd from "./content/data.md?raw";
34
+ import storageMd from "./content/storage.md?raw";
35
+ import aiMd from "./content/ai.md?raw";
36
+ import mcpMd from "./content/mcp.md?raw";
37
+ import testingMd from "./content/testing.md?raw";
38
+ import runtimeMd from "./content/runtime.md?raw";
39
+ import uiMd from "./content/ui.md?raw";
40
+ import cliMd from "./content/cli.md?raw";
41
+ import tokensMd from "./content/tokens.md?raw";
42
+ import semanticContextMd from "./content/semantic-context.md?raw";
43
+ import communicationMd from "./content/communication.md?raw";
44
+ import customizationMd from "./content/customization.md?raw";
44
45
 
45
46
  // — Componentes —
46
- import accordionMd from './content/accordion.md?raw'
47
- import alertMd from './content/alert.md?raw'
48
- import alertDialogMd from './content/alert-dialog.md?raw'
49
- import confirmMd from './content/confirm.md?raw'
50
- import aspectRatioMd from './content/aspect-ratio.md?raw'
51
- import avatarMd from './content/avatar.md?raw'
52
- import badgeMd from './content/badge.md?raw'
53
- import dotMd from './content/dot.md?raw'
54
- import dockMd from './content/dock.md?raw'
55
- import breadcrumbMd from './content/breadcrumb.md?raw'
56
- import buttonMd from './content/button.md?raw'
57
- import buttonGroupMd from './content/button-group.md?raw'
58
- import calendarMd from './content/calendar.md?raw'
59
- import cardMd from './content/card.md?raw'
60
- import carouselMd from './content/carousel.md?raw'
61
- import askMd from './content/ask.md?raw'
62
- import chatMd from './content/chat.md?raw'
63
- import checkboxMd from './content/checkbox.md?raw'
64
- import collapsibleMd from './content/collapsible.md?raw'
65
- import iconPickerMd from './content/icon-picker.md?raw'
66
- import commandMd from './content/command.md?raw'
67
- import composerMd from './content/composer.md?raw'
68
- import copyableMd from './content/copyable.md?raw'
69
- import dialogMd from './content/dialog.md?raw'
70
- import detailMd from './content/detail.md?raw'
71
- import dictionaryValueMd from './content/dictionary-value.md?raw'
72
- import emptyValueMd from './content/empty-value.md?raw'
73
- import drawerMd from './content/drawer.md?raw'
74
- import menuMd from './content/menu.md?raw'
75
- import emptyMd from './content/empty.md?raw'
76
- import fieldMd from './content/field.md?raw'
77
- import inputMd from './content/input.md?raw'
78
- import inputGroupMd from './content/input-group.md?raw'
79
- import inputOtpMd from './content/input-otp.md?raw'
80
- import itemMd from './content/item.md?raw'
81
- import kbdMd from './content/kbd.md?raw'
82
- import labelMd from './content/label.md?raw'
83
- import markdownMd from './content/markdown.md?raw'
84
- import paginationMd from './content/pagination.md?raw'
85
- import popoverMd from './content/popover.md?raw'
86
- import progressMd from './content/progress.md?raw'
87
- import radioGroupMd from './content/radio-group.md?raw'
88
- import scrollAreaMd from './content/scroll-area.md?raw'
89
- import selectMd from './content/select.md?raw'
90
- import separatorMd from './content/separator.md?raw'
91
- import skeletonMd from './content/skeleton.md?raw'
92
- import sliderMd from './content/slider.md?raw'
93
- import spinnerMd from './content/spinner.md?raw'
94
- import switchMd from './content/switch.md?raw'
95
- import tableMd from './content/table.md?raw'
96
- import tabsMd from './content/tabs.md?raw'
97
- import textareaMd from './content/textarea.md?raw'
98
- import toastMd from './content/toast.md?raw'
99
- import toggleMd from './content/toggle.md?raw'
100
- import toggleGroupMd from './content/toggle-group.md?raw'
101
- import tooltipMd from './content/tooltip.md?raw'
102
- import truncateMd from './content/truncate.md?raw'
47
+ import accordionMd from "./content/accordion.md?raw";
48
+ import alertMd from "./content/alert.md?raw";
49
+ import alertDialogMd from "./content/alert-dialog.md?raw";
50
+ import confirmMd from "./content/confirm.md?raw";
51
+ import aspectRatioMd from "./content/aspect-ratio.md?raw";
52
+ import avatarMd from "./content/avatar.md?raw";
53
+ import badgeMd from "./content/badge.md?raw";
54
+ import dotMd from "./content/dot.md?raw";
55
+ import dockMd from "./content/dock.md?raw";
56
+ import breadcrumbMd from "./content/breadcrumb.md?raw";
57
+ import buttonMd from "./content/button.md?raw";
58
+ import buttonGroupMd from "./content/button-group.md?raw";
59
+ import calendarMd from "./content/calendar.md?raw";
60
+ import cardMd from "./content/card.md?raw";
61
+ import metricCardMd from "./content/metric-card.md?raw";
62
+ import carouselMd from "./content/carousel.md?raw";
63
+ import askMd from "./content/ask.md?raw";
64
+ import chatMd from "./content/chat.md?raw";
65
+ import checkboxMd from "./content/checkbox.md?raw";
66
+ import collapsibleMd from "./content/collapsible.md?raw";
67
+ import iconPickerMd from "./content/icon-picker.md?raw";
68
+ import commandMd from "./content/command.md?raw";
69
+ import composerMd from "./content/composer.md?raw";
70
+ import copyableMd from "./content/copyable.md?raw";
71
+ import dialogMd from "./content/dialog.md?raw";
72
+ import detailMd from "./content/detail.md?raw";
73
+ import dictionaryValueMd from "./content/dictionary-value.md?raw";
74
+ import emptyValueMd from "./content/empty-value.md?raw";
75
+ import drawerMd from "./content/drawer.md?raw";
76
+ import menuMd from "./content/menu.md?raw";
77
+ import emptyMd from "./content/empty.md?raw";
78
+ import fieldMd from "./content/field.md?raw";
79
+ import inputMd from "./content/input.md?raw";
80
+ import inputGroupMd from "./content/input-group.md?raw";
81
+ import inputOtpMd from "./content/input-otp.md?raw";
82
+ import itemMd from "./content/item.md?raw";
83
+ import kbdMd from "./content/kbd.md?raw";
84
+ import labelMd from "./content/label.md?raw";
85
+ import markdownMd from "./content/markdown.md?raw";
86
+ import paginationMd from "./content/pagination.md?raw";
87
+ import popoverMd from "./content/popover.md?raw";
88
+ import progressMd from "./content/progress.md?raw";
89
+ import radioGroupMd from "./content/radio-group.md?raw";
90
+ import scrollAreaMd from "./content/scroll-area.md?raw";
91
+ import selectMd from "./content/select.md?raw";
92
+ import separatorMd from "./content/separator.md?raw";
93
+ import skeletonMd from "./content/skeleton.md?raw";
94
+ import sliderMd from "./content/slider.md?raw";
95
+ import spinnerMd from "./content/spinner.md?raw";
96
+ import switchMd from "./content/switch.md?raw";
97
+ import tableMd from "./content/table.md?raw";
98
+ import tabsMd from "./content/tabs.md?raw";
99
+ import textareaMd from "./content/textarea.md?raw";
100
+ import toastMd from "./content/toast.md?raw";
101
+ import toggleMd from "./content/toggle.md?raw";
102
+ import toggleGroupMd from "./content/toggle-group.md?raw";
103
+ import tooltipMd from "./content/tooltip.md?raw";
104
+ import truncateMd from "./content/truncate.md?raw";
103
105
 
104
106
  // — Patterns (markdown + palco doc-client injetado no scope dos previews) —
105
107
  import {
@@ -110,37 +112,39 @@ import {
110
112
  docWorkspaceList,
111
113
  docWorkspaceStatus,
112
114
  docWorkspaceView,
113
- } from './doc-client'
114
- import actionFormMd from './content/action-form.md?raw'
115
- import actionFormDialogMd from './content/action-form-dialog.md?raw'
116
- import actionFormCardMd from './content/action-form-card.md?raw'
117
- import actionSearchMd from './content/action-list.md?raw'
118
- import actionViewMd from './content/action-view.md?raw'
119
- import actionTriggerMd from './content/action-trigger.md?raw'
120
- import actionSearchDialogMd from './content/action-list-dialog.md?raw'
121
- import pageMd from './content/page.md?raw'
122
- import sidebarMd from './content/sidebar.md?raw'
123
- import splitMd from './content/split.md?raw'
124
- import routerMd from './content/router.md?raw'
125
- import dataStateMd from './content/data-state.md?raw'
115
+ } from "./doc-client";
116
+ import actionFormMd from "./content/action-form.md?raw";
117
+ import actionFormDialogMd from "./content/action-form-dialog.md?raw";
118
+ import actionFormCardMd from "./content/action-form-card.md?raw";
119
+ import actionSearchMd from "./content/action-list.md?raw";
120
+ import actionViewMd from "./content/action-view.md?raw";
121
+ import actionTriggerMd from "./content/action-trigger.md?raw";
122
+ import actionSearchDialogMd from "./content/action-list-dialog.md?raw";
123
+ import pageMd from "./content/page.md?raw";
124
+ import contentMd from "./content/content.md?raw";
125
+ import pageStateMd from "./content/page-state.md?raw";
126
+ import sidebarMd from "./content/sidebar.md?raw";
127
+ import splitMd from "./content/split.md?raw";
128
+ import routerMd from "./content/router.md?raw";
129
+ import dataStateMd from "./content/data-state.md?raw";
126
130
 
127
131
  export interface DocEntry {
128
- slug: string
129
- title: string
132
+ slug: string;
133
+ title: string;
130
134
  /** Tag técnica opcional exibida na nav ao lado do título — o subpath do SDK (ex.: 'auth'). */
131
- badge?: string
132
- render: () => React.ReactElement
135
+ badge?: string;
136
+ render: () => React.ReactElement;
133
137
  }
134
138
 
135
139
  export interface DocGroup {
136
140
  /** Sub-rótulo opcional dentro da seção (ex.: Primitivos). Ausente = páginas direto na seção. */
137
- label?: string
138
- pages: DocEntry[]
141
+ label?: string;
142
+ pages: DocEntry[];
139
143
  }
140
144
 
141
145
  export interface DocSection {
142
- label: string
143
- groups: DocGroup[]
146
+ label: string;
147
+ groups: DocGroup[];
144
148
  }
145
149
 
146
150
  /**
@@ -154,10 +158,12 @@ export interface DocSection {
154
158
  // precisar, entra por alias no scope do chamador.
155
159
  const iconScope: Record<string, unknown> = Object.fromEntries(
156
160
  Object.entries(lucideIcons).filter(([name]) => !(name in opusUi)),
157
- )
161
+ );
158
162
 
159
163
  /** Página conceitual (Começar/Framework/Design/Intro): markdown direto (o H1/lead moram no md). */
160
- const doc = (content: string) => (): React.ReactElement => <DocMarkdown content={content} scope={iconScope} />
164
+ const doc = (content: string) => (): React.ReactElement => (
165
+ <DocMarkdown content={content} scope={iconScope} />
166
+ );
161
167
 
162
168
  /**
163
169
  * Página de componente: o cabeçalho (título + badge de origem + whenToUse) vem do `meta` central
@@ -170,7 +176,7 @@ const comp =
170
176
  <DocPage title={title} meta={componentMeta[key]}>
171
177
  <DocMarkdown content={content} scope={iconScope} />
172
178
  </DocPage>
173
- )
179
+ );
174
180
 
175
181
  /** O palco dos patterns no scope dos previews: ícones + client fake + contratos de mentira. */
176
182
  const patternScope = {
@@ -182,7 +188,7 @@ const patternScope = {
182
188
  docWorkspaceView,
183
189
  docSessionArchive,
184
190
  docSessionDelete,
185
- }
191
+ };
186
192
 
187
193
  /** Página de pattern: igual ao `comp`, mas os previews enxergam o palco doc-client no scope. */
188
194
  const pattern =
@@ -191,18 +197,20 @@ const pattern =
191
197
  <DocPage title={title} meta={componentMeta[key]}>
192
198
  <DocMarkdown content={content} scope={patternScope} />
193
199
  </DocPage>
194
- )
200
+ );
195
201
 
196
202
  /** Entrada 'UI' do Docs: a UI é um recurso do MESMO SDK, mas mora na superfície `/ui` (o
197
203
  * catálogo é grande e visual). Em vez de duplicar, a página redireciona pra lá. */
198
204
  function UiRedirect(): React.ReactElement {
199
205
  useEffect(() => {
200
- if (typeof window === 'undefined') return
206
+ if (typeof window === "undefined") return;
201
207
  // `replace`: um redirect não merece uma entrada no histórico — com `push`, o "voltar"
202
208
  // cairia aqui de novo e redirecionaria outra vez.
203
- navigate('/ui', { replace: true })
204
- }, [])
205
- return <p className="text-sm text-muted-foreground">Redirecionando para a UI…</p>
209
+ navigate("/ui", { replace: true });
210
+ }, []);
211
+ return (
212
+ <p className="text-sm text-muted-foreground">Redirecionando para a UI…</p>
213
+ );
206
214
  }
207
215
 
208
216
  /** As seções da doc do SDK (surface `/docs` do site). "Começar" fica na RAIZ (seção sem
@@ -210,13 +218,21 @@ function UiRedirect(): React.ReactElement {
210
218
  export const PROTOCOL_SECTIONS: DocSection[] = [
211
219
  {
212
220
  // Sem label → páginas soltas no topo do menu (sem cabeçalho de seção).
213
- label: '',
221
+ label: "",
214
222
  groups: [
215
223
  {
216
224
  pages: [
217
- { slug: 'getting-started', title: 'Getting started', render: doc(gettingStartedMd) },
218
- { slug: 'cycle', title: 'Evolução contínua', render: doc(cycleMd) },
219
- { slug: 'upgrading', title: 'Atualizar a base', render: doc(upgradingMd) },
225
+ {
226
+ slug: "getting-started",
227
+ title: "Getting started",
228
+ render: doc(gettingStartedMd),
229
+ },
230
+ { slug: "cycle", title: "Evolução contínua", render: doc(cycleMd) },
231
+ {
232
+ slug: "upgrading",
233
+ title: "Atualizar a base",
234
+ render: doc(upgradingMd),
235
+ },
220
236
  ],
221
237
  },
222
238
  ],
@@ -224,15 +240,27 @@ export const PROTOCOL_SECTIONS: DocSection[] = [
224
240
  {
225
241
  // O núcleo invariante do protocolo — uma página por recurso. Opus é protocolo + peças
226
242
  // opcionais entregues como SDK (não Framework: a inversão de controle é do app).
227
- label: 'Protocolo',
243
+ label: "Protocolo",
228
244
  groups: [
229
245
  {
230
246
  pages: [
231
- { slug: 'actions', title: 'Actions & contratos', render: doc(actionsMd) },
232
- { slug: 'runtime', title: 'Runtime & adapters', render: doc(runtimeMd) },
233
- { slug: 'data', title: 'Camada de dados', render: doc(dataMd) },
234
- { slug: 'testing', title: 'Testes de action', render: doc(testingMd) },
235
- { slug: 'cli', title: 'CLI opus', render: doc(cliMd) },
247
+ {
248
+ slug: "actions",
249
+ title: "Actions & contratos",
250
+ render: doc(actionsMd),
251
+ },
252
+ {
253
+ slug: "runtime",
254
+ title: "Runtime & adapters",
255
+ render: doc(runtimeMd),
256
+ },
257
+ { slug: "data", title: "Camada de dados", render: doc(dataMd) },
258
+ {
259
+ slug: "testing",
260
+ title: "Testes de action",
261
+ render: doc(testingMd),
262
+ },
263
+ { slug: "cli", title: "CLI opus", render: doc(cliMd) },
236
264
  ],
237
265
  },
238
266
  ],
@@ -240,171 +268,504 @@ export const PROTOCOL_SECTIONS: DocSection[] = [
240
268
  {
241
269
  // As peças OPT-IN que você liga (adapter + driver). A UI também é recurso do SDK, mas
242
270
  // com catálogo próprio — a entrada 'ui' redireciona pra superfície /ui.
243
- label: 'Recursos',
271
+ label: "Recursos",
244
272
  groups: [
245
273
  {
246
274
  pages: [
247
- { slug: 'auth', title: 'Autenticação', badge: 'auth', render: doc(authMd) },
248
- { slug: 'audit', title: 'Auditoria', badge: 'audit', render: doc(auditMd) },
249
- { slug: 'events', title: 'Eventos', badge: 'events', render: doc(eventsMd) },
250
- { slug: 'log', title: 'Log', badge: 'log', render: doc(logMd) },
251
- { slug: 'queue', title: 'Filas', badge: 'queue', render: doc(queueMd) },
252
- { slug: 'scheduler', title: 'Agendador', badge: 'scheduler', render: doc(schedulerMd) },
253
- { slug: 'storage', title: 'Armazenamento', badge: 'storage', render: doc(storageMd) },
254
- { slug: 'ai', title: 'IA generativa', badge: 'ai', render: doc(aiMd) },
255
- { slug: 'mcp', title: 'MCP', badge: 'mcp', render: doc(mcpMd) },
256
- { slug: 'ui', title: 'UI ↗', render: () => <UiRedirect /> },
275
+ {
276
+ slug: "auth",
277
+ title: "Autenticação",
278
+ badge: "auth",
279
+ render: doc(authMd),
280
+ },
281
+ {
282
+ slug: "audit",
283
+ title: "Auditoria",
284
+ badge: "audit",
285
+ render: doc(auditMd),
286
+ },
287
+ {
288
+ slug: "events",
289
+ title: "Eventos",
290
+ badge: "events",
291
+ render: doc(eventsMd),
292
+ },
293
+ { slug: "log", title: "Log", badge: "log", render: doc(logMd) },
294
+ {
295
+ slug: "queue",
296
+ title: "Filas",
297
+ badge: "queue",
298
+ render: doc(queueMd),
299
+ },
300
+ {
301
+ slug: "scheduler",
302
+ title: "Agendador",
303
+ badge: "scheduler",
304
+ render: doc(schedulerMd),
305
+ },
306
+ {
307
+ slug: "storage",
308
+ title: "Armazenamento",
309
+ badge: "storage",
310
+ render: doc(storageMd),
311
+ },
312
+ {
313
+ slug: "ai",
314
+ title: "IA generativa",
315
+ badge: "ai",
316
+ render: doc(aiMd),
317
+ },
318
+ { slug: "mcp", title: "MCP", badge: "mcp", render: doc(mcpMd) },
319
+ { slug: "ui", title: "UI ↗", render: () => <UiRedirect /> },
257
320
  ],
258
321
  },
259
322
  ],
260
323
  },
261
- ]
324
+ ];
262
325
 
263
326
  /** As seções da parte de UI do SDK (`/ui`): consumo, design, catálogo de componentes e
264
327
  * patterns. Mesma família das seções de protocolo — superfície própria só pelo volume. */
265
328
  export const UI_SECTIONS: DocSection[] = [
266
329
  {
267
330
  // Raiz (sem label): o "getting started" da UI.
268
- label: '',
269
- groups: [{ pages: [{ slug: 'como-consumir', title: 'Getting started', render: doc(uiMd) }] }],
331
+ label: "",
332
+ groups: [
333
+ {
334
+ pages: [
335
+ {
336
+ slug: "como-consumir",
337
+ title: "Getting started",
338
+ render: doc(uiMd),
339
+ },
340
+ ],
341
+ },
342
+ ],
270
343
  },
271
344
  {
272
- label: 'Design',
345
+ label: "Design",
273
346
  groups: [
274
347
  {
275
348
  pages: [
276
- { slug: 'tokens', title: 'Tokens & Tema', render: doc(tokensMd) },
277
- { slug: 'communication', title: 'Comunicação', render: doc(communicationMd) },
278
- { slug: 'customization', title: 'Customização', render: doc(customizationMd) },
349
+ { slug: "tokens", title: "Tokens & Tema", render: doc(tokensMd) },
350
+ {
351
+ slug: "semantic-context",
352
+ title: "Contexto & Variante",
353
+ render: doc(semanticContextMd),
354
+ },
355
+ {
356
+ slug: "communication",
357
+ title: "Comunicação",
358
+ render: doc(communicationMd),
359
+ },
360
+ {
361
+ slug: "customization",
362
+ title: "Customização",
363
+ render: doc(customizationMd),
364
+ },
279
365
  ],
280
366
  },
281
367
  ],
282
368
  },
283
369
  {
284
- label: 'Componentes',
370
+ label: "Componentes",
285
371
  groups: [
286
372
  {
287
- label: 'Fundamentos',
373
+ label: "Fundamentos",
288
374
  pages: [
289
- { slug: 'router', title: 'Router', render: pattern('Router', 'router', routerMd) },
375
+ {
376
+ slug: "router",
377
+ title: "Router",
378
+ render: pattern("Router", "router", routerMd),
379
+ },
290
380
  ],
291
381
  },
292
382
  {
293
- label: 'Layout',
383
+ label: "Layout",
294
384
  pages: [
295
- { slug: 'split', title: 'Split & Pane', render: pattern('Split & Pane', 'split', splitMd) },
296
- { slug: 'sidebar', title: 'Sidebar', render: pattern('Sidebar', 'sidebar', sidebarMd) },
297
- { slug: 'page', title: 'Page', render: pattern('Page', 'page', pageMd) },
298
- { slug: 'accordion', title: 'Accordion', render: comp('Accordion', 'accordion', accordionMd) },
299
- { slug: 'aspect-ratio', title: 'Aspect Ratio', render: comp('Aspect Ratio', 'aspect-ratio', aspectRatioMd) },
300
- { slug: 'card', title: 'Card', render: comp('Card', 'card', cardMd) },
301
- { slug: 'collapsible', title: 'Collapsible', render: comp('Collapsible', 'collapsible', collapsibleMd) },
302
- { slug: 'scroll-area', title: 'Scroll Area', render: comp('Scroll Area', 'scroll-area', scrollAreaMd) },
303
- { slug: 'separator', title: 'Separator', render: comp('Separator', 'separator', separatorMd) },
385
+ {
386
+ slug: "split",
387
+ title: "Split & Pane",
388
+ render: pattern("Split & Pane", "split", splitMd),
389
+ },
390
+ {
391
+ slug: "sidebar",
392
+ title: "Sidebar",
393
+ render: pattern("Sidebar", "sidebar", sidebarMd),
394
+ },
395
+ {
396
+ slug: "page",
397
+ title: "Page",
398
+ render: pattern("Page", "page", pageMd),
399
+ },
400
+ {
401
+ slug: "content",
402
+ title: "Content",
403
+ render: pattern("Content", "content", contentMd),
404
+ },
405
+ {
406
+ slug: "page-state",
407
+ title: "Page State",
408
+ render: pattern("Page State", "page-state", pageStateMd),
409
+ },
410
+ {
411
+ slug: "accordion",
412
+ title: "Accordion",
413
+ render: comp("Accordion", "accordion", accordionMd),
414
+ },
415
+ {
416
+ slug: "aspect-ratio",
417
+ title: "Aspect Ratio",
418
+ render: comp("Aspect Ratio", "aspect-ratio", aspectRatioMd),
419
+ },
420
+ { slug: "card", title: "Card", render: comp("Card", "card", cardMd) },
421
+ {
422
+ slug: "metric-card",
423
+ title: "Metric Card",
424
+ render: comp("Metric Card", "metric-card", metricCardMd),
425
+ },
426
+ {
427
+ slug: "collapsible",
428
+ title: "Collapsible",
429
+ render: comp("Collapsible", "collapsible", collapsibleMd),
430
+ },
431
+ {
432
+ slug: "scroll-area",
433
+ title: "Scroll Area",
434
+ render: comp("Scroll Area", "scroll-area", scrollAreaMd),
435
+ },
436
+ {
437
+ slug: "separator",
438
+ title: "Separator",
439
+ render: comp("Separator", "separator", separatorMd),
440
+ },
304
441
  ],
305
442
  },
306
443
  {
307
- label: 'Actions',
444
+ label: "Actions",
308
445
  pages: [
309
- { slug: 'action-form', title: 'Action Form', render: pattern('Action Form', 'action-form', actionFormMd) },
310
- { slug: 'action-form-card', title: 'Action Form Card', render: pattern('Action Form Card', 'action-form-card', actionFormCardMd) },
311
- { slug: 'action-form-dialog', title: 'Action Form Dialog', render: pattern('Action Form Dialog', 'action-form-dialog', actionFormDialogMd) },
312
- { slug: 'action-list', title: 'Action List', render: pattern('Action List', 'action-list', actionSearchMd) },
313
- { slug: 'action-list-dialog', title: 'Action List Dialog', render: pattern('Action List Dialog', 'action-list-dialog', actionSearchDialogMd) },
314
- { slug: 'action-trigger', title: 'Action Trigger', render: pattern('Action Trigger', 'action-trigger', actionTriggerMd) },
315
- { slug: 'action-view', title: 'Action View', render: pattern('Action View', 'action-view', actionViewMd) },
446
+ {
447
+ slug: "action-form",
448
+ title: "Action Form",
449
+ render: pattern("Action Form", "action-form", actionFormMd),
450
+ },
451
+ {
452
+ slug: "action-form-card",
453
+ title: "Action Form Card",
454
+ render: pattern(
455
+ "Action Form Card",
456
+ "action-form-card",
457
+ actionFormCardMd,
458
+ ),
459
+ },
460
+ {
461
+ slug: "action-form-dialog",
462
+ title: "Action Form Dialog",
463
+ render: pattern(
464
+ "Action Form Dialog",
465
+ "action-form-dialog",
466
+ actionFormDialogMd,
467
+ ),
468
+ },
469
+ {
470
+ slug: "action-list",
471
+ title: "Action List",
472
+ render: pattern("Action List", "action-list", actionSearchMd),
473
+ },
474
+ {
475
+ slug: "action-list-dialog",
476
+ title: "Action List Dialog",
477
+ render: pattern(
478
+ "Action List Dialog",
479
+ "action-list-dialog",
480
+ actionSearchDialogMd,
481
+ ),
482
+ },
483
+ {
484
+ slug: "action-trigger",
485
+ title: "Action Trigger",
486
+ render: pattern(
487
+ "Action Trigger",
488
+ "action-trigger",
489
+ actionTriggerMd,
490
+ ),
491
+ },
492
+ {
493
+ slug: "action-view",
494
+ title: "Action View",
495
+ render: pattern("Action View", "action-view", actionViewMd),
496
+ },
316
497
  ],
317
498
  },
318
499
  {
319
- label: 'IA',
500
+ label: "IA",
320
501
  pages: [
321
- { slug: 'ask', title: 'Ask', render: comp('Ask', 'ask', askMd) },
322
- { slug: 'chat', title: 'Chat', render: comp('Chat', 'chat', chatMd) },
323
- { slug: 'composer', title: 'Composer', render: comp('Composer', 'composer', composerMd) },
502
+ { slug: "ask", title: "Ask", render: comp("Ask", "ask", askMd) },
503
+ { slug: "chat", title: "Chat", render: comp("Chat", "chat", chatMd) },
504
+ {
505
+ slug: "composer",
506
+ title: "Composer",
507
+ render: comp("Composer", "composer", composerMd),
508
+ },
324
509
  ],
325
510
  },
326
511
  {
327
- label: 'Formulário',
512
+ label: "Formulário",
328
513
  pages: [
329
- { slug: 'calendar', title: 'Calendar', render: comp('Calendar', 'calendar', calendarMd) },
330
- { slug: 'checkbox', title: 'Checkbox', render: comp('Checkbox', 'checkbox', checkboxMd) },
331
- { slug: 'field', title: 'Field', render: comp('Field', 'field', fieldMd) },
332
- { slug: 'icon-picker', title: 'Icon Picker', render: comp('Icon Picker', 'icon-picker', iconPickerMd) },
333
- { slug: 'input', title: 'Input', render: comp('Input', 'input', inputMd) },
334
- { slug: 'input-group', title: 'Input Group', render: comp('Input Group', 'input-group', inputGroupMd) },
335
- { slug: 'input-otp', title: 'Input OTP', render: comp('Input OTP', 'input-otp', inputOtpMd) },
336
- { slug: 'label', title: 'Label', render: comp('Label', 'label', labelMd) },
337
- { slug: 'radio-group', title: 'Radio Group', render: comp('Radio Group', 'radio-group', radioGroupMd) },
338
- { slug: 'select', title: 'Select', render: comp('Select', 'select', selectMd) },
339
- { slug: 'slider', title: 'Slider', render: comp('Slider', 'slider', sliderMd) },
340
- { slug: 'switch', title: 'Switch', render: comp('Switch', 'switch', switchMd) },
341
- { slug: 'textarea', title: 'Textarea', render: comp('Textarea', 'textarea', textareaMd) },
514
+ {
515
+ slug: "calendar",
516
+ title: "Calendar",
517
+ render: comp("Calendar", "calendar", calendarMd),
518
+ },
519
+ {
520
+ slug: "checkbox",
521
+ title: "Checkbox",
522
+ render: comp("Checkbox", "checkbox", checkboxMd),
523
+ },
524
+ {
525
+ slug: "field",
526
+ title: "Field",
527
+ render: comp("Field", "field", fieldMd),
528
+ },
529
+ {
530
+ slug: "icon-picker",
531
+ title: "Icon Picker",
532
+ render: comp("Icon Picker", "icon-picker", iconPickerMd),
533
+ },
534
+ {
535
+ slug: "input",
536
+ title: "Input",
537
+ render: comp("Input", "input", inputMd),
538
+ },
539
+ {
540
+ slug: "input-group",
541
+ title: "Input Group",
542
+ render: comp("Input Group", "input-group", inputGroupMd),
543
+ },
544
+ {
545
+ slug: "input-otp",
546
+ title: "Input OTP",
547
+ render: comp("Input OTP", "input-otp", inputOtpMd),
548
+ },
549
+ {
550
+ slug: "label",
551
+ title: "Label",
552
+ render: comp("Label", "label", labelMd),
553
+ },
554
+ {
555
+ slug: "radio-group",
556
+ title: "Radio Group",
557
+ render: comp("Radio Group", "radio-group", radioGroupMd),
558
+ },
559
+ {
560
+ slug: "select",
561
+ title: "Select",
562
+ render: comp("Select", "select", selectMd),
563
+ },
564
+ {
565
+ slug: "slider",
566
+ title: "Slider",
567
+ render: comp("Slider", "slider", sliderMd),
568
+ },
569
+ {
570
+ slug: "switch",
571
+ title: "Switch",
572
+ render: comp("Switch", "switch", switchMd),
573
+ },
574
+ {
575
+ slug: "textarea",
576
+ title: "Textarea",
577
+ render: comp("Textarea", "textarea", textareaMd),
578
+ },
342
579
  ],
343
580
  },
344
581
  {
345
- label: 'Botões',
582
+ label: "Botões",
346
583
  pages: [
347
- { slug: 'button', title: 'Button', render: comp('Button', 'button', buttonMd) },
348
- { slug: 'button-group', title: 'Button Group', render: comp('Button Group', 'button-group', buttonGroupMd) },
349
- { slug: 'toggle', title: 'Toggle', render: comp('Toggle', 'toggle', toggleMd) },
350
- { slug: 'toggle-group', title: 'Toggle Group', render: comp('Toggle Group', 'toggle-group', toggleGroupMd) },
584
+ {
585
+ slug: "button",
586
+ title: "Button",
587
+ render: comp("Button", "button", buttonMd),
588
+ },
589
+ {
590
+ slug: "button-group",
591
+ title: "Button Group",
592
+ render: comp("Button Group", "button-group", buttonGroupMd),
593
+ },
594
+ {
595
+ slug: "toggle",
596
+ title: "Toggle",
597
+ render: comp("Toggle", "toggle", toggleMd),
598
+ },
599
+ {
600
+ slug: "toggle-group",
601
+ title: "Toggle Group",
602
+ render: comp("Toggle Group", "toggle-group", toggleGroupMd),
603
+ },
351
604
  ],
352
605
  },
353
606
  {
354
- label: 'Navegação',
607
+ label: "Navegação",
355
608
  pages: [
356
- { slug: 'breadcrumb', title: 'Breadcrumb', render: comp('Breadcrumb', 'breadcrumb', breadcrumbMd) },
357
- { slug: 'command', title: 'Command', render: comp('Command', 'command', commandMd) },
358
- { slug: 'pagination', title: 'Pagination', render: comp('Pagination', 'pagination', paginationMd) },
359
- { slug: 'tabs', title: 'Tabs', render: comp('Tabs', 'tabs', tabsMd) },
609
+ {
610
+ slug: "breadcrumb",
611
+ title: "Breadcrumb",
612
+ render: comp("Breadcrumb", "breadcrumb", breadcrumbMd),
613
+ },
614
+ {
615
+ slug: "command",
616
+ title: "Command",
617
+ render: comp("Command", "command", commandMd),
618
+ },
619
+ {
620
+ slug: "pagination",
621
+ title: "Pagination",
622
+ render: comp("Pagination", "pagination", paginationMd),
623
+ },
624
+ { slug: "tabs", title: "Tabs", render: comp("Tabs", "tabs", tabsMd) },
360
625
  ],
361
626
  },
362
627
  {
363
- label: 'Exibição',
628
+ label: "Exibição",
364
629
  pages: [
365
- { slug: 'avatar', title: 'Avatar', render: comp('Avatar', 'avatar', avatarMd) },
366
- { slug: 'badge', title: 'Badge', render: comp('Badge', 'badge', badgeMd) },
367
- { slug: 'dot', title: 'Dot', render: comp('Dot', 'dot', dotMd) },
368
- { slug: 'dock', title: 'Dock', render: comp('Dock', 'dock', dockMd) },
369
- { slug: 'carousel', title: 'Carousel', render: comp('Carousel', 'carousel', carouselMd) },
370
- { slug: 'copyable', title: 'Copyable', render: comp('Copyable', 'copyable', copyableMd) },
371
- { slug: 'detail', title: 'Detail', render: comp('Detail', 'detail', detailMd) },
372
- { slug: 'dictionary-value', title: 'Dictionary Value', render: comp('Dictionary Value', 'dictionary-value', dictionaryValueMd) },
373
- { slug: 'empty-value', title: 'Empty Value', render: comp('Empty Value', 'empty-value', emptyValueMd) },
374
- { slug: 'item', title: 'Item', render: comp('Item', 'item', itemMd) },
375
- { slug: 'kbd', title: 'Kbd', render: comp('Kbd', 'kbd', kbdMd) },
376
- { slug: 'markdown', title: 'Markdown', render: comp('Markdown', 'markdown', markdownMd) },
377
- { slug: 'table', title: 'Table', render: comp('Table', 'table', tableMd) },
378
- { slug: 'truncate', title: 'Truncate', render: comp('Truncate', 'truncate', truncateMd) },
630
+ {
631
+ slug: "avatar",
632
+ title: "Avatar",
633
+ render: comp("Avatar", "avatar", avatarMd),
634
+ },
635
+ {
636
+ slug: "badge",
637
+ title: "Badge",
638
+ render: comp("Badge", "badge", badgeMd),
639
+ },
640
+ { slug: "dot", title: "Dot", render: comp("Dot", "dot", dotMd) },
641
+ { slug: "dock", title: "Dock", render: comp("Dock", "dock", dockMd) },
642
+ {
643
+ slug: "carousel",
644
+ title: "Carousel",
645
+ render: comp("Carousel", "carousel", carouselMd),
646
+ },
647
+ {
648
+ slug: "copyable",
649
+ title: "Copyable",
650
+ render: comp("Copyable", "copyable", copyableMd),
651
+ },
652
+ {
653
+ slug: "detail",
654
+ title: "Detail",
655
+ render: comp("Detail", "detail", detailMd),
656
+ },
657
+ {
658
+ slug: "dictionary-value",
659
+ title: "Dictionary Value",
660
+ render: comp(
661
+ "Dictionary Value",
662
+ "dictionary-value",
663
+ dictionaryValueMd,
664
+ ),
665
+ },
666
+ {
667
+ slug: "empty-value",
668
+ title: "Empty Value",
669
+ render: comp("Empty Value", "empty-value", emptyValueMd),
670
+ },
671
+ { slug: "item", title: "Item", render: comp("Item", "item", itemMd) },
672
+ { slug: "kbd", title: "Kbd", render: comp("Kbd", "kbd", kbdMd) },
673
+ {
674
+ slug: "markdown",
675
+ title: "Markdown",
676
+ render: comp("Markdown", "markdown", markdownMd),
677
+ },
678
+ {
679
+ slug: "table",
680
+ title: "Table",
681
+ render: comp("Table", "table", tableMd),
682
+ },
683
+ {
684
+ slug: "truncate",
685
+ title: "Truncate",
686
+ render: comp("Truncate", "truncate", truncateMd),
687
+ },
379
688
  ],
380
689
  },
381
690
  {
382
- label: 'Feedback',
691
+ label: "Feedback",
383
692
  pages: [
384
- { slug: 'alert', title: 'Alert', render: comp('Alert', 'alert', alertMd) },
385
- { slug: 'confirm', title: 'Dialog (imperativo)', render: comp('Dialog (imperativo)', 'confirm', confirmMd) },
386
- { slug: 'data-state', title: 'Data State', render: comp('Data State', 'data-state', dataStateMd) },
387
- { slug: 'empty', title: 'Empty', render: comp('Empty', 'empty', emptyMd) },
388
- { slug: 'progress', title: 'Progress', render: comp('Progress', 'progress', progressMd) },
389
- { slug: 'skeleton', title: 'Skeleton', render: comp('Skeleton', 'skeleton', skeletonMd) },
390
- { slug: 'spinner', title: 'Spinner', render: comp('Spinner', 'spinner', spinnerMd) },
391
- { slug: 'toast', title: 'Toast', render: comp('Toast', 'toast', toastMd) },
693
+ {
694
+ slug: "alert",
695
+ title: "Alert",
696
+ render: comp("Alert", "alert", alertMd),
697
+ },
698
+ {
699
+ slug: "confirm",
700
+ title: "Dialog (imperativo)",
701
+ render: comp("Dialog (imperativo)", "confirm", confirmMd),
702
+ },
703
+ {
704
+ slug: "data-state",
705
+ title: "Data State",
706
+ render: comp("Data State", "data-state", dataStateMd),
707
+ },
708
+ {
709
+ slug: "empty",
710
+ title: "Empty",
711
+ render: comp("Empty", "empty", emptyMd),
712
+ },
713
+ {
714
+ slug: "progress",
715
+ title: "Progress",
716
+ render: comp("Progress", "progress", progressMd),
717
+ },
718
+ {
719
+ slug: "skeleton",
720
+ title: "Skeleton",
721
+ render: comp("Skeleton", "skeleton", skeletonMd),
722
+ },
723
+ {
724
+ slug: "spinner",
725
+ title: "Spinner",
726
+ render: comp("Spinner", "spinner", spinnerMd),
727
+ },
728
+ {
729
+ slug: "toast",
730
+ title: "Toast",
731
+ render: comp("Toast", "toast", toastMd),
732
+ },
392
733
  ],
393
734
  },
394
735
  {
395
- label: 'Sobreposição',
736
+ label: "Sobreposição",
396
737
  pages: [
397
- { slug: 'alert-dialog', title: 'Alert Dialog', render: comp('Alert Dialog', 'alert-dialog', alertDialogMd) },
398
- { slug: 'dialog', title: 'Dialog', render: comp('Dialog', 'dialog', dialogMd) },
399
- { slug: 'drawer', title: 'Drawer', render: comp('Drawer', 'drawer', drawerMd) },
400
- { slug: 'menu', title: 'Menu', render: comp('Menu', 'menu', menuMd) },
401
- { slug: 'popover', title: 'Popover', render: comp('Popover', 'popover', popoverMd) },
402
- { slug: 'tooltip', title: 'Tooltip', render: comp('Tooltip', 'tooltip', tooltipMd) },
738
+ {
739
+ slug: "alert-dialog",
740
+ title: "Alert Dialog",
741
+ render: comp("Alert Dialog", "alert-dialog", alertDialogMd),
742
+ },
743
+ {
744
+ slug: "dialog",
745
+ title: "Dialog",
746
+ render: comp("Dialog", "dialog", dialogMd),
747
+ },
748
+ {
749
+ slug: "drawer",
750
+ title: "Drawer",
751
+ render: comp("Drawer", "drawer", drawerMd),
752
+ },
753
+ { slug: "menu", title: "Menu", render: comp("Menu", "menu", menuMd) },
754
+ {
755
+ slug: "popover",
756
+ title: "Popover",
757
+ render: comp("Popover", "popover", popoverMd),
758
+ },
759
+ {
760
+ slug: "tooltip",
761
+ title: "Tooltip",
762
+ render: comp("Tooltip", "tooltip", tooltipMd),
763
+ },
403
764
  ],
404
765
  },
405
766
  ],
406
767
  },
407
- ]
768
+ ];
408
769
 
409
770
  /** O catálogo INTEIRO (compat): Maestro (lente) e `/__docs` mostram tudo numa nav só —
410
771
  * inclusive o changelog, que no SITE é página do menu superior (fora destas seções);
@@ -417,7 +778,11 @@ export const DOC_SECTIONS: DocSection[] = [
417
778
  {
418
779
  pages: [
419
780
  ...PROTOCOL_SECTIONS[0]!.groups[0]!.pages,
420
- { slug: 'changelog', title: 'Changelog', render: () => <OpusChangelog /> },
781
+ {
782
+ slug: "changelog",
783
+ title: "Changelog",
784
+ render: () => <OpusChangelog />,
785
+ },
421
786
  ],
422
787
  },
423
788
  ],
@@ -426,7 +791,10 @@ export const DOC_SECTIONS: DocSection[] = [
426
791
  // à parte — então tira a entrada-redirect 'ui' (o catálogo já entra via UI_SECTIONS).
427
792
  ...PROTOCOL_SECTIONS.slice(1).map((s) => ({
428
793
  ...s,
429
- groups: s.groups.map((g) => ({ ...g, pages: g.pages.filter((p) => p.slug !== 'ui') })),
794
+ groups: s.groups.map((g) => ({
795
+ ...g,
796
+ pages: g.pages.filter((p) => p.slug !== "ui"),
797
+ })),
430
798
  })),
431
799
  ...UI_SECTIONS,
432
- ]
800
+ ];