@popcraft/cli 0.7.1 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/popcraft.mjs +1586 -1260
  2. package/package.json +2 -2
package/dist/popcraft.mjs CHANGED
@@ -1173,7 +1173,7 @@ function operations(spec = openapi) {
1173
1173
  }
1174
1174
  async function call(target2, method, path, opts = {}) {
1175
1175
  const qs = new URLSearchParams(opts.query ?? {}).toString();
1176
- const headers = { "user-agent": `popcraft-cli/${"0.7.1"}`, ...opts.headers };
1176
+ const headers = { "user-agent": `popcraft-cli/${"0.8.1"}`, ...opts.headers };
1177
1177
  if (target2.token) headers.authorization = `Bearer ${target2.token}`;
1178
1178
  if (opts.contentType) headers["content-type"] = opts.contentType;
1179
1179
  try {
@@ -2832,8 +2832,8 @@ function nodeFlips(node2) {
2832
2832
  function localMatrix(node2, ignoreFlips = false, shiftX = 0, shiftY = 0) {
2833
2833
  const w = node2.width, h = node2.height;
2834
2834
  const ax = restValue(node2, "anchorX"), ay = restValue(node2, "anchorY");
2835
- const rad2 = (node2.rotation || 0) * Math.PI / 180;
2836
- const cos = rad2 !== 0 ? Math.cos(rad2) : 1, sin = rad2 !== 0 ? Math.sin(rad2) : 0;
2835
+ const rad3 = (node2.rotation || 0) * Math.PI / 180;
2836
+ const cos = rad3 !== 0 ? Math.cos(rad3) : 1, sin = rad3 !== 0 ? Math.sin(rad3) : 0;
2837
2837
  const sx = restValue(node2, "scaleX") * (!ignoreFlips && node2.flipHorizontal ? -1 : 1);
2838
2838
  const sy = restValue(node2, "scaleY") * (!ignoreFlips && node2.flipVertical ? -1 : 1);
2839
2839
  const px5 = node2.x + ax * w + restValue(node2, "translateX");
@@ -32029,6 +32029,9 @@ var init_en2 = __esm({
32029
32029
  "command:show.setAdvance": "Set how the show advances",
32030
32030
  "command:site.setBreakpoints": "Breakpoints",
32031
32031
  "command:site.setBreakpoints#defaults": "Reset breakpoints to Desktop, Tablet and Phone",
32032
+ "command:site.setGpuTransitions": "Draw 3D transitions with WebGPU",
32033
+ "command:site.setGpuTransitions#off": "Draw 3D transitions in CSS only",
32034
+ "command:site.setGpuTransitions#on": "Draw 3D transitions with WebGPU",
32032
32035
  "command:site.setRoute": "Page address",
32033
32036
  "command:text.detach": "Detach text from path or shape",
32034
32037
  "command:text.flowIntoShape": "Flow text into shape",
@@ -34250,6 +34253,7 @@ var init_en2 = __esm({
34250
34253
  "prototypePanel.pagePrototypeSettings": "Page Prototype Settings",
34251
34254
  "prototypePanel.pickCollection": "\u2014 Pick collection \u2014",
34252
34255
  "prototypePanel.pickVariable": "\u2014 Pick variable \u2014",
34256
+ "prototypePanel.picture": "Picture",
34253
34257
  "prototypePanel.pixel7": "Pixel 7",
34254
34258
  "prototypePanel.press": "Press",
34255
34259
  "prototypePanel.previousMarker": "Previous marker",
@@ -35174,6 +35178,43 @@ var init_en2 = __esm({
35174
35178
  "topBar.webPreview": "Web preview",
35175
35179
  "topBar.zoomToFit": "Zoom to fit",
35176
35180
  "topBar.zoomToFrame": "Zoom to frame",
35181
+ "transition:CAROUSEL_FROM_LEFT": "Carousel \u2190 left",
35182
+ "transition:CAROUSEL_FROM_RIGHT": "Carousel \u2192 right",
35183
+ "transition:CIRCLE_WIPE": "Circle wipe",
35184
+ "transition:CUBE_FROM_BOTTOM": "Cube \u2193 bottom",
35185
+ "transition:CUBE_FROM_LEFT": "Cube \u2190 left",
35186
+ "transition:CUBE_FROM_RIGHT": "Cube \u2192 right",
35187
+ "transition:CUBE_FROM_TOP": "Cube \u2191 top",
35188
+ "transition:CUT": "Cut",
35189
+ "transition:DEPTH_PULL": "Depth pull",
35190
+ "transition:DEPTH_PUSH": "Depth push",
35191
+ "transition:DISSOLVE": "Dissolve",
35192
+ "transition:FLIP_HORIZONTAL": "Flip \u2194",
35193
+ "transition:FLIP_VERTICAL": "Flip \u2195",
35194
+ "transition:INSTANT": "Instant",
35195
+ "transition:IRIS": "Iris",
35196
+ "transition:MOVE_OUT_TO_BOTTOM": "Move out \u2193 bottom",
35197
+ "transition:MOVE_OUT_TO_LEFT": "Move out \u2190 left",
35198
+ "transition:MOVE_OUT_TO_RIGHT": "Move out \u2192 right",
35199
+ "transition:MOVE_OUT_TO_TOP": "Move out \u2191 top",
35200
+ "transition:PUSH_FROM_BOTTOM": "Push \u2193 bottom",
35201
+ "transition:PUSH_FROM_LEFT": "Push \u2190 left",
35202
+ "transition:PUSH_FROM_RIGHT": "Push \u2192 right",
35203
+ "transition:PUSH_FROM_TOP": "Push \u2191 top",
35204
+ "transition:SLIDE_FROM_BOTTOM": "Slide in \u2193 bottom",
35205
+ "transition:SLIDE_FROM_LEFT": "Slide in \u2190 left",
35206
+ "transition:SLIDE_FROM_RIGHT": "Slide in \u2192 right",
35207
+ "transition:SLIDE_FROM_TOP": "Slide in \u2191 top",
35208
+ "transition:SMART_ANIMATE": "Smart animate",
35209
+ "transition:STACK_IN": "Stack in",
35210
+ "transition:STACK_OUT": "Stack out",
35211
+ "transition:SWING_CLOSE": "Swing close",
35212
+ "transition:SWING_OPEN": "Swing open",
35213
+ "transition:WHIP_LEFT": "Whip pan \u2190 left",
35214
+ "transition:WHIP_RIGHT": "Whip pan \u2192 right",
35215
+ "transition:ZOOM_THROUGH": "Zoom through",
35216
+ "transitions.group3d": "3D",
35217
+ "transitions.groupFlat": "Flat",
35177
35218
  "transportBar.aMotionComponentEveryInstance": "{frameName}: a motion component \u2014 every instance plays this timeline",
35178
35219
  "transportBar.animateTheSelectedLayersKeyframe": "Animate the selected layers: keyframe, or a preset",
35179
35220
  "transportBar.backToTheKeyframes": "Back to the keyframes",
@@ -85937,7 +85978,6 @@ function repairDocumentPaints(doc2) {
85937
85978
  var broken;
85938
85979
  var init_paint_repair = __esm({
85939
85980
  "lib/document/paint-repair.ts"() {
85940
- "use strict";
85941
85981
  init_shader_graph();
85942
85982
  broken = (p2) => {
85943
85983
  if (!p2 || typeof p2 !== "object") return false;
@@ -87162,6 +87202,7 @@ function relinkCopies(doc2, copies) {
87162
87202
  var TEXT_PATH_SOURCE_TYPES, isPathSource;
87163
87203
  var init_text_links = __esm({
87164
87204
  "lib/document/text-links.ts"() {
87205
+ "use strict";
87165
87206
  init_transform();
87166
87207
  TEXT_PATH_SOURCE_TYPES = ["VECTOR", "ELLIPSE", "RECTANGLE", "POLYGON", "STAR", "LINE", "ARROW", "FRAME"];
87167
87208
  isPathSource = (n) => !!n && TEXT_PATH_SOURCE_TYPES.includes(n.type);
@@ -87522,7 +87563,7 @@ function applyAutoLayout(doc2) {
87522
87563
  let rowSizes = frame2.layoutGridRowSizes || [];
87523
87564
  if (rows === "AUTO") {
87524
87565
  actualRows = Math.max(1, Math.ceil(childIds.length / actualCols));
87525
- rowSizes = Array.from({ length: actualRows }).map(() => ({ sizing: "FIXED", value: String(minRowH) }));
87566
+ rowSizes = Array.from({ length: actualRows }).map(() => ({ sizing: "HUG", value: "113", min: minRowH }));
87526
87567
  } else {
87527
87568
  actualRows = Math.max(1, rows);
87528
87569
  if (rowSizes.length !== actualRows) {
@@ -87548,7 +87589,7 @@ function applyAutoLayout(doc2) {
87548
87589
  let sumFixedRows = 0;
87549
87590
  rowSizes.forEach((s, r) => {
87550
87591
  if (s.sizing === "FIXED") sumFixedRows += parseFloat(s.value) || 0;
87551
- else if (s.sizing === "HUG") sumFixedRows += rowMaxHugs[r];
87592
+ else if (s.sizing === "HUG") sumFixedRows += Math.max(s.min ?? 0, rowMaxHugs[r]);
87552
87593
  });
87553
87594
  intrinsicW = sumFixedCols + Math.max(0, actualCols - 1) * itemSpacing + paddingX;
87554
87595
  intrinsicH = sumFixedRows + Math.max(0, actualRows - 1) * counterSpacing + paddingY;
@@ -87659,7 +87700,7 @@ function applyAutoLayout(doc2) {
87659
87700
  let rowSizes = frame2.layoutGridRowSizes || [];
87660
87701
  if (rows === "AUTO") {
87661
87702
  actualRows = Math.max(1, Math.ceil(childIds.length / actualCols));
87662
- rowSizes = Array.from({ length: actualRows }).map(() => ({ sizing: "HUG", value: "113" }));
87703
+ rowSizes = Array.from({ length: actualRows }).map(() => ({ sizing: "HUG", value: "113", min: minRowH }));
87663
87704
  } else {
87664
87705
  actualRows = Math.max(1, rows);
87665
87706
  if (rowSizes.length !== actualRows) {
@@ -87695,14 +87736,14 @@ function applyAutoLayout(doc2) {
87695
87736
  let totalRowFr = 0;
87696
87737
  rowSizes.forEach((s, r) => {
87697
87738
  if (s.sizing === "FIXED") fixedRowH += parseFloat(s.value) || 0;
87698
- else if (s.sizing === "HUG") fixedRowH += rowMaxHugs[r];
87739
+ else if (s.sizing === "HUG") fixedRowH += Math.max(s.min ?? 0, rowMaxHugs[r]);
87699
87740
  else if (s.sizing === "FILL") totalRowFr += parseFloat(s.value) || 1;
87700
87741
  });
87701
87742
  const availRowH = Math.max(0, frame2.height - paddingY - Math.max(0, actualRows - 1) * counterSpacing - fixedRowH);
87702
87743
  const rowH = new Array(actualRows).fill(0);
87703
87744
  rowSizes.forEach((s, r) => {
87704
87745
  if (s.sizing === "FIXED") rowH[r] = parseFloat(s.value) || 0;
87705
- else if (s.sizing === "HUG") rowH[r] = rowMaxHugs[r];
87746
+ else if (s.sizing === "HUG") rowH[r] = Math.max(s.min ?? 0, rowMaxHugs[r]);
87706
87747
  else if (s.sizing === "FILL") rowH[r] = totalRowFr > 0 ? availRowH * ((parseFloat(s.value) || 1) / totalRowFr) : 0;
87707
87748
  });
87708
87749
  const colX = new Array(actualCols).fill(0);
@@ -87873,6 +87914,7 @@ function isAutoLayout(node2) {
87873
87914
  }
87874
87915
  var init_auto_layout = __esm({
87875
87916
  "lib/document/auto-layout.ts"() {
87917
+ "use strict";
87876
87918
  init_instance_layout();
87877
87919
  setLayoutEngine(applyAutoLayout);
87878
87920
  }
@@ -89179,6 +89221,83 @@ var init_keys = __esm({
89179
89221
  });
89180
89222
 
89181
89223
  // lib/motion/transitions.ts
89224
+ function faceBrightness(rotateX, rotateY) {
89225
+ const c2 = Math.abs(Math.cos(rotateX * Math.PI / 180) * Math.cos(rotateY * Math.PI / 180));
89226
+ return AMBIENT_SHADE + (1 - AMBIENT_SHADE) * c2;
89227
+ }
89228
+ function ringFace(side, axis, angle2, r, dolly) {
89229
+ const s = Math.sin(rad2(angle2)), z2 = -r + r * Math.cos(rad2(angle2)) - dolly;
89230
+ return axis === "y" ? { side, anchorX: 0.5, anchorY: 0.5, tx: r * s, ty: 0, z: z2, rotateX: 0, rotateY: angle2, opacity: 1, brightness: faceBrightness(0, angle2) } : { side, anchorX: 0.5, anchorY: 0.5, tx: 0, ty: -r * s, z: z2, rotateX: angle2, rotateY: 0, opacity: 1, brightness: faceBrightness(angle2, 0) };
89231
+ }
89232
+ function transition3dPose(type, progress2, stage) {
89233
+ if (!is3DTransition(type)) return null;
89234
+ const p2 = Math.min(1, Math.max(0, progress2));
89235
+ const W = Math.max(1, stage.width), H = Math.max(1, stage.height);
89236
+ const arc = Math.sin(Math.PI * p2);
89237
+ const pose = (extent2, faces2) => ({ perspective: 1.8 * extent2, faces: backToFront(faces2) });
89238
+ if (p2 <= 0) return pose(W, [still("a")]);
89239
+ if (p2 >= 1) return pose(W, [still("b")]);
89240
+ switch (type) {
89241
+ case "CUBE_FROM_RIGHT":
89242
+ return pose(W, [ringFace("a", "y", -90 * p2, W / 2, 0.1 * W * arc), ringFace("b", "y", 90 * (1 - p2), W / 2, 0.1 * W * arc)]);
89243
+ case "CUBE_FROM_LEFT":
89244
+ return pose(W, [ringFace("a", "y", 90 * p2, W / 2, 0.1 * W * arc), ringFace("b", "y", -90 * (1 - p2), W / 2, 0.1 * W * arc)]);
89245
+ case "CUBE_FROM_BOTTOM":
89246
+ return pose(H, [ringFace("a", "x", 90 * p2, H / 2, 0.1 * H * arc), ringFace("b", "x", -90 * (1 - p2), H / 2, 0.1 * H * arc)]);
89247
+ case "CUBE_FROM_TOP":
89248
+ return pose(H, [ringFace("a", "x", -90 * p2, H / 2, 0.1 * H * arc), ringFace("b", "x", 90 * (1 - p2), H / 2, 0.1 * H * arc)]);
89249
+ case "CAROUSEL_FROM_RIGHT":
89250
+ case "CAROUSEL_FROM_LEFT": {
89251
+ const r = (W / 2 + 0.06 * W) / Math.tan(rad2(30)), dir = type === "CAROUSEL_FROM_RIGHT" ? 1 : -1;
89252
+ return pose(W, [ringFace("a", "y", -dir * 60 * p2, r, 0.25 * W * arc), ringFace("b", "y", dir * 60 * (1 - p2), r, 0.25 * W * arc)]);
89253
+ }
89254
+ case "FLIP_HORIZONTAL":
89255
+ case "FLIP_VERTICAL": {
89256
+ const front = -180 * p2, back = 180 * (1 - p2), z2 = -0.2 * (type === "FLIP_HORIZONTAL" ? W : H) * arc;
89257
+ const face = (side, angle2) => still(side, {
89258
+ z: z2,
89259
+ ...type === "FLIP_HORIZONTAL" ? { rotateY: angle2 } : { rotateX: -angle2 },
89260
+ opacity: Math.cos(rad2(angle2)) > 0 ? 1 : 0,
89261
+ brightness: faceBrightness(0, angle2)
89262
+ });
89263
+ return pose(type === "FLIP_HORIZONTAL" ? W : H, [face("a", front), face("b", back)]);
89264
+ }
89265
+ // A door: a nearer camera than the turns (the hinge must read as turning in depth, not as a page shrinking), and
89266
+ // the room behind it does not move — it only comes out of the door's shadow.
89267
+ case "SWING_OPEN":
89268
+ return { perspective: 1.1 * W, faces: backToFront([
89269
+ still("b", { z: -1, brightness: 0.55 + 0.45 * p2 }),
89270
+ still("a", { anchorX: 0, rotateY: 100 * p2, opacity: 1 - ramp(p2, 0.75, 1), brightness: faceBrightness(0, 100 * p2) })
89271
+ ]) };
89272
+ case "SWING_CLOSE":
89273
+ return { perspective: 1.1 * W, faces: backToFront([
89274
+ still("a", { z: -1, brightness: 1 - 0.45 * p2 }),
89275
+ still("b", { anchorX: 0, rotateY: 100 * (1 - p2), opacity: ramp(p2, 0, 0.25), brightness: faceBrightness(0, 100 * (1 - p2)) })
89276
+ ]) };
89277
+ case "STACK_IN":
89278
+ return pose(H, [
89279
+ still("a", { z: -0.12 * W * p2, rotateX: 6 * p2, brightness: 1 - 0.35 * p2 }),
89280
+ still("b", { ty: H * (1 - p2), z: 1e-3 })
89281
+ ]);
89282
+ case "STACK_OUT":
89283
+ return pose(H, [
89284
+ still("b", { z: -0.12 * W * (1 - p2), rotateX: 6 * (1 - p2), brightness: 1 - 0.35 * (1 - p2) }),
89285
+ still("a", { ty: H * p2, z: 1e-3 })
89286
+ ]);
89287
+ case "DEPTH_PUSH":
89288
+ return pose(Math.max(W, H), [
89289
+ still("a", { z: -0.6 * W * p2, opacity: 1 - p2, brightness: 1 - 0.3 * p2 }),
89290
+ still("b", { z: 0.35 * W * (1 - p2), opacity: p2 })
89291
+ ]);
89292
+ case "DEPTH_PULL":
89293
+ return pose(Math.max(W, H), [
89294
+ still("b", { z: -0.6 * W * (1 - p2), opacity: p2, brightness: 1 - 0.3 * (1 - p2) }),
89295
+ still("a", { z: 0.35 * W * p2, opacity: 1 - p2 })
89296
+ ]);
89297
+ default:
89298
+ return null;
89299
+ }
89300
+ }
89182
89301
  function scaledAbout(m, k2, cx, cy) {
89183
89302
  return k2 === 1 ? m : multiply([k2, 0, 0, k2, cx - k2 * cx, cy - k2 * cy], m);
89184
89303
  }
@@ -89193,6 +89312,16 @@ function coverRadius(stage, c2) {
89193
89312
  }
89194
89313
  function transitionRoots(type, progress2, a, b, stage, params2) {
89195
89314
  const p2 = Math.min(1, Math.max(0, progress2));
89315
+ if (is3DTransition(type)) {
89316
+ const flat2 = transitionRoots(flatTransitionType(type), p2, a, b, stage, params2);
89317
+ const pose = p2 > 0 && p2 < 1 ? transition3dPose(type, p2, stage) : null;
89318
+ if (!pose) return flat2;
89319
+ return pose.faces.map((f2) => {
89320
+ const side = f2.side === "a" ? a : b;
89321
+ const r = flat2.find((x2) => x2.rootId === side.id);
89322
+ return { rootId: side.id, matrix: r?.matrix ?? side.base, opacity: r ? r.opacity : 0, face: { ...f2, base: side.base, stage, perspective: pose.perspective } };
89323
+ });
89324
+ }
89196
89325
  switch (type) {
89197
89326
  case "INSTANT":
89198
89327
  case "CUT":
@@ -89248,9 +89377,11 @@ function transitionRoots(type, progress2, a, b, stage, params2) {
89248
89377
  const outScale = 1 + (ZOOM_OUT_SCALE - 1) * p2;
89249
89378
  return [root(b, scaledAbout(b.base, inScale, c2.x, c2.y), p2), root(a, scaledAbout(a.base, outScale, c2.x, c2.y), 1 - p2)];
89250
89379
  }
89380
+ default:
89381
+ return [root(a, a.base, 1 - p2), root(b, b.base, p2)];
89251
89382
  }
89252
89383
  }
89253
- var TRANSITION_TYPES, PROTOTYPE_TRANSITION_TYPES, SCENE_TRANSITION_TYPES, isCut, REVERSE, reverseTransitionType, ZOOM_OUT_SCALE, ZOOM_IN_SCALE, WHIP_SMEAR, whipSmear, root, shifted, rootShows;
89384
+ var TRANSITION_TYPES, TRANSITION_3D_TYPES, PROTOTYPE_TRANSITION_TYPES, SCENE_TRANSITION_TYPES, isCut, REVERSE, reverseTransitionType, THREE_D, is3DTransition, FLAT, flatTransitionType, AMBIENT_SHADE, rad2, ramp, still, backToFront, ZOOM_OUT_SCALE, ZOOM_IN_SCALE, WHIP_SMEAR, whipSmear, root, shifted, rootShows;
89254
89385
  var init_transitions = __esm({
89255
89386
  "lib/motion/transitions.ts"() {
89256
89387
  "use strict";
@@ -89276,8 +89407,23 @@ var init_transitions = __esm({
89276
89407
  "IRIS",
89277
89408
  "ZOOM_THROUGH",
89278
89409
  "WHIP_LEFT",
89279
- "WHIP_RIGHT"
89410
+ "WHIP_RIGHT",
89411
+ "CUBE_FROM_LEFT",
89412
+ "CUBE_FROM_RIGHT",
89413
+ "CUBE_FROM_TOP",
89414
+ "CUBE_FROM_BOTTOM",
89415
+ "FLIP_HORIZONTAL",
89416
+ "FLIP_VERTICAL",
89417
+ "SWING_OPEN",
89418
+ "SWING_CLOSE",
89419
+ "STACK_IN",
89420
+ "STACK_OUT",
89421
+ "DEPTH_PUSH",
89422
+ "DEPTH_PULL",
89423
+ "CAROUSEL_FROM_LEFT",
89424
+ "CAROUSEL_FROM_RIGHT"
89280
89425
  ];
89426
+ TRANSITION_3D_TYPES = TRANSITION_TYPES.slice(TRANSITION_TYPES.indexOf("CUBE_FROM_LEFT"));
89281
89427
  PROTOTYPE_TRANSITION_TYPES = TRANSITION_TYPES.filter((t3) => t3 !== "CUT" && t3 !== "WHIP_LEFT" && t3 !== "WHIP_RIGHT");
89282
89428
  SCENE_TRANSITION_TYPES = TRANSITION_TYPES.filter((t3) => t3 !== "SMART_ANIMATE" && t3 !== "INSTANT");
89283
89429
  isCut = (type) => type === "INSTANT" || type === "CUT";
@@ -89293,16 +89439,52 @@ var init_transitions = __esm({
89293
89439
  CIRCLE_WIPE: "IRIS",
89294
89440
  IRIS: "CIRCLE_WIPE",
89295
89441
  WHIP_LEFT: "WHIP_RIGHT",
89296
- WHIP_RIGHT: "WHIP_LEFT"
89442
+ WHIP_RIGHT: "WHIP_LEFT",
89443
+ CUBE_FROM_LEFT: "CUBE_FROM_RIGHT",
89444
+ CUBE_FROM_RIGHT: "CUBE_FROM_LEFT",
89445
+ CUBE_FROM_TOP: "CUBE_FROM_BOTTOM",
89446
+ CUBE_FROM_BOTTOM: "CUBE_FROM_TOP",
89447
+ SWING_OPEN: "SWING_CLOSE",
89448
+ SWING_CLOSE: "SWING_OPEN",
89449
+ STACK_IN: "STACK_OUT",
89450
+ STACK_OUT: "STACK_IN",
89451
+ DEPTH_PUSH: "DEPTH_PULL",
89452
+ DEPTH_PULL: "DEPTH_PUSH",
89453
+ CAROUSEL_FROM_LEFT: "CAROUSEL_FROM_RIGHT",
89454
+ CAROUSEL_FROM_RIGHT: "CAROUSEL_FROM_LEFT"
89297
89455
  };
89298
89456
  reverseTransitionType = (type) => REVERSE[type] ?? type;
89457
+ THREE_D = new Set(TRANSITION_3D_TYPES);
89458
+ is3DTransition = (type) => THREE_D.has(type);
89459
+ FLAT = {
89460
+ CUBE_FROM_LEFT: "PUSH_FROM_LEFT",
89461
+ CUBE_FROM_RIGHT: "PUSH_FROM_RIGHT",
89462
+ CUBE_FROM_TOP: "PUSH_FROM_TOP",
89463
+ CUBE_FROM_BOTTOM: "PUSH_FROM_BOTTOM",
89464
+ CAROUSEL_FROM_LEFT: "PUSH_FROM_LEFT",
89465
+ CAROUSEL_FROM_RIGHT: "PUSH_FROM_RIGHT",
89466
+ STACK_IN: "SLIDE_FROM_BOTTOM",
89467
+ STACK_OUT: "MOVE_OUT_TO_BOTTOM",
89468
+ FLIP_HORIZONTAL: "DISSOLVE",
89469
+ FLIP_VERTICAL: "DISSOLVE",
89470
+ SWING_OPEN: "DISSOLVE",
89471
+ SWING_CLOSE: "DISSOLVE",
89472
+ DEPTH_PUSH: "DISSOLVE",
89473
+ DEPTH_PULL: "DISSOLVE"
89474
+ };
89475
+ flatTransitionType = (type) => FLAT[type] ?? type;
89476
+ AMBIENT_SHADE = 0.45;
89477
+ rad2 = (deg) => deg * Math.PI / 180;
89478
+ ramp = (x2, e0, e1) => Math.min(1, Math.max(0, (x2 - e0) / (e1 - e0)));
89479
+ still = (side, o = {}) => ({ side, anchorX: 0.5, anchorY: 0.5, tx: 0, ty: 0, z: 0, rotateX: 0, rotateY: 0, opacity: 1, brightness: 1, ...o });
89480
+ backToFront = (faces2) => faces2.map((f2, i2) => [f2, i2]).sort((x2, y) => x2[0].z - y[0].z || x2[1] - y[1]).map(([f2]) => f2);
89299
89481
  ZOOM_OUT_SCALE = 2.5;
89300
89482
  ZOOM_IN_SCALE = 0.85;
89301
89483
  WHIP_SMEAR = 0.22;
89302
89484
  whipSmear = (p2, width) => WHIP_SMEAR * width * 4 * p2 * (1 - p2);
89303
89485
  root = (side, matrix = side.base, opacity = 1) => ({ rootId: side.id, matrix, opacity });
89304
89486
  shifted = (side, dx, dy) => dx || dy ? multiply(translation(dx, dy), side.base) : side.base;
89305
- rootShows = (r) => r.opacity > 0 && (!r.clip || r.clip.r > 0);
89487
+ rootShows = (r) => (r.opacity > 0 || (r.face?.opacity ?? 0) > 0) && (!r.clip || r.clip.r > 0);
89306
89488
  }
89307
89489
  });
89308
89490
 
@@ -90677,6 +90859,7 @@ function layerInputPatch(node2, name2, path) {
90677
90859
  var NO_RUNTIME, MAX_DEPTH, freshIndex, indexOf, isComponentLike, selfStarting, startedAt, endMemo, HOST_OWNS, rootTracksMemo, layerMemo, idle;
90678
90860
  var init_instances2 = __esm({
90679
90861
  "lib/motion/instances.ts"() {
90862
+ "use strict";
90680
90863
  init_node_delta();
90681
90864
  init_instances();
90682
90865
  init_scene_graph();
@@ -90948,6 +91131,7 @@ function repairStateMachine(raw, markerIds, hasNode) {
90948
91131
  var STATE_MACHINE_INPUT_TYPES, STATE_MACHINE_GUARD_OPS, STATE_MACHINE_ACTION_TYPES, STATE_MACHINE_LISTENER_TYPES, isKeyListener, ANY_STATE, MAX_STEPS2, byId2, sortedValues, machineOf, startValue, isObj3, finite4, isValue, goodId;
90949
91132
  var init_state_machine = __esm({
90950
91133
  "lib/motion/state-machine.ts"() {
91134
+ "use strict";
90951
91135
  STATE_MACHINE_INPUT_TYPES = ["boolean", "number", "string", "event"];
90952
91136
  STATE_MACHINE_GUARD_OPS = ["eq", "neq", "gt", "gte", "lt", "lte"];
90953
91137
  STATE_MACHINE_ACTION_TYPES = ["set", "toggle", "increment", "decrement", "fire", "reset"];
@@ -235128,6 +235312,7 @@ function repairCompositions(comps, nodes) {
235128
235312
  var isObj5, finite6, optFinite, isVec2, TIMELINE_COLOR_IDS, TIMELINE_COLORS, UNITS, ORDERS, PROP_KEYS, ANIMATOR_ID, MOTION_TYPES, TRANSITIONS, isFraction, MEDIA_HASH;
235129
235313
  var init_invariants = __esm({
235130
235314
  "lib/motion/invariants.ts"() {
235315
+ "use strict";
235131
235316
  init_easing();
235132
235317
  init_properties();
235133
235318
  init_markers();
@@ -239652,6 +239837,7 @@ function resizeWindow(doc2, target2, rect) {
239652
239837
  }
239653
239838
  var init_crop = __esm({
239654
239839
  "lib/editor/crop.ts"() {
239840
+ "use strict";
239655
239841
  init_dist_node();
239656
239842
  init_scene_graph();
239657
239843
  init_photo_frames();
@@ -243174,6 +243360,7 @@ fn shade(uv: vec2<f32>, res: vec2<f32>, tm: f32) -> vec4<f32> {
243174
243360
  var SHADER_PRESETS, shaderPreset, legacyPresetOf, DEFAULT_SHADER_PRESET, DEFAULT_TEXTURE_PARAMS, f, vec4, NOISE_LIB;
243175
243361
  var init_shader_presets = __esm({
243176
243362
  "lib/engine/shader-presets.ts"() {
243363
+ "use strict";
243177
243364
  init_shader_graph();
243178
243365
  init_shader_graph_presets();
243179
243366
  init_shader_presets_legacy();
@@ -244381,11 +244568,11 @@ function buildStamp2(type) {
244381
244568
  const a = h2(i2, 1, 5) * Math.PI * 2;
244382
244569
  const rr = Math.pow(h2(i2, 2, 9), 0.7) * R * 0.92;
244383
244570
  const px5 = cx + Math.cos(a) * rr, py = cy + Math.sin(a) * rr;
244384
- const rad2 = 1 + h2(i2, 3, 13) * 5;
244571
+ const rad3 = 1 + h2(i2, 3, 13) * 5;
244385
244572
  const peak = 0.35 + h2(i2, 4, 17) * 0.6;
244386
- for (let y = Math.max(0, Math.floor(py - rad2)); y <= Math.min(SIZE - 1, Math.ceil(py + rad2)); y++) {
244387
- for (let x2 = Math.max(0, Math.floor(px5 - rad2)); x2 <= Math.min(SIZE - 1, Math.ceil(px5 + rad2)); x2++) {
244388
- const d = Math.hypot(x2 + 0.5 - px5, y + 0.5 - py) / rad2;
244573
+ for (let y = Math.max(0, Math.floor(py - rad3)); y <= Math.min(SIZE - 1, Math.ceil(py + rad3)); y++) {
244574
+ for (let x2 = Math.max(0, Math.floor(px5 - rad3)); x2 <= Math.min(SIZE - 1, Math.ceil(px5 + rad3)); x2++) {
244575
+ const d = Math.hypot(x2 + 0.5 - px5, y + 0.5 - py) / rad3;
244389
244576
  if (d >= 1) continue;
244390
244577
  const src = peak * (1 - d);
244391
244578
  const k2 = y * SIZE + x2;
@@ -246320,14 +246507,14 @@ function liveStaggerParent(nodes, ids2) {
246320
246507
  if (!parent || parent.type === "PAGE" || parent.motion?.stagger) return null;
246321
246508
  const set3 = new Set(ids2);
246322
246509
  if (set3.size !== parent.childIds.length || !parent.childIds.every((c2) => set3.has(c2))) return null;
246323
- const still = (id3) => {
246510
+ const still2 = (id3) => {
246324
246511
  const n = nodes[id3];
246325
246512
  if (!n) return true;
246326
246513
  const m = n.motion;
246327
246514
  if (m && (Object.keys(m.tracks).length || m.timeOffset || m.span || m.stagger)) return false;
246328
- return (n.childIds ?? []).every(still);
246515
+ return (n.childIds ?? []).every(still2);
246329
246516
  };
246330
- return ids2.every(still) ? parent.id : null;
246517
+ return ids2.every(still2) ? parent.id : null;
246331
246518
  }
246332
246519
  function staggerDocument(doc2, ids2, opts) {
246333
246520
  const present2 = ids2.filter((id3) => doc2.nodes[id3]);
@@ -247267,11 +247454,11 @@ function editSelected(nodes, sel, change2) {
247267
247454
  for (const [path, ids2] of byPath) {
247268
247455
  const track2 = motion?.tracks[path];
247269
247456
  if (!track2) continue;
247270
- const moved3 = [], still = [];
247457
+ const moved3 = [], still2 = [];
247271
247458
  let touched = false;
247272
247459
  for (const k2 of track2.keys) {
247273
247460
  if (!ids2.has(k2.id)) {
247274
- still.push(k2);
247461
+ still2.push(k2);
247275
247462
  continue;
247276
247463
  }
247277
247464
  const next2 = change2(k2, nodeId2, path);
@@ -247289,7 +247476,7 @@ function editSelected(nodes, sel, change2) {
247289
247476
  keys3.push(k2);
247290
247477
  }
247291
247478
  }
247292
- for (const k2 of still) if (!moved3.some((m) => Math.abs(m.t - k2.t) < 1)) keys3.push(k2);
247479
+ for (const k2 of still2) if (!moved3.some((m) => Math.abs(m.t - k2.t) < 1)) keys3.push(k2);
247293
247480
  keys3.sort((a, b) => a.t - b.t);
247294
247481
  motion = withTrack(motion, path, keys3.length || track2.modifiers?.length ? { ...track2, keys: keys3 } : null);
247295
247482
  changed = true;
@@ -247514,6 +247701,7 @@ function retuneShaderAudio(node2, fillId) {
247514
247701
  }
247515
247702
  var init_shader_audio = __esm({
247516
247703
  "lib/motion/shader-audio.ts"() {
247704
+ "use strict";
247517
247705
  init_shader_params();
247518
247706
  init_modifier_edit();
247519
247707
  init_keys();
@@ -248285,6 +248473,7 @@ function hrefOf(link2, nodes, routes) {
248285
248473
  var anchorOf, cleanAnchor, opensNewTab;
248286
248474
  var init_semantics = __esm({
248287
248475
  "lib/document/semantics.ts"() {
248476
+ "use strict";
248288
248477
  init_safe_url();
248289
248478
  anchorOf = (node2) => node2.semantics?.anchor || `pc-${node2.id.replace(/[^A-Za-z0-9_-]/g, "-")}`;
248290
248479
  cleanAnchor = (raw) => raw.trim().toLowerCase().replace(/^#/, "").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
@@ -248377,6 +248566,15 @@ function repeatRecords(doc2, repeat, under) {
248377
248566
  const from2 = Math.max(0, repeat.offset ?? 0);
248378
248567
  return list2.slice(from2, repeat.limit !== void 0 ? from2 + Math.max(0, repeat.limit) : void 0);
248379
248568
  }
248569
+ function shownRecordOf(nodes, doc2, id3) {
248570
+ for (let at3 = nodes[id3]?.parentId, hops = 0; at3 && hops < 64; at3 = nodes[at3]?.parentId, hops++) {
248571
+ const frame2 = nodes[at3];
248572
+ if (frame2?.repeat) return repeatRecords(doc2, frame2.repeat)[0] ?? null;
248573
+ const of = frame2?.route?.collectionId;
248574
+ if (of && doc2.collections?.[of]) return repeatRecords(doc2, { collectionId: of })[0] ?? null;
248575
+ }
248576
+ return null;
248577
+ }
248380
248578
  function recordSlugs(doc2, collectionId) {
248381
248579
  const c2 = doc2.collections?.[collectionId];
248382
248580
  const out = /* @__PURE__ */ new Map();
@@ -248489,9 +248687,10 @@ function removeRecords(doc2, ids2) {
248489
248687
  const collections = Object.fromEntries(Object.entries(doc2.collections ?? {}).map(([id3, c2]) => [id3, c2.order.some((r) => gone.has(r)) ? { ...c2, order: c2.order.filter((r) => !gone.has(r)) } : c2]));
248490
248688
  return { ...doc2, records, collections };
248491
248689
  }
248492
- var COLLECTION_LIMITS, slugify2, dataMemo, withData, ITEM_RECORD, MARK, itemMark, templateRecord, compare, TOKEN2, hasItemToken, layerId, copyRecord, coerce3, newId;
248690
+ var COLLECTION_LIMITS, slugify2, dataMemo, withData, ITEM_RECORD, MARK, itemMark, templateRecord, compare, TOKEN2, hasItemToken, layerId, copySuffix, copyRecord, coerce3, newId;
248493
248691
  var init_collections = __esm({
248494
248692
  "lib/document/collections.ts"() {
248693
+ "use strict";
248495
248694
  init_expressions2();
248496
248695
  init_variables();
248497
248696
  init_contract();
@@ -248518,6 +248717,10 @@ var init_collections = __esm({
248518
248717
  const at3 = id3.indexOf("~");
248519
248718
  return at3 < 0 ? id3 : id3.slice(0, at3);
248520
248719
  };
248720
+ copySuffix = (id3) => {
248721
+ const at3 = id3.indexOf("~");
248722
+ return at3 < 0 ? "" : id3.slice(at3);
248723
+ };
248521
248724
  copyRecord = (id3) => {
248522
248725
  const at3 = id3.lastIndexOf("~");
248523
248726
  return at3 < 0 ? null : id3.slice(at3 + 1);
@@ -249519,7 +249722,6 @@ function activeTeamWorkspaceId() {
249519
249722
  var STORAGE_KEY2, useHyperyTeam, useTeamPrompt;
249520
249723
  var init_team = __esm({
249521
249724
  "lib/client/cloud/team.ts"() {
249522
- "use strict";
249523
249725
  init_esm();
249524
249726
  init_api4();
249525
249727
  init_session();
@@ -259499,11 +259701,12 @@ function templateFromDocument(doc2, meta3, o = {}) {
259499
259701
  for (const v of variants) for (const id3 of v.rootIds) nodes[id3] = { ...nodes[id3], parentId: null };
259500
259702
  const deps = collectStyleDependencies(doc2, nodes);
259501
259703
  const payload = {
259704
+ // A record's picture (a project's cover in a CMS collection) is media the file uses, as a layer's is.
259502
259705
  mode: "document",
259503
259706
  nodes,
259504
259707
  variants,
259505
259708
  pages: pages2,
259506
- media: mediaHashes({ nodes, compositions: doc2.compositions }),
259709
+ media: mediaHashes({ nodes, compositions: doc2.compositions, records: doc2.records }),
259507
259710
  styles: { ...deps.styles, ...doc2.styles },
259508
259711
  variables: { ...deps.variables, ...doc2.variables },
259509
259712
  variableCollections: { ...deps.variableCollections, ...doc2.variableCollections },
@@ -296019,8 +296222,8 @@ async function syncTemplatePreview(row2, rootId, doc2) {
296019
296222
  const path = (file2, q) => `/api/templates/${encodeURIComponent(row2.id)}/preview/${file2}${q ? `?${new URLSearchParams(q)}` : ""}`;
296020
296223
  const put3 = (file2, bytes2, type, q) => api(path(file2, q), { method: "PUT", body: new Blob([bytes2], { type }) });
296021
296224
  let preview = row2.preview;
296022
- const still = await renderTemplateDetail2(root2, doc2);
296023
- if (still) ({ preview } = await put3("still", still.bytes, still.type, { w: String(still.width), h: String(still.height) }));
296225
+ const still2 = await renderTemplateDetail2(root2, doc2);
296226
+ if (still2) ({ preview } = await put3("still", still2.bytes, still2.type, { w: String(still2.width), h: String(still2.height) }));
296024
296227
  const loop = await renderTemplatePreview2(renderer, doc2, rootId);
296025
296228
  if (loop) ({ preview } = await put3("anim", loop.bytes, loop.type, { w: String(loop.width), h: String(loop.height), ms: String(loop.durationMs) }));
296026
296229
  else if (preview?.anim) {
@@ -296188,6 +296391,7 @@ async function createFreshFileOrExplain(place3 = {}, seed2 = {}) {
296188
296391
  var online, goesLocal;
296189
296392
  var init_new_file = __esm({
296190
296393
  "lib/client/cloud/new-file.ts"() {
296394
+ "use strict";
296191
296395
  init_scene_graph();
296192
296396
  init_print_pages();
296193
296397
  init_page_presets();
@@ -296695,7 +296899,6 @@ function startCloudSync() {
296695
296899
  var status, readOnlyDoc, activeLink, statusListeners, notice, urlArmed, opening, syncStatus, canEdit, uploaded, MEDIA_UPLOAD_PARALLEL, pushTimer, pushing, dirty, pendingMedia, collab, collabSession, collabAnonymous, uploadedThumbs, thumbCheckedAt, THUMB_EVERY_MS, putThumbnail, openingFiles, mediaHealed, started;
296696
296900
  var init_sync2 = __esm({
296697
296901
  "lib/client/cloud/sync.ts"() {
296698
- "use strict";
296699
296902
  init_paint_repair();
296700
296903
  init_migrate();
296701
296904
  init_view();
@@ -296901,7 +297104,6 @@ async function dispatchShaped(key5, options) {
296901
297104
  var onViolation;
296902
297105
  var init_dispatch = __esm({
296903
297106
  "lib/commands/dispatch.ts"() {
296904
- "use strict";
296905
297107
  init_errors();
296906
297108
  init_registry();
296907
297109
  init_confirm();
@@ -296942,13 +297144,18 @@ var init_review_kits = __esm({
296942
297144
 
296943
297145
  // lib/templates/text-measurer.ts
296944
297146
  function shownNode(doc2, n) {
296945
- return resolveNodeVariables(n, doc2.variables, doc2.variableCollections);
297147
+ const r = resolveNodeVariables(n, doc2.variables, doc2.variableCollections);
297148
+ const record2 = doc2.nodes && doc2.records ? shownRecordOf(doc2.nodes, doc2, n.id) : null;
297149
+ const collection = record2 && doc2.collections?.[record2.collectionId];
297150
+ return record2 && collection ? itemNode(r, n, collection, record2, itemScope(collection, record2, withData(variablesScope(doc2.variables, doc2.variableCollections), doc2))) : r;
296946
297151
  }
296947
297152
  var templateTextMeasurer;
296948
297153
  var init_text_measurer = __esm({
296949
297154
  "lib/templates/text-measurer.ts"() {
296950
297155
  "use strict";
296951
297156
  init_variables();
297157
+ init_collections();
297158
+ init_expressions2();
296952
297159
  init_measure();
296953
297160
  templateTextMeasurer = (node2) => {
296954
297161
  const characters = casedText(node2.characters ?? "", node2.textCase);
@@ -297279,6 +297486,7 @@ function creditLine(c2) {
297279
297486
  var MAX_PHOTO_PAGE, MAX_PHOTO_QUERY, UUID, isPhotoId, photoImagePath;
297280
297487
  var init_stock = __esm({
297281
297488
  "lib/photos/stock.ts"() {
297489
+ "use strict";
297282
297490
  MAX_PHOTO_PAGE = 12;
297283
297491
  MAX_PHOTO_QUERY = 200;
297284
297492
  UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -297940,6 +298148,7 @@ function applyTextPath(layout2, path, tp, rebase = true) {
297940
298148
  var defaultCircleRadius, ownsPath, mapPoint;
297941
298149
  var init_text_path = __esm({
297942
298150
  "lib/engine/text/text-path.ts"() {
298151
+ "use strict";
297943
298152
  init_scene_graph();
297944
298153
  init_transform();
297945
298154
  init_shape_to_path();
@@ -298057,6 +298266,7 @@ function areaBounds(rings) {
298057
298266
  }
298058
298267
  var init_text_area = __esm({
298059
298268
  "lib/engine/text/text-area.ts"() {
298269
+ "use strict";
298060
298270
  }
298061
298271
  });
298062
298272
 
@@ -302288,7 +302498,6 @@ async function exportSettingFile(renderer, node2, setting, doc2, styles) {
302288
302498
  var MIME, DEFAULT_EXPORT, exportSettingsOf;
302289
302499
  var init_export = __esm({
302290
302500
  "lib/io/export.ts"() {
302291
- "use strict";
302292
302501
  init_download();
302293
302502
  init_scene_graph();
302294
302503
  init_codecs();
@@ -302309,6 +302518,9 @@ var init_export = __esm({
302309
302518
  // lib/ai/reference-images.ts
302310
302519
  var reference_images_exports = {};
302311
302520
  __export(reference_images_exports, {
302521
+ FIT_QUALITIES: () => FIT_QUALITIES,
302522
+ FIT_SCALES: () => FIT_SCALES,
302523
+ fitReference: () => fitReference,
302312
302524
  referenceGroups: () => referenceGroups,
302313
302525
  referenceScale: () => referenceScale,
302314
302526
  selectionReferenceImages: () => selectionReferenceImages,
@@ -302331,6 +302543,16 @@ function withinBudget(refs, opts = {}) {
302331
302543
  }
302332
302544
  return kept;
302333
302545
  }
302546
+ async function fitReference(encode3, budget) {
302547
+ for (const scale of FIT_SCALES) {
302548
+ for (const quality of scale === 1 ? FIT_QUALITIES : FIT_QUALITIES.slice(-1)) {
302549
+ const url4 = await encode3(scale, quality);
302550
+ if (url4 === null) return null;
302551
+ if (url4.length <= budget) return url4;
302552
+ }
302553
+ }
302554
+ return null;
302555
+ }
302334
302556
  function referenceGroups(ids2, max3 = AI_LIMITS.maxReferenceImages) {
302335
302557
  if (!ids2.length) return [];
302336
302558
  return ids2.length <= max3 ? ids2.map((id3) => [id3]) : [[...ids2]];
@@ -302349,22 +302571,30 @@ async function selectionReferenceImages(doc2, selection, opts = {}) {
302349
302571
  const regions = opts.bands?.length ? opts.bands.map((b) => ({ ...whole, minY: whole.minY + b.y, maxY: Math.min(whole.maxY, whole.minY + b.y + b.height) })).filter((b) => b.maxY - b.minY > 1) : [whole];
302350
302572
  for (const bounds2 of regions) {
302351
302573
  if (out.length >= max3) break;
302352
- const image = await renderer.exportRegion(members2, bounds2, referenceScale(bounds2, opts.maxEdge), doc2, doc2.styles, void 0, true);
302353
- if (!image) continue;
302354
- const blob = await encodeImageData(image, opts.format ?? "PNG", 0.86);
302355
- if (!blob) continue;
302356
- out.push(await blobToDataUrl(blob));
302574
+ const left = AI_LIMITS.maxReferenceTotalChars - out.reduce((n, u) => n + u.length, 0);
302575
+ const budget = Math.min(AI_LIMITS.maxReferenceImageChars, Math.floor(left / Math.max(1, Math.min(max3, regions.length * referenceGroups(selection, max3).length) - out.length)));
302576
+ const scale = referenceScale(bounds2, opts.maxEdge);
302577
+ const drawn = /* @__PURE__ */ new Map();
302578
+ const url4 = await fitReference(async (k2, quality) => {
302579
+ if (!drawn.has(k2)) drawn.set(k2, await renderer.exportRegion(members2, bounds2, scale * k2, doc2, doc2.styles, void 0, true));
302580
+ const image = drawn.get(k2);
302581
+ const blob = image ? await encodeImageData(image, opts.format ?? "PNG", quality) : null;
302582
+ return blob ? blobToDataUrl(blob) : null;
302583
+ }, budget);
302584
+ if (url4) out.push(url4);
302357
302585
  }
302358
302586
  }
302359
302587
  return withinBudget(out, { max: max3 });
302360
302588
  }
302361
- var blobToDataUrl;
302589
+ var FIT_QUALITIES, FIT_SCALES, blobToDataUrl;
302362
302590
  var init_reference_images = __esm({
302363
302591
  "lib/ai/reference-images.ts"() {
302364
302592
  init_export();
302365
302593
  init_selection_bounds();
302366
302594
  init_renderer_registry();
302367
302595
  init_limits();
302596
+ FIT_QUALITIES = [0.86, 0.7, 0.5];
302597
+ FIT_SCALES = [1, 0.75, 0.55, 0.4];
302368
302598
  blobToDataUrl = (blob) => new Promise((resolve6, reject) => {
302369
302599
  const reader = new FileReader();
302370
302600
  reader.onload = () => resolve6(String(reader.result));
@@ -302644,6 +302874,7 @@ function videoPixelSize(resolution, aspect) {
302644
302874
  var VIDEO_ASPECTS, VIDEO_RESOLUTIONS, SEEDANCE_ASPECTS, range, VIDEO_MODELS, DEFAULT_VIDEO_MODEL, videoModel, VIDEO_LIMITS;
302645
302875
  var init_video_models = __esm({
302646
302876
  "lib/ai/video-models.ts"() {
302877
+ "use strict";
302647
302878
  VIDEO_ASPECTS = ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"];
302648
302879
  VIDEO_RESOLUTIONS = ["480p", "720p", "1080p"];
302649
302880
  SEEDANCE_ASPECTS = ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"];
@@ -303132,7 +303363,6 @@ function agentToolList() {
303132
303363
  var AGENT_CAPABILITIES, legacyCommandId, legacyTools, blobToDataUrl3, provided, legacyTool, legacyToolList;
303133
303364
  var init_agent = __esm({
303134
303365
  "lib/commands/agent.ts"() {
303135
- "use strict";
303136
303366
  init_types5();
303137
303367
  init_registry();
303138
303368
  init_errors();
@@ -303918,7 +304148,7 @@ function parseTransform(t3) {
303918
304148
  let x2;
303919
304149
  while (x2 = re.exec(t3)) {
303920
304150
  const v = nums(x2[2]);
303921
- const rad2 = (deg) => deg * Math.PI / 180;
304151
+ const rad3 = (deg) => deg * Math.PI / 180;
303922
304152
  let n = I;
303923
304153
  switch (x2[1].toLowerCase()) {
303924
304154
  case "matrix":
@@ -303931,16 +304161,16 @@ function parseTransform(t3) {
303931
304161
  n = [v[0] ?? 1, 0, 0, v[1] ?? v[0] ?? 1, 0, 0];
303932
304162
  break;
303933
304163
  case "rotate": {
303934
- const c2 = Math.cos(rad2(v[0] ?? 0)), s = Math.sin(rad2(v[0] ?? 0));
304164
+ const c2 = Math.cos(rad3(v[0] ?? 0)), s = Math.sin(rad3(v[0] ?? 0));
303935
304165
  n = [c2, s, -s, c2, 0, 0];
303936
304166
  if (v.length >= 3) n = mul2(mul2([1, 0, 0, 1, v[1], v[2]], n), [1, 0, 0, 1, -v[1], -v[2]]);
303937
304167
  break;
303938
304168
  }
303939
304169
  case "skewx":
303940
- n = [1, 0, Math.tan(rad2(v[0] ?? 0)), 1, 0, 0];
304170
+ n = [1, 0, Math.tan(rad3(v[0] ?? 0)), 1, 0, 0];
303941
304171
  break;
303942
304172
  case "skewy":
303943
- n = [1, Math.tan(rad2(v[0] ?? 0)), 0, 1, 0, 0];
304173
+ n = [1, Math.tan(rad3(v[0] ?? 0)), 0, 1, 0, 0];
303944
304174
  break;
303945
304175
  }
303946
304176
  m = mul2(m, n);
@@ -308659,7 +308889,8 @@ async function exportSlidesToPPTX(renderer, slides, docIn, styles) {
308659
308889
  function transitionXml(t3) {
308660
308890
  if (!t3 || t3.type === "INSTANT") return "";
308661
308891
  const dur = Math.max(1, Math.round(t3.duration));
308662
- const inner = t3.type === "DISSOLVE" ? "<p:fade/>" : t3.type.startsWith("PUSH") ? `<p:push dir="${t3.type.endsWith("RIGHT") ? "l" : t3.type.endsWith("LEFT") ? "r" : t3.type.endsWith("BOTTOM") ? "u" : "d"}"/>` : t3.type.startsWith("SLIDE") ? `<p:cover dir="${t3.type.endsWith("RIGHT") ? "l" : t3.type.endsWith("LEFT") ? "r" : t3.type.endsWith("BOTTOM") ? "u" : "d"}"/>` : "<p:fade/>";
308892
+ const type = flatTransitionType(t3.type);
308893
+ const inner = type === "DISSOLVE" ? "<p:fade/>" : type.startsWith("PUSH") ? `<p:push dir="${type.endsWith("RIGHT") ? "l" : type.endsWith("LEFT") ? "r" : type.endsWith("BOTTOM") ? "u" : "d"}"/>` : type.startsWith("SLIDE") ? `<p:cover dir="${type.endsWith("RIGHT") ? "l" : type.endsWith("LEFT") ? "r" : type.endsWith("BOTTOM") ? "u" : "d"}"/>` : "<p:fade/>";
308663
308894
  return `<p:transition spd="${dur > 900 ? "slow" : dur > 400 ? "med" : "fast"}">${inner}</p:transition>`;
308664
308895
  }
308665
308896
  var EMU, emu, esc2, hex9, alphaTag, solid3, NS, REL, xfrm, needsPicture, xmlHead, relsXml, themeXml, masterXml, layoutXml, notesMasterXml, notesSlideXml;
@@ -308673,6 +308904,7 @@ var init_pptx = __esm({
308673
308904
  init_native_registry();
308674
308905
  init_png();
308675
308906
  init_export_fills();
308907
+ init_transitions();
308676
308908
  init_page_tokens();
308677
308909
  init_text_styles();
308678
308910
  init_effects();
@@ -308987,10 +309219,10 @@ function emitChannel(ch, grid, scalar = false, stats) {
308987
309219
  const eps = ch.eps ?? 1e-3;
308988
309220
  const fill = filled(ch.samples);
308989
309221
  if (!fill) return staticProp([0], scalar);
308990
- const still = constantOf({ ...ch, eps: ch.eps ?? 1e-4 });
308991
- if (still) {
309222
+ const still2 = constantOf({ ...ch, eps: ch.eps ?? 1e-4 });
309223
+ if (still2) {
308992
309224
  if (stats) stats.still++;
308993
- return staticProp(still, scalar);
309225
+ return staticProp(still2, scalar);
308994
309226
  }
308995
309227
  const present2 = ch.samples.map((s) => !!s);
308996
309228
  if (ch.exact && !ch.hold) {
@@ -310099,7 +310331,7 @@ var init_build = __esm({
310099
310331
  const nodeId2 = node0?.id;
310100
310332
  const geometry = [];
310101
310333
  if (rectLike) {
310102
- const rad2 = (n) => {
310334
+ const rad3 = (n) => {
310103
310335
  const cr = n?.cornerRadius;
310104
310336
  return Array.isArray(cr) ? num8(cr[0]) : num8(cr);
310105
310337
  };
@@ -310109,7 +310341,7 @@ var init_build = __esm({
310109
310341
  d: 1,
310110
310342
  p: this.prop(frames.map((p2, f2) => p2 ? [ownerNodes[f2].width / 2, ownerNodes[f2].height / 2] : void 0), null, false, 1e-3),
310111
310343
  s: this.prop(frames.map((p2, f2) => p2 ? [ownerNodes[f2].width, ownerNodes[f2].height] : void 0), null, false, 1e-3),
310112
- r: this.prop(frames.map((p2, f2) => p2 ? [rad2(ownerNodes[f2])] : void 0), this.exact(nodeId2, [this.dim(nodeId2, "cornerRadius")]), true, 1e-3)
310344
+ r: this.prop(frames.map((p2, f2) => p2 ? [rad3(ownerNodes[f2])] : void 0), this.exact(nodeId2, [this.dim(nodeId2, "cornerRadius")]), true, 1e-3)
310113
310345
  });
310114
310346
  } else if (ellipse) {
310115
310347
  geometry.push({
@@ -311579,12 +311811,12 @@ function staticSiteFiles(site, scripts, opts = {}) {
311579
311811
  const lang = opts.lang ?? "en";
311580
311812
  const files = externalizeBitmaps(site);
311581
311813
  const taken = /* @__PURE__ */ new Set();
311582
- const still = visitorCollections(site.program.document.collections).reduce((s, c2) => withVisitorRecords(s, c2.id, []), site);
311583
- for (const page of still.pages) {
311814
+ const still2 = visitorCollections(site.program.document.collections).reduce((s, c2) => withVisitorRecords(s, c2.id, []), site);
311815
+ for (const page of still2.pages) {
311584
311816
  const path = page.notFound ? "404.html" : routeFile(page.route);
311585
311817
  if (taken.has(path)) continue;
311586
311818
  taken.add(path);
311587
- files.push({ path, content: pageHTML(still, page, lang, !!page.notFound) });
311819
+ files.push({ path, content: pageHTML(still2, page, lang, !!page.notFound) });
311588
311820
  }
311589
311821
  files.push({ path: "site.json", content: JSON.stringify(site) });
311590
311822
  files.push({ path: "pc/site.js", content: scripts.site });
@@ -312561,7 +312793,7 @@ var init_package = __esm({
312561
312793
  "packages/runtime/package.json"() {
312562
312794
  package_default = {
312563
312795
  name: "@popcraft/runtime",
312564
- version: "0.7.1",
312796
+ version: "0.8.1",
312565
312797
  description: "What code exported from PopCraft shares: the meaning of expressions (operators and functions) and, as it grows, the parts of a design's behaviour that are common code rather than generated React.",
312566
312798
  license: "MIT",
312567
312799
  homepage: "https://popcraft.app/docs/exporting/nextjs",
@@ -313145,6 +313377,1253 @@ var init_next = __esm({
313145
313377
  }
313146
313378
  });
313147
313379
 
313380
+ // lib/document/routes.ts
313381
+ function screensOf(doc2, pageId2) {
313382
+ return (doc2.nodes[pageId2]?.childIds ?? []).map((id3) => doc2.nodes[id3]).filter((f2) => f2?.type === "FRAME" && f2.visible !== false && !f2.print?.isMaster);
313383
+ }
313384
+ function cleanPath(raw) {
313385
+ const parts = raw.trim().split("/").map(slug2).filter(Boolean);
313386
+ return `/${parts.join("/")}`;
313387
+ }
313388
+ function routesOf(screens) {
313389
+ const taken = /* @__PURE__ */ new Set();
313390
+ const own2 = /* @__PURE__ */ new Map();
313391
+ for (const s of screens) {
313392
+ const path = s.route?.path ? cleanPath(s.route.path) : null;
313393
+ if (path && !taken.has(path)) {
313394
+ taken.add(path);
313395
+ own2.set(s.id, path);
313396
+ }
313397
+ }
313398
+ const rest = screens.filter((s) => !own2.has(s.id) && !s.route?.notFound);
313399
+ const home = taken.has("/") ? void 0 : rest.find((s) => s.isFlowStartingPoint) ?? rest[0];
313400
+ if (home) taken.add("/");
313401
+ const out = /* @__PURE__ */ new Map();
313402
+ for (const s of screens) {
313403
+ if (own2.has(s.id)) {
313404
+ out.set(s.id, own2.get(s.id));
313405
+ continue;
313406
+ }
313407
+ if (s === home) {
313408
+ out.set(s.id, "/");
313409
+ continue;
313410
+ }
313411
+ const base = s.route?.notFound ? "/404" : `/${slug2(s.name) || "page"}`;
313412
+ let route2 = base;
313413
+ for (let n = 2; taken.has(route2); n++) route2 = `${base}-${n}`;
313414
+ taken.add(route2);
313415
+ out.set(s.id, route2);
313416
+ }
313417
+ return out;
313418
+ }
313419
+ var slug2;
313420
+ var init_routes = __esm({
313421
+ "lib/document/routes.ts"() {
313422
+ "use strict";
313423
+ slug2 = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
313424
+ }
313425
+ });
313426
+
313427
+ // lib/island/slice.ts
313428
+ function sliceDocument(doc2, nodeId2, opts = {}) {
313429
+ const nodes = {};
313430
+ const take = (id3) => {
313431
+ const n = doc2.nodes[id3];
313432
+ if (!n || nodes[id3]) return;
313433
+ nodes[id3] = n;
313434
+ for (const c2 of n.childIds ?? []) take(c2);
313435
+ const main2 = n.mainComponentId;
313436
+ if (main2) {
313437
+ take(main2);
313438
+ const set3 = doc2.nodes[main2]?.parentId;
313439
+ if (set3 && doc2.nodes[set3]?.type === "COMPONENT_SET") take(set3);
313440
+ }
313441
+ };
313442
+ if (opts.self && doc2.nodes[nodeId2]) nodes[nodeId2] = { ...doc2.nodes[nodeId2], childIds: [] };
313443
+ else take(nodeId2);
313444
+ let frameId = null;
313445
+ let pageId2 = null;
313446
+ let rootId = nodeId2;
313447
+ for (let child = nodeId2, cur = doc2.nodes[nodeId2]?.parentId; cur; child = cur, cur = doc2.nodes[cur]?.parentId ?? null) {
313448
+ const p2 = doc2.nodes[cur];
313449
+ if (!p2) break;
313450
+ if (p2.type === "PAGE") {
313451
+ pageId2 = cur;
313452
+ frameId = doc2.nodes[child]?.type === "FRAME" ? child : frameId;
313453
+ }
313454
+ if (!nodes[cur]) nodes[cur] = p2.type === "PAGE" ? { ...p2, childIds: [child] } : { ...p2, childIds: [child], fills: [], strokes: [], effects: [], shadows: void 0, blurs: void 0, clipsContent: false, layoutMode: "NONE" };
313455
+ if (p2.type !== "PAGE") rootId = cur;
313456
+ }
313457
+ if (!frameId && doc2.nodes[nodeId2]?.type === "FRAME" && doc2.nodes[doc2.nodes[nodeId2].parentId ?? ""]?.type === "PAGE") frameId = nodeId2;
313458
+ return {
313459
+ nodeId: nodeId2,
313460
+ frameId,
313461
+ rootId,
313462
+ ...opts.self ? { fit: "fill" } : {},
313463
+ ...opts.screen ? { screen: true } : {},
313464
+ document: {
313465
+ id: doc2.id,
313466
+ name: doc2.name,
313467
+ pages: pageId2 ? [pageId2] : [],
313468
+ nodes,
313469
+ styles: doc2.styles,
313470
+ variables: doc2.variables,
313471
+ variableCollections: doc2.variableCollections,
313472
+ activeVariableModes: doc2.activeVariableModes,
313473
+ settings: doc2.settings,
313474
+ ...opts.screen ? { ...doc2.site ? { site: doc2.site } : {}, ...doc2.collections ? { collections: doc2.collections, records: doc2.records } : {} } : {}
313475
+ }
313476
+ };
313477
+ }
313478
+ var init_slice = __esm({
313479
+ "lib/island/slice.ts"() {
313480
+ "use strict";
313481
+ init_breakpoints();
313482
+ init_collections();
313483
+ init_expressions2();
313484
+ }
313485
+ });
313486
+
313487
+ // lib/runtime/dom/render.ts
313488
+ var HIDDEN_ATTR, HIDDEN_RULE, SCREEN_ISLAND;
313489
+ var init_render = __esm({
313490
+ "lib/runtime/dom/render.ts"() {
313491
+ "use strict";
313492
+ init_css();
313493
+ init_element();
313494
+ HIDDEN_ATTR = "data-pc-hidden";
313495
+ HIDDEN_RULE = `[${HIDDEN_ATTR}] { display: none !important; }`;
313496
+ SCREEN_ISLAND = "screen:";
313497
+ }
313498
+ });
313499
+
313500
+ // lib/code/props.ts
313501
+ function propName(key5) {
313502
+ const words = key5.split("#")[0].trim().split(/[^A-Za-z0-9]+/).filter(Boolean);
313503
+ const name2 = words.map((w, i2) => i2 === 0 ? w.charAt(0).toLowerCase() + w.slice(1) : w.charAt(0).toUpperCase() + w.slice(1)).join("");
313504
+ return /^[A-Za-z_$]/.test(name2) ? name2 : `p${name2}`;
313505
+ }
313506
+ function componentOf(nodes, node2) {
313507
+ const c2 = node2.type === "COMPONENT" ? node2 : node2.type === "INSTANCE" ? nodes[node2.mainComponentId] : void 0;
313508
+ return c2?.type === "COMPONENT" ? c2 : void 0;
313509
+ }
313510
+ function codeOf(nodes, node2) {
313511
+ if (node2.type !== "COMPONENT" && node2.type !== "INSTANCE") return null;
313512
+ return componentOf(nodes, node2)?.code ?? null;
313513
+ }
313514
+ function codeProps(nodes, node2) {
313515
+ const component = componentOf(nodes, node2);
313516
+ const out = {};
313517
+ if (!component) return out;
313518
+ const set3 = component.parentId ? nodes[component.parentId] : void 0;
313519
+ const defs = (set3?.type === "COMPONENT_SET" ? set3.componentPropertyDefinitions : component.componentPropertyDefinitions) ?? {};
313520
+ const given = node2.type === "INSTANCE" ? node2.componentProperties ?? {} : {};
313521
+ for (const key5 of Object.keys(defs).sort()) {
313522
+ const v = value(key5 in given ? given[key5] : defs[key5].defaultValue);
313523
+ if (v !== void 0) out[propName(key5)] = v;
313524
+ }
313525
+ out.width = Math.round(node2.width);
313526
+ out.height = Math.round(node2.height);
313527
+ return out;
313528
+ }
313529
+ var value;
313530
+ var init_props = __esm({
313531
+ "lib/code/props.ts"() {
313532
+ "use strict";
313533
+ init_color();
313534
+ value = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" ? v : v && typeof v === "object" && "r" in v ? colorToHex8(v) : void 0;
313535
+ }
313536
+ });
313537
+
313538
+ // lib/document/controls.ts
313539
+ function fieldPart(nodes, id3) {
313540
+ const n = nodes[id3];
313541
+ if (!n) return null;
313542
+ if (n.type === "TEXT") return id3;
313543
+ for (const c2 of n.childIds ?? []) {
313544
+ const hit = fieldPart(nodes, c2);
313545
+ if (hit) return hit;
313546
+ }
313547
+ return null;
313548
+ }
313549
+ var cleanName2;
313550
+ var init_controls = __esm({
313551
+ "lib/document/controls.ts"() {
313552
+ "use strict";
313553
+ cleanName2 = (raw) => raw.trim().replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
313554
+ }
313555
+ });
313556
+
313557
+ // lib/io/web/expressible.ts
313558
+ function expressibility(node2, styles) {
313559
+ const c2 = capability(node2, "css", styles);
313560
+ return { css: c2.reason === "", reason: c2.reason, needsRaster: c2.verdict === "raster" };
313561
+ }
313562
+ var init_expressible = __esm({
313563
+ "lib/io/web/expressible.ts"() {
313564
+ "use strict";
313565
+ init_capability();
313566
+ }
313567
+ });
313568
+
313569
+ // lib/io/web/responsive.ts
313570
+ function containerStyle(f2) {
313571
+ const out = {};
313572
+ if (isStack(f2) && f2.layoutWrap === "WRAP") {
313573
+ out["flex-wrap"] = "wrap";
313574
+ const cross2 = f2.counterAxisSpacing ?? f2.itemSpacing ?? 0;
313575
+ const main2 = f2.itemSpacing ?? 0;
313576
+ if (cross2 !== main2) out.gap = f2.layoutMode === "HORIZONTAL" ? `${cross2}px ${main2}px` : `${main2}px ${cross2}px`;
313577
+ out["align-content"] = "flex-start";
313578
+ }
313579
+ if (isGrid(f2)) {
313580
+ out.display = "grid";
313581
+ const cols = f2.layoutGridColumns ?? "AUTO";
313582
+ out["grid-template-columns"] = cols === "AUTO" ? `repeat(auto-fill, minmax(${f2.layoutGridMinColumnWidth ?? 100}px, 1fr))` : Array.from({ length: Math.max(1, cols) }, (_, i2) => track(f2.layoutGridColumnSizes?.[i2])).join(" ");
313583
+ const rows = f2.layoutGridRows ?? "AUTO";
313584
+ if (rows === "AUTO") out["grid-auto-rows"] = `minmax(${f2.layoutGridMinRowHeight ?? 100}px, auto)`;
313585
+ else out["grid-template-rows"] = Array.from({ length: Math.max(1, rows) }, (_, i2) => track(f2.layoutGridRowSizes?.[i2])).join(" ");
313586
+ const colGap = f2.itemSpacing ?? 0, rowGap = f2.counterAxisSpacing ?? colGap;
313587
+ out.gap = rowGap === colGap ? `${colGap}px` : `${rowGap}px ${colGap}px`;
313588
+ if (f2.padding) {
313589
+ out.padding = `${f2.padding.top}px ${f2.padding.right}px ${f2.padding.bottom}px ${f2.padding.left}px`;
313590
+ if (f2.padding.top || f2.padding.right || f2.padding.bottom || f2.padding.left) out["box-sizing"] = "border-box";
313591
+ }
313592
+ }
313593
+ const scroll = f2.overflowScrolling;
313594
+ if (scroll && scroll !== "NONE") {
313595
+ out["overflow-x"] = scroll === "HORIZONTAL" || scroll === "BOTH" ? "auto" : "hidden";
313596
+ out["overflow-y"] = scroll === "VERTICAL" || scroll === "BOTH" ? "auto" : "hidden";
313597
+ }
313598
+ return out;
313599
+ }
313600
+ function flowChild(node2, parent) {
313601
+ const style = { ...limits(node2) };
313602
+ const h = node2.layoutSizingHorizontal ?? "FIXED", v = node2.layoutSizingVertical ?? "FIXED";
313603
+ if (isGrid(parent)) {
313604
+ if (h !== "FIXED") style.width = h === "FILL" ? null : "fit-content";
313605
+ if (v !== "FIXED") style.height = null;
313606
+ return { style };
313607
+ }
313608
+ if (h === "FIXED" && style["max-width"] === void 0) style["max-width"] = "100%";
313609
+ const row2 = parent.layoutMode === "HORIZONTAL";
313610
+ const main2 = row2 ? h : v, cross2 = row2 ? v : h;
313611
+ const mainProp = row2 ? "width" : "height", crossProp = row2 ? "height" : "width";
313612
+ if (main2 === "FILL") {
313613
+ style[mainProp] = null;
313614
+ style.flex = "1 1 0";
313615
+ if (style[`min-${mainProp}`] === void 0) style[`min-${mainProp}`] = "0";
313616
+ } else {
313617
+ if (main2 === "HUG") style[mainProp] = null;
313618
+ style["flex-shrink"] = "0";
313619
+ }
313620
+ if (cross2 === "FILL") {
313621
+ style[crossProp] = null;
313622
+ style["align-self"] = "stretch";
313623
+ } else {
313624
+ if (cross2 === "HUG") style[crossProp] = null;
313625
+ if ((parent.counterAxisAlignItems ?? "MIN") === "MIN") style["align-self"] = "flex-start";
313626
+ }
313627
+ return { style };
313628
+ }
313629
+ function constrained(kind, pos, size6, parentSize, start2, end, sizeProp) {
313630
+ const far = parentSize - pos - size6;
313631
+ switch (kind) {
313632
+ case "MAX":
313633
+ return { place: { [end]: px4(far) }, style: {} };
313634
+ case "STRETCH":
313635
+ return { place: { [start2]: px4(pos), [end]: px4(far) }, style: { [sizeProp]: null } };
313636
+ // Its centre keeps its distance from the parent's centre.
313637
+ case "CENTER":
313638
+ return { place: { [start2]: `calc(50% + ${px4(pos - parentSize / 2)})` }, style: {} };
313639
+ case "SCALE":
313640
+ return parentSize > 0 ? { place: { [start2]: pct2(pos / parentSize) }, style: { [sizeProp]: pct2(size6 / parentSize) } } : { place: { [start2]: px4(pos) }, style: {} };
313641
+ default:
313642
+ return { place: { [start2]: px4(pos) }, style: {} };
313643
+ }
313644
+ }
313645
+ function placedChild(node2, parent, frame2 = parent) {
313646
+ const c2 = node2.constraints ?? { horizontal: "MIN", vertical: "MIN" };
313647
+ const x2 = constrained(c2.horizontal, node2.x, node2.width, frame2.width, "left", "right", "width");
313648
+ const y = constrained(c2.vertical, node2.y, node2.height, frame2.height, "top", "bottom", "height");
313649
+ return { style: { ...limits(node2), ...x2.style, ...y.style }, place: { position: "absolute", ...x2.place, ...y.place } };
313650
+ }
313651
+ function siteLayout(node2, parent, layout2) {
313652
+ const own2 = node2.type === "FRAME" || node2.type === "COMPONENT" || node2.type === "INSTANCE" ? node2 : null;
313653
+ if (!parent) {
313654
+ const grows = !own2 || laysOut(own2) || own2.overflowScrolling === "NONE" || !own2.overflowScrolling;
313655
+ return { style: { ...limits(node2), width: "100%", ...grows ? { height: null, "min-height": `max(${px4(node2.height)}, 100dvh)` } : {} }, place: { position: "relative" } };
313656
+ }
313657
+ const s = node2;
313658
+ return layout2 && laysOut(layout2) && s.layoutPositioning !== "ABSOLUTE" ? flowChild(s, layout2) : placedChild(s, parent, parent.type === "INSTANCE" && layout2 ? layout2 : parent);
313659
+ }
313660
+ var px4, pct2, isStack, isGrid, laysOut, track, limits;
313661
+ var init_responsive = __esm({
313662
+ "lib/io/web/responsive.ts"() {
313663
+ "use strict";
313664
+ px4 = (v) => `${Math.round(v * 100) / 100}px`;
313665
+ pct2 = (v) => `${Math.round(v * 1e4) / 100}%`;
313666
+ isStack = (f2) => f2?.layoutMode === "HORIZONTAL" || f2?.layoutMode === "VERTICAL";
313667
+ isGrid = (f2) => f2?.layoutMode === "GRID";
313668
+ laysOut = (f2) => isStack(f2) || isGrid(f2);
313669
+ track = (t3) => {
313670
+ if (!t3 || t3.sizing === "FILL") return t3?.value && /fr$/.test(t3.value) ? t3.value : "1fr";
313671
+ if (t3.sizing === "HUG") return "auto";
313672
+ return /^[\d.]+$/.test(t3.value) ? `${t3.value}px` : t3.value;
313673
+ };
313674
+ limits = (n) => {
313675
+ const out = {};
313676
+ if (n.minWidth !== void 0) out["min-width"] = px4(n.minWidth);
313677
+ if (n.maxWidth !== void 0) out["max-width"] = px4(n.maxWidth);
313678
+ if (n.minHeight !== void 0) out["min-height"] = px4(n.minHeight);
313679
+ if (n.maxHeight !== void 0) out["max-height"] = px4(n.maxHeight);
313680
+ return out;
313681
+ };
313682
+ }
313683
+ });
313684
+
313685
+ // lib/io/web/richtext.ts
313686
+ function runStyle(seg) {
313687
+ const out = {};
313688
+ if (seg.fontFamily) out["font-family"] = `"${seg.fontFamily}", system-ui, sans-serif`;
313689
+ if (seg.fontSize) out["font-size"] = `${seg.fontSize}px`;
313690
+ if (seg.fontWeight) out["font-weight"] = String(seg.fontWeight);
313691
+ if (seg.fontStyle) out["font-style"] = seg.fontStyle;
313692
+ if (seg.lineHeight !== void 0 && seg.lineHeight !== "AUTO") out["line-height"] = `${seg.lineHeight}px`;
313693
+ if (seg.textDecoration === "UNDERLINE") out["text-decoration"] = "underline";
313694
+ else if (seg.textDecoration === "STRIKETHROUGH") out["text-decoration"] = "line-through";
313695
+ else if (seg.textDecoration === "NONE") out["text-decoration"] = "none";
313696
+ if (seg.textCase === "UPPER") out["text-transform"] = "uppercase";
313697
+ else if (seg.textCase === "LOWER") out["text-transform"] = "lowercase";
313698
+ else if (seg.textCase === "TITLE") out["text-transform"] = "capitalize";
313699
+ else if (seg.textCase === "ORIGINAL") out["text-transform"] = "none";
313700
+ const solid4 = seg.fills?.find((f2) => f2.visible !== false && f2.type === "SOLID" && f2.color);
313701
+ if (solid4?.color) out.color = toHex(solid4.color);
313702
+ return out;
313703
+ }
313704
+ function textRuns(t3) {
313705
+ const text = t3.characters ?? "";
313706
+ const segs = [...t3.styledSegments ?? []].filter((s) => s.end > s.start).sort((a, b) => a.start - b.start);
313707
+ if (!segs.length && !t3.link) return void 0;
313708
+ const runs = [];
313709
+ const push2 = (from2, to, seg) => {
313710
+ if (to <= from2) return;
313711
+ const link2 = seg?.link ?? t3.link;
313712
+ runs.push({ text: text.slice(from2, to), style: seg ? runStyle(seg) : {}, ...link2 ? { link: link2 } : {} });
313713
+ };
313714
+ let at3 = 0;
313715
+ for (const s of segs) {
313716
+ const start2 = Math.max(at3, Math.min(text.length, s.start)), end = Math.min(text.length, s.end);
313717
+ push2(at3, start2);
313718
+ push2(start2, end, s);
313719
+ at3 = Math.max(at3, end);
313720
+ }
313721
+ push2(at3, text.length);
313722
+ return runs;
313723
+ }
313724
+ var init_richtext = __esm({
313725
+ "lib/io/web/richtext.ts"() {
313726
+ "use strict";
313727
+ init_paint2();
313728
+ }
313729
+ });
313730
+
313731
+ // lib/io/web/timeline.ts
313732
+ function frameWebMotion(doc2, frameId, style) {
313733
+ const nodes = doc2.nodes;
313734
+ const frame2 = nodes[frameId];
313735
+ if (!frame2 || !hasFrameMotion(nodes, frameId)) return null;
313736
+ const len3 = timelineDuration(nodes, frameId);
313737
+ if (!(len3 > 0)) return null;
313738
+ const steps = Math.max(1, Math.ceil(len3 / 1e3 * SAMPLE_RATE));
313739
+ const times2 = [];
313740
+ const poses = [];
313741
+ for (let i2 = 0; i2 <= steps; i2++) {
313742
+ const t3 = len3 * i2 / steps;
313743
+ times2.push(t3);
313744
+ poses.push(evaluatePose(nodes, { kind: "frame", frameId }, t3).nodes);
313745
+ }
313746
+ const ids2 = /* @__PURE__ */ new Set();
313747
+ for (const p2 of poses) for (const id3 in p2) if (id3 !== frameId && p2[id3] !== nodes[id3]) ids2.add(id3);
313748
+ const loops = frameRunsOn(nodes, frameId);
313749
+ const out = /* @__PURE__ */ new Map();
313750
+ const tag = frameId.replace(/[^a-zA-Z0-9]/g, "").slice(-6);
313751
+ let n = 0;
313752
+ for (const id3 of ids2) {
313753
+ const rest = id3.includes("::") ? resolveVirtualNode2(nodes, id3) : nodes[id3];
313754
+ if (!rest || !underFrame(nodes, id3, frameId)) continue;
313755
+ const frames = keyframesOf(times2, poses.map((p2) => declarationsOf(p2[id3] ?? rest, rest, style)), len3);
313756
+ if (!frames) continue;
313757
+ out.set(id3, {
313758
+ name: `timeline-${tag}-${n++}`,
313759
+ frames,
313760
+ durationMs: Math.round(len3),
313761
+ delayMs: 0,
313762
+ iterations: loops ? "infinite" : 1,
313763
+ direction: "normal",
313764
+ fill: "both"
313765
+ });
313766
+ }
313767
+ return out.size ? out : null;
313768
+ }
313769
+ function underFrame(nodes, id3, frameId) {
313770
+ const real = id3.split("::")[0];
313771
+ for (let n = nodes[real]; n; n = n.parentId ? nodes[n.parentId] : void 0) if (n.id === frameId) return true;
313772
+ return false;
313773
+ }
313774
+ var init_timeline = __esm({
313775
+ "lib/io/web/timeline.ts"() {
313776
+ "use strict";
313777
+ init_scene_graph();
313778
+ init_pose();
313779
+ init_instances2();
313780
+ init_keyframes();
313781
+ }
313782
+ });
313783
+
313784
+ // lib/io/web/tree.ts
313785
+ function anchorTargets(doc2) {
313786
+ const hit = anchorMemo.get(doc2.nodes);
313787
+ if (hit) return hit;
313788
+ const out = /* @__PURE__ */ new Set();
313789
+ for (const id3 in doc2.nodes) {
313790
+ const n = doc2.nodes[id3];
313791
+ if (n.semantics?.link?.kind === "anchor") out.add(n.semantics.link.nodeId);
313792
+ for (const ix of n.interactions ?? []) if (ix.action.link?.kind === "anchor" && ix.action.link.nodeId) out.add(ix.action.link.nodeId);
313793
+ }
313794
+ anchorMemo.set(doc2.nodes, out);
313795
+ return out;
313796
+ }
313797
+ function prepared(node2, doc2) {
313798
+ let n = node2;
313799
+ if (n.id.includes("::")) n = withInstanceBox(n, doc2.nodes);
313800
+ n = resolveNodeVariables(n, doc2.variables, doc2.variableCollections, doc2.activeVariableModes, exprData(doc2));
313801
+ n = resolveTextNodeStyles(n, doc2.styles ?? {});
313802
+ return n;
313803
+ }
313804
+ function layoutOf2(node2, nodes) {
313805
+ if (!node2) return null;
313806
+ if (node2.type === "INSTANCE") {
313807
+ const mainId = node2.mainComponentId;
313808
+ const main2 = mainId ? nodes[mainId] : void 0;
313809
+ return main2 ?? null;
313810
+ }
313811
+ if (node2.id.includes("::")) {
313812
+ const real = nodes[node2.id.split("::").pop()];
313813
+ return real ?? node2;
313814
+ }
313815
+ return node2;
313816
+ }
313817
+ function buildPlainTree(doc2, nodeId2, opts = {}, start2, hooks = {}) {
313818
+ const cap2 = opts.nodeCap ?? DEFAULT_NODE_CAP;
313819
+ const first2 = doc2.nodes[nodeId2] ?? (nodeId2.includes("::") ? childLookup(doc2, nodeId2) : void 0);
313820
+ if (!first2) throw new Error(`No node ${nodeId2}`);
313821
+ let emitted = 0;
313822
+ let truncated = false;
313823
+ let folds = 0;
313824
+ const tokens = opts.target === "site" && Object.keys(doc2.variables ?? {}).length ? siteTokens(doc2) : null;
313825
+ const anchored = anchorTargets(doc2);
313826
+ const pageItem = () => {
313827
+ const c2 = opts.item && doc2.collections?.[opts.item.collectionId];
313828
+ const r = opts.item && doc2.records?.[opts.item.recordId];
313829
+ return c2 && r ? { collection: c2, record: r, suffix: "" } : null;
313830
+ };
313831
+ let item = pageItem();
313832
+ const scopeOf2 = (it) => itemScope(it.collection, it.record, withData(variablesScope(doc2.variables, doc2.variableCollections, doc2.activeVariableModes), doc2));
313833
+ const itemised = (node2, raw, it) => itemNode(node2, raw, it.collection, it.record, scopeOf2(it));
313834
+ const itemLink = (link2, it) => {
313835
+ const filled2 = it && link2.kind === "url" ? { ...link2, url: itemText(link2.url, it.collection, it.record) } : it && (link2.kind === "email" || link2.kind === "tel") ? { ...link2, value: itemText(link2.value, it.collection, it.record) } : link2;
313836
+ if (filled2.kind === "screen") {
313837
+ const dest = doc2.nodes[filled2.frameId];
313838
+ const base = opts.routes?.[filled2.frameId];
313839
+ const of = dest?.route?.collectionId;
313840
+ if (of && base !== void 0) {
313841
+ const slugs = recordSlugs(doc2, of);
313842
+ const rec = it?.collection.id === of ? it.record.id : slugs.keys().next().value;
313843
+ const slug3 = rec ? slugs.get(rec) : void 0;
313844
+ return slug3 ? { link: filled2, href: `${base === "/" ? "" : base}/${slug3}`, screen: `${filled2.frameId}~${rec}` } : { link: filled2, href: null };
313845
+ }
313846
+ return { link: filled2, href: base ?? null, screen: filled2.frameId };
313847
+ }
313848
+ return { link: filled2, href: hrefOf(filled2, doc2.nodes, opts.routes) };
313849
+ };
313850
+ const fields = /* @__PURE__ */ new Map();
313851
+ const styleOpts = { fullImageUrl: opts.fullImageUrls ?? opts.target === "site" };
313852
+ const stylesOf = (n) => styleMapFor(n, doc2.styles, styleOpts);
313853
+ let motion = null;
313854
+ const timeline = !opts.static && !start2 && first2.type === "FRAME" ? frameWebMotion(doc2, first2.id, (n) => stylesOf(prepared(n, doc2))) : null;
313855
+ const build3 = (raw, parent, in3D2, fold) => {
313856
+ if (emitted >= cap2) {
313857
+ truncated = true;
313858
+ return null;
313859
+ }
313860
+ emitted++;
313861
+ const node2 = item ? itemised(prepared(raw, doc2), raw, item) : prepared(raw, doc2);
313862
+ const waits = node2.visible === false && parent !== null;
313863
+ if (waits && !(opts.target === "site" && followsVisibility(raw))) return null;
313864
+ const exp = expressibility(node2, doc2.styles);
313865
+ const f2 = layoutOf2(node2, doc2.nodes) ?? node2;
313866
+ const style = stylesOf(node2);
313867
+ if (f2 !== node2 && !style.display) Object.assign(style, flexDeclarations(f2));
313868
+ const through = in3D2 && passesThrough(raw, doc2.nodes);
313869
+ const own2 = typeof node2.opacity === "number" ? node2.opacity : 1;
313870
+ if (through) {
313871
+ style["transform-style"] = "preserve-3d";
313872
+ delete style.opacity;
313873
+ style[foldVar(fold + 1)] = fold ? `calc(var(${foldVar(fold)}) * ${round3(own2)})` : String(round3(own2));
313874
+ folds = Math.max(folds, fold + 1);
313875
+ } else if (fold) style.opacity = own2 === 1 ? `var(${foldVar(fold)})` : `calc(var(${foldVar(fold)}) * ${round3(own2)})`;
313876
+ if (own2 === 0) style["pointer-events"] = "none";
313877
+ if (clickable(raw) && !style.cursor) style.cursor = "pointer";
313878
+ const web = {
313879
+ id: item?.suffix ? `${node2.id}${item.suffix}` : node2.id,
313880
+ name: node2.name || node2.type,
313881
+ type: node2.type,
313882
+ x: Math.round(node2.x),
313883
+ y: Math.round(node2.y),
313884
+ width: Math.round(node2.width),
313885
+ height: Math.round(node2.height),
313886
+ // Absolutely-positioned auto-layout children are taken out of the flow, exactly as the canvas does.
313887
+ // A grid's children are in its flow too: its tracks place them.
313888
+ positioning: (isFlex(layoutOf2(parent, doc2.nodes)) || layoutOf2(parent, doc2.nodes)?.layoutMode === "GRID") && node2.layoutPositioning !== "ABSOLUTE" ? "flow" : "absolute",
313889
+ style,
313890
+ children: []
313891
+ };
313892
+ if (tokens) Object.assign(style, tokenStyle(raw, style, tokens));
313893
+ if (opts.target === "site") {
313894
+ const lay = siteLayout(node2, parent, layoutOf2(parent, doc2.nodes));
313895
+ for (const [k2, v] of Object.entries(lay.style)) {
313896
+ if (v === null) delete style[k2];
313897
+ else style[k2] = v;
313898
+ }
313899
+ if (laysOut(f2) || f2.overflowScrolling) Object.assign(style, containerStyle(f2));
313900
+ if (node2.type === "TEXT") {
313901
+ if (style["white-space"] === "pre") {
313902
+ style["white-space"] = "pre-wrap";
313903
+ style.width = "fit-content";
313904
+ }
313905
+ if (style["max-width"] === void 0) style["max-width"] = "100%";
313906
+ if (style.height && style.height !== "auto") {
313907
+ style["min-height"] = style.height;
313908
+ delete style.height;
313909
+ }
313910
+ }
313911
+ if (lay.place && (parent !== null || !start2?.parent)) web.place = lay.place;
313912
+ }
313913
+ if (waits) web.hidden = true;
313914
+ const sem = node2.semantics;
313915
+ if (sem) {
313916
+ if (sem.tag && sem.tag !== "div") web.tag = sem.tag;
313917
+ const attrs = {};
313918
+ if (sem.label) attrs["aria-label"] = sem.label;
313919
+ if (sem.hidden) attrs["aria-hidden"] = "true";
313920
+ if (Object.keys(attrs).length) web.attrs = attrs;
313921
+ const to = sem.link ? itemLink(sem.link, item) : null;
313922
+ if (to?.href) web.link = { href: to.href, ...opensNewTab(to.link) ? { newTab: true } : {}, ...to.screen ? { screen: to.screen } : {} };
313923
+ }
313924
+ const control = node2.control;
313925
+ if (control) {
313926
+ const named = control.name ? { name: control.name } : {};
313927
+ if (control.kind === "FORM") web.tag = "form";
313928
+ else if (control.kind === "BUTTON") {
313929
+ web.tag = "button";
313930
+ web.attrs = { ...web.attrs, type: control.buttonType ?? "submit", ...named, ...control.name && control.value !== void 0 ? { value: item && hasItemToken(control.value) ? itemText(control.value, item.collection, item.record) : control.value } : {} };
313931
+ } else if (control.kind === "CHECKBOX" || control.kind === "RADIO") {
313932
+ web.check = { attrs: { type: control.kind === "RADIO" ? "radio" : "checkbox", ...named, ...control.value !== void 0 ? { value: control.value } : {}, ...control.checked ? { checked: "" } : {}, ...control.required ? { required: "" } : {} }, ...control.variableId ? { variable: control.variableId } : {} };
313933
+ } else fields.set(fieldPart(doc2.nodes, raw.id) ?? raw.id, control);
313934
+ }
313935
+ const control0 = fields.get(raw.id);
313936
+ const field = control0 && item && control0.value !== void 0 && hasItemToken(control0.value) ? { ...control0, value: itemText(control0.value, item.collection, item.record) } : control0;
313937
+ if (field) {
313938
+ const tag = field.kind === "TEXTAREA" ? "textarea" : field.kind === "SELECT" ? "select" : "input";
313939
+ const words = node2.characters;
313940
+ web.input = {
313941
+ tag,
313942
+ attrs: {
313943
+ ...tag === "input" ? { type: field.inputType ?? "text" } : {},
313944
+ ...field.name ? { name: field.name } : {},
313945
+ ...tag !== "select" && (field.placeholder ?? words) ? { placeholder: field.placeholder ?? words } : {},
313946
+ ...field.required ? { required: "" } : {},
313947
+ ...tag === "input" && field.value !== void 0 ? { value: field.value } : {},
313948
+ "aria-label": node2.semantics?.label ?? field.placeholder ?? field.name ?? web.name
313949
+ },
313950
+ ...tag === "select" ? { options: field.options ?? [] } : {},
313951
+ ...tag !== "input" && field.value !== void 0 ? { value: field.value } : {},
313952
+ ...field.variableId ? { variable: field.variableId } : {}
313953
+ };
313954
+ }
313955
+ if (sem?.anchor || anchored.has(node2.id)) web.attrs = { ...web.attrs, id: anchorOf(node2) };
313956
+ if (through) web.preserve3d = true;
313957
+ web.tf = transformParts(node2);
313958
+ if (typeof node2.altText === "string") web.alt = node2.altText;
313959
+ if (parent === null) web.positioning = start2?.parent ? web.positioning : "flow";
313960
+ if (f2.layoutMode === "HORIZONTAL" || f2.layoutMode === "VERTICAL") {
313961
+ web.layout = {
313962
+ direction: f2.layoutMode === "HORIZONTAL" ? "row" : "column",
313963
+ gap: f2.itemSpacing ?? 0,
313964
+ justify: JUSTIFY[f2.primaryAxisAlignItems ?? "MIN"],
313965
+ align: ALIGN2[f2.counterAxisAlignItems ?? "MIN"],
313966
+ padding: f2.padding ?? { top: 0, right: 0, bottom: 0, left: 0 }
313967
+ };
313968
+ }
313969
+ if (node2.type === "TEXT") {
313970
+ const t3 = node2;
313971
+ const solid4 = (t3.fills ?? []).find((p2) => p2.visible !== false && p2.type === "SOLID" && p2.color);
313972
+ web.text = {
313973
+ characters: t3.characters ?? "",
313974
+ align: t3.textAlign,
313975
+ fontFamily: t3.fontFamily,
313976
+ fontSize: t3.fontSize,
313977
+ fontWeight: t3.fontWeight,
313978
+ italic: t3.fontStyle === "italic",
313979
+ ...solid4?.color ? { color: toHex(solid4.color) } : {},
313980
+ ...t3.letterSpacing ? { letterSpacing: t3.letterSpacing } : {},
313981
+ ...t3.lineHeight !== "AUTO" ? { lineHeight: t3.lineHeight } : {}
313982
+ };
313983
+ const runs = textRuns(t3);
313984
+ if (runs) web.runs = runs;
313985
+ }
313986
+ const tl = timeline?.get(node2.id);
313987
+ const mo = tl ?? motion?.children.get(node2.id);
313988
+ if (mo) web.motion = { style: animationStyle(mo, tl ? "load" : motion.trigger), keyframes: keyframesCSS(mo) };
313989
+ const ext = getNativeExtension(raw.type);
313990
+ if (ext?.toWeb) {
313991
+ const said = ext.toWeb(node2, { escape: escapeHTML, color: (c2) => toRgba({ ...c2, a: c2.a ?? 1 }) });
313992
+ if (said.tag) web.tag = said.tag;
313993
+ Object.assign(style, said.style);
313994
+ web.html = said.html;
313995
+ hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
313996
+ return web;
313997
+ }
313998
+ const code = opts.target === "site" ? codeOf(doc2.nodes, raw) : null;
313999
+ if (code && doc2.codeModules?.[code.moduleId]) {
314000
+ for (const k2 of PAINTED) delete style[k2];
314001
+ web.code = { module: code.moduleId, ...code.exportName ? { export: code.exportName } : {}, props: codeProps(doc2.nodes, node2) };
314002
+ hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
314003
+ return web;
314004
+ }
314005
+ if (!exp.css) {
314006
+ for (const k2 of PAINTED) delete style[k2];
314007
+ web.asset = { kind: opts.assetKind ?? (exp.needsRaster ? "png" : "svg"), reason: exp.reason, ...item?.suffix ? { of: node2.id } : {} };
314008
+ if (opts.target === "site" && renderMode(node2, { styles: doc2.styles, live: isLive(doc2.nodes, raw.id) }) === "island") web.island = true;
314009
+ hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
314010
+ return web;
314011
+ }
314012
+ const lost = capability(node2, "css", doc2.styles).dropped.find((f3) => f3.startsWith("paint:"));
314013
+ if (lost && !node2.id.includes("::")) {
314014
+ const site = opts.target === "site";
314015
+ style.isolation = "isolate";
314016
+ web.children.push({
314017
+ id: `${node2.id}/backdrop${item?.suffix ?? ""}`,
314018
+ name: `${web.name} fill`,
314019
+ type: "BACKDROP",
314020
+ x: 0,
314021
+ y: 0,
314022
+ width: web.width,
314023
+ height: web.height,
314024
+ positioning: "absolute",
314025
+ ...site ? { place: { position: "absolute", inset: "0" } } : {},
314026
+ style: { ...site ? {} : { width: `${web.width}px`, height: `${web.height}px` }, "border-radius": "inherit", overflow: "hidden", "z-index": "-1", "pointer-events": "none" },
314027
+ alt: "",
314028
+ asset: { kind: "png", reason: featureName(lost), of: node2.id, self: true },
314029
+ ...site && movesItself(raw) ? { island: true } : {},
314030
+ children: []
314031
+ });
314032
+ }
314033
+ const outer = motion;
314034
+ if (!motion && node2.type === "INSTANCE" && !opts.static) {
314035
+ motion = instanceWebMotion(doc2, node2, (n) => stylesOf(prepared(n, doc2)));
314036
+ if (motion && (motion.trigger !== "load" || opts.target === "site")) web.motionTrigger = motion.trigger;
314037
+ }
314038
+ try {
314039
+ if (opts.includeChildren !== false) {
314040
+ const kids3D = in3D2 ? through : is3DContext(raw) && !raw.id.includes("::");
314041
+ const kidFold = through ? fold + 1 : 0;
314042
+ const repeat = raw.repeat;
314043
+ const collection = repeat && doc2.collections?.[repeat.collectionId];
314044
+ if (repeat && collection && opts.target === "site") {
314045
+ const outerItem = item;
314046
+ const under = outerItem ? scopeOf2(outerItem) : withData(variablesScope(doc2.variables, doc2.variableCollections, doc2.activeVariableModes), doc2);
314047
+ try {
314048
+ for (const record2 of repeatRecords(doc2, repeat, under)) {
314049
+ item = { collection, record: record2, suffix: `${outerItem?.suffix ?? ""}~${record2.id}` };
314050
+ for (const child of childrenOf(node2, doc2.nodes)) {
314051
+ const built = build3(child, node2, kids3D, kidFold);
314052
+ if (built) web.children.push(built);
314053
+ }
314054
+ }
314055
+ if (collection.perVisitor && !outerItem) {
314056
+ item = { collection, record: templateRecord(collection), suffix: `~${ITEM_RECORD}` };
314057
+ const template2 = [];
314058
+ for (const child of childrenOf(node2, doc2.nodes)) {
314059
+ const built = build3(child, node2, kids3D, kidFold);
314060
+ if (built) template2.push(built);
314061
+ }
314062
+ const sortField = repeat.sort && collection.fields.find((f3) => f3.id === repeat.sort.fieldId);
314063
+ web.repeat = {
314064
+ collectionId: collection.id,
314065
+ template: template2,
314066
+ ...repeat.filter?.trim() ? { filter: repeat.filter } : {},
314067
+ ...sortField ? { sort: { key: fieldKey(sortField.name), dir: repeat.sort.dir } } : {},
314068
+ ...repeat.offset ? { offset: repeat.offset } : {},
314069
+ ...repeat.limit ? { limit: repeat.limit } : {}
314070
+ };
314071
+ }
314072
+ } finally {
314073
+ item = outerItem;
314074
+ }
314075
+ } else for (const child of childrenOf(node2, doc2.nodes)) {
314076
+ const built = build3(child, node2, kids3D, kidFold);
314077
+ if (built) web.children.push(built);
314078
+ }
314079
+ }
314080
+ } finally {
314081
+ motion = outer;
314082
+ }
314083
+ if (web.children.some((c2) => c2.positioning === "absolute")) {
314084
+ for (const c2 of web.children) if (c2.positioning === "flow") c2.layered = true;
314085
+ }
314086
+ hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
314087
+ return web;
314088
+ };
314089
+ const root2 = build3(first2, start2?.parent ?? null, start2?.in3D ?? false, start2?.fold ?? 0);
314090
+ if (!root2) throw new Error("Node cap of 0");
314091
+ return { root: root2, truncated, ...folds ? { rules: foldRules(folds) } : {}, ...tokens?.vars.length ? { tokens } : {} };
314092
+ }
314093
+ function childLookup(doc2, id3) {
314094
+ const at3 = id3.lastIndexOf("::");
314095
+ const host = at3 > 0 ? id3.slice(0, at3) : "";
314096
+ const hostNode = doc2.nodes[host] ?? (host.includes("::") ? childLookup(doc2, host) : void 0);
314097
+ return hostNode ? childrenOf(hostNode, doc2.nodes).find((c2) => c2.id === id3) : void 0;
314098
+ }
314099
+ function flatten2(node2, out = []) {
314100
+ out.push(node2);
314101
+ for (const c2 of node2.children) flatten2(c2, out);
314102
+ return out;
314103
+ }
314104
+ var DEFAULT_NODE_CAP, PAINTED, anchorMemo, followsVisibility, isFlex, round3, foldVar, foldRules, clickable;
314105
+ var init_tree = __esm({
314106
+ "lib/io/web/tree.ts"() {
314107
+ "use strict";
314108
+ init_instance_layout();
314109
+ init_text_styles();
314110
+ init_variables();
314111
+ init_scene3d();
314112
+ init_semantics();
314113
+ init_collections();
314114
+ init_props();
314115
+ init_native_registry();
314116
+ init_controls();
314117
+ init_expressions2();
314118
+ init_children();
314119
+ init_css();
314120
+ init_capability();
314121
+ init_expressible();
314122
+ init_motion();
314123
+ init_element();
314124
+ init_paint2();
314125
+ init_responsive();
314126
+ init_richtext();
314127
+ init_tokens2();
314128
+ init_timeline();
314129
+ init_interactive();
314130
+ DEFAULT_NODE_CAP = 120;
314131
+ PAINTED = ["background", "border", "border-style", "border-color", "border-width", "outline", "border-radius", "box-shadow", "box-sizing", "filter", "backdrop-filter"];
314132
+ anchorMemo = /* @__PURE__ */ new WeakMap();
314133
+ followsVisibility = (n) => !!n.boundVariables?.visible || !!n.boundExpressions?.visible || // Hidden in the design and shown at a breakpoint: on the page, for the media query that shows it.
314134
+ Object.values(n.responsive ?? {}).some((o) => o.visible === true);
314135
+ isFlex = (f2) => f2?.layoutMode === "HORIZONTAL" || f2?.layoutMode === "VERTICAL";
314136
+ round3 = (v) => Math.round(v * 1e3) / 1e3;
314137
+ foldVar = (depth2) => `--pc-f${depth2}`;
314138
+ foldRules = (depth2) => Array.from({ length: depth2 }, (_, i2) => `@property ${foldVar(i2 + 1)} { syntax: '<number>'; inherits: true; initial-value: 1; }`);
314139
+ clickable = (n) => !!n.semantics?.link || (n.interactions ?? []).some((ix) => ix.trigger === "ON_CLICK" || ix.trigger === "ON_PRESS");
314140
+ }
314141
+ });
314142
+
314143
+ // lib/io/web/interactive.ts
314144
+ function subtreeIds(doc2, id3, out = /* @__PURE__ */ new Set()) {
314145
+ if (out.has(id3)) return out;
314146
+ const n = doc2.nodes[id3];
314147
+ if (!n) return out;
314148
+ out.add(id3);
314149
+ if (n.type === "INSTANCE") subtreeIds(doc2, n.mainComponentId, out);
314150
+ for (const c2 of n.childIds ?? []) subtreeIds(doc2, c2, out);
314151
+ return out;
314152
+ }
314153
+ function flowScreens(doc2, startId) {
314154
+ const start2 = doc2.nodes[startId];
314155
+ if (!start2 || start2.type !== "FRAME" || doc2.nodes[start2.parentId ?? ""]?.type !== "PAGE") return [startId];
314156
+ const out = [startId];
314157
+ for (let i2 = 0; i2 < out.length; i2++) {
314158
+ for (const id3 of subtreeIds(doc2, out[i2])) {
314159
+ for (const ix of interactionsOf(doc2.nodes[id3])) {
314160
+ const to = ix.action.navigationType === "NAVIGATE" ? ix.action.destinationId : null;
314161
+ const dest = to ? doc2.nodes[to] : void 0;
314162
+ if (!dest || out.includes(dest.id) || dest.type !== "FRAME" || doc2.nodes[dest.parentId ?? ""]?.type !== "PAGE") continue;
314163
+ if (Math.round(dest.width) !== Math.round(start2.width) || Math.round(dest.height) !== Math.round(start2.height)) continue;
314164
+ out.push(dest.id);
314165
+ }
314166
+ }
314167
+ }
314168
+ return out;
314169
+ }
314170
+ function variantStates(doc2, mainId) {
314171
+ const out = [mainId];
314172
+ for (let i2 = 0; i2 < out.length; i2++) {
314173
+ for (const id3 of subtreeIds(doc2, out[i2])) {
314174
+ for (const ix of interactionsOf(doc2.nodes[id3])) {
314175
+ const to = ix.action.navigationType === "CHANGE_TO" ? ix.action.destinationId : null;
314176
+ if (to && !out.includes(to) && doc2.nodes[to]?.type === "COMPONENT") out.push(to);
314177
+ }
314178
+ }
314179
+ }
314180
+ return out;
314181
+ }
314182
+ function buildState(ctx2, doc2, id3, machine, state, start2, variantOf2) {
314183
+ const expand = /* @__PURE__ */ new Map();
314184
+ const tree = buildPlainTree(doc2, id3, ctx2.opts, start2, { built: (web, _node, at3) => {
314185
+ if (web.type === "INSTANCE") expand.set(web, at3);
314186
+ } });
314187
+ for (const r of tree.rules ?? []) ctx2.rules.add(r);
314188
+ if (tree.truncated) ctx2.truncated = true;
314189
+ const ids2 = /* @__PURE__ */ new Map();
314190
+ const index2 = (w) => {
314191
+ ids2.set(w.id, w);
314192
+ w.children.forEach(index2);
314193
+ };
314194
+ index2(tree.root);
314195
+ const visit2 = (w, owner, st, isRoot) => {
314196
+ w.owner = owner;
314197
+ w.looks = { [st]: lookOf(w, isRoot) };
314198
+ if (w.motion) ctx2.keyframes.add(w.motion.keyframes);
314199
+ const node2 = nodeOf(doc2, w.id);
314200
+ note(ctx2, w, interactionsOf(doc2.nodes[realId(w.id)]), owner, st, ids2);
314201
+ const at3 = expand.get(w);
314202
+ const inst = node2?.type === "INSTANCE" ? node2 : void 0;
314203
+ const states = inst && at3 && ctx2.depth < 4 ? variantStates(doc2, inst.mainComponentId) : [];
314204
+ if (inst && at3 && states.length > 1 && w.id !== variantOf2) {
314205
+ const m = { id: `m${ctx2.machines.length}`, initial: inst.mainComponentId, states: states.map((s) => ({ id: s, name: stateName(doc2, s) })) };
314206
+ ctx2.machines.push(m);
314207
+ w.machine = m;
314208
+ const perState = [];
314209
+ for (const s of states) {
314210
+ let kids;
314211
+ if (s === inst.mainComponentId) {
314212
+ kids = w.children;
314213
+ kids.forEach((c2) => visit2(c2, m.id, s, false));
314214
+ } else {
314215
+ const shown2 = { ...doc2, nodes: { ...doc2.nodes, [inst.id]: { ...inst, mainComponentId: s } } };
314216
+ ctx2.depth++;
314217
+ try {
314218
+ kids = buildState(ctx2, shown2, inst.id, m.id, s, at3, inst.id).children;
314219
+ } finally {
314220
+ ctx2.depth--;
314221
+ }
314222
+ }
314223
+ note(ctx2, w, interactionsOf(doc2.nodes[s]), m.id, s, ids2, m.id);
314224
+ perState.push([s, kids]);
314225
+ }
314226
+ w.children = mergeChildren(perState, m.id, m.states.map((s) => s.id), ctx2);
314227
+ } else if (w.id === variantOf2) {
314228
+ w.children.forEach((c2) => visit2(c2, owner, st, false));
314229
+ } else {
314230
+ if (inst) note(ctx2, w, interactionsOf(doc2.nodes[inst.mainComponentId]), owner, st, ids2);
314231
+ w.children.forEach((c2) => visit2(c2, owner, st, false));
314232
+ }
314233
+ };
314234
+ visit2(tree.root, machine, state, !start2);
314235
+ return tree.root;
314236
+ }
314237
+ function note(ctx2, w, list2, machine, state, ids2, hostMachine) {
314238
+ if (!list2.length) return;
314239
+ const at3 = ctx2.pending.get(w) ?? [];
314240
+ for (const ix of list2) at3.push({ machine, state, ix, hostMachine: hostMachine ?? (machine !== FLOW ? machine : void 0), ids: ids2 });
314241
+ ctx2.pending.set(w, at3);
314242
+ }
314243
+ function lookOf(w, isRoot) {
314244
+ return {
314245
+ style: { ...placementStyle(w, isRoot), ...w.style, ...w.motion?.style ?? {} },
314246
+ ...w.text ? { text: w.text.characters } : {},
314247
+ ...w.tf ? { tf: w.tf } : {}
314248
+ };
314249
+ }
314250
+ function keyed(kids) {
314251
+ const seen = /* @__PURE__ */ new Map();
314252
+ return kids.map((k2) => {
314253
+ const base = `${k2.name}\0${k2.type}`;
314254
+ const i2 = seen.get(base) ?? 0;
314255
+ seen.set(base, i2 + 1);
314256
+ return [`${base}\0${i2}`, k2];
314257
+ });
314258
+ }
314259
+ function mergeChildren(perState, machine, states, ctx2) {
314260
+ const order2 = [];
314261
+ const groups = /* @__PURE__ */ new Map();
314262
+ for (const [state, kids] of perState) {
314263
+ let after = -1;
314264
+ for (const [k2, node2] of keyed(kids)) {
314265
+ let at3 = order2.indexOf(k2);
314266
+ if (at3 < 0) {
314267
+ order2.splice(after + 1, 0, k2);
314268
+ at3 = after + 1;
314269
+ }
314270
+ after = at3;
314271
+ (groups.get(k2) ?? groups.set(k2, []).get(k2)).push([state, node2]);
314272
+ }
314273
+ }
314274
+ return order2.map((k2) => mergeNode(groups.get(k2), machine, states, ctx2));
314275
+ }
314276
+ function mergeNode(items, machine, states, ctx2) {
314277
+ const [, first2] = items[0];
314278
+ if (first2.owner !== machine) {
314279
+ for (const [, w] of items.slice(1)) alias(ctx2, w, first2);
314280
+ return first2;
314281
+ }
314282
+ const looks = {};
314283
+ for (const s of states) looks[s] = null;
314284
+ for (const [s, w] of items) looks[s] = w.looks?.[s] ?? null;
314285
+ const merged = { ...first2, looks };
314286
+ const pend = items.flatMap(([, w]) => ctx2.pending.get(w) ?? []);
314287
+ if (pend.length) ctx2.pending.set(merged, pend);
314288
+ for (const [, w] of items) if (w !== merged) alias(ctx2, w, merged);
314289
+ if (first2.machine) {
314290
+ for (const [, w] of items) if (w.machine && w.machine !== first2.machine) ctx2.renamed.set(w.machine.id, first2.machine.id);
314291
+ }
314292
+ merged.children = first2.machine ? first2.children : mergeChildren(items.map(([s, w]) => [s, w.children]), machine, states, ctx2);
314293
+ return merged;
314294
+ }
314295
+ function alias(ctx2, from2, to) {
314296
+ const a = ctx2.alias ??= /* @__PURE__ */ new Map();
314297
+ a.set(from2, to);
314298
+ }
314299
+ function mergedOf(ctx2, w) {
314300
+ const a = ctx2.alias;
314301
+ let cur = w;
314302
+ for (let i2 = 0; i2 < 16 && a?.has(cur); i2++) cur = a.get(cur);
314303
+ return cur;
314304
+ }
314305
+ function actionOf(ctx2, p2) {
314306
+ const a = p2.ix.action;
314307
+ const glide2 = glideOf2(a.transition);
314308
+ const hold = p2.ix.trigger === "ON_HOVER" || p2.ix.trigger === "ON_PRESS";
314309
+ switch (a.navigationType) {
314310
+ case "NAVIGATE":
314311
+ return a.destinationId && ctx2.screens.has(a.destinationId) ? { kind: "go", machine: FLOW, to: a.destinationId, ...glide2, ...hold ? { hold } : {} } : null;
314312
+ case "BACK":
314313
+ return ctx2.screens.size > 1 ? { kind: "back", machine: FLOW } : null;
314314
+ case "CHANGE_TO":
314315
+ return p2.hostMachine && a.destinationId ? { kind: "go", machine: p2.hostMachine, to: a.destinationId, ...glide2, ...hold ? { hold } : {} } : null;
314316
+ case "ORBIT_3D": {
314317
+ const o = a.orbit ?? {};
314318
+ const uidOf = (id3) => {
314319
+ const w = id3 ? p2.ids.get(id3) : void 0;
314320
+ return w ? mergedOf(ctx2, w).uid : void 0;
314321
+ };
314322
+ const uid2 = uidOf(a.destinationId);
314323
+ const tiltUid = uidOf(o.tiltLayerId) ?? uid2;
314324
+ return uid2 === void 0 || tiltUid === void 0 ? null : { kind: "orbit", target: uid2, tiltTarget: tiltUid, degreesPerPx: o.degreesPerPx ?? 0.4, tilt: !!o.tilt, tiltRange: o.tiltRange ?? [-30, 30] };
314325
+ }
314326
+ default:
314327
+ return null;
314328
+ }
314329
+ }
314330
+ function buildWebTree(doc2, nodeId2, opts = {}) {
314331
+ const tree = buildTree(doc2, nodeId2, opts);
314332
+ const machine = opts.static || opts.stateMachine === false ? null : webStateMachine(doc2, nodeId2);
314333
+ return machine ? { ...tree, stateMachine: machine } : tree;
314334
+ }
314335
+ function buildTree(doc2, nodeId2, opts = {}) {
314336
+ if (opts.static || opts.target === "site") return buildPlainTree(doc2, nodeId2, opts);
314337
+ const screens = flowScreens(doc2, nodeId2);
314338
+ const anything = screens.length > 1 || [...subtreeIds(doc2, nodeId2)].some((id3) => interactionsOf(doc2.nodes[id3]).some((ix) => ix.action.navigationType === "CHANGE_TO" || ix.action.navigationType === "ORBIT_3D"));
314339
+ if (!anything) return buildPlainTree(doc2, nodeId2, opts);
314340
+ const flow = { id: FLOW, initial: nodeId2, states: screens.map((s) => ({ id: s, name: doc2.nodes[s]?.name ?? s })) };
314341
+ const ctx2 = { doc: doc2, opts, screens: new Set(screens), machines: [flow], keyframes: /* @__PURE__ */ new Set(), rules: /* @__PURE__ */ new Set(), pending: /* @__PURE__ */ new Map(), depth: 0, renamed: /* @__PURE__ */ new Map() };
314342
+ const roots = screens.map((s) => [s, buildState(ctx2, doc2, s, FLOW, s)]);
314343
+ const truncated = !!ctx2.truncated;
314344
+ const root2 = mergeNode(roots, FLOW, screens, ctx2);
314345
+ let uid2 = 0;
314346
+ const number4 = (w) => {
314347
+ w.uid = uid2++;
314348
+ w.children.forEach(number4);
314349
+ };
314350
+ number4(root2);
314351
+ const place3 = (w) => {
314352
+ const pend = ctx2.pending.get(w);
314353
+ if (pend) {
314354
+ const seen = /* @__PURE__ */ new Set();
314355
+ const on = [];
314356
+ for (const raw of pend) {
314357
+ const p2 = { ...raw, machine: ctx2.renamed.get(raw.machine) ?? raw.machine, ...raw.hostMachine ? { hostMachine: ctx2.renamed.get(raw.hostMachine) ?? raw.hostMachine } : {} };
314358
+ const trigger = TRIGGERS[p2.ix.trigger];
314359
+ const action3 = trigger ? actionOf(ctx2, p2) : null;
314360
+ if (!trigger || !action3) continue;
314361
+ const ix = { machine: p2.machine, state: p2.state, trigger, ...p2.ix.triggerDelay ? { delay: p2.ix.triggerDelay } : {}, ...p2.ix.triggerKey ? { key: p2.ix.triggerKey } : {}, action: action3 };
314362
+ const sig = JSON.stringify(ix);
314363
+ if (!seen.has(sig)) {
314364
+ seen.add(sig);
314365
+ on.push(ix);
314366
+ }
314367
+ }
314368
+ if (on.length) w.on = on;
314369
+ }
314370
+ w.children.forEach(place3);
314371
+ };
314372
+ place3(root2);
314373
+ return { root: root2, truncated, ...ctx2.rules.size ? { rules: [...ctx2.rules].sort() } : {}, interactive: { machines: ctx2.machines.filter((m) => !ctx2.renamed.has(m.id)), keyframes: [...ctx2.keyframes] } };
314374
+ }
314375
+ var FLOW, interactionsOf, realId, nodeOf, stateName, TRIGGERS, EASINGS2, glideOf2;
314376
+ var init_interactive = __esm({
314377
+ "lib/io/web/interactive.ts"() {
314378
+ "use strict";
314379
+ init_scene_graph();
314380
+ init_tree();
314381
+ init_state_machine3();
314382
+ init_element();
314383
+ FLOW = "flow";
314384
+ interactionsOf = (n) => n?.interactions ?? [];
314385
+ realId = (id3) => id3.includes("::") ? id3.slice(id3.lastIndexOf("::") + 2) : id3;
314386
+ nodeOf = (doc2, id3) => doc2.nodes[id3] ?? (id3.includes("::") ? resolveVirtualNode2(doc2.nodes, id3) ?? void 0 : void 0);
314387
+ stateName = (doc2, id3) => {
314388
+ const n = doc2.nodes[id3];
314389
+ const v = n?.variantProperties;
314390
+ return v ? Object.values(v).join(", ") : n?.name ?? id3;
314391
+ };
314392
+ TRIGGERS = {
314393
+ ON_CLICK: "click",
314394
+ ON_HOVER: "hover",
314395
+ ON_PRESS: "press",
314396
+ ON_DRAG: "drag",
314397
+ MOUSE_ENTER: "enter",
314398
+ MOUSE_LEAVE: "leave",
314399
+ AFTER_TIMEOUT: "timeout",
314400
+ KEY_DOWN: "key"
314401
+ };
314402
+ EASINGS2 = { EASE_IN: "ease-in", EASE_OUT: "ease-out", EASE_IN_OUT: "ease-in-out", LINEAR: "linear", SPRING: "cubic-bezier(0.34, 1.56, 0.64, 1)" };
314403
+ glideOf2 = (t3) => !t3 || t3.type === "INSTANT" || t3.type === "CUT" ? { ms: 0, easing: "linear" } : { ms: Math.max(0, Math.round(t3.duration)), easing: EASINGS2[t3.easing] ?? "ease-in-out" };
314404
+ }
314405
+ });
314406
+
314407
+ // lib/io/web/site.ts
314408
+ function light(node2) {
314409
+ const out = {};
314410
+ for (const k2 in node2) if (!HEAVY.has(k2)) out[k2] = node2[k2];
314411
+ return out;
314412
+ }
314413
+ function programDocument(doc2, pageId2, screens) {
314414
+ const nodes = {};
314415
+ const take = (id3) => {
314416
+ const n = doc2.nodes[id3];
314417
+ if (!n || nodes[id3]) return;
314418
+ nodes[id3] = light(n);
314419
+ for (const c2 of n.childIds ?? []) take(c2);
314420
+ const main2 = n.mainComponentId;
314421
+ if (main2) {
314422
+ take(main2);
314423
+ const set3 = doc2.nodes[main2]?.parentId;
314424
+ if (set3 && doc2.nodes[set3]?.type === "COMPONENT_SET") take(set3);
314425
+ }
314426
+ };
314427
+ const page = doc2.nodes[pageId2];
314428
+ if (page) nodes[pageId2] = { ...light(page), childIds: screens.map((s) => s.id) };
314429
+ for (const s of screens) take(s.id);
314430
+ return {
314431
+ id: doc2.id,
314432
+ name: doc2.name,
314433
+ nodes,
314434
+ pages: [pageId2],
314435
+ styles: {},
314436
+ variables: doc2.variables,
314437
+ variableCollections: doc2.variableCollections,
314438
+ activeVariableModes: doc2.activeVariableModes,
314439
+ settings: doc2.settings,
314440
+ // What a layer that follows a record's field is drawn from, while the page runs.
314441
+ ...doc2.collections && Object.keys(doc2.collections).length ? { collections: doc2.collections, records: doc2.records } : {}
314442
+ };
314443
+ }
314444
+ function withVariants(doc2, root2, opts, depth2 = 3) {
314445
+ if (depth2 <= 0) return;
314446
+ for (const w of flatten2(root2)) {
314447
+ const real = layerId(w.id), suffix = copySuffix(w.id);
314448
+ const inst = w.type === "INSTANCE" && !real.includes("::") ? doc2.nodes[real] : void 0;
314449
+ const main2 = inst?.mainComponentId;
314450
+ if (!inst || !main2 || w.variants) continue;
314451
+ const reach = variantStates(doc2, main2);
314452
+ if (reach.length < 2) continue;
314453
+ w.variant = main2;
314454
+ w.variants = {};
314455
+ const parent = inst.parentId ? doc2.nodes[inst.parentId] ?? null : null;
314456
+ const record2 = suffix ? doc2.records?.[copyRecord(w.id) ?? ""] : void 0;
314457
+ const as3 = record2 ? { ...opts, item: { collectionId: record2.collectionId, recordId: record2.id } } : opts;
314458
+ for (const v of reach.slice(1)) {
314459
+ const as2 = { ...doc2, nodes: { ...doc2.nodes, [inst.id]: { ...inst, mainComponentId: v } } };
314460
+ const built = buildPlainTree(as2, inst.id, as3, { parent, in3D: false, fold: 0 }).root;
314461
+ if (suffix) for (const n of flatten2(built)) n.id += suffix;
314462
+ built.variant = v;
314463
+ withVariants(as2, built, opts, depth2 - 1);
314464
+ w.variants[v] = built;
314465
+ }
314466
+ }
314467
+ }
314468
+ function everyNode(root2, out = []) {
314469
+ for (const n of flatten2(root2)) {
314470
+ out.push(n);
314471
+ for (const v of Object.values(n.variants ?? {})) everyNode(v, out);
314472
+ }
314473
+ return out;
314474
+ }
314475
+ function mediaRules(doc2, screenId, base, opts) {
314476
+ const rules = [];
314477
+ let above = new Map(flatten2(base).map((n) => [n.id, declared(n, n === base)]));
314478
+ for (const bp of breakpointsOf(doc2).slice(1)) {
314479
+ const view2 = breakpointDocument(doc2, bp.id);
314480
+ const root2 = buildPlainTree(view2, screenId, opts).root;
314481
+ const here = new Map(flatten2(root2).map((n) => [n.id, declared(n, n === root2)]));
314482
+ const blocks = [];
314483
+ for (const [id3, was] of above) {
314484
+ const now2 = here.get(id3);
314485
+ const diff = {};
314486
+ if (!now2) {
314487
+ if (was.display !== "none") diff.display = "none";
314488
+ } else {
314489
+ for (const k2 in was) if (!(k2 in now2)) diff[k2] = "revert";
314490
+ for (const k2 in now2) if (now2[k2] !== was[k2]) diff[k2] = now2[k2];
314491
+ }
314492
+ if (Object.keys(diff).length) blocks.push(` [data-pc-id="${id3}"] {
314493
+ ${styleMapToCSSText(Object.fromEntries(Object.entries(diff).map(([k2, v]) => [k2, `${v} !important`])), " ")}
314494
+ }`);
314495
+ }
314496
+ if (blocks.length) rules.push(`@media (max-width: ${bp.maxWidth}px) {
314497
+ ${blocks.join("\n")}
314498
+ }`);
314499
+ above = new Map([...above].map(([id3, was]) => [id3, here.get(id3) ?? { ...was, display: "none" }]));
314500
+ }
314501
+ return rules;
314502
+ }
314503
+ function sitePages(doc2, pageId2) {
314504
+ const screens = screensOf(doc2, pageId2);
314505
+ const routes = routesOf(screens);
314506
+ return screens.flatMap((s) => {
314507
+ const base = routes.get(s.id);
314508
+ const collection = s.route?.collectionId ? doc2.collections?.[s.route.collectionId] : void 0;
314509
+ if (!collection) return [{ id: s.id, frame: s, route: base, title: s.route?.title || s.name }];
314510
+ const slugs = recordSlugs(doc2, collection.id);
314511
+ return recordsIn(doc2, collection.id).map((record2) => ({
314512
+ id: `${s.id}~${record2.id}`,
314513
+ frame: s,
314514
+ record: record2,
314515
+ collection,
314516
+ route: `${base === "/" ? "" : base}/${slugs.get(record2.id)}`,
314517
+ title: itemText(s.route?.title || s.name, collection, record2)
314518
+ }));
314519
+ });
314520
+ }
314521
+ function screenTransitions3d(doc2, screens) {
314522
+ const out = /* @__PURE__ */ new Set();
314523
+ const turns = (a) => {
314524
+ if (!a) return [];
314525
+ if (a.navigationType === "CONDITIONAL") return (a.branches ?? []).flatMap((b) => b.actions.flatMap(turns));
314526
+ return a.navigationType === "NAVIGATE" && a.destinationId && a.transition && is3DTransition(a.transition.type) ? [a.destinationId] : [];
314527
+ };
314528
+ for (const s of screens) {
314529
+ const seen = /* @__PURE__ */ new Set();
314530
+ const walk3 = (id3) => {
314531
+ const n = doc2.nodes[id3];
314532
+ if (!n || seen.has(id3)) return;
314533
+ seen.add(id3);
314534
+ for (const ix of n.interactions ?? []) for (const to of turns(ix.action)) {
314535
+ out.add(s.id);
314536
+ out.add(to);
314537
+ }
314538
+ for (const c2 of n.childIds ?? []) walk3(c2);
314539
+ const main2 = n.mainComponentId;
314540
+ if (main2) walk3(main2);
314541
+ };
314542
+ walk3(s.id);
314543
+ }
314544
+ return out;
314545
+ }
314546
+ function withoutScreenIslands(site) {
314547
+ if (!site.islands) return site;
314548
+ const kept = Object.entries(site.islands).filter(([k2]) => !k2.startsWith(SCREEN_ISLAND));
314549
+ if (kept.length === Object.keys(site.islands).length) return site;
314550
+ const { islands: _, ...rest } = site;
314551
+ return kept.length ? { ...rest, islands: Object.fromEntries(kept) } : rest;
314552
+ }
314553
+ function buildWebSite(doc2, opts = {}) {
314554
+ const pageId2 = opts.pageId ?? doc2.pages[0];
314555
+ const screens = screensOf(doc2, pageId2);
314556
+ const routes = routesOf(screens);
314557
+ const build3 = { target: "site", nodeCap: opts.nodeCap ?? 2e4, static: opts.static, routes: Object.fromEntries(routes) };
314558
+ const laid = /* @__PURE__ */ new Set();
314559
+ const pages2 = sitePages(doc2, pageId2).map((p2) => {
314560
+ const s = p2.frame;
314561
+ const opts2 = p2.record ? { ...build3, item: { collectionId: p2.collection.id, recordId: p2.record.id } } : build3;
314562
+ const tree = buildPlainTree(doc2, s.id, opts2);
314563
+ const media2 = laid.has(s.id) ? [] : mediaRules(doc2, s.id, tree.root, opts2);
314564
+ laid.add(s.id);
314565
+ withVariants(doc2, tree.root, opts2);
314566
+ const description = s.route?.description ? p2.record ? itemText(s.route.description, p2.collection, p2.record) : s.route.description : void 0;
314567
+ const moves3 = !opts2.static && hasFrameMotion(doc2.nodes, s.id);
314568
+ const length2 = moves3 ? timelineDuration(doc2.nodes, s.id) : 0;
314569
+ const machine = moves3 ? webStateMachine(doc2, s.id) : null;
314570
+ return {
314571
+ ...machine ? { machine } : {},
314572
+ ...length2 > 0 ? { timeline: { duration: length2, stops: stopsOf(frameTimeline(doc2.nodes, s.id).markers, [0, length2]), loops: frameRunsOn(doc2.nodes, s.id) } } : {},
314573
+ id: p2.id,
314574
+ route: p2.route,
314575
+ title: p2.title,
314576
+ ...p2.record ? { screen: s.id, record: p2.record.id } : {},
314577
+ ...description ? { description } : {},
314578
+ ...s.route?.notFound ? { notFound: true } : {},
314579
+ ...s.route?.access ? { access: s.route.access } : {},
314580
+ tree,
314581
+ ...media2.length ? { media: media2 } : {}
314582
+ };
314583
+ });
314584
+ const islandNodes = new Map(pages2.flatMap((p2) => everyNode(p2.tree.root).filter((n) => n.island && !n.id.includes("::"))).map((n) => [n.id, n]));
314585
+ const fonts = /* @__PURE__ */ new Map();
314586
+ for (const p2 of pages2) for (const [family, weights] of fontFamilies(p2.tree)) for (const w of weights) (fonts.get(family) ?? fonts.set(family, /* @__PURE__ */ new Set()).get(family)).add(w);
314587
+ const home = pages2.find((p2) => p2.route === "/" && !p2.screen);
314588
+ const turned = doc2.site?.gpuTransitions === false ? /* @__PURE__ */ new Set() : screenTransitions3d(doc2, screens);
314589
+ const screenSlices = [...turned].filter((id3) => doc2.nodes[id3] && pages2.filter((p2) => (p2.screen ?? p2.id) === id3).every(drawnByGpu)).map((id3) => [`${SCREEN_ISLAND}${id3}`, sliceDocument(doc2, id3, { screen: true })]);
314590
+ const islands = [...[...islandNodes].map(([id3, n]) => [id3, sliceDocument(doc2, n.asset?.of ?? layerId(id3), { self: !!n.asset?.self })]), ...screenSlices];
314591
+ return {
314592
+ name: doc2.name,
314593
+ pages: pages2,
314594
+ home: home?.id ?? null,
314595
+ tokens: pages2.find((p2) => p2.tree.tokens)?.tree.tokens,
314596
+ fonts: [...fonts].sort(([a], [b]) => a.localeCompare(b)).map(([family, w]) => ({ family, weights: [...w].sort((a, b) => a - b) })),
314597
+ assets: pages2.flatMap((p2) => everyNode(p2.tree.root).filter((n) => n.asset).map((n) => n.id)),
314598
+ program: { document: programDocument(doc2, pageId2, screens), start: home?.id ?? null },
314599
+ ...islands.length ? { islands: Object.fromEntries(islands) } : {}
314600
+ };
314601
+ }
314602
+ var HEAVY, declared, drawnByGpu;
314603
+ var init_site = __esm({
314604
+ "lib/io/web/site.ts"() {
314605
+ "use strict";
314606
+ init_breakpoints();
314607
+ init_collections();
314608
+ init_routes();
314609
+ init_instances2();
314610
+ init_timeline_stops();
314611
+ init_transitions();
314612
+ init_css();
314613
+ init_element();
314614
+ init_fonts3();
314615
+ init_slice();
314616
+ init_render();
314617
+ init_state_machine3();
314618
+ init_interactive();
314619
+ init_tree();
314620
+ init_routes();
314621
+ HEAVY = /* @__PURE__ */ new Set(["fills", "strokes", "effects", "shadows", "blurs", "vectorPaths", "paths", "styledSegments", "paragraphs", "imageUrl", "exportSettings", "annotations", "devResources", "codeConnect", "layoutGrids", "aiPending"]);
314622
+ declared = (n, isRoot) => ({ ...placementStyle(n, isRoot), ...n.style, ...n.hidden ? { display: "none" } : {} });
314623
+ drawnByGpu = (page) => !everyNode(page.tree.root).some((n) => n.input || n.check || n.html || n.code);
314624
+ }
314625
+ });
314626
+
313148
314627
  // lib/code/cdn.ts
313149
314628
  var CDN;
313150
314629
  var init_cdn = __esm({
@@ -336868,7 +338347,7 @@ async function withSiteCode(site, doc2) {
336868
338347
  return { ...site, code: { modules, ...imports3.size ? { packages: { versions, imports: [...imports3].sort() } } : {} } };
336869
338348
  }
336870
338349
  var codeNodes;
336871
- var init_site = __esm({
338350
+ var init_site2 = __esm({
336872
338351
  "lib/code/site.ts"() {
336873
338352
  "use strict";
336874
338353
  codeNodes = (n, out = []) => {
@@ -336919,44 +338398,6 @@ var init_hash = __esm({
336919
338398
  }
336920
338399
  });
336921
338400
 
336922
- // lib/code/props.ts
336923
- function propName(key5) {
336924
- const words = key5.split("#")[0].trim().split(/[^A-Za-z0-9]+/).filter(Boolean);
336925
- const name2 = words.map((w, i2) => i2 === 0 ? w.charAt(0).toLowerCase() + w.slice(1) : w.charAt(0).toUpperCase() + w.slice(1)).join("");
336926
- return /^[A-Za-z_$]/.test(name2) ? name2 : `p${name2}`;
336927
- }
336928
- function componentOf(nodes, node2) {
336929
- const c2 = node2.type === "COMPONENT" ? node2 : node2.type === "INSTANCE" ? nodes[node2.mainComponentId] : void 0;
336930
- return c2?.type === "COMPONENT" ? c2 : void 0;
336931
- }
336932
- function codeOf(nodes, node2) {
336933
- if (node2.type !== "COMPONENT" && node2.type !== "INSTANCE") return null;
336934
- return componentOf(nodes, node2)?.code ?? null;
336935
- }
336936
- function codeProps(nodes, node2) {
336937
- const component = componentOf(nodes, node2);
336938
- const out = {};
336939
- if (!component) return out;
336940
- const set3 = component.parentId ? nodes[component.parentId] : void 0;
336941
- const defs = (set3?.type === "COMPONENT_SET" ? set3.componentPropertyDefinitions : component.componentPropertyDefinitions) ?? {};
336942
- const given = node2.type === "INSTANCE" ? node2.componentProperties ?? {} : {};
336943
- for (const key5 of Object.keys(defs).sort()) {
336944
- const v = value(key5 in given ? given[key5] : defs[key5].defaultValue);
336945
- if (v !== void 0) out[propName(key5)] = v;
336946
- }
336947
- out.width = Math.round(node2.width);
336948
- out.height = Math.round(node2.height);
336949
- return out;
336950
- }
336951
- var value;
336952
- var init_props = __esm({
336953
- "lib/code/props.ts"() {
336954
- "use strict";
336955
- init_color();
336956
- value = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" ? v : v && typeof v === "object" && "r" in v ? colorToHex8(v) : void 0;
336957
- }
336958
- });
336959
-
336960
338401
  // lib/code/snapshots.ts
336961
338402
  var init_snapshots = __esm({
336962
338403
  "lib/code/snapshots.ts"() {
@@ -337401,871 +338842,6 @@ ${indent}<img src="" width="${node2.width}" height="${node2.height}" alt="${esca
337401
338842
  }
337402
338843
  });
337403
338844
 
337404
- // lib/document/controls.ts
337405
- function fieldPart(nodes, id3) {
337406
- const n = nodes[id3];
337407
- if (!n) return null;
337408
- if (n.type === "TEXT") return id3;
337409
- for (const c2 of n.childIds ?? []) {
337410
- const hit = fieldPart(nodes, c2);
337411
- if (hit) return hit;
337412
- }
337413
- return null;
337414
- }
337415
- var cleanName2;
337416
- var init_controls = __esm({
337417
- "lib/document/controls.ts"() {
337418
- cleanName2 = (raw) => raw.trim().replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
337419
- }
337420
- });
337421
-
337422
- // lib/io/web/expressible.ts
337423
- function expressibility(node2, styles) {
337424
- const c2 = capability(node2, "css", styles);
337425
- return { css: c2.reason === "", reason: c2.reason, needsRaster: c2.verdict === "raster" };
337426
- }
337427
- var init_expressible = __esm({
337428
- "lib/io/web/expressible.ts"() {
337429
- "use strict";
337430
- init_capability();
337431
- }
337432
- });
337433
-
337434
- // lib/io/web/responsive.ts
337435
- function containerStyle(f2) {
337436
- const out = {};
337437
- if (isStack(f2) && f2.layoutWrap === "WRAP") {
337438
- out["flex-wrap"] = "wrap";
337439
- const cross2 = f2.counterAxisSpacing ?? f2.itemSpacing ?? 0;
337440
- const main2 = f2.itemSpacing ?? 0;
337441
- if (cross2 !== main2) out.gap = f2.layoutMode === "HORIZONTAL" ? `${cross2}px ${main2}px` : `${main2}px ${cross2}px`;
337442
- out["align-content"] = "flex-start";
337443
- }
337444
- if (isGrid(f2)) {
337445
- out.display = "grid";
337446
- const cols = f2.layoutGridColumns ?? "AUTO";
337447
- out["grid-template-columns"] = cols === "AUTO" ? `repeat(auto-fill, minmax(${f2.layoutGridMinColumnWidth ?? 100}px, 1fr))` : Array.from({ length: Math.max(1, cols) }, (_, i2) => track(f2.layoutGridColumnSizes?.[i2])).join(" ");
337448
- const rows = f2.layoutGridRows ?? "AUTO";
337449
- if (rows === "AUTO") out["grid-auto-rows"] = `minmax(${f2.layoutGridMinRowHeight ?? 100}px, auto)`;
337450
- else out["grid-template-rows"] = Array.from({ length: Math.max(1, rows) }, (_, i2) => track(f2.layoutGridRowSizes?.[i2])).join(" ");
337451
- const colGap = f2.itemSpacing ?? 0, rowGap = f2.counterAxisSpacing ?? colGap;
337452
- out.gap = rowGap === colGap ? `${colGap}px` : `${rowGap}px ${colGap}px`;
337453
- if (f2.padding) {
337454
- out.padding = `${f2.padding.top}px ${f2.padding.right}px ${f2.padding.bottom}px ${f2.padding.left}px`;
337455
- if (f2.padding.top || f2.padding.right || f2.padding.bottom || f2.padding.left) out["box-sizing"] = "border-box";
337456
- }
337457
- }
337458
- const scroll = f2.overflowScrolling;
337459
- if (scroll && scroll !== "NONE") {
337460
- out["overflow-x"] = scroll === "HORIZONTAL" || scroll === "BOTH" ? "auto" : "hidden";
337461
- out["overflow-y"] = scroll === "VERTICAL" || scroll === "BOTH" ? "auto" : "hidden";
337462
- }
337463
- return out;
337464
- }
337465
- function flowChild(node2, parent) {
337466
- const style = { ...limits(node2) };
337467
- const h = node2.layoutSizingHorizontal ?? "FIXED", v = node2.layoutSizingVertical ?? "FIXED";
337468
- if (isGrid(parent)) {
337469
- if (h !== "FIXED") style.width = h === "FILL" ? null : "fit-content";
337470
- if (v !== "FIXED") style.height = null;
337471
- return { style };
337472
- }
337473
- if (h === "FIXED" && style["max-width"] === void 0) style["max-width"] = "100%";
337474
- const row2 = parent.layoutMode === "HORIZONTAL";
337475
- const main2 = row2 ? h : v, cross2 = row2 ? v : h;
337476
- const mainProp = row2 ? "width" : "height", crossProp = row2 ? "height" : "width";
337477
- if (main2 === "FILL") {
337478
- style[mainProp] = null;
337479
- style.flex = "1 1 0";
337480
- if (style[`min-${mainProp}`] === void 0) style[`min-${mainProp}`] = "0";
337481
- } else {
337482
- if (main2 === "HUG") style[mainProp] = null;
337483
- style["flex-shrink"] = "0";
337484
- }
337485
- if (cross2 === "FILL") {
337486
- style[crossProp] = null;
337487
- style["align-self"] = "stretch";
337488
- } else {
337489
- if (cross2 === "HUG") style[crossProp] = null;
337490
- if ((parent.counterAxisAlignItems ?? "MIN") === "MIN") style["align-self"] = "flex-start";
337491
- }
337492
- return { style };
337493
- }
337494
- function constrained(kind, pos, size6, parentSize, start2, end, sizeProp) {
337495
- const far = parentSize - pos - size6;
337496
- switch (kind) {
337497
- case "MAX":
337498
- return { place: { [end]: px4(far) }, style: {} };
337499
- case "STRETCH":
337500
- return { place: { [start2]: px4(pos), [end]: px4(far) }, style: { [sizeProp]: null } };
337501
- // Its centre keeps its distance from the parent's centre.
337502
- case "CENTER":
337503
- return { place: { [start2]: `calc(50% + ${px4(pos - parentSize / 2)})` }, style: {} };
337504
- case "SCALE":
337505
- return parentSize > 0 ? { place: { [start2]: pct2(pos / parentSize) }, style: { [sizeProp]: pct2(size6 / parentSize) } } : { place: { [start2]: px4(pos) }, style: {} };
337506
- default:
337507
- return { place: { [start2]: px4(pos) }, style: {} };
337508
- }
337509
- }
337510
- function placedChild(node2, parent) {
337511
- const c2 = node2.constraints ?? { horizontal: "MIN", vertical: "MIN" };
337512
- const x2 = constrained(c2.horizontal, node2.x, node2.width, parent.width, "left", "right", "width");
337513
- const y = constrained(c2.vertical, node2.y, node2.height, parent.height, "top", "bottom", "height");
337514
- return { style: { ...limits(node2), ...x2.style, ...y.style }, place: { position: "absolute", ...x2.place, ...y.place } };
337515
- }
337516
- function siteLayout(node2, parent, layout2) {
337517
- const own2 = node2.type === "FRAME" || node2.type === "COMPONENT" || node2.type === "INSTANCE" ? node2 : null;
337518
- if (!parent) {
337519
- const grows = !own2 || laysOut(own2) || own2.overflowScrolling === "NONE" || !own2.overflowScrolling;
337520
- return { style: { ...limits(node2), width: "100%", ...grows ? { height: null, "min-height": `max(${px4(node2.height)}, 100dvh)` } : {} }, place: { position: "relative" } };
337521
- }
337522
- const s = node2;
337523
- return layout2 && laysOut(layout2) && s.layoutPositioning !== "ABSOLUTE" ? flowChild(s, layout2) : placedChild(s, parent);
337524
- }
337525
- var px4, pct2, isStack, isGrid, laysOut, track, limits;
337526
- var init_responsive = __esm({
337527
- "lib/io/web/responsive.ts"() {
337528
- "use strict";
337529
- px4 = (v) => `${Math.round(v * 100) / 100}px`;
337530
- pct2 = (v) => `${Math.round(v * 1e4) / 100}%`;
337531
- isStack = (f2) => f2?.layoutMode === "HORIZONTAL" || f2?.layoutMode === "VERTICAL";
337532
- isGrid = (f2) => f2?.layoutMode === "GRID";
337533
- laysOut = (f2) => isStack(f2) || isGrid(f2);
337534
- track = (t3) => {
337535
- if (!t3 || t3.sizing === "FILL") return t3?.value && /fr$/.test(t3.value) ? t3.value : "1fr";
337536
- if (t3.sizing === "HUG") return "auto";
337537
- return /^[\d.]+$/.test(t3.value) ? `${t3.value}px` : t3.value;
337538
- };
337539
- limits = (n) => {
337540
- const out = {};
337541
- if (n.minWidth !== void 0) out["min-width"] = px4(n.minWidth);
337542
- if (n.maxWidth !== void 0) out["max-width"] = px4(n.maxWidth);
337543
- if (n.minHeight !== void 0) out["min-height"] = px4(n.minHeight);
337544
- if (n.maxHeight !== void 0) out["max-height"] = px4(n.maxHeight);
337545
- return out;
337546
- };
337547
- }
337548
- });
337549
-
337550
- // lib/io/web/richtext.ts
337551
- function runStyle(seg) {
337552
- const out = {};
337553
- if (seg.fontFamily) out["font-family"] = `"${seg.fontFamily}", system-ui, sans-serif`;
337554
- if (seg.fontSize) out["font-size"] = `${seg.fontSize}px`;
337555
- if (seg.fontWeight) out["font-weight"] = String(seg.fontWeight);
337556
- if (seg.fontStyle) out["font-style"] = seg.fontStyle;
337557
- if (seg.lineHeight !== void 0 && seg.lineHeight !== "AUTO") out["line-height"] = `${seg.lineHeight}px`;
337558
- if (seg.textDecoration === "UNDERLINE") out["text-decoration"] = "underline";
337559
- else if (seg.textDecoration === "STRIKETHROUGH") out["text-decoration"] = "line-through";
337560
- else if (seg.textDecoration === "NONE") out["text-decoration"] = "none";
337561
- if (seg.textCase === "UPPER") out["text-transform"] = "uppercase";
337562
- else if (seg.textCase === "LOWER") out["text-transform"] = "lowercase";
337563
- else if (seg.textCase === "TITLE") out["text-transform"] = "capitalize";
337564
- else if (seg.textCase === "ORIGINAL") out["text-transform"] = "none";
337565
- const solid4 = seg.fills?.find((f2) => f2.visible !== false && f2.type === "SOLID" && f2.color);
337566
- if (solid4?.color) out.color = toHex(solid4.color);
337567
- return out;
337568
- }
337569
- function textRuns(t3) {
337570
- const text = t3.characters ?? "";
337571
- const segs = [...t3.styledSegments ?? []].filter((s) => s.end > s.start).sort((a, b) => a.start - b.start);
337572
- if (!segs.length && !t3.link) return void 0;
337573
- const runs = [];
337574
- const push2 = (from2, to, seg) => {
337575
- if (to <= from2) return;
337576
- const link2 = seg?.link ?? t3.link;
337577
- runs.push({ text: text.slice(from2, to), style: seg ? runStyle(seg) : {}, ...link2 ? { link: link2 } : {} });
337578
- };
337579
- let at3 = 0;
337580
- for (const s of segs) {
337581
- const start2 = Math.max(at3, Math.min(text.length, s.start)), end = Math.min(text.length, s.end);
337582
- push2(at3, start2);
337583
- push2(start2, end, s);
337584
- at3 = Math.max(at3, end);
337585
- }
337586
- push2(at3, text.length);
337587
- return runs;
337588
- }
337589
- var init_richtext = __esm({
337590
- "lib/io/web/richtext.ts"() {
337591
- "use strict";
337592
- init_paint2();
337593
- }
337594
- });
337595
-
337596
- // lib/io/web/timeline.ts
337597
- function frameWebMotion(doc2, frameId, style) {
337598
- const nodes = doc2.nodes;
337599
- const frame2 = nodes[frameId];
337600
- if (!frame2 || !hasFrameMotion(nodes, frameId)) return null;
337601
- const len3 = timelineDuration(nodes, frameId);
337602
- if (!(len3 > 0)) return null;
337603
- const steps = Math.max(1, Math.ceil(len3 / 1e3 * SAMPLE_RATE));
337604
- const times2 = [];
337605
- const poses = [];
337606
- for (let i2 = 0; i2 <= steps; i2++) {
337607
- const t3 = len3 * i2 / steps;
337608
- times2.push(t3);
337609
- poses.push(evaluatePose(nodes, { kind: "frame", frameId }, t3).nodes);
337610
- }
337611
- const ids2 = /* @__PURE__ */ new Set();
337612
- for (const p2 of poses) for (const id3 in p2) if (id3 !== frameId && p2[id3] !== nodes[id3]) ids2.add(id3);
337613
- const loops = frameRunsOn(nodes, frameId);
337614
- const out = /* @__PURE__ */ new Map();
337615
- const tag = frameId.replace(/[^a-zA-Z0-9]/g, "").slice(-6);
337616
- let n = 0;
337617
- for (const id3 of ids2) {
337618
- const rest = id3.includes("::") ? resolveVirtualNode2(nodes, id3) : nodes[id3];
337619
- if (!rest || !underFrame(nodes, id3, frameId)) continue;
337620
- const frames = keyframesOf(times2, poses.map((p2) => declarationsOf(p2[id3] ?? rest, rest, style)), len3);
337621
- if (!frames) continue;
337622
- out.set(id3, {
337623
- name: `timeline-${tag}-${n++}`,
337624
- frames,
337625
- durationMs: Math.round(len3),
337626
- delayMs: 0,
337627
- iterations: loops ? "infinite" : 1,
337628
- direction: "normal",
337629
- fill: "both"
337630
- });
337631
- }
337632
- return out.size ? out : null;
337633
- }
337634
- function underFrame(nodes, id3, frameId) {
337635
- const real = id3.split("::")[0];
337636
- for (let n = nodes[real]; n; n = n.parentId ? nodes[n.parentId] : void 0) if (n.id === frameId) return true;
337637
- return false;
337638
- }
337639
- var init_timeline = __esm({
337640
- "lib/io/web/timeline.ts"() {
337641
- "use strict";
337642
- init_scene_graph();
337643
- init_pose();
337644
- init_instances2();
337645
- init_keyframes();
337646
- }
337647
- });
337648
-
337649
- // lib/io/web/interactive.ts
337650
- function subtreeIds(doc2, id3, out = /* @__PURE__ */ new Set()) {
337651
- if (out.has(id3)) return out;
337652
- const n = doc2.nodes[id3];
337653
- if (!n) return out;
337654
- out.add(id3);
337655
- if (n.type === "INSTANCE") subtreeIds(doc2, n.mainComponentId, out);
337656
- for (const c2 of n.childIds ?? []) subtreeIds(doc2, c2, out);
337657
- return out;
337658
- }
337659
- function flowScreens(doc2, startId) {
337660
- const start2 = doc2.nodes[startId];
337661
- if (!start2 || start2.type !== "FRAME" || doc2.nodes[start2.parentId ?? ""]?.type !== "PAGE") return [startId];
337662
- const out = [startId];
337663
- for (let i2 = 0; i2 < out.length; i2++) {
337664
- for (const id3 of subtreeIds(doc2, out[i2])) {
337665
- for (const ix of interactionsOf(doc2.nodes[id3])) {
337666
- const to = ix.action.navigationType === "NAVIGATE" ? ix.action.destinationId : null;
337667
- const dest = to ? doc2.nodes[to] : void 0;
337668
- if (!dest || out.includes(dest.id) || dest.type !== "FRAME" || doc2.nodes[dest.parentId ?? ""]?.type !== "PAGE") continue;
337669
- if (Math.round(dest.width) !== Math.round(start2.width) || Math.round(dest.height) !== Math.round(start2.height)) continue;
337670
- out.push(dest.id);
337671
- }
337672
- }
337673
- }
337674
- return out;
337675
- }
337676
- function variantStates(doc2, mainId) {
337677
- const out = [mainId];
337678
- for (let i2 = 0; i2 < out.length; i2++) {
337679
- for (const id3 of subtreeIds(doc2, out[i2])) {
337680
- for (const ix of interactionsOf(doc2.nodes[id3])) {
337681
- const to = ix.action.navigationType === "CHANGE_TO" ? ix.action.destinationId : null;
337682
- if (to && !out.includes(to) && doc2.nodes[to]?.type === "COMPONENT") out.push(to);
337683
- }
337684
- }
337685
- }
337686
- return out;
337687
- }
337688
- function buildState(ctx2, doc2, id3, machine, state, start2, variantOf2) {
337689
- const expand = /* @__PURE__ */ new Map();
337690
- const tree = buildPlainTree(doc2, id3, ctx2.opts, start2, { built: (web, _node, at3) => {
337691
- if (web.type === "INSTANCE") expand.set(web, at3);
337692
- } });
337693
- for (const r of tree.rules ?? []) ctx2.rules.add(r);
337694
- if (tree.truncated) ctx2.truncated = true;
337695
- const ids2 = /* @__PURE__ */ new Map();
337696
- const index2 = (w) => {
337697
- ids2.set(w.id, w);
337698
- w.children.forEach(index2);
337699
- };
337700
- index2(tree.root);
337701
- const visit2 = (w, owner, st, isRoot) => {
337702
- w.owner = owner;
337703
- w.looks = { [st]: lookOf(w, isRoot) };
337704
- if (w.motion) ctx2.keyframes.add(w.motion.keyframes);
337705
- const node2 = nodeOf(doc2, w.id);
337706
- note(ctx2, w, interactionsOf(doc2.nodes[realId(w.id)]), owner, st, ids2);
337707
- const at3 = expand.get(w);
337708
- const inst = node2?.type === "INSTANCE" ? node2 : void 0;
337709
- const states = inst && at3 && ctx2.depth < 4 ? variantStates(doc2, inst.mainComponentId) : [];
337710
- if (inst && at3 && states.length > 1 && w.id !== variantOf2) {
337711
- const m = { id: `m${ctx2.machines.length}`, initial: inst.mainComponentId, states: states.map((s) => ({ id: s, name: stateName(doc2, s) })) };
337712
- ctx2.machines.push(m);
337713
- w.machine = m;
337714
- const perState = [];
337715
- for (const s of states) {
337716
- let kids;
337717
- if (s === inst.mainComponentId) {
337718
- kids = w.children;
337719
- kids.forEach((c2) => visit2(c2, m.id, s, false));
337720
- } else {
337721
- const shown2 = { ...doc2, nodes: { ...doc2.nodes, [inst.id]: { ...inst, mainComponentId: s } } };
337722
- ctx2.depth++;
337723
- try {
337724
- kids = buildState(ctx2, shown2, inst.id, m.id, s, at3, inst.id).children;
337725
- } finally {
337726
- ctx2.depth--;
337727
- }
337728
- }
337729
- note(ctx2, w, interactionsOf(doc2.nodes[s]), m.id, s, ids2, m.id);
337730
- perState.push([s, kids]);
337731
- }
337732
- w.children = mergeChildren(perState, m.id, m.states.map((s) => s.id), ctx2);
337733
- } else if (w.id === variantOf2) {
337734
- w.children.forEach((c2) => visit2(c2, owner, st, false));
337735
- } else {
337736
- if (inst) note(ctx2, w, interactionsOf(doc2.nodes[inst.mainComponentId]), owner, st, ids2);
337737
- w.children.forEach((c2) => visit2(c2, owner, st, false));
337738
- }
337739
- };
337740
- visit2(tree.root, machine, state, !start2);
337741
- return tree.root;
337742
- }
337743
- function note(ctx2, w, list2, machine, state, ids2, hostMachine) {
337744
- if (!list2.length) return;
337745
- const at3 = ctx2.pending.get(w) ?? [];
337746
- for (const ix of list2) at3.push({ machine, state, ix, hostMachine: hostMachine ?? (machine !== FLOW ? machine : void 0), ids: ids2 });
337747
- ctx2.pending.set(w, at3);
337748
- }
337749
- function lookOf(w, isRoot) {
337750
- return {
337751
- style: { ...placementStyle(w, isRoot), ...w.style, ...w.motion?.style ?? {} },
337752
- ...w.text ? { text: w.text.characters } : {},
337753
- ...w.tf ? { tf: w.tf } : {}
337754
- };
337755
- }
337756
- function keyed(kids) {
337757
- const seen = /* @__PURE__ */ new Map();
337758
- return kids.map((k2) => {
337759
- const base = `${k2.name}\0${k2.type}`;
337760
- const i2 = seen.get(base) ?? 0;
337761
- seen.set(base, i2 + 1);
337762
- return [`${base}\0${i2}`, k2];
337763
- });
337764
- }
337765
- function mergeChildren(perState, machine, states, ctx2) {
337766
- const order2 = [];
337767
- const groups = /* @__PURE__ */ new Map();
337768
- for (const [state, kids] of perState) {
337769
- let after = -1;
337770
- for (const [k2, node2] of keyed(kids)) {
337771
- let at3 = order2.indexOf(k2);
337772
- if (at3 < 0) {
337773
- order2.splice(after + 1, 0, k2);
337774
- at3 = after + 1;
337775
- }
337776
- after = at3;
337777
- (groups.get(k2) ?? groups.set(k2, []).get(k2)).push([state, node2]);
337778
- }
337779
- }
337780
- return order2.map((k2) => mergeNode(groups.get(k2), machine, states, ctx2));
337781
- }
337782
- function mergeNode(items, machine, states, ctx2) {
337783
- const [, first2] = items[0];
337784
- if (first2.owner !== machine) {
337785
- for (const [, w] of items.slice(1)) alias(ctx2, w, first2);
337786
- return first2;
337787
- }
337788
- const looks = {};
337789
- for (const s of states) looks[s] = null;
337790
- for (const [s, w] of items) looks[s] = w.looks?.[s] ?? null;
337791
- const merged = { ...first2, looks };
337792
- const pend = items.flatMap(([, w]) => ctx2.pending.get(w) ?? []);
337793
- if (pend.length) ctx2.pending.set(merged, pend);
337794
- for (const [, w] of items) if (w !== merged) alias(ctx2, w, merged);
337795
- if (first2.machine) {
337796
- for (const [, w] of items) if (w.machine && w.machine !== first2.machine) ctx2.renamed.set(w.machine.id, first2.machine.id);
337797
- }
337798
- merged.children = first2.machine ? first2.children : mergeChildren(items.map(([s, w]) => [s, w.children]), machine, states, ctx2);
337799
- return merged;
337800
- }
337801
- function alias(ctx2, from2, to) {
337802
- const a = ctx2.alias ??= /* @__PURE__ */ new Map();
337803
- a.set(from2, to);
337804
- }
337805
- function mergedOf(ctx2, w) {
337806
- const a = ctx2.alias;
337807
- let cur = w;
337808
- for (let i2 = 0; i2 < 16 && a?.has(cur); i2++) cur = a.get(cur);
337809
- return cur;
337810
- }
337811
- function actionOf(ctx2, p2) {
337812
- const a = p2.ix.action;
337813
- const glide2 = glideOf2(a.transition);
337814
- const hold = p2.ix.trigger === "ON_HOVER" || p2.ix.trigger === "ON_PRESS";
337815
- switch (a.navigationType) {
337816
- case "NAVIGATE":
337817
- return a.destinationId && ctx2.screens.has(a.destinationId) ? { kind: "go", machine: FLOW, to: a.destinationId, ...glide2, ...hold ? { hold } : {} } : null;
337818
- case "BACK":
337819
- return ctx2.screens.size > 1 ? { kind: "back", machine: FLOW } : null;
337820
- case "CHANGE_TO":
337821
- return p2.hostMachine && a.destinationId ? { kind: "go", machine: p2.hostMachine, to: a.destinationId, ...glide2, ...hold ? { hold } : {} } : null;
337822
- case "ORBIT_3D": {
337823
- const o = a.orbit ?? {};
337824
- const uidOf = (id3) => {
337825
- const w = id3 ? p2.ids.get(id3) : void 0;
337826
- return w ? mergedOf(ctx2, w).uid : void 0;
337827
- };
337828
- const uid2 = uidOf(a.destinationId);
337829
- const tiltUid = uidOf(o.tiltLayerId) ?? uid2;
337830
- return uid2 === void 0 || tiltUid === void 0 ? null : { kind: "orbit", target: uid2, tiltTarget: tiltUid, degreesPerPx: o.degreesPerPx ?? 0.4, tilt: !!o.tilt, tiltRange: o.tiltRange ?? [-30, 30] };
337831
- }
337832
- default:
337833
- return null;
337834
- }
337835
- }
337836
- function buildWebTree(doc2, nodeId2, opts = {}) {
337837
- const tree = buildTree(doc2, nodeId2, opts);
337838
- const machine = opts.static || opts.stateMachine === false ? null : webStateMachine(doc2, nodeId2);
337839
- return machine ? { ...tree, stateMachine: machine } : tree;
337840
- }
337841
- function buildTree(doc2, nodeId2, opts = {}) {
337842
- if (opts.static || opts.target === "site") return buildPlainTree(doc2, nodeId2, opts);
337843
- const screens = flowScreens(doc2, nodeId2);
337844
- const anything = screens.length > 1 || [...subtreeIds(doc2, nodeId2)].some((id3) => interactionsOf(doc2.nodes[id3]).some((ix) => ix.action.navigationType === "CHANGE_TO" || ix.action.navigationType === "ORBIT_3D"));
337845
- if (!anything) return buildPlainTree(doc2, nodeId2, opts);
337846
- const flow = { id: FLOW, initial: nodeId2, states: screens.map((s) => ({ id: s, name: doc2.nodes[s]?.name ?? s })) };
337847
- const ctx2 = { doc: doc2, opts, screens: new Set(screens), machines: [flow], keyframes: /* @__PURE__ */ new Set(), rules: /* @__PURE__ */ new Set(), pending: /* @__PURE__ */ new Map(), depth: 0, renamed: /* @__PURE__ */ new Map() };
337848
- const roots = screens.map((s) => [s, buildState(ctx2, doc2, s, FLOW, s)]);
337849
- const truncated = !!ctx2.truncated;
337850
- const root2 = mergeNode(roots, FLOW, screens, ctx2);
337851
- let uid2 = 0;
337852
- const number4 = (w) => {
337853
- w.uid = uid2++;
337854
- w.children.forEach(number4);
337855
- };
337856
- number4(root2);
337857
- const place3 = (w) => {
337858
- const pend = ctx2.pending.get(w);
337859
- if (pend) {
337860
- const seen = /* @__PURE__ */ new Set();
337861
- const on = [];
337862
- for (const raw of pend) {
337863
- const p2 = { ...raw, machine: ctx2.renamed.get(raw.machine) ?? raw.machine, ...raw.hostMachine ? { hostMachine: ctx2.renamed.get(raw.hostMachine) ?? raw.hostMachine } : {} };
337864
- const trigger = TRIGGERS[p2.ix.trigger];
337865
- const action3 = trigger ? actionOf(ctx2, p2) : null;
337866
- if (!trigger || !action3) continue;
337867
- const ix = { machine: p2.machine, state: p2.state, trigger, ...p2.ix.triggerDelay ? { delay: p2.ix.triggerDelay } : {}, ...p2.ix.triggerKey ? { key: p2.ix.triggerKey } : {}, action: action3 };
337868
- const sig = JSON.stringify(ix);
337869
- if (!seen.has(sig)) {
337870
- seen.add(sig);
337871
- on.push(ix);
337872
- }
337873
- }
337874
- if (on.length) w.on = on;
337875
- }
337876
- w.children.forEach(place3);
337877
- };
337878
- place3(root2);
337879
- return { root: root2, truncated, ...ctx2.rules.size ? { rules: [...ctx2.rules].sort() } : {}, interactive: { machines: ctx2.machines.filter((m) => !ctx2.renamed.has(m.id)), keyframes: [...ctx2.keyframes] } };
337880
- }
337881
- var FLOW, interactionsOf, realId, nodeOf, stateName, TRIGGERS, EASINGS2, glideOf2;
337882
- var init_interactive = __esm({
337883
- "lib/io/web/interactive.ts"() {
337884
- "use strict";
337885
- init_scene_graph();
337886
- init_tree();
337887
- init_state_machine3();
337888
- init_element();
337889
- FLOW = "flow";
337890
- interactionsOf = (n) => n?.interactions ?? [];
337891
- realId = (id3) => id3.includes("::") ? id3.slice(id3.lastIndexOf("::") + 2) : id3;
337892
- nodeOf = (doc2, id3) => doc2.nodes[id3] ?? (id3.includes("::") ? resolveVirtualNode2(doc2.nodes, id3) ?? void 0 : void 0);
337893
- stateName = (doc2, id3) => {
337894
- const n = doc2.nodes[id3];
337895
- const v = n?.variantProperties;
337896
- return v ? Object.values(v).join(", ") : n?.name ?? id3;
337897
- };
337898
- TRIGGERS = {
337899
- ON_CLICK: "click",
337900
- ON_HOVER: "hover",
337901
- ON_PRESS: "press",
337902
- ON_DRAG: "drag",
337903
- MOUSE_ENTER: "enter",
337904
- MOUSE_LEAVE: "leave",
337905
- AFTER_TIMEOUT: "timeout",
337906
- KEY_DOWN: "key"
337907
- };
337908
- EASINGS2 = { EASE_IN: "ease-in", EASE_OUT: "ease-out", EASE_IN_OUT: "ease-in-out", LINEAR: "linear", SPRING: "cubic-bezier(0.34, 1.56, 0.64, 1)" };
337909
- glideOf2 = (t3) => !t3 || t3.type === "INSTANT" || t3.type === "CUT" ? { ms: 0, easing: "linear" } : { ms: Math.max(0, Math.round(t3.duration)), easing: EASINGS2[t3.easing] ?? "ease-in-out" };
337910
- }
337911
- });
337912
-
337913
- // lib/io/web/tree.ts
337914
- function anchorTargets(doc2) {
337915
- const hit = anchorMemo.get(doc2.nodes);
337916
- if (hit) return hit;
337917
- const out = /* @__PURE__ */ new Set();
337918
- for (const id3 in doc2.nodes) {
337919
- const n = doc2.nodes[id3];
337920
- if (n.semantics?.link?.kind === "anchor") out.add(n.semantics.link.nodeId);
337921
- for (const ix of n.interactions ?? []) if (ix.action.link?.kind === "anchor" && ix.action.link.nodeId) out.add(ix.action.link.nodeId);
337922
- }
337923
- anchorMemo.set(doc2.nodes, out);
337924
- return out;
337925
- }
337926
- function prepared(node2, doc2) {
337927
- let n = node2;
337928
- if (n.id.includes("::")) n = withInstanceBox(n, doc2.nodes);
337929
- n = resolveNodeVariables(n, doc2.variables, doc2.variableCollections, doc2.activeVariableModes, exprData(doc2));
337930
- n = resolveTextNodeStyles(n, doc2.styles ?? {});
337931
- return n;
337932
- }
337933
- function layoutOf2(node2, nodes) {
337934
- if (!node2) return null;
337935
- if (node2.type === "INSTANCE") {
337936
- const mainId = node2.mainComponentId;
337937
- const main2 = mainId ? nodes[mainId] : void 0;
337938
- return main2 ?? null;
337939
- }
337940
- if (node2.id.includes("::")) {
337941
- const real = nodes[node2.id.split("::").pop()];
337942
- return real ?? node2;
337943
- }
337944
- return node2;
337945
- }
337946
- function buildPlainTree(doc2, nodeId2, opts = {}, start2, hooks = {}) {
337947
- const cap2 = opts.nodeCap ?? DEFAULT_NODE_CAP;
337948
- const first2 = doc2.nodes[nodeId2] ?? (nodeId2.includes("::") ? childLookup(doc2, nodeId2) : void 0);
337949
- if (!first2) throw new Error(`No node ${nodeId2}`);
337950
- let emitted = 0;
337951
- let truncated = false;
337952
- let folds = 0;
337953
- const tokens = opts.target === "site" && Object.keys(doc2.variables ?? {}).length ? siteTokens(doc2) : null;
337954
- const anchored = anchorTargets(doc2);
337955
- const pageItem = () => {
337956
- const c2 = opts.item && doc2.collections?.[opts.item.collectionId];
337957
- const r = opts.item && doc2.records?.[opts.item.recordId];
337958
- return c2 && r ? { collection: c2, record: r, suffix: "" } : null;
337959
- };
337960
- let item = pageItem();
337961
- const scopeOf2 = (it) => itemScope(it.collection, it.record, withData(variablesScope(doc2.variables, doc2.variableCollections, doc2.activeVariableModes), doc2));
337962
- const itemised = (node2, raw, it) => itemNode(node2, raw, it.collection, it.record, scopeOf2(it));
337963
- const itemLink = (link2, it) => {
337964
- const filled2 = it && link2.kind === "url" ? { ...link2, url: itemText(link2.url, it.collection, it.record) } : it && (link2.kind === "email" || link2.kind === "tel") ? { ...link2, value: itemText(link2.value, it.collection, it.record) } : link2;
337965
- if (filled2.kind === "screen") {
337966
- const dest = doc2.nodes[filled2.frameId];
337967
- const base = opts.routes?.[filled2.frameId];
337968
- const of = dest?.route?.collectionId;
337969
- if (of && base !== void 0) {
337970
- const slugs = recordSlugs(doc2, of);
337971
- const rec = it?.collection.id === of ? it.record.id : slugs.keys().next().value;
337972
- const slug3 = rec ? slugs.get(rec) : void 0;
337973
- return slug3 ? { link: filled2, href: `${base === "/" ? "" : base}/${slug3}`, screen: `${filled2.frameId}~${rec}` } : { link: filled2, href: null };
337974
- }
337975
- return { link: filled2, href: base ?? null, screen: filled2.frameId };
337976
- }
337977
- return { link: filled2, href: hrefOf(filled2, doc2.nodes, opts.routes) };
337978
- };
337979
- const fields = /* @__PURE__ */ new Map();
337980
- const styleOpts = { fullImageUrl: opts.fullImageUrls ?? opts.target === "site" };
337981
- const stylesOf = (n) => styleMapFor(n, doc2.styles, styleOpts);
337982
- let motion = null;
337983
- const timeline = !opts.static && !start2 && first2.type === "FRAME" ? frameWebMotion(doc2, first2.id, (n) => stylesOf(prepared(n, doc2))) : null;
337984
- const build3 = (raw, parent, in3D2, fold) => {
337985
- if (emitted >= cap2) {
337986
- truncated = true;
337987
- return null;
337988
- }
337989
- emitted++;
337990
- const node2 = item ? itemised(prepared(raw, doc2), raw, item) : prepared(raw, doc2);
337991
- const waits = node2.visible === false && parent !== null;
337992
- if (waits && !(opts.target === "site" && followsVisibility(raw))) return null;
337993
- const exp = expressibility(node2, doc2.styles);
337994
- const f2 = layoutOf2(node2, doc2.nodes) ?? node2;
337995
- const style = stylesOf(node2);
337996
- if (f2 !== node2 && !style.display) Object.assign(style, flexDeclarations(f2));
337997
- const through = in3D2 && passesThrough(raw, doc2.nodes);
337998
- const own2 = typeof node2.opacity === "number" ? node2.opacity : 1;
337999
- if (through) {
338000
- style["transform-style"] = "preserve-3d";
338001
- delete style.opacity;
338002
- style[foldVar(fold + 1)] = fold ? `calc(var(${foldVar(fold)}) * ${round3(own2)})` : String(round3(own2));
338003
- folds = Math.max(folds, fold + 1);
338004
- } else if (fold) style.opacity = own2 === 1 ? `var(${foldVar(fold)})` : `calc(var(${foldVar(fold)}) * ${round3(own2)})`;
338005
- if (own2 === 0) style["pointer-events"] = "none";
338006
- const web = {
338007
- id: item?.suffix ? `${node2.id}${item.suffix}` : node2.id,
338008
- name: node2.name || node2.type,
338009
- type: node2.type,
338010
- x: Math.round(node2.x),
338011
- y: Math.round(node2.y),
338012
- width: Math.round(node2.width),
338013
- height: Math.round(node2.height),
338014
- // Absolutely-positioned auto-layout children are taken out of the flow, exactly as the canvas does.
338015
- positioning: isFlex(layoutOf2(parent, doc2.nodes)) && node2.layoutPositioning !== "ABSOLUTE" ? "flow" : "absolute",
338016
- style,
338017
- children: []
338018
- };
338019
- if (tokens) Object.assign(style, tokenStyle(raw, style, tokens));
338020
- if (opts.target === "site") {
338021
- const lay = siteLayout(node2, parent, layoutOf2(parent, doc2.nodes));
338022
- for (const [k2, v] of Object.entries(lay.style)) {
338023
- if (v === null) delete style[k2];
338024
- else style[k2] = v;
338025
- }
338026
- if (laysOut(f2) || f2.overflowScrolling) Object.assign(style, containerStyle(f2));
338027
- if (node2.type === "TEXT") {
338028
- if (style["white-space"] === "pre") {
338029
- style["white-space"] = "pre-wrap";
338030
- style.width = "fit-content";
338031
- }
338032
- if (style["max-width"] === void 0) style["max-width"] = "100%";
338033
- if (style.height && style.height !== "auto") {
338034
- style["min-height"] = style.height;
338035
- delete style.height;
338036
- }
338037
- }
338038
- if (lay.place && (parent !== null || !start2?.parent)) web.place = lay.place;
338039
- }
338040
- if (waits) web.hidden = true;
338041
- const sem = node2.semantics;
338042
- if (sem) {
338043
- if (sem.tag && sem.tag !== "div") web.tag = sem.tag;
338044
- const attrs = {};
338045
- if (sem.label) attrs["aria-label"] = sem.label;
338046
- if (sem.hidden) attrs["aria-hidden"] = "true";
338047
- if (Object.keys(attrs).length) web.attrs = attrs;
338048
- const to = sem.link ? itemLink(sem.link, item) : null;
338049
- if (to?.href) web.link = { href: to.href, ...opensNewTab(to.link) ? { newTab: true } : {}, ...to.screen ? { screen: to.screen } : {} };
338050
- }
338051
- const control = node2.control;
338052
- if (control) {
338053
- const named = control.name ? { name: control.name } : {};
338054
- if (control.kind === "FORM") web.tag = "form";
338055
- else if (control.kind === "BUTTON") {
338056
- web.tag = "button";
338057
- web.attrs = { ...web.attrs, type: control.buttonType ?? "submit", ...named, ...control.name && control.value !== void 0 ? { value: item && hasItemToken(control.value) ? itemText(control.value, item.collection, item.record) : control.value } : {} };
338058
- } else if (control.kind === "CHECKBOX" || control.kind === "RADIO") {
338059
- web.check = { attrs: { type: control.kind === "RADIO" ? "radio" : "checkbox", ...named, ...control.value !== void 0 ? { value: control.value } : {}, ...control.checked ? { checked: "" } : {}, ...control.required ? { required: "" } : {} }, ...control.variableId ? { variable: control.variableId } : {} };
338060
- } else fields.set(fieldPart(doc2.nodes, raw.id) ?? raw.id, control);
338061
- }
338062
- const control0 = fields.get(raw.id);
338063
- const field = control0 && item && control0.value !== void 0 && hasItemToken(control0.value) ? { ...control0, value: itemText(control0.value, item.collection, item.record) } : control0;
338064
- if (field) {
338065
- const tag = field.kind === "TEXTAREA" ? "textarea" : field.kind === "SELECT" ? "select" : "input";
338066
- const words = node2.characters;
338067
- web.input = {
338068
- tag,
338069
- attrs: {
338070
- ...tag === "input" ? { type: field.inputType ?? "text" } : {},
338071
- ...field.name ? { name: field.name } : {},
338072
- ...tag !== "select" && (field.placeholder ?? words) ? { placeholder: field.placeholder ?? words } : {},
338073
- ...field.required ? { required: "" } : {},
338074
- ...tag === "input" && field.value !== void 0 ? { value: field.value } : {},
338075
- "aria-label": node2.semantics?.label ?? field.placeholder ?? field.name ?? web.name
338076
- },
338077
- ...tag === "select" ? { options: field.options ?? [] } : {},
338078
- ...tag !== "input" && field.value !== void 0 ? { value: field.value } : {},
338079
- ...field.variableId ? { variable: field.variableId } : {}
338080
- };
338081
- }
338082
- if (sem?.anchor || anchored.has(node2.id)) web.attrs = { ...web.attrs, id: anchorOf(node2) };
338083
- if (through) web.preserve3d = true;
338084
- web.tf = transformParts(node2);
338085
- if (typeof node2.altText === "string") web.alt = node2.altText;
338086
- if (parent === null) web.positioning = start2?.parent ? web.positioning : "flow";
338087
- if (f2.layoutMode === "HORIZONTAL" || f2.layoutMode === "VERTICAL") {
338088
- web.layout = {
338089
- direction: f2.layoutMode === "HORIZONTAL" ? "row" : "column",
338090
- gap: f2.itemSpacing ?? 0,
338091
- justify: JUSTIFY[f2.primaryAxisAlignItems ?? "MIN"],
338092
- align: ALIGN2[f2.counterAxisAlignItems ?? "MIN"],
338093
- padding: f2.padding ?? { top: 0, right: 0, bottom: 0, left: 0 }
338094
- };
338095
- }
338096
- if (node2.type === "TEXT") {
338097
- const t3 = node2;
338098
- const solid4 = (t3.fills ?? []).find((p2) => p2.visible !== false && p2.type === "SOLID" && p2.color);
338099
- web.text = {
338100
- characters: t3.characters ?? "",
338101
- align: t3.textAlign,
338102
- fontFamily: t3.fontFamily,
338103
- fontSize: t3.fontSize,
338104
- fontWeight: t3.fontWeight,
338105
- italic: t3.fontStyle === "italic",
338106
- ...solid4?.color ? { color: toHex(solid4.color) } : {},
338107
- ...t3.letterSpacing ? { letterSpacing: t3.letterSpacing } : {},
338108
- ...t3.lineHeight !== "AUTO" ? { lineHeight: t3.lineHeight } : {}
338109
- };
338110
- const runs = textRuns(t3);
338111
- if (runs) web.runs = runs;
338112
- }
338113
- const tl = timeline?.get(node2.id);
338114
- const mo = tl ?? motion?.children.get(node2.id);
338115
- if (mo) web.motion = { style: animationStyle(mo, tl ? "load" : motion.trigger), keyframes: keyframesCSS(mo) };
338116
- const ext = getNativeExtension(raw.type);
338117
- if (ext?.toWeb) {
338118
- const said = ext.toWeb(node2, { escape: escapeHTML, color: (c2) => toRgba({ ...c2, a: c2.a ?? 1 }) });
338119
- if (said.tag) web.tag = said.tag;
338120
- Object.assign(style, said.style);
338121
- web.html = said.html;
338122
- hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
338123
- return web;
338124
- }
338125
- const code = opts.target === "site" ? codeOf(doc2.nodes, raw) : null;
338126
- if (code && doc2.codeModules?.[code.moduleId]) {
338127
- for (const k2 of PAINTED) delete style[k2];
338128
- web.code = { module: code.moduleId, ...code.exportName ? { export: code.exportName } : {}, props: codeProps(doc2.nodes, node2) };
338129
- hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
338130
- return web;
338131
- }
338132
- if (!exp.css) {
338133
- for (const k2 of PAINTED) delete style[k2];
338134
- web.asset = { kind: opts.assetKind ?? (exp.needsRaster ? "png" : "svg"), reason: exp.reason, ...item?.suffix ? { of: node2.id } : {} };
338135
- if (opts.target === "site" && renderMode(node2, { styles: doc2.styles, live: isLive(doc2.nodes, raw.id) }) === "island") web.island = true;
338136
- hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
338137
- return web;
338138
- }
338139
- const lost = capability(node2, "css", doc2.styles).dropped.find((f3) => f3.startsWith("paint:"));
338140
- if (lost && !node2.id.includes("::")) {
338141
- const site = opts.target === "site";
338142
- style.isolation = "isolate";
338143
- web.children.push({
338144
- id: `${node2.id}/backdrop${item?.suffix ?? ""}`,
338145
- name: `${web.name} fill`,
338146
- type: "BACKDROP",
338147
- x: 0,
338148
- y: 0,
338149
- width: web.width,
338150
- height: web.height,
338151
- positioning: "absolute",
338152
- ...site ? { place: { position: "absolute", inset: "0" } } : {},
338153
- style: { ...site ? {} : { width: `${web.width}px`, height: `${web.height}px` }, "border-radius": "inherit", overflow: "hidden", "z-index": "-1", "pointer-events": "none" },
338154
- alt: "",
338155
- asset: { kind: "png", reason: featureName(lost), of: node2.id, self: true },
338156
- ...site && movesItself(raw) ? { island: true } : {},
338157
- children: []
338158
- });
338159
- }
338160
- const outer = motion;
338161
- if (!motion && node2.type === "INSTANCE" && !opts.static) {
338162
- motion = instanceWebMotion(doc2, node2, (n) => stylesOf(prepared(n, doc2)));
338163
- if (motion && (motion.trigger !== "load" || opts.target === "site")) web.motionTrigger = motion.trigger;
338164
- }
338165
- try {
338166
- if (opts.includeChildren !== false) {
338167
- const kids3D = in3D2 ? through : is3DContext(raw) && !raw.id.includes("::");
338168
- const kidFold = through ? fold + 1 : 0;
338169
- const repeat = raw.repeat;
338170
- const collection = repeat && doc2.collections?.[repeat.collectionId];
338171
- if (repeat && collection && opts.target === "site") {
338172
- const outerItem = item;
338173
- const under = outerItem ? scopeOf2(outerItem) : withData(variablesScope(doc2.variables, doc2.variableCollections, doc2.activeVariableModes), doc2);
338174
- try {
338175
- for (const record2 of repeatRecords(doc2, repeat, under)) {
338176
- item = { collection, record: record2, suffix: `${outerItem?.suffix ?? ""}~${record2.id}` };
338177
- for (const child of childrenOf(node2, doc2.nodes)) {
338178
- const built = build3(child, node2, kids3D, kidFold);
338179
- if (built) web.children.push(built);
338180
- }
338181
- }
338182
- if (collection.perVisitor && !outerItem) {
338183
- item = { collection, record: templateRecord(collection), suffix: `~${ITEM_RECORD}` };
338184
- const template2 = [];
338185
- for (const child of childrenOf(node2, doc2.nodes)) {
338186
- const built = build3(child, node2, kids3D, kidFold);
338187
- if (built) template2.push(built);
338188
- }
338189
- const sortField = repeat.sort && collection.fields.find((f3) => f3.id === repeat.sort.fieldId);
338190
- web.repeat = {
338191
- collectionId: collection.id,
338192
- template: template2,
338193
- ...repeat.filter?.trim() ? { filter: repeat.filter } : {},
338194
- ...sortField ? { sort: { key: fieldKey(sortField.name), dir: repeat.sort.dir } } : {},
338195
- ...repeat.offset ? { offset: repeat.offset } : {},
338196
- ...repeat.limit ? { limit: repeat.limit } : {}
338197
- };
338198
- }
338199
- } finally {
338200
- item = outerItem;
338201
- }
338202
- } else for (const child of childrenOf(node2, doc2.nodes)) {
338203
- const built = build3(child, node2, kids3D, kidFold);
338204
- if (built) web.children.push(built);
338205
- }
338206
- }
338207
- } finally {
338208
- motion = outer;
338209
- }
338210
- if (web.children.some((c2) => c2.positioning === "absolute")) {
338211
- for (const c2 of web.children) if (c2.positioning === "flow") c2.layered = true;
338212
- }
338213
- hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
338214
- return web;
338215
- };
338216
- const root2 = build3(first2, start2?.parent ?? null, start2?.in3D ?? false, start2?.fold ?? 0);
338217
- if (!root2) throw new Error("Node cap of 0");
338218
- return { root: root2, truncated, ...folds ? { rules: foldRules(folds) } : {}, ...tokens?.vars.length ? { tokens } : {} };
338219
- }
338220
- function childLookup(doc2, id3) {
338221
- const at3 = id3.lastIndexOf("::");
338222
- const host = at3 > 0 ? id3.slice(0, at3) : "";
338223
- const hostNode = doc2.nodes[host] ?? (host.includes("::") ? childLookup(doc2, host) : void 0);
338224
- return hostNode ? childrenOf(hostNode, doc2.nodes).find((c2) => c2.id === id3) : void 0;
338225
- }
338226
- function flatten2(node2, out = []) {
338227
- out.push(node2);
338228
- for (const c2 of node2.children) flatten2(c2, out);
338229
- return out;
338230
- }
338231
- var DEFAULT_NODE_CAP, PAINTED, anchorMemo, followsVisibility, isFlex, round3, foldVar, foldRules;
338232
- var init_tree = __esm({
338233
- "lib/io/web/tree.ts"() {
338234
- "use strict";
338235
- init_instance_layout();
338236
- init_text_styles();
338237
- init_variables();
338238
- init_scene3d();
338239
- init_semantics();
338240
- init_collections();
338241
- init_props();
338242
- init_native_registry();
338243
- init_controls();
338244
- init_expressions2();
338245
- init_children();
338246
- init_css();
338247
- init_capability();
338248
- init_expressible();
338249
- init_motion();
338250
- init_element();
338251
- init_paint2();
338252
- init_responsive();
338253
- init_richtext();
338254
- init_tokens2();
338255
- init_timeline();
338256
- init_interactive();
338257
- DEFAULT_NODE_CAP = 120;
338258
- PAINTED = ["background", "border", "border-style", "border-color", "border-width", "outline", "border-radius", "box-shadow", "box-sizing", "filter", "backdrop-filter"];
338259
- anchorMemo = /* @__PURE__ */ new WeakMap();
338260
- followsVisibility = (n) => !!n.boundVariables?.visible || !!n.boundExpressions?.visible || // Hidden in the design and shown at a breakpoint: on the page, for the media query that shows it.
338261
- Object.values(n.responsive ?? {}).some((o) => o.visible === true);
338262
- isFlex = (f2) => f2?.layoutMode === "HORIZONTAL" || f2?.layoutMode === "VERTICAL";
338263
- round3 = (v) => Math.round(v * 1e3) / 1e3;
338264
- foldVar = (depth2) => `--pc-f${depth2}`;
338265
- foldRules = (depth2) => Array.from({ length: depth2 }, (_, i2) => `@property ${foldVar(i2 + 1)} { syntax: '<number>'; inherits: true; initial-value: 1; }`);
338266
- }
338267
- });
338268
-
338269
338845
  // lib/io/web/assets.ts
338270
338846
  async function resolveWebAssets(tree, resolvers) {
338271
338847
  const pending7 = (Array.isArray(tree) ? tree : flatten2(tree.root)).filter((n) => !!n.asset);
@@ -338316,285 +338892,6 @@ var init_asset_files = __esm({
338316
338892
  }
338317
338893
  });
338318
338894
 
338319
- // lib/document/routes.ts
338320
- function screensOf(doc2, pageId2) {
338321
- return (doc2.nodes[pageId2]?.childIds ?? []).map((id3) => doc2.nodes[id3]).filter((f2) => f2?.type === "FRAME" && f2.visible !== false && !f2.print?.isMaster);
338322
- }
338323
- function cleanPath(raw) {
338324
- const parts = raw.trim().split("/").map(slug2).filter(Boolean);
338325
- return `/${parts.join("/")}`;
338326
- }
338327
- function routesOf(screens) {
338328
- const taken = /* @__PURE__ */ new Set();
338329
- const own2 = /* @__PURE__ */ new Map();
338330
- for (const s of screens) {
338331
- const path = s.route?.path ? cleanPath(s.route.path) : null;
338332
- if (path && !taken.has(path)) {
338333
- taken.add(path);
338334
- own2.set(s.id, path);
338335
- }
338336
- }
338337
- const rest = screens.filter((s) => !own2.has(s.id) && !s.route?.notFound);
338338
- const home = taken.has("/") ? void 0 : rest.find((s) => s.isFlowStartingPoint) ?? rest[0];
338339
- if (home) taken.add("/");
338340
- const out = /* @__PURE__ */ new Map();
338341
- for (const s of screens) {
338342
- if (own2.has(s.id)) {
338343
- out.set(s.id, own2.get(s.id));
338344
- continue;
338345
- }
338346
- if (s === home) {
338347
- out.set(s.id, "/");
338348
- continue;
338349
- }
338350
- const base = s.route?.notFound ? "/404" : `/${slug2(s.name) || "page"}`;
338351
- let route2 = base;
338352
- for (let n = 2; taken.has(route2); n++) route2 = `${base}-${n}`;
338353
- taken.add(route2);
338354
- out.set(s.id, route2);
338355
- }
338356
- return out;
338357
- }
338358
- var slug2;
338359
- var init_routes = __esm({
338360
- "lib/document/routes.ts"() {
338361
- slug2 = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
338362
- }
338363
- });
338364
-
338365
- // lib/island/slice.ts
338366
- function sliceDocument(doc2, nodeId2, opts = {}) {
338367
- const nodes = {};
338368
- const take = (id3) => {
338369
- const n = doc2.nodes[id3];
338370
- if (!n || nodes[id3]) return;
338371
- nodes[id3] = n;
338372
- for (const c2 of n.childIds ?? []) take(c2);
338373
- const main2 = n.mainComponentId;
338374
- if (main2) {
338375
- take(main2);
338376
- const set3 = doc2.nodes[main2]?.parentId;
338377
- if (set3 && doc2.nodes[set3]?.type === "COMPONENT_SET") take(set3);
338378
- }
338379
- };
338380
- if (opts.self && doc2.nodes[nodeId2]) nodes[nodeId2] = { ...doc2.nodes[nodeId2], childIds: [] };
338381
- else take(nodeId2);
338382
- let frameId = null;
338383
- let pageId2 = null;
338384
- let rootId = nodeId2;
338385
- for (let child = nodeId2, cur = doc2.nodes[nodeId2]?.parentId; cur; child = cur, cur = doc2.nodes[cur]?.parentId ?? null) {
338386
- const p2 = doc2.nodes[cur];
338387
- if (!p2) break;
338388
- if (p2.type === "PAGE") {
338389
- pageId2 = cur;
338390
- frameId = doc2.nodes[child]?.type === "FRAME" ? child : frameId;
338391
- }
338392
- if (!nodes[cur]) nodes[cur] = p2.type === "PAGE" ? { ...p2, childIds: [child] } : { ...p2, childIds: [child], fills: [], strokes: [], effects: [], shadows: void 0, blurs: void 0, clipsContent: false, layoutMode: "NONE" };
338393
- if (p2.type !== "PAGE") rootId = cur;
338394
- }
338395
- if (!frameId && doc2.nodes[nodeId2]?.type === "FRAME" && doc2.nodes[doc2.nodes[nodeId2].parentId ?? ""]?.type === "PAGE") frameId = nodeId2;
338396
- return {
338397
- nodeId: nodeId2,
338398
- frameId,
338399
- rootId,
338400
- ...opts.self ? { fit: "fill" } : {},
338401
- document: {
338402
- id: doc2.id,
338403
- name: doc2.name,
338404
- pages: pageId2 ? [pageId2] : [],
338405
- nodes,
338406
- styles: doc2.styles,
338407
- variables: doc2.variables,
338408
- variableCollections: doc2.variableCollections,
338409
- activeVariableModes: doc2.activeVariableModes,
338410
- settings: doc2.settings
338411
- }
338412
- };
338413
- }
338414
- var init_slice = __esm({
338415
- "lib/island/slice.ts"() {
338416
- "use strict";
338417
- }
338418
- });
338419
-
338420
- // lib/io/web/site.ts
338421
- function light(node2) {
338422
- const out = {};
338423
- for (const k2 in node2) if (!HEAVY.has(k2)) out[k2] = node2[k2];
338424
- return out;
338425
- }
338426
- function programDocument(doc2, pageId2, screens) {
338427
- const nodes = {};
338428
- const take = (id3) => {
338429
- const n = doc2.nodes[id3];
338430
- if (!n || nodes[id3]) return;
338431
- nodes[id3] = light(n);
338432
- for (const c2 of n.childIds ?? []) take(c2);
338433
- const main2 = n.mainComponentId;
338434
- if (main2) {
338435
- take(main2);
338436
- const set3 = doc2.nodes[main2]?.parentId;
338437
- if (set3 && doc2.nodes[set3]?.type === "COMPONENT_SET") take(set3);
338438
- }
338439
- };
338440
- const page = doc2.nodes[pageId2];
338441
- if (page) nodes[pageId2] = { ...light(page), childIds: screens.map((s) => s.id) };
338442
- for (const s of screens) take(s.id);
338443
- return {
338444
- id: doc2.id,
338445
- name: doc2.name,
338446
- nodes,
338447
- pages: [pageId2],
338448
- styles: {},
338449
- variables: doc2.variables,
338450
- variableCollections: doc2.variableCollections,
338451
- activeVariableModes: doc2.activeVariableModes,
338452
- settings: doc2.settings,
338453
- // What a layer that follows a record's field is drawn from, while the page runs.
338454
- ...doc2.collections && Object.keys(doc2.collections).length ? { collections: doc2.collections, records: doc2.records } : {}
338455
- };
338456
- }
338457
- function withVariants(doc2, root2, opts, depth2 = 3) {
338458
- if (depth2 <= 0) return;
338459
- for (const w of flatten2(root2)) {
338460
- const inst = w.type === "INSTANCE" && !w.id.includes("::") ? doc2.nodes[w.id] : void 0;
338461
- const main2 = inst?.mainComponentId;
338462
- if (!inst || !main2 || w.variants) continue;
338463
- const reach = variantStates(doc2, main2);
338464
- if (reach.length < 2) continue;
338465
- w.variant = main2;
338466
- w.variants = {};
338467
- const parent = inst.parentId ? doc2.nodes[inst.parentId] ?? null : null;
338468
- for (const v of reach.slice(1)) {
338469
- const as2 = { ...doc2, nodes: { ...doc2.nodes, [inst.id]: { ...inst, mainComponentId: v } } };
338470
- const built = buildPlainTree(as2, inst.id, opts, { parent, in3D: false, fold: 0 }).root;
338471
- built.variant = v;
338472
- withVariants(as2, built, opts, depth2 - 1);
338473
- w.variants[v] = built;
338474
- }
338475
- }
338476
- }
338477
- function everyNode(root2, out = []) {
338478
- for (const n of flatten2(root2)) {
338479
- out.push(n);
338480
- for (const v of Object.values(n.variants ?? {})) everyNode(v, out);
338481
- }
338482
- return out;
338483
- }
338484
- function mediaRules(doc2, screenId, base, opts) {
338485
- const rules = [];
338486
- let above = new Map(flatten2(base).map((n) => [n.id, declared(n, n === base)]));
338487
- for (const bp of breakpointsOf(doc2).slice(1)) {
338488
- const view2 = breakpointDocument(doc2, bp.id);
338489
- const root2 = buildPlainTree(view2, screenId, opts).root;
338490
- const here = new Map(flatten2(root2).map((n) => [n.id, declared(n, n === root2)]));
338491
- const blocks = [];
338492
- for (const [id3, was] of above) {
338493
- const now2 = here.get(id3);
338494
- const diff = {};
338495
- if (!now2) {
338496
- if (was.display !== "none") diff.display = "none";
338497
- } else {
338498
- for (const k2 in was) if (!(k2 in now2)) diff[k2] = "revert";
338499
- for (const k2 in now2) if (now2[k2] !== was[k2]) diff[k2] = now2[k2];
338500
- }
338501
- if (Object.keys(diff).length) blocks.push(` [data-pc-id="${id3}"] {
338502
- ${styleMapToCSSText(Object.fromEntries(Object.entries(diff).map(([k2, v]) => [k2, `${v} !important`])), " ")}
338503
- }`);
338504
- }
338505
- if (blocks.length) rules.push(`@media (max-width: ${bp.maxWidth}px) {
338506
- ${blocks.join("\n")}
338507
- }`);
338508
- above = new Map([...above].map(([id3, was]) => [id3, here.get(id3) ?? { ...was, display: "none" }]));
338509
- }
338510
- return rules;
338511
- }
338512
- function sitePages(doc2, pageId2) {
338513
- const screens = screensOf(doc2, pageId2);
338514
- const routes = routesOf(screens);
338515
- return screens.flatMap((s) => {
338516
- const base = routes.get(s.id);
338517
- const collection = s.route?.collectionId ? doc2.collections?.[s.route.collectionId] : void 0;
338518
- if (!collection) return [{ id: s.id, frame: s, route: base, title: s.route?.title || s.name }];
338519
- const slugs = recordSlugs(doc2, collection.id);
338520
- return recordsIn(doc2, collection.id).map((record2) => ({
338521
- id: `${s.id}~${record2.id}`,
338522
- frame: s,
338523
- record: record2,
338524
- collection,
338525
- route: `${base === "/" ? "" : base}/${slugs.get(record2.id)}`,
338526
- title: itemText(s.route?.title || s.name, collection, record2)
338527
- }));
338528
- });
338529
- }
338530
- function buildWebSite(doc2, opts = {}) {
338531
- const pageId2 = opts.pageId ?? doc2.pages[0];
338532
- const screens = screensOf(doc2, pageId2);
338533
- const routes = routesOf(screens);
338534
- const build3 = { target: "site", nodeCap: opts.nodeCap ?? 2e4, static: opts.static, routes: Object.fromEntries(routes) };
338535
- const laid = /* @__PURE__ */ new Set();
338536
- const pages2 = sitePages(doc2, pageId2).map((p2) => {
338537
- const s = p2.frame;
338538
- const opts2 = p2.record ? { ...build3, item: { collectionId: p2.collection.id, recordId: p2.record.id } } : build3;
338539
- const tree = buildPlainTree(doc2, s.id, opts2);
338540
- const media2 = laid.has(s.id) ? [] : mediaRules(doc2, s.id, tree.root, opts2);
338541
- laid.add(s.id);
338542
- withVariants(doc2, tree.root, opts2);
338543
- const description = s.route?.description ? p2.record ? itemText(s.route.description, p2.collection, p2.record) : s.route.description : void 0;
338544
- const moves3 = !opts2.static && hasFrameMotion(doc2.nodes, s.id);
338545
- const length2 = moves3 ? timelineDuration(doc2.nodes, s.id) : 0;
338546
- const machine = moves3 ? webStateMachine(doc2, s.id) : null;
338547
- return {
338548
- ...machine ? { machine } : {},
338549
- ...length2 > 0 ? { timeline: { duration: length2, stops: stopsOf(frameTimeline(doc2.nodes, s.id).markers, [0, length2]), loops: frameRunsOn(doc2.nodes, s.id) } } : {},
338550
- id: p2.id,
338551
- route: p2.route,
338552
- title: p2.title,
338553
- ...p2.record ? { screen: s.id, record: p2.record.id } : {},
338554
- ...description ? { description } : {},
338555
- ...s.route?.notFound ? { notFound: true } : {},
338556
- ...s.route?.access ? { access: s.route.access } : {},
338557
- tree,
338558
- ...media2.length ? { media: media2 } : {}
338559
- };
338560
- });
338561
- const islandNodes = new Map(pages2.flatMap((p2) => everyNode(p2.tree.root).filter((n) => n.island && !n.id.includes("::"))).map((n) => [n.id, n]));
338562
- const fonts = /* @__PURE__ */ new Map();
338563
- for (const p2 of pages2) for (const [family, weights] of fontFamilies(p2.tree)) for (const w of weights) (fonts.get(family) ?? fonts.set(family, /* @__PURE__ */ new Set()).get(family)).add(w);
338564
- const home = pages2.find((p2) => p2.route === "/" && !p2.screen);
338565
- return {
338566
- name: doc2.name,
338567
- pages: pages2,
338568
- home: home?.id ?? null,
338569
- tokens: pages2.find((p2) => p2.tree.tokens)?.tree.tokens,
338570
- fonts: [...fonts].sort(([a], [b]) => a.localeCompare(b)).map(([family, w]) => ({ family, weights: [...w].sort((a, b) => a - b) })),
338571
- assets: pages2.flatMap((p2) => everyNode(p2.tree.root).filter((n) => n.asset).map((n) => n.id)),
338572
- program: { document: programDocument(doc2, pageId2, screens), start: home?.id ?? null },
338573
- ...islandNodes.size ? { islands: Object.fromEntries([...islandNodes].map(([id3, n]) => [id3, sliceDocument(doc2, n.asset?.of ?? layerId(id3), { self: !!n.asset?.self })])) } : {}
338574
- };
338575
- }
338576
- var HEAVY, declared;
338577
- var init_site2 = __esm({
338578
- "lib/io/web/site.ts"() {
338579
- "use strict";
338580
- init_breakpoints();
338581
- init_collections();
338582
- init_routes();
338583
- init_instances2();
338584
- init_timeline_stops();
338585
- init_css();
338586
- init_element();
338587
- init_fonts3();
338588
- init_slice();
338589
- init_state_machine3();
338590
- init_interactive();
338591
- init_tree();
338592
- init_routes();
338593
- HEAVY = /* @__PURE__ */ new Set(["fills", "strokes", "effects", "shadows", "blurs", "vectorPaths", "paths", "styledSegments", "paragraphs", "imageUrl", "exportSettings", "annotations", "devResources", "codeConnect", "layoutGrids", "aiPending"]);
338594
- declared = (n, isRoot) => ({ ...placementStyle(n, isRoot), ...n.style, ...n.hidden ? { display: "none" } : {} });
338595
- }
338596
- });
338597
-
338598
338895
  // lib/io/web/index.ts
338599
338896
  var web_exports = {};
338600
338897
  __export(web_exports, {
@@ -338670,7 +338967,7 @@ var init_web = __esm({
338670
338967
  init_asset_files();
338671
338968
  init_element();
338672
338969
  init_fonts3();
338673
- init_site2();
338970
+ init_site();
338674
338971
  init_tokens2();
338675
338972
  init_naming();
338676
338973
  init_tree();
@@ -338796,7 +339093,7 @@ var init_host = __esm({
338796
339093
  "lib/preview/host.ts"() {
338797
339094
  "use strict";
338798
339095
  init_cdn();
338799
- init_site();
339096
+ init_site2();
338800
339097
  init_snapshot_frame();
338801
339098
  init_web();
338802
339099
  init_media_store();
@@ -338878,7 +339175,8 @@ async function completeSite(doc2, pageId2) {
338878
339175
  const [{ previewSite: previewSite2 }, { rendererAssetResolvers: rendererAssetResolvers2 }] = await Promise.all([Promise.resolve().then(() => (init_host(), host_exports)), Promise.resolve().then(() => (init_resolvers(), resolvers_exports))]);
338879
339176
  return previewSite2(doc2, pageId2, rendererAssetResolvers2(doc2));
338880
339177
  }
338881
- async function nextFilesOf(site, doc2, opts = {}) {
339178
+ async function nextFilesOf(full, doc2, opts = {}) {
339179
+ const site = withoutScreenIslands(full);
338882
339180
  const islandScript2 = site.islands && Object.keys(site.islands).length ? await runtimeScript("island") : null;
338883
339181
  return [...nextProjectFiles(site, doc2, { ...opts, islandScript: islandScript2 }), ...await appAssetFiles(appAssetPaths(site), "public/")];
338884
339182
  }
@@ -338894,6 +339192,7 @@ var init_build2 = __esm({
338894
339192
  init_assets();
338895
339193
  init_static();
338896
339194
  init_next();
339195
+ init_site();
338897
339196
  runtimeScript = (name2) => fetch(`/pc/${name2}.js?fresh=${Date.now()}`, { cache: "no-store" }).then((r) => r.ok ? r.text() : null).catch(() => null);
338898
339197
  NoSiteRuntime = class extends Error {
338899
339198
  constructor() {
@@ -340134,7 +340433,7 @@ var init_motion2 = __esm({
340134
340433
  ui: { label: "Edit composition", palette: false },
340135
340434
  agent: {
340136
340435
  name: "edit_composition",
340137
- description: `Change a composition's scenes: reorder a clip (move), trim what of its frame's timeline it plays (trim), set the transition INTO a clip from the one before (transition: DISSOLVE, SLIDE_*/PUSH_*/MOVE_OUT_*, CIRCLE_WIPE, IRIS, ZOOM_THROUGH, WHIP_LEFT, WHIP_RIGHT, CUT), add frames as clips, remove a clip, swap the frame a clip plays (frame), rename, or delete it. Clips stay in sequence: later clips ripple, and a transition overlaps the clip before by its duration. Sound: addAudio places a file from the media store on a lane (clips on a lane never overlap; one that would moves to the next free lane), audio moves/trims/fades/pans/mutes a clip, trimAudio drags an edge, gainKey keys its level (clip ms, linear), removeAudio drops it, splitAudio cuts it at a time, crossfade crosses two clips over with equal-power fades, onsets replaces the "onsets" markers. settings sets the stage size, frame rate, background and work area; addMarker / updateMarker / removeMarker edit its markers. Read it with get_compositions; add sound from a URL or the media store with add_audio.`
340436
+ description: `Change a composition's scenes: reorder a clip (move), trim what of its frame's timeline it plays (trim), set the transition INTO a clip from the one before (transition: DISSOLVE, SLIDE_*/PUSH_*/MOVE_OUT_*, CIRCLE_WIPE, IRIS, ZOOM_THROUGH, WHIP_LEFT, WHIP_RIGHT, CUBE_FROM_*, CAROUSEL_FROM_LEFT/RIGHT, FLIP_HORIZONTAL/VERTICAL, SWING_OPEN/CLOSE, STACK_IN/OUT, DEPTH_PUSH/PULL, CUT), add frames as clips, remove a clip, swap the frame a clip plays (frame), rename, or delete it. Clips stay in sequence: later clips ripple, and a transition overlaps the clip before by its duration. Sound: addAudio places a file from the media store on a lane (clips on a lane never overlap; one that would moves to the next free lane), audio moves/trims/fades/pans/mutes a clip, trimAudio drags an edge, gainKey keys its level (clip ms, linear), removeAudio drops it, splitAudio cuts it at a time, crossfade crosses two clips over with equal-power fades, onsets replaces the "onsets" markers. settings sets the stage size, frame rate, background and work area; addMarker / updateMarker / removeMarker edit its markers. Read it with get_compositions; add sound from a URL or the media store with add_audio.`
340138
340437
  }
340139
340438
  },
340140
340439
  run: (args2, ctx2) => {
@@ -343898,7 +344197,7 @@ var init_prototype = __esm({
343898
344197
  triggerKey: external_exports.string().max(40).optional(),
343899
344198
  dragDirection: external_exports.enum(["LEFT", "RIGHT", "UP", "DOWN"]).optional()
343900
344199
  });
343901
- LIVE = ["characters", ...LIVE_VALUE_PROPS];
344200
+ LIVE = ["characters", "imageUrl", ...LIVE_VALUE_PROPS];
343902
344201
  prototypeEdit = defineCommand({
343903
344202
  id: "prototype.edit",
343904
344203
  title: "Edit prototype",
@@ -344715,6 +345014,7 @@ function designFrameOf(doc2, id3) {
344715
345014
  }
344716
345015
  var init_locate = __esm({
344717
345016
  "lib/agent/design-script/locate.ts"() {
345017
+ "use strict";
344718
345018
  }
344719
345019
  });
344720
345020
 
@@ -344953,6 +345253,7 @@ function placeDesign(doc2, built, source3, size6, name2, at3) {
344953
345253
  var DESIGN_NAMESPACES, DERIVED2, templateOfBuild;
344954
345254
  var init_build3 = __esm({
344955
345255
  "lib/agent/design-script/build.ts"() {
345256
+ "use strict";
344956
345257
  init_hash();
344957
345258
  init_scene_graph();
344958
345259
  init_libraries();
@@ -345871,7 +346172,9 @@ Every layer call returns its id. **Name** every layer a cue, count or swap must
345871
346172
  - Live state: \`const yearly = k.variable('Billing', 'yearly', 'BOOLEAN', false)\`, \`k.setVariable(layer, yearly, { toggle: true })\`
345872
346173
  on click, \`k.bindVariable(layer, 'visible', yearly)\` to show a layer while it is true (see the pricing example).
345873
346174
  - Prototype links: \`k.link(fromLayer, toFrame, 'PUSH_FROM_RIGHT')\` between screens made with \`k.addScreen(name)\`, and
345874
- \`k.flowStart(frame, name)\`.`;
346175
+ \`k.flowStart(frame, name)\`. 3D transitions (\`'CUBE_FROM_RIGHT'\`, \`'CAROUSEL_FROM_LEFT'\`, \`'FLIP_HORIZONTAL'\`,
346176
+ \`'SWING_OPEN'\`, \`'STACK_IN'\`, \`'DEPTH_PUSH'\` and their pairs) turn the screens through a perspective and default to
346177
+ 650 ms; a published site draws them on the GPU only when one is used, so keep a plain site's links flat.`;
345875
346178
  MOTION = `## Motion and music
345876
346179
 
345877
346180
  Set the timeline first, then add moves. Times are ms on the frame's timeline.
@@ -346433,7 +346736,7 @@ function collectionOf(doc2, ref3) {
346433
346736
  if (!c2) throw new ToolError(`No collection "${ref3}". ${Object.values(doc2.collections ?? {}).length ? `There is: ${Object.values(doc2.collections).map((x2) => x2.name).join(", ")}.` : "Make one with edit_collection."}`);
346434
346737
  return c2;
346435
346738
  }
346436
- var sizing, padding, overrides, nodeSetResponsive, link, nodeSetSemantics, nodeSetControl, siteSetRoute, breakpoint, siteSetBreakpoints, siteGetBreakpoints, described2, dataEditCollection, dataEditRecords, dataGetRecords, nodeSetRepeat;
346739
+ var sizing, padding, overrides, nodeSetResponsive, link, nodeSetSemantics, nodeSetControl, siteSetRoute, breakpoint, siteSetBreakpoints, siteSetGpuTransitions, siteGetBreakpoints, described2, dataEditCollection, dataEditRecords, dataGetRecords, nodeSetRepeat;
346437
346740
  var init_site3 = __esm({
346438
346741
  "lib/commands/site.ts"() {
346439
346742
  "use strict";
@@ -346719,6 +347022,30 @@ var init_site3 = __esm({
346719
347022
  return { summary: `Breakpoints: ${breakpointsOf({ site: { breakpoints: list2 } }).map((b) => b.maxWidth === null ? b.name : `${b.name} \u2264 ${b.maxWidth}`).join(", ")}`, data: { breakpoints: breakpointsOf({ site: { breakpoints: list2 } }) } };
346720
347023
  }
346721
347024
  });
347025
+ siteSetGpuTransitions = defineCommand({
347026
+ id: "site.setGpuTransitions",
347027
+ title: "Draw 3D transitions with WebGPU",
347028
+ domain: "site",
347029
+ effect: "document",
347030
+ permission: "write",
347031
+ undoLabel: "Change how 3D transitions are drawn",
347032
+ params: external_exports.object({
347033
+ on: external_exports.boolean().describe("true (the default): a published site draws its 3D transitions on the GPU where the visitor has WebGPU, in CSS 3D elsewhere. false: always in CSS 3D, and the GPU renderer is never shipped for them.")
347034
+ }).strict(),
347035
+ expose: {
347036
+ ui: { label: "Draw 3D transitions with WebGPU", keywords: ["webgpu", "gpu", "3d", "transition", "cube", "flip", "css", "site", "publish"], variants: [{ id: "on", label: "Draw 3D transitions with WebGPU", params: { on: true } }, { id: "off", label: "Draw 3D transitions in CSS only", params: { on: false } }] },
347037
+ agent: {
347038
+ name: "set_gpu_transitions",
347039
+ description: "Choose how a published site draws its 3D transitions (cube, carousel, flip, swing, stack, depth): on the GPU where the visitor's browser has WebGPU and in CSS 3D elsewhere (on, the default), or always in CSS 3D so the site never loads the GPU renderer for them (off). Sites whose links use no 3D transition never load it either way."
347040
+ }
347041
+ },
347042
+ run: (args2, ctx2) => {
347043
+ const doc2 = ctx2.doc();
347044
+ const { gpuTransitions: _, ...rest } = doc2.site ?? {};
347045
+ ctx2.commit({ ...doc2, site: args2.on ? rest : { ...rest, gpuTransitions: false } });
347046
+ return { summary: args2.on ? "3D transitions draw with WebGPU where the browser has it" : "3D transitions draw in CSS 3D only", data: { on: args2.on } };
347047
+ }
347048
+ });
346722
347049
  siteGetBreakpoints = defineCommand({
346723
347050
  id: "site.getBreakpoints",
346724
347051
  title: "Get breakpoints",
@@ -347299,7 +347626,6 @@ var init_plugin_widget = __esm({
347299
347626
  var storeOpsSeam;
347300
347627
  var init_seams = __esm({
347301
347628
  "lib/commands/seams.ts"() {
347302
- "use strict";
347303
347629
  storeOpsSeam = (st) => ({
347304
347630
  booleanOperation: (op4) => st().booleanOperation(op4),
347305
347631
  flatten: () => st().flattenSelection(),
@@ -380187,7 +380513,6 @@ function registerBuiltinCommands() {
380187
380513
  var builtinCommands, uiOnlyCommands;
380188
380514
  var init_builtin2 = __esm({
380189
380515
  "lib/commands/builtin.ts"() {
380190
- "use strict";
380191
380516
  init_registry();
380192
380517
  init_node();
380193
380518
  init_node();
@@ -380372,6 +380697,7 @@ var init_builtin2 = __esm({
380372
380697
  dataEditCollection,
380373
380698
  dataEditRecords,
380374
380699
  dataGetRecords,
380700
+ siteSetGpuTransitions,
380375
380701
  // the file as a website online (lib/client/cloud/publish-site.ts): what is published (appended, as above)
380376
380702
  publishStatus,
380377
380703
  // designs as code (lib/agent/design-script): a whole design from one template-kit script (appended, as above)
@@ -380743,8 +381069,8 @@ async function renderLibraryPreviews(renderer, doc2, listing, format = pickPrevi
380743
381069
  const cap2 = await capture(renderer, doc2, c2.playsId, componentSchedule(c2.duration), previewScale(PREVIEW_BOX));
380744
381070
  if (!cap2.frames.length) continue;
380745
381071
  out.push({ key: c2.id, file: "anim", type: FORMAT_MIME[format], bytes: await encodeFrames(format, cap2.width, cap2.height, cap2.frames, PREVIEW_FPS) });
380746
- const still = cap2.frames[fullestFrame(cap2.frames)];
380747
- out.push({ key: c2.id, file: "still", type: PREVIEW_STILL_TYPE, bytes: await encodeRaster("PNG", cap2.width, cap2.height, still.rgba) });
381072
+ const still2 = cap2.frames[fullestFrame(cap2.frames)];
381073
+ out.push({ key: c2.id, file: "still", type: PREVIEW_STILL_TYPE, bytes: await encodeRaster("PNG", cap2.width, cap2.height, still2.rgba) });
380748
381074
  }
380749
381075
  const shownCells = listing.filter((c2) => doc2.nodes[c2.playsId]).slice(0, POSTER_MAX);
380750
381076
  if (!shownCells.length) return out;
@@ -381139,8 +381465,8 @@ async function renderShaderPreview(device, fills, code, params2, zoom = 1) {
381139
381465
  };
381140
381466
  const animated = reflectShader(code).animated;
381141
381467
  if (!animated) {
381142
- const still = await draw(0);
381143
- return still && { type: "image/png", bytes: await encodeRaster("PNG", w, h, overGround(still)), width: w, height: h, animated };
381468
+ const still2 = await draw(0);
381469
+ return still2 && { type: "image/png", bytes: await encodeRaster("PNG", w, h, overGround(still2)), width: w, height: h, animated };
381144
381470
  }
381145
381471
  const frames = [];
381146
381472
  for (const f2 of previewFrames()) {
@@ -391555,7 +391881,7 @@ async function runInEditor(doc2, commandId, params2, opts) {
391555
391881
  }
391556
391882
  }
391557
391883
  var decodeDataUrl2;
391558
- var init_render = __esm({
391884
+ var init_render2 = __esm({
391559
391885
  "packages/cli/src/render.ts"() {
391560
391886
  "use strict";
391561
391887
  init_editor_open();
@@ -391664,7 +391990,7 @@ async function step2(command, params2, flags, rc) {
391664
391990
  if (where === "plugin" || where === "signin" || where === "app" || where === "unavailable") throw new CliError(`${command.id}: ${WHERE_HELP[where]}`);
391665
391991
  if (where === "browser") {
391666
391992
  if (flagBool(flags, "dryRun")) return { result: { summary: `Would run ${command.id} in the editor (dry run)` }, files: [] };
391667
- const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render(), render_exports));
391993
+ const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render2(), render_exports));
391668
391994
  const download = specOf(command).flags.some((f2) => f2.param === "download" && f2.type === "boolean") && params2.download === void 0 ? { download: true } : {};
391669
391995
  const done = await runInEditor2(currentDocument(), command.id, { ...params2, ...download }, { appUrl: rc.appUrl, surface: command.expose.ui ? "ui" : "agent", headful: flagBool(flags, "headful"), out: flagString(flags, "out"), info: rc.out.info });
391670
391996
  return { result: done.result ?? { summary: `Ran ${command.id}` }, files: done.files };
@@ -391680,7 +392006,7 @@ async function step2(command, params2, flags, rc) {
391680
392006
  }
391681
392007
  async function reviewInEditor(doc2, frames, look, flags, rc, media2) {
391682
392008
  if (!frames.length) return [];
391683
- const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render(), render_exports));
392009
+ const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render2(), render_exports));
391684
392010
  const out = flagString(flags, "out") ?? "look/";
391685
392011
  const opts = { appUrl: rc.appUrl, surface: "agent", headful: flagBool(flags, "headful"), out: out.endsWith("/") ? out : `${out}/`, info: rc.out.info, media: media2 };
391686
392012
  const files = [];
@@ -392237,13 +392563,13 @@ async function openSettled(page, t3, sizeId) {
392237
392563
  const sleep4 = (ms2) => new Promise((r) => setTimeout(r, ms2));
392238
392564
  const quiet = async () => {
392239
392565
  let last3 = w.__vpStore.getState().document.nodes;
392240
- for (let still = 0, i2 = 0; still < 6 && i2 < 300; i2++) {
392566
+ for (let still2 = 0, i2 = 0; still2 < 6 && i2 < 300; i2++) {
392241
392567
  await w.__vpRenderer.whenReady();
392242
392568
  await sleep4(100);
392243
392569
  const now2 = w.__vpStore.getState().document.nodes;
392244
- if (now2 === last3) still++;
392570
+ if (now2 === last3) still2++;
392245
392571
  else {
392246
- still = 0;
392572
+ still2 = 0;
392247
392573
  last3 = now2;
392248
392574
  }
392249
392575
  }
@@ -392422,14 +392748,14 @@ async function runPictures(root2, appUrl, out) {
392422
392748
  const t3 = asTemplate(upload);
392423
392749
  const sizeId = t3.payload.variants[0].sizeId;
392424
392750
  const thumbnail = await drawThumbnail(editor, t3, sizeId);
392425
- const still = await drawDetailStill(editor, t3, sizeId);
392751
+ const still2 = await drawDetailStill(editor, t3, sizeId);
392426
392752
  const anim = upload.meta.animated ? await drawPreview(editor, t3, false) : null;
392427
392753
  const folder = join9(dir, "pictures");
392428
392754
  rmSync4(folder, { recursive: true, force: true });
392429
392755
  mkdirSync6(folder, { recursive: true });
392430
- writeFileSync7(join9(folder, "still.webp"), still.bytes);
392756
+ writeFileSync7(join9(folder, "still.webp"), still2.bytes);
392431
392757
  if (anim) writeFileSync7(join9(folder, "anim.mp4"), anim.bytes);
392432
- const pictures = { still: { w: still.width, h: still.height }, ...anim ? { anim: { w: anim.width, h: anim.height, ms: anim.durationMs } } : {} };
392758
+ const pictures = { still: { w: still2.width, h: still2.height }, ...anim ? { anim: { w: anim.width, h: anim.height, ms: anim.durationMs } } : {} };
392433
392759
  writeFileSync7(join9(folder, "pictures.json"), `${JSON.stringify(pictures, null, 2)}
392434
392760
  `);
392435
392761
  writeFileSync7(join9(dir, "template.json"), JSON.stringify({ ...upload, meta: { ...upload.meta, thumbnail } }));
@@ -392450,7 +392776,7 @@ var init_pictures = __esm({
392450
392776
  "use strict";
392451
392777
  init_pictures_node();
392452
392778
  init_publish2();
392453
- init_render();
392779
+ init_render2();
392454
392780
  init_io();
392455
392781
  asTemplate = (u) => ({ meta: { ...u.meta, id: u.meta.localId }, payload: u.payload });
392456
392782
  }
@@ -393019,7 +393345,7 @@ init_resources();
393019
393345
  init_desktop();
393020
393346
  init_hypery();
393021
393347
  import { createInterface } from "node:readline";
393022
- var VERSION2 = "0.7.1";
393348
+ var VERSION2 = "0.8.1";
393023
393349
  var HELP = `popcraft ${VERSION2} \u2014 the PopCraft command line
393024
393350
 
393025
393351
  Files (headless, on .popcraft files):