@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
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Getting started
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Getting started
|
|
6
|
+
|
|
7
|
+
O Opus é um SDK/protocolo spec-driven: o domínio **É** a aplicação (contratos +
|
|
8
|
+
actions); front e back são cascas. Um projeto Opus-based pina o Opus, herda o runtime e segue os gates.
|
|
9
|
+
|
|
10
|
+
## O modelo
|
|
11
|
+
|
|
12
|
+
> Antes de qualquer arquivo: por que o Opus existe e o que ele assume.
|
|
13
|
+
|
|
14
|
+
A aplicação é o **domínio** — entidades, dicts e contratos de action. A API e a web são cascas
|
|
15
|
+
que consomem esse domínio: zero shape duplicado. O Opus entrega o núcleo (runtime, adapters, UI,
|
|
16
|
+
CLI) e os gates que mantêm o padrão. O que cada projeto adiciona é o seu domínio; o resto vem pinado.
|
|
17
|
+
|
|
18
|
+
## Começar do zero
|
|
19
|
+
|
|
20
|
+
> Projeto novo não se monta à mão: o esqueleto canônico sai do `opus create`, com os
|
|
21
|
+
> pré-requisitos do protocolo, da UI e do preview já plugados — e os gates verdes.
|
|
22
|
+
|
|
23
|
+
O Opus mora no registry da Softize (não no npm público) — uma vez por máquina, ensine
|
|
24
|
+
o escopo ao pnpm; dentro do projeto criado o `.npmrc` já cuida disso:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm config set @softize:registry https://registry.softize.com.br/ --global # 1x por máquina
|
|
28
|
+
|
|
29
|
+
pnpm dlx @softize/opus create meu-app
|
|
30
|
+
cd meu-app && git init && pnpm install && pnpm test
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Máquina nova: se o pnpm reclamar que o diretório global de binários não está no PATH
|
|
34
|
+
(o `dlx` exige), rode `pnpm setup` e reabra o terminal — também é 1x por máquina. Se o
|
|
35
|
+
setup acusar seção pnpm antiga no shell rc (`ERR_PNPM_BAD_SHELL_SECTION`), é resquício
|
|
36
|
+
de versão anterior: `pnpm setup --force` substitui só o bloco dele.
|
|
37
|
+
|
|
38
|
+
Release recém-saída (menos de 24h): a quarentena do pnpm resolve o `dlx` pra versão
|
|
39
|
+
ANTIGA em silêncio ("Comando desconhecido" = sintoma clássico). Fure com a versão
|
|
40
|
+
explícita — `pnpm dlx @softize/opus@<versão> create meu-app` — ou com a flag
|
|
41
|
+
`pnpm --config.minimum-release-age=0 dlx …`. Dentro de projeto o pnpm se resolve
|
|
42
|
+
sozinho (auto-exclui o Opus da quarentena no install).
|
|
43
|
+
|
|
44
|
+
Nasce com: `opus.config.ts` + domínio-exemplo canônico (0 violações, spec documentada),
|
|
45
|
+
vite + react + tema do Opus (Tailwind v4 CSS-first), dev server na porta que o Maestro
|
|
46
|
+
injeta no preview, `opus.json` (pin), `CLAUDE.md` (bloco gerenciado), `.claude/memory/`
|
|
47
|
+
e o CI de fábrica.
|
|
48
|
+
|
|
49
|
+
**Monorepo:** a raiz nasce do `--monorepo` e cada app nasce dentro dela — o create
|
|
50
|
+
detecta o `pnpm-workspace.yaml` e gera só o que é do app (nada de `.npmrc`/workspace
|
|
51
|
+
yaml aninhado), **avisando** o que a raiz precisa ter (glob de packages, escopo do
|
|
52
|
+
registry, allowBuilds) sem tocar nos seus arquivos:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pnpm dlx @softize/opus create meu-cliente --monorepo # a raiz do workspace
|
|
56
|
+
cd meu-cliente && git init
|
|
57
|
+
pnpm dlx @softize/opus create apps/portal # o app (modo detectado)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Carregar o Opus num projeto existente
|
|
61
|
+
|
|
62
|
+
> O pin vive no `opus.json`; o setup grava o esqueleto local. Ausência de `opus.json` = projeto
|
|
63
|
+
> não inicializado — não improvise, rode o setup.
|
|
64
|
+
|
|
65
|
+
A versão do Opus fica pinada em `opus.json`. O `opus setup` é per-app: grava o `opus.json`,
|
|
66
|
+
mantém o bloco gerenciado do `CLAUDE.md` (fora dele o arquivo é seu) e semeia o dia zero
|
|
67
|
+
(`.claude/memory/`, CI) se faltarem. Os componentes e hooks vêm do barrel
|
|
68
|
+
`@softize/opus/ui/react`; o tema, por CSS.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Bootstrap per-app (idempotente): pin + bloco do CLAUDE.md + dia zero.
|
|
72
|
+
npx @softize/opus setup
|
|
73
|
+
|
|
74
|
+
# index.css do app — o tema canônico + os componentes do Opus no scan do Tailwind.
|
|
75
|
+
@import '@softize/opus/ui/theme.css';
|
|
76
|
+
@source '../node_modules/@softize/opus/src/ui/**/*.{ts,tsx}';
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## A stack do runtime
|
|
80
|
+
|
|
81
|
+
> `createRuntime` compõe a stack a partir de adapters plugáveis. Cada capacidade (data, auth,
|
|
82
|
+
> audit…) é um adapter — troca a implementação sem tocar o domínio.
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { createRuntime } from '@softize/opus/core'
|
|
86
|
+
import { kyselyData } from '@softize/opus/data/kysely'
|
|
87
|
+
import { fastifyServer } from '@softize/opus/server/fastify'
|
|
88
|
+
import { pgAudit } from '@softize/opus/audit/pg'
|
|
89
|
+
|
|
90
|
+
const runtime = createRuntime({
|
|
91
|
+
server: fastifyServer({ app }),
|
|
92
|
+
data: kyselyData({ db }), // Kysely + Postgres
|
|
93
|
+
auth: makeAuthAdapter(), // gate (IdP)
|
|
94
|
+
audit: [pgAudit({ pool })], // trilha de auditoria
|
|
95
|
+
config: { env, i18n: { defaultLocale: 'pt-BR' } },
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
// Domínios = grupos de actions. Não registrado = não existe.
|
|
99
|
+
runtime.register([workspacesDomain, agentsDomain, skillsDomain])
|
|
100
|
+
await runtime.start()
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Antes de mexer
|
|
104
|
+
|
|
105
|
+
> O protocolo de leitura: a verdade local mora nos docs do repo, não nesta página.
|
|
106
|
+
|
|
107
|
+
- `CLAUDE.md` do repo e do app — o índice local: mapa, gates, gotchas.
|
|
108
|
+
- As `description` das entidades/actions — a spec de negócio, projetada no manifest pelo `opus gen`.
|
|
109
|
+
- Gate de build: `opus check` (convenções das actions) + `opus db check` (drift entidade ↔ banco). Rode antes de entregar.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
O value é o **nome** do ícone (kebab-case, chave da paleta) — quem consome renderiza com a mesma paleta: `iconPickerIcons[name] ?? FallbackIcon`. Selecionar o já-escolhido desmarca (volta a `''`).
|
|
2
|
+
|
|
3
|
+
## Básico
|
|
4
|
+
|
|
5
|
+
```tsx preview col md
|
|
6
|
+
const [icon, setIcon] = useState('chart-line')
|
|
7
|
+
|
|
8
|
+
render(
|
|
9
|
+
<div className="grid gap-2">
|
|
10
|
+
<Label htmlFor="report-icon">Ícone do relatório</Label>
|
|
11
|
+
<IconPicker id="report-icon" value={icon} onChange={setIcon} />
|
|
12
|
+
</div>,
|
|
13
|
+
)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Renderizando o escolhido
|
|
17
|
+
|
|
18
|
+
A paleta default é exportada (`iconPickerIcons`) — use-a pra desenhar o ícone salvo onde ele aparece (item de lista, card, árvore).
|
|
19
|
+
|
|
20
|
+
```tsx preview col md
|
|
21
|
+
const [icon, setIcon] = useState('store')
|
|
22
|
+
const Icon = iconPickerIcons[icon] ?? FileText
|
|
23
|
+
|
|
24
|
+
render(
|
|
25
|
+
<div className="flex items-center gap-3">
|
|
26
|
+
<IconPicker value={icon} onChange={setIcon} className="w-56" />
|
|
27
|
+
<span className="flex items-center gap-2 rounded-md border px-3 py-2 text-sm">
|
|
28
|
+
<Icon className="size-4 text-muted-foreground" />
|
|
29
|
+
Painel comercial
|
|
30
|
+
</span>
|
|
31
|
+
</div>,
|
|
32
|
+
)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Paleta própria
|
|
36
|
+
|
|
37
|
+
`icons` troca o vocabulário (nome → componente lucide). A paleta default é curta de propósito — cada ícone importado entra no bundle; monte a sua com o que faz sentido no domínio.
|
|
38
|
+
|
|
39
|
+
```tsx preview col md
|
|
40
|
+
const [icon, setIcon] = useState('')
|
|
41
|
+
|
|
42
|
+
render(
|
|
43
|
+
<IconPicker
|
|
44
|
+
value={icon}
|
|
45
|
+
onChange={setIcon}
|
|
46
|
+
icons={{ 'zap': Zap, 'star': Star, 'flag': Flag, 'heart': Heart }}
|
|
47
|
+
placeholder="Selecione um ícone…"
|
|
48
|
+
className="w-56"
|
|
49
|
+
/>,
|
|
50
|
+
)
|
|
51
|
+
```
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
> Só um **ícone leading**? Não precisa do InputGroup — é a prop `icon` do `Input` (a mesma do Select e do Alert). O InputGroup é pros casos que a prop não cobre: botão no fim, prefixo de texto, adorno em bloco, múltiplos.
|
|
2
|
+
|
|
3
|
+
## Com ícone (addon)
|
|
4
|
+
|
|
5
|
+
InputGroupAddon na borda (align inline-start por padrão) cola um ícone ao InputGroupInput dentro da mesma moldura. Clicar no addon foca o campo. Pra um leading simples, prefira `<Input icon={…} />`; aqui é quando o ícone convive com outros adornos.
|
|
6
|
+
|
|
7
|
+
```tsx preview col
|
|
8
|
+
<InputGroup>
|
|
9
|
+
<InputGroupAddon>
|
|
10
|
+
<Search />
|
|
11
|
+
</InputGroupAddon>
|
|
12
|
+
<InputGroupInput placeholder="Buscar sessões do workspace" />
|
|
13
|
+
</InputGroup>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Ícone + ação juntos (o caso do InputGroup)
|
|
17
|
+
|
|
18
|
+
> Só uma ação no fim (um limpar, um mostrar-senha)? Isso é `<Input trailing={…} />` — não precisa do InputGroup. O InputGroup entra quando os adornos se ACUMULAM: aqui, um ícone leading E um botão no fim, na mesma moldura (a busca do `ActionList` é assim). `align=inline-end` joga o addon pro fim; `InputGroupButton` já vem ghost, tamanho `icon-xs`.
|
|
19
|
+
|
|
20
|
+
```tsx preview col
|
|
21
|
+
<InputGroup>
|
|
22
|
+
<InputGroupAddon>
|
|
23
|
+
<Search />
|
|
24
|
+
</InputGroupAddon>
|
|
25
|
+
<InputGroupInput placeholder="Buscar agente" defaultValue="reviewer" />
|
|
26
|
+
<InputGroupAddon align="inline-end">
|
|
27
|
+
<InputGroupButton size="icon-xs" aria-label="Limpar filtro">
|
|
28
|
+
<X />
|
|
29
|
+
</InputGroupButton>
|
|
30
|
+
</InputGroupAddon>
|
|
31
|
+
</InputGroup>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Prefixo e sufixo
|
|
35
|
+
|
|
36
|
+
InputGroupText é o rótulo inerte na borda — prefixo ou sufixo. Aqui emoldura o slug do repositório entre o host fixo e o sufixo .git.
|
|
37
|
+
|
|
38
|
+
```tsx preview col
|
|
39
|
+
<InputGroup>
|
|
40
|
+
<InputGroupAddon>
|
|
41
|
+
<GitBranch />
|
|
42
|
+
<InputGroupText>github.com/softize/</InputGroupText>
|
|
43
|
+
</InputGroupAddon>
|
|
44
|
+
<InputGroupInput placeholder="empresa-x-api" />
|
|
45
|
+
<InputGroupAddon align="inline-end">
|
|
46
|
+
<InputGroupText>.git</InputGroupText>
|
|
47
|
+
</InputGroupAddon>
|
|
48
|
+
</InputGroup>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Composer com rodapé
|
|
52
|
+
|
|
53
|
+
Com InputGroupTextarea a moldura cresce; align=block-end empilha um rodapé de ações embaixo do campo — o padrão do composer de brief do agente.
|
|
54
|
+
|
|
55
|
+
```tsx preview col
|
|
56
|
+
<InputGroup>
|
|
57
|
+
<InputGroupTextarea placeholder="Descreva a task para o agente developer" rows={3} />
|
|
58
|
+
<InputGroupAddon align="block-end">
|
|
59
|
+
<InputGroupText>
|
|
60
|
+
<Sparkles />
|
|
61
|
+
Título gerado pela IA
|
|
62
|
+
</InputGroupText>
|
|
63
|
+
<InputGroupButton size="sm" variant="default" className="ml-auto" aria-label="Enviar brief">
|
|
64
|
+
Enviar
|
|
65
|
+
<ArrowUp />
|
|
66
|
+
</InputGroupButton>
|
|
67
|
+
</InputGroupAddon>
|
|
68
|
+
</InputGroup>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Props
|
|
72
|
+
|
|
73
|
+
| Prop | Tipo | Default | Descrição |
|
|
74
|
+
|---|---|---|---|
|
|
75
|
+
| `align` (InputGroupAddon) | `'inline-start' \| 'inline-end' \| 'block-start' \| 'block-end'` | `'inline-start'` | Onde o addon ancora: inline nas laterais; block empilha (vira coluna) acima ou abaixo — block exige a moldura alta de um InputGroupTextarea. |
|
|
76
|
+
| `size` (InputGroupButton) | `'xs' \| 'sm' \| 'icon-xs' \| 'icon-sm'` | `'xs'` | Tamanho do botão embutido. As variantes icon-* são quadradas, pra um botão só de ícone. |
|
|
77
|
+
| `variant` (InputGroupButton) | `'default' \| 'secondary' \| 'outline' \| 'ghost' \| 'destructive' \| 'link'` | `'ghost'` | Intenção do botão (herda do Button). O padrão ghost some na moldura; use default pra a ação primária. |
|
|
78
|
+
| `placeholder / defaultValue / value` (InputGroupInput, InputGroupTextarea) | `string` | | Props nativas do <input>/<textarea> repassadas ao controle. Controle como faria com Input/Textarea (value + onChange). |
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
## Básico
|
|
2
|
+
|
|
3
|
+
maxLength define quantas casas existem; cada InputOTPSlot recebe o index da sua posição. Um InputOTPGroup envolve as casas.
|
|
4
|
+
|
|
5
|
+
```tsx preview
|
|
6
|
+
<InputOTP maxLength={6}>
|
|
7
|
+
<InputOTPGroup>
|
|
8
|
+
<InputOTPSlot index={0} />
|
|
9
|
+
<InputOTPSlot index={1} />
|
|
10
|
+
<InputOTPSlot index={2} />
|
|
11
|
+
<InputOTPSlot index={3} />
|
|
12
|
+
<InputOTPSlot index={4} />
|
|
13
|
+
<InputOTPSlot index={5} />
|
|
14
|
+
</InputOTPGroup>
|
|
15
|
+
</InputOTP>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Com separador
|
|
19
|
+
|
|
20
|
+
Vários grupos com InputOTPSeparator entre eles quebram o código em blocos — os index seguem contínuos (0–5) por cima da divisão visual.
|
|
21
|
+
|
|
22
|
+
```tsx preview
|
|
23
|
+
<InputOTP maxLength={6}>
|
|
24
|
+
<InputOTPGroup>
|
|
25
|
+
<InputOTPSlot index={0} />
|
|
26
|
+
<InputOTPSlot index={1} />
|
|
27
|
+
<InputOTPSlot index={2} />
|
|
28
|
+
</InputOTPGroup>
|
|
29
|
+
<InputOTPSeparator />
|
|
30
|
+
<InputOTPGroup>
|
|
31
|
+
<InputOTPSlot index={3} />
|
|
32
|
+
<InputOTPSlot index={4} />
|
|
33
|
+
<InputOTPSlot index={5} />
|
|
34
|
+
</InputOTPGroup>
|
|
35
|
+
</InputOTP>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Controlado
|
|
39
|
+
|
|
40
|
+
value + onChange deixam o código no seu estado — bom pra liberar a ação só quando todas as casas estão preenchidas.
|
|
41
|
+
|
|
42
|
+
```tsx preview col-start
|
|
43
|
+
const [code, setCode] = useState('')
|
|
44
|
+
|
|
45
|
+
render(
|
|
46
|
+
<>
|
|
47
|
+
<InputOTP maxLength={6} value={code} onChange={setCode}>
|
|
48
|
+
<InputOTPGroup>
|
|
49
|
+
<InputOTPSlot index={0} />
|
|
50
|
+
<InputOTPSlot index={1} />
|
|
51
|
+
<InputOTPSlot index={2} />
|
|
52
|
+
<InputOTPSlot index={3} />
|
|
53
|
+
<InputOTPSlot index={4} />
|
|
54
|
+
<InputOTPSlot index={5} />
|
|
55
|
+
</InputOTPGroup>
|
|
56
|
+
</InputOTP>
|
|
57
|
+
<p className="text-sm text-muted-foreground">
|
|
58
|
+
{code.length === 6 ? 'Código pronto pra confirmar o acesso ao workspace.' : 'Digite o código de 6 dígitos.'}
|
|
59
|
+
</p>
|
|
60
|
+
</>,
|
|
61
|
+
)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Props
|
|
65
|
+
|
|
66
|
+
| Prop | Tipo | Default | Descrição |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| `maxLength` (InputOTP) | `number` | | Quantas casas o código tem — defina um InputOTPSlot por posição. |
|
|
69
|
+
| `value` (InputOTP) | `string` | | O código no modo controlado — parear com onChange. |
|
|
70
|
+
| `onChange` (InputOTP) | `(value: string) => void` | | Chamado a cada dígito; recebe o código acumulado. |
|
|
71
|
+
| `disabled` (InputOTP) | `boolean` | `false` | Esmaece e bloqueia a digitação do conjunto inteiro. |
|
|
72
|
+
| `index` (InputOTPSlot) | `number` | | A posição da casa (0-based); liga o slot ao dígito correspondente. |
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
## Básico
|
|
2
|
+
|
|
3
|
+
Placeholder orienta o formato, não substitui o rótulo — em formulário de verdade, pareie com Label.
|
|
4
|
+
|
|
5
|
+
```tsx preview col md
|
|
6
|
+
<Input placeholder="Ex.: empresa-x" />
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Ícone dentro do campo
|
|
10
|
+
|
|
11
|
+
`icon` põe um ícone LEADING dentro do campo — identidade (calendário na data, prédio na filial). É a MESMA prop do Select e do Alert: adorno de campo é **prop**, não composição à mão nem ícone jogado ao lado (que desalinha na quebra de linha e some no responsivo). Decorativo — quem nomeia é o Label.
|
|
12
|
+
|
|
13
|
+
```tsx preview col md
|
|
14
|
+
<div className="grid gap-2">
|
|
15
|
+
<Label htmlFor="filial">Filial</Label>
|
|
16
|
+
<Input id="filial" icon={<Building2 />} placeholder="Ex.: Matriz" />
|
|
17
|
+
</div>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Pra mais que um ícone — um botão no fim, um prefixo de texto, adorno em bloco — aí é `InputGroup` (a composição rica). Só o ícone leading é a prop.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## Ação no fim do campo (trailing)
|
|
24
|
+
|
|
25
|
+
`trailing` é o par do `icon`: uma ação DENTRO do campo, no fim — um botão que age sobre o valor (limpar, mostrar senha). Igual ao Select. Diferente do ícone (decorativo), o trailing é interativo.
|
|
26
|
+
|
|
27
|
+
```tsx preview col md
|
|
28
|
+
function Demo() {
|
|
29
|
+
const [q, setQ] = useState('preview pipeline')
|
|
30
|
+
return (
|
|
31
|
+
<Input
|
|
32
|
+
icon={<Search />}
|
|
33
|
+
value={q}
|
|
34
|
+
onChange={(e) => setQ(e.target.value)}
|
|
35
|
+
trailing={
|
|
36
|
+
q ? (
|
|
37
|
+
<Button variant="ghost" size="icon-xs" onClick={() => setQ('')}>
|
|
38
|
+
<X />
|
|
39
|
+
</Button>
|
|
40
|
+
) : undefined
|
|
41
|
+
}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
render(<Demo />)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Pra MAIS de um adorno junto (ícone + botão + prefixo de texto), aí é `InputGroup`. Um ícone e/ou uma ação → props.
|
|
49
|
+
|
|
50
|
+
## Com Label
|
|
51
|
+
|
|
52
|
+
htmlFor aponta pro id do campo — clicar no rótulo foca o input.
|
|
53
|
+
|
|
54
|
+
```tsx preview col md
|
|
55
|
+
<div className="grid gap-2">
|
|
56
|
+
<Label htmlFor="client-name">Nome do cliente</Label>
|
|
57
|
+
<Input id="client-name" defaultValue="Empresa X" />
|
|
58
|
+
</div>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Tipos nativos
|
|
62
|
+
|
|
63
|
+
type é o atributo nativo de <input> — teclado, máscara e validação vêm do browser de graça.
|
|
64
|
+
|
|
65
|
+
```tsx preview col md
|
|
66
|
+
<Input type="email" placeholder="Ex.: joao@softize.com.br" />
|
|
67
|
+
<Input type="password" placeholder="Token de serviço" />
|
|
68
|
+
<Input type="number" placeholder="Porta do dev server" />
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Estados
|
|
72
|
+
|
|
73
|
+
Inválido é aria-invalid (borda e anel destructive) — semântica e visual na mesma prop, sem classe de erro à parte. disabled esmaece e bloqueia.
|
|
74
|
+
|
|
75
|
+
```tsx preview col md
|
|
76
|
+
<Input aria-invalid defaultValue="empresa x" placeholder="Slug do workspace" />
|
|
77
|
+
<Input disabled defaultValue="softize-multica" />
|
|
78
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
## Básico
|
|
2
|
+
|
|
3
|
+
A composição completa: ItemMedia à esquerda, ItemContent (ItemTitle + ItemDescription) ocupando o meio e ItemActions à direita. variant=outline desenha a borda.
|
|
4
|
+
|
|
5
|
+
```tsx preview col
|
|
6
|
+
<Item variant="outline">
|
|
7
|
+
<ItemMedia variant="icon">
|
|
8
|
+
<FolderGit2 />
|
|
9
|
+
</ItemMedia>
|
|
10
|
+
<ItemContent>
|
|
11
|
+
<ItemTitle>empresa-x-api</ItemTitle>
|
|
12
|
+
<ItemDescription>Repositório do backend do workspace Empresa X.</ItemDescription>
|
|
13
|
+
</ItemContent>
|
|
14
|
+
<ItemActions>
|
|
15
|
+
<Button size="sm" variant="outline">Abrir</Button>
|
|
16
|
+
</ItemActions>
|
|
17
|
+
</Item>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Lista
|
|
21
|
+
|
|
22
|
+
Empilhe vários Item num ItemGroup e separe com ItemSeparator — o padrão pra listas de repositórios, agentes ou sessões.
|
|
23
|
+
|
|
24
|
+
```tsx preview col
|
|
25
|
+
<ItemGroup>
|
|
26
|
+
<Item>
|
|
27
|
+
<ItemMedia variant="icon">
|
|
28
|
+
<GitBranch />
|
|
29
|
+
</ItemMedia>
|
|
30
|
+
<ItemContent>
|
|
31
|
+
<ItemTitle>empresa-x-web</ItemTitle>
|
|
32
|
+
<ItemDescription>Front do workspace Empresa X.</ItemDescription>
|
|
33
|
+
</ItemContent>
|
|
34
|
+
<ItemActions>
|
|
35
|
+
<Badge variant="success">sincronizado</Badge>
|
|
36
|
+
</ItemActions>
|
|
37
|
+
</Item>
|
|
38
|
+
<ItemSeparator />
|
|
39
|
+
<Item>
|
|
40
|
+
<ItemMedia variant="icon">
|
|
41
|
+
<GitBranch />
|
|
42
|
+
</ItemMedia>
|
|
43
|
+
<ItemContent>
|
|
44
|
+
<ItemTitle>empresa-x-api</ItemTitle>
|
|
45
|
+
<ItemDescription>Backend do workspace Empresa X.</ItemDescription>
|
|
46
|
+
</ItemContent>
|
|
47
|
+
<ItemActions>
|
|
48
|
+
<Badge variant="warning">3 sessões</Badge>
|
|
49
|
+
</ItemActions>
|
|
50
|
+
</Item>
|
|
51
|
+
</ItemGroup>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Clicável e compacto
|
|
55
|
+
|
|
56
|
+
asChild funde o Item num <a> — a linha inteira vira alvo (hover no fundo). size=sm aperta o respiro; ItemMedia variant=image ancora um avatar.
|
|
57
|
+
|
|
58
|
+
```tsx preview col
|
|
59
|
+
<Item asChild size="sm" variant="outline">
|
|
60
|
+
<a href="#empresa-x">
|
|
61
|
+
<ItemMedia>
|
|
62
|
+
<Avatar>
|
|
63
|
+
<AvatarFallback>AL</AvatarFallback>
|
|
64
|
+
</Avatar>
|
|
65
|
+
</ItemMedia>
|
|
66
|
+
<ItemContent>
|
|
67
|
+
<ItemTitle>Empresa X</ItemTitle>
|
|
68
|
+
<ItemDescription>Workspace com 2 repositórios e 3 agentes.</ItemDescription>
|
|
69
|
+
</ItemContent>
|
|
70
|
+
<ItemActions>
|
|
71
|
+
<ChevronRight className="size-4 text-muted-foreground" />
|
|
72
|
+
</ItemActions>
|
|
73
|
+
</a>
|
|
74
|
+
</Item>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Props
|
|
78
|
+
|
|
79
|
+
| Prop | Tipo | Default | Descrição |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| `variant` (Item) | `'default' \| 'outline' \| 'muted'` | `'default'` | O fundo da linha — default transparente, outline com borda, muted levemente tingido. |
|
|
82
|
+
| `size` (Item) | `'default' \| 'sm'` | `'default'` | O respiro interno — sm aperta o padding pra listas densas. |
|
|
83
|
+
| `asChild` (Item) | `boolean` | `false` | Funde o Item no filho (ex.: <a> ou <button>) — a linha inteira vira o alvo. |
|
|
84
|
+
| `variant` (ItemMedia) | `'default' \| 'icon' \| 'image'` | `'default'` | A moldura da mídia — icon dá caixa quadrada com borda; image recorta a imagem; default sem moldura. |
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
## Básico
|
|
2
|
+
|
|
3
|
+
Uma tecla por Kbd. É só visual — quem escuta o atalho é o seu handler, não o componente.
|
|
4
|
+
|
|
5
|
+
```tsx preview
|
|
6
|
+
<Kbd>Esc</Kbd>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Combinação
|
|
10
|
+
|
|
11
|
+
Envolva as teclas num KbdGroup e ponha o conector (+) como texto entre elas — o padrão pra paleta de comandos do Maestro.
|
|
12
|
+
|
|
13
|
+
```tsx preview
|
|
14
|
+
<KbdGroup>
|
|
15
|
+
<Kbd>⌘</Kbd>
|
|
16
|
+
<span className="text-xs text-muted-foreground">+</span>
|
|
17
|
+
<Kbd>K</Kbd>
|
|
18
|
+
</KbdGroup>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Com ícone
|
|
22
|
+
|
|
23
|
+
Um ícone (lucide) como filho do Kbd ganha size-3 automático — bom pra ⌘ e Enter, onde o glifo lê melhor que a letra.
|
|
24
|
+
|
|
25
|
+
```tsx preview col-start
|
|
26
|
+
<KbdGroup>
|
|
27
|
+
<Kbd>
|
|
28
|
+
<Command />
|
|
29
|
+
</Kbd>
|
|
30
|
+
<Kbd>
|
|
31
|
+
<CornerDownLeft />
|
|
32
|
+
</Kbd>
|
|
33
|
+
</KbdGroup>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## No tooltip
|
|
37
|
+
|
|
38
|
+
Dentro de um TooltipContent o Kbd inverte o tom sozinho (fundo claro sobre o balão escuro) — anuncie o atalho da ação ao passar o mouse.
|
|
39
|
+
|
|
40
|
+
```tsx preview
|
|
41
|
+
<Tooltip>
|
|
42
|
+
<TooltipTrigger className="text-sm text-muted-foreground underline underline-offset-4">
|
|
43
|
+
Abrir paleta de comandos
|
|
44
|
+
</TooltipTrigger>
|
|
45
|
+
<TooltipContent className="flex items-center gap-2">
|
|
46
|
+
Buscar workspace
|
|
47
|
+
<KbdGroup>
|
|
48
|
+
<Kbd>⌘</Kbd>
|
|
49
|
+
<Kbd>K</Kbd>
|
|
50
|
+
</KbdGroup>
|
|
51
|
+
</TooltipContent>
|
|
52
|
+
</Tooltip>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Props
|
|
56
|
+
|
|
57
|
+
| Prop | Tipo | Default | Descrição |
|
|
58
|
+
|---|---|---|---|
|
|
59
|
+
| `children (Kbd)` | `React.ReactNode` | | A tecla — texto (Esc, ⌘, K) ou um ícone lucide, que recebe size-3 automático. |
|
|
60
|
+
| `className (Kbd)` | `string` | | Classes extras na tecla, mescladas com cn — pra ajustar tamanho ou cor pontualmente. |
|
|
61
|
+
| `children (KbdGroup)` | `React.ReactNode` | | As teclas do combo, mais o conector (ex.: "+") como texto entre elas. |
|
|
62
|
+
| `className (KbdGroup)` | `string` | | Classes extras no agrupador (inline-flex + gap-1), mescladas com cn. |
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
## Com campo de texto
|
|
2
|
+
|
|
3
|
+
htmlFor aponta pro id do controle — clicar no rótulo foca o campo.
|
|
4
|
+
|
|
5
|
+
```tsx preview col md
|
|
6
|
+
<div className="grid gap-2">
|
|
7
|
+
<Label htmlFor="workspace-name">Nome do workspace</Label>
|
|
8
|
+
<Input id="workspace-name" placeholder="Ex.: empresa-x" />
|
|
9
|
+
</div>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Com Checkbox
|
|
13
|
+
|
|
14
|
+
O Label já é flex com gap — controle inline entra sem wrapper extra; clicar no texto alterna a caixa.
|
|
15
|
+
|
|
16
|
+
```tsx preview
|
|
17
|
+
<div className="flex items-center gap-2">
|
|
18
|
+
<Checkbox id="notify-reviewer" defaultChecked />
|
|
19
|
+
<Label htmlFor="notify-reviewer">Avisar o revisor ao abrir o handoff</Label>
|
|
20
|
+
</div>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Par desabilitado
|
|
24
|
+
|
|
25
|
+
Controle disabled esmaece o rótulo junto (peer-disabled) — o par inteiro comunica o estado, sem classe manual.
|
|
26
|
+
|
|
27
|
+
```tsx preview
|
|
28
|
+
<div className="flex items-center gap-2">
|
|
29
|
+
<Checkbox id="archive-workspace" disabled />
|
|
30
|
+
<Label htmlFor="archive-workspace">Arquivar o workspace</Label>
|
|
31
|
+
</div>
|
|
32
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Log
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Log
|
|
6
|
+
|
|
7
|
+
Log estruturado que chega no handler já com contexto (per-request, per-action) via
|
|
8
|
+
`ctx.log`. O contrato é o `LoggerAdapter` — a mesma interface `Logger` que o core usa por
|
|
9
|
+
dentro, então o seu log e o do runtime saem no mesmo lugar, no mesmo formato.
|
|
10
|
+
|
|
11
|
+
## O contrato
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
interface Logger {
|
|
15
|
+
trace(msg: string, meta?: object): void
|
|
16
|
+
debug(msg: string, meta?: object): void
|
|
17
|
+
info(msg: string, meta?: object): void
|
|
18
|
+
warn(msg: string, meta?: object): void
|
|
19
|
+
error(msg: string, meta?: object): void
|
|
20
|
+
fatal(msg: string, meta?: object): void
|
|
21
|
+
child(bindings: object): Logger // logger derivado com bindings fixos
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Driver
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import pino from 'pino'
|
|
29
|
+
import { pinoLogger } from '@softize/opus/log/pino'
|
|
30
|
+
|
|
31
|
+
const logger = pinoLogger({ logger: pino({ level: 'info' }) })
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
O `pino` é seu (nível, transport, redact) — o driver só faz a ponte. Peer opcional: quem
|
|
35
|
+
não usa o driver não instala o `pino`.
|
|
36
|
+
|
|
37
|
+
## No runtime
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
const runtime = createRuntime({
|
|
41
|
+
// …server/data…
|
|
42
|
+
logger,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// No handler: ctx.log já vem com o requestId/action injetados (via child()).
|
|
46
|
+
handler: async (ctx, input) => {
|
|
47
|
+
ctx.log.info('emitindo nota', { valor: input.valor })
|
|
48
|
+
return repo.create(input)
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Limites (por enquanto)
|
|
53
|
+
|
|
54
|
+
Superfície mínima de níveis + `child`. Sem sampling nem transports próprios — isso mora no
|
|
55
|
+
`pino` que você passa. Drivers hoje: `pino`; outros entram por reincidência.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
## Fonte e resultado
|
|
2
|
+
|
|
3
|
+
Uso: <Markdown content={fonte} />. No palco, o resultado; no bloco abaixo, a fonte markdown que o produziu. O componente recebe só content: string.
|
|
4
|
+
|
|
5
|
+
```tsx preview col 2xl
|
|
6
|
+
const sample = [
|
|
7
|
+
'# Markdown na Softize',
|
|
8
|
+
'',
|
|
9
|
+
'Renderiza **doc técnica** e mensagem de chat — `SKILL.md`, síntese de papel, resposta de agente.',
|
|
10
|
+
'O motor é o markdown-it, o MESMO que renderiza estas páginas.',
|
|
11
|
+
'',
|
|
12
|
+
'## Sintaxe coberta',
|
|
13
|
+
'',
|
|
14
|
+
'- Headings de `#` a `####`',
|
|
15
|
+
'- Listas com `-` ou numeradas',
|
|
16
|
+
'- **Negrito**, código inline e [links](https://softize.com.br)',
|
|
17
|
+
'',
|
|
18
|
+
'1. Primeiro passo',
|
|
19
|
+
'2. Segundo passo',
|
|
20
|
+
'',
|
|
21
|
+
'> Citação calma, pro tom certo.',
|
|
22
|
+
'',
|
|
23
|
+
'---',
|
|
24
|
+
'',
|
|
25
|
+
'```ts',
|
|
26
|
+
'function ola(): string {',
|
|
27
|
+
" return 'mundo'",
|
|
28
|
+
'}',
|
|
29
|
+
'```',
|
|
30
|
+
].join('\n')
|
|
31
|
+
|
|
32
|
+
render(<Markdown content={sample} />)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
## Props
|
|
37
|
+
|
|
38
|
+
| Prop | Tipo | Default | Descrição |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `content` | `string` | | O markdown cru (CommonMark + tabela GFM, via markdown-it). HTML no fonte é **escapado**, não interpretado — por isso serve pra texto vindo de gente ou de modelo. |
|
|
41
|
+
| `className` | `string` | | Classes do wrapper. |
|