@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.
- package/CHANGELOG.md +76 -0
- package/PROMOTED.md +46 -0
- package/README.md +28 -19
- package/bin/cli.mjs +87 -216
- package/bin/lib/check.mjs +2 -7
- package/bin/lib/cli-shared.mjs +131 -0
- package/bin/lib/copy.mjs +1 -5
- package/bin/lib/db.mjs +16 -74
- package/bin/lib/gen-openapi.mjs +3 -3
- package/bin/lib/gen-runner.mjs +1 -1
- package/bin/lib/gen.mjs +14 -69
- package/bin/lib/mcp.mjs +3 -1
- package/bin/lib/seed.mjs +5 -62
- package/docs/adr/0005-structural-surfaces-share-an-explicit-anatomy.md +93 -10
- package/docs/adr/0007-toast-actions-form-an-ordered-collection.md +63 -0
- package/docs/adr/0008-hierarchical-navigation-is-composed-at-the-consumer-boundary.md +71 -0
- package/docs/ownership-vs-shadcn-lock.md +2 -3
- package/docs/protocol.md +7 -7
- package/docs/radius-scale.md +1 -1
- package/docs/releasing.md +8 -2
- package/package.json +7 -3
- package/registry/skills/maintain-opus-docs/SKILL.md +83 -0
- package/registry/skills/maintain-opus-docs/agents/openai.yaml +4 -0
- package/registry/skills/maintain-opus-docs/references/editorial-standard.md +85 -0
- package/registry/skills/maintain-opus-docs/references/evaluations.md +34 -0
- package/registry/skills/maintain-opus-docs/scripts/audit-docs.mjs +81 -0
- package/registry/templates/app/package.json +1 -1
- package/registry/templates/app/src/main.tsx +4 -4
- package/src/audit/drivers/console.ts +1 -0
- package/src/auth/drivers/better-auth.ts +1 -0
- package/src/auth/drivers/jwt.ts +1 -0
- package/src/cache/drivers/memory.ts +1 -0
- package/src/client/drivers/fetch.ts +2 -1
- package/src/core/actions.ts +6 -1
- package/src/core/audit.ts +9 -3
- package/src/core/contracts.ts +7 -0
- package/src/core/domain.ts +1 -1
- package/src/core/errors.ts +18 -15
- package/src/core/index.ts +4 -2
- package/src/core/package-version.ts +26 -0
- package/src/core/reactions.ts +1 -1
- package/src/core/runtime.ts +33 -23
- package/src/core/schedules.ts +1 -1
- package/src/core/types.ts +2 -2
- package/src/dsl/eval.ts +2 -2
- package/src/dsl/kysely.ts +2 -2
- package/src/dsl/loads.ts +1 -1
- package/src/dsl/parser.ts +5 -5
- package/src/events/drivers/mitt.ts +1 -0
- package/src/mcp/index.ts +2 -1
- package/src/observability/drivers/opentelemetry.ts +1 -0
- package/src/queue/drivers/bullmq.ts +3 -3
- package/src/scheduler/drivers/node-cron.ts +3 -2
- package/src/scheduler/every.ts +7 -7
- package/src/schema/openapi.ts +3 -3
- package/src/seed/index.ts +29 -0
- package/src/server/drivers/fastify.ts +5 -2
- package/src/server/drivers/node.ts +9 -6
- package/src/server/index.ts +3 -1
- package/src/storage/drivers/fs.ts +1 -0
- package/src/testing/index.ts +3 -3
- package/src/ui/components/patterns/confirm.tsx +142 -42
- package/src/ui/components/patterns/content-header.tsx +7 -1
- package/src/ui/components/patterns/data-state.tsx +1 -1
- package/src/ui/components/patterns/dock.tsx +20 -3
- package/src/ui/components/patterns/form.tsx +12 -8
- package/src/ui/components/patterns/list.tsx +36 -41
- package/src/ui/components/patterns/page-state.tsx +2 -2
- package/src/ui/components/patterns/page.tsx +19 -1
- package/src/ui/components/patterns/shell-nav.tsx +10 -3
- package/src/ui/components/patterns/sidebar.tsx +43 -32
- package/src/ui/components/patterns/trigger.tsx +39 -38
- package/src/ui/components/patterns/view.tsx +26 -17
- package/src/ui/components/primitives/alert.tsx +14 -8
- package/src/ui/components/primitives/ask.tsx +3 -3
- package/src/ui/components/primitives/badge.tsx +11 -6
- package/src/ui/components/primitives/breadcrumb.tsx +2 -2
- package/src/ui/components/primitives/button.tsx +16 -3
- package/src/ui/components/primitives/calendar.tsx +28 -2
- package/src/ui/components/primitives/carousel.tsx +3 -3
- package/src/ui/components/primitives/chat.tsx +1 -1
- package/src/ui/components/primitives/checkbox.tsx +1 -1
- package/src/ui/components/primitives/command.tsx +2 -2
- package/src/ui/components/primitives/control.ts +12 -0
- package/src/ui/components/primitives/copyable.tsx +1 -1
- package/src/ui/components/primitives/dialog.tsx +202 -40
- package/src/ui/components/primitives/dot.tsx +5 -0
- package/src/ui/components/primitives/drawer.tsx +18 -8
- package/src/ui/components/primitives/empty.tsx +3 -3
- package/src/ui/components/primitives/field.tsx +3 -3
- package/src/ui/components/primitives/icon-picker.tsx +3 -1
- package/src/ui/components/primitives/input-group.tsx +1 -1
- package/src/ui/components/primitives/input-otp.tsx +1 -1
- package/src/ui/components/primitives/input.tsx +2 -2
- package/src/ui/components/primitives/item.tsx +3 -3
- package/src/ui/components/primitives/progress.tsx +32 -3
- package/src/ui/components/primitives/radio-group.tsx +1 -1
- package/src/ui/components/primitives/resizable.tsx +3 -1
- package/src/ui/components/primitives/select.tsx +5 -5
- package/src/ui/components/primitives/slider.tsx +5 -1
- package/src/ui/components/primitives/sonner.tsx +190 -8
- package/src/ui/components/primitives/switch.tsx +1 -0
- package/src/ui/components/primitives/tabs.tsx +1 -0
- package/src/ui/components/primitives/textarea.tsx +1 -1
- package/src/ui/components/primitives/toggle.tsx +1 -1
- package/src/ui/components/primitives/tooltip.tsx +1 -0
- package/src/ui/docs/DocBrowser.tsx +102 -23
- package/src/ui/docs/changelog.tsx +1 -1
- package/src/ui/docs/content/accordion.md +22 -16
- package/src/ui/docs/content/action-form-card.md +8 -8
- package/src/ui/docs/content/action-form-dialog.md +9 -9
- package/src/ui/docs/content/action-form.md +37 -36
- package/src/ui/docs/content/action-list-dialog.md +11 -6
- package/src/ui/docs/content/action-list.md +73 -39
- package/src/ui/docs/content/action-trigger.md +29 -15
- package/src/ui/docs/content/action-view.md +17 -10
- package/src/ui/docs/content/actions.md +9 -9
- package/src/ui/docs/content/ai.md +3 -3
- package/src/ui/docs/content/alert.md +14 -12
- package/src/ui/docs/content/ask.md +11 -0
- package/src/ui/docs/content/aspect-ratio.md +4 -4
- package/src/ui/docs/content/audit.md +2 -2
- package/src/ui/docs/content/auth.md +3 -3
- package/src/ui/docs/content/avatar.md +34 -14
- package/src/ui/docs/content/badge.md +3 -3
- package/src/ui/docs/content/breadcrumb.md +13 -8
- package/src/ui/docs/content/button.md +81 -6
- package/src/ui/docs/content/calendar.md +18 -5
- package/src/ui/docs/content/card.md +27 -1
- package/src/ui/docs/content/carousel.md +16 -11
- package/src/ui/docs/content/chat.md +23 -3
- package/src/ui/docs/content/checkbox.md +7 -7
- package/src/ui/docs/content/cli.md +74 -22
- package/src/ui/docs/content/collapsible.md +8 -8
- package/src/ui/docs/content/command.md +16 -8
- package/src/ui/docs/content/composer.md +17 -2
- package/src/ui/docs/content/content.md +17 -2
- package/src/ui/docs/content/copyable.md +12 -3
- package/src/ui/docs/content/customization.md +5 -5
- package/src/ui/docs/content/cycle.md +3 -3
- package/src/ui/docs/content/data-state.md +11 -12
- package/src/ui/docs/content/data.md +26 -33
- package/src/ui/docs/content/detail.md +22 -4
- package/src/ui/docs/content/dialog.md +339 -31
- package/src/ui/docs/content/dictionary-value.md +17 -10
- package/src/ui/docs/content/dock.md +11 -3
- package/src/ui/docs/content/dot.md +8 -0
- package/src/ui/docs/content/drawer.md +27 -14
- package/src/ui/docs/content/empty-value.md +2 -2
- package/src/ui/docs/content/empty.md +19 -12
- package/src/ui/docs/content/events.md +4 -4
- package/src/ui/docs/content/field.md +34 -12
- package/src/ui/docs/content/getting-started.md +3 -3
- package/src/ui/docs/content/icon-picker.md +19 -4
- package/src/ui/docs/content/input-otp.md +20 -12
- package/src/ui/docs/content/input.md +121 -9
- package/src/ui/docs/content/item.md +27 -13
- package/src/ui/docs/content/kbd.md +19 -11
- package/src/ui/docs/content/label.md +12 -3
- package/src/ui/docs/content/log.md +4 -4
- package/src/ui/docs/content/markdown.md +7 -6
- package/src/ui/docs/content/mcp.md +13 -15
- package/src/ui/docs/content/menu.md +40 -16
- package/src/ui/docs/content/metric-card.md +13 -0
- package/src/ui/docs/content/observability.md +2 -2
- package/src/ui/docs/content/page.md +59 -6
- package/src/ui/docs/content/pagination.md +22 -17
- package/src/ui/docs/content/popover.md +22 -8
- package/src/ui/docs/content/progress.md +15 -16
- package/src/ui/docs/content/queue.md +5 -5
- package/src/ui/docs/content/radio-group.md +20 -12
- package/src/ui/docs/content/router.md +11 -6
- package/src/ui/docs/content/scheduler.md +4 -5
- package/src/ui/docs/content/scroll-area.md +12 -7
- package/src/ui/docs/content/select.md +47 -34
- package/src/ui/docs/content/semantic-context.md +2 -2
- package/src/ui/docs/content/separator.md +5 -5
- package/src/ui/docs/content/sidebar.md +329 -54
- package/src/ui/docs/content/skeleton.md +9 -2
- package/src/ui/docs/content/slider.md +8 -7
- package/src/ui/docs/content/spinner.md +8 -8
- package/src/ui/docs/content/split.md +29 -5
- package/src/ui/docs/content/storage.md +6 -8
- package/src/ui/docs/content/switch.md +8 -7
- package/src/ui/docs/content/table.md +13 -3
- package/src/ui/docs/content/tabs.md +28 -14
- package/src/ui/docs/content/testing.md +9 -11
- package/src/ui/docs/content/textarea.md +12 -4
- package/src/ui/docs/content/toast.md +47 -13
- package/src/ui/docs/content/toggle.md +75 -7
- package/src/ui/docs/content/tokens.md +7 -7
- package/src/ui/docs/content/tooltip.md +19 -11
- package/src/ui/docs/content/truncate.md +15 -8
- package/src/ui/docs/content/ui.md +24 -9
- package/src/ui/docs/content/upgrading.md +7 -8
- package/src/ui/docs/doc-client.tsx +5 -5
- package/src/ui/docs/doc.tsx +26 -14
- package/src/ui/docs/registry.tsx +25 -42
- package/src/ui/docs/standalone.tsx +2 -2
- package/src/ui/drivers/react.tsx +17 -12
- package/src/ui/lib/action-errors.ts +45 -0
- package/src/ui/lib/zod-pt-br.ts +31 -4
- package/src/ui/meta.ts +65 -95
- package/src/ui/react.tsx +17 -16
- package/src/ui/theme.css +60 -8
- package/src/vite/design.ts +6 -18
- package/src/ui/components/primitives/alert-dialog.tsx +0 -192
- package/src/ui/docs/content/alert-dialog.md +0 -73
- package/src/ui/docs/content/button-group.md +0 -71
- package/src/ui/docs/content/confirm.md +0 -120
- package/src/ui/docs/content/input-group.md +0 -79
- package/src/ui/docs/content/page-state.md +0 -45
- 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
|
-
|
|
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 (
|
|
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
|
|
111
|
-
que
|
|
112
|
-
|
|
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
|
}
|
package/src/vite/design.ts
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* // vite --mode design
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { readdirSync
|
|
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 =
|
|
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: `
|
|
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: `
|
|
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: `
|
|
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. |
|