@softize/opus 8.6.6
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 +1616 -0
- package/LICENSE +21 -0
- package/README.md +113 -0
- package/bin/cli.mjs +528 -0
- package/bin/lib/check.mjs +307 -0
- package/bin/lib/components.mjs +151 -0
- package/bin/lib/create.mjs +208 -0
- package/bin/lib/db-check-runner.mjs +86 -0
- package/bin/lib/db-migrate-runner.mjs +89 -0
- package/bin/lib/db-scaffold-runner.mjs +84 -0
- package/bin/lib/db.mjs +261 -0
- package/bin/lib/docs-include.mjs +48 -0
- package/bin/lib/gen-dicts.mjs +134 -0
- package/bin/lib/gen-docs.mjs +288 -0
- package/bin/lib/gen-manifest.mjs +102 -0
- package/bin/lib/gen-openapi.mjs +195 -0
- package/bin/lib/gen-runner.mjs +472 -0
- package/bin/lib/gen-stubs.mjs +463 -0
- package/bin/lib/gen.mjs +311 -0
- package/bin/lib/init.mjs +514 -0
- package/bin/lib/introspect.mjs +107 -0
- package/bin/lib/mcp.mjs +85 -0
- package/bin/lib/postinstall.mjs +56 -0
- package/docs/chat-event-protocol.md +85 -0
- package/docs/code-style.md +16 -0
- package/docs/data-layer.md +246 -0
- package/docs/ownership-vs-shadcn-lock.md +102 -0
- package/docs/protocol.md +2053 -0
- package/docs/releasing.md +110 -0
- package/docs/shellnav.md +131 -0
- package/package.json +338 -0
- package/registry/hooks/hooks.json +26 -0
- package/registry/hooks/link-memory-on-start.mjs +46 -0
- package/registry/hooks/opus-check-on-stop.mjs +114 -0
- package/registry/skills/create-action/SKILL.md +49 -0
- package/registry/skills/create-action/scaffold.mjs +122 -0
- package/registry/templates/app/_gitignore +3 -0
- package/registry/templates/app/_npmrc +1 -0
- package/registry/templates/app/_opus/_gitignore +5 -0
- package/registry/templates/app/_prettierrc.json +6 -0
- package/registry/templates/app/index.html +13 -0
- package/registry/templates/app/opus.config.ts +16 -0
- package/registry/templates/app/package.json +43 -0
- package/registry/templates/app/pnpm-workspace.yaml +11 -0
- package/registry/templates/app/public/favicon.svg +4 -0
- package/registry/templates/app/src/App.tsx +37 -0
- package/registry/templates/app/src/domains/tasks/actions/list.test.ts +34 -0
- package/registry/templates/app/src/domains/tasks/actions/list.ts +33 -0
- package/registry/templates/app/src/domains/tasks/index.ts +13 -0
- package/registry/templates/app/src/index.css +18 -0
- package/registry/templates/app/src/main.tsx +25 -0
- package/registry/templates/app/tsconfig.json +20 -0
- package/registry/templates/app/vite.config.ts +46 -0
- package/registry/templates/monorepo/_gitignore +3 -0
- package/registry/templates/monorepo/_npmrc +1 -0
- package/registry/templates/monorepo/package.json +9 -0
- package/registry/templates/monorepo/pnpm-workspace.yaml +14 -0
- package/src/ai/ask.ts +64 -0
- package/src/ai/drivers/anthropic.ts +309 -0
- package/src/ai/index.ts +17 -0
- package/src/audit/drivers/console.ts +117 -0
- package/src/audit/drivers/pg.ts +172 -0
- package/src/audit/index.ts +51 -0
- package/src/auth/drivers/better-auth.ts +103 -0
- package/src/auth/drivers/jwt.ts +188 -0
- package/src/auth/index.ts +9 -0
- package/src/client/drivers/fetch.ts +202 -0
- package/src/client/index.ts +22 -0
- package/src/core/actions.ts +110 -0
- package/src/core/audit.ts +239 -0
- package/src/core/contracts.ts +137 -0
- package/src/core/domain.ts +310 -0
- package/src/core/errors.ts +181 -0
- package/src/core/index.ts +174 -0
- package/src/core/logical-type.ts +31 -0
- package/src/core/reactions.ts +81 -0
- package/src/core/runtime.ts +1167 -0
- package/src/core/schedules.ts +41 -0
- package/src/core/types.ts +1356 -0
- package/src/data/drivers/kysely.ts +389 -0
- package/src/data/index.ts +10 -0
- package/src/data/readonly-pool.ts +160 -0
- package/src/dsl/eval.ts +136 -0
- package/src/dsl/index.ts +29 -0
- package/src/dsl/kysely.ts +230 -0
- package/src/dsl/loads.ts +123 -0
- package/src/dsl/parser.ts +423 -0
- package/src/dsl/types.ts +113 -0
- package/src/events/drivers/mitt.ts +70 -0
- package/src/events/index.ts +9 -0
- package/src/log/drivers/pino.ts +57 -0
- package/src/log/index.ts +9 -0
- package/src/mcp/index.ts +62 -0
- package/src/queue/drivers/bullmq.ts +190 -0
- package/src/queue/index.ts +9 -0
- package/src/scheduler/drivers/node-cron.ts +93 -0
- package/src/scheduler/every.ts +45 -0
- package/src/scheduler/index.ts +9 -0
- package/src/schema/drivers/zod.ts +765 -0
- package/src/schema/entity.ts +439 -0
- package/src/schema/format/locale.ts +144 -0
- package/src/schema/index.ts +65 -0
- package/src/schema/openapi.ts +302 -0
- package/src/schema/scaffold.ts +160 -0
- package/src/server/drivers/fastify.ts +224 -0
- package/src/server/drivers/node.ts +386 -0
- package/src/server/index.ts +142 -0
- package/src/storage/drivers/fs.ts +90 -0
- package/src/storage/drivers/s3.ts +117 -0
- package/src/storage/index.ts +27 -0
- package/src/testing/fake.ts +298 -0
- package/src/testing/index.ts +324 -0
- package/src/ui/components/patterns/action-form-card.tsx +48 -0
- package/src/ui/components/patterns/action-list-dialog.tsx +93 -0
- package/src/ui/components/patterns/app-shell.tsx +227 -0
- package/src/ui/components/patterns/confirm.tsx +226 -0
- package/src/ui/components/patterns/data-state.tsx +75 -0
- package/src/ui/components/patterns/form-dialog.tsx +64 -0
- package/src/ui/components/patterns/form.tsx +584 -0
- package/src/ui/components/patterns/list.tsx +1488 -0
- package/src/ui/components/patterns/page.tsx +46 -0
- package/src/ui/components/patterns/section-shell.tsx +246 -0
- package/src/ui/components/patterns/shell-nav.tsx +150 -0
- package/src/ui/components/patterns/sidebar.tsx +89 -0
- package/src/ui/components/patterns/split.tsx +93 -0
- package/src/ui/components/patterns/trigger.tsx +196 -0
- package/src/ui/components/patterns/view.tsx +84 -0
- package/src/ui/components/primitives/accordion.tsx +64 -0
- package/src/ui/components/primitives/alert-dialog.tsx +190 -0
- package/src/ui/components/primitives/alert.tsx +116 -0
- package/src/ui/components/primitives/aspect-ratio.tsx +9 -0
- package/src/ui/components/primitives/avatar.tsx +107 -0
- package/src/ui/components/primitives/badge.tsx +37 -0
- package/src/ui/components/primitives/breadcrumb.tsx +109 -0
- package/src/ui/components/primitives/button-group.tsx +83 -0
- package/src/ui/components/primitives/button.tsx +102 -0
- package/src/ui/components/primitives/calendar.tsx +218 -0
- package/src/ui/components/primitives/card.tsx +56 -0
- package/src/ui/components/primitives/carousel.tsx +239 -0
- package/src/ui/components/primitives/chat.tsx +407 -0
- package/src/ui/components/primitives/checkbox.tsx +30 -0
- package/src/ui/components/primitives/collapsible.tsx +31 -0
- package/src/ui/components/primitives/command.tsx +182 -0
- package/src/ui/components/primitives/composer.tsx +121 -0
- package/src/ui/components/primitives/copyable.tsx +50 -0
- package/src/ui/components/primitives/dialog.tsx +147 -0
- package/src/ui/components/primitives/drawer.tsx +141 -0
- package/src/ui/components/primitives/empty.tsx +104 -0
- package/src/ui/components/primitives/field.tsx +246 -0
- package/src/ui/components/primitives/icon-picker.tsx +180 -0
- package/src/ui/components/primitives/input-group.tsx +168 -0
- package/src/ui/components/primitives/input-otp.tsx +75 -0
- package/src/ui/components/primitives/input.tsx +72 -0
- package/src/ui/components/primitives/item.tsx +193 -0
- package/src/ui/components/primitives/kbd.tsx +28 -0
- package/src/ui/components/primitives/label.tsx +22 -0
- package/src/ui/components/primitives/markdown.tsx +35 -0
- package/src/ui/components/primitives/menu.tsx +255 -0
- package/src/ui/components/primitives/pagination.tsx +127 -0
- package/src/ui/components/primitives/popover.tsx +87 -0
- package/src/ui/components/primitives/progress.tsx +29 -0
- package/src/ui/components/primitives/radio-group.tsx +43 -0
- package/src/ui/components/primitives/resizable.tsx +51 -0
- package/src/ui/components/primitives/scroll-area.tsx +56 -0
- package/src/ui/components/primitives/select.tsx +479 -0
- package/src/ui/components/primitives/separator.tsx +26 -0
- package/src/ui/components/primitives/skeleton.tsx +13 -0
- package/src/ui/components/primitives/slider.tsx +61 -0
- package/src/ui/components/primitives/sonner.tsx +46 -0
- package/src/ui/components/primitives/spinner.tsx +29 -0
- package/src/ui/components/primitives/switch.tsx +33 -0
- package/src/ui/components/primitives/table.tsx +114 -0
- package/src/ui/components/primitives/tabs.tsx +104 -0
- package/src/ui/components/primitives/textarea.tsx +18 -0
- package/src/ui/components/primitives/toggle-group.tsx +81 -0
- package/src/ui/components/primitives/toggle.tsx +45 -0
- package/src/ui/components/primitives/tooltip.tsx +55 -0
- package/src/ui/components/primitives/truncate.tsx +49 -0
- package/src/ui/docs/DocBrowser.tsx +90 -0
- package/src/ui/docs/changelog.tsx +80 -0
- package/src/ui/docs/content/accordion.md +86 -0
- package/src/ui/docs/content/action-form-card.md +24 -0
- package/src/ui/docs/content/action-form-dialog.md +30 -0
- package/src/ui/docs/content/action-form.md +125 -0
- package/src/ui/docs/content/action-list-dialog.md +68 -0
- package/src/ui/docs/content/action-list.md +194 -0
- package/src/ui/docs/content/action-trigger.md +72 -0
- package/src/ui/docs/content/action-view.md +47 -0
- package/src/ui/docs/content/actions.md +138 -0
- package/src/ui/docs/content/ai.md +112 -0
- package/src/ui/docs/content/alert-dialog.md +73 -0
- package/src/ui/docs/content/alert.md +69 -0
- package/src/ui/docs/content/app-shell.md +155 -0
- package/src/ui/docs/content/aspect-ratio.md +66 -0
- package/src/ui/docs/content/audit.md +84 -0
- package/src/ui/docs/content/auth.md +70 -0
- package/src/ui/docs/content/avatar.md +94 -0
- package/src/ui/docs/content/badge.md +48 -0
- package/src/ui/docs/content/breadcrumb.md +87 -0
- package/src/ui/docs/content/button-group.md +71 -0
- package/src/ui/docs/content/button.md +60 -0
- package/src/ui/docs/content/calendar.md +62 -0
- package/src/ui/docs/content/card.md +49 -0
- package/src/ui/docs/content/carousel.md +85 -0
- package/src/ui/docs/content/chat.md +69 -0
- package/src/ui/docs/content/checkbox.md +75 -0
- package/src/ui/docs/content/cli.md +58 -0
- package/src/ui/docs/content/collapsible.md +64 -0
- package/src/ui/docs/content/command.md +56 -0
- package/src/ui/docs/content/composer.md +50 -0
- package/src/ui/docs/content/confirm.md +120 -0
- package/src/ui/docs/content/copyable.md +30 -0
- package/src/ui/docs/content/customization.md +110 -0
- package/src/ui/docs/content/cycle.md +34 -0
- package/src/ui/docs/content/data-state.md +47 -0
- package/src/ui/docs/content/data.md +99 -0
- package/src/ui/docs/content/dialog.md +60 -0
- package/src/ui/docs/content/drawer.md +55 -0
- package/src/ui/docs/content/empty.md +66 -0
- package/src/ui/docs/content/events.md +61 -0
- package/src/ui/docs/content/field.md +58 -0
- package/src/ui/docs/content/getting-started.md +109 -0
- package/src/ui/docs/content/icon-picker.md +51 -0
- package/src/ui/docs/content/input-group.md +78 -0
- package/src/ui/docs/content/input-otp.md +72 -0
- package/src/ui/docs/content/input.md +78 -0
- package/src/ui/docs/content/item.md +84 -0
- package/src/ui/docs/content/kbd.md +62 -0
- package/src/ui/docs/content/label.md +32 -0
- package/src/ui/docs/content/log.md +55 -0
- package/src/ui/docs/content/markdown.md +41 -0
- package/src/ui/docs/content/mcp.md +44 -0
- package/src/ui/docs/content/menu.md +114 -0
- package/src/ui/docs/content/microcopy.md +83 -0
- package/src/ui/docs/content/page.md +34 -0
- package/src/ui/docs/content/pagination.md +99 -0
- package/src/ui/docs/content/popover.md +49 -0
- package/src/ui/docs/content/progress.md +69 -0
- package/src/ui/docs/content/queue.md +62 -0
- package/src/ui/docs/content/radio-group.md +77 -0
- package/src/ui/docs/content/resizable.md +86 -0
- package/src/ui/docs/content/router.md +56 -0
- package/src/ui/docs/content/runtime.md +77 -0
- package/src/ui/docs/content/scheduler.md +66 -0
- package/src/ui/docs/content/scroll-area.md +89 -0
- package/src/ui/docs/content/section-shell.md +121 -0
- package/src/ui/docs/content/select.md +342 -0
- package/src/ui/docs/content/separator.md +33 -0
- package/src/ui/docs/content/sidebar.md +38 -0
- package/src/ui/docs/content/skeleton.md +34 -0
- package/src/ui/docs/content/slider.md +64 -0
- package/src/ui/docs/content/spinner.md +37 -0
- package/src/ui/docs/content/split.md +33 -0
- package/src/ui/docs/content/storage.md +69 -0
- package/src/ui/docs/content/switch.md +69 -0
- package/src/ui/docs/content/table.md +102 -0
- package/src/ui/docs/content/tabs.md +94 -0
- package/src/ui/docs/content/testing.md +89 -0
- package/src/ui/docs/content/textarea.md +30 -0
- package/src/ui/docs/content/toast.md +67 -0
- package/src/ui/docs/content/toggle-group.md +81 -0
- package/src/ui/docs/content/toggle.md +72 -0
- package/src/ui/docs/content/tokens.md +171 -0
- package/src/ui/docs/content/tooltip.md +50 -0
- package/src/ui/docs/content/truncate.md +37 -0
- package/src/ui/docs/content/ui.md +40 -0
- package/src/ui/docs/content/upgrading.md +48 -0
- package/src/ui/docs/doc-client.tsx +214 -0
- package/src/ui/docs/doc.tsx +301 -0
- package/src/ui/docs/folder.tsx +149 -0
- package/src/ui/docs/index.ts +21 -0
- package/src/ui/docs/markdown.tsx +130 -0
- package/src/ui/docs/md-raw.d.ts +4 -0
- package/src/ui/docs/plugin.ts +104 -0
- package/src/ui/docs/registry.tsx +424 -0
- package/src/ui/docs/standalone.tsx +107 -0
- package/src/ui/drivers/react.tsx +627 -0
- package/src/ui/index.ts +92 -0
- package/src/ui/lib/cn.ts +10 -0
- package/src/ui/lib/zod-pt-br.ts +38 -0
- package/src/ui/meta.ts +412 -0
- package/src/ui/react.tsx +235 -0
- package/src/ui/router.ts +96 -0
- package/src/ui/theme.css +234 -0
- package/src/vite/design.ts +652 -0
- package/src/vite/index.ts +8 -0
package/src/ui/react.tsx
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @softize/opus/ui/react — a superfície React da UI: Provider + hooks (driver de action)
|
|
3
|
+
* + componentes + cn. O consumidor importa tudo daqui.
|
|
4
|
+
*
|
|
5
|
+
* `meta` de cada componente NÃO é re-exportado aqui de propósito — é metadado de
|
|
6
|
+
* build-time (lido pelo manifesto/MCP da fonte), fora do bundle de runtime.
|
|
7
|
+
*/
|
|
8
|
+
export * from './drivers/react.tsx'
|
|
9
|
+
|
|
10
|
+
// Utilitário
|
|
11
|
+
export { cn } from './lib/cn.ts'
|
|
12
|
+
|
|
13
|
+
// Primitivos
|
|
14
|
+
export { Button, buttonVariants } from './components/primitives/button.tsx'
|
|
15
|
+
export type { ButtonProps } from './components/primitives/button.tsx'
|
|
16
|
+
|
|
17
|
+
export { Input } from './components/primitives/input.tsx'
|
|
18
|
+
|
|
19
|
+
export { Chat } from './components/primitives/chat.tsx'
|
|
20
|
+
export type { ChatProps, ChatMessage, ChatArtifact, ChatTranscriptItem } from './components/primitives/chat.tsx'
|
|
21
|
+
export { Composer } from './components/primitives/composer.tsx'
|
|
22
|
+
export type { ComposerProps } from './components/primitives/composer.tsx'
|
|
23
|
+
export { Copyable } from './components/primitives/copyable.tsx'
|
|
24
|
+
export type { CopyableProps } from './components/primitives/copyable.tsx'
|
|
25
|
+
export { IconPicker, iconPickerIcons } from './components/primitives/icon-picker.tsx'
|
|
26
|
+
export type { IconPickerProps } from './components/primitives/icon-picker.tsx'
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
Command,
|
|
30
|
+
CommandDialog,
|
|
31
|
+
CommandInput,
|
|
32
|
+
CommandList,
|
|
33
|
+
CommandEmpty,
|
|
34
|
+
CommandGroup,
|
|
35
|
+
CommandItem,
|
|
36
|
+
CommandSeparator,
|
|
37
|
+
CommandShortcut,
|
|
38
|
+
} from './components/primitives/command.tsx'
|
|
39
|
+
|
|
40
|
+
export { Textarea } from './components/primitives/textarea.tsx'
|
|
41
|
+
|
|
42
|
+
export { Label } from './components/primitives/label.tsx'
|
|
43
|
+
|
|
44
|
+
export { Badge, badgeVariants } from './components/primitives/badge.tsx'
|
|
45
|
+
export type { BadgeProps } from './components/primitives/badge.tsx'
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
Card,
|
|
49
|
+
CardHeader,
|
|
50
|
+
CardTitle,
|
|
51
|
+
CardDescription,
|
|
52
|
+
CardAction,
|
|
53
|
+
CardContent,
|
|
54
|
+
CardFooter,
|
|
55
|
+
} from './components/primitives/card.tsx'
|
|
56
|
+
|
|
57
|
+
export { Alert, AlertTitle, AlertDescription, alertVariants } from './components/primitives/alert.tsx'
|
|
58
|
+
export type { AlertProps } from './components/primitives/alert.tsx'
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
Dialog,
|
|
62
|
+
DialogTrigger,
|
|
63
|
+
DialogPortal,
|
|
64
|
+
DialogClose,
|
|
65
|
+
DialogOverlay,
|
|
66
|
+
DialogContent,
|
|
67
|
+
DialogHeader,
|
|
68
|
+
DialogBody,
|
|
69
|
+
DialogFooter,
|
|
70
|
+
DialogTitle,
|
|
71
|
+
DialogDescription,
|
|
72
|
+
} from './components/primitives/dialog.tsx'
|
|
73
|
+
|
|
74
|
+
export {
|
|
75
|
+
Menu,
|
|
76
|
+
MenuTrigger,
|
|
77
|
+
MenuGroup,
|
|
78
|
+
MenuPortal,
|
|
79
|
+
MenuSub,
|
|
80
|
+
MenuRadioGroup,
|
|
81
|
+
MenuSubTrigger,
|
|
82
|
+
MenuSubContent,
|
|
83
|
+
MenuContent,
|
|
84
|
+
MenuItem,
|
|
85
|
+
MenuCheckboxItem,
|
|
86
|
+
MenuRadioItem,
|
|
87
|
+
MenuLabel,
|
|
88
|
+
MenuSeparator,
|
|
89
|
+
MenuShortcut,
|
|
90
|
+
} from './components/primitives/menu.tsx'
|
|
91
|
+
|
|
92
|
+
export {
|
|
93
|
+
Popover,
|
|
94
|
+
PopoverTrigger,
|
|
95
|
+
PopoverAnchor,
|
|
96
|
+
PopoverContent,
|
|
97
|
+
PopoverHeader,
|
|
98
|
+
PopoverTitle,
|
|
99
|
+
PopoverDescription,
|
|
100
|
+
} from './components/primitives/popover.tsx'
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
TooltipProvider,
|
|
104
|
+
Tooltip,
|
|
105
|
+
TooltipTrigger,
|
|
106
|
+
TooltipContent,
|
|
107
|
+
} from './components/primitives/tooltip.tsx'
|
|
108
|
+
|
|
109
|
+
export { Checkbox } from './components/primitives/checkbox.tsx'
|
|
110
|
+
|
|
111
|
+
export { Separator } from './components/primitives/separator.tsx'
|
|
112
|
+
|
|
113
|
+
export {
|
|
114
|
+
Tabs,
|
|
115
|
+
TabsList,
|
|
116
|
+
TabsTrigger,
|
|
117
|
+
TabsContent,
|
|
118
|
+
} from './components/primitives/tabs.tsx'
|
|
119
|
+
|
|
120
|
+
export { Skeleton } from './components/primitives/skeleton.tsx'
|
|
121
|
+
|
|
122
|
+
export { Spinner } from './components/primitives/spinner.tsx'
|
|
123
|
+
export type { SpinnerProps } from './components/primitives/spinner.tsx'
|
|
124
|
+
|
|
125
|
+
export {
|
|
126
|
+
Table,
|
|
127
|
+
TableHeader,
|
|
128
|
+
TableBody,
|
|
129
|
+
TableFooter,
|
|
130
|
+
TableRow,
|
|
131
|
+
TableHead,
|
|
132
|
+
TableCell,
|
|
133
|
+
TableCaption,
|
|
134
|
+
} from './components/primitives/table.tsx'
|
|
135
|
+
|
|
136
|
+
// UM seletor: `native` (menu do SO), `searchable` (busca), `multiple` (chips) e
|
|
137
|
+
// `variant="ghost"` (barra de composer) são PROPS, não componentes. Ver select.tsx.
|
|
138
|
+
export { Select } from './components/primitives/select.tsx'
|
|
139
|
+
export type { SelectProps, SelectOption } from './components/primitives/select.tsx'
|
|
140
|
+
|
|
141
|
+
export { Toaster, toast } from './components/primitives/sonner.tsx'
|
|
142
|
+
export { Markdown } from './components/primitives/markdown.tsx'
|
|
143
|
+
|
|
144
|
+
// shadcn (lote inicial — byte-fiéis via registry JSON, locked no registry.lock.json)
|
|
145
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './components/primitives/accordion.tsx'
|
|
146
|
+
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger } from './components/primitives/alert-dialog.tsx'
|
|
147
|
+
export { AspectRatio } from './components/primitives/aspect-ratio.tsx'
|
|
148
|
+
export { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage } from './components/primitives/avatar.tsx'
|
|
149
|
+
export { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from './components/primitives/breadcrumb.tsx'
|
|
150
|
+
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants } from './components/primitives/button-group.tsx'
|
|
151
|
+
export { Calendar, CalendarDayButton } from './components/primitives/calendar.tsx'
|
|
152
|
+
export { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from './components/primitives/carousel.tsx'
|
|
153
|
+
export { Collapsible, CollapsibleContent, CollapsibleTrigger } from './components/primitives/collapsible.tsx'
|
|
154
|
+
export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger } from './components/primitives/drawer.tsx'
|
|
155
|
+
export { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from './components/primitives/empty.tsx'
|
|
156
|
+
export { Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle } from './components/primitives/field.tsx'
|
|
157
|
+
export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea } from './components/primitives/input-group.tsx'
|
|
158
|
+
export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from './components/primitives/input-otp.tsx'
|
|
159
|
+
export { Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle } from './components/primitives/item.tsx'
|
|
160
|
+
export { Kbd, KbdGroup } from './components/primitives/kbd.tsx'
|
|
161
|
+
export { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from './components/primitives/pagination.tsx'
|
|
162
|
+
export { Progress } from './components/primitives/progress.tsx'
|
|
163
|
+
export { RadioGroup, RadioGroupItem } from './components/primitives/radio-group.tsx'
|
|
164
|
+
export { ResizableHandle, ResizablePanel, ResizablePanelGroup } from './components/primitives/resizable.tsx'
|
|
165
|
+
export { ScrollArea, ScrollBar } from './components/primitives/scroll-area.tsx'
|
|
166
|
+
export { Slider } from './components/primitives/slider.tsx'
|
|
167
|
+
export { Switch } from './components/primitives/switch.tsx'
|
|
168
|
+
export { Toggle, toggleVariants } from './components/primitives/toggle.tsx'
|
|
169
|
+
export { ToggleGroup, ToggleGroupItem } from './components/primitives/toggle-group.tsx'
|
|
170
|
+
export { Truncate } from './components/primitives/truncate.tsx'
|
|
171
|
+
export type { TruncateProps } from './components/primitives/truncate.tsx'
|
|
172
|
+
|
|
173
|
+
// Patterns (renderizam actions a partir do spec)
|
|
174
|
+
export { ActionForm, ActionFormField, useActionFormContext } from './components/patterns/form.tsx'
|
|
175
|
+
export type { ActionFormProps, ActionFormFieldProps, ActionFormContextValue } from './components/patterns/form.tsx'
|
|
176
|
+
|
|
177
|
+
export { ActionFormDialog } from './components/patterns/form-dialog.tsx'
|
|
178
|
+
export type { ActionFormDialogProps } from './components/patterns/form-dialog.tsx'
|
|
179
|
+
|
|
180
|
+
export { ActionFormCard } from './components/patterns/action-form-card.tsx'
|
|
181
|
+
export type { ActionFormCardProps } from './components/patterns/action-form-card.tsx'
|
|
182
|
+
|
|
183
|
+
export { ActionList, emptyListState, presetRange, listParamsToState, listStateToParams } from './components/patterns/list.tsx'
|
|
184
|
+
export type { ActionListProps, ActionListColumn, ActionListState, ActionListView, ActionListBatchAction, ListActionLike } from './components/patterns/list.tsx'
|
|
185
|
+
|
|
186
|
+
export { ActionView } from './components/patterns/view.tsx'
|
|
187
|
+
export type { ActionViewProps } from './components/patterns/view.tsx'
|
|
188
|
+
|
|
189
|
+
export { ActionTrigger } from './components/patterns/trigger.tsx'
|
|
190
|
+
export { dialog, DialogHost, confirm, ConfirmHost } from './components/patterns/confirm.tsx'
|
|
191
|
+
export type { AlertOptions, ConfirmOptions, PromptOptions } from './components/patterns/confirm.tsx'
|
|
192
|
+
export type { ActionTriggerProps } from './components/patterns/trigger.tsx'
|
|
193
|
+
|
|
194
|
+
// Listagem em modal: ListAction query-backed + chrome (toolbar/estados derivados).
|
|
195
|
+
export { ActionListDialog } from './components/patterns/action-list-dialog.tsx'
|
|
196
|
+
export type { ActionListDialogProps } from './components/patterns/action-list-dialog.tsx'
|
|
197
|
+
|
|
198
|
+
// Estado de carga (carregando/vazio/erro → conteúdo) — o "antes" do conteúdo.
|
|
199
|
+
export { DataState } from './components/patterns/data-state.tsx'
|
|
200
|
+
export type { DataStateProps } from './components/patterns/data-state.tsx'
|
|
201
|
+
|
|
202
|
+
// Esqueleto de página do back-office (main + container + header título/descrição/ação).
|
|
203
|
+
export { Page } from './components/patterns/page.tsx'
|
|
204
|
+
export type { PageProps } from './components/patterns/page.tsx'
|
|
205
|
+
|
|
206
|
+
// Chrome da aplicação (sidebar + conteúdo + rail opcional redimensionável).
|
|
207
|
+
export { AppShell, AppShellBar, AppShellTrigger, useAppShell, useSidebarSlot } from './components/patterns/app-shell.tsx'
|
|
208
|
+
export type { AppShellProps } from './components/patterns/app-shell.tsx'
|
|
209
|
+
|
|
210
|
+
// Layout composicional: Split decide a relação espacial; Pane carrega conteúdo com inset.
|
|
211
|
+
export { Split, Pane } from './components/patterns/split.tsx'
|
|
212
|
+
export type { SplitProps, PaneProps } from './components/patterns/split.tsx'
|
|
213
|
+
|
|
214
|
+
// Barra lateral composicional: header/conteúdo/footer e navegação, sem possuir o layout.
|
|
215
|
+
export { PaneHeader, PaneContent, PaneFooter, Sidebar, SidebarHeader, SidebarContent, SidebarFooter, SidebarItem, SidebarNav } from './components/patterns/sidebar.tsx'
|
|
216
|
+
export type { SidebarProps, SidebarItemProps, SidebarNavGroup } from './components/patterns/sidebar.tsx'
|
|
217
|
+
|
|
218
|
+
// Seção com navegação própria (nav w-56 + painel) — o nível entre o AppShell e a Page.
|
|
219
|
+
export { SectionShell } from './components/patterns/section-shell.tsx'
|
|
220
|
+
export type {
|
|
221
|
+
SectionShellProps,
|
|
222
|
+
SectionNavGroup,
|
|
223
|
+
SectionNavSubgroup,
|
|
224
|
+
SectionNavItem,
|
|
225
|
+
} from './components/patterns/section-shell.tsx'
|
|
226
|
+
|
|
227
|
+
// O menu como primitivo PIVOTÁVEL: mesmo nav na sidebar do AppShell ou dentro do conteúdo
|
|
228
|
+
// (colapso por CSS via o grupo `sidebar`). Ver docs/shellnav.md.
|
|
229
|
+
export { ShellNav, ShellNavHeading } from './components/patterns/shell-nav.tsx'
|
|
230
|
+
export type { ShellNavProps, ShellNavGroup, ShellNavItem, ShellNavHeadingProps } from './components/patterns/shell-nav.tsx'
|
|
231
|
+
|
|
232
|
+
// Roteamento history-based (o pathname É o estado). Escopo pequeno de propósito: leitura
|
|
233
|
+
// reativa da URL + navigate — sem tabela de rotas. Ver src/ui/router.ts.
|
|
234
|
+
export { navigate, usePathname, useSegments, useSearchParams } from './router.ts'
|
|
235
|
+
export type { NavigateOptions } from './router.ts'
|
package/src/ui/router.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Roteamento history-based — o pathname É o estado.
|
|
3
|
+
*
|
|
4
|
+
* Nasceu por REINCIDÊNCIA: o mesmo mecanismo estava reimplementado à mão em quatro
|
|
5
|
+
* lugares, três deles dentro da casa (o `DocBrowser` daqui, o site do Opus e o
|
|
6
|
+
* back-office da Empresa X). As cópias divergiam no que importa — só uma usava
|
|
7
|
+
* `useSyncExternalStore` (as outras leem `window.location` em `useState`, que sofre
|
|
8
|
+
* tearing no modo concurrent), e cada uma notificava de um jeito.
|
|
9
|
+
*
|
|
10
|
+
* Escopo deliberadamente PEQUENO: não há tabela de rotas, `<Route>`, params tipados nem
|
|
11
|
+
* carregamento de dados. Isto é a leitura reativa da URL + um `navigate` — quem decide o
|
|
12
|
+
* que renderizar é o app, com `if`/`switch` sobre os segmentos. Se um dia o caso pedir
|
|
13
|
+
* casamento de padrão e params, aí é outra conversa (e provavelmente outra biblioteca).
|
|
14
|
+
*
|
|
15
|
+
* import { navigate, useSegments } from '@softize/opus/ui/react'
|
|
16
|
+
*
|
|
17
|
+
* const segments = useSegments() // '/settings/users' → ['settings','users']
|
|
18
|
+
* navigate('/settings/users') // pushState + notifica
|
|
19
|
+
* navigate('/x', { replace: true }) // troca a entrada corrente
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { useMemo, useSyncExternalStore } from 'react'
|
|
23
|
+
|
|
24
|
+
/** `popstate` é o ÚNICO canal de notificação, e de propósito: cobre voltar/avançar do
|
|
25
|
+
* browser, o `navigate` daqui e quem ainda notifica na unha por evento sintético. Um
|
|
26
|
+
* `Set` de assinantes em escopo de módulo pareceria mais direto e seria pior — ele mora
|
|
27
|
+
* numa instância do bundle, então código não-migrado (que escuta o evento) e uma segunda
|
|
28
|
+
* cópia do pacote no `node_modules` ficariam de fora. O `window` é um só. */
|
|
29
|
+
function subscribe(callback: () => void): () => void {
|
|
30
|
+
window.addEventListener('popstate', callback)
|
|
31
|
+
return () => window.removeEventListener('popstate', callback)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** SSR / build estático: sem `window` não há URL a ler. O snapshot de servidor é
|
|
35
|
+
* constante de propósito — o primeiro render no cliente reconcilia com a URL real. */
|
|
36
|
+
const SERVER_PATHNAME = '/'
|
|
37
|
+
const SERVER_SEARCH = ''
|
|
38
|
+
|
|
39
|
+
export interface NavigateOptions {
|
|
40
|
+
/** Troca a entrada corrente (`replaceState`) em vez de empilhar. Para estado que não é
|
|
41
|
+
* história — um rascunho que ganha id no meio do fluxo, um filtro que não merece uma
|
|
42
|
+
* volta do botão "voltar". */
|
|
43
|
+
replace?: boolean
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Navega e notifica. No-op se já estiver exatamente no destino — sem isso, clicar duas
|
|
48
|
+
* vezes no mesmo item empilha entradas idênticas e o "voltar" não sai do lugar.
|
|
49
|
+
*
|
|
50
|
+
* "Exatamente" cobra normalizar: comparar o argumento CRU contra `window.location` erra
|
|
51
|
+
* em duas frentes. O hash — estando em `/a#secao`, `navigate('/a')` pareceria repetido e a
|
|
52
|
+
* âncora nunca sairia. E o encoding — `/relatórios` sai do `location` percent-encodado, e
|
|
53
|
+
* a comparação crua nunca casaria, empilhando uma entrada por clique justamente no caso
|
|
54
|
+
* pt-BR. Resolver os dois lados com `new URL` e comparar `href` resolve as duas.
|
|
55
|
+
*
|
|
56
|
+
* O `path` é da PRÓPRIA origem (ex.: `/settings/users?q=ana`). Passar URL absoluta aqui é
|
|
57
|
+
* erro de uso — validar destino externo é problema de quem recebe input de terceiro
|
|
58
|
+
* (redirect pós-login, por exemplo), não desta função. Comparar `href` (e não só o
|
|
59
|
+
* caminho) preserva isso: destino de outra origem não vira no-op, segue para o
|
|
60
|
+
* `pushState` e estoura lá, que é onde o erro é legível.
|
|
61
|
+
*/
|
|
62
|
+
export function navigate(path: string, options?: NavigateOptions): void {
|
|
63
|
+
if (new URL(path, window.location.origin).href === window.location.href) return
|
|
64
|
+
if (options?.replace === true) window.history.replaceState(null, '', path)
|
|
65
|
+
else window.history.pushState(null, '', path)
|
|
66
|
+
// `pushState` não dispara `popstate` — quem muda a URL por código tem que avisar. Um
|
|
67
|
+
// evento (e não uma lista privada) é o que faz host não-migrado continuar acompanhando.
|
|
68
|
+
window.dispatchEvent(new PopStateEvent('popstate'))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** O pathname como estado reativo. */
|
|
72
|
+
export function usePathname(): string {
|
|
73
|
+
return useSyncExternalStore(
|
|
74
|
+
subscribe,
|
|
75
|
+
() => window.location.pathname,
|
|
76
|
+
() => SERVER_PATHNAME,
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Os segmentos do path: `/settings/users` → `['settings', 'users']`. Vazios caem fora,
|
|
81
|
+
* então `/` e `//` dão `[]`. */
|
|
82
|
+
export function useSegments(): string[] {
|
|
83
|
+
const pathname = usePathname()
|
|
84
|
+
return useMemo(() => pathname.split('/').filter(Boolean), [pathname])
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** A querystring como estado reativo — o lar natural do estado interno de uma seção
|
|
88
|
+
* (qual relatório está aberto, o recorte de uma lista). */
|
|
89
|
+
export function useSearchParams(): URLSearchParams {
|
|
90
|
+
const search = useSyncExternalStore(
|
|
91
|
+
subscribe,
|
|
92
|
+
() => window.location.search,
|
|
93
|
+
() => SERVER_SEARCH,
|
|
94
|
+
)
|
|
95
|
+
return useMemo(() => new URLSearchParams(search), [search])
|
|
96
|
+
}
|
package/src/ui/theme.css
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tema canônico do Opus (Tailwind v4, CSS-first). É o ENTRY de CSS da UI:
|
|
3
|
+
* importa o Tailwind + o tw-animate + define os tokens (cor inteira na var) e mapeia
|
|
4
|
+
* pro Tailwind via `@theme inline`. O app faz `@import '@softize/opus/ui/theme.css'`
|
|
5
|
+
* + um `@source` pros componentes do Opus (monorepo), e sobrescreve vars pra identidade.
|
|
6
|
+
*
|
|
7
|
+
* ── DIVERGÊNCIAS DECLARADAS vs shadcn upstream (regra: o que não está aqui é DRIFT
|
|
8
|
+
* e deve ser sincronizado; ver skill `shadcn-ui`) ─────────────────────────────────
|
|
9
|
+
* 1. Formato HSL nos tokens (upstream migrou pra oklch) — legibilidade/ferramentas
|
|
10
|
+
* nossas; os VALORES acompanham o upstream, só o formato difere.
|
|
11
|
+
* 2. Elevação dark: --card/--popover ACIMA de --background (10% vs 3.9%) — identidade
|
|
12
|
+
* da casa (upstream v4 também elevou; calibramos pelo site deles em 2026-06).
|
|
13
|
+
* 3. Radius mapeado (sm/md/lg/xl em @theme inline) preservando o sentido pré-v4 dos
|
|
14
|
+
* utilitários `rounded-*` — neutraliza o rename do v4.
|
|
15
|
+
* (A antiga nº 4 — escala shadow-* sobrescrita — foi APOSENTADA: a elevação da casa
|
|
16
|
+
* vive em namespace próprio, shadow-card/popover/dialog + ring-edge, sem tocar os
|
|
17
|
+
* defaults do Tailwind.)
|
|
18
|
+
* 5. Bordas mais leves no light: --border/--input em 92.5% (upstream 89.8%) — par do
|
|
19
|
+
* canvas quase-branco; a aresta de superfície elevada já é o ring-edge.
|
|
20
|
+
* Tudo o mais (escala neutra, radius base 0.625rem, semânticas) segue o upstream.
|
|
21
|
+
*/
|
|
22
|
+
@import 'tailwindcss';
|
|
23
|
+
@import 'tw-animate-css';
|
|
24
|
+
@plugin '@tailwindcss/typography';
|
|
25
|
+
|
|
26
|
+
/* dark por classe (v4 é CSS-first) */
|
|
27
|
+
@custom-variant dark (&:is(.dark *));
|
|
28
|
+
|
|
29
|
+
:root {
|
|
30
|
+
/* Elevação POR PAPEL (par do bg-card/bg-popover): família Notion — camada curta +
|
|
31
|
+
longa, tinte 25/25/25 — e a ARESTA (--edge-value): o anel hairline que SUBSTITUI a
|
|
32
|
+
borda em superfície elevada (ring-1 ring-edge). Papel novo = token novo; os
|
|
33
|
+
defaults shadow-* do Tailwind ficam INTACTOS (sem pegadinha). */
|
|
34
|
+
--edge-value: rgba(42, 28, 0, 0.07);
|
|
35
|
+
--elevation-card: 0 1px 2px rgba(25, 25, 25, 0.027), 0 3px 6px rgba(25, 25, 25, 0.05);
|
|
36
|
+
--elevation-popover: 0 5px 8px rgba(25, 25, 25, 0.027), 0 20px 24px rgba(25, 25, 25, 0.05);
|
|
37
|
+
--elevation-dialog: 0 4px 8px rgba(25, 25, 25, 0.03), 0 16px 24px rgba(25, 25, 25, 0.06);
|
|
38
|
+
|
|
39
|
+
/* Scrollbars e controles NATIVOS (date picker, autofill…) seguem o tema — sem
|
|
40
|
+
isto o browser assume light e pinta scrollbar branca no dark. */
|
|
41
|
+
color-scheme: light;
|
|
42
|
+
--background: hsl(0 0% 100%);
|
|
43
|
+
--foreground: hsl(0 0% 3.9%);
|
|
44
|
+
--card: hsl(0 0% 100%);
|
|
45
|
+
--card-foreground: hsl(0 0% 3.9%);
|
|
46
|
+
--popover: hsl(0 0% 100%);
|
|
47
|
+
--popover-foreground: hsl(0 0% 3.9%);
|
|
48
|
+
--primary: hsl(0 0% 9%);
|
|
49
|
+
--primary-foreground: hsl(0 0% 98%);
|
|
50
|
+
--secondary: hsl(0 0% 96.1%);
|
|
51
|
+
--secondary-foreground: hsl(0 0% 9%);
|
|
52
|
+
--muted: hsl(0 0% 96.1%);
|
|
53
|
+
--muted-foreground: hsl(0 0% 45.1%);
|
|
54
|
+
--accent: hsl(0 0% 96.1%);
|
|
55
|
+
--accent-foreground: hsl(0 0% 9%);
|
|
56
|
+
--destructive: hsl(0 84.2% 60.2%);
|
|
57
|
+
--destructive-foreground: hsl(0 0% 98%);
|
|
58
|
+
--border: hsl(0 0% 92.5%);
|
|
59
|
+
--input: hsl(0 0% 92.5%);
|
|
60
|
+
/* Ring de foco LEVE (pedido da casa): aro sutil, não um halo. Com ring-[3px] + /50,
|
|
61
|
+
~86% encosta na borda (89.8%) — um sussurro de foco. */
|
|
62
|
+
--ring: hsl(0 0% 86%);
|
|
63
|
+
--radius: 0.625rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.dark {
|
|
67
|
+
--edge-value: rgba(255, 255, 255, 0.06);
|
|
68
|
+
--elevation-card: 0 1px 2px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.28);
|
|
69
|
+
--elevation-popover: 0 5px 8px rgba(0, 0, 0, 0.16), 0 20px 24px rgba(0, 0, 0, 0.3);
|
|
70
|
+
--elevation-dialog: 0 4px 8px rgba(0, 0, 0, 0.2), 0 16px 24px rgba(0, 0, 0, 0.35);
|
|
71
|
+
color-scheme: dark;
|
|
72
|
+
--background: hsl(0 0% 3.9%);
|
|
73
|
+
--foreground: hsl(0 0% 98%);
|
|
74
|
+
/* Elevação com contraste de verdade (dialog/card "sobem" da página, como no site
|
|
75
|
+
do shadcn): superfície ~10% sobre fundo 3.9%, borda um ponto acima pra definir. */
|
|
76
|
+
--card: hsl(0 0% 10%);
|
|
77
|
+
--card-foreground: hsl(0 0% 98%);
|
|
78
|
+
--popover: hsl(0 0% 10%);
|
|
79
|
+
--popover-foreground: hsl(0 0% 98%);
|
|
80
|
+
--primary: hsl(0 0% 98%);
|
|
81
|
+
--primary-foreground: hsl(0 0% 9%);
|
|
82
|
+
--secondary: hsl(0 0% 14.9%);
|
|
83
|
+
--secondary-foreground: hsl(0 0% 98%);
|
|
84
|
+
--muted: hsl(0 0% 14.9%);
|
|
85
|
+
--muted-foreground: hsl(0 0% 63.9%);
|
|
86
|
+
--accent: hsl(0 0% 14.9%);
|
|
87
|
+
--accent-foreground: hsl(0 0% 98%);
|
|
88
|
+
/* Vermelho CLARO no escuro (era 30.6% — calibrado só pra FUNDO, com texto branco).
|
|
89
|
+
Como o menu/alert/field/erros usam `text-destructive` como FOREGROUND, o valor
|
|
90
|
+
escuro dava ~1,7:1 sobre o popover — ilegível. ~58% passa o AA como texto e é o
|
|
91
|
+
que o success já fazia (dark:text-emerald-400 pula pro tom claro). Fundo sólido
|
|
92
|
+
(Button/Badge/toast destructive) fica mais vivo — igual ao light, com branco por
|
|
93
|
+
cima, como o shadcn novo. */
|
|
94
|
+
--destructive: hsl(0 72% 58%);
|
|
95
|
+
--destructive-foreground: hsl(0 0% 98%);
|
|
96
|
+
--border: hsl(0 0% 16.5%);
|
|
97
|
+
--input: hsl(0 0% 16.5%);
|
|
98
|
+
/* No escuro o 83.1% virava um halo quase branco; ~36% marca o foco sem brilhar. */
|
|
99
|
+
--ring: hsl(0 0% 36%);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Syntax highlighting (CodeBlock via prism-react-renderer): paleta calma mapeada por CSS
|
|
103
|
+
var — o prism theme referencia estes vars, então light/dark troca sozinho pelo cascade. */
|
|
104
|
+
:root {
|
|
105
|
+
--code-fg: hsl(0 0% 25%);
|
|
106
|
+
--code-comment: hsl(0 0% 55%);
|
|
107
|
+
--code-keyword: hsl(265 50% 47%);
|
|
108
|
+
--code-string: hsl(140 45% 32%);
|
|
109
|
+
--code-function: hsl(210 65% 45%);
|
|
110
|
+
--code-number: hsl(25 75% 45%);
|
|
111
|
+
--code-class: hsl(190 50% 35%);
|
|
112
|
+
--code-property: hsl(210 55% 42%);
|
|
113
|
+
--code-punctuation: hsl(0 0% 45%);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.dark {
|
|
117
|
+
--code-fg: hsl(0 0% 85%);
|
|
118
|
+
--code-comment: hsl(0 0% 50%);
|
|
119
|
+
--code-keyword: hsl(265 70% 78%);
|
|
120
|
+
--code-string: hsl(140 45% 68%);
|
|
121
|
+
--code-function: hsl(210 70% 72%);
|
|
122
|
+
--code-number: hsl(30 80% 70%);
|
|
123
|
+
--code-class: hsl(180 50% 68%);
|
|
124
|
+
--code-property: hsl(195 60% 72%);
|
|
125
|
+
--code-punctuation: hsl(0 0% 60%);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@theme inline {
|
|
129
|
+
--color-background: var(--background);
|
|
130
|
+
--color-foreground: var(--foreground);
|
|
131
|
+
--color-card: var(--card);
|
|
132
|
+
--color-card-foreground: var(--card-foreground);
|
|
133
|
+
--color-popover: var(--popover);
|
|
134
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
135
|
+
--color-primary: var(--primary);
|
|
136
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
137
|
+
--color-secondary: var(--secondary);
|
|
138
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
139
|
+
--color-muted: var(--muted);
|
|
140
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
141
|
+
--color-accent: var(--accent);
|
|
142
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
143
|
+
--color-destructive: var(--destructive);
|
|
144
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
145
|
+
--color-border: var(--border);
|
|
146
|
+
--color-input: var(--input);
|
|
147
|
+
--color-ring: var(--ring);
|
|
148
|
+
|
|
149
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
150
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
151
|
+
--radius-lg: var(--radius);
|
|
152
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
153
|
+
|
|
154
|
+
/* Forma por papel (rounded-card/popover/dialog) — o papel de superfície carrega cor
|
|
155
|
+
(bg-*), elevação (shadow-*) E forma. Derivados de --radius: a identidade por app
|
|
156
|
+
(sobrescrever --radius) escala os papéis junto. Controles ficam na escala sm–xl. */
|
|
157
|
+
--radius-card: calc(var(--radius) + 6px);
|
|
158
|
+
--radius-popover: calc(var(--radius) - 2px);
|
|
159
|
+
--radius-dialog: calc(var(--radius) + 6px);
|
|
160
|
+
|
|
161
|
+
/* Elevação por papel (utilitários shadow-card/popover/dialog + ring-edge/border-edge)
|
|
162
|
+
— namespace PRÓPRIO: os shadow-* default do Tailwind seguem intactos. Superfície
|
|
163
|
+
elevada usa `ring-1 ring-edge` NO LUGAR de border (não combine os dois). */
|
|
164
|
+
--shadow-card: var(--elevation-card);
|
|
165
|
+
--shadow-popover: var(--elevation-popover);
|
|
166
|
+
--shadow-dialog: var(--elevation-dialog);
|
|
167
|
+
--color-edge: var(--edge-value);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* Base canônica do consumidor — vem DAQUI, não do entry de cada app. Tailwind v4
|
|
171
|
+
* deixou a borda default em currentColor (preta): o reset aponta pro token (é o
|
|
172
|
+
* globals.css do shadcn). App que ainda tiver a cópia local: redundante, inofensivo. */
|
|
173
|
+
@layer base {
|
|
174
|
+
* {
|
|
175
|
+
border-color: var(--border);
|
|
176
|
+
}
|
|
177
|
+
/* Base 15px: o rem da casa — TODA a escala rem (texto, spacing, radius) deriva daqui,
|
|
178
|
+
então a UI densifica ~6% vs o default do browser (16px). Histórico (conferido no git):
|
|
179
|
+
até a 2.31.4 o pacote NÃO fixava rem (valia o 16px do browser); a 2.31.5 introduziu
|
|
180
|
+
14px; a 2.35.0 assenta em 15px — valor INÉDITO, não é revert. O 15px veio da prática:
|
|
181
|
+
a Empresa X escolheu 15px por conta própria em DOIS apps, e a exceção reincidente
|
|
182
|
+
virou default. Quem quiser mais denso sobrescreve o `html` no próprio entry. */
|
|
183
|
+
html {
|
|
184
|
+
font-size: 15px;
|
|
185
|
+
}
|
|
186
|
+
/* Canvas da casa: quase-branco vem do BODY — o shell é transparente e as
|
|
187
|
+
superfícies (cards, miolo flush) pintam bg-background por cima. Tinte de 25%
|
|
188
|
+
de muted: separa a superfície do canvas sem virar cinza; segue o tema. */
|
|
189
|
+
body {
|
|
190
|
+
background-color: color-mix(in oklab, var(--muted) 25%, var(--background));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* Markdown (componente `prose`) segue os tokens da casa — light/dark sozinho via as vars
|
|
195
|
+
(que já viram no `.dark`), então dispensa o `prose-invert`. O corpo é muted (como era na
|
|
196
|
+
versão à mão); headings/bold no foreground; bordas/regras no --border. */
|
|
197
|
+
.prose {
|
|
198
|
+
--tw-prose-body: var(--muted-foreground);
|
|
199
|
+
--tw-prose-headings: var(--foreground);
|
|
200
|
+
--tw-prose-lead: var(--muted-foreground);
|
|
201
|
+
--tw-prose-links: var(--foreground);
|
|
202
|
+
--tw-prose-bold: var(--foreground);
|
|
203
|
+
--tw-prose-counters: var(--muted-foreground);
|
|
204
|
+
--tw-prose-bullets: var(--border);
|
|
205
|
+
--tw-prose-hr: var(--border);
|
|
206
|
+
--tw-prose-quotes: var(--muted-foreground);
|
|
207
|
+
--tw-prose-quote-borders: var(--border);
|
|
208
|
+
--tw-prose-captions: var(--muted-foreground);
|
|
209
|
+
--tw-prose-code: var(--foreground);
|
|
210
|
+
--tw-prose-pre-code: var(--code-fg);
|
|
211
|
+
--tw-prose-pre-bg: var(--muted);
|
|
212
|
+
--tw-prose-th-borders: var(--border);
|
|
213
|
+
--tw-prose-td-borders: var(--border);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* Code inline = chip da casa (bg-muted), sem as aspas que o prose injeta.
|
|
217
|
+
* O guard [class~='not-prose'] espelha o escopo do plugin typography: sem ele a
|
|
218
|
+
* regra custom vaza pra dentro do not-prose (o CodeBlock ganhava uma SEGUNDA
|
|
219
|
+
* borda no <pre>, colada na do contêiner — a "borda duplicada"). */
|
|
220
|
+
.prose :where(code):not(:where(pre code, [class~='not-prose'], [class~='not-prose'] *)) {
|
|
221
|
+
border-radius: calc(var(--radius) - 4px);
|
|
222
|
+
background: var(--muted);
|
|
223
|
+
padding: 0.125rem 0.375rem;
|
|
224
|
+
font-weight: 400;
|
|
225
|
+
}
|
|
226
|
+
.prose :where(code):not(:where(pre code, [class~='not-prose'], [class~='not-prose'] *))::before,
|
|
227
|
+
.prose :where(code):not(:where(pre code, [class~='not-prose'], [class~='not-prose'] *))::after {
|
|
228
|
+
content: none;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* Code block = superfície da casa (borda + bg muted) — só o <pre> CRU do prose. */
|
|
232
|
+
.prose :where(pre):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
|
|
233
|
+
border: 1px solid var(--border);
|
|
234
|
+
}
|