@praeko/studio-kit 0.0.0-stage → 0.1.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ Segue [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/) e [SemVer](https://semver.org/lang/pt-BR/).
4
+
5
+ ## [0.1.0] - 2026-11-07
6
+
7
+ Primeira versão publicada, extraída do projeto de divulgação onde nasceu. Publica `dist/` compilado (ESM + `.d.ts`); `react` e `remotion` são peers.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Marcone Santos
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/LICENSES.md ADDED
@@ -0,0 +1,38 @@
1
+ # Licenças do Praeko Studio / Licenses
2
+
3
+ Conferido em 07/11/2026 (verified on 2026-11-07). Este arquivo não é aconselhamento jurídico; vale o texto de cada fornecedor.
4
+
5
+ ## O código do Praeko Studio
6
+ Os pacotes `@praeko/studio`, `@praeko/studio-core` e `@praeko/studio-kit` são **MIT** (ver `LICENSE`, Copyright (c) 2026 Marcone Santos), como `@praeko/sdk` e `@praeko/cli`. Os efeitos sonoros (`pop`, `ding`, `thump`, `whoosh`) e o `avatar.png` do modelo de projeto foram criados para o Studio (sons sintetizados por `scripts/gerar-sfx.mjs`, sem amostras de terceiros) e seguem a mesma licença MIT. O pacote não traz fontes, músicas, imagens de banco nem arte de terceiros.
7
+
8
+ ## Aviso que você precisa ver (Remotion NÃO é MIT)
9
+ > **Remotion.** O Remotion é *source-available*, não open source. É **grátis** para pessoas físicas, organizações sem fins lucrativos, avaliação e empresas com **até 3 funcionários** (uso comercial incluído). Empresas com **4 ou mais pessoas** precisam da **Company License** (remotion.pro/license). Quem instala e roda o Remotion é **você**: a licença é sua, não do Praeko. O Remotion também vende planos para quem **automatiza renders por programa ou agente** (Creators, Automators); o FAQ deles não diz expressamente se um agente local que roda `remotion render` entra: **pergunte ao Remotion** antes de usar em escala. O Praeko Studio não copia nem modifica código do Remotion: usa-o como dependência (peer) instalada por você.
10
+ >
11
+ > **Remotion** is source-available, not open source. Free for individuals, non-profits, evaluation and companies of up to 3 employees (commercial use included); companies of 4+ need the Company License (remotion.pro/license). You install and run Remotion, so the license is yours. They also sell plans for programmatic/agent-driven rendering; their FAQ does not say whether a local agent running `remotion render` counts: ask Remotion before using at scale. Praeko Studio does not copy or modify Remotion code; it uses it as a dependency you install.
12
+
13
+ Este aviso aparece no `README`, na instalação (`praeko studio init`), em `praeko studio doctor` e em `praeko studio licencas` (`--aceitar` registra a leitura em `~/.config/praeko/studio/licencas.json`).
14
+
15
+ **Capas** são renderizadas com `remotion still`, mesmo com `--motor hyperframes`: hoje não existe projeto 100% livre de Remotion. Uma capa sem Remotion está no roteiro de trabalho (`docs/studio-produto.md`, item 9) e não foi prometida.
16
+
17
+ **Não prometemos "grátis para sempre":** as condições do Remotion podem mudar (a própria página avisa que a licença muda no Remotion 5.0). Reveja a licença ao subir de versão.
18
+
19
+ ## Dependências de terceiros
20
+ | Componente | Onde | Licença | Fonte |
21
+ |---|---|---|---|
22
+ | `remotion`, `@remotion/cli` (4.0.539) | instalados no **projeto** do usuário (peer de core/kit) | Remotion License (ver acima), não MIT | remotion.pro/license; github.com/remotion-dev/remotion (LICENSE.md) |
23
+ | `react`, `react-dom` (19.2.3) | projeto do usuário (peer) | MIT | package.json de cada pacote |
24
+ | `@praeko/studio-core`, `-kit` | projeto do usuário | MIT | LICENSE |
25
+ | `yaml` (2.9.1) | embutido no bundle de `@praeko/studio` | ISC | package.json |
26
+ | `@elevenlabs/elevenlabs-js` (2.x) | dependência de `@praeko/studio` | MIT | package.json |
27
+ | `hyperframes` (0.9.13, motor opcional) | baixado por `npx` na primeira vez que você usa `--motor hyperframes` | Apache-2.0 | github.com/heygen-com/hyperframes |
28
+ | `typescript`, `esbuild`, `@types/*` | só desenvolvimento/build | Apache-2.0 / MIT | package.json |
29
+ | ffmpeg / ffprobe | você instala | LGPL ou GPL, conforme a compilação | ffmpeg.org/legal.html |
30
+ | Chrome Headless Shell / Chromium | o Remotion baixa no primeiro render | licenças do Chromium/Google | remotion.dev/docs/miscellaneous/chrome-headless-shell |
31
+
32
+ ## Serviços e modelos (você contrata)
33
+ - **ElevenLabs**: seus termos e seu plano (clonagem de voz só com direito sobre a voz). A chave é sua; o Studio nunca a imprime.
34
+ - **VoiceStudio local** (opcional): o modelo OmniVoice é **CC-BY-NC (uso não comercial)**. Não é padrão em nenhuma configuração do Studio e **não deve ser usado em conteúdo monetizado**. Confira a licença de qualquer modelo local que usar.
35
+ - **YouTube, Instagram, TikTok**: termos e regras de conteúdo sintético de cada rede (veja `praeko studio docs publicar`).
36
+
37
+ ## Fontes e mídia
38
+ Nenhuma fonte é distribuída. O modelo de projeto usa fontes do sistema (`Arial Black`, `Menlo`) que o `doctor` confere; troque-as no `marca.json` por fontes abertas (OFL) se quiser que o vídeo saia igual em todos os sistemas. Música, imagens e clipes que você adicionar são responsabilidade sua (direitos e licenças).
package/README.md CHANGED
@@ -1,3 +1,20 @@
1
- # Temporary Holding Version
1
+ # @praeko/studio-kit
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Peças de cena do Praeko Studio (painel, caixa, linha, balão, código, janela, celular, moldura) e o episódio declarativo do episodio.yaml compilado. Biblioteca para projetos criados com [`@praeko/studio`](https://www.npmjs.com/package/@praeko/studio) (`praeko studio init` já instala e configura).
4
+
5
+ > **Licenças.** Este pacote é MIT e usa o **Remotion** como dependência (peer) que **você** instala. O Remotion **não é MIT**: grátis para pessoas, organizações sem fins lucrativos e empresas de até 3 funcionários; empresas com 4 ou mais pessoas precisam da Company License ([remotion.pro/license](https://www.remotion.pro/license)). Detalhes em [LICENSES.md](./LICENSES.md).
6
+ >
7
+ > **Licenses.** This package is MIT and uses **Remotion** as a peer dependency that **you** install. Remotion is **not MIT**: free for individuals, non-profits and companies of up to 3 employees; companies of 4+ need the Company License.
8
+
9
+ ## Instalar
10
+ ```sh
11
+ # npm
12
+ npm install @praeko/studio-kit remotion react
13
+ # yarn
14
+ yarn add @praeko/studio-kit remotion react
15
+ # pnpm
16
+ pnpm add @praeko/studio-kit remotion react
17
+ # bun
18
+ bun add @praeko/studio-kit remotion react
19
+ ```
20
+ Peers: `remotion` ^4.0.539 (todos os pacotes `@remotion/*` na mesma versão) e `react` ^19. Node 22 ou mais novo. Uso: `praeko studio docs episodio-yaml`.
@@ -0,0 +1,31 @@
1
+ import { Tema } from "@praeko/studio-core";
2
+ export type CapaLongoSpec = {
3
+ id: string;
4
+ titulo: [string, string];
5
+ gato?: string;
6
+ codigo?: {
7
+ titulo: string;
8
+ linhas: {
9
+ s: string;
10
+ hl?: boolean;
11
+ }[];
12
+ };
13
+ chips?: {
14
+ texto: string;
15
+ cor?: string;
16
+ }[];
17
+ cor?: string;
18
+ glow?: string;
19
+ };
20
+ export declare const CapaLongo16x9: React.FC<{
21
+ spec: CapaLongoSpec;
22
+ }>;
23
+ /** Vertical (Instagram): título em duas linhas, cartão de código, chips e o gato, dentro da `Moldura` das capas dos Shorts. */
24
+ export declare const CapaLongoVertical: React.FC<{
25
+ spec: CapaLongoSpec;
26
+ }>;
27
+ /** As duas Stills de uma capa de longo: `<id>` (1280×720) e `<id>Vertical` (1080×1920). */
28
+ export declare const CapasLongo: React.FC<{
29
+ spec: CapaLongoSpec;
30
+ tema: Tema;
31
+ }>;
@@ -0,0 +1,65 @@
1
+ import { EpData, Palavra, Tema } from "@praeko/studio-core";
2
+ type Cor = string;
3
+ export type Item = {
4
+ tipo: string;
5
+ quando?: string | [string, number];
6
+ em?: number;
7
+ pos?: {
8
+ left?: number;
9
+ right?: number;
10
+ top?: number;
11
+ bottom?: number;
12
+ w?: number;
13
+ h?: number;
14
+ };
15
+ [k: string]: any;
16
+ };
17
+ export type CenaSpec = {
18
+ inicio: number;
19
+ fim?: number;
20
+ rotulo?: string;
21
+ sons?: {
22
+ at: number;
23
+ f: "pop" | "ding" | "thump" | "whoosh";
24
+ v?: number;
25
+ }[];
26
+ layout?: "painel" | "livre";
27
+ titulo?: string;
28
+ itens?: Item[];
29
+ componente?: string;
30
+ };
31
+ export type EpSpec = {
32
+ id: string;
33
+ durS: number;
34
+ legendaPx?: number;
35
+ voz: string;
36
+ fundoLinhas?: string[];
37
+ golpes?: {
38
+ at: number;
39
+ tipo: "shake" | "zoom" | "flash" | "tudo";
40
+ }[];
41
+ fechamento: {
42
+ a: number;
43
+ cta: string;
44
+ };
45
+ cenas: CenaSpec[];
46
+ capa?: {
47
+ id: string;
48
+ componente?: string;
49
+ titulo?: [string, string, string?];
50
+ cor?: Cor;
51
+ glow?: string;
52
+ tam?: number;
53
+ itens?: Item[];
54
+ };
55
+ };
56
+ /** Monta o EpData: cada cena vira um componente (declarativo ou, com `componente`, um TSX do projeto). */
57
+ export declare function epDataDeSpec(spec: EpSpec, palavras: Palavra[], pecas?: Record<string, React.FC<any>>): EpData;
58
+ /** `<EpisodioDecl spec palavras tema pecas />` registra a Composition do episódio e a Still da capa. */
59
+ export declare const EpisodioDecl: React.FC<{
60
+ spec: EpSpec;
61
+ palavras: Palavra[];
62
+ tema: Tema;
63
+ pecas?: Record<string, React.FC<any>>;
64
+ }>;
65
+ export {};
@@ -0,0 +1,5 @@
1
+ export * from "./pecas";
2
+ export * from "./declarativo";
3
+ export * from "./longo";
4
+ export * from "./longo-decl";
5
+ export * from "./capa-longo";
package/dist/index.js ADDED
@@ -0,0 +1,491 @@
1
+ // src/pecas.tsx
2
+ import { Loop, OffthreadVideo, interpolate, spring, staticFile, useCurrentFrame, useVideoConfig, Img, AbsoluteFill } from "remotion";
3
+ import { FPS, pop, ramp, rgba, surge, useTema } from "@praeko/studio-core";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ var PainelD = ({ titulo, dur, children }) => {
6
+ const { destaque: LAMP, texto: INK, fonte: FONT } = useTema();
7
+ const frame = useCurrentFrame();
8
+ const { fps } = useVideoConfig();
9
+ const pop3 = spring({ frame, fps, config: { damping: 13, stiffness: 190 } });
10
+ const out = interpolate(frame, [dur * FPS - 6, dur * FPS], [1, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
11
+ return /* @__PURE__ */ jsxs(
12
+ "div",
13
+ {
14
+ style: {
15
+ position: "absolute",
16
+ left: 70,
17
+ right: 70,
18
+ top: 330,
19
+ height: 1e3,
20
+ display: "flex",
21
+ flexDirection: "column",
22
+ background: "rgba(20,17,15,.94)",
23
+ border: `4px solid ${LAMP}`,
24
+ borderRadius: 36,
25
+ boxShadow: "0 24px 60px rgba(0,0,0,.6)",
26
+ padding: "40px 48px",
27
+ fontFamily: FONT,
28
+ color: INK,
29
+ transform: `scale(${0.82 + 0.18 * pop3}) translateY(${(1 - pop3) * 60}px)`,
30
+ opacity: Math.min(1, pop3 * 1.6) * out,
31
+ overflow: "hidden",
32
+ boxSizing: "border-box"
33
+ },
34
+ children: [
35
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 38, letterSpacing: 5, color: LAMP, whiteSpace: "nowrap" }, children: titulo }),
36
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, display: "flex", flexDirection: "column", justifyContent: "center", gap: 40, minHeight: 0 }, children })
37
+ ]
38
+ }
39
+ );
40
+ };
41
+ var Caixa = ({ t, q, cor: cor4, children, mono, size = 48, dim, dash }) => {
42
+ const { caixa: CAIXA, texto: INK, fonte: FONT, mono: MONO } = useTema();
43
+ return /* @__PURE__ */ jsx("div", { style: { background: CAIXA, border: `4px ${dash ? "dashed" : "solid"} ${cor4}`, borderRadius: 22, padding: "18px 28px", fontFamily: mono ? MONO : FONT, fontSize: size, textAlign: "center", whiteSpace: "nowrap", color: INK, opacity: surge(t, q) * (dim ? 0.55 : 1), translate: `0px ${(1 - surge(t, q)) * 30}px` }, children });
44
+ };
45
+ var Linha = ({ t, q, cor: cor4, size = 46, children }) => {
46
+ const { caixa: CAIXA, texto: INK, fonte: FONT, destaque: LAMP } = useTema();
47
+ return /* @__PURE__ */ jsx("div", { style: { background: CAIXA, border: `4px solid ${cor4 ?? LAMP}`, borderRadius: 24, padding: "22px 30px", fontSize: size, opacity: surge(t, q), translate: `${(1 - surge(t, q)) * 70}px 0px`, whiteSpace: "nowrap", display: "flex", alignItems: "center", gap: 22, fontFamily: FONT, color: INK }, children });
48
+ };
49
+ var Big = ({ t, q, cor: cor4, size, mono, children }) => {
50
+ const { texto: INK, fonte: FONT, mono: MONO } = useTema();
51
+ return /* @__PURE__ */ jsx("div", { style: { fontFamily: mono ? MONO : FONT, fontSize: size, fontWeight: 900, color: cor4 ?? INK, textAlign: "center", lineHeight: 1.05, opacity: surge(t, q, 0.25), scale: String(pop(t, q)), whiteSpace: "nowrap" }, children });
52
+ };
53
+ var Balao = ({ t, q, cor: cor4, children, autor = "\u2014 um jogador, no chat" }) => {
54
+ const { caixa: CAIXA, texto: INK, fonte: FONT, mono: MONO, suave: MUTED } = useTema();
55
+ return /* @__PURE__ */ jsxs("div", { style: { position: "relative", background: CAIXA, border: `4px solid ${cor4}`, borderRadius: 28, padding: "28px 34px", fontFamily: FONT, fontSize: 46, lineHeight: 1.25, color: INK, textAlign: "center", opacity: surge(t, q), translate: `0px ${(1 - surge(t, q)) * 30}px` }, children: [
56
+ /* @__PURE__ */ jsx("span", { style: { position: "absolute", left: 24, top: -34, fontSize: 90, color: cor4, lineHeight: 1 }, children: "\u201C" }),
57
+ children,
58
+ /* @__PURE__ */ jsx("div", { style: { fontFamily: MONO, fontSize: 26, color: MUTED, marginTop: 16 }, children: autor })
59
+ ] });
60
+ };
61
+ var Codigo = ({ t, q, titulo, cor: cor4, linhas }) => {
62
+ const { caixa: CAIXA, texto: INK, mono: MONO } = useTema();
63
+ return /* @__PURE__ */ jsxs("div", { style: { background: CAIXA, borderRadius: 24, overflow: "hidden", border: `4px solid ${cor4}`, opacity: surge(t, q), translate: `0px ${(1 - surge(t, q)) * 30}px` }, children: [
64
+ /* @__PURE__ */ jsx("div", { style: { background: "#1c1830", padding: "12px 26px", fontFamily: MONO, fontSize: 26, color: "#8b86a8", whiteSpace: "nowrap" }, children: titulo }),
65
+ /* @__PURE__ */ jsx("div", { style: { fontFamily: MONO, fontSize: 30, lineHeight: 1.6, padding: "20px 0" }, children: linhas.map((l, i) => /* @__PURE__ */ jsx("div", { style: { whiteSpace: "pre", padding: "0 26px", color: l.cor || INK, background: l.marca ? `${l.cor}26` : "transparent", borderLeft: `6px solid ${l.marca ? l.cor : "transparent"}` }, children: l.s }, i)) })
66
+ ] });
67
+ };
68
+ var Janela = ({ t, q, src, duracao, de, left, top, w, reg = [0, 0, 1920, 1080], tag = "CENA REAL DO JOGO", dur }) => {
69
+ const { destaque: LAMP, texto: INK, erro: RUIM, mono: MONO } = useTema();
70
+ const s = w / reg[2], h = w * reg[3] / reg[2], o = surge(t, q, 0.5);
71
+ const push = 1 + 0.07 * ramp(t, q, q + dur);
72
+ const total = duracao - de;
73
+ return /* @__PURE__ */ jsxs("div", { style: { position: "absolute", left, top, width: w, height: h, borderRadius: 26, overflow: "hidden", border: `4px solid ${LAMP}`, boxShadow: `0 0 70px ${rgba(LAMP, 0.25)}, 0 24px 60px rgba(0,0,0,.6)`, opacity: o, translate: `0px ${(1 - o) * 40}px`, background: "#0b0b10" }, children: [
74
+ /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, scale: String(push), transformOrigin: "50% 60%" }, children: /* @__PURE__ */ jsx(Loop, { durationInFrames: Math.round(total * FPS), children: /* @__PURE__ */ jsx(OffthreadVideo, { src: staticFile(src), startFrom: Math.round(de * FPS), muted: true, style: { position: "absolute", left: -reg[0] * s, top: -reg[1] * s, width: 1920 * s, height: 1080 * s, imageRendering: "pixelated" } }) }) }),
75
+ /* @__PURE__ */ jsxs("div", { style: { position: "absolute", left: 14, bottom: 12, background: "rgba(10,8,6,.78)", color: INK, fontFamily: MONO, fontSize: 22, padding: "4px 14px", borderRadius: 10, display: "flex", gap: 10, alignItems: "center" }, children: [
76
+ /* @__PURE__ */ jsx("span", { style: { width: 12, height: 12, borderRadius: 6, background: RUIM, opacity: 0.5 + 0.5 * Math.abs(Math.sin(t * 4)) } }),
77
+ tag
78
+ ] })
79
+ ] });
80
+ };
81
+ var Celular = ({ t, q, src, duracao, de, left, top, w, dur }) => {
82
+ const { destaque: LAMP } = useTema();
83
+ const h = w * 1920 / 1080, o = surge(t, q, 0.5);
84
+ return /* @__PURE__ */ jsx("div", { style: { position: "absolute", left, top, width: w, height: h, borderRadius: 46, border: "10px solid #0b0b10", outline: `3px solid ${LAMP}`, overflow: "hidden", boxShadow: `0 0 70px ${rgba(LAMP, 0.22)}, 0 24px 60px rgba(0,0,0,.6)`, opacity: o, translate: `0px ${(1 - o) * 50}px`, background: "#0b0b10", scale: String(0.96 + 0.04 * ramp(t, q, q + dur)) }, children: /* @__PURE__ */ jsx(Loop, { durationInFrames: Math.round((duracao - de) * FPS), children: /* @__PURE__ */ jsx(OffthreadVideo, { src: staticFile(src), startFrom: Math.round(de * FPS), muted: true, style: { width: "100%", height: "100%", objectFit: "cover" } }) }) });
85
+ };
86
+ var Gato = ({ nome, tam = 220 }) => /* @__PURE__ */ jsx("div", { style: { background: "#1c1830", border: "6px solid #3a3358", borderRadius: 30, padding: 12 }, children: /* @__PURE__ */ jsx(Img, { src: staticFile(`gatos/gato-${nome}.png`), style: { width: tam, height: tam, imageRendering: "pixelated" } }) });
87
+ var Moldura = ({ glow, titulo, cor: cor4, children, tam = 130 }) => {
88
+ const { fundoCapa: BG, texto: INK, destaque: LAMP, fonte: FONT, handle } = useTema();
89
+ return /* @__PURE__ */ jsxs(AbsoluteFill, { style: { background: `radial-gradient(ellipse at 50% 44%, ${glow} 0%, rgba(0,0,0,0) 56%), ${BG}`, alignItems: "center", fontFamily: FONT, textAlign: "center" }, children: [
90
+ /* @__PURE__ */ jsxs("div", { style: { marginTop: 350, fontSize: tam, fontWeight: 900, color: INK, lineHeight: 1.02, textShadow: "0 8px 0 #000", whiteSpace: "nowrap" }, children: [
91
+ titulo[0],
92
+ /* @__PURE__ */ jsx("br", {}),
93
+ /* @__PURE__ */ jsx("span", { style: { color: cor4 }, children: titulo[1] }),
94
+ titulo[2] ? /* @__PURE__ */ jsxs(Fragment, { children: [
95
+ /* @__PURE__ */ jsx("br", {}),
96
+ titulo[2]
97
+ ] }) : null
98
+ ] }),
99
+ /* @__PURE__ */ jsx("div", { style: { marginTop: 130, display: "flex", flexDirection: "column", alignItems: "center", width: 1e3, transform: "scale(1.16)", transformOrigin: "top center" }, children }),
100
+ /* @__PURE__ */ jsx("div", { style: { position: "absolute", bottom: 400, fontSize: 52, color: LAMP, letterSpacing: 2 }, children: handle })
101
+ ] });
102
+ };
103
+
104
+ // src/declarativo.tsx
105
+ import { Composition, Still, useCurrentFrame as useCurrentFrame2 } from "remotion";
106
+ import { Episodio, FPS as FPS2, TemaProvider, mkAt, pop as pop2, ramp as ramp2, surge as surge2, useTema as useTema2 } from "@praeko/studio-core";
107
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
108
+ var cor = (T, c) => c ? T[c] && !c.startsWith("#") ? T[c] : c : void 0;
109
+ var estilo = (it, base = {}) => {
110
+ const p = it.pos;
111
+ return p ? { position: "absolute", left: p.left, right: p.right, top: p.top, bottom: p.bottom, width: p.w, height: p.h, ...base } : base;
112
+ };
113
+ var alinhar = { centro: "center", inicio: "flex-start", fim: "flex-end", esticar: "stretch" };
114
+ var Texto = ({ it, t }) => {
115
+ const T = useTema2();
116
+ const q = it.em ?? 0.3, linhas = String(it.texto).split("\n");
117
+ const base = {
118
+ ...it.fonte ? { fontFamily: it.fonte === "mono" ? T.mono : T.fonte } : {},
119
+ fontSize: it.tamanho ?? 40,
120
+ color: cor(T, it.cor) ?? T.texto,
121
+ ...it.alinhar === "esquerda" ? { textAlign: "left" } : { textAlign: "center" },
122
+ ...it.semFade ? {} : { opacity: surge2(t, q) },
123
+ ...it.altura ? { lineHeight: it.altura } : {},
124
+ ...it.peso ? { fontWeight: it.peso } : {},
125
+ ...it.pop ? { scale: String(pop2(t, q)) } : {},
126
+ ...it.semQuebra ? { whiteSpace: "nowrap" } : {}
127
+ };
128
+ return /* @__PURE__ */ jsx2("div", { style: estilo(it, base), children: linhas.map((l, i) => /* @__PURE__ */ jsxs2("span", { children: [
129
+ l,
130
+ i < linhas.length - 1 ? /* @__PURE__ */ jsx2("br", {}) : null
131
+ ] }, i)) });
132
+ };
133
+ var Barra = ({ it, t }) => {
134
+ const T = useTema2();
135
+ const q = it.em ?? 0.3, pr = it.preenche ?? {}, de = pr.de ?? 0, ate = pr.ate ?? 1;
136
+ const p = pr.duracao ? de + (ate - de) * ramp2(t, pr.inicio ?? q, (pr.inicio ?? q) + pr.duracao) : ate;
137
+ const g = (it.gradiente ?? [T.erro, T.erro]).map((c) => {
138
+ const [n, ...r] = String(c).split(" ");
139
+ return [cor(T, n), ...r].join(" ");
140
+ });
141
+ const fim = it.brilhoAoFim && p > 0.98;
142
+ const dentro = { width: `${p * 100}%`, height: "100%", background: it.gradienteAngulo === false ? g[0] : `linear-gradient(90deg, ${g.join(", ")})` };
143
+ return /* @__PURE__ */ jsx2("div", { style: estilo(it, { height: it.altura ?? 40, borderRadius: it.raio ?? 14, background: it.fundo ?? "#1d1812", ...it.borda === false ? {} : { border: `${it.borda ?? 3}px solid #3a2f22` }, overflow: "hidden", ...it.semFade ? {} : { opacity: surge2(t, q) }, ...fim ? { boxShadow: `0 0 40px ${cor(T, it.brilhoAoFim)}` } : {} }), children: /* @__PURE__ */ jsx2("div", { style: dentro }) });
144
+ };
145
+ var Barras = ({ it, t }) => {
146
+ const T = useTema2();
147
+ const q0 = it.em ?? 0.3;
148
+ return /* @__PURE__ */ jsx2("div", { style: estilo(it, { display: "flex", flexDirection: "column", gap: it.gap ?? 16 }), children: it.linhas.map((l, i) => {
149
+ const q = q0 + i * (it.passo ?? 0.5);
150
+ return /* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: 18, opacity: surge2(t, q) }, children: [
151
+ /* @__PURE__ */ jsx2("div", { style: { width: it.larguraRotulo ?? 190, fontFamily: T.mono, fontSize: 30, color: T.suave, whiteSpace: "nowrap" }, children: l.rotulo }),
152
+ /* @__PURE__ */ jsx2("div", { style: { height: 34, width: (it.larguraMax ?? 640) * (l.valor / it.max) * ramp2(t, q, q + 0.9), borderRadius: 10, background: `linear-gradient(90deg, #b9453a, ${cor(T, it.cor) ?? T.erro})` } }),
153
+ /* @__PURE__ */ jsx2("div", { style: { fontFamily: T.mono, fontSize: 30, color: cor(T, it.cor) ?? T.erro, fontWeight: 900 }, children: l.texto })
154
+ ] }, i);
155
+ }) });
156
+ };
157
+ var Render = ({ it, t, dur }) => {
158
+ const T = useTema2();
159
+ const q = it.em ?? 0.3;
160
+ const filhos = it.itens?.map((f, i) => /* @__PURE__ */ jsx2(Render, { it: f, t, dur }, i));
161
+ switch (it.tipo) {
162
+ case "texto":
163
+ return /* @__PURE__ */ jsx2(Texto, { it, t });
164
+ case "big":
165
+ return /* @__PURE__ */ jsx2("div", { style: estilo(it, it.pos ? { display: "flex", justifyContent: "center" } : {}), children: /* @__PURE__ */ jsx2(Big, { t, q, cor: cor(T, it.cor), size: it.tamanho, mono: it.mono, children: it.texto }) });
166
+ case "caixa":
167
+ return /* @__PURE__ */ jsx2(Caixa, { t, q, cor: cor(T, it.cor) ?? T.destaque, size: it.tamanho, mono: it.mono, dim: it.apagada, dash: it.tracejada, children: it.texto });
168
+ case "linha":
169
+ return /* @__PURE__ */ jsx2(Linha, { t, q, cor: cor(T, it.cor), size: it.tamanho, children: it.partes.map((p, i) => /* @__PURE__ */ jsx2("span", { style: { ...p.mono ? { fontFamily: T.mono } : {}, ...p.cor ? { color: cor(T, p.cor) } : {}, ...p.peso ? { fontWeight: p.peso } : {} }, children: p.texto }, i)) });
170
+ case "balao":
171
+ return /* @__PURE__ */ jsx2(Balao, { t, q, cor: cor(T, it.cor) ?? T.info, autor: it.autor, children: it.texto });
172
+ case "codigo":
173
+ return /* @__PURE__ */ jsx2(Codigo, { t, q, titulo: it.titulo, cor: cor(T, it.cor) ?? T.erro, linhas: it.linhas.map((l) => ({ ...l, cor: cor(T, l.cor) })) });
174
+ case "janela":
175
+ return /* @__PURE__ */ jsx2(Janela, { t, q, src: it.src, duracao: it.duracaoClipe, de: it.de ?? 0, left: it.pos.left, top: it.pos.top, w: it.pos.w, reg: it.reg, tag: it.tag, dur });
176
+ case "celular":
177
+ return /* @__PURE__ */ jsx2(Celular, { t, q, src: it.src, duracao: it.duracaoClipe, de: it.de ?? 0, left: it.pos.left, top: it.pos.top, w: it.pos.w, dur });
178
+ case "barra":
179
+ return /* @__PURE__ */ jsx2(Barra, { it, t });
180
+ case "barras":
181
+ return /* @__PURE__ */ jsx2(Barras, { it, t });
182
+ case "pilha":
183
+ return /* @__PURE__ */ jsx2("div", { style: estilo(it, { display: "flex", flexDirection: "column", gap: it.gap ?? 20, alignItems: alinhar[it.alinhar ?? "esticar"] }), children: filhos });
184
+ case "fila":
185
+ return /* @__PURE__ */ jsx2("div", { style: estilo(it, it.espalhar ? { display: "flex", justifyContent: "space-between" } : it.centrar === false ? { display: "flex", gap: it.gap ?? 20 } : { display: "flex", justifyContent: "center", alignItems: "center", gap: it.gap ?? 20, whiteSpace: "nowrap" }), children: filhos });
186
+ case "cartao": {
187
+ const o = surge2(t, q);
188
+ return /* @__PURE__ */ jsx2("div", { style: estilo(it, { background: T.caixa, border: `4px solid ${cor(T, it.cor) ?? T.destaque}`, borderRadius: 24, padding: "20px 24px", fontFamily: T.mono, fontSize: it.tamanho ?? 40, color: T.texto, opacity: o, translate: `${(1 - o) * 60}px 0px` }), children: it.linhas.map((l, i) => /* @__PURE__ */ jsxs2("span", { children: [
189
+ l.map((p, k) => /* @__PURE__ */ jsx2("span", { style: { ...p.cor ? { color: cor(T, p.cor) } : {}, ...p.peso ? { fontWeight: p.peso } : {} }, children: p.texto }, k)),
190
+ i < it.linhas.length - 1 ? /* @__PURE__ */ jsx2("br", {}) : null
191
+ ] }, i)) });
192
+ }
193
+ default:
194
+ return /* @__PURE__ */ jsxs2("div", { style: { color: "#f00", fontSize: 30 }, children: [
195
+ "tipo desconhecido: ",
196
+ it.tipo
197
+ ] });
198
+ }
199
+ };
200
+ var CenaDecl = ({ spec, painelDur, dur }) => {
201
+ const t = useCurrentFrame2() / FPS2;
202
+ const itens = (spec.itens ?? []).map((it, i) => /* @__PURE__ */ jsx2(Render, { it, t, dur }, i));
203
+ if ((spec.layout ?? "painel") === "livre") return /* @__PURE__ */ jsx2(Fragment2, { children: itens });
204
+ return /* @__PURE__ */ jsx2(PainelD, { titulo: spec.titulo ?? "", dur: painelDur, children: itens });
205
+ };
206
+ var resolver = (it, at) => {
207
+ const o = { ...it };
208
+ if (it.quando !== void 0) {
209
+ const [f, n] = Array.isArray(it.quando) ? it.quando : [it.quando, 0];
210
+ o.em = at(f, n) + (it.deslocar ?? 0);
211
+ delete o.quando;
212
+ }
213
+ if (it.itens) o.itens = it.itens.map((f) => resolver(f, at));
214
+ return o;
215
+ };
216
+ function epDataDeSpec(spec, palavras, pecas = {}) {
217
+ const S = spec.cenas.map((c) => c.inicio);
218
+ const fimDe = (i) => spec.cenas[i].fim ?? (i + 1 < S.length ? S[i + 1] : spec.fechamento.a);
219
+ const A = mkAt(palavras, S);
220
+ return {
221
+ id: spec.id,
222
+ durS: spec.durS,
223
+ legendaPx: spec.legendaPx,
224
+ voz: spec.voz,
225
+ palavras,
226
+ fundoLinhas: spec.fundoLinhas,
227
+ golpes: spec.golpes,
228
+ fechamento: spec.fechamento,
229
+ cenas: spec.cenas.map((c, i) => {
230
+ const painelDur = fimDe(i) - c.inicio;
231
+ const rs = { ...c, itens: c.itens?.map((it) => resolver(it, (f, n) => A(i)(f, n))) };
232
+ return {
233
+ a: c.inicio,
234
+ b: i + 1 < S.length ? S[i + 1] - 0.1 : fimDe(i) - 0.1,
235
+ rotulo: c.rotulo,
236
+ sons: c.sons,
237
+ C: c.componente ? pecas[c.componente] ?? (() => /* @__PURE__ */ jsxs2("div", { style: { color: "#f00", fontSize: 40 }, children: [
238
+ 'componente "',
239
+ c.componente,
240
+ '" n\xE3o registrado'
241
+ ] })) : ({ dur }) => /* @__PURE__ */ jsx2(CenaDecl, { spec: rs, painelDur, dur })
242
+ };
243
+ })
244
+ };
245
+ }
246
+ var CapaDecl = ({ spec }) => {
247
+ const T = useTema2();
248
+ return /* @__PURE__ */ jsx2(Moldura, { glow: spec.glow ?? "rgba(244,185,66,.16)", titulo: spec.titulo ?? ["", "", ""], cor: cor(T, spec.cor) ?? T.destaque, tam: spec.tam, children: (spec.itens ?? []).map((it, i) => /* @__PURE__ */ jsx2(Render, { it, t: 99, dur: 99 }, i)) });
249
+ };
250
+ var EpisodioDecl = ({ spec, palavras, tema, pecas = {} }) => {
251
+ const d = epDataDeSpec(spec, palavras, pecas);
252
+ const CapaC = spec.capa?.componente ? pecas[spec.capa.componente] : void 0;
253
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
254
+ /* @__PURE__ */ jsx2(Composition, { id: spec.id, component: () => /* @__PURE__ */ jsx2(TemaProvider, { tema, children: /* @__PURE__ */ jsx2(Episodio, { d }) }), durationInFrames: Math.round(spec.durS * FPS2), fps: FPS2, width: 1080, height: 1920 }),
255
+ spec.capa ? /* @__PURE__ */ jsx2(Still, { id: spec.capa.id, component: () => /* @__PURE__ */ jsx2(TemaProvider, { tema, children: CapaC ? /* @__PURE__ */ jsx2(CapaC, {}) : /* @__PURE__ */ jsx2(CapaDecl, { spec: spec.capa, palavras }) }), width: 1080, height: 1920 }) : null
256
+ ] });
257
+ };
258
+
259
+ // src/longo.tsx
260
+ import { useTema as useTema3 } from "@praeko/studio-core";
261
+ import { interpolate as interpolate2 } from "remotion";
262
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
263
+ var clamp = { extrapolateLeft: "clamp", extrapolateRight: "clamp" };
264
+ var surgeL = (t, q, d = 0.3) => interpolate2(t, [q, q + d], [0, 1], clamp);
265
+ var KW = /^(UPDATE|SET|WHERE|AND|INSERT|INTO|SELECT|FROM|CASE|WHEN|THEN|END|AS|VALUES|IS|NOT|NULL|const|await|if)$/;
266
+ var FN = /^(changes|abs|json_set|json_remove|json_extract)$/;
267
+ var colorize = (s, c) => s.split(/(--.*$|\/\/.*$|'[^']*'|\b\w+\b)/).map((p, i) => {
268
+ if (!p) return null;
269
+ let cor4 = c.texto;
270
+ if (/^(--|\/\/)/.test(p)) cor4 = c.suave;
271
+ else if (/^'/.test(p)) cor4 = c.ok;
272
+ else if (KW.test(p)) cor4 = c.destaque;
273
+ else if (/^\d+$/.test(p)) cor4 = "#7fb4ff";
274
+ else if (FN.test(p)) cor4 = c.info;
275
+ return /* @__PURE__ */ jsx3("span", { style: { color: cor4 }, children: p }, i);
276
+ });
277
+ var CodigoL = ({ titulo, lines, t, q, w, size = 32, left, top }) => {
278
+ const T = useTema3();
279
+ const o = surgeL(t, q);
280
+ return /* @__PURE__ */ jsxs3("div", { style: { position: "absolute", left, top, width: w, background: T.codigo, border: `3px solid #3a2f22`, borderRadius: 22, overflow: "hidden", opacity: o, transform: `translateY(${(1 - o) * 24}px)` }, children: [
281
+ /* @__PURE__ */ jsx3("div", { style: { background: "#262034", padding: "10px 26px", fontFamily: T.mono, fontSize: 26, color: "#9a95b8", whiteSpace: "nowrap" }, children: titulo }),
282
+ /* @__PURE__ */ jsx3("div", { style: { padding: "18px 0", fontFamily: T.mono, fontSize: size, lineHeight: 1.5 }, children: lines.map((l, i) => {
283
+ const on = l.hl ? t >= l.hl[0] && t < l.hl[1] : false;
284
+ return /* @__PURE__ */ jsx3("div", { style: { whiteSpace: "pre", padding: "0 26px", borderLeft: `6px solid ${on ? l.red ? T.erro : T.destaque : "transparent"}`, background: on ? l.red ? "rgba(255,107,94,.16)" : "rgba(244,185,66,.16)" : "transparent" }, children: colorize(l.s, T) || " " }, i);
285
+ }) })
286
+ ] });
287
+ };
288
+ var CartaoL = ({ t, q, left, top, w, h, cor: cor4, children }) => {
289
+ const T = useTema3();
290
+ const o = surgeL(t, q);
291
+ return /* @__PURE__ */ jsx3("div", { style: { position: "absolute", left, top, width: w, height: h, boxSizing: "border-box", background: T.caixaLongo ?? T.caixa, border: `4px solid ${cor4 ?? T.destaque}`, borderRadius: 24, padding: "20px 28px", fontFamily: T.fonte, color: T.texto, opacity: o, transform: `translateY(${(1 - o) * 26}px)`, display: "flex", flexDirection: "column", justifyContent: "center", gap: 8 }, children });
292
+ };
293
+ var ChipL = ({ t, q, left, top, cor: cor4, size = 34, children }) => {
294
+ const T = useTema3();
295
+ const o = surgeL(t, q);
296
+ return /* @__PURE__ */ jsx3("div", { style: { position: "absolute", left, top, opacity: o, transform: `scale(${1.15 - 0.15 * o})`, transformOrigin: "left center", fontFamily: T.fonte, fontSize: size, color: T.fundo, background: cor4 ?? T.destaque, borderRadius: 16, padding: "10px 26px", whiteSpace: "nowrap" }, children });
297
+ };
298
+ var TxtL = ({ t, q, left, top, w, size = 44, cor: cor4, align = "left", mono, children }) => {
299
+ const T = useTema3();
300
+ const o = surgeL(t, q);
301
+ return /* @__PURE__ */ jsx3("div", { style: { position: "absolute", left, top, width: w, opacity: o, transform: `translateY(${(1 - o) * 18}px)`, fontFamily: mono ? T.mono : T.fonte, fontSize: size, color: cor4 ?? T.texto, textAlign: align, lineHeight: 1.2 }, children });
302
+ };
303
+
304
+ // src/longo-decl.tsx
305
+ import { Composition as Composition2 } from "remotion";
306
+ import { FPS as FPS3, Longo, TemaProvider as TemaProvider3, mkAtG, useTema as useTemaLocal } from "@praeko/studio-core";
307
+ import { interpolate as interpolate3, Easing } from "remotion";
308
+
309
+ // src/capa-longo.tsx
310
+ import { Still as Still2 } from "remotion";
311
+ import { TemaProvider as TemaProvider2, rgba as rgba2, useTema as useTema4 } from "@praeko/studio-core";
312
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
313
+ var cor2 = (T, c) => c && !c.startsWith("#") && T[c] ? T[c] : c;
314
+ var Cartao = ({ spec, w, escala = 1 }) => {
315
+ const T = useTema4();
316
+ if (!spec.codigo) return null;
317
+ const px = (n) => n * escala;
318
+ return /* @__PURE__ */ jsxs4("div", { style: { width: w, background: T.codigo, border: `${px(5)}px solid ${T.destaque}`, borderRadius: px(24), overflow: "hidden", textAlign: "left" }, children: [
319
+ /* @__PURE__ */ jsx4("div", { style: { background: "#262034", padding: `${px(8)}px ${px(22)}px`, fontFamily: T.mono, fontSize: px(24), color: "#9a95b8" }, children: spec.codigo.titulo }),
320
+ /* @__PURE__ */ jsx4("div", { style: { padding: `${px(18)}px ${px(24)}px`, fontFamily: T.mono, fontSize: px(30), lineHeight: 1.5, whiteSpace: "pre" }, children: spec.codigo.linhas.map((l, i) => l.hl ? /* @__PURE__ */ jsx4("div", { style: { background: rgba2(T.destaque, 0.2), borderLeft: `${px(6)}px solid ${T.destaque}`, marginLeft: -px(24), paddingLeft: px(18) }, children: colorize(l.s, T) }, i) : /* @__PURE__ */ jsx4("div", { children: colorize(l.s, T) }, i)) })
321
+ ] });
322
+ };
323
+ var Chips = ({ spec, escala = 1, coluna }) => {
324
+ const T = useTema4();
325
+ return /* @__PURE__ */ jsx4("div", { style: { display: "flex", flexDirection: coluna ? "column" : "row", alignItems: coluna ? "flex-start" : void 0, gap: 24 * escala }, children: (spec.chips ?? []).map((c, i) => /* @__PURE__ */ jsx4("div", { style: { background: cor2(T, c.cor) ?? T.destaque, color: T.fundo, fontSize: 48 * escala, padding: `${10 * escala}px ${34 * escala}px`, borderRadius: 18 * escala }, children: c.texto }, i)) });
326
+ };
327
+ var CapaLongo16x9 = ({ spec }) => {
328
+ const T = useTema4();
329
+ return /* @__PURE__ */ jsxs4("div", { style: { width: 1280, height: 720, background: `radial-gradient(900px 500px at 75% 30%, ${rgba2(T.destaque, 0.16)}, ${T.fundo} 70%)`, position: "relative", fontFamily: T.fonte, color: T.texto, overflow: "hidden" }, children: [
330
+ /* @__PURE__ */ jsxs4("div", { style: { position: "absolute", left: 70, top: 70, fontSize: 92, lineHeight: 1.05, color: T.texto }, children: [
331
+ spec.titulo[0],
332
+ /* @__PURE__ */ jsx4("br", {}),
333
+ /* @__PURE__ */ jsx4("span", { style: { color: cor2(T, spec.cor) ?? T.destaque }, children: spec.titulo[1] })
334
+ ] }),
335
+ /* @__PURE__ */ jsx4("div", { style: { position: "absolute", left: 70, top: 310 }, children: /* @__PURE__ */ jsx4(Cartao, { spec, w: 700 }) }),
336
+ /* @__PURE__ */ jsx4("div", { style: { position: "absolute", left: 70, top: 560 }, children: /* @__PURE__ */ jsx4(Chips, { spec, escala: 0.9 }) }),
337
+ spec.gato ? /* @__PURE__ */ jsx4("div", { style: { position: "absolute", right: 70, top: 150 }, children: /* @__PURE__ */ jsx4(Gato, { nome: spec.gato, tam: 380 }) }) : null,
338
+ /* @__PURE__ */ jsx4("div", { style: { position: "absolute", right: 70, bottom: 50, fontSize: 34, color: T.destaque, letterSpacing: 2 }, children: T.handle })
339
+ ] });
340
+ };
341
+ var CapaLongoVertical = ({ spec }) => {
342
+ const T = useTema4();
343
+ return /* @__PURE__ */ jsx4(Moldura, { glow: spec.glow ?? rgba2(T.destaque, 0.16), titulo: [spec.titulo[0], spec.titulo[1]], cor: cor2(T, spec.cor) ?? T.destaque, tam: spec.titulo.some((l) => l.length > 11) ? 104 : 130, children: /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 34 }, children: [
344
+ /* @__PURE__ */ jsx4(Cartao, { spec, w: 780, escala: 1 }),
345
+ /* @__PURE__ */ jsxs4("div", { style: { display: "flex", alignItems: "center", gap: 30 }, children: [
346
+ spec.gato ? /* @__PURE__ */ jsx4(Gato, { nome: spec.gato, tam: 210 }) : null,
347
+ /* @__PURE__ */ jsx4(Chips, { spec, escala: 0.7, coluna: true })
348
+ ] })
349
+ ] }) });
350
+ };
351
+ var CapasLongo = ({ spec, tema }) => /* @__PURE__ */ jsxs4(Fragment3, { children: [
352
+ /* @__PURE__ */ jsx4(Still2, { id: spec.id, component: () => /* @__PURE__ */ jsx4(TemaProvider2, { tema, children: /* @__PURE__ */ jsx4(CapaLongo16x9, { spec }) }), width: 1280, height: 720 }),
353
+ /* @__PURE__ */ jsx4(Still2, { id: `${spec.id}Vertical`, component: () => /* @__PURE__ */ jsx4(TemaProvider2, { tema, children: /* @__PURE__ */ jsx4(CapaLongoVertical, { spec }) }), width: 1080, height: 1920 })
354
+ ] });
355
+
356
+ // src/longo-decl.tsx
357
+ import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
358
+ var cor3 = (T, c) => c && !c.startsWith("#") && T[c] ? T[c] : c;
359
+ var Partes = ({ it }) => {
360
+ const T = useTemaLocal();
361
+ if (!it.partes) return /* @__PURE__ */ jsx5(Fragment4, { children: it.texto });
362
+ return /* @__PURE__ */ jsx5(Fragment4, { children: it.partes.map((p, i) => /* @__PURE__ */ jsx5("span", { style: { ...p.cor ? { color: cor3(T, p.cor) } : {}, ...p.mono ? { fontFamily: T.mono } : {} }, children: p.texto }, i)) });
363
+ };
364
+ var clampL = { extrapolateLeft: "clamp", extrapolateRight: "clamp" };
365
+ var BarraL = ({ it, t, q, T }) => {
366
+ const p = it.pos ?? {}, dur = it.duracao ?? 1.4, v = it.valor ?? 1, h = it.altura ?? 46;
367
+ const o = surgeL(t, q), f = interpolate3(t, [q, q + dur], [0, v], { ...clampL, easing: Easing.out(Easing.cubic) });
368
+ const c = cor3(T, it.cor) ?? T.destaque;
369
+ return /* @__PURE__ */ jsxs5("div", { style: { position: "absolute", left: p.left, top: p.top, width: p.w, opacity: o, fontFamily: T.fonte }, children: [
370
+ it.rotulo ? /* @__PURE__ */ jsx5("div", { style: { fontSize: it.tamanho ?? 30, color: T.suave, marginBottom: 8 }, children: it.rotulo }) : null,
371
+ /* @__PURE__ */ jsxs5("div", { style: { position: "relative", height: h, borderRadius: h / 2, background: "rgba(255,255,255,.07)", border: `3px solid ${c}`, overflow: "hidden" }, children: [
372
+ /* @__PURE__ */ jsx5("div", { style: { position: "absolute", left: 0, top: 0, bottom: 0, width: `${f * 100}%`, background: `linear-gradient(90deg, ${c}88, ${c})` } }),
373
+ it.texto ? /* @__PURE__ */ jsx5("div", { style: { position: "absolute", right: 22, top: 0, bottom: 0, display: "flex", alignItems: "center", fontSize: Math.round(h * 0.55), color: T.texto, fontWeight: 900, textShadow: "0 2px 8px rgba(0,0,0,.8)" }, children: it.texto }) : null
374
+ ] })
375
+ ] });
376
+ };
377
+ var ContadorL = ({ it, t, q, T }) => {
378
+ const p = it.pos ?? {}, dur = it.duracao ?? 1.6, a = it.de ?? 0, b = it.ate ?? 0, casas = it.casas ?? 0;
379
+ const o = surgeL(t, q), n = interpolate3(t, [q, q + dur], [a, b], { ...clampL, easing: Easing.out(Easing.cubic) });
380
+ const s = n.toLocaleString("pt-BR", { minimumFractionDigits: casas, maximumFractionDigits: casas });
381
+ return /* @__PURE__ */ jsxs5("div", { style: { position: "absolute", left: p.left, top: p.top, width: p.w, opacity: o, fontFamily: it.mono ? T.mono : T.fonte, fontSize: it.tamanho ?? 96, fontWeight: 900, color: cor3(T, it.cor) ?? T.destaque, lineHeight: 1.1, textAlign: it.alinhar === "centro" ? "center" : "left" }, children: [
382
+ it.prefixo ?? "",
383
+ s,
384
+ it.sufixo ?? ""
385
+ ] });
386
+ };
387
+ function longoDeSpec(spec, palavras, T, pecas = {}) {
388
+ const at = mkAtG(palavras);
389
+ const q = (x) => typeof x === "number" ? x : typeof x === "string" ? at(x) : at(x.quando, x.nth ?? 0, x.depois ?? 0) + (x.mais ?? 0);
390
+ const Item = ({ it, t }) => {
391
+ const p = it.pos ?? {};
392
+ switch (it.tipo) {
393
+ case "codigo":
394
+ return /* @__PURE__ */ jsx5(
395
+ CodigoL,
396
+ {
397
+ titulo: it.titulo,
398
+ t,
399
+ q: q(it.quando),
400
+ w: p.w,
401
+ left: p.left,
402
+ top: p.top,
403
+ size: it.tamanho,
404
+ lines: it.linhas.map((l) => ({ s: l.s, ...l.hl ? { hl: [q(l.hl[0]), q(l.hl[1])] } : {}, ...l.vermelho ? { red: true } : {} }))
405
+ }
406
+ );
407
+ case "cartao":
408
+ return /* @__PURE__ */ jsx5(CartaoL, { t, q: q(it.quando), left: p.left, top: p.top, w: p.w, h: p.h, cor: cor3(T, it.cor), children: it.itens.map((f, i) => /* @__PURE__ */ jsx5(Item, { it: f, t }, i)) });
409
+ case "texto":
410
+ return /* @__PURE__ */ jsx5("div", { style: { fontSize: it.tamanho, color: cor3(T, it.cor), ...it.espacar ? { letterSpacing: it.espacar } : {}, ...it.quando !== void 0 ? { opacity: surgeL(t, q(it.quando)) } : {} }, children: /* @__PURE__ */ jsx5(Partes, { it }) });
411
+ case "chip":
412
+ return /* @__PURE__ */ jsx5(ChipL, { t, q: q(it.quando), left: p.left, top: p.top, cor: cor3(T, it.cor), size: it.tamanho, children: it.texto });
413
+ case "txt":
414
+ return /* @__PURE__ */ jsx5(TxtL, { t, q: q(it.quando), left: p.left, top: p.top, w: p.w, size: it.tamanho, cor: cor3(T, it.cor), align: it.alinhar === "centro" ? "center" : "left", mono: it.mono, children: /* @__PURE__ */ jsx5(Partes, { it }) });
415
+ case "video":
416
+ return /* @__PURE__ */ jsx5(Janela, { t, q: q(it.quando), src: it.src, duracao: it.duracaoClipe, de: it.de ?? 0, left: p.left, top: p.top, w: p.w, reg: it.reg ?? [0, 0, 1920, 1080], tag: it.tag ?? "jogo", dur: it.dur ?? 20 });
417
+ case "celular":
418
+ return /* @__PURE__ */ jsx5(Celular, { t, q: q(it.quando), src: it.src, duracao: it.duracaoClipe, de: it.de ?? 0, left: p.left, top: p.top, w: p.w, dur: it.dur ?? 20 });
419
+ case "barra":
420
+ return /* @__PURE__ */ jsx5(BarraL, { it, t, q: q(it.quando), T });
421
+ case "contador":
422
+ return /* @__PURE__ */ jsx5(ContadorL, { it, t, q: q(it.quando), T });
423
+ case "fluxo": {
424
+ const nos = it.nos ?? [], tam = it.tamanho ?? 34, c0 = cor3(T, it.cor) ?? T.destaque;
425
+ return /* @__PURE__ */ jsx5("div", { style: { position: "absolute", left: p.left, top: p.top, width: p.w, display: "flex", alignItems: "center", justifyContent: "space-between", fontFamily: T.fonte }, children: nos.map((n, i) => {
426
+ const o = surgeL(t, q(n.quando)), c = cor3(T, n.cor) ?? c0;
427
+ return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", alignItems: "center", flex: i < nos.length - 1 ? 1 : void 0 }, children: [
428
+ /* @__PURE__ */ jsx5("div", { style: { opacity: o, transform: `scale(${0.85 + 0.15 * o})`, background: T.caixaLongo ?? T.caixa, border: `4px solid ${c}`, borderRadius: 22, padding: "16px 26px", fontSize: tam, color: T.texto, textAlign: "center", lineHeight: 1.2, whiteSpace: "pre-line" }, children: n.texto }),
429
+ i < nos.length - 1 ? /* @__PURE__ */ jsx5("div", { style: { flex: 1, textAlign: "center", fontSize: tam * 1.2, color: T.suave, opacity: surgeL(t, q(nos[i + 1].quando)) }, children: "\u2192" }) : null
430
+ ] }, i);
431
+ }) });
432
+ }
433
+ default:
434
+ return /* @__PURE__ */ jsxs5("div", { style: { color: "#f00", fontSize: 30 }, children: [
435
+ "tipo desconhecido: ",
436
+ it.tipo
437
+ ] });
438
+ }
439
+ };
440
+ const S = spec.cenas.map((c) => c.inicio);
441
+ return {
442
+ id: spec.id,
443
+ durS: spec.durS,
444
+ voz: spec.voz,
445
+ palavras,
446
+ ...spec.fecho ? { fecho: { a: spec.fecho.inicio, texto: spec.fecho.texto, link: spec.fecho.link, imagem: spec.fecho.imagem } } : {},
447
+ cenas: spec.cenas.map((c, i) => ({
448
+ n: c.n ?? String(i + 1),
449
+ titulo: c.titulo,
450
+ a: c.inicio,
451
+ b: i + 1 < S.length ? S[i + 1] : spec.durS,
452
+ C: c.componente ? pecas[c.componente] ?? (() => /* @__PURE__ */ jsxs5("div", { style: { color: "#f00", fontSize: 40 }, children: [
453
+ 'componente "',
454
+ c.componente,
455
+ '" n\xE3o registrado'
456
+ ] })) : ({ t }) => /* @__PURE__ */ jsx5(Fragment4, { children: (c.itens ?? []).map((it, k) => /* @__PURE__ */ jsx5(Item, { it, t }, k)) })
457
+ }))
458
+ };
459
+ }
460
+ var LongoDecl = ({ spec, palavras, tema, pecas }) => {
461
+ const d = longoDeSpec(spec, palavras, tema, pecas);
462
+ return /* @__PURE__ */ jsxs5(Fragment4, { children: [
463
+ /* @__PURE__ */ jsx5(Composition2, { id: spec.id, component: () => /* @__PURE__ */ jsx5(TemaProvider3, { tema, children: /* @__PURE__ */ jsx5(Longo, { d }) }), durationInFrames: Math.round(spec.durS * FPS3), fps: FPS3, width: d.largura ?? 1920, height: d.altura ?? 1080 }),
464
+ spec.capa ? /* @__PURE__ */ jsx5(CapasLongo, { spec: spec.capa, tema }) : null
465
+ ] });
466
+ };
467
+ export {
468
+ Balao,
469
+ Big,
470
+ Caixa,
471
+ CapaLongo16x9,
472
+ CapaLongoVertical,
473
+ CapasLongo,
474
+ CartaoL,
475
+ Celular,
476
+ ChipL,
477
+ Codigo,
478
+ CodigoL,
479
+ EpisodioDecl,
480
+ Gato,
481
+ Janela,
482
+ Linha,
483
+ LongoDecl,
484
+ Moldura,
485
+ PainelD,
486
+ TxtL,
487
+ colorize,
488
+ epDataDeSpec,
489
+ longoDeSpec,
490
+ surgeL
491
+ };
@@ -0,0 +1,61 @@
1
+ import { LongoData, Palavra, Tema } from "@praeko/studio-core";
2
+ import { CapaLongoSpec } from "./capa-longo";
3
+ export type Tempo = number | string | {
4
+ quando: string;
5
+ nth?: number;
6
+ depois?: number;
7
+ mais?: number;
8
+ };
9
+ type Pos = {
10
+ left?: number;
11
+ top?: number;
12
+ w?: number;
13
+ h?: number;
14
+ };
15
+ export type ItemL = {
16
+ tipo: string;
17
+ quando?: Tempo;
18
+ pos?: Pos;
19
+ cor?: string;
20
+ tamanho?: number;
21
+ texto?: string;
22
+ partes?: {
23
+ texto: string;
24
+ cor?: string;
25
+ mono?: boolean;
26
+ }[];
27
+ [k: string]: any;
28
+ };
29
+ export type CenaLSpec = {
30
+ n?: string;
31
+ titulo: string;
32
+ inicio: number;
33
+ itens?: ItemL[];
34
+ componente?: string;
35
+ };
36
+ export type LongoSpec = {
37
+ id: string;
38
+ durS: number;
39
+ voz: string;
40
+ cenas: CenaLSpec[];
41
+ capa?: CapaLongoSpec;
42
+ fecho?: {
43
+ inicio: number;
44
+ texto?: string;
45
+ link?: string;
46
+ imagem?: string;
47
+ };
48
+ };
49
+ export declare function longoDeSpec(spec: LongoSpec, palavras: Palavra[], T: Tema, pecas?: Record<string, React.FC<{
50
+ t: number;
51
+ }>>): LongoData;
52
+ /** Registra a Composition do longo (1920×1080). */
53
+ export declare const LongoDecl: React.FC<{
54
+ spec: LongoSpec;
55
+ palavras: Palavra[];
56
+ tema: Tema;
57
+ pecas?: Record<string, React.FC<{
58
+ t: number;
59
+ }>>;
60
+ }>;
61
+ export {};
@@ -0,0 +1,57 @@
1
+ /** 0 → 1 a partir de `q` (linear, d = 0,3 s), como nos longos. */
2
+ export declare const surgeL: (t: number, q: number, d?: number) => number;
3
+ /** Colore uma linha de código/SQL (palavras-chave, funções, números, strings, comentários). */
4
+ export declare const colorize: (s: string, c: {
5
+ texto: string;
6
+ suave: string;
7
+ ok: string;
8
+ destaque: string;
9
+ info: string;
10
+ }) => (import("react/jsx-runtime").JSX.Element | null)[];
11
+ export type LinhaCodigo = {
12
+ s: string;
13
+ hl?: [number, number];
14
+ red?: boolean;
15
+ };
16
+ /** Bloco de código com linhas que acendem entre `hl[0]` e `hl[1]` (s globais). */
17
+ export declare const CodigoL: React.FC<{
18
+ titulo: string;
19
+ lines: LinhaCodigo[];
20
+ t: number;
21
+ q: number;
22
+ w: number;
23
+ size?: number;
24
+ left: number;
25
+ top: number;
26
+ }>;
27
+ export declare const CartaoL: React.FC<{
28
+ t: number;
29
+ q: number;
30
+ left: number;
31
+ top: number;
32
+ w: number;
33
+ h?: number;
34
+ cor?: string;
35
+ children: React.ReactNode;
36
+ }>;
37
+ export declare const ChipL: React.FC<{
38
+ t: number;
39
+ q: number;
40
+ left: number;
41
+ top: number;
42
+ cor?: string;
43
+ size?: number;
44
+ children: React.ReactNode;
45
+ }>;
46
+ export declare const TxtL: React.FC<{
47
+ t: number;
48
+ q: number;
49
+ left: number;
50
+ top: number;
51
+ w?: number;
52
+ size?: number;
53
+ cor?: string;
54
+ align?: "left" | "center";
55
+ mono?: boolean;
56
+ children: React.ReactNode;
57
+ }>;
@@ -0,0 +1,89 @@
1
+ /** Painel central de um Short: mesmo tamanho e lugar sempre (margem de 70 px, longe do rótulo e da legenda). */
2
+ export declare const PainelD: React.FC<{
3
+ titulo: string;
4
+ dur: number;
5
+ children: React.ReactNode;
6
+ }>;
7
+ export declare const Caixa: React.FC<{
8
+ t: number;
9
+ q: number;
10
+ cor: string;
11
+ children: React.ReactNode;
12
+ mono?: boolean;
13
+ size?: number;
14
+ dim?: boolean;
15
+ dash?: boolean;
16
+ }>;
17
+ export declare const Linha: React.FC<{
18
+ t: number;
19
+ q: number;
20
+ cor?: string;
21
+ size?: number;
22
+ children: React.ReactNode;
23
+ }>;
24
+ export declare const Big: React.FC<{
25
+ t: number;
26
+ q: number;
27
+ cor?: string;
28
+ size: number;
29
+ mono?: boolean;
30
+ children: React.ReactNode;
31
+ }>;
32
+ export declare const Balao: React.FC<{
33
+ t: number;
34
+ q: number;
35
+ cor: string;
36
+ children: React.ReactNode;
37
+ autor?: string;
38
+ }>;
39
+ /** Bloco de código com linhas marcadas (a cor da linha marcada vem em `cor`). */
40
+ export declare const Codigo: React.FC<{
41
+ t: number;
42
+ q: number;
43
+ titulo: string;
44
+ cor: string;
45
+ linhas: {
46
+ s: string;
47
+ cor?: string;
48
+ marca?: boolean;
49
+ }[];
50
+ }>;
51
+ /** Cena real do jogo (ou de qualquer app gravado) numa janela com moldura, recorte opcional e empurrão lento de câmera. */
52
+ export declare const Janela: React.FC<{
53
+ t: number;
54
+ q: number;
55
+ src: string;
56
+ duracao: number;
57
+ de: number;
58
+ left: number;
59
+ top: number;
60
+ w: number;
61
+ reg?: [number, number, number, number];
62
+ tag?: string;
63
+ dur: number;
64
+ }>;
65
+ /** Gravação vertical (celular) com moldura de aparelho. */
66
+ export declare const Celular: React.FC<{
67
+ t: number;
68
+ q: number;
69
+ src: string;
70
+ duracao: number;
71
+ de: number;
72
+ left: number;
73
+ top: number;
74
+ w: number;
75
+ dur: number;
76
+ }>;
77
+ /** Mascote em pixel art num cartão (arquivo `gatos/gato-<nome>.png`; troque o prefixo no projeto se o mascote for outro). */
78
+ export declare const Gato: React.FC<{
79
+ nome: string;
80
+ tam?: number;
81
+ }>;
82
+ /** Moldura das capas verticais (conteúdo entre y=260 e y=1660, recorte 3:4 da grade do Instagram). */
83
+ export declare const Moldura: React.FC<{
84
+ glow: string;
85
+ titulo: [string, string, string?];
86
+ cor: string;
87
+ children: React.ReactNode;
88
+ tam?: number;
89
+ }>;
package/package.json CHANGED
@@ -1,6 +1,64 @@
1
1
  {
2
2
  "name": "@praeko/studio-kit",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Peças de cena do Praeko Studio (painel, caixa, linha, balão, código, janela, celular, moldura) e o episódio declarativo que lê o episodio.yaml compilado. Biblioteca para projetos criados com `praeko studio init`.",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "praeko",
9
+ "video",
10
+ "shorts",
11
+ "remotion",
12
+ "captions",
13
+ "kit"
14
+ ],
15
+ "homepage": "https://praeko.app/docs",
16
+ "bugs": {
17
+ "url": "https://praeko.app/docs"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/Praeko/praeko-js.git",
22
+ "directory": "studio/packages/kit"
23
+ },
24
+ "main": "./dist/index.js",
25
+ "types": "./dist/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "default": "./dist/index.js"
30
+ },
31
+ "./package.json": "./package.json"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "README.md",
36
+ "CHANGELOG.md",
37
+ "LICENSE",
38
+ "LICENSES.md"
39
+ ],
40
+ "sideEffects": false,
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "scripts": {
45
+ "build": "node ../../../scripts/build-studio.mjs kit",
46
+ "prepack": "npm run build",
47
+ "typecheck": "tsc --noEmit -p tsconfig.json"
48
+ },
49
+ "peerDependencies": {
50
+ "@praeko/studio-core": "^0.1.0",
51
+ "react": "^19.0.0",
52
+ "remotion": "^4.0.539"
53
+ },
54
+ "devDependencies": {
55
+ "@praeko/studio-core": "*",
56
+ "@types/react": "19.2.7",
57
+ "react": "19.2.3",
58
+ "react-dom": "19.2.3",
59
+ "remotion": "4.0.539"
60
+ },
61
+ "engines": {
62
+ "node": ">=22"
63
+ }
64
+ }