@popcraft/cli 0.7.0 → 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 +1572 -1262
  2. package/package.json +2 -2
package/dist/popcraft.mjs CHANGED
@@ -378,7 +378,6 @@ var init_page_presets = __esm({
378
378
  var TEMPLATE_GROUP_IDS, t, ids, COMIC_PRESETS, TEMPLATE_GROUPS, BY_ID, TEMPLATE_TYPES, typesForKind;
379
379
  var init_groups = __esm({
380
380
  "lib/templates/groups.ts"() {
381
- "use strict";
382
381
  init_page_presets();
383
382
  TEMPLATE_GROUP_IDS = ["print", "comic", "social", "slides", "web", "app", "game", "email", "motion", "board"];
384
383
  t = (id3, label3, ...kinds) => ({ id: id3, label: label3, kinds });
@@ -1174,7 +1173,7 @@ function operations(spec = openapi) {
1174
1173
  }
1175
1174
  async function call(target2, method, path, opts = {}) {
1176
1175
  const qs = new URLSearchParams(opts.query ?? {}).toString();
1177
- const headers = { "user-agent": `popcraft-cli/${"0.7.0"}`, ...opts.headers };
1176
+ const headers = { "user-agent": `popcraft-cli/${"0.8.0"}`, ...opts.headers };
1178
1177
  if (target2.token) headers.authorization = `Bearer ${target2.token}`;
1179
1178
  if (opts.contentType) headers["content-type"] = opts.contentType;
1180
1179
  try {
@@ -2833,8 +2832,8 @@ function nodeFlips(node2) {
2833
2832
  function localMatrix(node2, ignoreFlips = false, shiftX = 0, shiftY = 0) {
2834
2833
  const w = node2.width, h = node2.height;
2835
2834
  const ax = restValue(node2, "anchorX"), ay = restValue(node2, "anchorY");
2836
- const rad2 = (node2.rotation || 0) * Math.PI / 180;
2837
- 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;
2838
2837
  const sx = restValue(node2, "scaleX") * (!ignoreFlips && node2.flipHorizontal ? -1 : 1);
2839
2838
  const sy = restValue(node2, "scaleY") * (!ignoreFlips && node2.flipVertical ? -1 : 1);
2840
2839
  const px5 = node2.x + ax * w + restValue(node2, "translateX");
@@ -7973,6 +7972,7 @@ function updateConnectors(document2, movedNodeIds) {
7973
7972
  var ZERO_TRANSFORM, ROOT, resolverCache, OBSTACLE_TYPES, connectorIdCache;
7974
7973
  var init_scene_graph = __esm({
7975
7974
  "lib/document/scene-graph.ts"() {
7975
+ "use strict";
7976
7976
  init_dist_node();
7977
7977
  init_effects();
7978
7978
  init_variables();
@@ -32029,6 +32029,9 @@ var init_en2 = __esm({
32029
32029
  "command:show.setAdvance": "Set how the show advances",
32030
32030
  "command:site.setBreakpoints": "Breakpoints",
32031
32031
  "command:site.setBreakpoints#defaults": "Reset breakpoints to Desktop, Tablet and Phone",
32032
+ "command:site.setGpuTransitions": "Draw 3D transitions with WebGPU",
32033
+ "command:site.setGpuTransitions#off": "Draw 3D transitions in CSS only",
32034
+ "command:site.setGpuTransitions#on": "Draw 3D transitions with WebGPU",
32032
32035
  "command:site.setRoute": "Page address",
32033
32036
  "command:text.detach": "Detach text from path or shape",
32034
32037
  "command:text.flowIntoShape": "Flow text into shape",
@@ -34250,6 +34253,7 @@ var init_en2 = __esm({
34250
34253
  "prototypePanel.pagePrototypeSettings": "Page Prototype Settings",
34251
34254
  "prototypePanel.pickCollection": "\u2014 Pick collection \u2014",
34252
34255
  "prototypePanel.pickVariable": "\u2014 Pick variable \u2014",
34256
+ "prototypePanel.picture": "Picture",
34253
34257
  "prototypePanel.pixel7": "Pixel 7",
34254
34258
  "prototypePanel.press": "Press",
34255
34259
  "prototypePanel.previousMarker": "Previous marker",
@@ -35174,6 +35178,43 @@ var init_en2 = __esm({
35174
35178
  "topBar.webPreview": "Web preview",
35175
35179
  "topBar.zoomToFit": "Zoom to fit",
35176
35180
  "topBar.zoomToFrame": "Zoom to frame",
35181
+ "transition:CAROUSEL_FROM_LEFT": "Carousel \u2190 left",
35182
+ "transition:CAROUSEL_FROM_RIGHT": "Carousel \u2192 right",
35183
+ "transition:CIRCLE_WIPE": "Circle wipe",
35184
+ "transition:CUBE_FROM_BOTTOM": "Cube \u2193 bottom",
35185
+ "transition:CUBE_FROM_LEFT": "Cube \u2190 left",
35186
+ "transition:CUBE_FROM_RIGHT": "Cube \u2192 right",
35187
+ "transition:CUBE_FROM_TOP": "Cube \u2191 top",
35188
+ "transition:CUT": "Cut",
35189
+ "transition:DEPTH_PULL": "Depth pull",
35190
+ "transition:DEPTH_PUSH": "Depth push",
35191
+ "transition:DISSOLVE": "Dissolve",
35192
+ "transition:FLIP_HORIZONTAL": "Flip \u2194",
35193
+ "transition:FLIP_VERTICAL": "Flip \u2195",
35194
+ "transition:INSTANT": "Instant",
35195
+ "transition:IRIS": "Iris",
35196
+ "transition:MOVE_OUT_TO_BOTTOM": "Move out \u2193 bottom",
35197
+ "transition:MOVE_OUT_TO_LEFT": "Move out \u2190 left",
35198
+ "transition:MOVE_OUT_TO_RIGHT": "Move out \u2192 right",
35199
+ "transition:MOVE_OUT_TO_TOP": "Move out \u2191 top",
35200
+ "transition:PUSH_FROM_BOTTOM": "Push \u2193 bottom",
35201
+ "transition:PUSH_FROM_LEFT": "Push \u2190 left",
35202
+ "transition:PUSH_FROM_RIGHT": "Push \u2192 right",
35203
+ "transition:PUSH_FROM_TOP": "Push \u2191 top",
35204
+ "transition:SLIDE_FROM_BOTTOM": "Slide in \u2193 bottom",
35205
+ "transition:SLIDE_FROM_LEFT": "Slide in \u2190 left",
35206
+ "transition:SLIDE_FROM_RIGHT": "Slide in \u2192 right",
35207
+ "transition:SLIDE_FROM_TOP": "Slide in \u2191 top",
35208
+ "transition:SMART_ANIMATE": "Smart animate",
35209
+ "transition:STACK_IN": "Stack in",
35210
+ "transition:STACK_OUT": "Stack out",
35211
+ "transition:SWING_CLOSE": "Swing close",
35212
+ "transition:SWING_OPEN": "Swing open",
35213
+ "transition:WHIP_LEFT": "Whip pan \u2190 left",
35214
+ "transition:WHIP_RIGHT": "Whip pan \u2192 right",
35215
+ "transition:ZOOM_THROUGH": "Zoom through",
35216
+ "transitions.group3d": "3D",
35217
+ "transitions.groupFlat": "Flat",
35177
35218
  "transportBar.aMotionComponentEveryInstance": "{frameName}: a motion component \u2014 every instance plays this timeline",
35178
35219
  "transportBar.animateTheSelectedLayersKeyframe": "Animate the selected layers: keyframe, or a preset",
35179
35220
  "transportBar.backToTheKeyframes": "Back to the keyframes",
@@ -85937,6 +85978,7 @@ function repairDocumentPaints(doc2) {
85937
85978
  var broken;
85938
85979
  var init_paint_repair = __esm({
85939
85980
  "lib/document/paint-repair.ts"() {
85981
+ "use strict";
85940
85982
  init_shader_graph();
85941
85983
  broken = (p2) => {
85942
85984
  if (!p2 || typeof p2 !== "object") return false;
@@ -87161,7 +87203,6 @@ function relinkCopies(doc2, copies) {
87161
87203
  var TEXT_PATH_SOURCE_TYPES, isPathSource;
87162
87204
  var init_text_links = __esm({
87163
87205
  "lib/document/text-links.ts"() {
87164
- "use strict";
87165
87206
  init_transform();
87166
87207
  TEXT_PATH_SOURCE_TYPES = ["VECTOR", "ELLIPSE", "RECTANGLE", "POLYGON", "STAR", "LINE", "ARROW", "FRAME"];
87167
87208
  isPathSource = (n) => !!n && TEXT_PATH_SOURCE_TYPES.includes(n.type);
@@ -87522,7 +87563,7 @@ function applyAutoLayout(doc2) {
87522
87563
  let rowSizes = frame2.layoutGridRowSizes || [];
87523
87564
  if (rows === "AUTO") {
87524
87565
  actualRows = Math.max(1, Math.ceil(childIds.length / actualCols));
87525
- rowSizes = Array.from({ length: actualRows }).map(() => ({ sizing: "FIXED", value: String(minRowH) }));
87566
+ rowSizes = Array.from({ length: actualRows }).map(() => ({ sizing: "HUG", value: "113", min: minRowH }));
87526
87567
  } else {
87527
87568
  actualRows = Math.max(1, rows);
87528
87569
  if (rowSizes.length !== actualRows) {
@@ -87548,7 +87589,7 @@ function applyAutoLayout(doc2) {
87548
87589
  let sumFixedRows = 0;
87549
87590
  rowSizes.forEach((s, r) => {
87550
87591
  if (s.sizing === "FIXED") sumFixedRows += parseFloat(s.value) || 0;
87551
- else if (s.sizing === "HUG") sumFixedRows += rowMaxHugs[r];
87592
+ else if (s.sizing === "HUG") sumFixedRows += Math.max(s.min ?? 0, rowMaxHugs[r]);
87552
87593
  });
87553
87594
  intrinsicW = sumFixedCols + Math.max(0, actualCols - 1) * itemSpacing + paddingX;
87554
87595
  intrinsicH = sumFixedRows + Math.max(0, actualRows - 1) * counterSpacing + paddingY;
@@ -87659,7 +87700,7 @@ function applyAutoLayout(doc2) {
87659
87700
  let rowSizes = frame2.layoutGridRowSizes || [];
87660
87701
  if (rows === "AUTO") {
87661
87702
  actualRows = Math.max(1, Math.ceil(childIds.length / actualCols));
87662
- rowSizes = Array.from({ length: actualRows }).map(() => ({ sizing: "HUG", value: "113" }));
87703
+ rowSizes = Array.from({ length: actualRows }).map(() => ({ sizing: "HUG", value: "113", min: minRowH }));
87663
87704
  } else {
87664
87705
  actualRows = Math.max(1, rows);
87665
87706
  if (rowSizes.length !== actualRows) {
@@ -87695,14 +87736,14 @@ function applyAutoLayout(doc2) {
87695
87736
  let totalRowFr = 0;
87696
87737
  rowSizes.forEach((s, r) => {
87697
87738
  if (s.sizing === "FIXED") fixedRowH += parseFloat(s.value) || 0;
87698
- else if (s.sizing === "HUG") fixedRowH += rowMaxHugs[r];
87739
+ else if (s.sizing === "HUG") fixedRowH += Math.max(s.min ?? 0, rowMaxHugs[r]);
87699
87740
  else if (s.sizing === "FILL") totalRowFr += parseFloat(s.value) || 1;
87700
87741
  });
87701
87742
  const availRowH = Math.max(0, frame2.height - paddingY - Math.max(0, actualRows - 1) * counterSpacing - fixedRowH);
87702
87743
  const rowH = new Array(actualRows).fill(0);
87703
87744
  rowSizes.forEach((s, r) => {
87704
87745
  if (s.sizing === "FIXED") rowH[r] = parseFloat(s.value) || 0;
87705
- else if (s.sizing === "HUG") rowH[r] = rowMaxHugs[r];
87746
+ else if (s.sizing === "HUG") rowH[r] = Math.max(s.min ?? 0, rowMaxHugs[r]);
87706
87747
  else if (s.sizing === "FILL") rowH[r] = totalRowFr > 0 ? availRowH * ((parseFloat(s.value) || 1) / totalRowFr) : 0;
87707
87748
  });
87708
87749
  const colX = new Array(actualCols).fill(0);
@@ -87873,7 +87914,6 @@ function isAutoLayout(node2) {
87873
87914
  }
87874
87915
  var init_auto_layout = __esm({
87875
87916
  "lib/document/auto-layout.ts"() {
87876
- "use strict";
87877
87917
  init_instance_layout();
87878
87918
  setLayoutEngine(applyAutoLayout);
87879
87919
  }
@@ -89180,6 +89220,83 @@ var init_keys = __esm({
89180
89220
  });
89181
89221
 
89182
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
+ }
89183
89300
  function scaledAbout(m, k2, cx, cy) {
89184
89301
  return k2 === 1 ? m : multiply([k2, 0, 0, k2, cx - k2 * cx, cy - k2 * cy], m);
89185
89302
  }
@@ -89194,6 +89311,16 @@ function coverRadius(stage, c2) {
89194
89311
  }
89195
89312
  function transitionRoots(type, progress2, a, b, stage, params2) {
89196
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
+ }
89197
89324
  switch (type) {
89198
89325
  case "INSTANT":
89199
89326
  case "CUT":
@@ -89249,9 +89376,11 @@ function transitionRoots(type, progress2, a, b, stage, params2) {
89249
89376
  const outScale = 1 + (ZOOM_OUT_SCALE - 1) * p2;
89250
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)];
89251
89378
  }
89379
+ default:
89380
+ return [root(a, a.base, 1 - p2), root(b, b.base, p2)];
89252
89381
  }
89253
89382
  }
89254
- 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;
89255
89384
  var init_transitions = __esm({
89256
89385
  "lib/motion/transitions.ts"() {
89257
89386
  "use strict";
@@ -89277,8 +89406,23 @@ var init_transitions = __esm({
89277
89406
  "IRIS",
89278
89407
  "ZOOM_THROUGH",
89279
89408
  "WHIP_LEFT",
89280
- "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"
89281
89424
  ];
89425
+ TRANSITION_3D_TYPES = TRANSITION_TYPES.slice(TRANSITION_TYPES.indexOf("CUBE_FROM_LEFT"));
89282
89426
  PROTOTYPE_TRANSITION_TYPES = TRANSITION_TYPES.filter((t3) => t3 !== "CUT" && t3 !== "WHIP_LEFT" && t3 !== "WHIP_RIGHT");
89283
89427
  SCENE_TRANSITION_TYPES = TRANSITION_TYPES.filter((t3) => t3 !== "SMART_ANIMATE" && t3 !== "INSTANT");
89284
89428
  isCut = (type) => type === "INSTANT" || type === "CUT";
@@ -89294,16 +89438,52 @@ var init_transitions = __esm({
89294
89438
  CIRCLE_WIPE: "IRIS",
89295
89439
  IRIS: "CIRCLE_WIPE",
89296
89440
  WHIP_LEFT: "WHIP_RIGHT",
89297
- 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"
89298
89454
  };
89299
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);
89300
89480
  ZOOM_OUT_SCALE = 2.5;
89301
89481
  ZOOM_IN_SCALE = 0.85;
89302
89482
  WHIP_SMEAR = 0.22;
89303
89483
  whipSmear = (p2, width) => WHIP_SMEAR * width * 4 * p2 * (1 - p2);
89304
89484
  root = (side, matrix = side.base, opacity = 1) => ({ rootId: side.id, matrix, opacity });
89305
89485
  shifted = (side, dx, dy) => dx || dy ? multiply(translation(dx, dy), side.base) : side.base;
89306
- 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);
89307
89487
  }
89308
89488
  });
89309
89489
 
@@ -90678,7 +90858,6 @@ function layerInputPatch(node2, name2, path) {
90678
90858
  var NO_RUNTIME, MAX_DEPTH, freshIndex, indexOf, isComponentLike, selfStarting, startedAt, endMemo, HOST_OWNS, rootTracksMemo, layerMemo, idle;
90679
90859
  var init_instances2 = __esm({
90680
90860
  "lib/motion/instances.ts"() {
90681
- "use strict";
90682
90861
  init_node_delta();
90683
90862
  init_instances();
90684
90863
  init_scene_graph();
@@ -90950,7 +91129,6 @@ function repairStateMachine(raw, markerIds, hasNode) {
90950
91129
  var STATE_MACHINE_INPUT_TYPES, STATE_MACHINE_GUARD_OPS, STATE_MACHINE_ACTION_TYPES, STATE_MACHINE_LISTENER_TYPES, isKeyListener, ANY_STATE, MAX_STEPS2, byId2, sortedValues, machineOf, startValue, isObj3, finite4, isValue, goodId;
90951
91130
  var init_state_machine = __esm({
90952
91131
  "lib/motion/state-machine.ts"() {
90953
- "use strict";
90954
91132
  STATE_MACHINE_INPUT_TYPES = ["boolean", "number", "string", "event"];
90955
91133
  STATE_MACHINE_GUARD_OPS = ["eq", "neq", "gt", "gte", "lt", "lte"];
90956
91134
  STATE_MACHINE_ACTION_TYPES = ["set", "toggle", "increment", "decrement", "fire", "reset"];
@@ -235131,7 +235309,6 @@ function repairCompositions(comps, nodes) {
235131
235309
  var isObj5, finite6, optFinite, isVec2, TIMELINE_COLOR_IDS, TIMELINE_COLORS, UNITS, ORDERS, PROP_KEYS, ANIMATOR_ID, MOTION_TYPES, TRANSITIONS, isFraction, MEDIA_HASH;
235132
235310
  var init_invariants = __esm({
235133
235311
  "lib/motion/invariants.ts"() {
235134
- "use strict";
235135
235312
  init_easing();
235136
235313
  init_properties();
235137
235314
  init_markers();
@@ -239656,7 +239833,6 @@ function resizeWindow(doc2, target2, rect) {
239656
239833
  }
239657
239834
  var init_crop = __esm({
239658
239835
  "lib/editor/crop.ts"() {
239659
- "use strict";
239660
239836
  init_dist_node();
239661
239837
  init_scene_graph();
239662
239838
  init_photo_frames();
@@ -243179,7 +243355,6 @@ fn shade(uv: vec2<f32>, res: vec2<f32>, tm: f32) -> vec4<f32> {
243179
243355
  var SHADER_PRESETS, shaderPreset, legacyPresetOf, DEFAULT_SHADER_PRESET, DEFAULT_TEXTURE_PARAMS, f, vec4, NOISE_LIB;
243180
243356
  var init_shader_presets = __esm({
243181
243357
  "lib/engine/shader-presets.ts"() {
243182
- "use strict";
243183
243358
  init_shader_graph();
243184
243359
  init_shader_graph_presets();
243185
243360
  init_shader_presets_legacy();
@@ -244387,11 +244562,11 @@ function buildStamp2(type) {
244387
244562
  const a = h2(i2, 1, 5) * Math.PI * 2;
244388
244563
  const rr = Math.pow(h2(i2, 2, 9), 0.7) * R * 0.92;
244389
244564
  const px5 = cx + Math.cos(a) * rr, py = cy + Math.sin(a) * rr;
244390
- const rad2 = 1 + h2(i2, 3, 13) * 5;
244565
+ const rad3 = 1 + h2(i2, 3, 13) * 5;
244391
244566
  const peak = 0.35 + h2(i2, 4, 17) * 0.6;
244392
- for (let y = Math.max(0, Math.floor(py - rad2)); y <= Math.min(SIZE - 1, Math.ceil(py + rad2)); y++) {
244393
- for (let x2 = Math.max(0, Math.floor(px5 - rad2)); x2 <= Math.min(SIZE - 1, Math.ceil(px5 + rad2)); x2++) {
244394
- 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;
244395
244570
  if (d >= 1) continue;
244396
244571
  const src = peak * (1 - d);
244397
244572
  const k2 = y * SIZE + x2;
@@ -246326,14 +246501,14 @@ function liveStaggerParent(nodes, ids2) {
246326
246501
  if (!parent || parent.type === "PAGE" || parent.motion?.stagger) return null;
246327
246502
  const set3 = new Set(ids2);
246328
246503
  if (set3.size !== parent.childIds.length || !parent.childIds.every((c2) => set3.has(c2))) return null;
246329
- const still = (id3) => {
246504
+ const still2 = (id3) => {
246330
246505
  const n = nodes[id3];
246331
246506
  if (!n) return true;
246332
246507
  const m = n.motion;
246333
246508
  if (m && (Object.keys(m.tracks).length || m.timeOffset || m.span || m.stagger)) return false;
246334
- return (n.childIds ?? []).every(still);
246509
+ return (n.childIds ?? []).every(still2);
246335
246510
  };
246336
- return ids2.every(still) ? parent.id : null;
246511
+ return ids2.every(still2) ? parent.id : null;
246337
246512
  }
246338
246513
  function staggerDocument(doc2, ids2, opts) {
246339
246514
  const present2 = ids2.filter((id3) => doc2.nodes[id3]);
@@ -247273,11 +247448,11 @@ function editSelected(nodes, sel, change2) {
247273
247448
  for (const [path, ids2] of byPath) {
247274
247449
  const track2 = motion?.tracks[path];
247275
247450
  if (!track2) continue;
247276
- const moved3 = [], still = [];
247451
+ const moved3 = [], still2 = [];
247277
247452
  let touched = false;
247278
247453
  for (const k2 of track2.keys) {
247279
247454
  if (!ids2.has(k2.id)) {
247280
- still.push(k2);
247455
+ still2.push(k2);
247281
247456
  continue;
247282
247457
  }
247283
247458
  const next2 = change2(k2, nodeId2, path);
@@ -247295,7 +247470,7 @@ function editSelected(nodes, sel, change2) {
247295
247470
  keys3.push(k2);
247296
247471
  }
247297
247472
  }
247298
- 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);
247299
247474
  keys3.sort((a, b) => a.t - b.t);
247300
247475
  motion = withTrack(motion, path, keys3.length || track2.modifiers?.length ? { ...track2, keys: keys3 } : null);
247301
247476
  changed = true;
@@ -248385,6 +248560,15 @@ function repeatRecords(doc2, repeat, under) {
248385
248560
  const from2 = Math.max(0, repeat.offset ?? 0);
248386
248561
  return list2.slice(from2, repeat.limit !== void 0 ? from2 + Math.max(0, repeat.limit) : void 0);
248387
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
+ }
248388
248572
  function recordSlugs(doc2, collectionId) {
248389
248573
  const c2 = doc2.collections?.[collectionId];
248390
248574
  const out = /* @__PURE__ */ new Map();
@@ -248497,7 +248681,7 @@ function removeRecords(doc2, ids2) {
248497
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]));
248498
248682
  return { ...doc2, records, collections };
248499
248683
  }
248500
- 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;
248501
248685
  var init_collections = __esm({
248502
248686
  "lib/document/collections.ts"() {
248503
248687
  "use strict";
@@ -248527,6 +248711,10 @@ var init_collections = __esm({
248527
248711
  const at3 = id3.indexOf("~");
248528
248712
  return at3 < 0 ? id3 : id3.slice(0, at3);
248529
248713
  };
248714
+ copySuffix = (id3) => {
248715
+ const at3 = id3.indexOf("~");
248716
+ return at3 < 0 ? "" : id3.slice(at3);
248717
+ };
248530
248718
  copyRecord = (id3) => {
248531
248719
  const at3 = id3.lastIndexOf("~");
248532
248720
  return at3 < 0 ? null : id3.slice(at3 + 1);
@@ -259508,11 +259696,12 @@ function templateFromDocument(doc2, meta3, o = {}) {
259508
259696
  for (const v of variants) for (const id3 of v.rootIds) nodes[id3] = { ...nodes[id3], parentId: null };
259509
259697
  const deps = collectStyleDependencies(doc2, nodes);
259510
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.
259511
259700
  mode: "document",
259512
259701
  nodes,
259513
259702
  variants,
259514
259703
  pages: pages2,
259515
- media: mediaHashes({ nodes, compositions: doc2.compositions }),
259704
+ media: mediaHashes({ nodes, compositions: doc2.compositions, records: doc2.records }),
259516
259705
  styles: { ...deps.styles, ...doc2.styles },
259517
259706
  variables: { ...deps.variables, ...doc2.variables },
259518
259707
  variableCollections: { ...deps.variableCollections, ...doc2.variableCollections },
@@ -296028,8 +296217,8 @@ async function syncTemplatePreview(row2, rootId, doc2) {
296028
296217
  const path = (file2, q) => `/api/templates/${encodeURIComponent(row2.id)}/preview/${file2}${q ? `?${new URLSearchParams(q)}` : ""}`;
296029
296218
  const put3 = (file2, bytes2, type, q) => api(path(file2, q), { method: "PUT", body: new Blob([bytes2], { type }) });
296030
296219
  let preview = row2.preview;
296031
- const still = await renderTemplateDetail2(root2, doc2);
296032
- 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) }));
296033
296222
  const loop = await renderTemplatePreview2(renderer, doc2, rootId);
296034
296223
  if (loop) ({ preview } = await put3("anim", loop.bytes, loop.type, { w: String(loop.width), h: String(loop.height), ms: String(loop.durationMs) }));
296035
296224
  else if (preview?.anim) {
@@ -296197,6 +296386,7 @@ async function createFreshFileOrExplain(place3 = {}, seed2 = {}) {
296197
296386
  var online, goesLocal;
296198
296387
  var init_new_file = __esm({
296199
296388
  "lib/client/cloud/new-file.ts"() {
296389
+ "use strict";
296200
296390
  init_scene_graph();
296201
296391
  init_print_pages();
296202
296392
  init_page_presets();
@@ -296704,6 +296894,7 @@ function startCloudSync() {
296704
296894
  var status, readOnlyDoc, activeLink, statusListeners, notice, urlArmed, opening, syncStatus, canEdit, uploaded, MEDIA_UPLOAD_PARALLEL, pushTimer, pushing, dirty, pendingMedia, collab, collabSession, collabAnonymous, uploadedThumbs, thumbCheckedAt, THUMB_EVERY_MS, putThumbnail, openingFiles, mediaHealed, started;
296705
296895
  var init_sync2 = __esm({
296706
296896
  "lib/client/cloud/sync.ts"() {
296897
+ "use strict";
296707
296898
  init_paint_repair();
296708
296899
  init_migrate();
296709
296900
  init_view();
@@ -296950,13 +297141,18 @@ var init_review_kits = __esm({
296950
297141
 
296951
297142
  // lib/templates/text-measurer.ts
296952
297143
  function shownNode(doc2, n) {
296953
- 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;
296954
297148
  }
296955
297149
  var templateTextMeasurer;
296956
297150
  var init_text_measurer = __esm({
296957
297151
  "lib/templates/text-measurer.ts"() {
296958
297152
  "use strict";
296959
297153
  init_variables();
297154
+ init_collections();
297155
+ init_expressions2();
296960
297156
  init_measure();
296961
297157
  templateTextMeasurer = (node2) => {
296962
297158
  const characters = casedText(node2.characters ?? "", node2.textCase);
@@ -302317,6 +302513,9 @@ var init_export = __esm({
302317
302513
  // lib/ai/reference-images.ts
302318
302514
  var reference_images_exports = {};
302319
302515
  __export(reference_images_exports, {
302516
+ FIT_QUALITIES: () => FIT_QUALITIES,
302517
+ FIT_SCALES: () => FIT_SCALES,
302518
+ fitReference: () => fitReference,
302320
302519
  referenceGroups: () => referenceGroups,
302321
302520
  referenceScale: () => referenceScale,
302322
302521
  selectionReferenceImages: () => selectionReferenceImages,
@@ -302339,6 +302538,16 @@ function withinBudget(refs, opts = {}) {
302339
302538
  }
302340
302539
  return kept;
302341
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
+ }
302342
302551
  function referenceGroups(ids2, max3 = AI_LIMITS.maxReferenceImages) {
302343
302552
  if (!ids2.length) return [];
302344
302553
  return ids2.length <= max3 ? ids2.map((id3) => [id3]) : [[...ids2]];
@@ -302357,22 +302566,30 @@ async function selectionReferenceImages(doc2, selection, opts = {}) {
302357
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];
302358
302567
  for (const bounds2 of regions) {
302359
302568
  if (out.length >= max3) break;
302360
- const image = await renderer.exportRegion(members2, bounds2, referenceScale(bounds2, opts.maxEdge), doc2, doc2.styles, void 0, true);
302361
- if (!image) continue;
302362
- const blob = await encodeImageData(image, opts.format ?? "PNG", 0.86);
302363
- if (!blob) continue;
302364
- 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);
302365
302580
  }
302366
302581
  }
302367
302582
  return withinBudget(out, { max: max3 });
302368
302583
  }
302369
- var blobToDataUrl;
302584
+ var FIT_QUALITIES, FIT_SCALES, blobToDataUrl;
302370
302585
  var init_reference_images = __esm({
302371
302586
  "lib/ai/reference-images.ts"() {
302372
302587
  init_export();
302373
302588
  init_selection_bounds();
302374
302589
  init_renderer_registry();
302375
302590
  init_limits();
302591
+ FIT_QUALITIES = [0.86, 0.7, 0.5];
302592
+ FIT_SCALES = [1, 0.75, 0.55, 0.4];
302376
302593
  blobToDataUrl = (blob) => new Promise((resolve6, reject) => {
302377
302594
  const reader = new FileReader();
302378
302595
  reader.onload = () => resolve6(String(reader.result));
@@ -303926,7 +304143,7 @@ function parseTransform(t3) {
303926
304143
  let x2;
303927
304144
  while (x2 = re.exec(t3)) {
303928
304145
  const v = nums(x2[2]);
303929
- const rad2 = (deg) => deg * Math.PI / 180;
304146
+ const rad3 = (deg) => deg * Math.PI / 180;
303930
304147
  let n = I;
303931
304148
  switch (x2[1].toLowerCase()) {
303932
304149
  case "matrix":
@@ -303939,16 +304156,16 @@ function parseTransform(t3) {
303939
304156
  n = [v[0] ?? 1, 0, 0, v[1] ?? v[0] ?? 1, 0, 0];
303940
304157
  break;
303941
304158
  case "rotate": {
303942
- 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));
303943
304160
  n = [c2, s, -s, c2, 0, 0];
303944
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]]);
303945
304162
  break;
303946
304163
  }
303947
304164
  case "skewx":
303948
- 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];
303949
304166
  break;
303950
304167
  case "skewy":
303951
- 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];
303952
304169
  break;
303953
304170
  }
303954
304171
  m = mul2(m, n);
@@ -308667,7 +308884,8 @@ async function exportSlidesToPPTX(renderer, slides, docIn, styles) {
308667
308884
  function transitionXml(t3) {
308668
308885
  if (!t3 || t3.type === "INSTANT") return "";
308669
308886
  const dur = Math.max(1, Math.round(t3.duration));
308670
- 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/>";
308671
308889
  return `<p:transition spd="${dur > 900 ? "slow" : dur > 400 ? "med" : "fast"}">${inner}</p:transition>`;
308672
308890
  }
308673
308891
  var EMU, emu, esc2, hex9, alphaTag, solid3, NS, REL, xfrm, needsPicture, xmlHead, relsXml, themeXml, masterXml, layoutXml, notesMasterXml, notesSlideXml;
@@ -308681,6 +308899,7 @@ var init_pptx = __esm({
308681
308899
  init_native_registry();
308682
308900
  init_png();
308683
308901
  init_export_fills();
308902
+ init_transitions();
308684
308903
  init_page_tokens();
308685
308904
  init_text_styles();
308686
308905
  init_effects();
@@ -308995,10 +309214,10 @@ function emitChannel(ch, grid, scalar = false, stats) {
308995
309214
  const eps = ch.eps ?? 1e-3;
308996
309215
  const fill = filled(ch.samples);
308997
309216
  if (!fill) return staticProp([0], scalar);
308998
- const still = constantOf({ ...ch, eps: ch.eps ?? 1e-4 });
308999
- if (still) {
309217
+ const still2 = constantOf({ ...ch, eps: ch.eps ?? 1e-4 });
309218
+ if (still2) {
309000
309219
  if (stats) stats.still++;
309001
- return staticProp(still, scalar);
309220
+ return staticProp(still2, scalar);
309002
309221
  }
309003
309222
  const present2 = ch.samples.map((s) => !!s);
309004
309223
  if (ch.exact && !ch.hold) {
@@ -310107,7 +310326,7 @@ var init_build = __esm({
310107
310326
  const nodeId2 = node0?.id;
310108
310327
  const geometry = [];
310109
310328
  if (rectLike) {
310110
- const rad2 = (n) => {
310329
+ const rad3 = (n) => {
310111
310330
  const cr = n?.cornerRadius;
310112
310331
  return Array.isArray(cr) ? num8(cr[0]) : num8(cr);
310113
310332
  };
@@ -310117,7 +310336,7 @@ var init_build = __esm({
310117
310336
  d: 1,
310118
310337
  p: this.prop(frames.map((p2, f2) => p2 ? [ownerNodes[f2].width / 2, ownerNodes[f2].height / 2] : void 0), null, false, 1e-3),
310119
310338
  s: this.prop(frames.map((p2, f2) => p2 ? [ownerNodes[f2].width, ownerNodes[f2].height] : void 0), null, false, 1e-3),
310120
- 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)
310121
310340
  });
310122
310341
  } else if (ellipse) {
310123
310342
  geometry.push({
@@ -311587,12 +311806,12 @@ function staticSiteFiles(site, scripts, opts = {}) {
311587
311806
  const lang = opts.lang ?? "en";
311588
311807
  const files = externalizeBitmaps(site);
311589
311808
  const taken = /* @__PURE__ */ new Set();
311590
- const still = visitorCollections(site.program.document.collections).reduce((s, c2) => withVisitorRecords(s, c2.id, []), site);
311591
- 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) {
311592
311811
  const path = page.notFound ? "404.html" : routeFile(page.route);
311593
311812
  if (taken.has(path)) continue;
311594
311813
  taken.add(path);
311595
- files.push({ path, content: pageHTML(still, page, lang, !!page.notFound) });
311814
+ files.push({ path, content: pageHTML(still2, page, lang, !!page.notFound) });
311596
311815
  }
311597
311816
  files.push({ path: "site.json", content: JSON.stringify(site) });
311598
311817
  files.push({ path: "pc/site.js", content: scripts.site });
@@ -312569,7 +312788,7 @@ var init_package = __esm({
312569
312788
  "packages/runtime/package.json"() {
312570
312789
  package_default = {
312571
312790
  name: "@popcraft/runtime",
312572
- version: "0.7.0",
312791
+ version: "0.8.0",
312573
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.",
312574
312793
  license: "MIT",
312575
312794
  homepage: "https://popcraft.app/docs/exporting/nextjs",
@@ -313153,6 +313372,1251 @@ var init_next = __esm({
313153
313372
  }
313154
313373
  });
313155
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
+
313156
314620
  // lib/code/cdn.ts
313157
314621
  var CDN;
313158
314622
  var init_cdn = __esm({
@@ -336876,7 +338340,7 @@ async function withSiteCode(site, doc2) {
336876
338340
  return { ...site, code: { modules, ...imports3.size ? { packages: { versions, imports: [...imports3].sort() } } : {} } };
336877
338341
  }
336878
338342
  var codeNodes;
336879
- var init_site = __esm({
338343
+ var init_site2 = __esm({
336880
338344
  "lib/code/site.ts"() {
336881
338345
  "use strict";
336882
338346
  codeNodes = (n, out = []) => {
@@ -336927,44 +338391,6 @@ var init_hash = __esm({
336927
338391
  }
336928
338392
  });
336929
338393
 
336930
- // lib/code/props.ts
336931
- function propName(key5) {
336932
- const words = key5.split("#")[0].trim().split(/[^A-Za-z0-9]+/).filter(Boolean);
336933
- const name2 = words.map((w, i2) => i2 === 0 ? w.charAt(0).toLowerCase() + w.slice(1) : w.charAt(0).toUpperCase() + w.slice(1)).join("");
336934
- return /^[A-Za-z_$]/.test(name2) ? name2 : `p${name2}`;
336935
- }
336936
- function componentOf(nodes, node2) {
336937
- const c2 = node2.type === "COMPONENT" ? node2 : node2.type === "INSTANCE" ? nodes[node2.mainComponentId] : void 0;
336938
- return c2?.type === "COMPONENT" ? c2 : void 0;
336939
- }
336940
- function codeOf(nodes, node2) {
336941
- if (node2.type !== "COMPONENT" && node2.type !== "INSTANCE") return null;
336942
- return componentOf(nodes, node2)?.code ?? null;
336943
- }
336944
- function codeProps(nodes, node2) {
336945
- const component = componentOf(nodes, node2);
336946
- const out = {};
336947
- if (!component) return out;
336948
- const set3 = component.parentId ? nodes[component.parentId] : void 0;
336949
- const defs = (set3?.type === "COMPONENT_SET" ? set3.componentPropertyDefinitions : component.componentPropertyDefinitions) ?? {};
336950
- const given = node2.type === "INSTANCE" ? node2.componentProperties ?? {} : {};
336951
- for (const key5 of Object.keys(defs).sort()) {
336952
- const v = value(key5 in given ? given[key5] : defs[key5].defaultValue);
336953
- if (v !== void 0) out[propName(key5)] = v;
336954
- }
336955
- out.width = Math.round(node2.width);
336956
- out.height = Math.round(node2.height);
336957
- return out;
336958
- }
336959
- var value;
336960
- var init_props = __esm({
336961
- "lib/code/props.ts"() {
336962
- "use strict";
336963
- init_color();
336964
- value = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" ? v : v && typeof v === "object" && "r" in v ? colorToHex8(v) : void 0;
336965
- }
336966
- });
336967
-
336968
338394
  // lib/code/snapshots.ts
336969
338395
  var init_snapshots = __esm({
336970
338396
  "lib/code/snapshots.ts"() {
@@ -337409,872 +338835,6 @@ ${indent}<img src="" width="${node2.width}" height="${node2.height}" alt="${esca
337409
338835
  }
337410
338836
  });
337411
338837
 
337412
- // lib/document/controls.ts
337413
- function fieldPart(nodes, id3) {
337414
- const n = nodes[id3];
337415
- if (!n) return null;
337416
- if (n.type === "TEXT") return id3;
337417
- for (const c2 of n.childIds ?? []) {
337418
- const hit = fieldPart(nodes, c2);
337419
- if (hit) return hit;
337420
- }
337421
- return null;
337422
- }
337423
- var cleanName2;
337424
- var init_controls = __esm({
337425
- "lib/document/controls.ts"() {
337426
- "use strict";
337427
- cleanName2 = (raw) => raw.trim().replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
337428
- }
337429
- });
337430
-
337431
- // lib/io/web/expressible.ts
337432
- function expressibility(node2, styles) {
337433
- const c2 = capability(node2, "css", styles);
337434
- return { css: c2.reason === "", reason: c2.reason, needsRaster: c2.verdict === "raster" };
337435
- }
337436
- var init_expressible = __esm({
337437
- "lib/io/web/expressible.ts"() {
337438
- "use strict";
337439
- init_capability();
337440
- }
337441
- });
337442
-
337443
- // lib/io/web/responsive.ts
337444
- function containerStyle(f2) {
337445
- const out = {};
337446
- if (isStack(f2) && f2.layoutWrap === "WRAP") {
337447
- out["flex-wrap"] = "wrap";
337448
- const cross2 = f2.counterAxisSpacing ?? f2.itemSpacing ?? 0;
337449
- const main2 = f2.itemSpacing ?? 0;
337450
- if (cross2 !== main2) out.gap = f2.layoutMode === "HORIZONTAL" ? `${cross2}px ${main2}px` : `${main2}px ${cross2}px`;
337451
- out["align-content"] = "flex-start";
337452
- }
337453
- if (isGrid(f2)) {
337454
- out.display = "grid";
337455
- const cols = f2.layoutGridColumns ?? "AUTO";
337456
- 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(" ");
337457
- const rows = f2.layoutGridRows ?? "AUTO";
337458
- if (rows === "AUTO") out["grid-auto-rows"] = `minmax(${f2.layoutGridMinRowHeight ?? 100}px, auto)`;
337459
- else out["grid-template-rows"] = Array.from({ length: Math.max(1, rows) }, (_, i2) => track(f2.layoutGridRowSizes?.[i2])).join(" ");
337460
- const colGap = f2.itemSpacing ?? 0, rowGap = f2.counterAxisSpacing ?? colGap;
337461
- out.gap = rowGap === colGap ? `${colGap}px` : `${rowGap}px ${colGap}px`;
337462
- if (f2.padding) {
337463
- out.padding = `${f2.padding.top}px ${f2.padding.right}px ${f2.padding.bottom}px ${f2.padding.left}px`;
337464
- if (f2.padding.top || f2.padding.right || f2.padding.bottom || f2.padding.left) out["box-sizing"] = "border-box";
337465
- }
337466
- }
337467
- const scroll = f2.overflowScrolling;
337468
- if (scroll && scroll !== "NONE") {
337469
- out["overflow-x"] = scroll === "HORIZONTAL" || scroll === "BOTH" ? "auto" : "hidden";
337470
- out["overflow-y"] = scroll === "VERTICAL" || scroll === "BOTH" ? "auto" : "hidden";
337471
- }
337472
- return out;
337473
- }
337474
- function flowChild(node2, parent) {
337475
- const style = { ...limits(node2) };
337476
- const h = node2.layoutSizingHorizontal ?? "FIXED", v = node2.layoutSizingVertical ?? "FIXED";
337477
- if (isGrid(parent)) {
337478
- if (h !== "FIXED") style.width = h === "FILL" ? null : "fit-content";
337479
- if (v !== "FIXED") style.height = null;
337480
- return { style };
337481
- }
337482
- if (h === "FIXED" && style["max-width"] === void 0) style["max-width"] = "100%";
337483
- const row2 = parent.layoutMode === "HORIZONTAL";
337484
- const main2 = row2 ? h : v, cross2 = row2 ? v : h;
337485
- const mainProp = row2 ? "width" : "height", crossProp = row2 ? "height" : "width";
337486
- if (main2 === "FILL") {
337487
- style[mainProp] = null;
337488
- style.flex = "1 1 0";
337489
- if (style[`min-${mainProp}`] === void 0) style[`min-${mainProp}`] = "0";
337490
- } else {
337491
- if (main2 === "HUG") style[mainProp] = null;
337492
- style["flex-shrink"] = "0";
337493
- }
337494
- if (cross2 === "FILL") {
337495
- style[crossProp] = null;
337496
- style["align-self"] = "stretch";
337497
- } else {
337498
- if (cross2 === "HUG") style[crossProp] = null;
337499
- if ((parent.counterAxisAlignItems ?? "MIN") === "MIN") style["align-self"] = "flex-start";
337500
- }
337501
- return { style };
337502
- }
337503
- function constrained(kind, pos, size6, parentSize, start2, end, sizeProp) {
337504
- const far = parentSize - pos - size6;
337505
- switch (kind) {
337506
- case "MAX":
337507
- return { place: { [end]: px4(far) }, style: {} };
337508
- case "STRETCH":
337509
- return { place: { [start2]: px4(pos), [end]: px4(far) }, style: { [sizeProp]: null } };
337510
- // Its centre keeps its distance from the parent's centre.
337511
- case "CENTER":
337512
- return { place: { [start2]: `calc(50% + ${px4(pos - parentSize / 2)})` }, style: {} };
337513
- case "SCALE":
337514
- return parentSize > 0 ? { place: { [start2]: pct2(pos / parentSize) }, style: { [sizeProp]: pct2(size6 / parentSize) } } : { place: { [start2]: px4(pos) }, style: {} };
337515
- default:
337516
- return { place: { [start2]: px4(pos) }, style: {} };
337517
- }
337518
- }
337519
- function placedChild(node2, parent) {
337520
- const c2 = node2.constraints ?? { horizontal: "MIN", vertical: "MIN" };
337521
- const x2 = constrained(c2.horizontal, node2.x, node2.width, parent.width, "left", "right", "width");
337522
- const y = constrained(c2.vertical, node2.y, node2.height, parent.height, "top", "bottom", "height");
337523
- return { style: { ...limits(node2), ...x2.style, ...y.style }, place: { position: "absolute", ...x2.place, ...y.place } };
337524
- }
337525
- function siteLayout(node2, parent, layout2) {
337526
- const own2 = node2.type === "FRAME" || node2.type === "COMPONENT" || node2.type === "INSTANCE" ? node2 : null;
337527
- if (!parent) {
337528
- const grows = !own2 || laysOut(own2) || own2.overflowScrolling === "NONE" || !own2.overflowScrolling;
337529
- return { style: { ...limits(node2), width: "100%", ...grows ? { height: null, "min-height": `max(${px4(node2.height)}, 100dvh)` } : {} }, place: { position: "relative" } };
337530
- }
337531
- const s = node2;
337532
- return layout2 && laysOut(layout2) && s.layoutPositioning !== "ABSOLUTE" ? flowChild(s, layout2) : placedChild(s, parent);
337533
- }
337534
- var px4, pct2, isStack, isGrid, laysOut, track, limits;
337535
- var init_responsive = __esm({
337536
- "lib/io/web/responsive.ts"() {
337537
- "use strict";
337538
- px4 = (v) => `${Math.round(v * 100) / 100}px`;
337539
- pct2 = (v) => `${Math.round(v * 1e4) / 100}%`;
337540
- isStack = (f2) => f2?.layoutMode === "HORIZONTAL" || f2?.layoutMode === "VERTICAL";
337541
- isGrid = (f2) => f2?.layoutMode === "GRID";
337542
- laysOut = (f2) => isStack(f2) || isGrid(f2);
337543
- track = (t3) => {
337544
- if (!t3 || t3.sizing === "FILL") return t3?.value && /fr$/.test(t3.value) ? t3.value : "1fr";
337545
- if (t3.sizing === "HUG") return "auto";
337546
- return /^[\d.]+$/.test(t3.value) ? `${t3.value}px` : t3.value;
337547
- };
337548
- limits = (n) => {
337549
- const out = {};
337550
- if (n.minWidth !== void 0) out["min-width"] = px4(n.minWidth);
337551
- if (n.maxWidth !== void 0) out["max-width"] = px4(n.maxWidth);
337552
- if (n.minHeight !== void 0) out["min-height"] = px4(n.minHeight);
337553
- if (n.maxHeight !== void 0) out["max-height"] = px4(n.maxHeight);
337554
- return out;
337555
- };
337556
- }
337557
- });
337558
-
337559
- // lib/io/web/richtext.ts
337560
- function runStyle(seg) {
337561
- const out = {};
337562
- if (seg.fontFamily) out["font-family"] = `"${seg.fontFamily}", system-ui, sans-serif`;
337563
- if (seg.fontSize) out["font-size"] = `${seg.fontSize}px`;
337564
- if (seg.fontWeight) out["font-weight"] = String(seg.fontWeight);
337565
- if (seg.fontStyle) out["font-style"] = seg.fontStyle;
337566
- if (seg.lineHeight !== void 0 && seg.lineHeight !== "AUTO") out["line-height"] = `${seg.lineHeight}px`;
337567
- if (seg.textDecoration === "UNDERLINE") out["text-decoration"] = "underline";
337568
- else if (seg.textDecoration === "STRIKETHROUGH") out["text-decoration"] = "line-through";
337569
- else if (seg.textDecoration === "NONE") out["text-decoration"] = "none";
337570
- if (seg.textCase === "UPPER") out["text-transform"] = "uppercase";
337571
- else if (seg.textCase === "LOWER") out["text-transform"] = "lowercase";
337572
- else if (seg.textCase === "TITLE") out["text-transform"] = "capitalize";
337573
- else if (seg.textCase === "ORIGINAL") out["text-transform"] = "none";
337574
- const solid4 = seg.fills?.find((f2) => f2.visible !== false && f2.type === "SOLID" && f2.color);
337575
- if (solid4?.color) out.color = toHex(solid4.color);
337576
- return out;
337577
- }
337578
- function textRuns(t3) {
337579
- const text = t3.characters ?? "";
337580
- const segs = [...t3.styledSegments ?? []].filter((s) => s.end > s.start).sort((a, b) => a.start - b.start);
337581
- if (!segs.length && !t3.link) return void 0;
337582
- const runs = [];
337583
- const push2 = (from2, to, seg) => {
337584
- if (to <= from2) return;
337585
- const link2 = seg?.link ?? t3.link;
337586
- runs.push({ text: text.slice(from2, to), style: seg ? runStyle(seg) : {}, ...link2 ? { link: link2 } : {} });
337587
- };
337588
- let at3 = 0;
337589
- for (const s of segs) {
337590
- const start2 = Math.max(at3, Math.min(text.length, s.start)), end = Math.min(text.length, s.end);
337591
- push2(at3, start2);
337592
- push2(start2, end, s);
337593
- at3 = Math.max(at3, end);
337594
- }
337595
- push2(at3, text.length);
337596
- return runs;
337597
- }
337598
- var init_richtext = __esm({
337599
- "lib/io/web/richtext.ts"() {
337600
- "use strict";
337601
- init_paint2();
337602
- }
337603
- });
337604
-
337605
- // lib/io/web/timeline.ts
337606
- function frameWebMotion(doc2, frameId, style) {
337607
- const nodes = doc2.nodes;
337608
- const frame2 = nodes[frameId];
337609
- if (!frame2 || !hasFrameMotion(nodes, frameId)) return null;
337610
- const len3 = timelineDuration(nodes, frameId);
337611
- if (!(len3 > 0)) return null;
337612
- const steps = Math.max(1, Math.ceil(len3 / 1e3 * SAMPLE_RATE));
337613
- const times2 = [];
337614
- const poses = [];
337615
- for (let i2 = 0; i2 <= steps; i2++) {
337616
- const t3 = len3 * i2 / steps;
337617
- times2.push(t3);
337618
- poses.push(evaluatePose(nodes, { kind: "frame", frameId }, t3).nodes);
337619
- }
337620
- const ids2 = /* @__PURE__ */ new Set();
337621
- for (const p2 of poses) for (const id3 in p2) if (id3 !== frameId && p2[id3] !== nodes[id3]) ids2.add(id3);
337622
- const loops = frameRunsOn(nodes, frameId);
337623
- const out = /* @__PURE__ */ new Map();
337624
- const tag = frameId.replace(/[^a-zA-Z0-9]/g, "").slice(-6);
337625
- let n = 0;
337626
- for (const id3 of ids2) {
337627
- const rest = id3.includes("::") ? resolveVirtualNode2(nodes, id3) : nodes[id3];
337628
- if (!rest || !underFrame(nodes, id3, frameId)) continue;
337629
- const frames = keyframesOf(times2, poses.map((p2) => declarationsOf(p2[id3] ?? rest, rest, style)), len3);
337630
- if (!frames) continue;
337631
- out.set(id3, {
337632
- name: `timeline-${tag}-${n++}`,
337633
- frames,
337634
- durationMs: Math.round(len3),
337635
- delayMs: 0,
337636
- iterations: loops ? "infinite" : 1,
337637
- direction: "normal",
337638
- fill: "both"
337639
- });
337640
- }
337641
- return out.size ? out : null;
337642
- }
337643
- function underFrame(nodes, id3, frameId) {
337644
- const real = id3.split("::")[0];
337645
- for (let n = nodes[real]; n; n = n.parentId ? nodes[n.parentId] : void 0) if (n.id === frameId) return true;
337646
- return false;
337647
- }
337648
- var init_timeline = __esm({
337649
- "lib/io/web/timeline.ts"() {
337650
- "use strict";
337651
- init_scene_graph();
337652
- init_pose();
337653
- init_instances2();
337654
- init_keyframes();
337655
- }
337656
- });
337657
-
337658
- // lib/io/web/interactive.ts
337659
- function subtreeIds(doc2, id3, out = /* @__PURE__ */ new Set()) {
337660
- if (out.has(id3)) return out;
337661
- const n = doc2.nodes[id3];
337662
- if (!n) return out;
337663
- out.add(id3);
337664
- if (n.type === "INSTANCE") subtreeIds(doc2, n.mainComponentId, out);
337665
- for (const c2 of n.childIds ?? []) subtreeIds(doc2, c2, out);
337666
- return out;
337667
- }
337668
- function flowScreens(doc2, startId) {
337669
- const start2 = doc2.nodes[startId];
337670
- if (!start2 || start2.type !== "FRAME" || doc2.nodes[start2.parentId ?? ""]?.type !== "PAGE") return [startId];
337671
- const out = [startId];
337672
- for (let i2 = 0; i2 < out.length; i2++) {
337673
- for (const id3 of subtreeIds(doc2, out[i2])) {
337674
- for (const ix of interactionsOf(doc2.nodes[id3])) {
337675
- const to = ix.action.navigationType === "NAVIGATE" ? ix.action.destinationId : null;
337676
- const dest = to ? doc2.nodes[to] : void 0;
337677
- if (!dest || out.includes(dest.id) || dest.type !== "FRAME" || doc2.nodes[dest.parentId ?? ""]?.type !== "PAGE") continue;
337678
- if (Math.round(dest.width) !== Math.round(start2.width) || Math.round(dest.height) !== Math.round(start2.height)) continue;
337679
- out.push(dest.id);
337680
- }
337681
- }
337682
- }
337683
- return out;
337684
- }
337685
- function variantStates(doc2, mainId) {
337686
- const out = [mainId];
337687
- for (let i2 = 0; i2 < out.length; i2++) {
337688
- for (const id3 of subtreeIds(doc2, out[i2])) {
337689
- for (const ix of interactionsOf(doc2.nodes[id3])) {
337690
- const to = ix.action.navigationType === "CHANGE_TO" ? ix.action.destinationId : null;
337691
- if (to && !out.includes(to) && doc2.nodes[to]?.type === "COMPONENT") out.push(to);
337692
- }
337693
- }
337694
- }
337695
- return out;
337696
- }
337697
- function buildState(ctx2, doc2, id3, machine, state, start2, variantOf2) {
337698
- const expand = /* @__PURE__ */ new Map();
337699
- const tree = buildPlainTree(doc2, id3, ctx2.opts, start2, { built: (web, _node, at3) => {
337700
- if (web.type === "INSTANCE") expand.set(web, at3);
337701
- } });
337702
- for (const r of tree.rules ?? []) ctx2.rules.add(r);
337703
- if (tree.truncated) ctx2.truncated = true;
337704
- const ids2 = /* @__PURE__ */ new Map();
337705
- const index2 = (w) => {
337706
- ids2.set(w.id, w);
337707
- w.children.forEach(index2);
337708
- };
337709
- index2(tree.root);
337710
- const visit2 = (w, owner, st, isRoot) => {
337711
- w.owner = owner;
337712
- w.looks = { [st]: lookOf(w, isRoot) };
337713
- if (w.motion) ctx2.keyframes.add(w.motion.keyframes);
337714
- const node2 = nodeOf(doc2, w.id);
337715
- note(ctx2, w, interactionsOf(doc2.nodes[realId(w.id)]), owner, st, ids2);
337716
- const at3 = expand.get(w);
337717
- const inst = node2?.type === "INSTANCE" ? node2 : void 0;
337718
- const states = inst && at3 && ctx2.depth < 4 ? variantStates(doc2, inst.mainComponentId) : [];
337719
- if (inst && at3 && states.length > 1 && w.id !== variantOf2) {
337720
- const m = { id: `m${ctx2.machines.length}`, initial: inst.mainComponentId, states: states.map((s) => ({ id: s, name: stateName(doc2, s) })) };
337721
- ctx2.machines.push(m);
337722
- w.machine = m;
337723
- const perState = [];
337724
- for (const s of states) {
337725
- let kids;
337726
- if (s === inst.mainComponentId) {
337727
- kids = w.children;
337728
- kids.forEach((c2) => visit2(c2, m.id, s, false));
337729
- } else {
337730
- const shown2 = { ...doc2, nodes: { ...doc2.nodes, [inst.id]: { ...inst, mainComponentId: s } } };
337731
- ctx2.depth++;
337732
- try {
337733
- kids = buildState(ctx2, shown2, inst.id, m.id, s, at3, inst.id).children;
337734
- } finally {
337735
- ctx2.depth--;
337736
- }
337737
- }
337738
- note(ctx2, w, interactionsOf(doc2.nodes[s]), m.id, s, ids2, m.id);
337739
- perState.push([s, kids]);
337740
- }
337741
- w.children = mergeChildren(perState, m.id, m.states.map((s) => s.id), ctx2);
337742
- } else if (w.id === variantOf2) {
337743
- w.children.forEach((c2) => visit2(c2, owner, st, false));
337744
- } else {
337745
- if (inst) note(ctx2, w, interactionsOf(doc2.nodes[inst.mainComponentId]), owner, st, ids2);
337746
- w.children.forEach((c2) => visit2(c2, owner, st, false));
337747
- }
337748
- };
337749
- visit2(tree.root, machine, state, !start2);
337750
- return tree.root;
337751
- }
337752
- function note(ctx2, w, list2, machine, state, ids2, hostMachine) {
337753
- if (!list2.length) return;
337754
- const at3 = ctx2.pending.get(w) ?? [];
337755
- for (const ix of list2) at3.push({ machine, state, ix, hostMachine: hostMachine ?? (machine !== FLOW ? machine : void 0), ids: ids2 });
337756
- ctx2.pending.set(w, at3);
337757
- }
337758
- function lookOf(w, isRoot) {
337759
- return {
337760
- style: { ...placementStyle(w, isRoot), ...w.style, ...w.motion?.style ?? {} },
337761
- ...w.text ? { text: w.text.characters } : {},
337762
- ...w.tf ? { tf: w.tf } : {}
337763
- };
337764
- }
337765
- function keyed(kids) {
337766
- const seen = /* @__PURE__ */ new Map();
337767
- return kids.map((k2) => {
337768
- const base = `${k2.name}\0${k2.type}`;
337769
- const i2 = seen.get(base) ?? 0;
337770
- seen.set(base, i2 + 1);
337771
- return [`${base}\0${i2}`, k2];
337772
- });
337773
- }
337774
- function mergeChildren(perState, machine, states, ctx2) {
337775
- const order2 = [];
337776
- const groups = /* @__PURE__ */ new Map();
337777
- for (const [state, kids] of perState) {
337778
- let after = -1;
337779
- for (const [k2, node2] of keyed(kids)) {
337780
- let at3 = order2.indexOf(k2);
337781
- if (at3 < 0) {
337782
- order2.splice(after + 1, 0, k2);
337783
- at3 = after + 1;
337784
- }
337785
- after = at3;
337786
- (groups.get(k2) ?? groups.set(k2, []).get(k2)).push([state, node2]);
337787
- }
337788
- }
337789
- return order2.map((k2) => mergeNode(groups.get(k2), machine, states, ctx2));
337790
- }
337791
- function mergeNode(items, machine, states, ctx2) {
337792
- const [, first2] = items[0];
337793
- if (first2.owner !== machine) {
337794
- for (const [, w] of items.slice(1)) alias(ctx2, w, first2);
337795
- return first2;
337796
- }
337797
- const looks = {};
337798
- for (const s of states) looks[s] = null;
337799
- for (const [s, w] of items) looks[s] = w.looks?.[s] ?? null;
337800
- const merged = { ...first2, looks };
337801
- const pend = items.flatMap(([, w]) => ctx2.pending.get(w) ?? []);
337802
- if (pend.length) ctx2.pending.set(merged, pend);
337803
- for (const [, w] of items) if (w !== merged) alias(ctx2, w, merged);
337804
- if (first2.machine) {
337805
- for (const [, w] of items) if (w.machine && w.machine !== first2.machine) ctx2.renamed.set(w.machine.id, first2.machine.id);
337806
- }
337807
- merged.children = first2.machine ? first2.children : mergeChildren(items.map(([s, w]) => [s, w.children]), machine, states, ctx2);
337808
- return merged;
337809
- }
337810
- function alias(ctx2, from2, to) {
337811
- const a = ctx2.alias ??= /* @__PURE__ */ new Map();
337812
- a.set(from2, to);
337813
- }
337814
- function mergedOf(ctx2, w) {
337815
- const a = ctx2.alias;
337816
- let cur = w;
337817
- for (let i2 = 0; i2 < 16 && a?.has(cur); i2++) cur = a.get(cur);
337818
- return cur;
337819
- }
337820
- function actionOf(ctx2, p2) {
337821
- const a = p2.ix.action;
337822
- const glide2 = glideOf2(a.transition);
337823
- const hold = p2.ix.trigger === "ON_HOVER" || p2.ix.trigger === "ON_PRESS";
337824
- switch (a.navigationType) {
337825
- case "NAVIGATE":
337826
- return a.destinationId && ctx2.screens.has(a.destinationId) ? { kind: "go", machine: FLOW, to: a.destinationId, ...glide2, ...hold ? { hold } : {} } : null;
337827
- case "BACK":
337828
- return ctx2.screens.size > 1 ? { kind: "back", machine: FLOW } : null;
337829
- case "CHANGE_TO":
337830
- return p2.hostMachine && a.destinationId ? { kind: "go", machine: p2.hostMachine, to: a.destinationId, ...glide2, ...hold ? { hold } : {} } : null;
337831
- case "ORBIT_3D": {
337832
- const o = a.orbit ?? {};
337833
- const uidOf = (id3) => {
337834
- const w = id3 ? p2.ids.get(id3) : void 0;
337835
- return w ? mergedOf(ctx2, w).uid : void 0;
337836
- };
337837
- const uid2 = uidOf(a.destinationId);
337838
- const tiltUid = uidOf(o.tiltLayerId) ?? uid2;
337839
- 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] };
337840
- }
337841
- default:
337842
- return null;
337843
- }
337844
- }
337845
- function buildWebTree(doc2, nodeId2, opts = {}) {
337846
- const tree = buildTree(doc2, nodeId2, opts);
337847
- const machine = opts.static || opts.stateMachine === false ? null : webStateMachine(doc2, nodeId2);
337848
- return machine ? { ...tree, stateMachine: machine } : tree;
337849
- }
337850
- function buildTree(doc2, nodeId2, opts = {}) {
337851
- if (opts.static || opts.target === "site") return buildPlainTree(doc2, nodeId2, opts);
337852
- const screens = flowScreens(doc2, nodeId2);
337853
- 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"));
337854
- if (!anything) return buildPlainTree(doc2, nodeId2, opts);
337855
- const flow = { id: FLOW, initial: nodeId2, states: screens.map((s) => ({ id: s, name: doc2.nodes[s]?.name ?? s })) };
337856
- 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() };
337857
- const roots = screens.map((s) => [s, buildState(ctx2, doc2, s, FLOW, s)]);
337858
- const truncated = !!ctx2.truncated;
337859
- const root2 = mergeNode(roots, FLOW, screens, ctx2);
337860
- let uid2 = 0;
337861
- const number4 = (w) => {
337862
- w.uid = uid2++;
337863
- w.children.forEach(number4);
337864
- };
337865
- number4(root2);
337866
- const place3 = (w) => {
337867
- const pend = ctx2.pending.get(w);
337868
- if (pend) {
337869
- const seen = /* @__PURE__ */ new Set();
337870
- const on = [];
337871
- for (const raw of pend) {
337872
- const p2 = { ...raw, machine: ctx2.renamed.get(raw.machine) ?? raw.machine, ...raw.hostMachine ? { hostMachine: ctx2.renamed.get(raw.hostMachine) ?? raw.hostMachine } : {} };
337873
- const trigger = TRIGGERS[p2.ix.trigger];
337874
- const action3 = trigger ? actionOf(ctx2, p2) : null;
337875
- if (!trigger || !action3) continue;
337876
- 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 };
337877
- const sig = JSON.stringify(ix);
337878
- if (!seen.has(sig)) {
337879
- seen.add(sig);
337880
- on.push(ix);
337881
- }
337882
- }
337883
- if (on.length) w.on = on;
337884
- }
337885
- w.children.forEach(place3);
337886
- };
337887
- place3(root2);
337888
- 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] } };
337889
- }
337890
- var FLOW, interactionsOf, realId, nodeOf, stateName, TRIGGERS, EASINGS2, glideOf2;
337891
- var init_interactive = __esm({
337892
- "lib/io/web/interactive.ts"() {
337893
- "use strict";
337894
- init_scene_graph();
337895
- init_tree();
337896
- init_state_machine3();
337897
- init_element();
337898
- FLOW = "flow";
337899
- interactionsOf = (n) => n?.interactions ?? [];
337900
- realId = (id3) => id3.includes("::") ? id3.slice(id3.lastIndexOf("::") + 2) : id3;
337901
- nodeOf = (doc2, id3) => doc2.nodes[id3] ?? (id3.includes("::") ? resolveVirtualNode2(doc2.nodes, id3) ?? void 0 : void 0);
337902
- stateName = (doc2, id3) => {
337903
- const n = doc2.nodes[id3];
337904
- const v = n?.variantProperties;
337905
- return v ? Object.values(v).join(", ") : n?.name ?? id3;
337906
- };
337907
- TRIGGERS = {
337908
- ON_CLICK: "click",
337909
- ON_HOVER: "hover",
337910
- ON_PRESS: "press",
337911
- ON_DRAG: "drag",
337912
- MOUSE_ENTER: "enter",
337913
- MOUSE_LEAVE: "leave",
337914
- AFTER_TIMEOUT: "timeout",
337915
- KEY_DOWN: "key"
337916
- };
337917
- 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)" };
337918
- 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" };
337919
- }
337920
- });
337921
-
337922
- // lib/io/web/tree.ts
337923
- function anchorTargets(doc2) {
337924
- const hit = anchorMemo.get(doc2.nodes);
337925
- if (hit) return hit;
337926
- const out = /* @__PURE__ */ new Set();
337927
- for (const id3 in doc2.nodes) {
337928
- const n = doc2.nodes[id3];
337929
- if (n.semantics?.link?.kind === "anchor") out.add(n.semantics.link.nodeId);
337930
- for (const ix of n.interactions ?? []) if (ix.action.link?.kind === "anchor" && ix.action.link.nodeId) out.add(ix.action.link.nodeId);
337931
- }
337932
- anchorMemo.set(doc2.nodes, out);
337933
- return out;
337934
- }
337935
- function prepared(node2, doc2) {
337936
- let n = node2;
337937
- if (n.id.includes("::")) n = withInstanceBox(n, doc2.nodes);
337938
- n = resolveNodeVariables(n, doc2.variables, doc2.variableCollections, doc2.activeVariableModes, exprData(doc2));
337939
- n = resolveTextNodeStyles(n, doc2.styles ?? {});
337940
- return n;
337941
- }
337942
- function layoutOf2(node2, nodes) {
337943
- if (!node2) return null;
337944
- if (node2.type === "INSTANCE") {
337945
- const mainId = node2.mainComponentId;
337946
- const main2 = mainId ? nodes[mainId] : void 0;
337947
- return main2 ?? null;
337948
- }
337949
- if (node2.id.includes("::")) {
337950
- const real = nodes[node2.id.split("::").pop()];
337951
- return real ?? node2;
337952
- }
337953
- return node2;
337954
- }
337955
- function buildPlainTree(doc2, nodeId2, opts = {}, start2, hooks = {}) {
337956
- const cap2 = opts.nodeCap ?? DEFAULT_NODE_CAP;
337957
- const first2 = doc2.nodes[nodeId2] ?? (nodeId2.includes("::") ? childLookup(doc2, nodeId2) : void 0);
337958
- if (!first2) throw new Error(`No node ${nodeId2}`);
337959
- let emitted = 0;
337960
- let truncated = false;
337961
- let folds = 0;
337962
- const tokens = opts.target === "site" && Object.keys(doc2.variables ?? {}).length ? siteTokens(doc2) : null;
337963
- const anchored = anchorTargets(doc2);
337964
- const pageItem = () => {
337965
- const c2 = opts.item && doc2.collections?.[opts.item.collectionId];
337966
- const r = opts.item && doc2.records?.[opts.item.recordId];
337967
- return c2 && r ? { collection: c2, record: r, suffix: "" } : null;
337968
- };
337969
- let item = pageItem();
337970
- const scopeOf2 = (it) => itemScope(it.collection, it.record, withData(variablesScope(doc2.variables, doc2.variableCollections, doc2.activeVariableModes), doc2));
337971
- const itemised = (node2, raw, it) => itemNode(node2, raw, it.collection, it.record, scopeOf2(it));
337972
- const itemLink = (link2, it) => {
337973
- 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;
337974
- if (filled2.kind === "screen") {
337975
- const dest = doc2.nodes[filled2.frameId];
337976
- const base = opts.routes?.[filled2.frameId];
337977
- const of = dest?.route?.collectionId;
337978
- if (of && base !== void 0) {
337979
- const slugs = recordSlugs(doc2, of);
337980
- const rec = it?.collection.id === of ? it.record.id : slugs.keys().next().value;
337981
- const slug3 = rec ? slugs.get(rec) : void 0;
337982
- return slug3 ? { link: filled2, href: `${base === "/" ? "" : base}/${slug3}`, screen: `${filled2.frameId}~${rec}` } : { link: filled2, href: null };
337983
- }
337984
- return { link: filled2, href: base ?? null, screen: filled2.frameId };
337985
- }
337986
- return { link: filled2, href: hrefOf(filled2, doc2.nodes, opts.routes) };
337987
- };
337988
- const fields = /* @__PURE__ */ new Map();
337989
- const styleOpts = { fullImageUrl: opts.fullImageUrls ?? opts.target === "site" };
337990
- const stylesOf = (n) => styleMapFor(n, doc2.styles, styleOpts);
337991
- let motion = null;
337992
- const timeline = !opts.static && !start2 && first2.type === "FRAME" ? frameWebMotion(doc2, first2.id, (n) => stylesOf(prepared(n, doc2))) : null;
337993
- const build3 = (raw, parent, in3D2, fold) => {
337994
- if (emitted >= cap2) {
337995
- truncated = true;
337996
- return null;
337997
- }
337998
- emitted++;
337999
- const node2 = item ? itemised(prepared(raw, doc2), raw, item) : prepared(raw, doc2);
338000
- const waits = node2.visible === false && parent !== null;
338001
- if (waits && !(opts.target === "site" && followsVisibility(raw))) return null;
338002
- const exp = expressibility(node2, doc2.styles);
338003
- const f2 = layoutOf2(node2, doc2.nodes) ?? node2;
338004
- const style = stylesOf(node2);
338005
- if (f2 !== node2 && !style.display) Object.assign(style, flexDeclarations(f2));
338006
- const through = in3D2 && passesThrough(raw, doc2.nodes);
338007
- const own2 = typeof node2.opacity === "number" ? node2.opacity : 1;
338008
- if (through) {
338009
- style["transform-style"] = "preserve-3d";
338010
- delete style.opacity;
338011
- style[foldVar(fold + 1)] = fold ? `calc(var(${foldVar(fold)}) * ${round3(own2)})` : String(round3(own2));
338012
- folds = Math.max(folds, fold + 1);
338013
- } else if (fold) style.opacity = own2 === 1 ? `var(${foldVar(fold)})` : `calc(var(${foldVar(fold)}) * ${round3(own2)})`;
338014
- if (own2 === 0) style["pointer-events"] = "none";
338015
- const web = {
338016
- id: item?.suffix ? `${node2.id}${item.suffix}` : node2.id,
338017
- name: node2.name || node2.type,
338018
- type: node2.type,
338019
- x: Math.round(node2.x),
338020
- y: Math.round(node2.y),
338021
- width: Math.round(node2.width),
338022
- height: Math.round(node2.height),
338023
- // Absolutely-positioned auto-layout children are taken out of the flow, exactly as the canvas does.
338024
- positioning: isFlex(layoutOf2(parent, doc2.nodes)) && node2.layoutPositioning !== "ABSOLUTE" ? "flow" : "absolute",
338025
- style,
338026
- children: []
338027
- };
338028
- if (tokens) Object.assign(style, tokenStyle(raw, style, tokens));
338029
- if (opts.target === "site") {
338030
- const lay = siteLayout(node2, parent, layoutOf2(parent, doc2.nodes));
338031
- for (const [k2, v] of Object.entries(lay.style)) {
338032
- if (v === null) delete style[k2];
338033
- else style[k2] = v;
338034
- }
338035
- if (laysOut(f2) || f2.overflowScrolling) Object.assign(style, containerStyle(f2));
338036
- if (node2.type === "TEXT") {
338037
- if (style["white-space"] === "pre") {
338038
- style["white-space"] = "pre-wrap";
338039
- style.width = "fit-content";
338040
- }
338041
- if (style["max-width"] === void 0) style["max-width"] = "100%";
338042
- if (style.height && style.height !== "auto") {
338043
- style["min-height"] = style.height;
338044
- delete style.height;
338045
- }
338046
- }
338047
- if (lay.place && (parent !== null || !start2?.parent)) web.place = lay.place;
338048
- }
338049
- if (waits) web.hidden = true;
338050
- const sem = node2.semantics;
338051
- if (sem) {
338052
- if (sem.tag && sem.tag !== "div") web.tag = sem.tag;
338053
- const attrs = {};
338054
- if (sem.label) attrs["aria-label"] = sem.label;
338055
- if (sem.hidden) attrs["aria-hidden"] = "true";
338056
- if (Object.keys(attrs).length) web.attrs = attrs;
338057
- const to = sem.link ? itemLink(sem.link, item) : null;
338058
- if (to?.href) web.link = { href: to.href, ...opensNewTab(to.link) ? { newTab: true } : {}, ...to.screen ? { screen: to.screen } : {} };
338059
- }
338060
- const control = node2.control;
338061
- if (control) {
338062
- const named = control.name ? { name: control.name } : {};
338063
- if (control.kind === "FORM") web.tag = "form";
338064
- else if (control.kind === "BUTTON") {
338065
- web.tag = "button";
338066
- 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 } : {} };
338067
- } else if (control.kind === "CHECKBOX" || control.kind === "RADIO") {
338068
- 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 } : {} };
338069
- } else fields.set(fieldPart(doc2.nodes, raw.id) ?? raw.id, control);
338070
- }
338071
- const control0 = fields.get(raw.id);
338072
- const field = control0 && item && control0.value !== void 0 && hasItemToken(control0.value) ? { ...control0, value: itemText(control0.value, item.collection, item.record) } : control0;
338073
- if (field) {
338074
- const tag = field.kind === "TEXTAREA" ? "textarea" : field.kind === "SELECT" ? "select" : "input";
338075
- const words = node2.characters;
338076
- web.input = {
338077
- tag,
338078
- attrs: {
338079
- ...tag === "input" ? { type: field.inputType ?? "text" } : {},
338080
- ...field.name ? { name: field.name } : {},
338081
- ...tag !== "select" && (field.placeholder ?? words) ? { placeholder: field.placeholder ?? words } : {},
338082
- ...field.required ? { required: "" } : {},
338083
- ...tag === "input" && field.value !== void 0 ? { value: field.value } : {},
338084
- "aria-label": node2.semantics?.label ?? field.placeholder ?? field.name ?? web.name
338085
- },
338086
- ...tag === "select" ? { options: field.options ?? [] } : {},
338087
- ...tag !== "input" && field.value !== void 0 ? { value: field.value } : {},
338088
- ...field.variableId ? { variable: field.variableId } : {}
338089
- };
338090
- }
338091
- if (sem?.anchor || anchored.has(node2.id)) web.attrs = { ...web.attrs, id: anchorOf(node2) };
338092
- if (through) web.preserve3d = true;
338093
- web.tf = transformParts(node2);
338094
- if (typeof node2.altText === "string") web.alt = node2.altText;
338095
- if (parent === null) web.positioning = start2?.parent ? web.positioning : "flow";
338096
- if (f2.layoutMode === "HORIZONTAL" || f2.layoutMode === "VERTICAL") {
338097
- web.layout = {
338098
- direction: f2.layoutMode === "HORIZONTAL" ? "row" : "column",
338099
- gap: f2.itemSpacing ?? 0,
338100
- justify: JUSTIFY[f2.primaryAxisAlignItems ?? "MIN"],
338101
- align: ALIGN2[f2.counterAxisAlignItems ?? "MIN"],
338102
- padding: f2.padding ?? { top: 0, right: 0, bottom: 0, left: 0 }
338103
- };
338104
- }
338105
- if (node2.type === "TEXT") {
338106
- const t3 = node2;
338107
- const solid4 = (t3.fills ?? []).find((p2) => p2.visible !== false && p2.type === "SOLID" && p2.color);
338108
- web.text = {
338109
- characters: t3.characters ?? "",
338110
- align: t3.textAlign,
338111
- fontFamily: t3.fontFamily,
338112
- fontSize: t3.fontSize,
338113
- fontWeight: t3.fontWeight,
338114
- italic: t3.fontStyle === "italic",
338115
- ...solid4?.color ? { color: toHex(solid4.color) } : {},
338116
- ...t3.letterSpacing ? { letterSpacing: t3.letterSpacing } : {},
338117
- ...t3.lineHeight !== "AUTO" ? { lineHeight: t3.lineHeight } : {}
338118
- };
338119
- const runs = textRuns(t3);
338120
- if (runs) web.runs = runs;
338121
- }
338122
- const tl = timeline?.get(node2.id);
338123
- const mo = tl ?? motion?.children.get(node2.id);
338124
- if (mo) web.motion = { style: animationStyle(mo, tl ? "load" : motion.trigger), keyframes: keyframesCSS(mo) };
338125
- const ext = getNativeExtension(raw.type);
338126
- if (ext?.toWeb) {
338127
- const said = ext.toWeb(node2, { escape: escapeHTML, color: (c2) => toRgba({ ...c2, a: c2.a ?? 1 }) });
338128
- if (said.tag) web.tag = said.tag;
338129
- Object.assign(style, said.style);
338130
- web.html = said.html;
338131
- hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
338132
- return web;
338133
- }
338134
- const code = opts.target === "site" ? codeOf(doc2.nodes, raw) : null;
338135
- if (code && doc2.codeModules?.[code.moduleId]) {
338136
- for (const k2 of PAINTED) delete style[k2];
338137
- web.code = { module: code.moduleId, ...code.exportName ? { export: code.exportName } : {}, props: codeProps(doc2.nodes, node2) };
338138
- hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
338139
- return web;
338140
- }
338141
- if (!exp.css) {
338142
- for (const k2 of PAINTED) delete style[k2];
338143
- web.asset = { kind: opts.assetKind ?? (exp.needsRaster ? "png" : "svg"), reason: exp.reason, ...item?.suffix ? { of: node2.id } : {} };
338144
- if (opts.target === "site" && renderMode(node2, { styles: doc2.styles, live: isLive(doc2.nodes, raw.id) }) === "island") web.island = true;
338145
- hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
338146
- return web;
338147
- }
338148
- const lost = capability(node2, "css", doc2.styles).dropped.find((f3) => f3.startsWith("paint:"));
338149
- if (lost && !node2.id.includes("::")) {
338150
- const site = opts.target === "site";
338151
- style.isolation = "isolate";
338152
- web.children.push({
338153
- id: `${node2.id}/backdrop${item?.suffix ?? ""}`,
338154
- name: `${web.name} fill`,
338155
- type: "BACKDROP",
338156
- x: 0,
338157
- y: 0,
338158
- width: web.width,
338159
- height: web.height,
338160
- positioning: "absolute",
338161
- ...site ? { place: { position: "absolute", inset: "0" } } : {},
338162
- style: { ...site ? {} : { width: `${web.width}px`, height: `${web.height}px` }, "border-radius": "inherit", overflow: "hidden", "z-index": "-1", "pointer-events": "none" },
338163
- alt: "",
338164
- asset: { kind: "png", reason: featureName(lost), of: node2.id, self: true },
338165
- ...site && movesItself(raw) ? { island: true } : {},
338166
- children: []
338167
- });
338168
- }
338169
- const outer = motion;
338170
- if (!motion && node2.type === "INSTANCE" && !opts.static) {
338171
- motion = instanceWebMotion(doc2, node2, (n) => stylesOf(prepared(n, doc2)));
338172
- if (motion && (motion.trigger !== "load" || opts.target === "site")) web.motionTrigger = motion.trigger;
338173
- }
338174
- try {
338175
- if (opts.includeChildren !== false) {
338176
- const kids3D = in3D2 ? through : is3DContext(raw) && !raw.id.includes("::");
338177
- const kidFold = through ? fold + 1 : 0;
338178
- const repeat = raw.repeat;
338179
- const collection = repeat && doc2.collections?.[repeat.collectionId];
338180
- if (repeat && collection && opts.target === "site") {
338181
- const outerItem = item;
338182
- const under = outerItem ? scopeOf2(outerItem) : withData(variablesScope(doc2.variables, doc2.variableCollections, doc2.activeVariableModes), doc2);
338183
- try {
338184
- for (const record2 of repeatRecords(doc2, repeat, under)) {
338185
- item = { collection, record: record2, suffix: `${outerItem?.suffix ?? ""}~${record2.id}` };
338186
- for (const child of childrenOf(node2, doc2.nodes)) {
338187
- const built = build3(child, node2, kids3D, kidFold);
338188
- if (built) web.children.push(built);
338189
- }
338190
- }
338191
- if (collection.perVisitor && !outerItem) {
338192
- item = { collection, record: templateRecord(collection), suffix: `~${ITEM_RECORD}` };
338193
- const template2 = [];
338194
- for (const child of childrenOf(node2, doc2.nodes)) {
338195
- const built = build3(child, node2, kids3D, kidFold);
338196
- if (built) template2.push(built);
338197
- }
338198
- const sortField = repeat.sort && collection.fields.find((f3) => f3.id === repeat.sort.fieldId);
338199
- web.repeat = {
338200
- collectionId: collection.id,
338201
- template: template2,
338202
- ...repeat.filter?.trim() ? { filter: repeat.filter } : {},
338203
- ...sortField ? { sort: { key: fieldKey(sortField.name), dir: repeat.sort.dir } } : {},
338204
- ...repeat.offset ? { offset: repeat.offset } : {},
338205
- ...repeat.limit ? { limit: repeat.limit } : {}
338206
- };
338207
- }
338208
- } finally {
338209
- item = outerItem;
338210
- }
338211
- } else for (const child of childrenOf(node2, doc2.nodes)) {
338212
- const built = build3(child, node2, kids3D, kidFold);
338213
- if (built) web.children.push(built);
338214
- }
338215
- }
338216
- } finally {
338217
- motion = outer;
338218
- }
338219
- if (web.children.some((c2) => c2.positioning === "absolute")) {
338220
- for (const c2 of web.children) if (c2.positioning === "flow") c2.layered = true;
338221
- }
338222
- hooks.built?.(web, node2, { parent, in3D: in3D2, fold });
338223
- return web;
338224
- };
338225
- const root2 = build3(first2, start2?.parent ?? null, start2?.in3D ?? false, start2?.fold ?? 0);
338226
- if (!root2) throw new Error("Node cap of 0");
338227
- return { root: root2, truncated, ...folds ? { rules: foldRules(folds) } : {}, ...tokens?.vars.length ? { tokens } : {} };
338228
- }
338229
- function childLookup(doc2, id3) {
338230
- const at3 = id3.lastIndexOf("::");
338231
- const host = at3 > 0 ? id3.slice(0, at3) : "";
338232
- const hostNode = doc2.nodes[host] ?? (host.includes("::") ? childLookup(doc2, host) : void 0);
338233
- return hostNode ? childrenOf(hostNode, doc2.nodes).find((c2) => c2.id === id3) : void 0;
338234
- }
338235
- function flatten2(node2, out = []) {
338236
- out.push(node2);
338237
- for (const c2 of node2.children) flatten2(c2, out);
338238
- return out;
338239
- }
338240
- var DEFAULT_NODE_CAP, PAINTED, anchorMemo, followsVisibility, isFlex, round3, foldVar, foldRules;
338241
- var init_tree = __esm({
338242
- "lib/io/web/tree.ts"() {
338243
- "use strict";
338244
- init_instance_layout();
338245
- init_text_styles();
338246
- init_variables();
338247
- init_scene3d();
338248
- init_semantics();
338249
- init_collections();
338250
- init_props();
338251
- init_native_registry();
338252
- init_controls();
338253
- init_expressions2();
338254
- init_children();
338255
- init_css();
338256
- init_capability();
338257
- init_expressible();
338258
- init_motion();
338259
- init_element();
338260
- init_paint2();
338261
- init_responsive();
338262
- init_richtext();
338263
- init_tokens2();
338264
- init_timeline();
338265
- init_interactive();
338266
- DEFAULT_NODE_CAP = 120;
338267
- PAINTED = ["background", "border", "border-style", "border-color", "border-width", "outline", "border-radius", "box-shadow", "box-sizing", "filter", "backdrop-filter"];
338268
- anchorMemo = /* @__PURE__ */ new WeakMap();
338269
- 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.
338270
- Object.values(n.responsive ?? {}).some((o) => o.visible === true);
338271
- isFlex = (f2) => f2?.layoutMode === "HORIZONTAL" || f2?.layoutMode === "VERTICAL";
338272
- round3 = (v) => Math.round(v * 1e3) / 1e3;
338273
- foldVar = (depth2) => `--pc-f${depth2}`;
338274
- foldRules = (depth2) => Array.from({ length: depth2 }, (_, i2) => `@property ${foldVar(i2 + 1)} { syntax: '<number>'; inherits: true; initial-value: 1; }`);
338275
- }
338276
- });
338277
-
338278
338838
  // lib/io/web/assets.ts
338279
338839
  async function resolveWebAssets(tree, resolvers) {
338280
338840
  const pending7 = (Array.isArray(tree) ? tree : flatten2(tree.root)).filter((n) => !!n.asset);
@@ -338325,285 +338885,6 @@ var init_asset_files = __esm({
338325
338885
  }
338326
338886
  });
338327
338887
 
338328
- // lib/document/routes.ts
338329
- function screensOf(doc2, pageId2) {
338330
- return (doc2.nodes[pageId2]?.childIds ?? []).map((id3) => doc2.nodes[id3]).filter((f2) => f2?.type === "FRAME" && f2.visible !== false && !f2.print?.isMaster);
338331
- }
338332
- function cleanPath(raw) {
338333
- const parts = raw.trim().split("/").map(slug2).filter(Boolean);
338334
- return `/${parts.join("/")}`;
338335
- }
338336
- function routesOf(screens) {
338337
- const taken = /* @__PURE__ */ new Set();
338338
- const own2 = /* @__PURE__ */ new Map();
338339
- for (const s of screens) {
338340
- const path = s.route?.path ? cleanPath(s.route.path) : null;
338341
- if (path && !taken.has(path)) {
338342
- taken.add(path);
338343
- own2.set(s.id, path);
338344
- }
338345
- }
338346
- const rest = screens.filter((s) => !own2.has(s.id) && !s.route?.notFound);
338347
- const home = taken.has("/") ? void 0 : rest.find((s) => s.isFlowStartingPoint) ?? rest[0];
338348
- if (home) taken.add("/");
338349
- const out = /* @__PURE__ */ new Map();
338350
- for (const s of screens) {
338351
- if (own2.has(s.id)) {
338352
- out.set(s.id, own2.get(s.id));
338353
- continue;
338354
- }
338355
- if (s === home) {
338356
- out.set(s.id, "/");
338357
- continue;
338358
- }
338359
- const base = s.route?.notFound ? "/404" : `/${slug2(s.name) || "page"}`;
338360
- let route2 = base;
338361
- for (let n = 2; taken.has(route2); n++) route2 = `${base}-${n}`;
338362
- taken.add(route2);
338363
- out.set(s.id, route2);
338364
- }
338365
- return out;
338366
- }
338367
- var slug2;
338368
- var init_routes = __esm({
338369
- "lib/document/routes.ts"() {
338370
- slug2 = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
338371
- }
338372
- });
338373
-
338374
- // lib/island/slice.ts
338375
- function sliceDocument(doc2, nodeId2, opts = {}) {
338376
- const nodes = {};
338377
- const take = (id3) => {
338378
- const n = doc2.nodes[id3];
338379
- if (!n || nodes[id3]) return;
338380
- nodes[id3] = n;
338381
- for (const c2 of n.childIds ?? []) take(c2);
338382
- const main2 = n.mainComponentId;
338383
- if (main2) {
338384
- take(main2);
338385
- const set3 = doc2.nodes[main2]?.parentId;
338386
- if (set3 && doc2.nodes[set3]?.type === "COMPONENT_SET") take(set3);
338387
- }
338388
- };
338389
- if (opts.self && doc2.nodes[nodeId2]) nodes[nodeId2] = { ...doc2.nodes[nodeId2], childIds: [] };
338390
- else take(nodeId2);
338391
- let frameId = null;
338392
- let pageId2 = null;
338393
- let rootId = nodeId2;
338394
- for (let child = nodeId2, cur = doc2.nodes[nodeId2]?.parentId; cur; child = cur, cur = doc2.nodes[cur]?.parentId ?? null) {
338395
- const p2 = doc2.nodes[cur];
338396
- if (!p2) break;
338397
- if (p2.type === "PAGE") {
338398
- pageId2 = cur;
338399
- frameId = doc2.nodes[child]?.type === "FRAME" ? child : frameId;
338400
- }
338401
- 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" };
338402
- if (p2.type !== "PAGE") rootId = cur;
338403
- }
338404
- if (!frameId && doc2.nodes[nodeId2]?.type === "FRAME" && doc2.nodes[doc2.nodes[nodeId2].parentId ?? ""]?.type === "PAGE") frameId = nodeId2;
338405
- return {
338406
- nodeId: nodeId2,
338407
- frameId,
338408
- rootId,
338409
- ...opts.self ? { fit: "fill" } : {},
338410
- document: {
338411
- id: doc2.id,
338412
- name: doc2.name,
338413
- pages: pageId2 ? [pageId2] : [],
338414
- nodes,
338415
- styles: doc2.styles,
338416
- variables: doc2.variables,
338417
- variableCollections: doc2.variableCollections,
338418
- activeVariableModes: doc2.activeVariableModes,
338419
- settings: doc2.settings
338420
- }
338421
- };
338422
- }
338423
- var init_slice = __esm({
338424
- "lib/island/slice.ts"() {
338425
- "use strict";
338426
- }
338427
- });
338428
-
338429
- // lib/io/web/site.ts
338430
- function light(node2) {
338431
- const out = {};
338432
- for (const k2 in node2) if (!HEAVY.has(k2)) out[k2] = node2[k2];
338433
- return out;
338434
- }
338435
- function programDocument(doc2, pageId2, screens) {
338436
- const nodes = {};
338437
- const take = (id3) => {
338438
- const n = doc2.nodes[id3];
338439
- if (!n || nodes[id3]) return;
338440
- nodes[id3] = light(n);
338441
- for (const c2 of n.childIds ?? []) take(c2);
338442
- const main2 = n.mainComponentId;
338443
- if (main2) {
338444
- take(main2);
338445
- const set3 = doc2.nodes[main2]?.parentId;
338446
- if (set3 && doc2.nodes[set3]?.type === "COMPONENT_SET") take(set3);
338447
- }
338448
- };
338449
- const page = doc2.nodes[pageId2];
338450
- if (page) nodes[pageId2] = { ...light(page), childIds: screens.map((s) => s.id) };
338451
- for (const s of screens) take(s.id);
338452
- return {
338453
- id: doc2.id,
338454
- name: doc2.name,
338455
- nodes,
338456
- pages: [pageId2],
338457
- styles: {},
338458
- variables: doc2.variables,
338459
- variableCollections: doc2.variableCollections,
338460
- activeVariableModes: doc2.activeVariableModes,
338461
- settings: doc2.settings,
338462
- // What a layer that follows a record's field is drawn from, while the page runs.
338463
- ...doc2.collections && Object.keys(doc2.collections).length ? { collections: doc2.collections, records: doc2.records } : {}
338464
- };
338465
- }
338466
- function withVariants(doc2, root2, opts, depth2 = 3) {
338467
- if (depth2 <= 0) return;
338468
- for (const w of flatten2(root2)) {
338469
- const inst = w.type === "INSTANCE" && !w.id.includes("::") ? doc2.nodes[w.id] : void 0;
338470
- const main2 = inst?.mainComponentId;
338471
- if (!inst || !main2 || w.variants) continue;
338472
- const reach = variantStates(doc2, main2);
338473
- if (reach.length < 2) continue;
338474
- w.variant = main2;
338475
- w.variants = {};
338476
- const parent = inst.parentId ? doc2.nodes[inst.parentId] ?? null : null;
338477
- for (const v of reach.slice(1)) {
338478
- const as2 = { ...doc2, nodes: { ...doc2.nodes, [inst.id]: { ...inst, mainComponentId: v } } };
338479
- const built = buildPlainTree(as2, inst.id, opts, { parent, in3D: false, fold: 0 }).root;
338480
- built.variant = v;
338481
- withVariants(as2, built, opts, depth2 - 1);
338482
- w.variants[v] = built;
338483
- }
338484
- }
338485
- }
338486
- function everyNode(root2, out = []) {
338487
- for (const n of flatten2(root2)) {
338488
- out.push(n);
338489
- for (const v of Object.values(n.variants ?? {})) everyNode(v, out);
338490
- }
338491
- return out;
338492
- }
338493
- function mediaRules(doc2, screenId, base, opts) {
338494
- const rules = [];
338495
- let above = new Map(flatten2(base).map((n) => [n.id, declared(n, n === base)]));
338496
- for (const bp of breakpointsOf(doc2).slice(1)) {
338497
- const view2 = breakpointDocument(doc2, bp.id);
338498
- const root2 = buildPlainTree(view2, screenId, opts).root;
338499
- const here = new Map(flatten2(root2).map((n) => [n.id, declared(n, n === root2)]));
338500
- const blocks = [];
338501
- for (const [id3, was] of above) {
338502
- const now2 = here.get(id3);
338503
- const diff = {};
338504
- if (!now2) {
338505
- if (was.display !== "none") diff.display = "none";
338506
- } else {
338507
- for (const k2 in was) if (!(k2 in now2)) diff[k2] = "revert";
338508
- for (const k2 in now2) if (now2[k2] !== was[k2]) diff[k2] = now2[k2];
338509
- }
338510
- if (Object.keys(diff).length) blocks.push(` [data-pc-id="${id3}"] {
338511
- ${styleMapToCSSText(Object.fromEntries(Object.entries(diff).map(([k2, v]) => [k2, `${v} !important`])), " ")}
338512
- }`);
338513
- }
338514
- if (blocks.length) rules.push(`@media (max-width: ${bp.maxWidth}px) {
338515
- ${blocks.join("\n")}
338516
- }`);
338517
- above = new Map([...above].map(([id3, was]) => [id3, here.get(id3) ?? { ...was, display: "none" }]));
338518
- }
338519
- return rules;
338520
- }
338521
- function sitePages(doc2, pageId2) {
338522
- const screens = screensOf(doc2, pageId2);
338523
- const routes = routesOf(screens);
338524
- return screens.flatMap((s) => {
338525
- const base = routes.get(s.id);
338526
- const collection = s.route?.collectionId ? doc2.collections?.[s.route.collectionId] : void 0;
338527
- if (!collection) return [{ id: s.id, frame: s, route: base, title: s.route?.title || s.name }];
338528
- const slugs = recordSlugs(doc2, collection.id);
338529
- return recordsIn(doc2, collection.id).map((record2) => ({
338530
- id: `${s.id}~${record2.id}`,
338531
- frame: s,
338532
- record: record2,
338533
- collection,
338534
- route: `${base === "/" ? "" : base}/${slugs.get(record2.id)}`,
338535
- title: itemText(s.route?.title || s.name, collection, record2)
338536
- }));
338537
- });
338538
- }
338539
- function buildWebSite(doc2, opts = {}) {
338540
- const pageId2 = opts.pageId ?? doc2.pages[0];
338541
- const screens = screensOf(doc2, pageId2);
338542
- const routes = routesOf(screens);
338543
- const build3 = { target: "site", nodeCap: opts.nodeCap ?? 2e4, static: opts.static, routes: Object.fromEntries(routes) };
338544
- const laid = /* @__PURE__ */ new Set();
338545
- const pages2 = sitePages(doc2, pageId2).map((p2) => {
338546
- const s = p2.frame;
338547
- const opts2 = p2.record ? { ...build3, item: { collectionId: p2.collection.id, recordId: p2.record.id } } : build3;
338548
- const tree = buildPlainTree(doc2, s.id, opts2);
338549
- const media2 = laid.has(s.id) ? [] : mediaRules(doc2, s.id, tree.root, opts2);
338550
- laid.add(s.id);
338551
- withVariants(doc2, tree.root, opts2);
338552
- const description = s.route?.description ? p2.record ? itemText(s.route.description, p2.collection, p2.record) : s.route.description : void 0;
338553
- const moves3 = !opts2.static && hasFrameMotion(doc2.nodes, s.id);
338554
- const length2 = moves3 ? timelineDuration(doc2.nodes, s.id) : 0;
338555
- const machine = moves3 ? webStateMachine(doc2, s.id) : null;
338556
- return {
338557
- ...machine ? { machine } : {},
338558
- ...length2 > 0 ? { timeline: { duration: length2, stops: stopsOf(frameTimeline(doc2.nodes, s.id).markers, [0, length2]), loops: frameRunsOn(doc2.nodes, s.id) } } : {},
338559
- id: p2.id,
338560
- route: p2.route,
338561
- title: p2.title,
338562
- ...p2.record ? { screen: s.id, record: p2.record.id } : {},
338563
- ...description ? { description } : {},
338564
- ...s.route?.notFound ? { notFound: true } : {},
338565
- ...s.route?.access ? { access: s.route.access } : {},
338566
- tree,
338567
- ...media2.length ? { media: media2 } : {}
338568
- };
338569
- });
338570
- const islandNodes = new Map(pages2.flatMap((p2) => everyNode(p2.tree.root).filter((n) => n.island && !n.id.includes("::"))).map((n) => [n.id, n]));
338571
- const fonts = /* @__PURE__ */ new Map();
338572
- 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);
338573
- const home = pages2.find((p2) => p2.route === "/" && !p2.screen);
338574
- return {
338575
- name: doc2.name,
338576
- pages: pages2,
338577
- home: home?.id ?? null,
338578
- tokens: pages2.find((p2) => p2.tree.tokens)?.tree.tokens,
338579
- fonts: [...fonts].sort(([a], [b]) => a.localeCompare(b)).map(([family, w]) => ({ family, weights: [...w].sort((a, b) => a - b) })),
338580
- assets: pages2.flatMap((p2) => everyNode(p2.tree.root).filter((n) => n.asset).map((n) => n.id)),
338581
- program: { document: programDocument(doc2, pageId2, screens), start: home?.id ?? null },
338582
- ...islandNodes.size ? { islands: Object.fromEntries([...islandNodes].map(([id3, n]) => [id3, sliceDocument(doc2, n.asset?.of ?? layerId(id3), { self: !!n.asset?.self })])) } : {}
338583
- };
338584
- }
338585
- var HEAVY, declared;
338586
- var init_site2 = __esm({
338587
- "lib/io/web/site.ts"() {
338588
- "use strict";
338589
- init_breakpoints();
338590
- init_collections();
338591
- init_routes();
338592
- init_instances2();
338593
- init_timeline_stops();
338594
- init_css();
338595
- init_element();
338596
- init_fonts3();
338597
- init_slice();
338598
- init_state_machine3();
338599
- init_interactive();
338600
- init_tree();
338601
- init_routes();
338602
- HEAVY = /* @__PURE__ */ new Set(["fills", "strokes", "effects", "shadows", "blurs", "vectorPaths", "paths", "styledSegments", "paragraphs", "imageUrl", "exportSettings", "annotations", "devResources", "codeConnect", "layoutGrids", "aiPending"]);
338603
- declared = (n, isRoot) => ({ ...placementStyle(n, isRoot), ...n.style, ...n.hidden ? { display: "none" } : {} });
338604
- }
338605
- });
338606
-
338607
338888
  // lib/io/web/index.ts
338608
338889
  var web_exports = {};
338609
338890
  __export(web_exports, {
@@ -338679,7 +338960,7 @@ var init_web = __esm({
338679
338960
  init_asset_files();
338680
338961
  init_element();
338681
338962
  init_fonts3();
338682
- init_site2();
338963
+ init_site();
338683
338964
  init_tokens2();
338684
338965
  init_naming();
338685
338966
  init_tree();
@@ -338805,7 +339086,7 @@ var init_host = __esm({
338805
339086
  "lib/preview/host.ts"() {
338806
339087
  "use strict";
338807
339088
  init_cdn();
338808
- init_site();
339089
+ init_site2();
338809
339090
  init_snapshot_frame();
338810
339091
  init_web();
338811
339092
  init_media_store();
@@ -338887,7 +339168,8 @@ async function completeSite(doc2, pageId2) {
338887
339168
  const [{ previewSite: previewSite2 }, { rendererAssetResolvers: rendererAssetResolvers2 }] = await Promise.all([Promise.resolve().then(() => (init_host(), host_exports)), Promise.resolve().then(() => (init_resolvers(), resolvers_exports))]);
338888
339169
  return previewSite2(doc2, pageId2, rendererAssetResolvers2(doc2));
338889
339170
  }
338890
- async function nextFilesOf(site, doc2, opts = {}) {
339171
+ async function nextFilesOf(full, doc2, opts = {}) {
339172
+ const site = withoutScreenIslands(full);
338891
339173
  const islandScript2 = site.islands && Object.keys(site.islands).length ? await runtimeScript("island") : null;
338892
339174
  return [...nextProjectFiles(site, doc2, { ...opts, islandScript: islandScript2 }), ...await appAssetFiles(appAssetPaths(site), "public/")];
338893
339175
  }
@@ -338903,6 +339185,7 @@ var init_build2 = __esm({
338903
339185
  init_assets();
338904
339186
  init_static();
338905
339187
  init_next();
339188
+ init_site();
338906
339189
  runtimeScript = (name2) => fetch(`/pc/${name2}.js?fresh=${Date.now()}`, { cache: "no-store" }).then((r) => r.ok ? r.text() : null).catch(() => null);
338907
339190
  NoSiteRuntime = class extends Error {
338908
339191
  constructor() {
@@ -340143,7 +340426,7 @@ var init_motion2 = __esm({
340143
340426
  ui: { label: "Edit composition", palette: false },
340144
340427
  agent: {
340145
340428
  name: "edit_composition",
340146
- 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.`
340147
340430
  }
340148
340431
  },
340149
340432
  run: (args2, ctx2) => {
@@ -343907,7 +344190,7 @@ var init_prototype = __esm({
343907
344190
  triggerKey: external_exports.string().max(40).optional(),
343908
344191
  dragDirection: external_exports.enum(["LEFT", "RIGHT", "UP", "DOWN"]).optional()
343909
344192
  });
343910
- LIVE = ["characters", ...LIVE_VALUE_PROPS];
344193
+ LIVE = ["characters", "imageUrl", ...LIVE_VALUE_PROPS];
343911
344194
  prototypeEdit = defineCommand({
343912
344195
  id: "prototype.edit",
343913
344196
  title: "Edit prototype",
@@ -344184,6 +344467,7 @@ function publishSite(key5, files, opts = {}) {
344184
344467
  var siteStatus, setSiteVersion, renameSite;
344185
344468
  var init_sites = __esm({
344186
344469
  "lib/client/cloud/sites.ts"() {
344470
+ "use strict";
344187
344471
  init_files();
344188
344472
  init_upload2();
344189
344473
  init_api4();
@@ -344697,7 +344981,6 @@ function designRecorder() {
344697
344981
  var installed;
344698
344982
  var init_recorders = __esm({
344699
344983
  "lib/agent/design-script/recorders.ts"() {
344700
- "use strict";
344701
344984
  installed = null;
344702
344985
  }
344703
344986
  });
@@ -345882,7 +346165,9 @@ Every layer call returns its id. **Name** every layer a cue, count or swap must
345882
346165
  - Live state: \`const yearly = k.variable('Billing', 'yearly', 'BOOLEAN', false)\`, \`k.setVariable(layer, yearly, { toggle: true })\`
345883
346166
  on click, \`k.bindVariable(layer, 'visible', yearly)\` to show a layer while it is true (see the pricing example).
345884
346167
  - Prototype links: \`k.link(fromLayer, toFrame, 'PUSH_FROM_RIGHT')\` between screens made with \`k.addScreen(name)\`, and
345885
- \`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.`;
345886
346171
  MOTION = `## Motion and music
345887
346172
 
345888
346173
  Set the timeline first, then add moves. Times are ms on the frame's timeline.
@@ -346444,7 +346729,7 @@ function collectionOf(doc2, ref3) {
346444
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."}`);
346445
346730
  return c2;
346446
346731
  }
346447
- 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;
346448
346733
  var init_site3 = __esm({
346449
346734
  "lib/commands/site.ts"() {
346450
346735
  "use strict";
@@ -346730,6 +347015,30 @@ var init_site3 = __esm({
346730
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 } }) } };
346731
347016
  }
346732
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
+ });
346733
347042
  siteGetBreakpoints = defineCommand({
346734
347043
  id: "site.getBreakpoints",
346735
347044
  title: "Get breakpoints",
@@ -380383,6 +380692,7 @@ var init_builtin2 = __esm({
380383
380692
  dataEditCollection,
380384
380693
  dataEditRecords,
380385
380694
  dataGetRecords,
380695
+ siteSetGpuTransitions,
380386
380696
  // the file as a website online (lib/client/cloud/publish-site.ts): what is published (appended, as above)
380387
380697
  publishStatus,
380388
380698
  // designs as code (lib/agent/design-script): a whole design from one template-kit script (appended, as above)
@@ -380754,8 +381064,8 @@ async function renderLibraryPreviews(renderer, doc2, listing, format = pickPrevi
380754
381064
  const cap2 = await capture(renderer, doc2, c2.playsId, componentSchedule(c2.duration), previewScale(PREVIEW_BOX));
380755
381065
  if (!cap2.frames.length) continue;
380756
381066
  out.push({ key: c2.id, file: "anim", type: FORMAT_MIME[format], bytes: await encodeFrames(format, cap2.width, cap2.height, cap2.frames, PREVIEW_FPS) });
380757
- const still = cap2.frames[fullestFrame(cap2.frames)];
380758
- 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) });
380759
381069
  }
380760
381070
  const shownCells = listing.filter((c2) => doc2.nodes[c2.playsId]).slice(0, POSTER_MAX);
380761
381071
  if (!shownCells.length) return out;
@@ -381150,8 +381460,8 @@ async function renderShaderPreview(device, fills, code, params2, zoom = 1) {
381150
381460
  };
381151
381461
  const animated = reflectShader(code).animated;
381152
381462
  if (!animated) {
381153
- const still = await draw(0);
381154
- 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 };
381155
381465
  }
381156
381466
  const frames = [];
381157
381467
  for (const f2 of previewFrames()) {
@@ -391566,7 +391876,7 @@ async function runInEditor(doc2, commandId, params2, opts) {
391566
391876
  }
391567
391877
  }
391568
391878
  var decodeDataUrl2;
391569
- var init_render = __esm({
391879
+ var init_render2 = __esm({
391570
391880
  "packages/cli/src/render.ts"() {
391571
391881
  "use strict";
391572
391882
  init_editor_open();
@@ -391675,7 +391985,7 @@ async function step2(command, params2, flags, rc) {
391675
391985
  if (where === "plugin" || where === "signin" || where === "app" || where === "unavailable") throw new CliError(`${command.id}: ${WHERE_HELP[where]}`);
391676
391986
  if (where === "browser") {
391677
391987
  if (flagBool(flags, "dryRun")) return { result: { summary: `Would run ${command.id} in the editor (dry run)` }, files: [] };
391678
- const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render(), render_exports));
391988
+ const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render2(), render_exports));
391679
391989
  const download = specOf(command).flags.some((f2) => f2.param === "download" && f2.type === "boolean") && params2.download === void 0 ? { download: true } : {};
391680
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 });
391681
391991
  return { result: done.result ?? { summary: `Ran ${command.id}` }, files: done.files };
@@ -391691,7 +392001,7 @@ async function step2(command, params2, flags, rc) {
391691
392001
  }
391692
392002
  async function reviewInEditor(doc2, frames, look, flags, rc, media2) {
391693
392003
  if (!frames.length) return [];
391694
- const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render(), render_exports));
392004
+ const { runInEditor: runInEditor2 } = await Promise.resolve().then(() => (init_render2(), render_exports));
391695
392005
  const out = flagString(flags, "out") ?? "look/";
391696
392006
  const opts = { appUrl: rc.appUrl, surface: "agent", headful: flagBool(flags, "headful"), out: out.endsWith("/") ? out : `${out}/`, info: rc.out.info, media: media2 };
391697
392007
  const files = [];
@@ -392248,13 +392558,13 @@ async function openSettled(page, t3, sizeId) {
392248
392558
  const sleep4 = (ms2) => new Promise((r) => setTimeout(r, ms2));
392249
392559
  const quiet = async () => {
392250
392560
  let last3 = w.__vpStore.getState().document.nodes;
392251
- for (let still = 0, i2 = 0; still < 6 && i2 < 300; i2++) {
392561
+ for (let still2 = 0, i2 = 0; still2 < 6 && i2 < 300; i2++) {
392252
392562
  await w.__vpRenderer.whenReady();
392253
392563
  await sleep4(100);
392254
392564
  const now2 = w.__vpStore.getState().document.nodes;
392255
- if (now2 === last3) still++;
392565
+ if (now2 === last3) still2++;
392256
392566
  else {
392257
- still = 0;
392567
+ still2 = 0;
392258
392568
  last3 = now2;
392259
392569
  }
392260
392570
  }
@@ -392433,14 +392743,14 @@ async function runPictures(root2, appUrl, out) {
392433
392743
  const t3 = asTemplate(upload);
392434
392744
  const sizeId = t3.payload.variants[0].sizeId;
392435
392745
  const thumbnail = await drawThumbnail(editor, t3, sizeId);
392436
- const still = await drawDetailStill(editor, t3, sizeId);
392746
+ const still2 = await drawDetailStill(editor, t3, sizeId);
392437
392747
  const anim = upload.meta.animated ? await drawPreview(editor, t3, false) : null;
392438
392748
  const folder = join9(dir, "pictures");
392439
392749
  rmSync4(folder, { recursive: true, force: true });
392440
392750
  mkdirSync6(folder, { recursive: true });
392441
- writeFileSync7(join9(folder, "still.webp"), still.bytes);
392751
+ writeFileSync7(join9(folder, "still.webp"), still2.bytes);
392442
392752
  if (anim) writeFileSync7(join9(folder, "anim.mp4"), anim.bytes);
392443
- 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 } } : {} };
392444
392754
  writeFileSync7(join9(folder, "pictures.json"), `${JSON.stringify(pictures, null, 2)}
392445
392755
  `);
392446
392756
  writeFileSync7(join9(dir, "template.json"), JSON.stringify({ ...upload, meta: { ...upload.meta, thumbnail } }));
@@ -392461,7 +392771,7 @@ var init_pictures = __esm({
392461
392771
  "use strict";
392462
392772
  init_pictures_node();
392463
392773
  init_publish2();
392464
- init_render();
392774
+ init_render2();
392465
392775
  init_io();
392466
392776
  asTemplate = (u) => ({ meta: { ...u.meta, id: u.meta.localId }, payload: u.payload });
392467
392777
  }
@@ -393030,7 +393340,7 @@ init_resources();
393030
393340
  init_desktop();
393031
393341
  init_hypery();
393032
393342
  import { createInterface } from "node:readline";
393033
- var VERSION2 = "0.7.0";
393343
+ var VERSION2 = "0.8.0";
393034
393344
  var HELP = `popcraft ${VERSION2} \u2014 the PopCraft command line
393035
393345
 
393036
393346
  Files (headless, on .popcraft files):