@softize/opus 13.0.0 → 14.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/PROMOTED.md +46 -0
  3. package/README.md +28 -19
  4. package/bin/cli.mjs +87 -216
  5. package/bin/lib/cli-shared.mjs +131 -0
  6. package/bin/lib/copy.mjs +276 -6
  7. package/bin/lib/db.mjs +16 -74
  8. package/bin/lib/gen-openapi.mjs +3 -3
  9. package/bin/lib/gen-runner.mjs +1 -1
  10. package/bin/lib/gen.mjs +14 -69
  11. package/bin/lib/mcp.mjs +3 -1
  12. package/bin/lib/seed.mjs +5 -62
  13. package/docs/code-style.md +4 -1
  14. package/docs/ownership-vs-shadcn-lock.md +2 -3
  15. package/docs/protocol.md +7 -7
  16. package/docs/releasing.md +8 -2
  17. package/package.json +7 -3
  18. package/registry/instructions/opus.md +3 -3
  19. package/registry/templates/app/package.json +1 -1
  20. package/registry/templates/app/src/App.tsx +11 -6
  21. package/registry/templates/app/src/main.tsx +4 -4
  22. package/src/audit/drivers/console.ts +1 -0
  23. package/src/auth/drivers/better-auth.ts +1 -0
  24. package/src/auth/drivers/jwt.ts +1 -0
  25. package/src/cache/drivers/memory.ts +1 -0
  26. package/src/client/drivers/fetch.ts +2 -1
  27. package/src/core/actions.ts +6 -1
  28. package/src/core/audit.ts +9 -3
  29. package/src/core/contracts.ts +7 -0
  30. package/src/core/domain.ts +1 -1
  31. package/src/core/errors.ts +18 -15
  32. package/src/core/index.ts +4 -2
  33. package/src/core/package-version.ts +26 -0
  34. package/src/core/reactions.ts +1 -1
  35. package/src/core/runtime.ts +33 -23
  36. package/src/core/schedules.ts +1 -1
  37. package/src/core/types.ts +5 -6
  38. package/src/dsl/eval.ts +2 -2
  39. package/src/dsl/kysely.ts +2 -2
  40. package/src/dsl/loads.ts +1 -1
  41. package/src/dsl/parser.ts +5 -5
  42. package/src/events/drivers/mitt.ts +1 -0
  43. package/src/mcp/index.ts +2 -1
  44. package/src/observability/drivers/opentelemetry.ts +1 -0
  45. package/src/queue/drivers/bullmq.ts +3 -3
  46. package/src/scheduler/drivers/node-cron.ts +3 -2
  47. package/src/scheduler/every.ts +7 -7
  48. package/src/schema/openapi.ts +3 -3
  49. package/src/seed/index.ts +29 -0
  50. package/src/server/drivers/fastify.ts +5 -2
  51. package/src/server/drivers/node.ts +9 -6
  52. package/src/server/index.ts +3 -1
  53. package/src/storage/drivers/fs.ts +1 -0
  54. package/src/testing/index.ts +3 -3
  55. package/src/ui/components/patterns/action-list-dialog.tsx +10 -3
  56. package/src/ui/components/patterns/confirm.tsx +2 -31
  57. package/src/ui/components/patterns/content-header.tsx +44 -137
  58. package/src/ui/components/patterns/data-state.tsx +42 -68
  59. package/src/ui/components/patterns/dock.tsx +20 -3
  60. package/src/ui/components/patterns/form.tsx +26 -22
  61. package/src/ui/components/patterns/list.tsx +18 -12
  62. package/src/ui/components/patterns/page-state.tsx +39 -51
  63. package/src/ui/components/patterns/page.tsx +37 -54
  64. package/src/ui/components/patterns/sidebar.tsx +17 -6
  65. package/src/ui/components/patterns/state-surface.tsx +148 -0
  66. package/src/ui/components/patterns/surface-header.tsx +119 -0
  67. package/src/ui/components/patterns/trigger.tsx +21 -25
  68. package/src/ui/components/patterns/view.tsx +29 -22
  69. package/src/ui/components/primitives/alert.tsx +1 -27
  70. package/src/ui/components/primitives/ask.tsx +3 -3
  71. package/src/ui/components/primitives/avatar.tsx +15 -5
  72. package/src/ui/components/primitives/badge.tsx +5 -41
  73. package/src/ui/components/primitives/breadcrumb.tsx +2 -2
  74. package/src/ui/components/primitives/button.tsx +39 -30
  75. package/src/ui/components/primitives/calendar.tsx +28 -2
  76. package/src/ui/components/primitives/carousel.tsx +3 -3
  77. package/src/ui/components/primitives/chat.tsx +1 -1
  78. package/src/ui/components/primitives/checkbox.tsx +1 -1
  79. package/src/ui/components/primitives/command.tsx +2 -2
  80. package/src/ui/components/primitives/control.ts +72 -0
  81. package/src/ui/components/primitives/copyable.tsx +1 -1
  82. package/src/ui/components/primitives/dialog.tsx +12 -7
  83. package/src/ui/components/primitives/dot.tsx +1 -25
  84. package/src/ui/components/primitives/drawer.tsx +10 -3
  85. package/src/ui/components/primitives/field.tsx +3 -3
  86. package/src/ui/components/primitives/icon-picker.tsx +3 -1
  87. package/src/ui/components/primitives/input-group.tsx +12 -9
  88. package/src/ui/components/primitives/input-otp.tsx +1 -1
  89. package/src/ui/components/primitives/input.tsx +2 -2
  90. package/src/ui/components/primitives/item.tsx +3 -1
  91. package/src/ui/components/primitives/menu.tsx +1 -7
  92. package/src/ui/components/primitives/pagination.tsx +16 -8
  93. package/src/ui/components/primitives/progress.tsx +32 -3
  94. package/src/ui/components/primitives/radio-group.tsx +1 -1
  95. package/src/ui/components/primitives/resizable.tsx +3 -1
  96. package/src/ui/components/primitives/select.tsx +6 -6
  97. package/src/ui/components/primitives/slider.tsx +5 -1
  98. package/src/ui/components/primitives/sonner.tsx +3 -0
  99. package/src/ui/components/primitives/spinner.tsx +13 -16
  100. package/src/ui/components/primitives/switch.tsx +5 -1
  101. package/src/ui/components/primitives/tabs.tsx +6 -3
  102. package/src/ui/components/primitives/textarea.tsx +1 -1
  103. package/src/ui/components/primitives/toggle.tsx +9 -4
  104. package/src/ui/components/primitives/tooltip.tsx +1 -0
  105. package/src/ui/docs/changelog.tsx +1 -1
  106. package/src/ui/docs/content/action-form.md +36 -3
  107. package/src/ui/docs/content/action-list-dialog.md +2 -2
  108. package/src/ui/docs/content/action-list.md +13 -2
  109. package/src/ui/docs/content/action-trigger.md +12 -5
  110. package/src/ui/docs/content/action-view.md +11 -3
  111. package/src/ui/docs/content/ask.md +11 -0
  112. package/src/ui/docs/content/avatar.md +7 -3
  113. package/src/ui/docs/content/button.md +30 -14
  114. package/src/ui/docs/content/calendar.md +13 -0
  115. package/src/ui/docs/content/card.md +26 -0
  116. package/src/ui/docs/content/chat.md +20 -0
  117. package/src/ui/docs/content/cli.md +71 -19
  118. package/src/ui/docs/content/communication.md +36 -0
  119. package/src/ui/docs/content/composer.md +15 -0
  120. package/src/ui/docs/content/content.md +17 -1
  121. package/src/ui/docs/content/copyable.md +8 -0
  122. package/src/ui/docs/content/data-state.md +17 -13
  123. package/src/ui/docs/content/detail.md +19 -1
  124. package/src/ui/docs/content/dialog.md +1 -4
  125. package/src/ui/docs/content/dictionary-value.md +9 -2
  126. package/src/ui/docs/content/dock.md +8 -0
  127. package/src/ui/docs/content/dot.md +8 -0
  128. package/src/ui/docs/content/empty.md +2 -2
  129. package/src/ui/docs/content/getting-started.md +2 -2
  130. package/src/ui/docs/content/icon-picker.md +11 -0
  131. package/src/ui/docs/content/input.md +1 -1
  132. package/src/ui/docs/content/item.md +1 -1
  133. package/src/ui/docs/content/label.md +7 -0
  134. package/src/ui/docs/content/menu.md +6 -0
  135. package/src/ui/docs/content/metric-card.md +13 -0
  136. package/src/ui/docs/content/page.md +20 -4
  137. package/src/ui/docs/content/pagination.md +11 -9
  138. package/src/ui/docs/content/popover.md +6 -0
  139. package/src/ui/docs/content/progress.md +8 -11
  140. package/src/ui/docs/content/select.md +5 -5
  141. package/src/ui/docs/content/semantic-context.md +5 -4
  142. package/src/ui/docs/content/sidebar.md +13 -47
  143. package/src/ui/docs/content/skeleton.md +6 -0
  144. package/src/ui/docs/content/spinner.md +9 -6
  145. package/src/ui/docs/content/split.md +21 -0
  146. package/src/ui/docs/content/switch.md +1 -1
  147. package/src/ui/docs/content/tabs.md +1 -1
  148. package/src/ui/docs/content/textarea.md +7 -0
  149. package/src/ui/docs/content/toggle.md +1 -1
  150. package/src/ui/docs/content/tokens.md +4 -4
  151. package/src/ui/docs/content/truncate.md +8 -0
  152. package/src/ui/docs/content/ui.md +14 -0
  153. package/src/ui/docs/doc-client.tsx +5 -5
  154. package/src/ui/docs/doc.tsx +26 -14
  155. package/src/ui/docs/registry.tsx +5 -5
  156. package/src/ui/docs/standalone.tsx +2 -2
  157. package/src/ui/drivers/react.tsx +12 -12
  158. package/src/ui/lib/action-errors.ts +45 -0
  159. package/src/ui/lib/zod-pt-br.ts +31 -4
  160. package/src/ui/meta.ts +8 -8
  161. package/src/ui/react.tsx +10 -16
  162. package/src/ui/theme.css +10 -8
  163. package/src/vite/design.ts +6 -18
  164. package/src/ui/components/patterns/shell-nav.tsx +0 -147
@@ -1,147 +0,0 @@
1
- /**
2
- * <ShellNav /> — o menu como primitivo PIVOTÁVEL. Um nav (grupos → itens, com heading e
3
- * âncora inferior) que serve os DOIS lares do chrome sem flag:
4
- *
5
- * - dentro de <Sidebar> → recolhe pra ícone-só (com tooltip) junto com a coluna;
6
- * - fora de <Sidebar> → permanece expandido.
7
- *
8
- * "Tanto faz onde": o componente se adapta ao lugar, sem "modo" configurado.
9
- *
10
- * Presentacional e CONTROLADO — o app é dono do `activeId`, do clique e do roteamento.
11
- * v1 PLANA (grupos → itens); aninhamento (accordion/pasta) e DnD COMPOSTO entram quando o
12
- * primeiro consumidor de árvore migrar — ver `docs/shellnav.md`.
13
- */
14
-
15
- import type { ReactNode } from 'react'
16
- import { cn } from '../../lib/cn.ts'
17
- import { useSidebarCollapsed } from './sidebar.tsx'
18
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../primitives/tooltip.tsx'
19
-
20
- export interface ShellNavItem {
21
- /** Coordenada estável — volta em `onSelect` e casa com `activeId`. Único em toda a nav. */
22
- id: string
23
- label: string
24
- /** Ícone à esquerda (é o que sobra no modo recolhido — vira o alvo, com o label no tooltip). */
25
- icon?: ReactNode
26
- /** Selo à direita (contagem, `beta`). Some no recolhido. */
27
- badge?: ReactNode
28
- /** Visível mas inerte. */
29
- disabled?: boolean
30
- }
31
-
32
- export interface ShellNavGroup {
33
- /** Cabeçalho do grupo. Ausente/vazio = itens soltos, sem rótulo. Some no recolhido. */
34
- label?: string
35
- items: ShellNavItem[]
36
- }
37
-
38
- export interface ShellNavProps {
39
- groups: ShellNavGroup[]
40
- /** `id` do item ativo. Ausente = nenhum destacado. */
41
- activeId?: string
42
- onSelect: (id: string) => void
43
- /** Topo do nav — título, busca, botão (ex.: o "+" do Relatórios). Some no recolhido. Ver <ShellNavHeading>. */
44
- heading?: ReactNode
45
- /** Grupos ANCORADOS embaixo (ex.: Configurações no app), mesmo renderer, separados por filete. */
46
- footer?: ShellNavGroup[]
47
- /** Rótulo da landmark `<nav>`. */
48
- navLabel?: string
49
- /** Classes da raiz (a coluna). A largura vem do pane/sidebar que a contém. */
50
- className?: string
51
- }
52
-
53
- /** Rótulo só existe se tiver texto — vazio não vira cabeçalho fantasma. */
54
- const titled = (label?: string): boolean => (label ?? '').trim() !== ''
55
-
56
- /** Selo vazio não vira pílula sem texto. `0` conta (contagem legítima). */
57
- const shown = (badge: ReactNode): boolean => {
58
- if (badge === undefined || badge === null || badge === false || badge === '') return false
59
- if (typeof badge === 'number' && Number.isNaN(badge)) return false
60
- return !(Array.isArray(badge) && badge.length === 0)
61
- }
62
-
63
- /** Grupo sem item não abre buraco no `space-y` nem deixa rótulo pairando sobre nada. */
64
- const filled = (group: ShellNavGroup): boolean => group.items.length > 0
65
-
66
- function renderItem(item: ShellNavItem, activeId: string | undefined, onSelect: (id: string) => void, railed: boolean): React.ReactElement {
67
- const active = item.id === activeId
68
- const button = (
69
- <button
70
- type="button"
71
- disabled={item.disabled}
72
- aria-current={active ? 'page' : undefined}
73
- onClick={() => onSelect(item.id)}
74
- className={cn(
75
- 'flex w-full items-center gap-2.5 rounded-md py-1.5 text-left text-sm transition-colors',
76
- 'disabled:pointer-events-none disabled:opacity-40',
77
- 'outline-none focus-visible:ring-2 focus-visible:ring-ring/50',
78
- railed ? 'justify-center px-0' : 'px-2.5',
79
- active ? 'bg-muted font-medium text-foreground' : 'text-foreground/80 hover:bg-muted/60',
80
- )}
81
- >
82
- {item.icon !== undefined && <span className="flex shrink-0">{item.icon}</span>}
83
- {!railed && <span className="min-w-0 flex-1 truncate">{item.label}</span>}
84
- {!railed && shown(item.badge) && <span className="shrink-0">{item.badge}</span>}
85
- </button>
86
- )
87
- if (!railed) return <div key={item.id}>{button}</div>
88
- // Recolhido: o label migra pro tooltip (à direita) — sem ele, a coluna vira ícones adivinháveis.
89
- return (
90
- <Tooltip key={item.id}>
91
- <TooltipTrigger asChild>{button}</TooltipTrigger>
92
- <TooltipContent side="right">{item.label}</TooltipContent>
93
- </Tooltip>
94
- )
95
- }
96
-
97
- function renderGroup(group: ShellNavGroup, gi: number, activeId: string | undefined, onSelect: (id: string) => void, railed: boolean): React.ReactElement | null {
98
- if (!filled(group)) return null
99
- return (
100
- <div key={gi} className="space-y-0.5">
101
- {!railed && titled(group.label) && (
102
- <div className="px-2.5 pb-1 text-xs font-medium text-muted-foreground/70">{group.label}</div>
103
- )}
104
- {group.items.map((item) => renderItem(item, activeId, onSelect, railed))}
105
- </div>
106
- )
107
- }
108
-
109
- export function ShellNav({ groups, activeId, onSelect, heading, footer, navLabel = 'Navegação', className }: ShellNavProps): React.ReactElement {
110
- const railed = useSidebarCollapsed()
111
-
112
- const body = (
113
- <div data-slot="shell-nav" className={cn('flex h-full min-h-0 flex-col', className)}>
114
- {!railed && heading}
115
- <nav aria-label={navLabel} className={cn('min-h-0 flex-1 space-y-4 overflow-y-auto p-2', railed && 'px-1.5')}>
116
- {groups.map((group, gi) => renderGroup(group, gi, activeId, onSelect, railed))}
117
- </nav>
118
- {footer !== undefined && footer.some(filled) && (
119
- <div className={cn('space-y-4 border-t border-border p-2', railed && 'px-1.5')}>
120
- {footer.map((group, gi) => renderGroup(group, gi, activeId, onSelect, railed))}
121
- </div>
122
- )}
123
- </div>
124
- )
125
-
126
- // Recolhido usa tooltips — garante um provider (nested é ok se o app já tem um).
127
- return railed ? <TooltipProvider delayDuration={200}>{body}</TooltipProvider> : body
128
- }
129
-
130
- export interface ShellNavHeadingProps {
131
- /** Título da seção. */
132
- title: ReactNode
133
- /** Ação à direita — em geral um botão (o "+" de criar). */
134
- action?: ReactNode
135
- className?: string
136
- }
137
-
138
- /** Cabeçalho padrão do ShellNav: título + espaço pra um botão. É o gesto que hoje cada
139
- * nav monta à mão (o "+" do Relatórios, o título de Configurações). */
140
- export function ShellNavHeading({ title, action, className }: ShellNavHeadingProps): React.ReactElement {
141
- return (
142
- <div className={cn('flex h-12 shrink-0 items-center gap-1.5 border-b border-border px-4', className)}>
143
- <span className="min-w-0 flex-1 truncate text-sm font-semibold">{title}</span>
144
- {action !== undefined && <span className="shrink-0">{action}</span>}
145
- </div>
146
- )
147
- }