@softize/opus 11.1.0 → 11.1.1

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 CHANGED
@@ -6,6 +6,14 @@ Este arquivo viaja no pacote: num projeto, leia `node_modules/@softize/opus/CHAN
6
6
  Depois de qualquer bump, rode os gates (`typecheck` · `test` · `opus check` ·
7
7
  `manifest:check`) — eles apontam o que a mudança cobra do seu código.
8
8
 
9
+ ## 11.1.1 — 2026-08-21
10
+
11
+ A referência canônica passa a usar `communication.md` como nome do arquivo e `communication`
12
+ como slug. Assim, o nome interno e a URL acompanham o escopo ampliado da página, que deixou de
13
+ tratar apenas de microcopy. A URL anterior, `/ui/microcopy`, redireciona para
14
+ `/ui/communication`, preservando links existentes sem manter o nome antigo na navegação ou na
15
+ fonte materializada.
16
+
9
17
  ## 11.1.0 — 2026-08-21
10
18
 
11
19
  O Opus passa a distribuir a skill `write-product-communication` para orientar documentação,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softize/opus",
3
- "version": "11.1.0",
3
+ "version": "11.1.1",
4
4
  "description": "End-to-end action protocol for TypeScript. Single package with subpath exports (core + adapters).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -25,4 +25,4 @@ permite que a pessoa compreenda ou prossiga sem decodificar a linguagem interna
25
25
 
26
26
  ## Referência canônica
27
27
 
28
- <!-- opus-doc: microcopy.md -->
28
+ <!-- opus-doc: communication.md -->
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * DocBrowser — a VERDADE VISUAL da casa, como doc completa. Seção multi-página: conceitos
3
- * (Introdução, Tokens & Tema, Microcopy, Customização) + uma página por componente do
3
+ * (Introdução, Tokens & Tema, Comunicação, Customização) + uma página por componente do
4
4
  * opus/ui, agrupados por seção. O que você vê aqui é o que os apps entregam (o site
5
5
  * do shadcn é catálogo do que existe; a expectativa visual nasce aqui).
6
6
  *
@@ -35,6 +35,8 @@ export interface DocBrowserProps {
35
35
  path?: string
36
36
  /** Seções a exibir (seção → grupo → página). Default = catálogo inteiro. */
37
37
  sections?: DocSection[]
38
+ /** Slugs antigos que devem abrir e substituir a URL pela página canônica. */
39
+ redirects?: Readonly<Record<string, string>>
38
40
  /** Monta o `document.title` a partir do título da página atual (ex.: `(t) => `${t} · Opus``).
39
41
  * Ausente = não mexe no title. */
40
42
  documentTitle?: (pageTitle: string) => string
@@ -44,6 +46,7 @@ export function DocBrowser({
44
46
  basePath = '/docs',
45
47
  path: controlledPath,
46
48
  sections = DOC_SECTIONS,
49
+ redirects = {},
47
50
  documentTitle,
48
51
  }: DocBrowserProps): React.ReactElement {
49
52
  // Standalone: o path vem do router da casa (`usePathname` — pathname É o estado).
@@ -56,13 +59,18 @@ export function DocBrowser({
56
59
  // Slug = TODOS os segmentos após o basePath, unidos (rota aninhada: `/docs/guias/deploy`
57
60
  // → `guias/deploy`). Slug flat de 1 segmento continua igual (`join` de 1 elemento = ele).
58
61
  const rel = path.startsWith(basePath) ? path.slice(basePath.length) : ''
59
- const slug = rel.split('/').filter(Boolean).join('/') || defaultSlug
62
+ const requestedSlug = rel.split('/').filter(Boolean).join('/') || defaultSlug
63
+ const slug = redirects[requestedSlug] ?? requestedSlug
60
64
  const page = findPage(sections, slug) ?? findPage(sections, defaultSlug)
61
65
 
62
66
  // `navigate` emite `popstate`, então o host é notificado nos dois modos — inclusive o
63
67
  // que ainda escuta o evento na unha, que era como este componente avisava antes.
64
68
  const go = (to: string): void => navigate(to)
65
69
 
70
+ useEffect(() => {
71
+ if (requestedSlug !== slug) navigate(`${basePath}/${slug}`, { replace: true })
72
+ }, [basePath, requestedSlug, slug])
73
+
66
74
  // O title da aba acompanha a página atual (quando o host fornece o formato).
67
75
  useEffect(() => {
68
76
  if (page && documentTitle) document.title = documentTitle(page.title)
@@ -39,7 +39,7 @@ import runtimeMd from './content/runtime.md?raw'
39
39
  import uiMd from './content/ui.md?raw'
40
40
  import cliMd from './content/cli.md?raw'
41
41
  import tokensMd from './content/tokens.md?raw'
42
- import microcopyMd from './content/microcopy.md?raw'
42
+ import communicationMd from './content/communication.md?raw'
43
43
  import customizationMd from './content/customization.md?raw'
44
44
 
45
45
  // — Componentes —
@@ -267,7 +267,7 @@ export const UI_SECTIONS: DocSection[] = [
267
267
  {
268
268
  pages: [
269
269
  { slug: 'tokens', title: 'Tokens & Tema', render: doc(tokensMd) },
270
- { slug: 'microcopy', title: 'Comunicação', render: doc(microcopyMd) },
270
+ { slug: 'communication', title: 'Comunicação', render: doc(communicationMd) },
271
271
  { slug: 'customization', title: 'Customização', render: doc(customizationMd) },
272
272
  ],
273
273
  },