@popcraft/cli 0.53.15 → 0.53.16

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 +130 -46
  2. package/package.json +2 -2
package/dist/popcraft.mjs CHANGED
@@ -1198,7 +1198,7 @@ function operations(spec = openapi) {
1198
1198
  }
1199
1199
  async function call(target2, method, path, opts = {}) {
1200
1200
  const qs = new URLSearchParams(opts.query ?? {}).toString();
1201
- const headers = { "user-agent": `popcraft-cli/${"0.53.15"}`, ...opts.headers };
1201
+ const headers = { "user-agent": `popcraft-cli/${"0.53.16"}`, ...opts.headers };
1202
1202
  if (target2.token) headers.authorization = `Bearer ${target2.token}`;
1203
1203
  if (opts.contentType) headers["content-type"] = opts.contentType;
1204
1204
  try {
@@ -8179,6 +8179,8 @@ function duplicateNode(document2, nodeId2, offset = { x: 10, y: 10 }) {
8179
8179
  }
8180
8180
  const newNode = cloneNode(node2);
8181
8181
  let doc2 = addNode(document2, newNode, node2.parentId);
8182
+ const at4 = document2.nodes[node2.parentId]?.childIds.indexOf(nodeId2) ?? -1;
8183
+ if (at4 >= 0) doc2 = reparentNode(doc2, newNode.id, node2.parentId, at4 + 1);
8182
8184
  function cloneChildren(originalId, newParentId) {
8183
8185
  const original = document2.nodes[originalId];
8184
8186
  if (!original) return;
@@ -8188,6 +8190,7 @@ function duplicateNode(document2, nodeId2, offset = { x: 10, y: 10 }) {
8188
8190
  const newChild = cloneNode(child);
8189
8191
  newChild.x = child.x;
8190
8192
  newChild.y = child.y;
8193
+ newChild.name = child.name;
8191
8194
  doc2 = addNode(doc2, newChild, newParentId);
8192
8195
  cloneChildren(childId, newChild.id);
8193
8196
  }
@@ -29182,6 +29185,73 @@ var init_flags = __esm({
29182
29185
  }
29183
29186
  });
29184
29187
 
29188
+ // lib/document/z-order.ts
29189
+ function reorderSelection(doc2, ids2, dir) {
29190
+ const selected = new Set(ids2);
29191
+ const parents = /* @__PURE__ */ new Set();
29192
+ for (const id3 of ids2) {
29193
+ const p2 = doc2.nodes[id3]?.parentId;
29194
+ if (p2 && doc2.nodes[p2]) parents.add(p2);
29195
+ }
29196
+ if (!parents.size) return doc2;
29197
+ const nodes = { ...doc2.nodes };
29198
+ let changed = false;
29199
+ for (const pid of parents) {
29200
+ const list2 = [...nodes[pid].childIds];
29201
+ if (dir === "top" || dir === "bottom") {
29202
+ const sel = list2.filter((id3) => selected.has(id3)), rest = list2.filter((id3) => !selected.has(id3));
29203
+ const next2 = dir === "top" ? [...rest, ...sel] : [...sel, ...rest];
29204
+ if (next2.some((id3, i2) => id3 !== list2[i2])) {
29205
+ nodes[pid] = { ...nodes[pid], childIds: next2 };
29206
+ changed = true;
29207
+ }
29208
+ continue;
29209
+ }
29210
+ let moved3 = false;
29211
+ if (dir === "up") {
29212
+ for (let i2 = list2.length - 2; i2 >= 0; i2--) {
29213
+ if (selected.has(list2[i2]) && !selected.has(list2[i2 + 1])) {
29214
+ [list2[i2], list2[i2 + 1]] = [list2[i2 + 1], list2[i2]];
29215
+ moved3 = true;
29216
+ }
29217
+ }
29218
+ } else {
29219
+ for (let i2 = 1; i2 < list2.length; i2++) {
29220
+ if (selected.has(list2[i2]) && !selected.has(list2[i2 - 1])) {
29221
+ [list2[i2], list2[i2 - 1]] = [list2[i2 - 1], list2[i2]];
29222
+ moved3 = true;
29223
+ }
29224
+ }
29225
+ }
29226
+ if (moved3) {
29227
+ nodes[pid] = { ...nodes[pid], childIds: list2 };
29228
+ changed = true;
29229
+ }
29230
+ }
29231
+ return changed ? { ...doc2, nodes } : doc2;
29232
+ }
29233
+ var init_z_order = __esm({
29234
+ "lib/document/z-order.ts"() {
29235
+ }
29236
+ });
29237
+
29238
+ // lib/editor/selection-drill.ts
29239
+ function selectAllTargets(doc2, pageId2, selection) {
29240
+ const parentId = (selection.length ? resolveVirtualNode2(doc2.nodes, selection[0])?.parentId : null) ?? pageId2;
29241
+ const parent = doc2.nodes[parentId] ?? doc2.nodes[pageId2];
29242
+ return (parent?.childIds ?? []).filter((id3) => selectable(doc2, id3));
29243
+ }
29244
+ var selectable;
29245
+ var init_selection_drill = __esm({
29246
+ "lib/editor/selection-drill.ts"() {
29247
+ init_scene_graph();
29248
+ selectable = (doc2, id3) => {
29249
+ const n = doc2.nodes[id3];
29250
+ return !!n && n.visible !== false && !n.locked;
29251
+ };
29252
+ }
29253
+ });
29254
+
29185
29255
  // lib/document/history-group.ts
29186
29256
  function withHistoryGroup(group2, fn) {
29187
29257
  if (!group2) return fn();
@@ -96874,6 +96944,7 @@ function releaseMediaMemory(hash3) {
96874
96944
  var key2, peaksKey, objectUrls, sourceKey, remoteResolver, MEDIA_FETCH_TIMEOUT_MS, SHIPPED_MEDIA_PATH, notShipped, MEDIA_SCHEME, isImageDataUrl, memory, pendingLoads, sourceAliases, PAINT_KEYS, URL_KEYS;
96875
96945
  var init_media_store = __esm({
96876
96946
  "lib/storage/media-store.ts"() {
96947
+ "use strict";
96877
96948
  init_media_types();
96878
96949
  init_idb();
96879
96950
  init_media_hash();
@@ -252666,7 +252737,6 @@ function resizeWindow(doc2, target2, rect) {
252666
252737
  }
252667
252738
  var init_crop = __esm({
252668
252739
  "lib/editor/crop.ts"() {
252669
- "use strict";
252670
252740
  init_dist_node();
252671
252741
  init_scene_graph();
252672
252742
  init_photo_frames();
@@ -257163,7 +257233,6 @@ function followPeers(peers) {
257163
257233
  var PALETTE, usePresence, awareness, CURSOR_SEND_MS, VIEWPORT_SEND_MS, cursorTimer, pendingCursor, sentCursor, EMOTE_MS, lastFollowCamera;
257164
257234
  var init_presence = __esm({
257165
257235
  "lib/collab/presence.ts"() {
257166
- "use strict";
257167
257236
  init_esm();
257168
257237
  init_editor_store();
257169
257238
  init_status_announcements();
@@ -262771,7 +262840,6 @@ function formatDate(date5, opts = { month: "short", day: "numeric", year: "numer
262771
262840
  var cache5, nf;
262772
262841
  var init_format = __esm({
262773
262842
  "lib/i18n/format.ts"() {
262774
- "use strict";
262775
262843
  init_runtime();
262776
262844
  cache5 = /* @__PURE__ */ new Map();
262777
262845
  nf = (opts) => cached2("n", opts, (l) => new Intl.NumberFormat(l, opts));
@@ -312398,7 +312466,6 @@ function creditLine(c2) {
312398
312466
  var MAX_PHOTO_PAGE, MAX_PHOTO_QUERY, UUID, isPhotoId, photoImagePath;
312399
312467
  var init_stock = __esm({
312400
312468
  "lib/photos/stock.ts"() {
312401
- "use strict";
312402
312469
  MAX_PHOTO_PAGE = 12;
312403
312470
  MAX_PHOTO_QUERY = 200;
312404
312471
  UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -313060,7 +313127,6 @@ function applyTextPath(layout2, path, tp, rebase = true) {
313060
313127
  var defaultCircleRadius, ownsPath, mapPoint;
313061
313128
  var init_text_path = __esm({
313062
313129
  "lib/engine/text/text-path.ts"() {
313063
- "use strict";
313064
313130
  init_scene_graph();
313065
313131
  init_transform();
313066
313132
  init_shape_to_path();
@@ -313178,7 +313244,6 @@ function areaBounds(rings) {
313178
313244
  }
313179
313245
  var init_text_area = __esm({
313180
313246
  "lib/engine/text/text-area.ts"() {
313181
- "use strict";
313182
313247
  }
313183
313248
  });
313184
313249
 
@@ -317615,7 +317680,6 @@ async function selectionReferenceImages(doc2, selection, opts = {}) {
317615
317680
  var FIT_QUALITIES, FIT_SCALES, blobToDataUrl;
317616
317681
  var init_reference_images = __esm({
317617
317682
  "lib/ai/reference-images.ts"() {
317618
- "use strict";
317619
317683
  init_export();
317620
317684
  init_selection_bounds();
317621
317685
  init_renderer_registry();
@@ -319394,6 +319458,7 @@ var nodeFind, nodeGet, nodeMeasure, docOutline, CREATABLE, nodeCreate, FORBIDDEN
319394
319458
  var init_node = __esm({
319395
319459
  "lib/commands/node.ts"() {
319396
319460
  "use strict";
319461
+ init_z_order();
319397
319462
  init_zod();
319398
319463
  init_limits();
319399
319464
  init_search();
@@ -320051,7 +320116,7 @@ var init_node = __esm({
320051
320116
  run: (args2, ctx2) => {
320052
320117
  const { doc: doc2, ids: ids2 } = resolveTargets(ctx2, args2.ids, "order");
320053
320118
  let next2 = doc2;
320054
- for (const id3 of ids2) next2 = moveNodeInZOrder(next2, id3, args2.direction);
320119
+ next2 = reorderSelection(next2, ids2, args2.direction);
320055
320120
  ctx2.commit(next2);
320056
320121
  return { summary: `Moved ${plural2(ids2.length, "layer")} ${args2.direction}`, data: { ids: ids2 } };
320057
320122
  }
@@ -328843,7 +328908,7 @@ var init_package = __esm({
328843
328908
  "packages/runtime/package.json"() {
328844
328909
  package_default = {
328845
328910
  name: "@popcraft/runtime",
328846
- version: "0.53.15",
328911
+ version: "0.53.16",
328847
328912
  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.",
328848
328913
  license: "MIT",
328849
328914
  homepage: "https://popcraft.app/docs/exporting/nextjs",
@@ -408095,6 +408160,8 @@ function placeInstance(document2, mainComponentId, pageId2, x2, y) {
408095
408160
  var STICKY_PROP_KEYS, initialDocument, initialPageId, TABS_PREFS_KEY, isUnsavedPlaceholder, libraryDocs, markLibraryDocument, isPersistableDocument, resetLibraryDocuments, MAX_OPEN_NODES, sessionDocumentInLibrary, saveFailureNotified, saveTimeout, latestValue, isSaving, firstPendingAt, SAVE_IDLE_MS, SAVE_MAX_WAIT_MS, pendingSave, customIdbPersistStorage, readOnlyToldAt, useEditorStore, useSelection, useActiveTool, useCamera, useCurrentPageId, useDocument, glideToken, useMode;
408096
408161
  var init_editor_store = __esm({
408097
408162
  "lib/store/editor-store.ts"() {
408163
+ init_z_order();
408164
+ init_selection_drill();
408098
408165
  init_history_group();
408099
408166
  init_pixel_art();
408100
408167
  init_runtime();
@@ -409310,12 +409377,29 @@ var init_editor_store = __esm({
409310
409377
  const topLevelNodes = nodes.filter((n) => !n.parentId || !clipboardIds.has(n.parentId));
409311
409378
  const newNodes = { ...doc2.nodes };
409312
409379
  const updatedParents = /* @__PURE__ */ new Map();
409380
+ const PASTE_INTO = /* @__PURE__ */ new Set(["FRAME", "COMPONENT", "SECTION"]);
409381
+ const sel = state.selection.length === 1 ? doc2.nodes[state.selection[0]] : void 0;
409382
+ const into = sel && PASTE_INTO.has(sel.type) && !clipboardIds.has(sel.id) ? sel : void 0;
409383
+ const pageOf4 = (d, id3) => {
409384
+ let n = d.nodes[id3];
409385
+ for (let guard2 = 0; n && n.type !== "PAGE" && guard2 < 64; guard2++) n = n.parentId ? d.nodes[n.parentId] : void 0;
409386
+ return n?.id;
409387
+ };
409388
+ const parentFor = (n) => {
409389
+ if (into) return into.id;
409390
+ if (n.parentId && doc2.nodes[n.parentId] && doc2.nodes[n.parentId].type !== "PAGE" && pageOf4(doc2, n.parentId) === state.currentPageId) return n.parentId;
409391
+ return state.currentPageId;
409392
+ };
409313
409393
  nodes.forEach((n) => {
409314
409394
  const newNode = { ...n, id: idMap.get(n.id) };
409315
409395
  if (topLevelNodes.includes(n)) {
409316
409396
  newNode.x += offset.x;
409317
409397
  newNode.y += offset.y;
409318
- newNode.parentId = state.currentPageId;
409398
+ newNode.parentId = parentFor(n);
409399
+ if (into && n.parentId !== into.id && (newNode.x < 0 || newNode.y < 0 || newNode.x > into.width || newNode.y > into.height)) {
409400
+ newNode.x = (into.width - newNode.width) / 2;
409401
+ newNode.y = (into.height - newNode.height) / 2;
409402
+ }
409319
409403
  newSelection.push(newNode.id);
409320
409404
  } else {
409321
409405
  newNode.parentId = idMap.get(n.parentId);
@@ -409489,10 +409573,7 @@ var init_editor_store = __esm({
409489
409573
  })),
409490
409574
  selectAll: () => {
409491
409575
  const state = get4();
409492
- const page = state.document.nodes[state.currentPageId];
409493
- if (page) {
409494
- set4({ selection: [...page.childIds] });
409495
- }
409576
+ set4({ selection: selectAllTargets(state.document, state.currentPageId, state.selection) });
409496
409577
  },
409497
409578
  deselectAll: () => set4({ selection: [] }),
409498
409579
  toggleSelectionVisibility: () => {
@@ -410257,57 +410338,59 @@ var init_editor_store = __esm({
410257
410338
  }
410258
410339
  };
410259
410340
  }),
410260
- // Z-order actions
410261
- bringToFront: () => {
410341
+ // Z-order actions: the selection moves as a block, keeps its own order, and can be undone (lib/document/z-order.ts).
410342
+ bringToFront: () => get4().reorderSelectionZ("top"),
410343
+ sendToBack: () => get4().reorderSelectionZ("bottom"),
410344
+ bringForward: () => get4().reorderSelectionZ("up"),
410345
+ sendBackward: () => get4().reorderSelectionZ("down"),
410346
+ reorderSelectionZ: (dir) => {
410262
410347
  const state = get4();
410263
- state.selection.forEach((id3) => {
410264
- set4({ document: moveNodeInZOrder(get4().document, id3, "top") });
410265
- });
410266
- },
410267
- sendToBack: () => {
410268
- const state = get4();
410269
- state.selection.forEach((id3) => {
410270
- set4({ document: moveNodeInZOrder(get4().document, id3, "bottom") });
410271
- });
410272
- },
410273
- bringForward: () => {
410274
- const state = get4();
410275
- state.selection.forEach((id3) => {
410276
- set4({ document: moveNodeInZOrder(get4().document, id3, "up") });
410277
- });
410278
- },
410279
- sendBackward: () => {
410280
- const state = get4();
410281
- state.selection.forEach((id3) => {
410282
- set4({ document: moveNodeInZOrder(get4().document, id3, "down") });
410283
- });
410348
+ const next2 = reorderSelection(state.document, state.selection, dir);
410349
+ if (next2 === state.document) return;
410350
+ const label3 = { top: "Bring to front", bottom: "Send to back", up: "Bring forward", down: "Send backward" }[dir];
410351
+ set4({ document: next2, history: pushCommand(state.history, createCommand("REORDER", label3, state.document, next2)) });
410284
410352
  },
410285
410353
  // Group actions
410286
410354
  groupSelection: () => {
410287
410355
  const state = get4();
410288
410356
  if (state.selection.length < 2) return;
410289
410357
  const documentBefore = state.document;
410358
+ let base = state.document;
410359
+ const order2 = /* @__PURE__ */ new Map();
410360
+ const walk4 = (id3) => {
410361
+ order2.set(id3, order2.size);
410362
+ for (const c2 of base.nodes[id3]?.childIds ?? []) walk4(c2);
410363
+ };
410364
+ walk4(state.currentPageId);
410365
+ const topmost = [...state.selection].sort((x2, y) => (order2.get(y) ?? 0) - (order2.get(x2) ?? 0))[0];
410366
+ const target2 = base.nodes[topmost]?.parentId ?? state.currentPageId;
410367
+ for (const id3 of state.selection) {
410368
+ const n = base.nodes[id3];
410369
+ if (!n || n.parentId === target2) continue;
410370
+ const placed2 = placementUnder(base, id3, target2);
410371
+ if (placed2) base = updateNode(base, id3, placed2);
410372
+ base = reparentNode(base, id3, target2);
410373
+ }
410290
410374
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
410291
410375
  state.selection.forEach((id3) => {
410292
- const n = state.document.nodes[id3];
410376
+ const n = base.nodes[id3];
410293
410377
  if (!n) return;
410294
410378
  minX = Math.min(minX, n.x);
410295
410379
  minY = Math.min(minY, n.y);
410296
410380
  maxX = Math.max(maxX, n.x + n.width);
410297
410381
  maxY = Math.max(maxY, n.y + n.height);
410298
410382
  });
410299
- const firstNode = state.document.nodes[state.selection[0]];
410300
- const parentId = firstNode?.parentId ?? state.currentPageId;
410383
+ const parentId = target2;
410301
410384
  const group2 = createGroup([]);
410302
410385
  group2.x = minX;
410303
410386
  group2.y = minY;
410304
410387
  group2.width = maxX - minX;
410305
410388
  group2.height = maxY - minY;
410306
410389
  group2.name = "Group";
410307
- const siblings = state.document.nodes[parentId]?.childIds ?? [];
410390
+ const siblings = base.nodes[parentId]?.childIds ?? [];
410308
410391
  const ordered2 = [...state.selection].sort((a, b) => siblings.indexOf(a) - siblings.indexOf(b));
410309
410392
  const top = Math.max(...ordered2.map((id3) => siblings.indexOf(id3)));
410310
- let doc2 = addNode(state.document, group2, parentId);
410393
+ let doc2 = addNode(base, group2, parentId);
410311
410394
  if (top >= 0) doc2 = reparentNode(doc2, group2.id, parentId, top + 1);
410312
410395
  ordered2.forEach((id3) => {
410313
410396
  doc2 = reparentNode(doc2, id3, group2.id);
@@ -410339,8 +410422,9 @@ var init_editor_store = __esm({
410339
410422
  return;
410340
410423
  }
410341
410424
  const parentId = node2.parentId ?? state.currentPageId;
410342
- node2.childIds.forEach((childId) => {
410343
- doc2 = reparentNode(doc2, childId, parentId);
410425
+ const slot2 = doc2.nodes[parentId]?.childIds.indexOf(id3) ?? -1;
410426
+ node2.childIds.forEach((childId, i2) => {
410427
+ doc2 = reparentNode(doc2, childId, parentId, slot2 >= 0 ? slot2 + i2 : void 0);
410344
410428
  const child = doc2.nodes[childId];
410345
410429
  if (child) {
410346
410430
  doc2.nodes[childId] = {
@@ -414448,7 +414532,7 @@ init_resources();
414448
414532
  init_desktop();
414449
414533
  init_hypery();
414450
414534
  import { createInterface } from "node:readline";
414451
- var VERSION2 = "0.53.15";
414535
+ var VERSION2 = "0.53.16";
414452
414536
  var HELP = `popcraft ${VERSION2} \u2014 the PopCraft command line
414453
414537
 
414454
414538
  Files (headless, on .popcraft files):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@popcraft/cli",
3
- "version": "0.53.15",
3
+ "version": "0.53.16",
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.53.15"
37
+ "@popcraft/kit": "0.53.16"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "node build.mjs",