@softize/opus 12.11.0 → 13.1.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 (213) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/PROMOTED.md +46 -0
  3. package/README.md +28 -19
  4. package/bin/cli.mjs +87 -216
  5. package/bin/lib/check.mjs +2 -7
  6. package/bin/lib/cli-shared.mjs +131 -0
  7. package/bin/lib/copy.mjs +1 -5
  8. package/bin/lib/db.mjs +16 -74
  9. package/bin/lib/gen-openapi.mjs +3 -3
  10. package/bin/lib/gen-runner.mjs +1 -1
  11. package/bin/lib/gen.mjs +14 -69
  12. package/bin/lib/mcp.mjs +3 -1
  13. package/bin/lib/seed.mjs +5 -62
  14. package/docs/adr/0005-structural-surfaces-share-an-explicit-anatomy.md +93 -10
  15. package/docs/adr/0007-toast-actions-form-an-ordered-collection.md +63 -0
  16. package/docs/adr/0008-hierarchical-navigation-is-composed-at-the-consumer-boundary.md +71 -0
  17. package/docs/ownership-vs-shadcn-lock.md +2 -3
  18. package/docs/protocol.md +7 -7
  19. package/docs/radius-scale.md +1 -1
  20. package/docs/releasing.md +8 -2
  21. package/package.json +7 -3
  22. package/registry/skills/maintain-opus-docs/SKILL.md +83 -0
  23. package/registry/skills/maintain-opus-docs/agents/openai.yaml +4 -0
  24. package/registry/skills/maintain-opus-docs/references/editorial-standard.md +85 -0
  25. package/registry/skills/maintain-opus-docs/references/evaluations.md +34 -0
  26. package/registry/skills/maintain-opus-docs/scripts/audit-docs.mjs +81 -0
  27. package/registry/templates/app/package.json +1 -1
  28. package/registry/templates/app/src/main.tsx +4 -4
  29. package/src/audit/drivers/console.ts +1 -0
  30. package/src/auth/drivers/better-auth.ts +1 -0
  31. package/src/auth/drivers/jwt.ts +1 -0
  32. package/src/cache/drivers/memory.ts +1 -0
  33. package/src/client/drivers/fetch.ts +2 -1
  34. package/src/core/actions.ts +6 -1
  35. package/src/core/audit.ts +9 -3
  36. package/src/core/contracts.ts +7 -0
  37. package/src/core/domain.ts +1 -1
  38. package/src/core/errors.ts +18 -15
  39. package/src/core/index.ts +4 -2
  40. package/src/core/package-version.ts +26 -0
  41. package/src/core/reactions.ts +1 -1
  42. package/src/core/runtime.ts +33 -23
  43. package/src/core/schedules.ts +1 -1
  44. package/src/core/types.ts +2 -2
  45. package/src/dsl/eval.ts +2 -2
  46. package/src/dsl/kysely.ts +2 -2
  47. package/src/dsl/loads.ts +1 -1
  48. package/src/dsl/parser.ts +5 -5
  49. package/src/events/drivers/mitt.ts +1 -0
  50. package/src/mcp/index.ts +2 -1
  51. package/src/observability/drivers/opentelemetry.ts +1 -0
  52. package/src/queue/drivers/bullmq.ts +3 -3
  53. package/src/scheduler/drivers/node-cron.ts +3 -2
  54. package/src/scheduler/every.ts +7 -7
  55. package/src/schema/openapi.ts +3 -3
  56. package/src/seed/index.ts +29 -0
  57. package/src/server/drivers/fastify.ts +5 -2
  58. package/src/server/drivers/node.ts +9 -6
  59. package/src/server/index.ts +3 -1
  60. package/src/storage/drivers/fs.ts +1 -0
  61. package/src/testing/index.ts +3 -3
  62. package/src/ui/components/patterns/confirm.tsx +142 -42
  63. package/src/ui/components/patterns/content-header.tsx +7 -1
  64. package/src/ui/components/patterns/data-state.tsx +1 -1
  65. package/src/ui/components/patterns/dock.tsx +20 -3
  66. package/src/ui/components/patterns/form.tsx +12 -8
  67. package/src/ui/components/patterns/list.tsx +36 -41
  68. package/src/ui/components/patterns/page-state.tsx +2 -2
  69. package/src/ui/components/patterns/page.tsx +19 -1
  70. package/src/ui/components/patterns/shell-nav.tsx +10 -3
  71. package/src/ui/components/patterns/sidebar.tsx +43 -32
  72. package/src/ui/components/patterns/trigger.tsx +39 -38
  73. package/src/ui/components/patterns/view.tsx +26 -17
  74. package/src/ui/components/primitives/alert.tsx +14 -8
  75. package/src/ui/components/primitives/ask.tsx +3 -3
  76. package/src/ui/components/primitives/badge.tsx +11 -6
  77. package/src/ui/components/primitives/breadcrumb.tsx +2 -2
  78. package/src/ui/components/primitives/button.tsx +16 -3
  79. package/src/ui/components/primitives/calendar.tsx +28 -2
  80. package/src/ui/components/primitives/carousel.tsx +3 -3
  81. package/src/ui/components/primitives/chat.tsx +1 -1
  82. package/src/ui/components/primitives/checkbox.tsx +1 -1
  83. package/src/ui/components/primitives/command.tsx +2 -2
  84. package/src/ui/components/primitives/control.ts +12 -0
  85. package/src/ui/components/primitives/copyable.tsx +1 -1
  86. package/src/ui/components/primitives/dialog.tsx +202 -40
  87. package/src/ui/components/primitives/dot.tsx +5 -0
  88. package/src/ui/components/primitives/drawer.tsx +18 -8
  89. package/src/ui/components/primitives/empty.tsx +3 -3
  90. package/src/ui/components/primitives/field.tsx +3 -3
  91. package/src/ui/components/primitives/icon-picker.tsx +3 -1
  92. package/src/ui/components/primitives/input-group.tsx +1 -1
  93. package/src/ui/components/primitives/input-otp.tsx +1 -1
  94. package/src/ui/components/primitives/input.tsx +2 -2
  95. package/src/ui/components/primitives/item.tsx +3 -3
  96. package/src/ui/components/primitives/progress.tsx +32 -3
  97. package/src/ui/components/primitives/radio-group.tsx +1 -1
  98. package/src/ui/components/primitives/resizable.tsx +3 -1
  99. package/src/ui/components/primitives/select.tsx +5 -5
  100. package/src/ui/components/primitives/slider.tsx +5 -1
  101. package/src/ui/components/primitives/sonner.tsx +190 -8
  102. package/src/ui/components/primitives/switch.tsx +1 -0
  103. package/src/ui/components/primitives/tabs.tsx +1 -0
  104. package/src/ui/components/primitives/textarea.tsx +1 -1
  105. package/src/ui/components/primitives/toggle.tsx +1 -1
  106. package/src/ui/components/primitives/tooltip.tsx +1 -0
  107. package/src/ui/docs/DocBrowser.tsx +102 -23
  108. package/src/ui/docs/changelog.tsx +1 -1
  109. package/src/ui/docs/content/accordion.md +22 -16
  110. package/src/ui/docs/content/action-form-card.md +8 -8
  111. package/src/ui/docs/content/action-form-dialog.md +9 -9
  112. package/src/ui/docs/content/action-form.md +37 -36
  113. package/src/ui/docs/content/action-list-dialog.md +11 -6
  114. package/src/ui/docs/content/action-list.md +73 -39
  115. package/src/ui/docs/content/action-trigger.md +29 -15
  116. package/src/ui/docs/content/action-view.md +17 -10
  117. package/src/ui/docs/content/actions.md +9 -9
  118. package/src/ui/docs/content/ai.md +3 -3
  119. package/src/ui/docs/content/alert.md +14 -12
  120. package/src/ui/docs/content/ask.md +11 -0
  121. package/src/ui/docs/content/aspect-ratio.md +4 -4
  122. package/src/ui/docs/content/audit.md +2 -2
  123. package/src/ui/docs/content/auth.md +3 -3
  124. package/src/ui/docs/content/avatar.md +34 -14
  125. package/src/ui/docs/content/badge.md +3 -3
  126. package/src/ui/docs/content/breadcrumb.md +13 -8
  127. package/src/ui/docs/content/button.md +81 -6
  128. package/src/ui/docs/content/calendar.md +18 -5
  129. package/src/ui/docs/content/card.md +27 -1
  130. package/src/ui/docs/content/carousel.md +16 -11
  131. package/src/ui/docs/content/chat.md +23 -3
  132. package/src/ui/docs/content/checkbox.md +7 -7
  133. package/src/ui/docs/content/cli.md +74 -22
  134. package/src/ui/docs/content/collapsible.md +8 -8
  135. package/src/ui/docs/content/command.md +16 -8
  136. package/src/ui/docs/content/composer.md +17 -2
  137. package/src/ui/docs/content/content.md +17 -2
  138. package/src/ui/docs/content/copyable.md +12 -3
  139. package/src/ui/docs/content/customization.md +5 -5
  140. package/src/ui/docs/content/cycle.md +3 -3
  141. package/src/ui/docs/content/data-state.md +11 -12
  142. package/src/ui/docs/content/data.md +26 -33
  143. package/src/ui/docs/content/detail.md +22 -4
  144. package/src/ui/docs/content/dialog.md +339 -31
  145. package/src/ui/docs/content/dictionary-value.md +17 -10
  146. package/src/ui/docs/content/dock.md +11 -3
  147. package/src/ui/docs/content/dot.md +8 -0
  148. package/src/ui/docs/content/drawer.md +27 -14
  149. package/src/ui/docs/content/empty-value.md +2 -2
  150. package/src/ui/docs/content/empty.md +19 -12
  151. package/src/ui/docs/content/events.md +4 -4
  152. package/src/ui/docs/content/field.md +34 -12
  153. package/src/ui/docs/content/getting-started.md +3 -3
  154. package/src/ui/docs/content/icon-picker.md +19 -4
  155. package/src/ui/docs/content/input-otp.md +20 -12
  156. package/src/ui/docs/content/input.md +121 -9
  157. package/src/ui/docs/content/item.md +27 -13
  158. package/src/ui/docs/content/kbd.md +19 -11
  159. package/src/ui/docs/content/label.md +12 -3
  160. package/src/ui/docs/content/log.md +4 -4
  161. package/src/ui/docs/content/markdown.md +7 -6
  162. package/src/ui/docs/content/mcp.md +13 -15
  163. package/src/ui/docs/content/menu.md +40 -16
  164. package/src/ui/docs/content/metric-card.md +13 -0
  165. package/src/ui/docs/content/observability.md +2 -2
  166. package/src/ui/docs/content/page.md +59 -6
  167. package/src/ui/docs/content/pagination.md +22 -17
  168. package/src/ui/docs/content/popover.md +22 -8
  169. package/src/ui/docs/content/progress.md +15 -16
  170. package/src/ui/docs/content/queue.md +5 -5
  171. package/src/ui/docs/content/radio-group.md +20 -12
  172. package/src/ui/docs/content/router.md +11 -6
  173. package/src/ui/docs/content/scheduler.md +4 -5
  174. package/src/ui/docs/content/scroll-area.md +12 -7
  175. package/src/ui/docs/content/select.md +47 -34
  176. package/src/ui/docs/content/semantic-context.md +2 -2
  177. package/src/ui/docs/content/separator.md +5 -5
  178. package/src/ui/docs/content/sidebar.md +329 -54
  179. package/src/ui/docs/content/skeleton.md +9 -2
  180. package/src/ui/docs/content/slider.md +8 -7
  181. package/src/ui/docs/content/spinner.md +8 -8
  182. package/src/ui/docs/content/split.md +29 -5
  183. package/src/ui/docs/content/storage.md +6 -8
  184. package/src/ui/docs/content/switch.md +8 -7
  185. package/src/ui/docs/content/table.md +13 -3
  186. package/src/ui/docs/content/tabs.md +28 -14
  187. package/src/ui/docs/content/testing.md +9 -11
  188. package/src/ui/docs/content/textarea.md +12 -4
  189. package/src/ui/docs/content/toast.md +47 -13
  190. package/src/ui/docs/content/toggle.md +75 -7
  191. package/src/ui/docs/content/tokens.md +7 -7
  192. package/src/ui/docs/content/tooltip.md +19 -11
  193. package/src/ui/docs/content/truncate.md +15 -8
  194. package/src/ui/docs/content/ui.md +24 -9
  195. package/src/ui/docs/content/upgrading.md +7 -8
  196. package/src/ui/docs/doc-client.tsx +5 -5
  197. package/src/ui/docs/doc.tsx +26 -14
  198. package/src/ui/docs/registry.tsx +25 -42
  199. package/src/ui/docs/standalone.tsx +2 -2
  200. package/src/ui/drivers/react.tsx +17 -12
  201. package/src/ui/lib/action-errors.ts +45 -0
  202. package/src/ui/lib/zod-pt-br.ts +31 -4
  203. package/src/ui/meta.ts +65 -95
  204. package/src/ui/react.tsx +17 -16
  205. package/src/ui/theme.css +60 -8
  206. package/src/vite/design.ts +6 -18
  207. package/src/ui/components/primitives/alert-dialog.tsx +0 -192
  208. package/src/ui/docs/content/alert-dialog.md +0 -73
  209. package/src/ui/docs/content/button-group.md +0 -71
  210. package/src/ui/docs/content/confirm.md +0 -120
  211. package/src/ui/docs/content/input-group.md +0 -79
  212. package/src/ui/docs/content/page-state.md +0 -45
  213. package/src/ui/docs/content/toggle-group.md +0 -81
package/src/ui/react.tsx CHANGED
@@ -125,11 +125,17 @@ export {
125
125
  DialogOverlay,
126
126
  DialogContent,
127
127
  DialogHeader,
128
+ DialogMedia,
128
129
  DialogBody,
129
130
  DialogFooter,
130
131
  DialogTitle,
131
132
  DialogDescription,
132
133
  } from "./components/primitives/dialog.tsx";
134
+ export type {
135
+ DialogProps,
136
+ DialogCloseProps,
137
+ DialogMode,
138
+ } from "./components/primitives/dialog.tsx";
133
139
 
134
140
  export {
135
141
  Menu,
@@ -203,6 +209,10 @@ export type {
203
209
  } from "./components/primitives/select.tsx";
204
210
 
205
211
  export { Toaster, toast } from "./components/primitives/sonner.tsx";
212
+ export type {
213
+ ToastAction,
214
+ ToastOptions,
215
+ } from "./components/primitives/sonner.tsx";
206
216
  export { Markdown } from "./components/primitives/markdown.tsx";
207
217
 
208
218
  // shadcn (lote inicial — byte-fiéis via registry JSON, locked no registry.lock.json)
@@ -212,20 +222,6 @@ export {
212
222
  AccordionItem,
213
223
  AccordionTrigger,
214
224
  } from "./components/primitives/accordion.tsx";
215
- export {
216
- AlertDialog,
217
- AlertDialogAction,
218
- AlertDialogCancel,
219
- AlertDialogContent,
220
- AlertDialogDescription,
221
- AlertDialogFooter,
222
- AlertDialogHeader,
223
- AlertDialogMedia,
224
- AlertDialogOverlay,
225
- AlertDialogPortal,
226
- AlertDialogTitle,
227
- AlertDialogTrigger,
228
- } from "./components/primitives/alert-dialog.tsx";
229
225
  export { AspectRatio } from "./components/primitives/aspect-ratio.tsx";
230
226
  export {
231
227
  Avatar,
@@ -279,7 +275,7 @@ export {
279
275
  } from "./components/primitives/drawer.tsx";
280
276
  export {
281
277
  Empty,
282
- EmptyContent,
278
+ EmptyActions,
283
279
  EmptyDescription,
284
280
  EmptyHeader,
285
281
  EmptyMedia,
@@ -407,7 +403,9 @@ export {
407
403
  } from "./components/patterns/confirm.tsx";
408
404
  export type {
409
405
  AlertOptions,
406
+ ChooseOptions,
410
407
  ConfirmOptions,
408
+ DialogChoice,
411
409
  PromptOptions,
412
410
  } from "./components/patterns/confirm.tsx";
413
411
  export type { ActionTriggerProps } from "./components/patterns/trigger.tsx";
@@ -428,6 +426,7 @@ export {
428
426
  PageDescription,
429
427
  PageMeta,
430
428
  PageActions,
429
+ PageActionsTarget,
431
430
  PageBody,
432
431
  } from "./components/patterns/page.tsx";
433
432
  export type { PageProps } from "./components/patterns/page.tsx";
@@ -477,6 +476,7 @@ export type {
477
476
  DockProps,
478
477
  DockActionProps,
479
478
  SurfaceStatusProps,
479
+ SurfaceStatusContext,
480
480
  } from "./components/patterns/dock.tsx";
481
481
 
482
482
  // Barra lateral composicional: header/conteúdo/footer e navegação, sem possuir o layout.
@@ -488,13 +488,14 @@ export {
488
488
  Sidebar,
489
489
  SidebarItem,
490
490
  SidebarGroupLabel,
491
+ SidebarTreeGroup,
491
492
  SidebarNav,
492
493
  } from "./components/patterns/sidebar.tsx";
493
494
  export type {
494
495
  SidebarProps,
495
496
  SidebarItemProps,
497
+ SidebarTreeGroupProps,
496
498
  SidebarNavGroup,
497
- SidebarNavSubgroup,
498
499
  SidebarNavItem,
499
500
  } from "./components/patterns/sidebar.tsx";
500
501
 
package/src/ui/theme.css CHANGED
@@ -59,6 +59,9 @@
59
59
  --context-primary-subtle: color-mix(in oklab, var(--primary) 8%, transparent);
60
60
  --context-primary-emphasis: var(--foreground);
61
61
  --context-primary-border: color-mix(in oklab, var(--primary) 25%, transparent);
62
+ /* info/success/warning: base, foreground, subtle e border (12 tokens) valem nos dois temas
63
+ de propósito — são cores saturadas com alpha, que já se assentam sobre qualquer canvas;
64
+ só `*-emphasis` (texto sobre o popover) precisa clarear no escuro, e é redefinido em .dark. */
62
65
  --context-info: hsl(217 91% 60%);
63
66
  --context-info-foreground: hsl(0 0% 100%);
64
67
  --context-info-subtle: hsl(217 91% 60% / 0.1);
@@ -82,7 +85,7 @@
82
85
  --border: hsl(0 0% 92.5%);
83
86
  --input: hsl(0 0% 92.5%);
84
87
  /* Ring de foco LEVE (pedido da casa): aro sutil, não um halo. Com ring-[0.1875rem] + /50,
85
- ~86% encosta na borda (89.8%) — um sussurro de foco. */
88
+ ~86% encosta na borda (92.5%) — um sussurro de foco. */
86
89
  --ring: hsl(0 0% 86%);
87
90
  --radius: 0.75rem;
88
91
  }
@@ -107,10 +110,9 @@
107
110
  --accent-foreground: hsl(0 0% 98%);
108
111
  /* Vermelho CLARO no escuro (era 30.6% — calibrado só pra FUNDO, com texto branco).
109
112
  Como o menu/alert/field/erros usam `text-destructive` como FOREGROUND, o valor
110
- escuro dava ~1,7:1 sobre o popover — ilegível. ~58% passa o AA como texto e é o
111
- que o success fazia (dark:text-emerald-400 pula pro tom claro). Fundo sólido
112
- (Button/Badge/toast destructive) fica mais vivo — igual ao light, com branco por
113
- cima, como o shadcn novo. */
113
+ escuro dava ~1,7:1 sobre o popover — ilegível. ~58% passa o AA como texto, o mesmo
114
+ salto que os `*-emphasis` abaixo dão para o tom claro. Fundo sólido (Button/Badge/toast
115
+ danger) fica mais vivo — igual ao light, com branco por cima, como o shadcn novo. */
114
116
  --destructive: hsl(0 72% 58%);
115
117
  --destructive-foreground: hsl(0 0% 98%);
116
118
  --context-info-emphasis: hsl(213 94% 68%);
@@ -272,8 +274,8 @@
272
274
  }
273
275
  :root::-webkit-scrollbar-thumb,
274
276
  :root *::-webkit-scrollbar-thumb {
275
- border: 2px solid transparent;
276
- border-radius: 9999px;
277
+ border: 2px solid transparent; /* px: hairline dupla do thumb — não deve escalar com a fonte. */
278
+ border-radius: 9999px; /* px: raio efetivamente infinito do scrollbar nativo. */
277
279
  background-color: transparent;
278
280
  background-clip: content-box;
279
281
  }
@@ -322,5 +324,55 @@
322
324
 
323
325
  /* Code block = superfície da casa (borda + bg muted) — só o <pre> CRU do prose. */
324
326
  .prose :where(pre):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
325
- border: 1px solid var(--border);
327
+ border: 1px solid var(--border); /* px: hairline do bloco de código — 1 pixel físico, não escala. */
328
+ }
329
+
330
+ /* O Sonner reserva por padrão apenas 1rem para a mídia. A moldura semântica do
331
+ * Opus ocupa 2.25rem; a coluna precisa ter a mesma medida para não avançar sob
332
+ * título e descrição. Estas classes são a fronteira estável com o CSS interno
333
+ * do Sonner, independentemente da ordem em que a biblioteca injeta seus estilos. */
334
+ .opus-toast {
335
+ gap: 0.75rem;
336
+ }
337
+
338
+ .opus-toast .opus-toast-icon {
339
+ width: 2.25rem;
340
+ height: 2.25rem;
341
+ margin: 0;
342
+ align-self: flex-start;
343
+ align-items: center;
344
+ justify-content: center;
345
+ }
346
+
347
+ .toaster .opus-toast[data-sonner-toast] .opus-toast-close[data-close-button]:focus-visible {
348
+ box-shadow: 0 0 0 0.125rem color-mix(in srgb, var(--ring) 50%, transparent);
349
+ }
350
+
351
+ .toaster .opus-toast[data-sonner-toast] .opus-toast-close[data-close-button][data-disabled='true'] {
352
+ pointer-events: none;
353
+ opacity: 0.5;
354
+ }
355
+
356
+ /* Fechar continua sendo um controle circular de ícone, mas deixa de herdar a
357
+ * paleta cinza, a medida e o foco particulares do Sonner. */
358
+ .toaster .opus-toast[data-sonner-toast] .opus-toast-close[data-close-button] {
359
+ box-sizing: border-box;
360
+ width: 1.5rem;
361
+ height: 1.5rem;
362
+ border: 0;
363
+ border-radius: 9999rem;
364
+ background: var(--popover);
365
+ color: var(--muted-foreground);
366
+ outline: none;
367
+ transition: color 150ms, background-color 150ms, box-shadow 150ms;
368
+ }
369
+
370
+ .toaster .opus-toast[data-sonner-toast] .opus-toast-close[data-close-button]:hover {
371
+ background: var(--accent);
372
+ color: var(--accent-foreground);
373
+ }
374
+
375
+ .toaster .opus-toast[data-sonner-toast] .opus-toast-close[data-close-button] svg {
376
+ width: 1rem;
377
+ height: 1rem;
326
378
  }
@@ -21,7 +21,7 @@
21
21
  * // vite --mode design
22
22
  */
23
23
 
24
- import { readdirSync, readFileSync } from 'node:fs'
24
+ import { readdirSync } from 'node:fs'
25
25
  import type { IncomingMessage, ServerResponse } from 'node:http'
26
26
  import path from 'node:path'
27
27
  import type { Plugin, ViteDevServer } from 'vite'
@@ -40,6 +40,7 @@ import {
40
40
  type RuntimeSetup,
41
41
  type User,
42
42
  } from '../core/index.ts'
43
+ import { readPackageVersion } from '../core/package-version.ts'
43
44
  import { mittEvents } from '../events/drivers/mitt.ts'
44
45
  import { nodeServer, type NodeServerHandle } from '../server/drivers/node.ts'
45
46
  import { serializeResult } from '../server/index.ts'
@@ -148,7 +149,7 @@ export function opusDesign(options: OpusDesignOptions = {}): Plugin {
148
149
  const stubEntries = Object.entries(options.stubs ?? {}).sort(
149
150
  (a, b) => b[0].length - a[0].length,
150
151
  )
151
- const opusVersion = readOpusVersion()
152
+ const opusVersion = readPackageVersion()
152
153
 
153
154
  let exProxyPrefixes: string[] = []
154
155
  let current: Promise<DesignState> | undefined
@@ -373,7 +374,7 @@ export function opusDesign(options: OpusDesignOptions = {}): Plugin {
373
374
  sendEnvelope(res, 503, {
374
375
  code: 'design.boot_failed',
375
376
  category: 'dependency',
376
- message: `Design runtime failed to boot: ${String(err)}`,
377
+ message: `O runtime de design não conseguiu iniciar: ${String(err)}`,
377
378
  })
378
379
  return
379
380
  }
@@ -421,7 +422,7 @@ export function opusDesign(options: OpusDesignOptions = {}): Plugin {
421
422
  sendEnvelope(res, 503, {
422
423
  code: 'design.no_backend',
423
424
  category: 'dependency',
424
- message: `No backend for "${orphan}" in design mode add a stub or serve it from the opus runtime`,
425
+ message: `Sem backend para "${orphan}" em modo design — adicione um stub ou sirva a action pelo runtime do Opus`,
425
426
  })
426
427
  return
427
428
  }
@@ -464,7 +465,7 @@ async function loadEntry(server: ViteDevServer, entry: string): Promise<unknown[
464
465
  throw error({
465
466
  code: 'design.invalid_entry',
466
467
  category: 'internal',
467
- message: `Entry "${entry}" must default-export { domains: [...] } or an array of registrables`,
468
+ message: `O entry "${entry}" precisa exportar por default { domains: [...] } ou uma lista de registráveis`,
468
469
  })
469
470
  }
470
471
 
@@ -637,16 +638,3 @@ function sendEnvelope(res: ServerResponse, status: number, input: ErrorInput): v
637
638
  )
638
639
  }
639
640
 
640
- function readOpusVersion(): string {
641
- // `import.meta.url` sobrevive ao bundling do vite.config (o vite injeta a
642
- // URL original do arquivo), então o package.json resolve do source real.
643
- try {
644
- const pkg = JSON.parse(
645
- readFileSync(new URL('../../package.json', import.meta.url), 'utf8'),
646
- ) as { version?: string }
647
- return pkg.version ?? '0.0.0'
648
- /* v8 ignore next 3 — defensivo; o package.json viaja junto do source */
649
- } catch {
650
- return '0.0.0'
651
- }
652
- }
@@ -1,192 +0,0 @@
1
- import * as React from "react"
2
- import { AlertDialog as AlertDialogPrimitive } from "radix-ui"
3
-
4
- import { cn } from '../../lib/cn.ts'
5
- import { Button } from './button.tsx'
6
-
7
- function AlertDialog({
8
- ...props
9
- }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
10
- return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
11
- }
12
-
13
- function AlertDialogTrigger({
14
- ...props
15
- }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
16
- return (
17
- <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
18
- )
19
- }
20
-
21
- function AlertDialogPortal({
22
- ...props
23
- }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
24
- return (
25
- <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
26
- )
27
- }
28
-
29
- function AlertDialogOverlay({
30
- className,
31
- ...props
32
- }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
33
- return (
34
- <AlertDialogPrimitive.Overlay
35
- data-slot="alert-dialog-overlay"
36
- className={cn(
37
- "fixed inset-0 z-50 bg-black/30 backdrop-blur-xs data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
38
- className
39
- )}
40
- {...props}
41
- />
42
- )
43
- }
44
-
45
- function AlertDialogContent({
46
- className,
47
- ...props
48
- }: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
49
- return (
50
- <AlertDialogPortal>
51
- <AlertDialogOverlay />
52
- <AlertDialogPrimitive.Content
53
- data-slot="alert-dialog-content"
54
- className={cn(
55
- "group/alert-dialog-content fixed top-[50%] left-[50%] z-50 grid w-full max-w-xs translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl border border-border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
56
- className
57
- )}
58
- {...props}
59
- />
60
- </AlertDialogPortal>
61
- )
62
- }
63
-
64
- function AlertDialogHeader({
65
- className,
66
- ...props
67
- }: React.ComponentProps<"div">) {
68
- return (
69
- <div
70
- data-slot="alert-dialog-header"
71
- className={cn(
72
- "grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr]",
73
- className
74
- )}
75
- {...props}
76
- />
77
- )
78
- }
79
-
80
- function AlertDialogFooter({
81
- className,
82
- ...props
83
- }: React.ComponentProps<"div">) {
84
- return (
85
- <div
86
- data-slot="alert-dialog-footer"
87
- className={cn(
88
- "grid grid-cols-2 gap-2",
89
- className
90
- )}
91
- {...props}
92
- />
93
- )
94
- }
95
-
96
- function AlertDialogTitle({
97
- className,
98
- ...props
99
- }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
100
- return (
101
- <AlertDialogPrimitive.Title
102
- data-slot="alert-dialog-title"
103
- className={cn(
104
- "text-lg font-semibold",
105
- className
106
- )}
107
- {...props}
108
- />
109
- )
110
- }
111
-
112
- function AlertDialogDescription({
113
- className,
114
- ...props
115
- }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
116
- return (
117
- <AlertDialogPrimitive.Description
118
- data-slot="alert-dialog-description"
119
- className={cn("text-sm text-muted-foreground", className)}
120
- {...props}
121
- />
122
- )
123
- }
124
-
125
- function AlertDialogMedia({
126
- className,
127
- ...props
128
- }: React.ComponentProps<"div">) {
129
- return (
130
- <div
131
- data-slot="alert-dialog-media"
132
- className={cn(
133
- "mb-2 inline-flex size-16 items-center justify-center rounded-md bg-muted *:[svg:not([class*='size-'])]:size-8",
134
- className
135
- )}
136
- {...props}
137
- />
138
- )
139
- }
140
-
141
- function AlertDialogAction({
142
- className,
143
- context = "primary",
144
- variant = "solid",
145
- size = "default",
146
- ...props
147
- }: React.ComponentProps<typeof AlertDialogPrimitive.Action> &
148
- Pick<React.ComponentProps<typeof Button>, "context" | "variant" | "size">) {
149
- return (
150
- <Button context={context} variant={variant} size={size} asChild>
151
- <AlertDialogPrimitive.Action
152
- data-slot="alert-dialog-action"
153
- className={cn(className)}
154
- {...props}
155
- />
156
- </Button>
157
- )
158
- }
159
-
160
- function AlertDialogCancel({
161
- className,
162
- context = "neutral",
163
- variant = "ghost",
164
- size = "default",
165
- ...props
166
- }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel> &
167
- Pick<React.ComponentProps<typeof Button>, "context" | "variant" | "size">) {
168
- return (
169
- <Button context={context} variant={variant} size={size} asChild>
170
- <AlertDialogPrimitive.Cancel
171
- data-slot="alert-dialog-cancel"
172
- className={cn(className)}
173
- {...props}
174
- />
175
- </Button>
176
- )
177
- }
178
-
179
- export {
180
- AlertDialog,
181
- AlertDialogAction,
182
- AlertDialogCancel,
183
- AlertDialogContent,
184
- AlertDialogDescription,
185
- AlertDialogFooter,
186
- AlertDialogHeader,
187
- AlertDialogMedia,
188
- AlertDialogOverlay,
189
- AlertDialogPortal,
190
- AlertDialogTitle,
191
- AlertDialogTrigger,
192
- }
@@ -1,73 +0,0 @@
1
- ## Quase sempre é o `dialog`
2
-
3
- Pergunta de sim/não, um aviso a reconhecer, uma string — **não monte isto à mão**: o trio
4
- `dialog.confirm/alert/prompt` faz em uma linha, e o `body` cobre até corpo com conteúdo
5
- próprio (lista, detalhe). A demo viva mora na [página do dialog](/ui/confirm). Este
6
- componente é o **primitivo por baixo deles**.
7
-
8
- Então **componha o AlertDialog à mão só quando o trio não alcança**: mais de duas ações, ou
9
- um layout totalmente custom. É o que as seções abaixo mostram.
10
-
11
- ## Mais de duas ações
12
-
13
- O caso que o `confirm` (binário) não expressa: três saídas. `AlertDialogTrigger` (asChild
14
- com Button) abre; cada `AlertDialogAction`/`AlertDialogCancel` é uma saída. Diferente do
15
- Dialog, **não fecha clicando fora** — exige uma escolha.
16
-
17
- ```tsx preview
18
- <AlertDialog>
19
- <AlertDialogTrigger asChild>
20
- <Button variant="outline">Fechar editor</Button>
21
- </AlertDialogTrigger>
22
- <AlertDialogContent>
23
- <AlertDialogHeader>
24
- <AlertDialogTitle>Alterações não salvas</AlertDialogTitle>
25
- <AlertDialogDescription>
26
- Você editou o contrato e ainda não salvou. O que fazer antes de fechar?
27
- </AlertDialogDescription>
28
- </AlertDialogHeader>
29
- <AlertDialogFooter>
30
- <AlertDialogCancel>Continuar editando</AlertDialogCancel>
31
- <AlertDialogAction variant="outline">Descartar</AlertDialogAction>
32
- <AlertDialogAction>Salvar e fechar</AlertDialogAction>
33
- </AlertDialogFooter>
34
- </AlertDialogContent>
35
- </AlertDialog>
36
- ```
37
-
38
- ## A estrutura e o botão destrutivo
39
-
40
- `AlertDialogHeader` (media/título/descrição) + `AlertDialogFooter` (as ações).
41
- `context="danger"` no `AlertDialogAction` (ele herda contexto, variante e tamanho do Button)
42
- comunica que a confirmação é perigosa. Uma confirmação destrutiva **binária** é só
43
- `dialog.confirm({ context: 'danger' })` — o exemplo abaixo é só para mostrar a composição e
44
- onde o `context` entra:
45
-
46
- ```tsx preview
47
- <AlertDialog>
48
- <AlertDialogTrigger asChild>
49
- <Button context="danger">Excluir repositório</Button>
50
- </AlertDialogTrigger>
51
- <AlertDialogContent>
52
- <AlertDialogHeader>
53
- <AlertDialogTitle>Excluir empresa-x-api?</AlertDialogTitle>
54
- <AlertDialogDescription>
55
- O repositório sai do workspace e os agentes vinculados perdem o acesso ao código. Não dá pra desfazer.
56
- </AlertDialogDescription>
57
- </AlertDialogHeader>
58
- <AlertDialogFooter>
59
- <AlertDialogCancel>Cancelar</AlertDialogCancel>
60
- <AlertDialogAction context="danger">Excluir</AlertDialogAction>
61
- </AlertDialogFooter>
62
- </AlertDialogContent>
63
- </AlertDialog>
64
- ```
65
-
66
- ## Props
67
-
68
- | Prop | Tipo | Default | Descrição |
69
- |---|---|---|---|
70
- | `open` (AlertDialog) | `boolean` | | Estado de aberto no modo controlado — pareie com onOpenChange. No padrão, o Trigger cuida disso. |
71
- | `onOpenChange` (AlertDialog) | `(open: boolean) => void` | | Chamado quando o diálogo abre ou fecha (Trigger, Cancel, Action ou Esc). |
72
- | `context` (Action/Cancel) | `'neutral' \| 'primary' \| 'danger'` | `primary` / `neutral` | Significado semântico herdado do Button. |
73
- | `variant` (Action/Cancel) | `'solid' \| 'subtle' \| 'outline' \| 'ghost' \| 'link'` | `solid` / `ghost` | Tratamento visual herdado do Button. |
@@ -1,71 +0,0 @@
1
- ## Básico
2
-
3
- Envolva os botões no ButtonGroup: as bordas internas colapsam e só as pontas ficam arredondadas.
4
- Use a mesma variant nos filhos pra manter a barra uniforme.
5
-
6
- ```tsx preview
7
- <ButtonGroup>
8
- <Button variant="outline">Visão geral</Button>
9
- <Button variant="outline">Sessões</Button>
10
- <Button variant="outline">Skills</Button>
11
- </ButtonGroup>
12
- ```
13
-
14
- ## Ação dividida
15
-
16
- O padrão da casa pra ação primária + variações: o botão principal, um separador e um gatilho de
17
- menu (size=icon).
18
-
19
- ```tsx preview
20
- <ButtonGroup>
21
- <Button icon={Play}>Rodar agente developer</Button>
22
- <ButtonGroupSeparator />
23
- <Button size="icon" aria-label="Mais opções">
24
- <ChevronDown />
25
- </Button>
26
- </ButtonGroup>
27
- ```
28
-
29
- ## Com rótulo
30
-
31
- ButtonGroupText cola um rótulo (fundo muted) ao grupo — bom pra prefixar o contexto. Aceita ícone
32
- via [&_svg] e asChild pra virar `<label>`.
33
-
34
- ```tsx preview
35
- <ButtonGroup>
36
- <ButtonGroupText>
37
- <GitBranch />
38
- empresa-x-api
39
- </ButtonGroupText>
40
- <Button variant="outline" icon={RotateCw}>
41
- Sincronizar
42
- </Button>
43
- </ButtonGroup>
44
- ```
45
-
46
- ## Vertical
47
-
48
- orientation=vertical empilha os filhos em coluna — as bordas que colapsam passam a ser as de
49
- cima/baixo. Combina com size=icon pra uma mini-toolbar.
50
-
51
- ```tsx preview col-start
52
- <ButtonGroup orientation="vertical">
53
- <Button variant="outline" size="icon" aria-label="Rodar sessão">
54
- <Play />
55
- </Button>
56
- <Button variant="outline" size="icon" aria-label="Pausar sessão">
57
- <Pause />
58
- </Button>
59
- <Button variant="outline" size="icon" aria-label="Reiniciar sessão">
60
- <RotateCw />
61
- </Button>
62
- </ButtonGroup>
63
- ```
64
-
65
- ## Props
66
-
67
- | Prop | Tipo | Default | Descrição |
68
- |---|---|---|---|
69
- | `orientation` (ButtonGroup) | `'horizontal' \| 'vertical'` | `'horizontal'` | Direção do bloco — vertical empilha os filhos em coluna. |
70
- | `orientation` (ButtonGroupSeparator) | `'horizontal' \| 'vertical'` | `'vertical'` | Direção do traço divisor — herde do grupo (vertical no horizontal). |
71
- | `asChild` (ButtonGroupText) | `boolean` | `false` | Renderiza como o filho (Radix Slot) — ex.: virar `<label>` sem forkar o estilo. |