@scenar/cli 0.5.0 → 0.7.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.
@@ -21,6 +21,12 @@ export interface EmbedEntryInput {
21
21
  canonicalWidth: number;
22
22
  /** Shell height in px, exposed as --scenar-shell-height. */
23
23
  shellHeight: number;
24
+ /**
25
+ * Wrap each step's content in `<ScenarioStage>` (backdrop + window shadow),
26
+ * and paint the backdrop in the static HTML so it shows before the entry
27
+ * script runs. Opt-in: staged embeds give up the transparent canvas.
28
+ */
29
+ stage?: boolean;
24
30
  }
25
31
 
26
32
  /**
@@ -69,6 +75,7 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
69
75
  "ViewportTransformLayer",
70
76
  "VIEWPORT_TRANSFORM_IDENTITY",
71
77
  ];
78
+ if (input.stage) reactImports.push("ScenarioStage");
72
79
  if (input.hasNarration) reactImports.push("useNarrationManifest");
73
80
  lines.push(`import { ${reactImports.join(", ")} } from "@scenar/react";`);
74
81
  lines.push(`import "@scenar/react/theme.css";`);
@@ -142,11 +149,15 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
142
149
 
143
150
  // --- App tree ---
144
151
  // The structure mirrors the in-app demo wiring exactly (see DemoViewport's
145
- // contract and ViewportTransformLayer's "Cursor must be a sibling" invariant):
152
+ // and ViewportTransformLayer's contracts):
146
153
  // DemoViewport(containerRef)
147
- // └ ViewportTransformLayer(transform)
154
+ // └ ViewportTransformLayer(transform, contentRef=cameraRef)
148
155
  // └ ScenarioPlayer(embed, onStepChange)
149
- // └ Cursor(target, containerRef) ← sibling, not a child
156
+ // └ Cursor(target, containerRef=cameraRef) ← child of the camera
157
+ // The cursor lives INSIDE the camera so it scales and pans with the content
158
+ // during viewport transitions — like a recorded pointer under a camera zoom.
159
+ // Both the cursor and the viewport-transition target math take the camera's
160
+ // contentRef so canonical coordinates stay correct at any camera state.
150
161
  // `useStepInteractions` reads the current step's `interactions` and drives the
151
162
  // cursor / ripple / drag / viewport state, synced to narration duration.
152
163
  const manifestExpr = input.hasNarration ? "_manifest" : "undefined";
@@ -156,6 +167,7 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
156
167
  lines.push(` const _manifest = useNarrationManifest(${JSON.stringify(input.scenarioId)}, _resolveManifestUrl);`);
157
168
  }
158
169
  lines.push(` const _containerRef = useRef<HTMLDivElement>(null);`);
170
+ lines.push(` const _cameraRef = useRef<HTMLDivElement>(null);`);
159
171
  lines.push(` const [_stepIndex, _setStepIndex] = useState(0);`);
160
172
  lines.push(` const [_cursorTarget, _setCursorTarget] = useState<string | undefined>(undefined);`);
161
173
  lines.push(` const [_showRipple, _setShowRipple] = useState(true);`);
@@ -173,6 +185,7 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
173
185
  lines.push(` stepIndex: _stepIndex,`);
174
186
  lines.push(` narrationManifest: ${manifestExpr},`);
175
187
  lines.push(` containerRef: _containerRef,`);
188
+ lines.push(` cameraRef: _cameraRef,`);
176
189
  lines.push(` setCursorTarget: _setCursorTarget,`);
177
190
  lines.push(` setShowRipple: _setShowRipple,`);
178
191
  lines.push(` setDragging: _setDragging,`);
@@ -190,13 +203,19 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
190
203
  lines.push(` return (`);
191
204
  lines.push(` <div className={_rootClass}>`);
192
205
  lines.push(` ${open}`);
206
+ // Staged embeds wrap each step's content — not the player chrome — in the
207
+ // stage, inside the camera, so a zoom scales the whole recording, backdrop
208
+ // included, while controls keep overlaying the stable content box.
209
+ const stepRender = input.stage
210
+ ? `{(data: any, stepIndex: number) => <ScenarioStage>{renderStep(data, stepIndex)}</ScenarioStage>}`
211
+ : `{(data: any, stepIndex: number) => renderStep(data, stepIndex)}`;
193
212
  lines.push(` <DemoViewport containerRef={_containerRef} canonicalWidth={${input.canonicalWidth}} shellHeight={${input.shellHeight}}>`);
194
- lines.push(` <ViewportTransformLayer transform={_viewport}>`);
213
+ lines.push(` <ViewportTransformLayer transform={_viewport} contentRef={_cameraRef}>`);
195
214
  lines.push(` <ScenarioPlayer bundle={_bundle} embed onStepChange={_handleStepChange}>`);
196
- lines.push(` {(data: any, stepIndex: number) => renderStep(data, stepIndex)}`);
215
+ lines.push(` ${stepRender}`);
197
216
  lines.push(` </ScenarioPlayer>`);
217
+ lines.push(` <Cursor target={_cursorTarget} containerRef={_cameraRef} showRipple={_showRipple} isDragging={_dragging} />`);
198
218
  lines.push(` </ViewportTransformLayer>`);
199
- lines.push(` <Cursor target={_cursorTarget} containerRef={_containerRef} showRipple={_showRipple} isDragging={_dragging} />`);
200
219
  lines.push(` </DemoViewport>`);
201
220
  lines.push(` ${close}`);
202
221
  lines.push(` </div>`);
@@ -213,6 +232,41 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
213
232
  return lines.join("\n");
214
233
  }
215
234
 
235
+ /**
236
+ * Staged pre-paint backdrop — a hand-maintained mirror of the
237
+ * `--scenar-backdrop-*` tokens in @scenar/react's theme/tokens.css (the token
238
+ * stylesheet is not loadable before the entry script runs, so the values are
239
+ * duplicated here by necessity). The token names, hex values, and gradient
240
+ * geometry are kept byte-identical to tokens.css; the drift-lock test in
241
+ * `pack-generate-embed-entry.test.ts` reads tokens.css and fails the build
242
+ * of anyone who retunes one side without the other.
243
+ *
244
+ * The theme split lives in the *colors* via `light-dark()` — a <color>-only
245
+ * function, so each custom property resolves against the propagated
246
+ * `color-scheme` while the mesh geometry is written once. (An earlier
247
+ * revision wrapped whole gradients in `light-dark()`, which is invalid CSS
248
+ * that browsers drop silently — the pre-paint never actually painted.)
249
+ */
250
+ export const STAGE_BACKDROP_COLORS: ReadonlyArray<{
251
+ readonly token: string;
252
+ readonly light: string;
253
+ readonly dark: string;
254
+ }> = [
255
+ { token: "--scenar-backdrop-glow-1", light: "#b7d4f2", dark: "#1c3a63" },
256
+ { token: "--scenar-backdrop-glow-2", light: "#e3d0ec", dark: "#372a5e" },
257
+ { token: "--scenar-backdrop-glow-3", light: "#b4c4ea", dark: "#142647" },
258
+ { token: "--scenar-backdrop-base-1", light: "#e4ecf7", dark: "#101828" },
259
+ { token: "--scenar-backdrop-base-2", light: "#e6e1f0", dark: "#14122a" },
260
+ ];
261
+
262
+ /** Mesh geometry, one layer per line — mirrors `--scenar-backdrop` in tokens.css. */
263
+ export const STAGE_BACKDROP_MESH: readonly string[] = [
264
+ "radial-gradient(120% 100% at 12% 8%, var(--scenar-backdrop-glow-1) 0%, transparent 55%)",
265
+ "radial-gradient(110% 95% at 88% 12%, var(--scenar-backdrop-glow-2) 0%, transparent 55%)",
266
+ "radial-gradient(130% 110% at 70% 100%, var(--scenar-backdrop-glow-3) 0%, transparent 60%)",
267
+ "linear-gradient(135deg, var(--scenar-backdrop-base-1) 0%, var(--scenar-backdrop-base-2) 100%)",
268
+ ];
269
+
216
270
  /**
217
271
  * Produce the index.html that boots the embed. The entry is referenced as an
218
272
  * external module script (`<script type="module" src>`) — never inline — so the
@@ -228,8 +282,33 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
228
282
  * opaque white canvas — the historical "white band under the embed".) The
229
283
  * margin reset guards against a host stylesheet-less load; the entry paints a
230
284
  * theme surface only when the page is top-level (see generateEmbedEntry).
285
+ *
286
+ * Staged embeds (`--stage`) deliberately trade that transparency away: the
287
+ * scenario floats on a backdrop, so the page pre-paints the same backdrop in
288
+ * static CSS — before the entry script runs — and there is no flash when the
289
+ * React-rendered stage takes over. See STAGE_BACKDROP_COLORS for the
290
+ * mirroring contract. Do NOT pin `colorScheme` here either — the
291
+ * `light dark` meta stays authoritative.
231
292
  */
232
- export function generateEmbedHtml(scenarioId: string, entryFileName: string): string {
293
+ export function generateEmbedHtml(
294
+ scenarioId: string,
295
+ entryFileName: string,
296
+ stage = false,
297
+ ): string {
298
+ const bodyBackground = stage
299
+ ? [
300
+ ` body {`,
301
+ ...STAGE_BACKDROP_COLORS.map(
302
+ ({ token, light, dark }) => ` ${token}: light-dark(${light}, ${dark});`,
303
+ ),
304
+ ` background:`,
305
+ ...STAGE_BACKDROP_MESH.map(
306
+ (layer, i) =>
307
+ ` ${layer}${i === STAGE_BACKDROP_MESH.length - 1 ? ";" : ","}`,
308
+ ),
309
+ ` }`,
310
+ ]
311
+ : [];
233
312
  return [
234
313
  `<!doctype html>`,
235
314
  `<html lang="en">`,
@@ -240,6 +319,7 @@ export function generateEmbedHtml(scenarioId: string, entryFileName: string): st
240
319
  ` <title>${escapeHtml(scenarioId)}</title>`,
241
320
  ` <style>`,
242
321
  ` html, body { margin: 0; background: transparent; }`,
322
+ ...bodyBackground,
243
323
  ` </style>`,
244
324
  ` </head>`,
245
325
  ` <body>`,
@@ -9,6 +9,12 @@ export interface RunPackOptions {
9
9
  readonly width?: number;
10
10
  /** Shell/container height in px (default: {@link DEFAULT_VIEWPORT}.height). */
11
11
  readonly shellHeight?: number;
12
+ /**
13
+ * Float the scenario on a backdrop with a window shadow (screen-recording
14
+ * framing). Opt-in: a staged embed paints its own background, giving up
15
+ * the default transparent canvas that lets the host page show through.
16
+ */
17
+ readonly stage?: boolean;
12
18
  /** Keep the generated entry directory for debugging (default: false). */
13
19
  readonly keepTemp?: boolean;
14
20
  /** Progress sink for mid-operation messages. */
@@ -1 +1 @@
1
- {"version":3,"file":"run-pack.d.ts","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"AAOA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAM5B,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAyF1E"}
1
+ {"version":3,"file":"run-pack.d.ts","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"AAOA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAM5B,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA2F1E"}
@@ -43,6 +43,7 @@ export async function runPack(options) {
43
43
  onLog(`Narration: ${hasNarration ? "yes (manifest found)" : "none"}`);
44
44
  onLog(`Output: ${outDir}`);
45
45
  // 1. Generate the browser entry + index.html into the temp dir.
46
+ const stage = options.stage ?? false;
46
47
  const entrySource = generateEmbedEntry({
47
48
  scenarioDir,
48
49
  renderFilePath,
@@ -51,12 +52,13 @@ export async function runPack(options) {
51
52
  providersPath,
52
53
  canonicalWidth: width,
53
54
  shellHeight,
55
+ stage,
54
56
  });
55
57
  await mkdir(tempDir, { recursive: true });
56
58
  const entryFileName = "entry.tsx";
57
59
  const entryHtmlPath = join(tempDir, "index.html");
58
60
  await writeFile(join(tempDir, entryFileName), entrySource, "utf-8");
59
- await writeFile(entryHtmlPath, generateEmbedHtml(scenarioId, entryFileName), "utf-8");
61
+ await writeFile(entryHtmlPath, generateEmbedHtml(scenarioId, entryFileName, stage), "utf-8");
60
62
  // 2. Build the static bundle with Vite.
61
63
  onLog("Bundling embed with Vite...");
62
64
  await runViteBuild({ root: tempDir, outDir, entryHtmlPath });
@@ -1 +1 @@
1
- {"version":3,"file":"run-pack.js","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-pack.js","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,12 @@ export interface RunPackOptions {
27
27
  readonly width?: number;
28
28
  /** Shell/container height in px (default: {@link DEFAULT_VIEWPORT}.height). */
29
29
  readonly shellHeight?: number;
30
+ /**
31
+ * Float the scenario on a backdrop with a window shadow (screen-recording
32
+ * framing). Opt-in: a staged embed paints its own background, giving up
33
+ * the default transparent canvas that lets the host page show through.
34
+ */
35
+ readonly stage?: boolean;
30
36
  /** Keep the generated entry directory for debugging (default: false). */
31
37
  readonly keepTemp?: boolean;
32
38
  /** Progress sink for mid-operation messages. */
@@ -86,6 +92,7 @@ export async function runPack(options: RunPackOptions): Promise<PackResult> {
86
92
  onLog(`Output: ${outDir}`);
87
93
 
88
94
  // 1. Generate the browser entry + index.html into the temp dir.
95
+ const stage = options.stage ?? false;
89
96
  const entrySource = generateEmbedEntry({
90
97
  scenarioDir,
91
98
  renderFilePath,
@@ -94,12 +101,13 @@ export async function runPack(options: RunPackOptions): Promise<PackResult> {
94
101
  providersPath,
95
102
  canonicalWidth: width,
96
103
  shellHeight,
104
+ stage,
97
105
  });
98
106
  await mkdir(tempDir, { recursive: true });
99
107
  const entryFileName = "entry.tsx";
100
108
  const entryHtmlPath = join(tempDir, "index.html");
101
109
  await writeFile(join(tempDir, entryFileName), entrySource, "utf-8");
102
- await writeFile(entryHtmlPath, generateEmbedHtml(scenarioId, entryFileName), "utf-8");
110
+ await writeFile(entryHtmlPath, generateEmbedHtml(scenarioId, entryFileName, stage), "utf-8");
103
111
 
104
112
  // 2. Build the static bundle with Vite.
105
113
  onLog("Bundling embed with Vite...");
@@ -19,7 +19,13 @@ export interface Viewport {
19
19
  /** Shell/container height in px (ViewportConfig.height; CLI `--shell-height`). */
20
20
  readonly height: number;
21
21
  }
22
- /** Defaults matching `DemoViewport`: 896 canonical width, 480 shell height. */
22
+ /**
23
+ * Pack-time defaults. The width matches `DemoViewport`'s default canonical
24
+ * width (896); the height is the CLI's own default — `DemoViewport` has no
25
+ * height default of its own, and the baked `--scenar-shell-height` variable
26
+ * overrides every per-shell fallback in `@scenar/react`'s `shells/tokens.ts`
27
+ * (380/420/460/500), so this number is what framed shells actually render at.
28
+ */
23
29
  export declare const DEFAULT_VIEWPORT: Viewport;
24
30
  /**
25
31
  * Narrow unknown JSON into a {@link Viewport}, or null if it is missing or
@@ -1 +1 @@
1
- {"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,QAAQ;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,QAAsC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAK7D"}
1
+ {"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,QAAQ;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAsC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAK7D"}
@@ -1,4 +1,10 @@
1
- /** Defaults matching `DemoViewport`: 896 canonical width, 480 shell height. */
1
+ /**
2
+ * Pack-time defaults. The width matches `DemoViewport`'s default canonical
3
+ * width (896); the height is the CLI's own default — `DemoViewport` has no
4
+ * height default of its own, and the baked `--scenar-shell-height` variable
5
+ * overrides every per-shell fallback in `@scenar/react`'s `shells/tokens.ts`
6
+ * (380/420/460/500), so this number is what framed shells actually render at.
7
+ */
2
8
  export const DEFAULT_VIEWPORT = { width: 896, height: 480 };
3
9
  /**
4
10
  * Narrow unknown JSON into a {@link Viewport}, or null if it is missing or
@@ -1 +1 @@
1
- {"version":3,"file":"viewport.js","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAsBA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAa,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAEtE;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAgC,CAAC;IAC3D,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AAC3E,CAAC"}
1
+ {"version":3,"file":"viewport.js","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAsBA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAa,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAEtE;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAgC,CAAC;IAC3D,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AAC3E,CAAC"}
@@ -20,7 +20,13 @@ export interface Viewport {
20
20
  readonly height: number;
21
21
  }
22
22
 
23
- /** Defaults matching `DemoViewport`: 896 canonical width, 480 shell height. */
23
+ /**
24
+ * Pack-time defaults. The width matches `DemoViewport`'s default canonical
25
+ * width (896); the height is the CLI's own default — `DemoViewport` has no
26
+ * height default of its own, and the baked `--scenar-shell-height` variable
27
+ * overrides every per-shell fallback in `@scenar/react`'s `shells/tokens.ts`
28
+ * (380/420/460/500), so this number is what framed shells actually render at.
29
+ */
24
30
  export const DEFAULT_VIEWPORT: Viewport = { width: 896, height: 480 };
25
31
 
26
32
  /**