@popcraft/cli 0.24.1 → 0.24.3

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 +61 -24
  2. package/package.json +2 -2
package/dist/popcraft.mjs CHANGED
@@ -1188,7 +1188,7 @@ function operations(spec = openapi) {
1188
1188
  }
1189
1189
  async function call(target2, method, path, opts = {}) {
1190
1190
  const qs = new URLSearchParams(opts.query ?? {}).toString();
1191
- const headers = { "user-agent": `popcraft-cli/${"0.24.1"}`, ...opts.headers };
1191
+ const headers = { "user-agent": `popcraft-cli/${"0.24.3"}`, ...opts.headers };
1192
1192
  if (target2.token) headers.authorization = `Bearer ${target2.token}`;
1193
1193
  if (opts.contentType) headers["content-type"] = opts.contentType;
1194
1194
  try {
@@ -256903,6 +256903,7 @@ __export(pose_exports, {
256903
256903
  bakeMotion: () => bakeMotion,
256904
256904
  evaluatePose: () => evaluatePose,
256905
256905
  frameTimeline: () => frameTimeline,
256906
+ poseNodesAt: () => poseNodesAt,
256906
256907
  poseOver: () => poseOver,
256907
256908
  posedNode: () => posedNode,
256908
256909
  reevaluatePose: () => reevaluatePose,
@@ -257037,6 +257038,19 @@ function bakeMotion(nodes, frameId, time4) {
257037
257038
  noteChanged(nodes, baked, ids2);
257038
257039
  return baked;
257039
257040
  }
257041
+ function poseNodesAt(nodes, ids2, time4, frameId) {
257042
+ const frames = [];
257043
+ for (const id3 of ids2) {
257044
+ let owner;
257045
+ for (let n = nodes[id3]; n && n.type !== "PAGE"; n = n.parentId ? nodes[n.parentId] : void 0) {
257046
+ if ((n.type === "FRAME" || n.type === "COMPONENT") && (frameId ? n.id === frameId : hasFrameMotion(nodes, n.id))) owner = n.id;
257047
+ }
257048
+ if (owner && !frames.includes(owner)) frames.push(owner);
257049
+ }
257050
+ let out = nodes;
257051
+ for (const f2 of frames) out = evaluatePose(out, { kind: "frame", frameId: f2 }, Math.max(0, time4)).nodes;
257052
+ return out;
257053
+ }
257040
257054
  function posedNode(nodes, id3, frameId, time4) {
257041
257055
  const node2 = nodes[id3];
257042
257056
  if (!node2) return void 0;
@@ -260624,6 +260638,7 @@ function listenDesktop(event, handler) {
260624
260638
  var isDesktop;
260625
260639
  var init_tauri = __esm({
260626
260640
  "lib/desktop/tauri.ts"() {
260641
+ "use strict";
260627
260642
  isDesktop = () => !!tauri();
260628
260643
  }
260629
260644
  });
@@ -260674,7 +260689,6 @@ function formatLimit(key5, max3) {
260674
260689
  var formatBytes;
260675
260690
  var init_limits2 = __esm({
260676
260691
  "lib/billing/limits.ts"() {
260677
- "use strict";
260678
260692
  init_format();
260679
260693
  init_plans();
260680
260694
  formatBytes = formatFileSize;
@@ -261140,7 +261154,6 @@ function planEntryAction({ home }) {
261140
261154
  var STORAGE_KEY2, useHyperyTeam, TEAM_PROMPT_ENABLED, TEAM_PROMPTED_KEY, PROMPTED_KEY, useTeamPrompt, started;
261141
261155
  var init_team = __esm({
261142
261156
  "lib/client/cloud/team.ts"() {
261143
- "use strict";
261144
261157
  init_esm();
261145
261158
  init_api4();
261146
261159
  init_session();
@@ -308912,7 +308925,6 @@ async function createFreshFileOrExplain(place4 = {}, seed2 = {}) {
308912
308925
  var online, goesLocal;
308913
308926
  var init_new_file = __esm({
308914
308927
  "lib/client/cloud/new-file.ts"() {
308915
- "use strict";
308916
308928
  init_scene_graph();
308917
308929
  init_print_pages();
308918
308930
  init_page_presets();
@@ -309637,7 +309649,6 @@ async function dispatchShaped(key5, options) {
309637
309649
  var onViolation;
309638
309650
  var init_dispatch = __esm({
309639
309651
  "lib/commands/dispatch.ts"() {
309640
- "use strict";
309641
309652
  init_errors();
309642
309653
  init_registry();
309643
309654
  init_confirm();
@@ -309828,6 +309839,7 @@ function documentForExport(doc2) {
309828
309839
  continue;
309829
309840
  }
309830
309841
  nodes[id3] = { ...node2, fills: fills.filter((p2) => !excluded(p2)) };
309842
+ carryTextPose(node2, nodes[id3]);
309831
309843
  changed = true;
309832
309844
  }
309833
309845
  return changed ? { ...doc2, nodes } : doc2;
@@ -309836,6 +309848,7 @@ var excluded, hasExcludedFill;
309836
309848
  var init_export_fills = __esm({
309837
309849
  "lib/document/export-fills.ts"() {
309838
309850
  "use strict";
309851
+ init_text_animators();
309839
309852
  excluded = (p2) => p2.includeInExport === false;
309840
309853
  hasExcludedFill = (fills) => !!fills?.some(excluded);
309841
309854
  }
@@ -325922,7 +325935,7 @@ var init_package = __esm({
325922
325935
  "packages/runtime/package.json"() {
325923
325936
  package_default = {
325924
325937
  name: "@popcraft/runtime",
325925
- version: "0.24.1",
325938
+ version: "0.24.3",
325926
325939
  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.",
325927
325940
  license: "MIT",
325928
325941
  homepage: "https://popcraft.app/docs/exporting/nextjs",
@@ -350588,7 +350601,6 @@ function exportsOf(source3) {
350588
350601
  var CODE_LIMITS, packageOf;
350589
350602
  var init_source2 = __esm({
350590
350603
  "lib/code/source.ts"() {
350591
- "use strict";
350592
350604
  CODE_LIMITS = { modules: 100, sourceLength: 2e5, packages: 12 };
350593
350605
  packageOf = (spec) => spec.split("/").slice(0, spec.startsWith("@") ? 2 : 1).join("/");
350594
350606
  }
@@ -350631,7 +350643,6 @@ function compileModule(module2) {
350631
350643
  var import_sucrase, BUILT_IN, memo4;
350632
350644
  var init_compile2 = __esm({
350633
350645
  "lib/code/compile.ts"() {
350634
- "use strict";
350635
350646
  import_sucrase = __toESM(require_dist2());
350636
350647
  init_source2();
350637
350648
  init_source2();
@@ -350709,7 +350720,6 @@ function hashOf(text) {
350709
350720
  }
350710
350721
  var init_hash = __esm({
350711
350722
  "lib/code/hash.ts"() {
350712
- "use strict";
350713
350723
  }
350714
350724
  });
350715
350725
 
@@ -352686,6 +352696,24 @@ var init_board_export = __esm({
352686
352696
  });
352687
352697
 
352688
352698
  // lib/commands/export.ts
352699
+ async function docAtTime(doc2, ids2, time4) {
352700
+ let frameId;
352701
+ if (time4 === void 0) {
352702
+ try {
352703
+ const { useEditorStore: useEditorStore2 } = await Promise.resolve().then(() => (init_editor_store(), editor_store_exports));
352704
+ const st = useEditorStore2.getState();
352705
+ const target2 = st.transport?.target;
352706
+ if (st.mode !== "ANIMATE" || target2?.kind !== "frame") return doc2;
352707
+ time4 = st.transport.time;
352708
+ frameId = target2.frameId;
352709
+ } catch {
352710
+ return doc2;
352711
+ }
352712
+ }
352713
+ const { poseNodesAt: poseNodesAt2 } = await Promise.resolve().then(() => (init_pose(), pose_exports));
352714
+ const nodes = poseNodesAt2(doc2.nodes, ids2, time4, frameId);
352715
+ return nodes === doc2.nodes ? doc2 : { ...doc2, nodes };
352716
+ }
352689
352717
  function animationTarget(args2, ctx2, doc2) {
352690
352718
  if (args2.composition) {
352691
352719
  if (!doc2.compositions?.[args2.composition]) throw new ToolError(`There is no composition "${args2.composition}".`);
@@ -352794,7 +352822,7 @@ async function exportSite(doc2, pageId2, packaging, styling = "css", siteUrl) {
352794
352822
  downloadBlob2(zipFiles2(files.map((f2) => ({ name: f2.path, bytes: bytesOf2(f2) }))), `${base}.zip`);
352795
352823
  return { summary: `Exported ${plural2(site.pages.length, "page")} as ${packaging === "next" ? "a Next.js project" : "a static site"} (${base}.zip)`, data: { filename: `${base}.zip`, packaging, pages: site.pages.map((p2) => p2.route), files: files.length } };
352796
352824
  }
352797
- var MAX_INLINE_BYTES, exportSvg, exportNodes, exportPdf, exportCopy, exportPages, exportPptx, animationParams, videoParams, gifParams, lottieParams, animationCommand, TARGET, exportMp4, exportWebm, exportGif, exportPngSequence, exportLottie2, exportWeb, APP_STOREFRONT_TARGETS, exportStorefront, exportBoard;
352825
+ var MAX_INLINE_BYTES, timeParam, exportSvg, exportNodes, exportPdf, exportCopy, exportPages, exportPptx, animationParams, videoParams, gifParams, lottieParams, animationCommand, TARGET, exportMp4, exportWebm, exportGif, exportPngSequence, exportLottie2, exportWeb, APP_STOREFRONT_TARGETS, exportStorefront, exportBoard;
352798
352826
  var init_export2 = __esm({
352799
352827
  "lib/commands/export.ts"() {
352800
352828
  "use strict";
@@ -352809,6 +352837,7 @@ var init_export2 = __esm({
352809
352837
  init_formats();
352810
352838
  init_tree();
352811
352839
  MAX_INLINE_BYTES = 15e5;
352840
+ timeParam = external_exports.number().min(0).optional().describe("Moment (ms) of the frame's timeline to export animated layers at. Defaults to the playhead when the frame is open in Animate, else the layers at rest.");
352812
352841
  exportSvg = defineCommand({
352813
352842
  id: "export.svg",
352814
352843
  title: "Export SVG",
@@ -352818,7 +352847,8 @@ var init_export2 = __esm({
352818
352847
  needs: ["canvas"],
352819
352848
  params: external_exports.object({
352820
352849
  id: external_exports.string().describe("Node to export."),
352821
- maxChars: external_exports.number().int().min(500).max(2e5).optional().describe("Truncate the markup at this many characters (default 20000).")
352850
+ maxChars: external_exports.number().int().min(500).max(2e5).optional().describe("Truncate the markup at this many characters (default 20000)."),
352851
+ time: timeParam
352822
352852
  }),
352823
352853
  expose: {
352824
352854
  agent: {
@@ -352827,7 +352857,7 @@ var init_export2 = __esm({
352827
352857
  }
352828
352858
  },
352829
352859
  run: async (args2, ctx2) => {
352830
- const doc2 = ctx2.doc();
352860
+ const doc2 = await docAtTime(ctx2.doc(), [args2.id], args2.time);
352831
352861
  const node2 = nodeOrThrow(doc2, args2.id);
352832
352862
  const renderer = ctx2.use("canvas")();
352833
352863
  if (!renderer) throw new ToolError("SVG export needs the canvas renderer, which is not running (the editor canvas may not have initialised WebGPU). Use get_node or measure instead.");
@@ -352857,7 +352887,8 @@ var init_export2 = __esm({
352857
352887
  scale: external_exports.number().min(0.1).max(8).optional().describe("With format: pixel scale factor (default 1; 2 for @2x)."),
352858
352888
  suffix: external_exports.string().max(20).optional().describe('With format: added to each file name ("@2x").'),
352859
352889
  download: external_exports.boolean().optional().describe("Save the files to the user's downloads folder. Off by default \u2014 never turn it on unless the user asked for a file."),
352860
- singlePdf: external_exports.boolean().optional().describe("For PDF only: put every layer in one document, one page each (default true).")
352890
+ singlePdf: external_exports.boolean().optional().describe("For PDF only: put every layer in one document, one page each (default true)."),
352891
+ time: timeParam
352861
352892
  }),
352862
352893
  expose: {
352863
352894
  ui: {
@@ -352879,8 +352910,8 @@ var init_export2 = __esm({
352879
352910
  }
352880
352911
  },
352881
352912
  run: async (args2, ctx2) => {
352882
- const doc2 = ctx2.doc();
352883
352913
  const ids2 = targetIds(args2.ids, ctx2.selection(), "export_nodes");
352914
+ const doc2 = await docAtTime(ctx2.doc(), ids2, args2.time);
352884
352915
  const nodes = ids2.map((id3) => nodeOrThrow(doc2, id3));
352885
352916
  const renderer = ctx2.use("canvas")();
352886
352917
  if (!renderer) throw new ToolError("Exporting needs the canvas renderer, which is not running (the editor canvas may not have initialised WebGPU). Use measure or export_svg instead.");
@@ -352943,7 +352974,8 @@ var init_export2 = __esm({
352943
352974
  spreads: external_exports.boolean().optional().describe("Facing pages on one sheet (2\u20133, 4\u20135 \u2026). Same as layout: spreads."),
352944
352975
  splitSpreads: external_exports.boolean().optional().describe("Cut an oversized sheet (a centrefold) into single pages so the file has ONE page size \u2014 what almost every printer requires. Off for the printers that take a spread as one image and cut it themselves. Default true."),
352945
352976
  layout: external_exports.enum(["pages", "spreads", "booklet", "nup2", "nup4"]).optional().describe("How pages sit on each printed sheet: one each, reader spreads, a saddle-stitch booklet to fold and staple, or two/four to a sheet."),
352946
- ats: external_exports.boolean().optional().describe("ATS-friendly: all text embedded, reading order, real spaces; gradient text becomes solid.")
352977
+ ats: external_exports.boolean().optional().describe("ATS-friendly: all text embedded, reading order, real spaces; gradient text becomes solid."),
352978
+ time: timeParam
352947
352979
  }),
352948
352980
  expose: {
352949
352981
  ui: { label: "Export as PDF", keywords: ["pdf", "export", "download", "print"] }
@@ -352960,12 +352992,15 @@ var init_export2 = __esm({
352960
352992
  nodes = frames.length ? frames : roots;
352961
352993
  }
352962
352994
  if (!nodes.length) throw new ToolError("There is nothing on this page to export.");
352995
+ const posed2 = await docAtTime(doc2, nodes.map((n) => n.id), args2.time);
352996
+ nodes = nodes.map((n) => posed2.nodes[n.id] ?? n);
352963
352997
  const { exportNodesToPDF: exportNodesToPDF2 } = await Promise.resolve().then(() => (init_pdf(), pdf_exports));
352964
352998
  const { downloadBlob: downloadBlob2 } = await Promise.resolve().then(() => (init_download(), download_exports));
352965
- const { scale, ids: _ids, ...print2 } = args2;
352999
+ const { scale, ids: _ids, time: _time, ...print2 } = args2;
352966
353000
  void _ids;
353001
+ void _time;
352967
353002
  const opts = Object.values(print2).some((v) => v !== void 0) ? { ...print2 } : scale ?? 1;
352968
- const blob = await exportNodesToPDF2(renderer, nodes, opts, doc2, doc2.styles);
353003
+ const blob = await exportNodesToPDF2(renderer, nodes, opts, posed2, posed2.styles);
352969
353004
  if (!blob) throw new ToolError("Those layers produced no PDF \u2014 they may be empty, hidden or zero-sized.");
352970
353005
  const filename = `${doc2.name || "export"}.pdf`;
352971
353006
  downloadBlob2(blob, filename);
@@ -352982,7 +353017,8 @@ var init_export2 = __esm({
352982
353017
  params: external_exports.object({
352983
353018
  id: external_exports.string().optional().describe("Layer to copy. Defaults to the first selected one."),
352984
353019
  format: external_exports.enum(["PNG", "SVG"]).optional().describe("Default PNG."),
352985
- scale: external_exports.number().min(0.1).max(8).optional().describe("PNG only; default 2.")
353020
+ scale: external_exports.number().min(0.1).max(8).optional().describe("PNG only; default 2."),
353021
+ time: timeParam
352986
353022
  }),
352987
353023
  expose: {
352988
353024
  ui: {
@@ -352996,9 +353032,9 @@ var init_export2 = __esm({
352996
353032
  }
352997
353033
  },
352998
353034
  run: async (args2, ctx2) => {
352999
- const doc2 = ctx2.doc();
353000
353035
  const id3 = args2.id ?? ctx2.selection()[0];
353001
353036
  if (!id3) throw new ToolError("Nothing is selected, so there is nothing to copy.");
353037
+ const doc2 = await docAtTime(ctx2.doc(), [id3], args2.time);
353002
353038
  const node2 = nodeOrThrow(doc2, id3);
353003
353039
  const renderer = ctx2.use("canvas")();
353004
353040
  if (!renderer) throw new ToolError("Copying a layer needs the canvas renderer, which is not running.");
@@ -353019,7 +353055,8 @@ var init_export2 = __esm({
353019
353055
  params: external_exports.object({
353020
353056
  ids: external_exports.array(external_exports.string()).max(500).optional().describe("Defaults to the selection, then to the page's print pages / top-level frames."),
353021
353057
  format: external_exports.enum(["PNG", "JPG", "WEBP"]).optional().describe("Default PNG."),
353022
- dpi: external_exports.number().min(36).max(1200).optional().describe("Resolution; 96 is 1:1 with the canvas. Print pages default to 300.")
353058
+ dpi: external_exports.number().min(36).max(1200).optional().describe("Resolution; 96 is 1:1 with the canvas. Print pages default to 300."),
353059
+ time: timeParam
353023
353060
  }),
353024
353061
  expose: {
353025
353062
  ui: { label: "Export pages as images", keywords: ["zip", "export", "pages", "png", "jpg", "dpi", "print"] },
@@ -353042,6 +353079,8 @@ var init_export2 = __esm({
353042
353079
  }
353043
353080
  }
353044
353081
  if (!nodes.length) throw new ToolError("There is nothing on this page to export.");
353082
+ const posed2 = await docAtTime(doc2, nodes.map((n) => n.id), args2.time);
353083
+ nodes = nodes.map((n) => posed2.nodes[n.id] ?? n);
353045
353084
  const format = args2.format ?? "PNG";
353046
353085
  const dpi = args2.dpi ?? (doc2.settings?.kind === "PRINT" ? doc2.settings.dpi ?? 300 : 96);
353047
353086
  const { exportNodeToBlob: exportNodeToBlob2 } = await Promise.resolve().then(() => (init_export(), export_exports));
@@ -353050,7 +353089,7 @@ var init_export2 = __esm({
353050
353089
  const files = [];
353051
353090
  const pad = String(nodes.length).length;
353052
353091
  for (let i2 = 0; i2 < nodes.length; i2++) {
353053
- const blob = await exportNodeToBlob2(renderer, nodes[i2], { suffix: "", format, scale: dpi / 96, dpi }, doc2, doc2.styles);
353092
+ const blob = await exportNodeToBlob2(renderer, nodes[i2], { suffix: "", format, scale: dpi / 96, dpi }, posed2, posed2.styles);
353054
353093
  if (blob) files.push({ name: `${String(i2 + 1).padStart(pad, "0")}-${(nodes[i2].name || "page").replace(/[\\/:*?"<>|]+/g, "_")}.${format.toLowerCase()}`, bytes: new Uint8Array(await blob.arrayBuffer()) });
353055
353094
  }
353056
353095
  if (!files.length) throw new ToolError("Those layers produced no images \u2014 they may be empty, hidden or zero-sized.");
@@ -359507,7 +359546,6 @@ var init_publish = __esm({
359507
359546
  var storeOpsSeam;
359508
359547
  var init_seams = __esm({
359509
359548
  "lib/commands/seams.ts"() {
359510
- "use strict";
359511
359549
  storeOpsSeam = (st) => ({
359512
359550
  booleanOperation: (op4) => st().booleanOperation(op4),
359513
359551
  flatten: () => st().flattenSelection(),
@@ -396394,7 +396432,6 @@ function designRecorder() {
396394
396432
  var installed;
396395
396433
  var init_recorders = __esm({
396396
396434
  "lib/agent/design-script/recorders.ts"() {
396397
- "use strict";
396398
396435
  installed = null;
396399
396436
  }
396400
396437
  });
@@ -408697,7 +408734,7 @@ init_resources();
408697
408734
  init_desktop();
408698
408735
  init_hypery();
408699
408736
  import { createInterface } from "node:readline";
408700
- var VERSION2 = "0.24.1";
408737
+ var VERSION2 = "0.24.3";
408701
408738
  var HELP = `popcraft ${VERSION2} \u2014 the PopCraft command line
408702
408739
 
408703
408740
  Files (headless, on .popcraft files):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@popcraft/cli",
3
- "version": "0.24.1",
3
+ "version": "0.24.3",
4
4
  "description": "The PopCraft command line: edit .popcraft files headlessly, call the REST API, publish to the marketplace and manage the desktop app's local plugins, themes, fonts, skills and agents.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://popcraft.app/docs/api/cli",
@@ -34,7 +34,7 @@
34
34
  "esbuild": "0.28.2"
35
35
  },
36
36
  "dependencies": {
37
- "@popcraft/kit": "0.24.1"
37
+ "@popcraft/kit": "0.24.3"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "node build.mjs",