@pixldocs/canvas-renderer 0.3.15 → 0.3.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.
- package/dist/index.cjs +72 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.js +72 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -179,11 +179,7 @@ export declare class PixldocsRenderer {
|
|
|
179
179
|
* Convenience: fetch by ID with simple flat data and render.
|
|
180
180
|
*/
|
|
181
181
|
renderById(templateId: string, formData?: Record<string, any>, options?: RenderOptions): Promise<RenderResult>;
|
|
182
|
-
|
|
183
|
-
* Wait until every image on the Fabric canvas inside the container has loaded.
|
|
184
|
-
* Checks both DOM <img> elements AND Fabric canvas image objects to ensure
|
|
185
|
-
* all async assets are fully painted before capture.
|
|
186
|
-
*/
|
|
182
|
+
private getExpectedImageCount;
|
|
187
183
|
private waitForCanvasImages;
|
|
188
184
|
private getNormalizedGradientStops;
|
|
189
185
|
private paintPageBackground;
|
package/dist/index.js
CHANGED
|
@@ -10689,50 +10689,85 @@ class PixldocsRenderer {
|
|
|
10689
10689
|
return this.render(resolved.config, options);
|
|
10690
10690
|
}
|
|
10691
10691
|
// ─── Internal: render a page using the full PreviewCanvas engine ───
|
|
10692
|
-
|
|
10693
|
-
|
|
10694
|
-
|
|
10695
|
-
|
|
10696
|
-
|
|
10697
|
-
|
|
10692
|
+
getExpectedImageCount(config, pageIndex) {
|
|
10693
|
+
const page = config.pages[pageIndex];
|
|
10694
|
+
if (!(page == null ? void 0 : page.children)) return 0;
|
|
10695
|
+
let count = 0;
|
|
10696
|
+
const walk = (nodes) => {
|
|
10697
|
+
for (const node of nodes) {
|
|
10698
|
+
if (!node || node.visible === false) continue;
|
|
10699
|
+
const src = typeof node.src === "string" ? node.src.trim() : "";
|
|
10700
|
+
const imageUrl = typeof node.imageUrl === "string" ? node.imageUrl.trim() : "";
|
|
10701
|
+
if (node.type === "image" && (src || imageUrl)) count += 1;
|
|
10702
|
+
if (Array.isArray(node.children) && node.children.length > 0) {
|
|
10703
|
+
walk(node.children);
|
|
10704
|
+
}
|
|
10705
|
+
}
|
|
10706
|
+
};
|
|
10707
|
+
walk(page.children);
|
|
10708
|
+
return count;
|
|
10709
|
+
}
|
|
10710
|
+
waitForCanvasImages(container, expectedImageCount, maxWaitMs = 15e3, pollMs = 120) {
|
|
10698
10711
|
return new Promise((resolve) => {
|
|
10699
10712
|
const start = Date.now();
|
|
10713
|
+
let stableFrames = 0;
|
|
10714
|
+
const isRenderableImage = (value) => value instanceof HTMLImageElement && value.complete && value.naturalWidth > 0 && value.naturalHeight > 0;
|
|
10715
|
+
const collectRenderableImages = (obj, seen) => {
|
|
10716
|
+
if (!obj || typeof obj !== "object") return;
|
|
10717
|
+
const candidates = [obj._element, obj._originalElement, obj._filteredEl, obj._cacheCanvasEl];
|
|
10718
|
+
for (const candidate of candidates) {
|
|
10719
|
+
if (isRenderableImage(candidate)) {
|
|
10720
|
+
seen.add(candidate);
|
|
10721
|
+
} else if (candidate instanceof HTMLImageElement) {
|
|
10722
|
+
return false;
|
|
10723
|
+
}
|
|
10724
|
+
}
|
|
10725
|
+
const nested = Array.isArray(obj._objects) ? obj._objects : Array.isArray(obj.objects) ? obj.objects : [];
|
|
10726
|
+
for (const child of nested) {
|
|
10727
|
+
if (collectRenderableImages(child, seen) === false) return false;
|
|
10728
|
+
}
|
|
10729
|
+
return true;
|
|
10730
|
+
};
|
|
10731
|
+
const getFabricCanvas = () => {
|
|
10732
|
+
const registry2 = window.__fabricCanvasRegistry;
|
|
10733
|
+
if (registry2 instanceof Map) {
|
|
10734
|
+
for (const entry of registry2.values()) {
|
|
10735
|
+
const canvas = entry == null ? void 0 : entry.canvas;
|
|
10736
|
+
const el = (canvas == null ? void 0 : canvas.lowerCanvasEl) || (canvas == null ? void 0 : canvas.upperCanvasEl);
|
|
10737
|
+
if (el && container.contains(el)) return canvas;
|
|
10738
|
+
}
|
|
10739
|
+
}
|
|
10740
|
+
return null;
|
|
10741
|
+
};
|
|
10742
|
+
const settle = () => requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
10700
10743
|
const check = () => {
|
|
10701
|
-
const
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
for (const child of obj._objects) {
|
|
10718
|
-
const childEl = child._element || child._originalElement;
|
|
10719
|
-
if (childEl instanceof HTMLImageElement && !childEl.complete) {
|
|
10720
|
-
allLoaded = false;
|
|
10721
|
-
break;
|
|
10722
|
-
}
|
|
10723
|
-
}
|
|
10724
|
-
if (!allLoaded) break;
|
|
10725
|
-
}
|
|
10726
|
-
}
|
|
10744
|
+
const elapsed = Date.now() - start;
|
|
10745
|
+
const domImages = Array.from(container.querySelectorAll("img"));
|
|
10746
|
+
const allDomLoaded = domImages.every((img) => img.complete && img.naturalWidth > 0 && img.naturalHeight > 0);
|
|
10747
|
+
const fabricCanvas = getFabricCanvas();
|
|
10748
|
+
const fabricObjects = fabricCanvas && typeof fabricCanvas.getObjects === "function" ? fabricCanvas.getObjects() : [];
|
|
10749
|
+
const renderableImages = /* @__PURE__ */ new Set();
|
|
10750
|
+
const fabricReady = fabricObjects.every((obj) => collectRenderableImages(obj, renderableImages) !== false);
|
|
10751
|
+
const actualImageCount = Math.max(domImages.length, renderableImages.size);
|
|
10752
|
+
!!fabricCanvas && !!(fabricCanvas.lowerCanvasEl || fabricCanvas.upperCanvasEl);
|
|
10753
|
+
const hasExpectedAssets = expectedImageCount === 0 ? true : actualImageCount >= expectedImageCount;
|
|
10754
|
+
const ready = allDomLoaded && fabricReady && hasExpectedAssets;
|
|
10755
|
+
if (ready) {
|
|
10756
|
+
stableFrames += 1;
|
|
10757
|
+
if (stableFrames >= 2) {
|
|
10758
|
+
settle();
|
|
10759
|
+
return;
|
|
10727
10760
|
}
|
|
10761
|
+
} else {
|
|
10762
|
+
stableFrames = 0;
|
|
10728
10763
|
}
|
|
10729
|
-
if (
|
|
10730
|
-
|
|
10764
|
+
if (elapsed >= maxWaitMs) {
|
|
10765
|
+
settle();
|
|
10731
10766
|
return;
|
|
10732
10767
|
}
|
|
10733
10768
|
setTimeout(check, pollMs);
|
|
10734
10769
|
};
|
|
10735
|
-
setTimeout(check,
|
|
10770
|
+
setTimeout(check, 0);
|
|
10736
10771
|
});
|
|
10737
10772
|
}
|
|
10738
10773
|
getNormalizedGradientStops(gradient) {
|
|
@@ -10833,7 +10868,8 @@ class PixldocsRenderer {
|
|
|
10833
10868
|
container.remove();
|
|
10834
10869
|
};
|
|
10835
10870
|
const onReady = () => {
|
|
10836
|
-
this.
|
|
10871
|
+
const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
|
|
10872
|
+
this.waitForCanvasImages(container, expectedImageCount).then(() => {
|
|
10837
10873
|
try {
|
|
10838
10874
|
const fabricCanvas = container.querySelector("canvas.upper-canvas, canvas");
|
|
10839
10875
|
if (!fabricCanvas) {
|