@pixldocs/canvas-renderer 0.5.189 → 0.5.190

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.
package/README.md CHANGED
@@ -483,7 +483,7 @@ const blurFieldIds = ['text-reference-name', 'text-phone', 'text-address'];
483
483
  the resolved config before handing it to the imperative renderer, so the
484
484
  blur is baked into the exported pixels.
485
485
 
486
- ### Biodata teaser previews — blur by flat form key (v0.5.187+, hardened in v0.5.189)
486
+ ### Biodata teaser previews — blur by flat form key (v0.5.187+, hardened in v0.5.189, pagination-safe in v0.5.190)
487
487
 
488
488
  Form-driven apps (BioMaker, the pixldocs.com Use page, etc.) already
489
489
  speak the **flat form-key** language produced by `applyFormDataToConfig`
@@ -530,11 +530,17 @@ Notes:
530
530
  with or without the wrapper `field_` prefix). **As of v0.5.189**
531
531
  every resolved id is then verified against the actual rendered page
532
532
  tree (`config.pages[*]`) — stale or alias map entries that don't
533
- match a real element are dropped silently. This eliminates the
534
- "phantom frost rectangle near a section title" class of bug that
535
- showed up in templates with nested repeatables, where
536
- `__cloneIdMap` returned ids like `text-…__cgroup-…_e4` but the
537
- rendered tree used `text-…__cgrp-…_pN_grp-…_eN`.
533
+ match a real element are dropped silently.
534
+ - **As of v0.5.190** `applyContentBoundsPagination` rewrites
535
+ `__cloneIdMap` after pagination so flat keys for overflow rows that
536
+ moved to continuation pages still resolve to ids that exist on the
537
+ tree (clones inherit `__sourceId` from the original element). If the
538
+ map is still stale for any reason, the resolver also falls back to
539
+ walking the page tree and matching `__sourceId` / `__baseNodeId`
540
+ against the raw resolved ids — the same strategy the theming pipeline
541
+ uses to track paginated clones. End result: frosted blur for row N
542
+ appears on whichever page row N actually renders on, even when
543
+ content-bounds pagination moved it.
538
544
  - Pass `pageIndex` in `blurFlatFormKeyOptions` to scope verification
539
545
  to a single page — clones that landed on a different page will not
540
546
  contribute overlays to this page. This is the recommended pattern
@@ -13327,6 +13327,7 @@ function isStaticOnNewPage(node) {
13327
13327
  function cloneNodeWithNewIds(node) {
13328
13328
  const base = node.__baseNodeId;
13329
13329
  const source = node.__sourceId;
13330
+ const effectiveSource = source ?? node.id;
13330
13331
  if (isGroup(node)) {
13331
13332
  const g = node;
13332
13333
  const cloned2 = {
@@ -13335,14 +13336,14 @@ function cloneNodeWithNewIds(node) {
13335
13336
  children: (g.children ?? []).map(cloneNodeWithNewIds)
13336
13337
  };
13337
13338
  if (base != null) cloned2.__baseNodeId = base;
13338
- if (source != null) cloned2.__sourceId = source;
13339
+ cloned2.__sourceId = effectiveSource;
13339
13340
  return cloned2;
13340
13341
  }
13341
13342
  const el = node;
13342
13343
  const prefix = el.type === "text" ? "text" : el.type === "image" ? "img" : el.type === "shape" ? "shape" : "line";
13343
13344
  const cloned = { ...el, id: generateId(prefix) };
13344
13345
  if (base != null) cloned.__baseNodeId = base;
13345
- if (source != null) cloned.__sourceId = source;
13346
+ cloned.__sourceId = effectiveSource;
13346
13347
  return cloned;
13347
13348
  }
13348
13349
  function cloneNodeWithStableIds(node, baseId2, path) {
@@ -13648,7 +13649,51 @@ function applyContentBoundsPagination(config) {
13648
13649
  resultPages.push(...paginated);
13649
13650
  }
13650
13651
  if (!mutated) return config;
13651
- return { ...config, pages: resultPages };
13652
+ const next = { ...config, pages: resultPages };
13653
+ remapCloneIdMapAfterPagination(next);
13654
+ return next;
13655
+ }
13656
+ function remapCloneIdMapAfterPagination(config) {
13657
+ const cloneIdMap = config.__cloneIdMap;
13658
+ if (!cloneIdMap || typeof cloneIdMap !== "object") return;
13659
+ const allIds = /* @__PURE__ */ new Set();
13660
+ const sourceToNew = /* @__PURE__ */ new Map();
13661
+ const walk = (node) => {
13662
+ if (!node || typeof node !== "object") return;
13663
+ const n = node;
13664
+ if (typeof n.id === "string") {
13665
+ allIds.add(n.id);
13666
+ const src = n.__sourceId;
13667
+ if (typeof src === "string" && src !== n.id) {
13668
+ const arr = sourceToNew.get(src);
13669
+ if (arr) arr.push(n.id);
13670
+ else sourceToNew.set(src, [n.id]);
13671
+ }
13672
+ }
13673
+ const children = n.children;
13674
+ if (Array.isArray(children)) for (const c of children) walk(c);
13675
+ };
13676
+ for (const page of config.pages ?? []) {
13677
+ const ch = page.children;
13678
+ if (Array.isArray(ch)) for (const c of ch) walk(c);
13679
+ }
13680
+ const updated = {};
13681
+ for (const [key, val] of Object.entries(cloneIdMap)) {
13682
+ const oldIds = Array.isArray(val) ? val : [val];
13683
+ const newIds = [];
13684
+ for (const oid of oldIds) {
13685
+ if (typeof oid !== "string") continue;
13686
+ if (allIds.has(oid)) newIds.push(oid);
13687
+ const clones = sourceToNew.get(oid);
13688
+ if (clones) {
13689
+ for (const c of clones) if (allIds.has(c)) newIds.push(c);
13690
+ }
13691
+ }
13692
+ if (newIds.length === 0) continue;
13693
+ const uniq = Array.from(new Set(newIds));
13694
+ updated[key] = uniq.length === 1 ? uniq[0] : uniq;
13695
+ }
13696
+ config.__cloneIdMap = updated;
13652
13697
  }
13653
13698
  const __vite_import_meta_env__ = {};
13654
13699
  const FONT_WEIGHT_LABELS = {
@@ -16274,6 +16319,32 @@ function collectPageTreeElementIds(config, pageIndex = "all") {
16274
16319
  }
16275
16320
  return out;
16276
16321
  }
16322
+ function collectIdsBySourceMatch(config, targetIds, pageIndex = "all") {
16323
+ const targets = /* @__PURE__ */ new Set();
16324
+ for (const t of targetIds) if (typeof t === "string" && t) targets.add(t);
16325
+ if (targets.size === 0) return [];
16326
+ const pages = config == null ? void 0 : config.pages;
16327
+ if (!Array.isArray(pages)) return [];
16328
+ const visitPages = pageIndex === "all" ? pages : pages[pageIndex] != null ? [pages[pageIndex]] : [];
16329
+ const out = /* @__PURE__ */ new Set();
16330
+ const walk = (node) => {
16331
+ if (!node || typeof node !== "object") return;
16332
+ const src = typeof node.__sourceId === "string" ? node.__sourceId : void 0;
16333
+ const base = typeof node.__baseNodeId === "string" ? node.__baseNodeId : void 0;
16334
+ if (typeof node.id === "string") {
16335
+ if (targets.has(node.id)) out.add(node.id);
16336
+ else if (src && targets.has(src)) out.add(node.id);
16337
+ else if (base && targets.has(base)) out.add(node.id);
16338
+ }
16339
+ const children = node.children || node.elements;
16340
+ if (Array.isArray(children)) for (const c of children) walk(c);
16341
+ };
16342
+ for (const page of visitPages) {
16343
+ const children = (page == null ? void 0 : page.children) || (page == null ? void 0 : page.elements);
16344
+ if (Array.isArray(children)) for (const c of children) walk(c);
16345
+ }
16346
+ return Array.from(out);
16347
+ }
16277
16348
  function resolveBlurElementExactIdsFromFlatFormKeys(config, flatFormKeys, options) {
16278
16349
  const cloneIdMap = (config == null ? void 0 : config.__cloneIdMap) || {};
16279
16350
  if (!cloneIdMap || typeof cloneIdMap !== "object") return [];
@@ -16307,7 +16378,8 @@ function resolveBlurElementExactIdsFromFlatFormKeys(config, flatFormKeys, option
16307
16378
  if (treeIds.size === 0) return Array.from(out);
16308
16379
  const verified = [];
16309
16380
  for (const id of out) if (treeIds.has(id)) verified.push(id);
16310
- return verified;
16381
+ if (verified.length > 0) return verified;
16382
+ return collectIdsBySourceMatch(config, out, (options == null ? void 0 : options.pageIndex) ?? "all");
16311
16383
  }
16312
16384
  function buildTeaserBlurFlatKeys(sectionState, sections, options) {
16313
16385
  const afterRow = Math.max(0, options.afterRow | 0);
@@ -16835,9 +16907,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
16835
16907
  }
16836
16908
  return svgString;
16837
16909
  }
16838
- const resolvedPackageVersion = "0.5.189";
16910
+ const resolvedPackageVersion = "0.5.190";
16839
16911
  const PACKAGE_VERSION = resolvedPackageVersion;
16840
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.189";
16912
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.190";
16841
16913
  const roundParityValue = (value) => {
16842
16914
  if (typeof value !== "number") return value;
16843
16915
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -17345,7 +17417,7 @@ class PixldocsRenderer {
17345
17417
  await this.waitForCanvasScene(container, cloned, i);
17346
17418
  }
17347
17419
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
17348
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BAAJU0RL.cjs"));
17420
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-Cgw8dB-L.cjs"));
17349
17421
  const prepared = preparePagesForExport(
17350
17422
  cloned.pages,
17351
17423
  canvasWidth,
@@ -19490,7 +19562,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
19490
19562
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
19491
19563
  sanitizeSvgTreeForPdf(svgToDraw);
19492
19564
  try {
19493
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BAAJU0RL.cjs"));
19565
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-Cgw8dB-L.cjs"));
19494
19566
  try {
19495
19567
  await logTextMeasurementDiagnostic(svgToDraw);
19496
19568
  } catch {
@@ -19887,4 +19959,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
19887
19959
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
19888
19960
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
19889
19961
  exports.warmTemplateFromForm = warmTemplateFromForm;
19890
- //# sourceMappingURL=index-CmrxeQ_K.cjs.map
19962
+ //# sourceMappingURL=index-BUm3wqlB.cjs.map