primocode 9.9.0 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +30 -6
  2. package/bin/primocode.js +100 -341
  3. package/lib/act.js +245 -23
  4. package/lib/browser.js +17 -0
  5. package/lib/casar.js +108 -0
  6. package/lib/catalogo.js +6 -2
  7. package/lib/config.js +10 -3
  8. package/lib/cursor.js +10 -1
  9. package/lib/entrada.js +4 -2
  10. package/lib/estudio/diretor.js +9 -1
  11. package/lib/estudio/ende.js +2 -0
  12. package/lib/estudio/estilo.js +51 -0
  13. package/lib/estudio/glifos.js +215 -0
  14. package/lib/estudio/index.js +63 -11
  15. package/lib/estudio/kit/base.jsx +285 -0
  16. package/lib/estudio/kit/index.jsx +11 -0
  17. package/lib/estudio/kit/marca.jsx +741 -0
  18. package/lib/estudio/kit/vox.jsx +357 -0
  19. package/lib/estudio/kit.js +72 -0
  20. package/lib/estudio/lancamento.js +413 -0
  21. package/lib/estudio/morfar.js +191 -0
  22. package/lib/estudio/motion.js +333 -0
  23. package/lib/estudio/plano.js +54 -7
  24. package/lib/estudio/remotion.js +167 -52
  25. package/lib/estudio/ritmo.js +77 -0
  26. package/lib/estudio/sons-leves.js +62 -0
  27. package/lib/estudio/vox.js +385 -0
  28. package/lib/fala.js +1 -94
  29. package/lib/pipeline.js +55 -56
  30. package/lib/repeticao.js +3 -1
  31. package/lib/skills.js +8 -2
  32. package/lib/snapshot.js +111 -0
  33. package/lib/tools.js +79 -20
  34. package/lib/ui.js +13 -6
  35. package/lib/video/analise.js +89 -0
  36. package/lib/video/cli.js +74 -0
  37. package/lib/video/delta.js +90 -0
  38. package/lib/video/edits.js +379 -0
  39. package/lib/video/filters.js +247 -0
  40. package/lib/video/ops.js +322 -0
  41. package/lib/video/projeto.js +133 -0
  42. package/lib/video/render.js +221 -0
  43. package/lib/video/texto.js +142 -0
  44. package/lib/video/timeline.js +310 -0
  45. package/lib/video/transcript.js +124 -0
  46. package/lib/voz.js +75 -223
  47. package/package.json +2 -3
  48. package/skills/motion-de-primeira/SKILL.md +21 -1
  49. package/studio/texto.py +208 -0
  50. package/voz/primo_voz/__main__.py +96 -236
  51. package/voz/primo_voz/transcrever.py +31 -1
  52. package/app/ansi.js +0 -55
  53. package/app/app.css +0 -500
  54. package/app/app.js +0 -1017
  55. package/app/icone.svg +0 -6
  56. package/app/index.html +0 -220
  57. package/app/primo-marca.js +0 -192
  58. package/lib/app.js +0 -615
  59. package/lib/icone.js +0 -263
  60. package/lib/instalar-app.js +0 -231
  61. package/lib/painel.js +0 -291
  62. package/voz/primo_voz/desperta.py +0 -195
  63. package/voz/primo_voz/orbe.py +0 -406
package/app/icone.svg DELETED
@@ -1,6 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
- <rect width="32" height="32" rx="7" fill="#0a0f16"/>
3
- <path d="M8 10.5 13 16l-5 5.5" fill="none" stroke="#22d3ee" stroke-width="2.6"
4
- stroke-linecap="round" stroke-linejoin="round"/>
5
- <path d="M16.5 22H24" fill="none" stroke="#22d3ee" stroke-width="2.6" stroke-linecap="round"/>
6
- </svg>
package/app/index.html DELETED
@@ -1,220 +0,0 @@
1
- <!doctype html>
2
- <html lang="pt-BR" data-tema="escuro">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width,initial-scale=1">
6
- <title>PrimoCode</title>
7
- <link rel="stylesheet" href="/app.css">
8
- <link rel="icon" href="/icone.svg">
9
- </head>
10
- <!--
11
- A janela do PrimoCode — /rc, /ide e `primo ide` abrem esta mesma página.
12
-
13
- O layout é o de um app de mesa de agente: barra lateral com novo chat,
14
- projetos e recentes; a pergunta no meio da tela vazia; o compositor embaixo
15
- com projeto, anexo, permissão, esforço e voz; e um painel à direita com a
16
- prévia do site e os arquivos (a IDE antiga, sem o editor).
17
-
18
- Os ícones são SVG em linha, de propósito: sem fonte de ícone, sem CDN, sem
19
- pedir nada fora da máquina (regra do AGENTS.md). Cada um é um <symbol> aqui
20
- em cima e um <use> onde aparece — o mesmo desenho não é copiado dez vezes.
21
- -->
22
- <body>
23
-
24
- <svg width="0" height="0" style="position:absolute" aria-hidden="true">
25
- <defs>
26
- <symbol id="i-lado" viewBox="0 0 24 24"><rect x="3.5" y="4.5" width="17" height="15" rx="3"/><path d="M9.5 4.5v15"/></symbol>
27
- <symbol id="i-painel" viewBox="0 0 24 24"><rect x="3.5" y="4.5" width="17" height="15" rx="3"/><path d="M14.5 4.5v15"/></symbol>
28
- <symbol id="i-chev" viewBox="0 0 24 24"><path d="m7 10 5 5 5-5"/></symbol>
29
- <symbol id="i-busca" viewBox="0 0 24 24"><circle cx="11" cy="11" r="6"/><path d="m20 20-4.6-4.6"/></symbol>
30
- <symbol id="i-sino" viewBox="0 0 24 24"><path d="M6.5 16.5V11a5.5 5.5 0 0 1 11 0v5.5l1.5 1.5H5z"/><path d="M10 20.5a2 2 0 0 0 4 0"/></symbol>
31
- <symbol id="i-editar" viewBox="0 0 24 24"><path d="M11 4.5H7a2.5 2.5 0 0 0-2.5 2.5v10A2.5 2.5 0 0 0 7 19.5h10a2.5 2.5 0 0 0 2.5-2.5v-4"/><path d="M17.8 3.9a1.8 1.8 0 0 1 2.5 2.5L12 14.7l-3.3.8.8-3.3z"/></symbol>
32
- <symbol id="i-mais-circ" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8"/><path d="M12 8.5v7M8.5 12h7"/></symbol>
33
- <symbol id="i-terminal" viewBox="0 0 24 24"><rect x="3.5" y="4.5" width="17" height="15" rx="3"/><path d="m7.5 10 2.5 2-2.5 2M12.5 14.5h4"/></symbol>
34
- <symbol id="i-olho" viewBox="0 0 24 24"><path d="M2.8 12S6 5.8 12 5.8 21.2 12 21.2 12 18 18.2 12 18.2 2.8 12 2.8 12z"/><circle cx="12" cy="12" r="2.6"/></symbol>
35
- <symbol id="i-barra" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.5"/><path d="m14 7.5-4 9"/></symbol>
36
- <symbol id="i-ajuda" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.5"/><path d="M9.7 9.6a2.4 2.4 0 1 1 3.3 2.2c-.6.3-1 .8-1 1.5v.4"/><circle cx="12" cy="16.6" r=".4"/></symbol>
37
- <symbol id="i-pasta" viewBox="0 0 24 24"><path d="M3.5 7.5A2 2 0 0 1 5.5 5.5h3.8l2 2h7.2a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2z"/></symbol>
38
- <symbol id="i-mais" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></symbol>
39
- <symbol id="i-perigo" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.5"/><path d="M12 7.8v5.2"/><circle cx="12" cy="16.3" r=".5"/></symbol>
40
- <symbol id="i-escudo" viewBox="0 0 24 24"><path d="M12 3.5 5.5 6v5.2c0 4.3 2.8 7.6 6.5 9.3 3.7-1.7 6.5-5 6.5-9.3V6z"/><path d="m9.2 12 2 2 3.8-4"/></symbol>
41
- <symbol id="i-mao" viewBox="0 0 24 24"><path d="M12 3.5 5.5 6v5.2c0 4.3 2.8 7.6 6.5 9.3 3.7-1.7 6.5-5 6.5-9.3V6z"/><path d="M12 8.5v4"/><circle cx="12" cy="15.6" r=".5"/></symbol>
42
- <symbol id="i-mic" viewBox="0 0 24 24"><rect x="9" y="3.5" width="6" height="11" rx="3"/><path d="M5.8 11.5a6.2 6.2 0 0 0 12.4 0M12 17.7v2.8"/></symbol>
43
- <symbol id="i-seta" viewBox="0 0 24 24"><path d="M12 19V5.5M6.5 11 12 5.5l5.5 5.5"/></symbol>
44
- <symbol id="i-fechar" viewBox="0 0 24 24"><path d="m6.5 6.5 11 11M17.5 6.5l-11 11"/></symbol>
45
- <symbol id="i-recarregar" viewBox="0 0 24 24"><path d="M19 12a7 7 0 1 1-2.1-5"/><path d="M19.2 4.5v4h-4"/></symbol>
46
- <symbol id="i-arquivo" viewBox="0 0 24 24"><path d="M7 3.5h6.5l4.5 4.5v11a1.5 1.5 0 0 1-1.5 1.5h-9.5A1.5 1.5 0 0 1 5.5 19V5A1.5 1.5 0 0 1 7 3.5z"/><path d="M13.5 3.5V8H18"/></symbol>
47
- <symbol id="i-ler" viewBox="0 0 24 24"><path d="M7 3.5h6.5l4.5 4.5v11a1.5 1.5 0 0 1-1.5 1.5h-9.5A1.5 1.5 0 0 1 5.5 19V5A1.5 1.5 0 0 1 7 3.5z"/><path d="M8.5 12.5h7M8.5 16h5"/></symbol>
48
- <symbol id="i-rodar" viewBox="0 0 24 24"><path d="m6 8.5 4 3.5-4 3.5M12 16h6"/></symbol>
49
- <symbol id="i-web" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.5"/><path d="M3.5 12h17M12 3.5c2.4 2.4 3.4 5.3 3.4 8.5s-1 6.1-3.4 8.5c-2.4-2.4-3.4-5.3-3.4-8.5s1-6.1 3.4-8.5z"/></symbol>
50
- <symbol id="i-computador" viewBox="0 0 24 24"><rect x="3.5" y="4.5" width="17" height="11.5" rx="2"/><path d="M9 20h6M12 16v4"/></symbol>
51
- <symbol id="i-plano" viewBox="0 0 24 24"><path d="M9.5 7h10M9.5 12h10M9.5 17h10"/><path d="m4 7 1.2 1.2L7 6.3M4 12l1.2 1.2L7 11.3"/><circle cx="5.5" cy="17" r=".8"/></symbol>
52
- <symbol id="i-agente" viewBox="0 0 24 24"><rect x="5" y="7.5" width="14" height="11" rx="3"/><path d="M12 7.5V4.5"/><circle cx="9.5" cy="12.5" r=".9"/><circle cx="14.5" cy="12.5" r=".9"/></symbol>
53
- <symbol id="i-pare" viewBox="0 0 24 24"><rect x="7.5" y="7.5" width="9" height="9" rx="1.6" fill="currentColor" stroke="none"/></symbol>
54
- </defs>
55
- </svg>
56
-
57
- <div class="app" id="app">
58
- <aside class="lado" id="lado" aria-label="Conversas e projetos">
59
- <div class="lado-barra">
60
- <button class="icone-btn" id="btnLado" type="button" aria-label="Recolher a barra lateral" title="Barra lateral (Ctrl+B)">
61
- <svg class="ic"><use href="#i-lado"/></svg>
62
- </button>
63
- </div>
64
-
65
- <div class="lado-marca">
66
- <button class="marca-btn" id="btnMarca" type="button" aria-haspopup="menu">
67
- <span>PrimoCode</span><svg class="ic ic-p"><use href="#i-chev"/></svg>
68
- </button>
69
- <div class="lado-acoes">
70
- <button class="icone-btn" id="btnBusca" type="button" aria-label="Buscar nos recentes" title="Buscar"><svg class="ic"><use href="#i-busca"/></svg></button>
71
- <button class="icone-btn" id="btnAvisos" type="button" aria-pressed="false" aria-label="Avisar quando terminar" title="Avisar quando o Primo terminar"><svg class="ic"><use href="#i-sino"/></svg></button>
72
- </div>
73
- </div>
74
-
75
- <div class="busca" id="busca" hidden>
76
- <input id="campoBusca" type="search" placeholder="Buscar nos recentes" autocomplete="off">
77
- </div>
78
-
79
- <nav class="nav" aria-label="Principal">
80
- <div class="nav-linha">
81
- <button class="nav-item ativo" id="btnNovo" type="button"><svg class="ic"><use href="#i-editar"/></svg>Novo chat</button>
82
- <button class="icone-btn" id="btnNovoProjeto" type="button" aria-label="Novo projeto" title="Novo projeto em ~/primocode"><svg class="ic"><use href="#i-mais-circ"/></svg></button>
83
- </div>
84
- <button class="nav-item" id="navTerminal" type="button" aria-pressed="false"><svg class="ic"><use href="#i-terminal"/></svg>Terminal</button>
85
- <button class="nav-item" id="navPrevia" type="button"><svg class="ic"><use href="#i-olho"/></svg>Prévia do site</button>
86
- <button class="nav-item" id="navComandos" type="button"><svg class="ic"><use href="#i-barra"/></svg>Comandos</button>
87
- </nav>
88
-
89
- <div class="rolagem-lado">
90
- <div class="secao" id="secaoProjetos">Projetos</div>
91
- <div class="lista" id="listaProjetos"><div class="vazio-lista">Nenhum projeto</div></div>
92
-
93
- <div class="secao" id="secaoRecentes">Recentes</div>
94
- <div class="lista" id="listaRecentes"><div class="vazio-lista">Nenhuma conversa ainda</div></div>
95
- </div>
96
-
97
- <div class="lado-pe">
98
- <div class="usuario"><span class="avatar" id="avatar">PC</span><span class="nome-usuario" id="nomeUsuario">Você</span></div>
99
- <button class="icone-btn" id="btnAjuda" type="button" aria-label="Atalhos e comandos" title="Atalhos e comandos"><svg class="ic"><use href="#i-ajuda"/></svg></button>
100
- </div>
101
- </aside>
102
-
103
- <main class="centro">
104
- <header class="topo">
105
- <button class="icone-btn" id="btnLadoAbrir" type="button" aria-label="Abrir a barra lateral" title="Barra lateral (Ctrl+B)"><svg class="ic"><use href="#i-lado"/></svg></button>
106
- <div class="topo-titulo" id="topoTitulo"></div>
107
- <button class="icone-btn" id="btnPainel" type="button" aria-pressed="false" aria-label="Abrir a prévia e os arquivos" title="Prévia e arquivos"><svg class="ic"><use href="#i-painel"/></svg></button>
108
- </header>
109
-
110
- <div class="rolo" id="rolo">
111
- <section class="vazio" id="vazio">
112
- <span class="mascote" id="mascote"></span>
113
- <h1>O que vamos criar?</h1>
114
- </section>
115
- <div class="chat" id="chat" hidden aria-live="polite"></div>
116
- </div>
117
-
118
- <section class="terminal" id="terminal" hidden aria-label="Terminal">
119
- <header class="terminal-topo">
120
- <span><b>Terminal</b> <small>o mesmo que aparece no CLI</small></span>
121
- <button class="icone-btn" id="fecharTerminal" type="button" aria-label="Voltar para o chat"><svg class="ic"><use href="#i-fechar"/></svg></button>
122
- </header>
123
- <pre class="terminal-saida" id="terminalSaida"></pre>
124
- </section>
125
-
126
- <footer class="rodape">
127
- <div class="compositor-zona" id="zona">
128
- <div class="projeto-barra">
129
- <button class="projeto-btn" id="btnProjeto" type="button" aria-haspopup="menu">
130
- <svg class="ic"><use href="#i-pasta"/></svg><span id="projetoNome">Escolher projeto</span>
131
- </button>
132
- </div>
133
- <form class="compositor" id="forma">
134
- <div class="anexos" id="anexos" hidden></div>
135
- <textarea id="campo" rows="1" placeholder="Peça qualquer coisa" autocomplete="off" spellcheck="false" aria-label="Pedido"></textarea>
136
- <div class="controles">
137
- <button class="icone-btn grande" id="btnAnexar" type="button" aria-label="Anexar arquivo" title="Anexar arquivo"><svg class="ic"><use href="#i-mais"/></svg></button>
138
- <input id="arquivo" type="file" multiple hidden>
139
- <button class="chip-perm" id="btnPermissao" type="button" aria-haspopup="menu" data-modo="auto">
140
- <svg class="ic" id="permIcone"><use href="#i-escudo"/></svg><span id="permRotulo">Pergunta antes do perigoso</span>
141
- </button>
142
- <span class="espaco"></span>
143
- <button class="seletor" id="btnEsforco" type="button" aria-haspopup="menu" title="Esforço do agente (/effort)">
144
- <b id="esforcoRotulo">Equilíbrio</b><span id="esforcoNome">medium</span><svg class="ic ic-p"><use href="#i-chev"/></svg>
145
- </button>
146
- <button class="icone-btn" id="btnMic" type="button" aria-pressed="false" aria-label="Ligar o modo voz" title="Modo voz (/voice)"><svg class="ic"><use href="#i-mic"/></svg></button>
147
- <button class="enviar" id="btnEnviar" type="submit" disabled aria-label="Enviar" title="Enviar (Enter)"><svg class="ic"><use href="#i-seta"/></svg></button>
148
- </div>
149
- </form>
150
- </div>
151
- </footer>
152
- </main>
153
-
154
- <aside class="painel" id="painel" hidden aria-label="Prévia e arquivos">
155
- <header class="painel-topo">
156
- <div class="abas" role="tablist">
157
- <button class="aba" id="abaPrevia" type="button" role="tab" aria-selected="true">Prévia</button>
158
- <button class="aba" id="abaArquivos" type="button" role="tab" aria-selected="false">Arquivos</button>
159
- </div>
160
- <span class="espaco"></span>
161
- <button class="icone-btn" id="btnRecarregar" type="button" aria-label="Recarregar" title="Recarregar"><svg class="ic"><use href="#i-recarregar"/></svg></button>
162
- <button class="icone-btn" id="fecharPainel" type="button" aria-label="Fechar o painel"><svg class="ic"><use href="#i-fechar"/></svg></button>
163
- </header>
164
- <div class="painel-corpo" id="corpoPrevia">
165
- <iframe class="previa" id="previa" title="Prévia do site"
166
- sandbox="allow-scripts allow-forms allow-modals allow-popups allow-pointer-lock"></iframe>
167
- <div class="painel-vazio" id="previaVazia" hidden>
168
- <span class="mascote pequeno" id="mascotePainel"></span>
169
- <p>Ainda não tem site nesta pasta.</p>
170
- <p class="fraco">Peça "crie uma página de…" e ele aparece aqui, atualizando sozinho.</p>
171
- </div>
172
- </div>
173
- <div class="painel-corpo arquivos" id="corpoArquivos" hidden>
174
- <div class="arvore" id="arvore" role="tree"></div>
175
- <div class="visor">
176
- <div class="visor-topo" id="visorNome">Escolha um arquivo</div>
177
- <pre class="visor-texto" id="visor"></pre>
178
- </div>
179
- </div>
180
- </aside>
181
- </div>
182
-
183
- <div class="menu" id="menu" role="menu" hidden></div>
184
-
185
- <dialog class="dialogo" id="dlgAjuda" aria-labelledby="tituloAjuda">
186
- <header class="dlg-topo">
187
- <h2 id="tituloAjuda">Atalhos e comandos</h2>
188
- <button class="icone-btn" id="fecharAjuda" type="button" aria-label="Fechar"><svg class="ic"><use href="#i-fechar"/></svg></button>
189
- </header>
190
- <div class="dlg-corpo">
191
- <h3>Teclado</h3>
192
- <dl class="atalhos">
193
- <dt><kbd>Enter</kbd></dt><dd>manda o pedido</dd>
194
- <dt><kbd>Shift</kbd> <kbd>Enter</kbd></dt><dd>quebra a linha</dd>
195
- <dt><kbd>Esc</kbd> <kbd>Esc</kbd></dt><dd>para o que o Primo está fazendo</dd>
196
- <dt><kbd>Ctrl</kbd> <kbd>B</kbd></dt><dd>mostra ou esconde a barra lateral</dd>
197
- <dt><kbd>Ctrl</kbd> <kbd>J</kbd></dt><dd>abre o terminal</dd>
198
- </dl>
199
- <h3>Comandos</h3>
200
- <p class="fraco">Digite no campo, como no terminal. Clique para usar.</p>
201
- <div class="comandos" id="listaComandos">
202
- <button type="button" data-cmd="/help">/help <span>todos os comandos</span></button>
203
- <button type="button" data-cmd="/novo ">/novo <span>projeto novo, do zero</span></button>
204
- <button type="button" data-cmd="/abrir">/abrir <span>abre o site do projeto</span></button>
205
- <button type="button" data-cmd="/desfazer">/desfazer <span>volta o que ele mexeu</span></button>
206
- <button type="button" data-cmd="/status">/status <span>conta e servidor</span></button>
207
- <button type="button" data-cmd="/mascot">/mascot <span>troca o mascote</span></button>
208
- <button type="button" data-cmd="/login">/login <span>entra na sua conta</span></button>
209
- <button type="button" data-cmd="/doctor">/doctor <span>confere o que costuma dar problema</span></button>
210
- </div>
211
- </div>
212
- </dialog>
213
-
214
- <div class="alvo-solto" id="alvoSolto"><div><strong>Solte aqui</strong><span>o arquivo entra como anexo do pedido</span></div></div>
215
-
216
- <script src="/primo-marca.js"></script>
217
- <script src="/ansi.js"></script>
218
- <script src="/app.js"></script>
219
- </body>
220
- </html>
@@ -1,192 +0,0 @@
1
- /**
2
- * primo-marca.js — o mascote do PrimoCode, desenhado em pixel.
3
- *
4
- * ── POR QUE MATRIZ, E NÃO O PNG ──────────────────────────────────────────
5
- * O logo veio como imagem. Guardar o PNG funcionaria, mas ele já é pixel art:
6
- * redesenhá-lo como MATRIZ dá o mesmo desenho nítido em qualquer tamanho —
7
- * favicon de 16px, cabeçalho de 28px, tela vazia de 96px — sem borrar, sem
8
- * três arquivos para manter, e pesando algumas centenas de bytes em vez de
9
- * dezenas de kB.
10
- *
11
- * E deixa a cor viver no TEMA: o mesmo bicho no claro e no escuro, sem PNG
12
- * com fundo grudado.
13
- *
14
- * Se um dia o desenho mudar, muda a matriz — é uma linha por fileira, e dá
15
- * para ler o bicho olhando o código.
16
- *
17
- * C = corpo (ciano claro) · D = detalhe (azul escuro): orelhas,
18
- * braços e pés · . = vazio
19
- */
20
- (function (raiz) {
21
- "use strict";
22
-
23
- var MATRIZ = [
24
- "...DD....DD...",
25
- "...DD....DD...",
26
- "..CCCCCCCCCC..",
27
- "..CCCCCCCCCC..",
28
- "DDCCCCCCCCCCDD",
29
- "DDCCCCCCCCCCDD",
30
- "..CCCCCCCCCC..",
31
- "..CCCCCCCCCC..",
32
- "..CCCCCCCCCC..",
33
- "...DD....DD...",
34
- "...DD....DD...",
35
- ];
36
-
37
- var CORPO = "#5ec8ef";
38
- var DETALHE = "#2b7fa8";
39
-
40
- /**
41
- * O mascote como SVG.
42
- *
43
- * Retângulos colados, sem `shape-rendering: crispEdges`: em pixel art
44
- * ampliado, o antialiasing do navegador deixa fios claros entre um quadrado
45
- * e outro. Colar meio pixel a mais em cada lado (o `+0.02`) some com a
46
- * costura sem mudar o desenho.
47
- *
48
- * @param {object} op
49
- * @param {number} [op.tamanho] lado em px (o SVG é quadrado)
50
- * @param {string} [op.corpo] cor do corpo
51
- * @param {string} [op.detalhe] cor das orelhas, braços e pés
52
- * @param {string} [op.fundo] cor do quadrado de trás (vazio = sem fundo)
53
- * @param {string} [op.rotulo] texto alternativo; vazio = decorativo
54
- */
55
- function svg(op) {
56
- op = op || {};
57
- var lado = op.tamanho || 32;
58
- var corpo = op.corpo || CORPO;
59
- var detalhe = op.detalhe || DETALHE;
60
- var linhas = MATRIZ.length;
61
- var colunas = MATRIZ[0].length;
62
- // O desenho é mais largo que alto; a caixa é quadrada e ele fica centrado.
63
- var caixa = Math.max(linhas, colunas);
64
- var dx = (caixa - colunas) / 2;
65
- var dy = (caixa - linhas) / 2;
66
-
67
- /* UM caminho por cor, e não um retângulo por célula.
68
- *
69
- * Com retângulos separados, o navegador antialiasa a borda de cada um
70
- * contra a do vizinho e o desenho ganha uma grade de fios claros no meio
71
- * do corpo — visível já em 96px, feio em 200px. Num caminho só, as
72
- * células vizinhas viram uma forma única e não há borda interna nenhuma
73
- * para suavizar. */
74
- var caminho = { C: [], D: [] };
75
- for (var y = 0; y < linhas; y++) {
76
- var fileira = MATRIZ[y];
77
- for (var x = 0; x < colunas; x++) {
78
- var ch = fileira[x];
79
- if (ch !== "C" && ch !== "D") continue;
80
- caminho[ch].push("M" + (x + dx) + " " + (y + dy) + "h1v1h-1z");
81
- }
82
- }
83
-
84
- var partes = [];
85
- if (op.fundo) {
86
- partes.push('<rect width="' + caixa + '" height="' + caixa
87
- + '" rx="' + (caixa * 0.18).toFixed(2) + '" fill="' + op.fundo + '"/>');
88
- }
89
- if (caminho.C.length) partes.push('<path d="' + caminho.C.join("") + '" fill="' + corpo + '"/>');
90
- if (caminho.D.length) partes.push('<path d="' + caminho.D.join("") + '" fill="' + detalhe + '"/>');
91
-
92
- var acessivel = op.rotulo
93
- ? ' role="img" aria-label="' + String(op.rotulo).replace(/"/g, "&quot;") + '"'
94
- : ' aria-hidden="true"';
95
-
96
- return '<svg viewBox="0 0 ' + caixa + " " + caixa + '" width="' + lado
97
- + '" height="' + lado + '"' + acessivel + ">" + partes.join("") + "</svg>";
98
- }
99
-
100
- /* A LOGO — a que o dono mandou, e a mesma do ícone do sistema
101
- (`app/icone.svg` no PrimoCode): quadrado escuro arredondado, o chevron do
102
- prompt e o sublinhado do cursor, em ciano. Onde o produto se apresenta
103
- (botão da barra lateral, cabeçalho, favicon) vai ELA; o mascote em pixel
104
- acima fica para onde ele é personagem, não marca. Foi por confundir os
105
- dois que a barra lateral mostrou o bicho onde devia estar a logo. */
106
- var LOGO_FUNDO = "#0a0f16";
107
- var LOGO_TRACO = "#22d3ee";
108
-
109
- /**
110
- * A logo como SVG.
111
- * @param {object} op
112
- * @param {number} [op.tamanho] lado em px
113
- * @param {string} [op.rotulo] texto alternativo; vazio = decorativo
114
- */
115
- function logo(op) {
116
- op = op || {};
117
- var lado = op.tamanho || 32;
118
- var acessivel = op.rotulo
119
- ? ' role="img" aria-label="' + String(op.rotulo).replace(/"/g, "&quot;") + '"'
120
- : ' aria-hidden="true"';
121
- return '<svg viewBox="0 0 32 32" width="' + lado + '" height="' + lado + '"' + acessivel + ">"
122
- + '<rect width="32" height="32" rx="7" fill="' + LOGO_FUNDO + '"/>'
123
- + '<path d="M8 10.5 13 16l-5 5.5" fill="none" stroke="' + LOGO_TRACO
124
- + '" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>'
125
- + '<path d="M16.5 22H24" fill="none" stroke="' + LOGO_TRACO + '" stroke-width="2.6" stroke-linecap="round"/>'
126
- + "</svg>";
127
- }
128
-
129
- /** A logo como favicon, sem pedir arquivo ao servidor. */
130
- function favicon() {
131
- return "data:image/svg+xml," + encodeURIComponent(logo({ tamanho: 32 }));
132
- }
133
-
134
- /* ── O MASCOTE EM TRAÇO ────────────────────────────────────────────────
135
- A tela vazia da janela pede um ícone de LINHA, fino e neutro, no lugar
136
- do bicho em pixel colorido: a janela é cinza e calma, e um mascote de
137
- blocos cianos no meio dela gritava mais alto que a pergunta. Um traço
138
- por mascote de lib/ui.js (MASCOTS), mesmo nome de id — quem escolheu a
139
- coruja no /mascot vê a coruja aqui também. Os três de orelha (primo,
140
- raposa, gato) têm o ❯_ do prompt no rosto: é a marca do PrimoCode.
141
-
142
- Tudo em `currentColor`, então a cor vem do CSS e segue o tema. */
143
- var CORPO_LINHA = "M14 16h20a5 5 0 0 1 5 5v12a5 5 0 0 1-5 5H14a5 5 0 0 1-5-5V21a5 5 0 0 1 5-5z";
144
- var ROSTO_PROMPT = "M17 23.5l4 3.5-4 3.5M24 31h7";
145
- var PES = "M17 38v4M31 38v4";
146
- var LINHAS = {
147
- primo: [CORPO_LINHA, ROSTO_PROMPT, PES, "M16 16v-6h4v6M28 16v-6h4v6", "M9 26H5M39 26h4"],
148
- fox: [CORPO_LINHA, ROSTO_PROMPT, PES, "M12 17 9 6l9 10M36 17l3-11-9 10"],
149
- cat: [CORPO_LINHA, ROSTO_PROMPT, PES, "M14 16l1-7 6 7M34 16l-1-7-6 7"],
150
- robo: ["M13 14h22a4 4 0 0 1 4 4v14a4 4 0 0 1-4 4H13a4 4 0 0 1-4-4V18a4 4 0 0 1 4-4z",
151
- "M24 14V9", "c24 6.5 2", "c18 24 2.5", "c30 24 2.5", "M19 31h10", "M16 36v5M32 36v5"],
152
- coruja: ["M12 11l6 5h12l6-5v19a12 12 0 0 1-24 0z", "c19 24 4", "c29 24 4", "M24 29l-2 3h4z"],
153
- dragao: [CORPO_LINHA, PES, "M13 16 9 8M35 16l4-8", "M9 22 3 18v10l6-2M39 22l6-4v10l-6-2",
154
- "c18.5 25 1.5", "c29.5 25 1.5", "M21 31h6"],
155
- fantasma: ["M12 40V22a12 12 0 0 1 24 0v18l-4-3-4 3-4-3-4 3-4-3z", "c20 23 2", "c28 23 2"],
156
- capivara: ["M8 24c0-6 5-9 11-9h13c6 0 9 5 9 11v5a6 6 0 0 1-6 6H14a6 6 0 0 1-6-6z",
157
- "M14 16l1-4 4 3", "c14.5 22.5 1.5", "M8 27h3", "M15 37v4M33 37v4"],
158
- polvo: ["M14 27a10 10 0 1 1 20 0v1H14z", "c20 22 1.5", "c28 22 1.5",
159
- "M15 28c-4 4-6 8-3 12M20 28c-1 5-1 9 1 12M28 28c1 5 1 9-1 12M33 28c4 4 6 8 3 12"],
160
- pinguim: ["M24 7c-8 0-12 8-12 18s4 15 12 15 12-5 12-15S32 7 24 7z",
161
- "M24 18c-4 0-6 5-6 11s2 8 6 8 6-2 6-8-2-11-6-11z", "c20.5 14 1.2", "c27.5 14 1.2",
162
- "M22 17l2 2 2-2", "M18 41h5M25 41h5"],
163
- };
164
-
165
- /**
166
- * O mascote em traço, para a tela vazia.
167
- * @param {object} op
168
- * @param {string} [op.mascote] id de lib/ui.js (primo, fox, cat, robo…); desconhecido = primo
169
- * @param {number} [op.tamanho] lado em px
170
- * @param {string} [op.rotulo] texto alternativo; vazio = decorativo
171
- */
172
- function linha(op) {
173
- op = op || {};
174
- var lado = op.tamanho || 48;
175
- var partes = LINHAS[op.mascote] || LINHAS.primo;
176
- var acessivel = op.rotulo
177
- ? ' role="img" aria-label="' + String(op.rotulo).replace(/"/g, "&quot;") + '"'
178
- : ' aria-hidden="true"';
179
- var corpo = partes.map(function (d) {
180
- if (d.charAt(0) === "c") { // "cX Y R" = círculo
181
- var n = d.slice(1).split(" ");
182
- return '<circle cx="' + n[0] + '" cy="' + n[1] + '" r="' + n[2] + '"/>';
183
- }
184
- return '<path d="' + d + '"/>';
185
- }).join("");
186
- return '<svg viewBox="0 0 48 48" width="' + lado + '" height="' + lado + '"' + acessivel
187
- + ' fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">'
188
- + corpo + "</svg>";
189
- }
190
-
191
- raiz.PrimoMarca = { svg: svg, logo: logo, linha: linha, LINHAS: LINHAS, favicon: favicon, MATRIZ: MATRIZ, CORPO: CORPO, DETALHE: DETALHE };
192
- })(typeof window !== "undefined" ? window : globalThis);