@popcraft/cli 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/popcraft.mjs +1573 -1252
  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.0"}`, ...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",
@@ -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);
@@ -89179,6 +89220,83 @@ var init_keys = __esm({
89179
89220
  });
89180
89221
 
89181
89222
  // lib/motion/transitions.ts
89223
+ function faceBrightness(rotateX, rotateY) {
89224
+ const c2 = Math.abs(Math.cos(rotateX * Math.PI / 180) * Math.cos(rotateY * Math.PI / 180));
89225
+ return AMBIENT_SHADE + (1 - AMBIENT_SHADE) * c2;
89226
+ }
89227
+ function ringFace(side, axis, angle2, r, dolly) {
89228
+ const s = Math.sin(rad2(angle2)), z2 = -r + r * Math.cos(rad2(angle2)) - dolly;
89229
+ 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) };
89230
+ }
89231
+ function transition3dPose(type, progress2, stage) {
89232
+ if (!is3DTransition(type)) return null;
89233
+ const p2 = Math.min(1, Math.max(0, progress2));
89234
+ const W = Math.max(1, stage.width), H = Math.max(1, stage.height);
89235
+ const arc = Math.sin(Math.PI * p2);
89236
+ const pose = (extent2, faces2) => ({ perspective: 1.8 * extent2, faces: backToFront(faces2) });
89237
+ if (p2 <= 0) return pose(W, [still("a")]);
89238
+ if (p2 >= 1) return pose(W, [still("b")]);
89239
+ switch (type) {
89240
+ case "CUBE_FROM_RIGHT":
89241
+ 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)]);
89242
+ case "CUBE_FROM_LEFT":
89243
+ 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)]);
89244
+ case "CUBE_FROM_BOTTOM":
89245
+ 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)]);
89246
+ case "CUBE_FROM_TOP":
89247
+ 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)]);
89248
+ case "CAROUSEL_FROM_RIGHT":
89249
+ case "CAROUSEL_FROM_LEFT": {
89250
+ const r = (W / 2 + 0.06 * W) / Math.tan(rad2(30)), dir = type === "CAROUSEL_FROM_RIGHT" ? 1 : -1;
89251
+ 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)]);
89252
+ }
89253
+ case "FLIP_HORIZONTAL":
89254
+ case "FLIP_VERTICAL": {
89255
+ const front = -180 * p2, back = 180 * (1 - p2), z2 = -0.2 * (type === "FLIP_HORIZONTAL" ? W : H) * arc;
89256
+ const face = (side, angle2) => still(side, {
89257
+ z: z2,
89258
+ ...type === "FLIP_HORIZONTAL" ? { rotateY: angle2 } : { rotateX: -angle2 },
89259
+ opacity: Math.cos(rad2(angle2)) > 0 ? 1 : 0,
89260
+ brightness: faceBrightness(0, angle2)
89261
+ });
89262
+ return pose(type === "FLIP_HORIZONTAL" ? W : H, [face("a", front), face("b", back)]);
89263
+ }
89264
+ // A door: a nearer camera than the turns (the hinge must read as turning in depth, not as a page shrinking), and
89265
+ // the room behind it does not move — it only comes out of the door's shadow.
89266
+ case "SWING_OPEN":
89267
+ return { perspective: 1.1 * W, faces: backToFront([
89268
+ still("b", { z: -1, brightness: 0.55 + 0.45 * p2 }),
89269
+ still("a", { anchorX: 0, rotateY: 100 * p2, opacity: 1 - ramp(p2, 0.75, 1), brightness: faceBrightness(0, 100 * p2) })
89270
+ ]) };
89271
+ case "SWING_CLOSE":
89272
+ return { perspective: 1.1 * W, faces: backToFront([
89273
+ still("a", { z: -1, brightness: 1 - 0.45 * p2 }),
89274
+ still("b", { anchorX: 0, rotateY: 100 * (1 - p2), opacity: ramp(p2, 0, 0.25), brightness: faceBrightness(0, 100 * (1 - p2)) })
89275
+ ]) };
89276
+ case "STACK_IN":
89277
+ return pose(H, [
89278
+ still("a", { z: -0.12 * W * p2, rotateX: 6 * p2, brightness: 1 - 0.35 * p2 }),
89279
+ still("b", { ty: H * (1 - p2), z: 1e-3 })
89280
+ ]);
89281
+ case "STACK_OUT":
89282
+ return pose(H, [
89283
+ still("b", { z: -0.12 * W * (1 - p2), rotateX: 6 * (1 - p2), brightness: 1 - 0.35 * (1 - p2) }),
89284
+ still("a", { ty: H * p2, z: 1e-3 })
89285
+ ]);
89286
+ case "DEPTH_PUSH":
89287
+ return pose(Math.max(W, H), [
89288
+ still("a", { z: -0.6 * W * p2, opacity: 1 - p2, brightness: 1 - 0.3 * p2 }),
89289
+ still("b", { z: 0.35 * W * (1 - p2), opacity: p2 })
89290
+ ]);
89291
+ case "DEPTH_PULL":
89292
+ return pose(Math.max(W, H), [
89293
+ still("b", { z: -0.6 * W * (1 - p2), opacity: p2, brightness: 1 - 0.3 * (1 - p2) }),
89294
+ still("a", { z: 0.35 * W * p2, opacity: 1 - p2 })
89295
+ ]);
89296
+ default:
89297
+ return null;
89298
+ }
89299
+ }
89182
89300
  function scaledAbout(m, k2, cx, cy) {
89183
89301
  return k2 === 1 ? m : multiply([k2, 0, 0, k2, cx - k2 * cx, cy - k2 * cy], m);
89184
89302
  }
@@ -89193,6 +89311,16 @@ function coverRadius(stage, c2) {
89193
89311
  }
89194
89312
  function transitionRoots(type, progress2, a, b, stage, params2) {
89195
89313
  const p2 = Math.min(1, Math.max(0, progress2));
89314
+ if (is3DTransition(type)) {
89315
+ const flat2 = transitionRoots(flatTransitionType(type), p2, a, b, stage, params2);
89316
+ const pose = p2 > 0 && p2 < 1 ? transition3dPose(type, p2, stage) : null;
89317
+ if (!pose) return flat2;
89318
+ return pose.faces.map((f2) => {
89319
+ const side = f2.side === "a" ? a : b;
89320
+ const r = flat2.find((x2) => x2.rootId === side.id);
89321
+ return { rootId: side.id, matrix: r?.matrix ?? side.base, opacity: r ? r.opacity : 0, face: { ...f2, base: side.base, stage, perspective: pose.perspective } };
89322
+ });
89323
+ }
89196
89324
  switch (type) {
89197
89325
  case "INSTANT":
89198
89326
  case "CUT":
@@ -89248,9 +89376,11 @@ function transitionRoots(type, progress2, a, b, stage, params2) {
89248
89376
  const outScale = 1 + (ZOOM_OUT_SCALE - 1) * p2;
89249
89377
  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
89378
  }
89379
+ default:
89380
+ return [root(a, a.base, 1 - p2), root(b, b.base, p2)];
89251
89381
  }
89252
89382
  }
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;
89383
+ 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
89384
  var init_transitions = __esm({
89255
89385
  "lib/motion/transitions.ts"() {
89256
89386
  "use strict";
@@ -89276,8 +89406,23 @@ var init_transitions = __esm({
89276
89406
  "IRIS",
89277
89407
  "ZOOM_THROUGH",
89278
89408
  "WHIP_LEFT",
89279
- "WHIP_RIGHT"
89409
+ "WHIP_RIGHT",
89410
+ "CUBE_FROM_LEFT",
89411
+ "CUBE_FROM_RIGHT",
89412
+ "CUBE_FROM_TOP",
89413
+ "CUBE_FROM_BOTTOM",
89414
+ "FLIP_HORIZONTAL",
89415
+ "FLIP_VERTICAL",
89416
+ "SWING_OPEN",
89417
+ "SWING_CLOSE",
89418
+ "STACK_IN",
89419
+ "STACK_OUT",
89420
+ "DEPTH_PUSH",
89421
+ "DEPTH_PULL",
89422
+ "CAROUSEL_FROM_LEFT",
89423
+ "CAROUSEL_FROM_RIGHT"
89280
89424
  ];
89425
+ TRANSITION_3D_TYPES = TRANSITION_TYPES.slice(TRANSITION_TYPES.indexOf("CUBE_FROM_LEFT"));
89281
89426
  PROTOTYPE_TRANSITION_TYPES = TRANSITION_TYPES.filter((t3) => t3 !== "CUT" && t3 !== "WHIP_LEFT" && t3 !== "WHIP_RIGHT");
89282
89427
  SCENE_TRANSITION_TYPES = TRANSITION_TYPES.filter((t3) => t3 !== "SMART_ANIMATE" && t3 !== "INSTANT");
89283
89428
  isCut = (type) => type === "INSTANT" || type === "CUT";
@@ -89293,16 +89438,52 @@ var init_transitions = __esm({
89293
89438
  CIRCLE_WIPE: "IRIS",
89294
89439
  IRIS: "CIRCLE_WIPE",
89295
89440
  WHIP_LEFT: "WHIP_RIGHT",
89296
- WHIP_RIGHT: "WHIP_LEFT"
89441
+ WHIP_RIGHT: "WHIP_LEFT",
89442
+ CUBE_FROM_LEFT: "CUBE_FROM_RIGHT",
89443
+ CUBE_FROM_RIGHT: "CUBE_FROM_LEFT",
89444
+ CUBE_FROM_TOP: "CUBE_FROM_BOTTOM",
89445
+ CUBE_FROM_BOTTOM: "CUBE_FROM_TOP",
89446
+ SWING_OPEN: "SWING_CLOSE",
89447
+ SWING_CLOSE: "SWING_OPEN",
89448
+ STACK_IN: "STACK_OUT",
89449
+ STACK_OUT: "STACK_IN",
89450
+ DEPTH_PUSH: "DEPTH_PULL",
89451
+ DEPTH_PULL: "DEPTH_PUSH",
89452
+ CAROUSEL_FROM_LEFT: "CAROUSEL_FROM_RIGHT",
89453
+ CAROUSEL_FROM_RIGHT: "CAROUSEL_FROM_LEFT"
89297
89454
  };
89298
89455
  reverseTransitionType = (type) => REVERSE[type] ?? type;
89456
+ THREE_D = new Set(TRANSITION_3D_TYPES);
89457
+ is3DTransition = (type) => THREE_D.has(type);
89458
+ FLAT = {
89459
+ CUBE_FROM_LEFT: "PUSH_FROM_LEFT",
89460
+ CUBE_FROM_RIGHT: "PUSH_FROM_RIGHT",
89461
+ CUBE_FROM_TOP: "PUSH_FROM_TOP",
89462
+ CUBE_FROM_BOTTOM: "PUSH_FROM_BOTTOM",
89463
+ CAROUSEL_FROM_LEFT: "PUSH_FROM_LEFT",
89464
+ CAROUSEL_FROM_RIGHT: "PUSH_FROM_RIGHT",
89465
+ STACK_IN: "SLIDE_FROM_BOTTOM",
89466
+ STACK_OUT: "MOVE_OUT_TO_BOTTOM",
89467
+ FLIP_HORIZONTAL: "DISSOLVE",
89468
+ FLIP_VERTICAL: "DISSOLVE",
89469
+ SWING_OPEN: "DISSOLVE",
89470
+ SWING_CLOSE: "DISSOLVE",
89471
+ DEPTH_PUSH: "DISSOLVE",
89472
+ DEPTH_PULL: "DISSOLVE"
89473
+ };
89474
+ flatTransitionType = (type) => FLAT[type] ?? type;
89475
+ AMBIENT_SHADE = 0.45;
89476
+ rad2 = (deg) => deg * Math.PI / 180;
89477
+ ramp = (x2, e0, e1) => Math.min(1, Math.max(0, (x2 - e0) / (e1 - e0)));
89478
+ 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 });
89479
+ 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
89480
  ZOOM_OUT_SCALE = 2.5;
89300
89481
  ZOOM_IN_SCALE = 0.85;
89301
89482
  WHIP_SMEAR = 0.22;
89302
89483
  whipSmear = (p2, width) => WHIP_SMEAR * width * 4 * p2 * (1 - p2);
89303
89484
  root = (side, matrix = side.base, opacity = 1) => ({ rootId: side.id, matrix, opacity });
89304
89485
  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);
89486
+ rootShows = (r) => (r.opacity > 0 || (r.face?.opacity ?? 0) > 0) && (!r.clip || r.clip.r > 0);
89306
89487
  }
89307
89488
  });
89308
89489
 
@@ -244381,11 +244562,11 @@ function buildStamp2(type) {
244381
244562
  const a = h2(i2, 1, 5) * Math.PI * 2;
244382
244563
  const rr = Math.pow(h2(i2, 2, 9), 0.7) * R * 0.92;
244383
244564
  const px5 = cx + Math.cos(a) * rr, py = cy + Math.sin(a) * rr;
244384
- const rad2 = 1 + h2(i2, 3, 13) * 5;
244565
+ const rad3 = 1 + h2(i2, 3, 13) * 5;
244385
244566
  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;
244567
+ for (let y = Math.max(0, Math.floor(py - rad3)); y <= Math.min(SIZE - 1, Math.ceil(py + rad3)); y++) {
244568
+ for (let x2 = Math.max(0, Math.floor(px5 - rad3)); x2 <= Math.min(SIZE - 1, Math.ceil(px5 + rad3)); x2++) {
244569
+ const d = Math.hypot(x2 + 0.5 - px5, y + 0.5 - py) / rad3;
244389
244570
  if (d >= 1) continue;
244390
244571
  const src = peak * (1 - d);
244391
244572
  const k2 = y * SIZE + x2;
@@ -246320,14 +246501,14 @@ function liveStaggerParent(nodes, ids2) {
246320
246501
  if (!parent || parent.type === "PAGE" || parent.motion?.stagger) return null;
246321
246502
  const set3 = new Set(ids2);
246322
246503
  if (set3.size !== parent.childIds.length || !parent.childIds.every((c2) => set3.has(c2))) return null;
246323
- const still = (id3) => {
246504
+ const still2 = (id3) => {
246324
246505
  const n = nodes[id3];
246325
246506
  if (!n) return true;
246326
246507
  const m = n.motion;
246327
246508
  if (m && (Object.keys(m.tracks).length || m.timeOffset || m.span || m.stagger)) return false;
246328
- return (n.childIds ?? []).every(still);
246509
+ return (n.childIds ?? []).every(still2);
246329
246510
  };
246330
- return ids2.every(still) ? parent.id : null;
246511
+ return ids2.every(still2) ? parent.id : null;
246331
246512
  }
246332
246513
  function staggerDocument(doc2, ids2, opts) {
246333
246514
  const present2 = ids2.filter((id3) => doc2.nodes[id3]);
@@ -247267,11 +247448,11 @@ function editSelected(nodes, sel, change2) {
247267
247448
  for (const [path, ids2] of byPath) {
247268
247449
  const track2 = motion?.tracks[path];
247269
247450
  if (!track2) continue;
247270
- const moved3 = [], still = [];
247451
+ const moved3 = [], still2 = [];
247271
247452
  let touched = false;
247272
247453
  for (const k2 of track2.keys) {
247273
247454
  if (!ids2.has(k2.id)) {
247274
- still.push(k2);
247455
+ still2.push(k2);
247275
247456
  continue;
247276
247457
  }
247277
247458
  const next2 = change2(k2, nodeId2, path);
@@ -247289,7 +247470,7 @@ function editSelected(nodes, sel, change2) {
247289
247470
  keys3.push(k2);
247290
247471
  }
247291
247472
  }
247292
- for (const k2 of still) if (!moved3.some((m) => Math.abs(m.t - k2.t) < 1)) keys3.push(k2);
247473
+ for (const k2 of still2) if (!moved3.some((m) => Math.abs(m.t - k2.t) < 1)) keys3.push(k2);
247293
247474
  keys3.sort((a, b) => a.t - b.t);
247294
247475
  motion = withTrack(motion, path, keys3.length || track2.modifiers?.length ? { ...track2, keys: keys3 } : null);
247295
247476
  changed = true;
@@ -247514,6 +247695,7 @@ function retuneShaderAudio(node2, fillId) {
247514
247695
  }
247515
247696
  var init_shader_audio = __esm({
247516
247697
  "lib/motion/shader-audio.ts"() {
247698
+ "use strict";
247517
247699
  init_shader_params();
247518
247700
  init_modifier_edit();
247519
247701
  init_keys();
@@ -248285,6 +248467,7 @@ function hrefOf(link2, nodes, routes) {
248285
248467
  var anchorOf, cleanAnchor, opensNewTab;
248286
248468
  var init_semantics = __esm({
248287
248469
  "lib/document/semantics.ts"() {
248470
+ "use strict";
248288
248471
  init_safe_url();
248289
248472
  anchorOf = (node2) => node2.semantics?.anchor || `pc-${node2.id.replace(/[^A-Za-z0-9_-]/g, "-")}`;
248290
248473
  cleanAnchor = (raw) => raw.trim().toLowerCase().replace(/^#/, "").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
@@ -248377,6 +248560,15 @@ function repeatRecords(doc2, repeat, under) {
248377
248560
  const from2 = Math.max(0, repeat.offset ?? 0);
248378
248561
  return list2.slice(from2, repeat.limit !== void 0 ? from2 + Math.max(0, repeat.limit) : void 0);
248379
248562
  }
248563
+ function shownRecordOf(nodes, doc2, id3) {
248564
+ for (let at3 = nodes[id3]?.parentId, hops = 0; at3 && hops < 64; at3 = nodes[at3]?.parentId, hops++) {
248565
+ const frame2 = nodes[at3];
248566
+ if (frame2?.repeat) return repeatRecords(doc2, frame2.repeat)[0] ?? null;
248567
+ const of = frame2?.route?.collectionId;
248568
+ if (of && doc2.collections?.[of]) return repeatRecords(doc2, { collectionId: of })[0] ?? null;
248569
+ }
248570
+ return null;
248571
+ }
248380
248572
  function recordSlugs(doc2, collectionId) {
248381
248573
  const c2 = doc2.collections?.[collectionId];
248382
248574
  const out = /* @__PURE__ */ new Map();
@@ -248489,9 +248681,10 @@ function removeRecords(doc2, ids2) {
248489
248681
  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
248682
  return { ...doc2, records, collections };
248491
248683
  }
248492
- var COLLECTION_LIMITS, slugify2, dataMemo, withData, ITEM_RECORD, MARK, itemMark, templateRecord, compare, TOKEN2, hasItemToken, layerId, copyRecord, coerce3, newId;
248684
+ var COLLECTION_LIMITS, slugify2, dataMemo, withData, ITEM_RECORD, MARK, itemMark, templateRecord, compare, TOKEN2, hasItemToken, layerId, copySuffix, copyRecord, coerce3, newId;
248493
248685
  var init_collections = __esm({
248494
248686
  "lib/document/collections.ts"() {
248687
+ "use strict";
248495
248688
  init_expressions2();
248496
248689
  init_variables();
248497
248690
  init_contract();
@@ -248518,6 +248711,10 @@ var init_collections = __esm({
248518
248711
  const at3 = id3.indexOf("~");
248519
248712
  return at3 < 0 ? id3 : id3.slice(0, at3);
248520
248713
  };
248714
+ copySuffix = (id3) => {
248715
+ const at3 = id3.indexOf("~");
248716
+ return at3 < 0 ? "" : id3.slice(at3);
248717
+ };
248521
248718
  copyRecord = (id3) => {
248522
248719
  const at3 = id3.lastIndexOf("~");
248523
248720
  return at3 < 0 ? null : id3.slice(at3 + 1);
@@ -259499,11 +259696,12 @@ function templateFromDocument(doc2, meta3, o = {}) {
259499
259696
  for (const v of variants) for (const id3 of v.rootIds) nodes[id3] = { ...nodes[id3], parentId: null };
259500
259697
  const deps = collectStyleDependencies(doc2, nodes);
259501
259698
  const payload = {
259699
+ // A record's picture (a project's cover in a CMS collection) is media the file uses, as a layer's is.
259502
259700
  mode: "document",
259503
259701
  nodes,
259504
259702
  variants,
259505
259703
  pages: pages2,
259506
- media: mediaHashes({ nodes, compositions: doc2.compositions }),
259704
+ media: mediaHashes({ nodes, compositions: doc2.compositions, records: doc2.records }),
259507
259705
  styles: { ...deps.styles, ...doc2.styles },
259508
259706
  variables: { ...deps.variables, ...doc2.variables },
259509
259707
  variableCollections: { ...deps.variableCollections, ...doc2.variableCollections },
@@ -296019,8 +296217,8 @@ async function syncTemplatePreview(row2, rootId, doc2) {
296019
296217
  const path = (file2, q) => `/api/templates/${encodeURIComponent(row2.id)}/preview/${file2}${q ? `?${new URLSearchParams(q)}` : ""}`;
296020
296218
  const put3 = (file2, bytes2, type, q) => api(path(file2, q), { method: "PUT", body: new Blob([bytes2], { type }) });
296021
296219
  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) }));
296220
+ const still2 = await renderTemplateDetail2(root2, doc2);
296221
+ if (still2) ({ preview } = await put3("still", still2.bytes, still2.type, { w: String(still2.width), h: String(still2.height) }));
296024
296222
  const loop = await renderTemplatePreview2(renderer, doc2, rootId);
296025
296223
  if (loop) ({ preview } = await put3("anim", loop.bytes, loop.type, { w: String(loop.width), h: String(loop.height), ms: String(loop.durationMs) }));
296026
296224
  else if (preview?.anim) {
@@ -296188,6 +296386,7 @@ async function createFreshFileOrExplain(place3 = {}, seed2 = {}) {
296188
296386
  var online, goesLocal;
296189
296387
  var init_new_file = __esm({
296190
296388
  "lib/client/cloud/new-file.ts"() {
296389
+ "use strict";
296191
296390
  init_scene_graph();
296192
296391
  init_print_pages();
296193
296392
  init_page_presets();
@@ -296942,13 +297141,18 @@ var init_review_kits = __esm({
296942
297141
 
296943
297142
  // lib/templates/text-measurer.ts
296944
297143
  function shownNode(doc2, n) {
296945
- return resolveNodeVariables(n, doc2.variables, doc2.variableCollections);
297144
+ const r = resolveNodeVariables(n, doc2.variables, doc2.variableCollections);
297145
+ const record2 = doc2.nodes && doc2.records ? shownRecordOf(doc2.nodes, doc2, n.id) : null;
297146
+ const collection = record2 && doc2.collections?.[record2.collectionId];
297147
+ return record2 && collection ? itemNode(r, n, collection, record2, itemScope(collection, record2, withData(variablesScope(doc2.variables, doc2.variableCollections), doc2))) : r;
296946
297148
  }
296947
297149
  var templateTextMeasurer;
296948
297150
  var init_text_measurer = __esm({
296949
297151
  "lib/templates/text-measurer.ts"() {
296950
297152
  "use strict";
296951
297153
  init_variables();
297154
+ init_collections();
297155
+ init_expressions2();
296952
297156
  init_measure();
296953
297157
  templateTextMeasurer = (node2) => {
296954
297158
  const characters = casedText(node2.characters ?? "", node2.textCase);
@@ -302309,6 +302513,9 @@ var init_export = __esm({
302309
302513
  // lib/ai/reference-images.ts
302310
302514
  var reference_images_exports = {};
302311
302515
  __export(reference_images_exports, {
302516
+ FIT_QUALITIES: () => FIT_QUALITIES,
302517
+ FIT_SCALES: () => FIT_SCALES,
302518
+ fitReference: () => fitReference,
302312
302519
  referenceGroups: () => referenceGroups,
302313
302520
  referenceScale: () => referenceScale,
302314
302521
  selectionReferenceImages: () => selectionReferenceImages,
@@ -302331,6 +302538,16 @@ function withinBudget(refs, opts = {}) {
302331
302538
  }
302332
302539
  return kept;
302333
302540
  }
302541
+ async function fitReference(encode3, budget) {
302542
+ for (const scale of FIT_SCALES) {
302543
+ for (const quality of scale === 1 ? FIT_QUALITIES : FIT_QUALITIES.slice(-1)) {
302544
+ const url4 = await encode3(scale, quality);
302545
+ if (url4 === null) return null;
302546
+ if (url4.length <= budget) return url4;
302547
+ }
302548
+ }
302549
+ return null;
302550
+ }
302334
302551
  function referenceGroups(ids2, max3 = AI_LIMITS.maxReferenceImages) {
302335
302552
  if (!ids2.length) return [];
302336
302553
  return ids2.length <= max3 ? ids2.map((id3) => [id3]) : [[...ids2]];
@@ -302349,22 +302566,30 @@ async function selectionReferenceImages(doc2, selection, opts = {}) {
302349
302566
  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
302567
  for (const bounds2 of regions) {
302351
302568
  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));
302569
+ const left = AI_LIMITS.maxReferenceTotalChars - out.reduce((n, u) => n + u.length, 0);
302570
+ const budget = Math.min(AI_LIMITS.maxReferenceImageChars, Math.floor(left / Math.max(1, Math.min(max3, regions.length * referenceGroups(selection, max3).length) - out.length)));
302571
+ const scale = referenceScale(bounds2, opts.maxEdge);
302572
+ const drawn = /* @__PURE__ */ new Map();
302573
+ const url4 = await fitReference(async (k2, quality) => {
302574
+ if (!drawn.has(k2)) drawn.set(k2, await renderer.exportRegion(members2, bounds2, scale * k2, doc2, doc2.styles, void 0, true));
302575
+ const image = drawn.get(k2);
302576
+ const blob = image ? await encodeImageData(image, opts.format ?? "PNG", quality) : null;
302577
+ return blob ? blobToDataUrl(blob) : null;
302578
+ }, budget);
302579
+ if (url4) out.push(url4);
302357
302580
  }
302358
302581
  }
302359
302582
  return withinBudget(out, { max: max3 });
302360
302583
  }
302361
- var blobToDataUrl;
302584
+ var FIT_QUALITIES, FIT_SCALES, blobToDataUrl;
302362
302585
  var init_reference_images = __esm({
302363
302586
  "lib/ai/reference-images.ts"() {
302364
302587
  init_export();
302365
302588
  init_selection_bounds();
302366
302589
  init_renderer_registry();
302367
302590
  init_limits();
302591
+ FIT_QUALITIES = [0.86, 0.7, 0.5];
302592
+ FIT_SCALES = [1, 0.75, 0.55, 0.4];
302368
302593
  blobToDataUrl = (blob) => new Promise((resolve6, reject) => {
302369
302594
  const reader = new FileReader();
302370
302595
  reader.onload = () => resolve6(String(reader.result));
@@ -303918,7 +304143,7 @@ function parseTransform(t3) {
303918
304143
  let x2;
303919
304144
  while (x2 = re.exec(t3)) {
303920
304145
  const v = nums(x2[2]);
303921
- const rad2 = (deg) => deg * Math.PI / 180;
304146
+ const rad3 = (deg) => deg * Math.PI / 180;
303922
304147
  let n = I;
303923
304148
  switch (x2[1].toLowerCase()) {
303924
304149
  case "matrix":
@@ -303931,16 +304156,16 @@ function parseTransform(t3) {
303931
304156
  n = [v[0] ?? 1, 0, 0, v[1] ?? v[0] ?? 1, 0, 0];
303932
304157
  break;
303933
304158
  case "rotate": {
303934
- const c2 = Math.cos(rad2(v[0] ?? 0)), s = Math.sin(rad2(v[0] ?? 0));
304159
+ const c2 = Math.cos(rad3(v[0] ?? 0)), s = Math.sin(rad3(v[0] ?? 0));
303935
304160
  n = [c2, s, -s, c2, 0, 0];
303936
304161
  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
304162
  break;
303938
304163
  }
303939
304164
  case "skewx":
303940
- n = [1, 0, Math.tan(rad2(v[0] ?? 0)), 1, 0, 0];
304165
+ n = [1, 0, Math.tan(rad3(v[0] ?? 0)), 1, 0, 0];
303941
304166
  break;
303942
304167
  case "skewy":
303943
- n = [1, Math.tan(rad2(v[0] ?? 0)), 0, 1, 0, 0];
304168
+ n = [1, Math.tan(rad3(v[0] ?? 0)), 0, 1, 0, 0];
303944
304169
  break;
303945
304170
  }
303946
304171
  m = mul2(m, n);
@@ -308659,7 +308884,8 @@ async function exportSlidesToPPTX(renderer, slides, docIn, styles) {
308659
308884
  function transitionXml(t3) {
308660
308885
  if (!t3 || t3.type === "INSTANT") return "";
308661
308886
  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/>";
308887
+ const type = flatTransitionType(t3.type);
308888
+ 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
308889
  return `<p:transition spd="${dur > 900 ? "slow" : dur > 400 ? "med" : "fast"}">${inner}</p:transition>`;
308664
308890
  }
308665
308891
  var EMU, emu, esc2, hex9, alphaTag, solid3, NS, REL, xfrm, needsPicture, xmlHead, relsXml, themeXml, masterXml, layoutXml, notesMasterXml, notesSlideXml;
@@ -308673,6 +308899,7 @@ var init_pptx = __esm({
308673
308899
  init_native_registry();
308674
308900
  init_png();
308675
308901
  init_export_fills();
308902
+ init_transitions();
308676
308903
  init_page_tokens();
308677
308904
  init_text_styles();
308678
308905
  init_effects();
@@ -308987,10 +309214,10 @@ function emitChannel(ch, grid, scalar = false, stats) {
308987
309214
  const eps = ch.eps ?? 1e-3;
308988
309215
  const fill = filled(ch.samples);
308989
309216
  if (!fill) return staticProp([0], scalar);
308990
- const still = constantOf({ ...ch, eps: ch.eps ?? 1e-4 });
308991
- if (still) {
309217
+ const still2 = constantOf({ ...ch, eps: ch.eps ?? 1e-4 });
309218
+ if (still2) {
308992
309219
  if (stats) stats.still++;
308993
- return staticProp(still, scalar);
309220
+ return staticProp(still2, scalar);
308994
309221
  }
308995
309222
  const present2 = ch.samples.map((s) => !!s);
308996
309223
  if (ch.exact && !ch.hold) {
@@ -310099,7 +310326,7 @@ var init_build = __esm({
310099
310326
  const nodeId2 = node0?.id;
310100
310327
  const geometry = [];
310101
310328
  if (rectLike) {
310102
- const rad2 = (n) => {
310329
+ const rad3 = (n) => {
310103
310330
  const cr = n?.cornerRadius;
310104
310331
  return Array.isArray(cr) ? num8(cr[0]) : num8(cr);
310105
310332
  };
@@ -310109,7 +310336,7 @@ var init_build = __esm({
310109
310336
  d: 1,
310110
310337
  p: this.prop(frames.map((p2, f2) => p2 ? [ownerNodes[f2].width / 2, ownerNodes[f2].height / 2] : void 0), null, false, 1e-3),
310111
310338
  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)
310339
+ r: this.prop(frames.map((p2, f2) => p2 ? [rad3(ownerNodes[f2])] : void 0), this.exact(nodeId2, [this.dim(nodeId2, "cornerRadius")]), true, 1e-3)
310113
310340
  });
310114
310341
  } else if (ellipse) {
310115
310342
  geometry.push({
@@ -311579,12 +311806,12 @@ function staticSiteFiles(site, scripts, opts = {}) {
311579
311806
  const lang = opts.lang ?? "en";
311580
311807
  const files = externalizeBitmaps(site);
311581
311808
  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) {
311809
+ const still2 = visitorCollections(site.program.document.collections).reduce((s, c2) => withVisitorRecords(s, c2.id, []), site);
311810
+ for (const page of still2.pages) {
311584
311811
  const path = page.notFound ? "404.html" : routeFile(page.route);
311585
311812
  if (taken.has(path)) continue;
311586
311813
  taken.add(path);
311587
- files.push({ path, content: pageHTML(still, page, lang, !!page.notFound) });
311814
+ files.push({ path, content: pageHTML(still2, page, lang, !!page.notFound) });
311588
311815
  }
311589
311816
  files.push({ path: "site.json", content: JSON.stringify(site) });
311590
311817
  files.push({ path: "pc/site.js", content: scripts.site });
@@ -312561,7 +312788,7 @@ var init_package = __esm({
312561
312788
  "packages/runtime/package.json"() {
312562
312789
  package_default = {
312563
312790
  name: "@popcraft/runtime",
312564
- version: "0.7.1",
312791
+ version: "0.8.0",
312565
312792
  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
312793
  license: "MIT",
312567
312794
  homepage: "https://popcraft.app/docs/exporting/nextjs",
@@ -313145,6 +313372,1251 @@ var init_next = __esm({
313145
313372
  }
313146
313373
  });
313147
313374
 
313375
+ // lib/document/routes.ts
313376
+ function screensOf(doc2, pageId2) {
313377
+ return (doc2.nodes[pageId2]?.childIds ?? []).map((id3) => doc2.nodes[id3]).filter((f2) => f2?.type === "FRAME" && f2.visible !== false && !f2.print?.isMaster);
313378
+ }
313379
+ function cleanPath(raw) {
313380
+ const parts = raw.trim().split("/").map(slug2).filter(Boolean);
313381
+ return `/${parts.join("/")}`;
313382
+ }
313383
+ function routesOf(screens) {
313384
+ const taken = /* @__PURE__ */ new Set();
313385
+ const own2 = /* @__PURE__ */ new Map();
313386
+ for (const s of screens) {
313387
+ const path = s.route?.path ? cleanPath(s.route.path) : null;
313388
+ if (path && !taken.has(path)) {
313389
+ taken.add(path);
313390
+ own2.set(s.id, path);
313391
+ }
313392
+ }
313393
+ const rest = screens.filter((s) => !own2.has(s.id) && !s.route?.notFound);
313394
+ const home = taken.has("/") ? void 0 : rest.find((s) => s.isFlowStartingPoint) ?? rest[0];
313395
+ if (home) taken.add("/");
313396
+ const out = /* @__PURE__ */ new Map();
313397
+ for (const s of screens) {
313398
+ if (own2.has(s.id)) {
313399
+ out.set(s.id, own2.get(s.id));
313400
+ continue;
313401
+ }
313402
+ if (s === home) {
313403
+ out.set(s.id, "/");
313404
+ continue;
313405
+ }
313406
+ const base = s.route?.notFound ? "/404" : `/${slug2(s.name) || "page"}`;
313407
+ let route2 = base;
313408
+ for (let n = 2; taken.has(route2); n++) route2 = `${base}-${n}`;
313409
+ taken.add(route2);
313410
+ out.set(s.id, route2);
313411
+ }
313412
+ return out;
313413
+ }
313414
+ var slug2;
313415
+ var init_routes = __esm({
313416
+ "lib/document/routes.ts"() {
313417
+ slug2 = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
313418
+ }
313419
+ });
313420
+
313421
+ // lib/island/slice.ts
313422
+ function sliceDocument(doc2, nodeId2, opts = {}) {
313423
+ const nodes = {};
313424
+ const take = (id3) => {
313425
+ const n = doc2.nodes[id3];
313426
+ if (!n || nodes[id3]) return;
313427
+ nodes[id3] = n;
313428
+ for (const c2 of n.childIds ?? []) take(c2);
313429
+ const main2 = n.mainComponentId;
313430
+ if (main2) {
313431
+ take(main2);
313432
+ const set3 = doc2.nodes[main2]?.parentId;
313433
+ if (set3 && doc2.nodes[set3]?.type === "COMPONENT_SET") take(set3);
313434
+ }
313435
+ };
313436
+ if (opts.self && doc2.nodes[nodeId2]) nodes[nodeId2] = { ...doc2.nodes[nodeId2], childIds: [] };
313437
+ else take(nodeId2);
313438
+ let frameId = null;
313439
+ let pageId2 = null;
313440
+ let rootId = nodeId2;
313441
+ for (let child = nodeId2, cur = doc2.nodes[nodeId2]?.parentId; cur; child = cur, cur = doc2.nodes[cur]?.parentId ?? null) {
313442
+ const p2 = doc2.nodes[cur];
313443
+ if (!p2) break;
313444
+ if (p2.type === "PAGE") {
313445
+ pageId2 = cur;
313446
+ frameId = doc2.nodes[child]?.type === "FRAME" ? child : frameId;
313447
+ }
313448
+ 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" };
313449
+ if (p2.type !== "PAGE") rootId = cur;
313450
+ }
313451
+ if (!frameId && doc2.nodes[nodeId2]?.type === "FRAME" && doc2.nodes[doc2.nodes[nodeId2].parentId ?? ""]?.type === "PAGE") frameId = nodeId2;
313452
+ return {
313453
+ nodeId: nodeId2,
313454
+ frameId,
313455
+ rootId,
313456
+ ...opts.self ? { fit: "fill" } : {},
313457
+ ...opts.screen ? { screen: true } : {},
313458
+ document: {
313459
+ id: doc2.id,
313460
+ name: doc2.name,
313461
+ pages: pageId2 ? [pageId2] : [],
313462
+ nodes,
313463
+ styles: doc2.styles,
313464
+ variables: doc2.variables,
313465
+ variableCollections: doc2.variableCollections,
313466
+ activeVariableModes: doc2.activeVariableModes,
313467
+ settings: doc2.settings,
313468
+ ...opts.screen ? { ...doc2.site ? { site: doc2.site } : {}, ...doc2.collections ? { collections: doc2.collections, records: doc2.records } : {} } : {}
313469
+ }
313470
+ };
313471
+ }
313472
+ var init_slice = __esm({
313473
+ "lib/island/slice.ts"() {
313474
+ "use strict";
313475
+ init_breakpoints();
313476
+ init_collections();
313477
+ init_expressions2();
313478
+ }
313479
+ });
313480
+
313481
+ // lib/runtime/dom/render.ts
313482
+ var HIDDEN_ATTR, HIDDEN_RULE, SCREEN_ISLAND;
313483
+ var init_render = __esm({
313484
+ "lib/runtime/dom/render.ts"() {
313485
+ "use strict";
313486
+ init_css();
313487
+ init_element();
313488
+ HIDDEN_ATTR = "data-pc-hidden";
313489
+ HIDDEN_RULE = `[${HIDDEN_ATTR}] { display: none !important; }`;
313490
+ SCREEN_ISLAND = "screen:";
313491
+ }
313492
+ });
313493
+
313494
+ // lib/code/props.ts
313495
+ function propName(key5) {
313496
+ const words = key5.split("#")[0].trim().split(/[^A-Za-z0-9]+/).filter(Boolean);
313497
+ const name2 = words.map((w, i2) => i2 === 0 ? w.charAt(0).toLowerCase() + w.slice(1) : w.charAt(0).toUpperCase() + w.slice(1)).join("");
313498
+ return /^[A-Za-z_$]/.test(name2) ? name2 : `p${name2}`;
313499
+ }
313500
+ function componentOf(nodes, node2) {
313501
+ const c2 = node2.type === "COMPONENT" ? node2 : node2.type === "INSTANCE" ? nodes[node2.mainComponentId] : void 0;
313502
+ return c2?.type === "COMPONENT" ? c2 : void 0;
313503
+ }
313504
+ function codeOf(nodes, node2) {
313505
+ if (node2.type !== "COMPONENT" && node2.type !== "INSTANCE") return null;
313506
+ return componentOf(nodes, node2)?.code ?? null;
313507
+ }
313508
+ function codeProps(nodes, node2) {
313509
+ const component = componentOf(nodes, node2);
313510
+ const out = {};
313511
+ if (!component) return out;
313512
+ const set3 = component.parentId ? nodes[component.parentId] : void 0;
313513
+ const defs = (set3?.type === "COMPONENT_SET" ? set3.componentPropertyDefinitions : component.componentPropertyDefinitions) ?? {};
313514
+ const given = node2.type === "INSTANCE" ? node2.componentProperties ?? {} : {};
313515
+ for (const key5 of Object.keys(defs).sort()) {
313516
+ const v = value(key5 in given ? given[key5] : defs[key5].defaultValue);
313517
+ if (v !== void 0) out[propName(key5)] = v;
313518
+ }
313519
+ out.width = Math.round(node2.width);
313520
+ out.height = Math.round(node2.height);
313521
+ return out;
313522
+ }
313523
+ var value;
313524
+ var init_props = __esm({
313525
+ "lib/code/props.ts"() {
313526
+ "use strict";
313527
+ init_color();
313528
+ value = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" ? v : v && typeof v === "object" && "r" in v ? colorToHex8(v) : void 0;
313529
+ }
313530
+ });
313531
+
313532
+ // lib/document/controls.ts
313533
+ function fieldPart(nodes, id3) {
313534
+ const n = nodes[id3];
313535
+ if (!n) return null;
313536
+ if (n.type === "TEXT") return id3;
313537
+ for (const c2 of n.childIds ?? []) {
313538
+ const hit = fieldPart(nodes, c2);
313539
+ if (hit) return hit;
313540
+ }
313541
+ return null;
313542
+ }
313543
+ var cleanName2;
313544
+ var init_controls = __esm({
313545
+ "lib/document/controls.ts"() {
313546
+ cleanName2 = (raw) => raw.trim().replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
313547
+ }
313548
+ });
313549
+
313550
+ // lib/io/web/expressible.ts
313551
+ function expressibility(node2, styles) {
313552
+ const c2 = capability(node2, "css", styles);
313553
+ return { css: c2.reason === "", reason: c2.reason, needsRaster: c2.verdict === "raster" };
313554
+ }
313555
+ var init_expressible = __esm({
313556
+ "lib/io/web/expressible.ts"() {
313557
+ "use strict";
313558
+ init_capability();
313559
+ }
313560
+ });
313561
+
313562
+ // lib/io/web/responsive.ts
313563
+ function containerStyle(f2) {
313564
+ const out = {};
313565
+ if (isStack(f2) && f2.layoutWrap === "WRAP") {
313566
+ out["flex-wrap"] = "wrap";
313567
+ const cross2 = f2.counterAxisSpacing ?? f2.itemSpacing ?? 0;
313568
+ const main2 = f2.itemSpacing ?? 0;
313569
+ if (cross2 !== main2) out.gap = f2.layoutMode === "HORIZONTAL" ? `${cross2}px ${main2}px` : `${main2}px ${cross2}px`;
313570
+ out["align-content"] = "flex-start";
313571
+ }
313572
+ if (isGrid(f2)) {
313573
+ out.display = "grid";
313574
+ const cols = f2.layoutGridColumns ?? "AUTO";
313575
+ 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(" ");
313576
+ const rows = f2.layoutGridRows ?? "AUTO";
313577
+ if (rows === "AUTO") out["grid-auto-rows"] = `minmax(${f2.layoutGridMinRowHeight ?? 100}px, auto)`;
313578
+ else out["grid-template-rows"] = Array.from({ length: Math.max(1, rows) }, (_, i2) => track(f2.layoutGridRowSizes?.[i2])).join(" ");
313579
+ const colGap = f2.itemSpacing ?? 0, rowGap = f2.counterAxisSpacing ?? colGap;
313580
+ out.gap = rowGap === colGap ? `${colGap}px` : `${rowGap}px ${colGap}px`;
313581
+ if (f2.padding) {
313582
+ out.padding = `${f2.padding.top}px ${f2.padding.right}px ${f2.padding.bottom}px ${f2.padding.left}px`;
313583
+ if (f2.padding.top || f2.padding.right || f2.padding.bottom || f2.padding.left) out["box-sizing"] = "border-box";
313584
+ }
313585
+ }
313586
+ const scroll = f2.overflowScrolling;
313587
+ if (scroll && scroll !== "NONE") {
313588
+ out["overflow-x"] = scroll === "HORIZONTAL" || scroll === "BOTH" ? "auto" : "hidden";
313589
+ out["overflow-y"] = scroll === "VERTICAL" || scroll === "BOTH" ? "auto" : "hidden";
313590
+ }
313591
+ return out;
313592
+ }
313593
+ function flowChild(node2, parent) {
313594
+ const style = { ...limits(node2) };
313595
+ const h = node2.layoutSizingHorizontal ?? "FIXED", v = node2.layoutSizingVertical ?? "FIXED";
313596
+ if (isGrid(parent)) {
313597
+ if (h !== "FIXED") style.width = h === "FILL" ? null : "fit-content";
313598
+ if (v !== "FIXED") style.height = null;
313599
+ return { style };
313600
+ }
313601
+ if (h === "FIXED" && style["max-width"] === void 0) style["max-width"] = "100%";
313602
+ const row2 = parent.layoutMode === "HORIZONTAL";
313603
+ const main2 = row2 ? h : v, cross2 = row2 ? v : h;
313604
+ const mainProp = row2 ? "width" : "height", crossProp = row2 ? "height" : "width";
313605
+ if (main2 === "FILL") {
313606
+ style[mainProp] = null;
313607
+ style.flex = "1 1 0";
313608
+ if (style[`min-${mainProp}`] === void 0) style[`min-${mainProp}`] = "0";
313609
+ } else {
313610
+ if (main2 === "HUG") style[mainProp] = null;
313611
+ style["flex-shrink"] = "0";
313612
+ }
313613
+ if (cross2 === "FILL") {
313614
+ style[crossProp] = null;
313615
+ style["align-self"] = "stretch";
313616
+ } else {
313617
+ if (cross2 === "HUG") style[crossProp] = null;
313618
+ if ((parent.counterAxisAlignItems ?? "MIN") === "MIN") style["align-self"] = "flex-start";
313619
+ }
313620
+ return { style };
313621
+ }
313622
+ function constrained(kind, pos, size6, parentSize, start2, end, sizeProp) {
313623
+ const far = parentSize - pos - size6;
313624
+ switch (kind) {
313625
+ case "MAX":
313626
+ return { place: { [end]: px4(far) }, style: {} };
313627
+ case "STRETCH":
313628
+ return { place: { [start2]: px4(pos), [end]: px4(far) }, style: { [sizeProp]: null } };
313629
+ // Its centre keeps its distance from the parent's centre.
313630
+ case "CENTER":
313631
+ return { place: { [start2]: `calc(50% + ${px4(pos - parentSize / 2)})` }, style: {} };
313632
+ case "SCALE":
313633
+ return parentSize > 0 ? { place: { [start2]: pct2(pos / parentSize) }, style: { [sizeProp]: pct2(size6 / parentSize) } } : { place: { [start2]: px4(pos) }, style: {} };
313634
+ default:
313635
+ return { place: { [start2]: px4(pos) }, style: {} };
313636
+ }
313637
+ }
313638
+ function placedChild(node2, parent, frame2 = parent) {
313639
+ const c2 = node2.constraints ?? { horizontal: "MIN", vertical: "MIN" };
313640
+ const x2 = constrained(c2.horizontal, node2.x, node2.width, frame2.width, "left", "right", "width");
313641
+ const y = constrained(c2.vertical, node2.y, node2.height, frame2.height, "top", "bottom", "height");
313642
+ return { style: { ...limits(node2), ...x2.style, ...y.style }, place: { position: "absolute", ...x2.place, ...y.place } };
313643
+ }
313644
+ function siteLayout(node2, parent, layout2) {
313645
+ const own2 = node2.type === "FRAME" || node2.type === "COMPONENT" || node2.type === "INSTANCE" ? node2 : null;
313646
+ if (!parent) {
313647
+ const grows = !own2 || laysOut(own2) || own2.overflowScrolling === "NONE" || !own2.overflowScrolling;
313648
+ return { style: { ...limits(node2), width: "100%", ...grows ? { height: null, "min-height": `max(${px4(node2.height)}, 100dvh)` } : {} }, place: { position: "relative" } };
313649
+ }
313650
+ const s = node2;
313651
+ return layout2 && laysOut(layout2) && s.layoutPositioning !== "ABSOLUTE" ? flowChild(s, layout2) : placedChild(s, parent, parent.type === "INSTANCE" && layout2 ? layout2 : parent);
313652
+ }
313653
+ var px4, pct2, isStack, isGrid, laysOut, track, limits;
313654
+ var init_responsive = __esm({
313655
+ "lib/io/web/responsive.ts"() {
313656
+ "use strict";
313657
+ px4 = (v) => `${Math.round(v * 100) / 100}px`;
313658
+ pct2 = (v) => `${Math.round(v * 1e4) / 100}%`;
313659
+ isStack = (f2) => f2?.layoutMode === "HORIZONTAL" || f2?.layoutMode === "VERTICAL";
313660
+ isGrid = (f2) => f2?.layoutMode === "GRID";
313661
+ laysOut = (f2) => isStack(f2) || isGrid(f2);
313662
+ track = (t3) => {
313663
+ if (!t3 || t3.sizing === "FILL") return t3?.value && /fr$/.test(t3.value) ? t3.value : "1fr";
313664
+ if (t3.sizing === "HUG") return "auto";
313665
+ return /^[\d.]+$/.test(t3.value) ? `${t3.value}px` : t3.value;
313666
+ };
313667
+ limits = (n) => {
313668
+ const out = {};
313669
+ if (n.minWidth !== void 0) out["min-width"] = px4(n.minWidth);
313670
+ if (n.maxWidth !== void 0) out["max-width"] = px4(n.maxWidth);
313671
+ if (n.minHeight !== void 0) out["min-height"] = px4(n.minHeight);
313672
+ if (n.maxHeight !== void 0) out["max-height"] = px4(n.maxHeight);
313673
+ return out;
313674
+ };
313675
+ }
313676
+ });
313677
+
313678
+ // lib/io/web/richtext.ts
313679
+ function runStyle(seg) {
313680
+ const out = {};
313681
+ if (seg.fontFamily) out["font-family"] = `"${seg.fontFamily}", system-ui, sans-serif`;
313682
+ if (seg.fontSize) out["font-size"] = `${seg.fontSize}px`;
313683
+ if (seg.fontWeight) out["font-weight"] = String(seg.fontWeight);
313684
+ if (seg.fontStyle) out["font-style"] = seg.fontStyle;
313685
+ if (seg.lineHeight !== void 0 && seg.lineHeight !== "AUTO") out["line-height"] = `${seg.lineHeight}px`;
313686
+ if (seg.textDecoration === "UNDERLINE") out["text-decoration"] = "underline";
313687
+ else if (seg.textDecoration === "STRIKETHROUGH") out["text-decoration"] = "line-through";
313688
+ else if (seg.textDecoration === "NONE") out["text-decoration"] = "none";
313689
+ if (seg.textCase === "UPPER") out["text-transform"] = "uppercase";
313690
+ else if (seg.textCase === "LOWER") out["text-transform"] = "lowercase";
313691
+ else if (seg.textCase === "TITLE") out["text-transform"] = "capitalize";
313692
+ else if (seg.textCase === "ORIGINAL") out["text-transform"] = "none";
313693
+ const solid4 = seg.fills?.find((f2) => f2.visible !== false && f2.type === "SOLID" && f2.color);
313694
+ if (solid4?.color) out.color = toHex(solid4.color);
313695
+ return out;
313696
+ }
313697
+ function textRuns(t3) {
313698
+ const text = t3.characters ?? "";
313699
+ const segs = [...t3.styledSegments ?? []].filter((s) => s.end > s.start).sort((a, b) => a.start - b.start);
313700
+ if (!segs.length && !t3.link) return void 0;
313701
+ const runs = [];
313702
+ const push2 = (from2, to, seg) => {
313703
+ if (to <= from2) return;
313704
+ const link2 = seg?.link ?? t3.link;
313705
+ runs.push({ text: text.slice(from2, to), style: seg ? runStyle(seg) : {}, ...link2 ? { link: link2 } : {} });
313706
+ };
313707
+ let at3 = 0;
313708
+ for (const s of segs) {
313709
+ const start2 = Math.max(at3, Math.min(text.length, s.start)), end = Math.min(text.length, s.end);
313710
+ push2(at3, start2);
313711
+ push2(start2, end, s);
313712
+ at3 = Math.max(at3, end);
313713
+ }
313714
+ push2(at3, text.length);
313715
+ return runs;
313716
+ }
313717
+ var init_richtext = __esm({
313718
+ "lib/io/web/richtext.ts"() {
313719
+ "use strict";
313720
+ init_paint2();
313721
+ }
313722
+ });
313723
+
313724
+ // lib/io/web/timeline.ts
313725
+ function frameWebMotion(doc2, frameId, style) {
313726
+ const nodes = doc2.nodes;
313727
+ const frame2 = nodes[frameId];
313728
+ if (!frame2 || !hasFrameMotion(nodes, frameId)) return null;
313729
+ const len3 = timelineDuration(nodes, frameId);
313730
+ if (!(len3 > 0)) return null;
313731
+ const steps = Math.max(1, Math.ceil(len3 / 1e3 * SAMPLE_RATE));
313732
+ const times2 = [];
313733
+ const poses = [];
313734
+ for (let i2 = 0; i2 <= steps; i2++) {
313735
+ const t3 = len3 * i2 / steps;
313736
+ times2.push(t3);
313737
+ poses.push(evaluatePose(nodes, { kind: "frame", frameId }, t3).nodes);
313738
+ }
313739
+ const ids2 = /* @__PURE__ */ new Set();
313740
+ for (const p2 of poses) for (const id3 in p2) if (id3 !== frameId && p2[id3] !== nodes[id3]) ids2.add(id3);
313741
+ const loops = frameRunsOn(nodes, frameId);
313742
+ const out = /* @__PURE__ */ new Map();
313743
+ const tag = frameId.replace(/[^a-zA-Z0-9]/g, "").slice(-6);
313744
+ let n = 0;
313745
+ for (const id3 of ids2) {
313746
+ const rest = id3.includes("::") ? resolveVirtualNode2(nodes, id3) : nodes[id3];
313747
+ if (!rest || !underFrame(nodes, id3, frameId)) continue;
313748
+ const frames = keyframesOf(times2, poses.map((p2) => declarationsOf(p2[id3] ?? rest, rest, style)), len3);
313749
+ if (!frames) continue;
313750
+ out.set(id3, {
313751
+ name: `timeline-${tag}-${n++}`,
313752
+ frames,
313753
+ durationMs: Math.round(len3),
313754
+ delayMs: 0,
313755
+ iterations: loops ? "infinite" : 1,
313756
+ direction: "normal",
313757
+ fill: "both"
313758
+ });
313759
+ }
313760
+ return out.size ? out : null;
313761
+ }
313762
+ function underFrame(nodes, id3, frameId) {
313763
+ const real = id3.split("::")[0];
313764
+ for (let n = nodes[real]; n; n = n.parentId ? nodes[n.parentId] : void 0) if (n.id === frameId) return true;
313765
+ return false;
313766
+ }
313767
+ var init_timeline = __esm({
313768
+ "lib/io/web/timeline.ts"() {
313769
+ "use strict";
313770
+ init_scene_graph();
313771
+ init_pose();
313772
+ init_instances2();
313773
+ init_keyframes();
313774
+ }
313775
+ });
313776
+
313777
+ // lib/io/web/tree.ts
313778
+ function anchorTargets(doc2) {
313779
+ const hit = anchorMemo.get(doc2.nodes);
313780
+ if (hit) return hit;
313781
+ const out = /* @__PURE__ */ new Set();
313782
+ for (const id3 in doc2.nodes) {
313783
+ const n = doc2.nodes[id3];
313784
+ if (n.semantics?.link?.kind === "anchor") out.add(n.semantics.link.nodeId);
313785
+ for (const ix of n.interactions ?? []) if (ix.action.link?.kind === "anchor" && ix.action.link.nodeId) out.add(ix.action.link.nodeId);
313786
+ }
313787
+ anchorMemo.set(doc2.nodes, out);
313788
+ return out;
313789
+ }
313790
+ function prepared(node2, doc2) {
313791
+ let n = node2;
313792
+ if (n.id.includes("::")) n = withInstanceBox(n, doc2.nodes);
313793
+ n = resolveNodeVariables(n, doc2.variables, doc2.variableCollections, doc2.activeVariableModes, exprData(doc2));
313794
+ n = resolveTextNodeStyles(n, doc2.styles ?? {});
313795
+ return n;
313796
+ }
313797
+ function layoutOf2(node2, nodes) {
313798
+ if (!node2) return null;
313799
+ if (node2.type === "INSTANCE") {
313800
+ const mainId = node2.mainComponentId;
313801
+ const main2 = mainId ? nodes[mainId] : void 0;
313802
+ return main2 ?? null;
313803
+ }
313804
+ if (node2.id.includes("::")) {
313805
+ const real = nodes[node2.id.split("::").pop()];
313806
+ return real ?? node2;
313807
+ }
313808
+ return node2;
313809
+ }
313810
+ function buildPlainTree(doc2, nodeId2, opts = {}, start2, hooks = {}) {
313811
+ const cap2 = opts.nodeCap ?? DEFAULT_NODE_CAP;
313812
+ const first2 = doc2.nodes[nodeId2] ?? (nodeId2.includes("::") ? childLookup(doc2, nodeId2) : void 0);
313813
+ if (!first2) throw new Error(`No node ${nodeId2}`);
313814
+ let emitted = 0;
313815
+ let truncated = false;
313816
+ let folds = 0;
313817
+ const tokens = opts.target === "site" && Object.keys(doc2.variables ?? {}).length ? siteTokens(doc2) : null;
313818
+ const anchored = anchorTargets(doc2);
313819
+ const pageItem = () => {
313820
+ const c2 = opts.item && doc2.collections?.[opts.item.collectionId];
313821
+ const r = opts.item && doc2.records?.[opts.item.recordId];
313822
+ return c2 && r ? { collection: c2, record: r, suffix: "" } : null;
313823
+ };
313824
+ let item = pageItem();
313825
+ const scopeOf2 = (it) => itemScope(it.collection, it.record, withData(variablesScope(doc2.variables, doc2.variableCollections, doc2.activeVariableModes), doc2));
313826
+ const itemised = (node2, raw, it) => itemNode(node2, raw, it.collection, it.record, scopeOf2(it));
313827
+ const itemLink = (link2, it) => {
313828
+ 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;
313829
+ if (filled2.kind === "screen") {
313830
+ const dest = doc2.nodes[filled2.frameId];
313831
+ const base = opts.routes?.[filled2.frameId];
313832
+ const of = dest?.route?.collectionId;
313833
+ if (of && base !== void 0) {
313834
+ const slugs = recordSlugs(doc2, of);
313835
+ const rec = it?.collection.id === of ? it.record.id : slugs.keys().next().value;
313836
+ const slug3 = rec ? slugs.get(rec) : void 0;
313837
+ return slug3 ? { link: filled2, href: `${base === "/" ? "" : base}/${slug3}`, screen: `${filled2.frameId}~${rec}` } : { link: filled2, href: null };
313838
+ }
313839
+ return { link: filled2, href: base ?? null, screen: filled2.frameId };
313840
+ }
313841
+ return { link: filled2, href: hrefOf(filled2, doc2.nodes, opts.routes) };
313842
+ };
313843
+ const fields = /* @__PURE__ */ new Map();
313844
+ const styleOpts = { fullImageUrl: opts.fullImageUrls ?? opts.target === "site" };
313845
+ const stylesOf = (n) => styleMapFor(n, doc2.styles, styleOpts);
313846
+ let motion = null;
313847
+ const timeline = !opts.static && !start2 && first2.type === "FRAME" ? frameWebMotion(doc2, first2.id, (n) => stylesOf(prepared(n, doc2))) : null;
313848
+ const build3 = (raw, parent, in3D2, fold) => {
313849
+ if (emitted >= cap2) {
313850
+ truncated = true;
313851
+ return null;
313852
+ }
313853
+ emitted++;
313854
+ const node2 = item ? itemised(prepared(raw, doc2), raw, item) : prepared(raw, doc2);
313855
+ const waits = node2.visible === false && parent !== null;
313856
+ if (waits && !(opts.target === "site" && followsVisibility(raw))) return null;
313857
+ const exp = expressibility(node2, doc2.styles);
313858
+ const f2 = layoutOf2(node2, doc2.nodes) ?? node2;
313859
+ const style = stylesOf(node2);
313860
+ if (f2 !== node2 && !style.display) Object.assign(style, flexDeclarations(f2));
313861
+ const through = in3D2 && passesThrough(raw, doc2.nodes);
313862
+ const own2 = typeof node2.opacity === "number" ? node2.opacity : 1;
313863
+ if (through) {
313864
+ style["transform-style"] = "preserve-3d";
313865
+ delete style.opacity;
313866
+ style[foldVar(fold + 1)] = fold ? `calc(var(${foldVar(fold)}) * ${round3(own2)})` : String(round3(own2));
313867
+ folds = Math.max(folds, fold + 1);
313868
+ } else if (fold) style.opacity = own2 === 1 ? `var(${foldVar(fold)})` : `calc(var(${foldVar(fold)}) * ${round3(own2)})`;
313869
+ if (own2 === 0) style["pointer-events"] = "none";
313870
+ if (clickable(raw) && !style.cursor) style.cursor = "pointer";
313871
+ const web = {
313872
+ id: item?.suffix ? `${node2.id}${item.suffix}` : node2.id,
313873
+ name: node2.name || node2.type,
313874
+ type: node2.type,
313875
+ x: Math.round(node2.x),
313876
+ y: Math.round(node2.y),
313877
+ width: Math.round(node2.width),
313878
+ height: Math.round(node2.height),
313879
+ // Absolutely-positioned auto-layout children are taken out of the flow, exactly as the canvas does.
313880
+ // A grid's children are in its flow too: its tracks place them.
313881
+ positioning: (isFlex(layoutOf2(parent, doc2.nodes)) || layoutOf2(parent, doc2.nodes)?.layoutMode === "GRID") && node2.layoutPositioning !== "ABSOLUTE" ? "flow" : "absolute",
313882
+ style,
313883
+ children: []
313884
+ };
313885
+ if (tokens) Object.assign(style, tokenStyle(raw, style, tokens));
313886
+ if (opts.target === "site") {
313887
+ const lay = siteLayout(node2, parent, layoutOf2(parent, doc2.nodes));
313888
+ for (const [k2, v] of Object.entries(lay.style)) {
313889
+ if (v === null) delete style[k2];
313890
+ else style[k2] = v;
313891
+ }
313892
+ if (laysOut(f2) || f2.overflowScrolling) Object.assign(style, containerStyle(f2));
313893
+ if (node2.type === "TEXT") {
313894
+ if (style["white-space"] === "pre") {
313895
+ style["white-space"] = "pre-wrap";
313896
+ style.width = "fit-content";
313897
+ }
313898
+ if (style["max-width"] === void 0) style["max-width"] = "100%";
313899
+ if (style.height && style.height !== "auto") {
313900
+ style["min-height"] = style.height;
313901
+ delete style.height;
313902
+ }
313903
+ }
313904
+ if (lay.place && (parent !== null || !start2?.parent)) web.place = lay.place;
313905
+ }
313906
+ if (waits) web.hidden = true;
313907
+ const sem = node2.semantics;
313908
+ if (sem) {
313909
+ if (sem.tag && sem.tag !== "div") web.tag = sem.tag;
313910
+ const attrs = {};
313911
+ if (sem.label) attrs["aria-label"] = sem.label;
313912
+ if (sem.hidden) attrs["aria-hidden"] = "true";
313913
+ if (Object.keys(attrs).length) web.attrs = attrs;
313914
+ const to = sem.link ? itemLink(sem.link, item) : null;
313915
+ if (to?.href) web.link = { href: to.href, ...opensNewTab(to.link) ? { newTab: true } : {}, ...to.screen ? { screen: to.screen } : {} };
313916
+ }
313917
+ const control = node2.control;
313918
+ if (control) {
313919
+ const named = control.name ? { name: control.name } : {};
313920
+ if (control.kind === "FORM") web.tag = "form";
313921
+ else if (control.kind === "BUTTON") {
313922
+ web.tag = "button";
313923
+ 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 } : {} };
313924
+ } else if (control.kind === "CHECKBOX" || control.kind === "RADIO") {
313925
+ 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 } : {} };
313926
+ } else fields.set(fieldPart(doc2.nodes, raw.id) ?? raw.id, control);
313927
+ }
313928
+ const control0 = fields.get(raw.id);
313929
+ const field = control0 && item && control0.value !== void 0 && hasItemToken(control0.value) ? { ...control0, value: itemText(control0.value, item.collection, item.record) } : control0;
313930
+ if (field) {
313931
+ const tag = field.kind === "TEXTAREA" ? "textarea" : field.kind === "SELECT" ? "select" : "input";
313932
+ const words = node2.characters;
313933
+ web.input = {
313934
+ tag,
313935
+ attrs: {
313936
+ ...tag === "input" ? { type: field.inputType ?? "text" } : {},
313937
+ ...field.name ? { name: field.name } : {},
313938
+ ...tag !== "select" && (field.placeholder ?? words) ? { placeholder: field.placeholder ?? words } : {},
313939
+ ...field.required ? { required: "" } : {},
313940
+ ...tag === "input" && field.value !== void 0 ? { value: field.value } : {},
313941
+ "aria-label": node2.semantics?.label ?? field.placeholder ?? field.name ?? web.name
313942
+ },
313943
+ ...tag === "select" ? { options: field.options ?? [] } : {},
313944
+ ...tag !== "input" && field.value !== void 0 ? { value: field.value } : {},
313945
+ ...field.variableId ? { variable: field.variableId } : {}
313946
+ };
313947
+ }
313948
+ if (sem?.anchor || anchored.has(node2.id)) web.attrs = { ...web.attrs, id: anchorOf(node2) };
313949
+ if (through) web.preserve3d = true;
313950
+ web.tf = transformParts(node2);
313951
+ if (typeof node2.altText === "string") web.alt = node2.altText;
313952
+ if (parent === null) web.positioning = start2?.parent ? web.positioning : "flow";
313953
+ if (f2.layoutMode === "HORIZONTAL" || f2.layoutMode === "VERTICAL") {
313954
+ web.layout = {
313955
+ direction: f2.layoutMode === "HORIZONTAL" ? "row" : "column",
313956
+ gap: f2.itemSpacing ?? 0,
313957
+ justify: JUSTIFY[f2.primaryAxisAlignItems ?? "MIN"],
313958
+ align: ALIGN2[f2.counterAxisAlignItems ?? "MIN"],
313959
+ padding: f2.padding ?? { top: 0, right: 0, bottom: 0, left: 0 }
313960
+ };
313961
+ }
313962
+ if (node2.type === "TEXT") {
313963
+ const t3 = node2;
313964
+ const solid4 = (t3.fills ?? []).find((p2) => p2.visible !== false && p2.type === "SOLID" && p2.color);
313965
+ web.text = {
313966
+ characters: t3.characters ?? "",
313967
+ align: t3.textAlign,
313968
+ fontFamily: t3.fontFamily,
313969
+ fontSize: t3.fontSize,
313970
+ fontWeight: t3.fontWeight,
313971
+ italic: t3.fontStyle === "italic",
313972
+ ...solid4?.color ? { color: toHex(solid4.color) } : {},
313973
+ ...t3.letterSpacing ? { letterSpacing: t3.letterSpacing } : {},
313974
+ ...t3.lineHeight !== "AUTO" ? { lineHeight: t3.lineHeight } : {}
313975
+ };
313976
+ const runs = textRuns(t3);
313977
+ if (runs) web.runs = runs;
313978
+ }
313979
+ const tl = timeline?.get(node2.id);
313980
+ const mo = tl ?? motion?.children.get(node2.id);
313981
+ if (mo) web.motion = { style: animationStyle(mo, tl ? "load" : motion.trigger), keyframes: keyframesCSS(mo) };
313982
+ const ext = getNativeExtension(raw.type);
313983
+ if (ext?.toWeb) {
313984
+ const said = ext.toWeb(node2, { escape: escapeHTML, color: (c2) => toRgba({ ...c2, a: c2.a ?? 1 }) });
313985
+ if (said.tag) web.tag = said.tag;
313986
+ Object.assign(style, said.style);
313987
+ web.html = said.html;
313988
+ hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
313989
+ return web;
313990
+ }
313991
+ const code = opts.target === "site" ? codeOf(doc2.nodes, raw) : null;
313992
+ if (code && doc2.codeModules?.[code.moduleId]) {
313993
+ for (const k2 of PAINTED) delete style[k2];
313994
+ web.code = { module: code.moduleId, ...code.exportName ? { export: code.exportName } : {}, props: codeProps(doc2.nodes, node2) };
313995
+ hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
313996
+ return web;
313997
+ }
313998
+ if (!exp.css) {
313999
+ for (const k2 of PAINTED) delete style[k2];
314000
+ web.asset = { kind: opts.assetKind ?? (exp.needsRaster ? "png" : "svg"), reason: exp.reason, ...item?.suffix ? { of: node2.id } : {} };
314001
+ if (opts.target === "site" && renderMode(node2, { styles: doc2.styles, live: isLive(doc2.nodes, raw.id) }) === "island") web.island = true;
314002
+ hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
314003
+ return web;
314004
+ }
314005
+ const lost = capability(node2, "css", doc2.styles).dropped.find((f3) => f3.startsWith("paint:"));
314006
+ if (lost && !node2.id.includes("::")) {
314007
+ const site = opts.target === "site";
314008
+ style.isolation = "isolate";
314009
+ web.children.push({
314010
+ id: `${node2.id}/backdrop${item?.suffix ?? ""}`,
314011
+ name: `${web.name} fill`,
314012
+ type: "BACKDROP",
314013
+ x: 0,
314014
+ y: 0,
314015
+ width: web.width,
314016
+ height: web.height,
314017
+ positioning: "absolute",
314018
+ ...site ? { place: { position: "absolute", inset: "0" } } : {},
314019
+ style: { ...site ? {} : { width: `${web.width}px`, height: `${web.height}px` }, "border-radius": "inherit", overflow: "hidden", "z-index": "-1", "pointer-events": "none" },
314020
+ alt: "",
314021
+ asset: { kind: "png", reason: featureName(lost), of: node2.id, self: true },
314022
+ ...site && movesItself(raw) ? { island: true } : {},
314023
+ children: []
314024
+ });
314025
+ }
314026
+ const outer = motion;
314027
+ if (!motion && node2.type === "INSTANCE" && !opts.static) {
314028
+ motion = instanceWebMotion(doc2, node2, (n) => stylesOf(prepared(n, doc2)));
314029
+ if (motion && (motion.trigger !== "load" || opts.target === "site")) web.motionTrigger = motion.trigger;
314030
+ }
314031
+ try {
314032
+ if (opts.includeChildren !== false) {
314033
+ const kids3D = in3D2 ? through : is3DContext(raw) && !raw.id.includes("::");
314034
+ const kidFold = through ? fold + 1 : 0;
314035
+ const repeat = raw.repeat;
314036
+ const collection = repeat && doc2.collections?.[repeat.collectionId];
314037
+ if (repeat && collection && opts.target === "site") {
314038
+ const outerItem = item;
314039
+ const under = outerItem ? scopeOf2(outerItem) : withData(variablesScope(doc2.variables, doc2.variableCollections, doc2.activeVariableModes), doc2);
314040
+ try {
314041
+ for (const record2 of repeatRecords(doc2, repeat, under)) {
314042
+ item = { collection, record: record2, suffix: `${outerItem?.suffix ?? ""}~${record2.id}` };
314043
+ for (const child of childrenOf(node2, doc2.nodes)) {
314044
+ const built = build3(child, node2, kids3D, kidFold);
314045
+ if (built) web.children.push(built);
314046
+ }
314047
+ }
314048
+ if (collection.perVisitor && !outerItem) {
314049
+ item = { collection, record: templateRecord(collection), suffix: `~${ITEM_RECORD}` };
314050
+ const template2 = [];
314051
+ for (const child of childrenOf(node2, doc2.nodes)) {
314052
+ const built = build3(child, node2, kids3D, kidFold);
314053
+ if (built) template2.push(built);
314054
+ }
314055
+ const sortField = repeat.sort && collection.fields.find((f3) => f3.id === repeat.sort.fieldId);
314056
+ web.repeat = {
314057
+ collectionId: collection.id,
314058
+ template: template2,
314059
+ ...repeat.filter?.trim() ? { filter: repeat.filter } : {},
314060
+ ...sortField ? { sort: { key: fieldKey(sortField.name), dir: repeat.sort.dir } } : {},
314061
+ ...repeat.offset ? { offset: repeat.offset } : {},
314062
+ ...repeat.limit ? { limit: repeat.limit } : {}
314063
+ };
314064
+ }
314065
+ } finally {
314066
+ item = outerItem;
314067
+ }
314068
+ } else for (const child of childrenOf(node2, doc2.nodes)) {
314069
+ const built = build3(child, node2, kids3D, kidFold);
314070
+ if (built) web.children.push(built);
314071
+ }
314072
+ }
314073
+ } finally {
314074
+ motion = outer;
314075
+ }
314076
+ if (web.children.some((c2) => c2.positioning === "absolute")) {
314077
+ for (const c2 of web.children) if (c2.positioning === "flow") c2.layered = true;
314078
+ }
314079
+ hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
314080
+ return web;
314081
+ };
314082
+ const root2 = build3(first2, start2?.parent ?? null, start2?.in3D ?? false, start2?.fold ?? 0);
314083
+ if (!root2) throw new Error("Node cap of 0");
314084
+ return { root: root2, truncated, ...folds ? { rules: foldRules(folds) } : {}, ...tokens?.vars.length ? { tokens } : {} };
314085
+ }
314086
+ function childLookup(doc2, id3) {
314087
+ const at3 = id3.lastIndexOf("::");
314088
+ const host = at3 > 0 ? id3.slice(0, at3) : "";
314089
+ const hostNode = doc2.nodes[host] ?? (host.includes("::") ? childLookup(doc2, host) : void 0);
314090
+ return hostNode ? childrenOf(hostNode, doc2.nodes).find((c2) => c2.id === id3) : void 0;
314091
+ }
314092
+ function flatten2(node2, out = []) {
314093
+ out.push(node2);
314094
+ for (const c2 of node2.children) flatten2(c2, out);
314095
+ return out;
314096
+ }
314097
+ var DEFAULT_NODE_CAP, PAINTED, anchorMemo, followsVisibility, isFlex, round3, foldVar, foldRules, clickable;
314098
+ var init_tree = __esm({
314099
+ "lib/io/web/tree.ts"() {
314100
+ "use strict";
314101
+ init_instance_layout();
314102
+ init_text_styles();
314103
+ init_variables();
314104
+ init_scene3d();
314105
+ init_semantics();
314106
+ init_collections();
314107
+ init_props();
314108
+ init_native_registry();
314109
+ init_controls();
314110
+ init_expressions2();
314111
+ init_children();
314112
+ init_css();
314113
+ init_capability();
314114
+ init_expressible();
314115
+ init_motion();
314116
+ init_element();
314117
+ init_paint2();
314118
+ init_responsive();
314119
+ init_richtext();
314120
+ init_tokens2();
314121
+ init_timeline();
314122
+ init_interactive();
314123
+ DEFAULT_NODE_CAP = 120;
314124
+ PAINTED = ["background", "border", "border-style", "border-color", "border-width", "outline", "border-radius", "box-shadow", "box-sizing", "filter", "backdrop-filter"];
314125
+ anchorMemo = /* @__PURE__ */ new WeakMap();
314126
+ 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.
314127
+ Object.values(n.responsive ?? {}).some((o) => o.visible === true);
314128
+ isFlex = (f2) => f2?.layoutMode === "HORIZONTAL" || f2?.layoutMode === "VERTICAL";
314129
+ round3 = (v) => Math.round(v * 1e3) / 1e3;
314130
+ foldVar = (depth2) => `--pc-f${depth2}`;
314131
+ foldRules = (depth2) => Array.from({ length: depth2 }, (_, i2) => `@property ${foldVar(i2 + 1)} { syntax: '<number>'; inherits: true; initial-value: 1; }`);
314132
+ clickable = (n) => !!n.semantics?.link || (n.interactions ?? []).some((ix) => ix.trigger === "ON_CLICK" || ix.trigger === "ON_PRESS");
314133
+ }
314134
+ });
314135
+
314136
+ // lib/io/web/interactive.ts
314137
+ function subtreeIds(doc2, id3, out = /* @__PURE__ */ new Set()) {
314138
+ if (out.has(id3)) return out;
314139
+ const n = doc2.nodes[id3];
314140
+ if (!n) return out;
314141
+ out.add(id3);
314142
+ if (n.type === "INSTANCE") subtreeIds(doc2, n.mainComponentId, out);
314143
+ for (const c2 of n.childIds ?? []) subtreeIds(doc2, c2, out);
314144
+ return out;
314145
+ }
314146
+ function flowScreens(doc2, startId) {
314147
+ const start2 = doc2.nodes[startId];
314148
+ if (!start2 || start2.type !== "FRAME" || doc2.nodes[start2.parentId ?? ""]?.type !== "PAGE") return [startId];
314149
+ const out = [startId];
314150
+ for (let i2 = 0; i2 < out.length; i2++) {
314151
+ for (const id3 of subtreeIds(doc2, out[i2])) {
314152
+ for (const ix of interactionsOf(doc2.nodes[id3])) {
314153
+ const to = ix.action.navigationType === "NAVIGATE" ? ix.action.destinationId : null;
314154
+ const dest = to ? doc2.nodes[to] : void 0;
314155
+ if (!dest || out.includes(dest.id) || dest.type !== "FRAME" || doc2.nodes[dest.parentId ?? ""]?.type !== "PAGE") continue;
314156
+ if (Math.round(dest.width) !== Math.round(start2.width) || Math.round(dest.height) !== Math.round(start2.height)) continue;
314157
+ out.push(dest.id);
314158
+ }
314159
+ }
314160
+ }
314161
+ return out;
314162
+ }
314163
+ function variantStates(doc2, mainId) {
314164
+ const out = [mainId];
314165
+ for (let i2 = 0; i2 < out.length; i2++) {
314166
+ for (const id3 of subtreeIds(doc2, out[i2])) {
314167
+ for (const ix of interactionsOf(doc2.nodes[id3])) {
314168
+ const to = ix.action.navigationType === "CHANGE_TO" ? ix.action.destinationId : null;
314169
+ if (to && !out.includes(to) && doc2.nodes[to]?.type === "COMPONENT") out.push(to);
314170
+ }
314171
+ }
314172
+ }
314173
+ return out;
314174
+ }
314175
+ function buildState(ctx2, doc2, id3, machine, state, start2, variantOf2) {
314176
+ const expand = /* @__PURE__ */ new Map();
314177
+ const tree = buildPlainTree(doc2, id3, ctx2.opts, start2, { built: (web, _node, at3) => {
314178
+ if (web.type === "INSTANCE") expand.set(web, at3);
314179
+ } });
314180
+ for (const r of tree.rules ?? []) ctx2.rules.add(r);
314181
+ if (tree.truncated) ctx2.truncated = true;
314182
+ const ids2 = /* @__PURE__ */ new Map();
314183
+ const index2 = (w) => {
314184
+ ids2.set(w.id, w);
314185
+ w.children.forEach(index2);
314186
+ };
314187
+ index2(tree.root);
314188
+ const visit2 = (w, owner, st, isRoot) => {
314189
+ w.owner = owner;
314190
+ w.looks = { [st]: lookOf(w, isRoot) };
314191
+ if (w.motion) ctx2.keyframes.add(w.motion.keyframes);
314192
+ const node2 = nodeOf(doc2, w.id);
314193
+ note(ctx2, w, interactionsOf(doc2.nodes[realId(w.id)]), owner, st, ids2);
314194
+ const at3 = expand.get(w);
314195
+ const inst = node2?.type === "INSTANCE" ? node2 : void 0;
314196
+ const states = inst && at3 && ctx2.depth < 4 ? variantStates(doc2, inst.mainComponentId) : [];
314197
+ if (inst && at3 && states.length > 1 && w.id !== variantOf2) {
314198
+ const m = { id: `m${ctx2.machines.length}`, initial: inst.mainComponentId, states: states.map((s) => ({ id: s, name: stateName(doc2, s) })) };
314199
+ ctx2.machines.push(m);
314200
+ w.machine = m;
314201
+ const perState = [];
314202
+ for (const s of states) {
314203
+ let kids;
314204
+ if (s === inst.mainComponentId) {
314205
+ kids = w.children;
314206
+ kids.forEach((c2) => visit2(c2, m.id, s, false));
314207
+ } else {
314208
+ const shown2 = { ...doc2, nodes: { ...doc2.nodes, [inst.id]: { ...inst, mainComponentId: s } } };
314209
+ ctx2.depth++;
314210
+ try {
314211
+ kids = buildState(ctx2, shown2, inst.id, m.id, s, at3, inst.id).children;
314212
+ } finally {
314213
+ ctx2.depth--;
314214
+ }
314215
+ }
314216
+ note(ctx2, w, interactionsOf(doc2.nodes[s]), m.id, s, ids2, m.id);
314217
+ perState.push([s, kids]);
314218
+ }
314219
+ w.children = mergeChildren(perState, m.id, m.states.map((s) => s.id), ctx2);
314220
+ } else if (w.id === variantOf2) {
314221
+ w.children.forEach((c2) => visit2(c2, owner, st, false));
314222
+ } else {
314223
+ if (inst) note(ctx2, w, interactionsOf(doc2.nodes[inst.mainComponentId]), owner, st, ids2);
314224
+ w.children.forEach((c2) => visit2(c2, owner, st, false));
314225
+ }
314226
+ };
314227
+ visit2(tree.root, machine, state, !start2);
314228
+ return tree.root;
314229
+ }
314230
+ function note(ctx2, w, list2, machine, state, ids2, hostMachine) {
314231
+ if (!list2.length) return;
314232
+ const at3 = ctx2.pending.get(w) ?? [];
314233
+ for (const ix of list2) at3.push({ machine, state, ix, hostMachine: hostMachine ?? (machine !== FLOW ? machine : void 0), ids: ids2 });
314234
+ ctx2.pending.set(w, at3);
314235
+ }
314236
+ function lookOf(w, isRoot) {
314237
+ return {
314238
+ style: { ...placementStyle(w, isRoot), ...w.style, ...w.motion?.style ?? {} },
314239
+ ...w.text ? { text: w.text.characters } : {},
314240
+ ...w.tf ? { tf: w.tf } : {}
314241
+ };
314242
+ }
314243
+ function keyed(kids) {
314244
+ const seen = /* @__PURE__ */ new Map();
314245
+ return kids.map((k2) => {
314246
+ const base = `${k2.name}\0${k2.type}`;
314247
+ const i2 = seen.get(base) ?? 0;
314248
+ seen.set(base, i2 + 1);
314249
+ return [`${base}\0${i2}`, k2];
314250
+ });
314251
+ }
314252
+ function mergeChildren(perState, machine, states, ctx2) {
314253
+ const order2 = [];
314254
+ const groups = /* @__PURE__ */ new Map();
314255
+ for (const [state, kids] of perState) {
314256
+ let after = -1;
314257
+ for (const [k2, node2] of keyed(kids)) {
314258
+ let at3 = order2.indexOf(k2);
314259
+ if (at3 < 0) {
314260
+ order2.splice(after + 1, 0, k2);
314261
+ at3 = after + 1;
314262
+ }
314263
+ after = at3;
314264
+ (groups.get(k2) ?? groups.set(k2, []).get(k2)).push([state, node2]);
314265
+ }
314266
+ }
314267
+ return order2.map((k2) => mergeNode(groups.get(k2), machine, states, ctx2));
314268
+ }
314269
+ function mergeNode(items, machine, states, ctx2) {
314270
+ const [, first2] = items[0];
314271
+ if (first2.owner !== machine) {
314272
+ for (const [, w] of items.slice(1)) alias(ctx2, w, first2);
314273
+ return first2;
314274
+ }
314275
+ const looks = {};
314276
+ for (const s of states) looks[s] = null;
314277
+ for (const [s, w] of items) looks[s] = w.looks?.[s] ?? null;
314278
+ const merged = { ...first2, looks };
314279
+ const pend = items.flatMap(([, w]) => ctx2.pending.get(w) ?? []);
314280
+ if (pend.length) ctx2.pending.set(merged, pend);
314281
+ for (const [, w] of items) if (w !== merged) alias(ctx2, w, merged);
314282
+ if (first2.machine) {
314283
+ for (const [, w] of items) if (w.machine && w.machine !== first2.machine) ctx2.renamed.set(w.machine.id, first2.machine.id);
314284
+ }
314285
+ merged.children = first2.machine ? first2.children : mergeChildren(items.map(([s, w]) => [s, w.children]), machine, states, ctx2);
314286
+ return merged;
314287
+ }
314288
+ function alias(ctx2, from2, to) {
314289
+ const a = ctx2.alias ??= /* @__PURE__ */ new Map();
314290
+ a.set(from2, to);
314291
+ }
314292
+ function mergedOf(ctx2, w) {
314293
+ const a = ctx2.alias;
314294
+ let cur = w;
314295
+ for (let i2 = 0; i2 < 16 && a?.has(cur); i2++) cur = a.get(cur);
314296
+ return cur;
314297
+ }
314298
+ function actionOf(ctx2, p2) {
314299
+ const a = p2.ix.action;
314300
+ const glide2 = glideOf2(a.transition);
314301
+ const hold = p2.ix.trigger === "ON_HOVER" || p2.ix.trigger === "ON_PRESS";
314302
+ switch (a.navigationType) {
314303
+ case "NAVIGATE":
314304
+ return a.destinationId && ctx2.screens.has(a.destinationId) ? { kind: "go", machine: FLOW, to: a.destinationId, ...glide2, ...hold ? { hold } : {} } : null;
314305
+ case "BACK":
314306
+ return ctx2.screens.size > 1 ? { kind: "back", machine: FLOW } : null;
314307
+ case "CHANGE_TO":
314308
+ return p2.hostMachine && a.destinationId ? { kind: "go", machine: p2.hostMachine, to: a.destinationId, ...glide2, ...hold ? { hold } : {} } : null;
314309
+ case "ORBIT_3D": {
314310
+ const o = a.orbit ?? {};
314311
+ const uidOf = (id3) => {
314312
+ const w = id3 ? p2.ids.get(id3) : void 0;
314313
+ return w ? mergedOf(ctx2, w).uid : void 0;
314314
+ };
314315
+ const uid2 = uidOf(a.destinationId);
314316
+ const tiltUid = uidOf(o.tiltLayerId) ?? uid2;
314317
+ 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] };
314318
+ }
314319
+ default:
314320
+ return null;
314321
+ }
314322
+ }
314323
+ function buildWebTree(doc2, nodeId2, opts = {}) {
314324
+ const tree = buildTree(doc2, nodeId2, opts);
314325
+ const machine = opts.static || opts.stateMachine === false ? null : webStateMachine(doc2, nodeId2);
314326
+ return machine ? { ...tree, stateMachine: machine } : tree;
314327
+ }
314328
+ function buildTree(doc2, nodeId2, opts = {}) {
314329
+ if (opts.static || opts.target === "site") return buildPlainTree(doc2, nodeId2, opts);
314330
+ const screens = flowScreens(doc2, nodeId2);
314331
+ 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"));
314332
+ if (!anything) return buildPlainTree(doc2, nodeId2, opts);
314333
+ const flow = { id: FLOW, initial: nodeId2, states: screens.map((s) => ({ id: s, name: doc2.nodes[s]?.name ?? s })) };
314334
+ 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() };
314335
+ const roots = screens.map((s) => [s, buildState(ctx2, doc2, s, FLOW, s)]);
314336
+ const truncated = !!ctx2.truncated;
314337
+ const root2 = mergeNode(roots, FLOW, screens, ctx2);
314338
+ let uid2 = 0;
314339
+ const number4 = (w) => {
314340
+ w.uid = uid2++;
314341
+ w.children.forEach(number4);
314342
+ };
314343
+ number4(root2);
314344
+ const place3 = (w) => {
314345
+ const pend = ctx2.pending.get(w);
314346
+ if (pend) {
314347
+ const seen = /* @__PURE__ */ new Set();
314348
+ const on = [];
314349
+ for (const raw of pend) {
314350
+ const p2 = { ...raw, machine: ctx2.renamed.get(raw.machine) ?? raw.machine, ...raw.hostMachine ? { hostMachine: ctx2.renamed.get(raw.hostMachine) ?? raw.hostMachine } : {} };
314351
+ const trigger = TRIGGERS[p2.ix.trigger];
314352
+ const action3 = trigger ? actionOf(ctx2, p2) : null;
314353
+ if (!trigger || !action3) continue;
314354
+ 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 };
314355
+ const sig = JSON.stringify(ix);
314356
+ if (!seen.has(sig)) {
314357
+ seen.add(sig);
314358
+ on.push(ix);
314359
+ }
314360
+ }
314361
+ if (on.length) w.on = on;
314362
+ }
314363
+ w.children.forEach(place3);
314364
+ };
314365
+ place3(root2);
314366
+ 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] } };
314367
+ }
314368
+ var FLOW, interactionsOf, realId, nodeOf, stateName, TRIGGERS, EASINGS2, glideOf2;
314369
+ var init_interactive = __esm({
314370
+ "lib/io/web/interactive.ts"() {
314371
+ "use strict";
314372
+ init_scene_graph();
314373
+ init_tree();
314374
+ init_state_machine3();
314375
+ init_element();
314376
+ FLOW = "flow";
314377
+ interactionsOf = (n) => n?.interactions ?? [];
314378
+ realId = (id3) => id3.includes("::") ? id3.slice(id3.lastIndexOf("::") + 2) : id3;
314379
+ nodeOf = (doc2, id3) => doc2.nodes[id3] ?? (id3.includes("::") ? resolveVirtualNode2(doc2.nodes, id3) ?? void 0 : void 0);
314380
+ stateName = (doc2, id3) => {
314381
+ const n = doc2.nodes[id3];
314382
+ const v = n?.variantProperties;
314383
+ return v ? Object.values(v).join(", ") : n?.name ?? id3;
314384
+ };
314385
+ TRIGGERS = {
314386
+ ON_CLICK: "click",
314387
+ ON_HOVER: "hover",
314388
+ ON_PRESS: "press",
314389
+ ON_DRAG: "drag",
314390
+ MOUSE_ENTER: "enter",
314391
+ MOUSE_LEAVE: "leave",
314392
+ AFTER_TIMEOUT: "timeout",
314393
+ KEY_DOWN: "key"
314394
+ };
314395
+ 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)" };
314396
+ 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" };
314397
+ }
314398
+ });
314399
+
314400
+ // lib/io/web/site.ts
314401
+ function light(node2) {
314402
+ const out = {};
314403
+ for (const k2 in node2) if (!HEAVY.has(k2)) out[k2] = node2[k2];
314404
+ return out;
314405
+ }
314406
+ function programDocument(doc2, pageId2, screens) {
314407
+ const nodes = {};
314408
+ const take = (id3) => {
314409
+ const n = doc2.nodes[id3];
314410
+ if (!n || nodes[id3]) return;
314411
+ nodes[id3] = light(n);
314412
+ for (const c2 of n.childIds ?? []) take(c2);
314413
+ const main2 = n.mainComponentId;
314414
+ if (main2) {
314415
+ take(main2);
314416
+ const set3 = doc2.nodes[main2]?.parentId;
314417
+ if (set3 && doc2.nodes[set3]?.type === "COMPONENT_SET") take(set3);
314418
+ }
314419
+ };
314420
+ const page = doc2.nodes[pageId2];
314421
+ if (page) nodes[pageId2] = { ...light(page), childIds: screens.map((s) => s.id) };
314422
+ for (const s of screens) take(s.id);
314423
+ return {
314424
+ id: doc2.id,
314425
+ name: doc2.name,
314426
+ nodes,
314427
+ pages: [pageId2],
314428
+ styles: {},
314429
+ variables: doc2.variables,
314430
+ variableCollections: doc2.variableCollections,
314431
+ activeVariableModes: doc2.activeVariableModes,
314432
+ settings: doc2.settings,
314433
+ // What a layer that follows a record's field is drawn from, while the page runs.
314434
+ ...doc2.collections && Object.keys(doc2.collections).length ? { collections: doc2.collections, records: doc2.records } : {}
314435
+ };
314436
+ }
314437
+ function withVariants(doc2, root2, opts, depth2 = 3) {
314438
+ if (depth2 <= 0) return;
314439
+ for (const w of flatten2(root2)) {
314440
+ const real = layerId(w.id), suffix = copySuffix(w.id);
314441
+ const inst = w.type === "INSTANCE" && !real.includes("::") ? doc2.nodes[real] : void 0;
314442
+ const main2 = inst?.mainComponentId;
314443
+ if (!inst || !main2 || w.variants) continue;
314444
+ const reach = variantStates(doc2, main2);
314445
+ if (reach.length < 2) continue;
314446
+ w.variant = main2;
314447
+ w.variants = {};
314448
+ const parent = inst.parentId ? doc2.nodes[inst.parentId] ?? null : null;
314449
+ const record2 = suffix ? doc2.records?.[copyRecord(w.id) ?? ""] : void 0;
314450
+ const as3 = record2 ? { ...opts, item: { collectionId: record2.collectionId, recordId: record2.id } } : opts;
314451
+ for (const v of reach.slice(1)) {
314452
+ const as2 = { ...doc2, nodes: { ...doc2.nodes, [inst.id]: { ...inst, mainComponentId: v } } };
314453
+ const built = buildPlainTree(as2, inst.id, as3, { parent, in3D: false, fold: 0 }).root;
314454
+ if (suffix) for (const n of flatten2(built)) n.id += suffix;
314455
+ built.variant = v;
314456
+ withVariants(as2, built, opts, depth2 - 1);
314457
+ w.variants[v] = built;
314458
+ }
314459
+ }
314460
+ }
314461
+ function everyNode(root2, out = []) {
314462
+ for (const n of flatten2(root2)) {
314463
+ out.push(n);
314464
+ for (const v of Object.values(n.variants ?? {})) everyNode(v, out);
314465
+ }
314466
+ return out;
314467
+ }
314468
+ function mediaRules(doc2, screenId, base, opts) {
314469
+ const rules = [];
314470
+ let above = new Map(flatten2(base).map((n) => [n.id, declared(n, n === base)]));
314471
+ for (const bp of breakpointsOf(doc2).slice(1)) {
314472
+ const view2 = breakpointDocument(doc2, bp.id);
314473
+ const root2 = buildPlainTree(view2, screenId, opts).root;
314474
+ const here = new Map(flatten2(root2).map((n) => [n.id, declared(n, n === root2)]));
314475
+ const blocks = [];
314476
+ for (const [id3, was] of above) {
314477
+ const now2 = here.get(id3);
314478
+ const diff = {};
314479
+ if (!now2) {
314480
+ if (was.display !== "none") diff.display = "none";
314481
+ } else {
314482
+ for (const k2 in was) if (!(k2 in now2)) diff[k2] = "revert";
314483
+ for (const k2 in now2) if (now2[k2] !== was[k2]) diff[k2] = now2[k2];
314484
+ }
314485
+ if (Object.keys(diff).length) blocks.push(` [data-pc-id="${id3}"] {
314486
+ ${styleMapToCSSText(Object.fromEntries(Object.entries(diff).map(([k2, v]) => [k2, `${v} !important`])), " ")}
314487
+ }`);
314488
+ }
314489
+ if (blocks.length) rules.push(`@media (max-width: ${bp.maxWidth}px) {
314490
+ ${blocks.join("\n")}
314491
+ }`);
314492
+ above = new Map([...above].map(([id3, was]) => [id3, here.get(id3) ?? { ...was, display: "none" }]));
314493
+ }
314494
+ return rules;
314495
+ }
314496
+ function sitePages(doc2, pageId2) {
314497
+ const screens = screensOf(doc2, pageId2);
314498
+ const routes = routesOf(screens);
314499
+ return screens.flatMap((s) => {
314500
+ const base = routes.get(s.id);
314501
+ const collection = s.route?.collectionId ? doc2.collections?.[s.route.collectionId] : void 0;
314502
+ if (!collection) return [{ id: s.id, frame: s, route: base, title: s.route?.title || s.name }];
314503
+ const slugs = recordSlugs(doc2, collection.id);
314504
+ return recordsIn(doc2, collection.id).map((record2) => ({
314505
+ id: `${s.id}~${record2.id}`,
314506
+ frame: s,
314507
+ record: record2,
314508
+ collection,
314509
+ route: `${base === "/" ? "" : base}/${slugs.get(record2.id)}`,
314510
+ title: itemText(s.route?.title || s.name, collection, record2)
314511
+ }));
314512
+ });
314513
+ }
314514
+ function screenTransitions3d(doc2, screens) {
314515
+ const out = /* @__PURE__ */ new Set();
314516
+ const turns = (a) => {
314517
+ if (!a) return [];
314518
+ if (a.navigationType === "CONDITIONAL") return (a.branches ?? []).flatMap((b) => b.actions.flatMap(turns));
314519
+ return a.navigationType === "NAVIGATE" && a.destinationId && a.transition && is3DTransition(a.transition.type) ? [a.destinationId] : [];
314520
+ };
314521
+ for (const s of screens) {
314522
+ const seen = /* @__PURE__ */ new Set();
314523
+ const walk3 = (id3) => {
314524
+ const n = doc2.nodes[id3];
314525
+ if (!n || seen.has(id3)) return;
314526
+ seen.add(id3);
314527
+ for (const ix of n.interactions ?? []) for (const to of turns(ix.action)) {
314528
+ out.add(s.id);
314529
+ out.add(to);
314530
+ }
314531
+ for (const c2 of n.childIds ?? []) walk3(c2);
314532
+ const main2 = n.mainComponentId;
314533
+ if (main2) walk3(main2);
314534
+ };
314535
+ walk3(s.id);
314536
+ }
314537
+ return out;
314538
+ }
314539
+ function withoutScreenIslands(site) {
314540
+ if (!site.islands) return site;
314541
+ const kept = Object.entries(site.islands).filter(([k2]) => !k2.startsWith(SCREEN_ISLAND));
314542
+ if (kept.length === Object.keys(site.islands).length) return site;
314543
+ const { islands: _, ...rest } = site;
314544
+ return kept.length ? { ...rest, islands: Object.fromEntries(kept) } : rest;
314545
+ }
314546
+ function buildWebSite(doc2, opts = {}) {
314547
+ const pageId2 = opts.pageId ?? doc2.pages[0];
314548
+ const screens = screensOf(doc2, pageId2);
314549
+ const routes = routesOf(screens);
314550
+ const build3 = { target: "site", nodeCap: opts.nodeCap ?? 2e4, static: opts.static, routes: Object.fromEntries(routes) };
314551
+ const laid = /* @__PURE__ */ new Set();
314552
+ const pages2 = sitePages(doc2, pageId2).map((p2) => {
314553
+ const s = p2.frame;
314554
+ const opts2 = p2.record ? { ...build3, item: { collectionId: p2.collection.id, recordId: p2.record.id } } : build3;
314555
+ const tree = buildPlainTree(doc2, s.id, opts2);
314556
+ const media2 = laid.has(s.id) ? [] : mediaRules(doc2, s.id, tree.root, opts2);
314557
+ laid.add(s.id);
314558
+ withVariants(doc2, tree.root, opts2);
314559
+ const description = s.route?.description ? p2.record ? itemText(s.route.description, p2.collection, p2.record) : s.route.description : void 0;
314560
+ const moves3 = !opts2.static && hasFrameMotion(doc2.nodes, s.id);
314561
+ const length2 = moves3 ? timelineDuration(doc2.nodes, s.id) : 0;
314562
+ const machine = moves3 ? webStateMachine(doc2, s.id) : null;
314563
+ return {
314564
+ ...machine ? { machine } : {},
314565
+ ...length2 > 0 ? { timeline: { duration: length2, stops: stopsOf(frameTimeline(doc2.nodes, s.id).markers, [0, length2]), loops: frameRunsOn(doc2.nodes, s.id) } } : {},
314566
+ id: p2.id,
314567
+ route: p2.route,
314568
+ title: p2.title,
314569
+ ...p2.record ? { screen: s.id, record: p2.record.id } : {},
314570
+ ...description ? { description } : {},
314571
+ ...s.route?.notFound ? { notFound: true } : {},
314572
+ ...s.route?.access ? { access: s.route.access } : {},
314573
+ tree,
314574
+ ...media2.length ? { media: media2 } : {}
314575
+ };
314576
+ });
314577
+ const islandNodes = new Map(pages2.flatMap((p2) => everyNode(p2.tree.root).filter((n) => n.island && !n.id.includes("::"))).map((n) => [n.id, n]));
314578
+ const fonts = /* @__PURE__ */ new Map();
314579
+ 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);
314580
+ const home = pages2.find((p2) => p2.route === "/" && !p2.screen);
314581
+ const turned = doc2.site?.gpuTransitions === false ? /* @__PURE__ */ new Set() : screenTransitions3d(doc2, screens);
314582
+ 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 })]);
314583
+ const islands = [...[...islandNodes].map(([id3, n]) => [id3, sliceDocument(doc2, n.asset?.of ?? layerId(id3), { self: !!n.asset?.self })]), ...screenSlices];
314584
+ return {
314585
+ name: doc2.name,
314586
+ pages: pages2,
314587
+ home: home?.id ?? null,
314588
+ tokens: pages2.find((p2) => p2.tree.tokens)?.tree.tokens,
314589
+ fonts: [...fonts].sort(([a], [b]) => a.localeCompare(b)).map(([family, w]) => ({ family, weights: [...w].sort((a, b) => a - b) })),
314590
+ assets: pages2.flatMap((p2) => everyNode(p2.tree.root).filter((n) => n.asset).map((n) => n.id)),
314591
+ program: { document: programDocument(doc2, pageId2, screens), start: home?.id ?? null },
314592
+ ...islands.length ? { islands: Object.fromEntries(islands) } : {}
314593
+ };
314594
+ }
314595
+ var HEAVY, declared, drawnByGpu;
314596
+ var init_site = __esm({
314597
+ "lib/io/web/site.ts"() {
314598
+ "use strict";
314599
+ init_breakpoints();
314600
+ init_collections();
314601
+ init_routes();
314602
+ init_instances2();
314603
+ init_timeline_stops();
314604
+ init_transitions();
314605
+ init_css();
314606
+ init_element();
314607
+ init_fonts3();
314608
+ init_slice();
314609
+ init_render();
314610
+ init_state_machine3();
314611
+ init_interactive();
314612
+ init_tree();
314613
+ init_routes();
314614
+ HEAVY = /* @__PURE__ */ new Set(["fills", "strokes", "effects", "shadows", "blurs", "vectorPaths", "paths", "styledSegments", "paragraphs", "imageUrl", "exportSettings", "annotations", "devResources", "codeConnect", "layoutGrids", "aiPending"]);
314615
+ declared = (n, isRoot) => ({ ...placementStyle(n, isRoot), ...n.style, ...n.hidden ? { display: "none" } : {} });
314616
+ drawnByGpu = (page) => !everyNode(page.tree.root).some((n) => n.input || n.check || n.html || n.code);
314617
+ }
314618
+ });
314619
+
313148
314620
  // lib/code/cdn.ts
313149
314621
  var CDN;
313150
314622
  var init_cdn = __esm({
@@ -336868,7 +338340,7 @@ async function withSiteCode(site, doc2) {
336868
338340
  return { ...site, code: { modules, ...imports3.size ? { packages: { versions, imports: [...imports3].sort() } } : {} } };
336869
338341
  }
336870
338342
  var codeNodes;
336871
- var init_site = __esm({
338343
+ var init_site2 = __esm({
336872
338344
  "lib/code/site.ts"() {
336873
338345
  "use strict";
336874
338346
  codeNodes = (n, out = []) => {
@@ -336919,44 +338391,6 @@ var init_hash = __esm({
336919
338391
  }
336920
338392
  });
336921
338393
 
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
338394
  // lib/code/snapshots.ts
336961
338395
  var init_snapshots = __esm({
336962
338396
  "lib/code/snapshots.ts"() {
@@ -337401,871 +338835,6 @@ ${indent}<img src="" width="${node2.width}" height="${node2.height}" alt="${esca
337401
338835
  }
337402
338836
  });
337403
338837
 
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
338838
  // lib/io/web/assets.ts
338270
338839
  async function resolveWebAssets(tree, resolvers) {
338271
338840
  const pending7 = (Array.isArray(tree) ? tree : flatten2(tree.root)).filter((n) => !!n.asset);
@@ -338316,285 +338885,6 @@ var init_asset_files = __esm({
338316
338885
  }
338317
338886
  });
338318
338887
 
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
338888
  // lib/io/web/index.ts
338599
338889
  var web_exports = {};
338600
338890
  __export(web_exports, {
@@ -338670,7 +338960,7 @@ var init_web = __esm({
338670
338960
  init_asset_files();
338671
338961
  init_element();
338672
338962
  init_fonts3();
338673
- init_site2();
338963
+ init_site();
338674
338964
  init_tokens2();
338675
338965
  init_naming();
338676
338966
  init_tree();
@@ -338796,7 +339086,7 @@ var init_host = __esm({
338796
339086
  "lib/preview/host.ts"() {
338797
339087
  "use strict";
338798
339088
  init_cdn();
338799
- init_site();
339089
+ init_site2();
338800
339090
  init_snapshot_frame();
338801
339091
  init_web();
338802
339092
  init_media_store();
@@ -338878,7 +339168,8 @@ async function completeSite(doc2, pageId2) {
338878
339168
  const [{ previewSite: previewSite2 }, { rendererAssetResolvers: rendererAssetResolvers2 }] = await Promise.all([Promise.resolve().then(() => (init_host(), host_exports)), Promise.resolve().then(() => (init_resolvers(), resolvers_exports))]);
338879
339169
  return previewSite2(doc2, pageId2, rendererAssetResolvers2(doc2));
338880
339170
  }
338881
- async function nextFilesOf(site, doc2, opts = {}) {
339171
+ async function nextFilesOf(full, doc2, opts = {}) {
339172
+ const site = withoutScreenIslands(full);
338882
339173
  const islandScript2 = site.islands && Object.keys(site.islands).length ? await runtimeScript("island") : null;
338883
339174
  return [...nextProjectFiles(site, doc2, { ...opts, islandScript: islandScript2 }), ...await appAssetFiles(appAssetPaths(site), "public/")];
338884
339175
  }
@@ -338894,6 +339185,7 @@ var init_build2 = __esm({
338894
339185
  init_assets();
338895
339186
  init_static();
338896
339187
  init_next();
339188
+ init_site();
338897
339189
  runtimeScript = (name2) => fetch(`/pc/${name2}.js?fresh=${Date.now()}`, { cache: "no-store" }).then((r) => r.ok ? r.text() : null).catch(() => null);
338898
339190
  NoSiteRuntime = class extends Error {
338899
339191
  constructor() {
@@ -340134,7 +340426,7 @@ var init_motion2 = __esm({
340134
340426
  ui: { label: "Edit composition", palette: false },
340135
340427
  agent: {
340136
340428
  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.`
340429
+ 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
340430
  }
340139
340431
  },
340140
340432
  run: (args2, ctx2) => {
@@ -343898,7 +344190,7 @@ var init_prototype = __esm({
343898
344190
  triggerKey: external_exports.string().max(40).optional(),
343899
344191
  dragDirection: external_exports.enum(["LEFT", "RIGHT", "UP", "DOWN"]).optional()
343900
344192
  });
343901
- LIVE = ["characters", ...LIVE_VALUE_PROPS];
344193
+ LIVE = ["characters", "imageUrl", ...LIVE_VALUE_PROPS];
343902
344194
  prototypeEdit = defineCommand({
343903
344195
  id: "prototype.edit",
343904
344196
  title: "Edit prototype",
@@ -344715,6 +345007,7 @@ function designFrameOf(doc2, id3) {
344715
345007
  }
344716
345008
  var init_locate = __esm({
344717
345009
  "lib/agent/design-script/locate.ts"() {
345010
+ "use strict";
344718
345011
  }
344719
345012
  });
344720
345013
 
@@ -344953,6 +345246,7 @@ function placeDesign(doc2, built, source3, size6, name2, at3) {
344953
345246
  var DESIGN_NAMESPACES, DERIVED2, templateOfBuild;
344954
345247
  var init_build3 = __esm({
344955
345248
  "lib/agent/design-script/build.ts"() {
345249
+ "use strict";
344956
345250
  init_hash();
344957
345251
  init_scene_graph();
344958
345252
  init_libraries();
@@ -345871,7 +346165,9 @@ Every layer call returns its id. **Name** every layer a cue, count or swap must
345871
346165
  - Live state: \`const yearly = k.variable('Billing', 'yearly', 'BOOLEAN', false)\`, \`k.setVariable(layer, yearly, { toggle: true })\`
345872
346166
  on click, \`k.bindVariable(layer, 'visible', yearly)\` to show a layer while it is true (see the pricing example).
345873
346167
  - Prototype links: \`k.link(fromLayer, toFrame, 'PUSH_FROM_RIGHT')\` between screens made with \`k.addScreen(name)\`, and
345874
- \`k.flowStart(frame, name)\`.`;
346168
+ \`k.flowStart(frame, name)\`. 3D transitions (\`'CUBE_FROM_RIGHT'\`, \`'CAROUSEL_FROM_LEFT'\`, \`'FLIP_HORIZONTAL'\`,
346169
+ \`'SWING_OPEN'\`, \`'STACK_IN'\`, \`'DEPTH_PUSH'\` and their pairs) turn the screens through a perspective and default to
346170
+ 650 ms; a published site draws them on the GPU only when one is used, so keep a plain site's links flat.`;
345875
346171
  MOTION = `## Motion and music
345876
346172
 
345877
346173
  Set the timeline first, then add moves. Times are ms on the frame's timeline.
@@ -346433,7 +346729,7 @@ function collectionOf(doc2, ref3) {
346433
346729
  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
346730
  return c2;
346435
346731
  }
346436
- var sizing, padding, overrides, nodeSetResponsive, link, nodeSetSemantics, nodeSetControl, siteSetRoute, breakpoint, siteSetBreakpoints, siteGetBreakpoints, described2, dataEditCollection, dataEditRecords, dataGetRecords, nodeSetRepeat;
346732
+ var sizing, padding, overrides, nodeSetResponsive, link, nodeSetSemantics, nodeSetControl, siteSetRoute, breakpoint, siteSetBreakpoints, siteSetGpuTransitions, siteGetBreakpoints, described2, dataEditCollection, dataEditRecords, dataGetRecords, nodeSetRepeat;
346437
346733
  var init_site3 = __esm({
346438
346734
  "lib/commands/site.ts"() {
346439
346735
  "use strict";
@@ -346719,6 +347015,30 @@ var init_site3 = __esm({
346719
347015
  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
347016
  }
346721
347017
  });
347018
+ siteSetGpuTransitions = defineCommand({
347019
+ id: "site.setGpuTransitions",
347020
+ title: "Draw 3D transitions with WebGPU",
347021
+ domain: "site",
347022
+ effect: "document",
347023
+ permission: "write",
347024
+ undoLabel: "Change how 3D transitions are drawn",
347025
+ params: external_exports.object({
347026
+ 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.")
347027
+ }).strict(),
347028
+ expose: {
347029
+ 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 } }] },
347030
+ agent: {
347031
+ name: "set_gpu_transitions",
347032
+ 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."
347033
+ }
347034
+ },
347035
+ run: (args2, ctx2) => {
347036
+ const doc2 = ctx2.doc();
347037
+ const { gpuTransitions: _, ...rest } = doc2.site ?? {};
347038
+ ctx2.commit({ ...doc2, site: args2.on ? rest : { ...rest, gpuTransitions: false } });
347039
+ 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 } };
347040
+ }
347041
+ });
346722
347042
  siteGetBreakpoints = defineCommand({
346723
347043
  id: "site.getBreakpoints",
346724
347044
  title: "Get breakpoints",
@@ -380372,6 +380692,7 @@ var init_builtin2 = __esm({
380372
380692
  dataEditCollection,
380373
380693
  dataEditRecords,
380374
380694
  dataGetRecords,
380695
+ siteSetGpuTransitions,
380375
380696
  // the file as a website online (lib/client/cloud/publish-site.ts): what is published (appended, as above)
380376
380697
  publishStatus,
380377
380698
  // designs as code (lib/agent/design-script): a whole design from one template-kit script (appended, as above)
@@ -380743,8 +381064,8 @@ async function renderLibraryPreviews(renderer, doc2, listing, format = pickPrevi
380743
381064
  const cap2 = await capture(renderer, doc2, c2.playsId, componentSchedule(c2.duration), previewScale(PREVIEW_BOX));
380744
381065
  if (!cap2.frames.length) continue;
380745
381066
  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) });
381067
+ const still2 = cap2.frames[fullestFrame(cap2.frames)];
381068
+ out.push({ key: c2.id, file: "still", type: PREVIEW_STILL_TYPE, bytes: await encodeRaster("PNG", cap2.width, cap2.height, still2.rgba) });
380748
381069
  }
380749
381070
  const shownCells = listing.filter((c2) => doc2.nodes[c2.playsId]).slice(0, POSTER_MAX);
380750
381071
  if (!shownCells.length) return out;
@@ -381139,8 +381460,8 @@ async function renderShaderPreview(device, fills, code, params2, zoom = 1) {
381139
381460
  };
381140
381461
  const animated = reflectShader(code).animated;
381141
381462
  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 };
381463
+ const still2 = await draw(0);
381464
+ return still2 && { type: "image/png", bytes: await encodeRaster("PNG", w, h, overGround(still2)), width: w, height: h, animated };
381144
381465
  }
381145
381466
  const frames = [];
381146
381467
  for (const f2 of previewFrames()) {
@@ -391555,7 +391876,7 @@ async function runInEditor(doc2, commandId, params2, opts) {
391555
391876
  }
391556
391877
  }
391557
391878
  var decodeDataUrl2;
391558
- var init_render = __esm({
391879
+ var init_render2 = __esm({
391559
391880
  "packages/cli/src/render.ts"() {
391560
391881
  "use strict";
391561
391882
  init_editor_open();
@@ -391664,7 +391985,7 @@ async function step2(command, params2, flags, rc) {
391664
391985
  if (where === "plugin" || where === "signin" || where === "app" || where === "unavailable") throw new CliError(`${command.id}: ${WHERE_HELP[where]}`);
391665
391986
  if (where === "browser") {
391666
391987
  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));
391988
+ const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render2(), render_exports));
391668
391989
  const download = specOf(command).flags.some((f2) => f2.param === "download" && f2.type === "boolean") && params2.download === void 0 ? { download: true } : {};
391669
391990
  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
391991
  return { result: done.result ?? { summary: `Ran ${command.id}` }, files: done.files };
@@ -391680,7 +392001,7 @@ async function step2(command, params2, flags, rc) {
391680
392001
  }
391681
392002
  async function reviewInEditor(doc2, frames, look, flags, rc, media2) {
391682
392003
  if (!frames.length) return [];
391683
- const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render(), render_exports));
392004
+ const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render2(), render_exports));
391684
392005
  const out = flagString(flags, "out") ?? "look/";
391685
392006
  const opts = { appUrl: rc.appUrl, surface: "agent", headful: flagBool(flags, "headful"), out: out.endsWith("/") ? out : `${out}/`, info: rc.out.info, media: media2 };
391686
392007
  const files = [];
@@ -392237,13 +392558,13 @@ async function openSettled(page, t3, sizeId) {
392237
392558
  const sleep4 = (ms2) => new Promise((r) => setTimeout(r, ms2));
392238
392559
  const quiet = async () => {
392239
392560
  let last3 = w.__vpStore.getState().document.nodes;
392240
- for (let still = 0, i2 = 0; still < 6 && i2 < 300; i2++) {
392561
+ for (let still2 = 0, i2 = 0; still2 < 6 && i2 < 300; i2++) {
392241
392562
  await w.__vpRenderer.whenReady();
392242
392563
  await sleep4(100);
392243
392564
  const now2 = w.__vpStore.getState().document.nodes;
392244
- if (now2 === last3) still++;
392565
+ if (now2 === last3) still2++;
392245
392566
  else {
392246
- still = 0;
392567
+ still2 = 0;
392247
392568
  last3 = now2;
392248
392569
  }
392249
392570
  }
@@ -392422,14 +392743,14 @@ async function runPictures(root2, appUrl, out) {
392422
392743
  const t3 = asTemplate(upload);
392423
392744
  const sizeId = t3.payload.variants[0].sizeId;
392424
392745
  const thumbnail = await drawThumbnail(editor, t3, sizeId);
392425
- const still = await drawDetailStill(editor, t3, sizeId);
392746
+ const still2 = await drawDetailStill(editor, t3, sizeId);
392426
392747
  const anim = upload.meta.animated ? await drawPreview(editor, t3, false) : null;
392427
392748
  const folder = join9(dir, "pictures");
392428
392749
  rmSync4(folder, { recursive: true, force: true });
392429
392750
  mkdirSync6(folder, { recursive: true });
392430
- writeFileSync7(join9(folder, "still.webp"), still.bytes);
392751
+ writeFileSync7(join9(folder, "still.webp"), still2.bytes);
392431
392752
  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 } } : {} };
392753
+ const pictures = { still: { w: still2.width, h: still2.height }, ...anim ? { anim: { w: anim.width, h: anim.height, ms: anim.durationMs } } : {} };
392433
392754
  writeFileSync7(join9(folder, "pictures.json"), `${JSON.stringify(pictures, null, 2)}
392434
392755
  `);
392435
392756
  writeFileSync7(join9(dir, "template.json"), JSON.stringify({ ...upload, meta: { ...upload.meta, thumbnail } }));
@@ -392450,7 +392771,7 @@ var init_pictures = __esm({
392450
392771
  "use strict";
392451
392772
  init_pictures_node();
392452
392773
  init_publish2();
392453
- init_render();
392774
+ init_render2();
392454
392775
  init_io();
392455
392776
  asTemplate = (u) => ({ meta: { ...u.meta, id: u.meta.localId }, payload: u.payload });
392456
392777
  }
@@ -393019,7 +393340,7 @@ init_resources();
393019
393340
  init_desktop();
393020
393341
  init_hypery();
393021
393342
  import { createInterface } from "node:readline";
393022
- var VERSION2 = "0.7.1";
393343
+ var VERSION2 = "0.8.0";
393023
393344
  var HELP = `popcraft ${VERSION2} \u2014 the PopCraft command line
393024
393345
 
393025
393346
  Files (headless, on .popcraft files):