@pixldocs/canvas-renderer 0.3.15 → 0.3.17
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/canvasWatermark-BgiyK4gu.js +115 -0
- package/dist/canvasWatermark-BgiyK4gu.js.map +1 -0
- package/dist/canvasWatermark-C7Jk6O8G.cjs +115 -0
- package/dist/canvasWatermark-C7Jk6O8G.cjs.map +1 -0
- package/dist/index.cjs +83 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +83 -40
- 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;
|
|
@@ -207,6 +203,8 @@ export declare interface RenderFromFormOptions extends Omit<RenderOptions, 'page
|
|
|
207
203
|
formSchemaId: string;
|
|
208
204
|
sectionState: SectionFormState;
|
|
209
205
|
themeId?: string;
|
|
206
|
+
/** Whether to inject watermark on preview. Default: auto (true for paid templates, false for free). */
|
|
207
|
+
watermark?: boolean;
|
|
210
208
|
}
|
|
211
209
|
|
|
212
210
|
export declare interface RenderOptions {
|
|
@@ -239,6 +237,8 @@ export declare interface ResolvedTemplate {
|
|
|
239
237
|
config: TemplateConfig;
|
|
240
238
|
templateName: string;
|
|
241
239
|
templateId: string;
|
|
240
|
+
/** Template price — 0 = free, >0 = paid (watermark applies) */
|
|
241
|
+
price: number;
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
/**
|
package/dist/index.js
CHANGED
|
@@ -10074,7 +10074,7 @@ async function resolveTemplateData(options) {
|
|
|
10074
10074
|
const defaultData = template.default_data;
|
|
10075
10075
|
if (defaultData) config = applyFormDataSimple(config, defaultData);
|
|
10076
10076
|
if (formData && Object.keys(formData).length > 0) config = applyFormDataSimple(config, formData);
|
|
10077
|
-
return { config, templateName: template.name || "Untitled", templateId };
|
|
10077
|
+
return { config, templateName: template.name || "Untitled", templateId, price: template.price ?? 0 };
|
|
10078
10078
|
}
|
|
10079
10079
|
async function resolveFromForm(options) {
|
|
10080
10080
|
var _a, _b, _c, _d;
|
|
@@ -10215,7 +10215,8 @@ async function resolveFromForm(options) {
|
|
|
10215
10215
|
return {
|
|
10216
10216
|
config: resolvedConfig,
|
|
10217
10217
|
templateName: templateRow.name || "Untitled",
|
|
10218
|
-
templateId
|
|
10218
|
+
templateId,
|
|
10219
|
+
price: templateRow.price ?? 0
|
|
10219
10220
|
};
|
|
10220
10221
|
}
|
|
10221
10222
|
function flattenAll(nodes) {
|
|
@@ -10665,7 +10666,7 @@ class PixldocsRenderer {
|
|
|
10665
10666
|
* This is the primary external API for the package.
|
|
10666
10667
|
*/
|
|
10667
10668
|
async renderFromForm(options) {
|
|
10668
|
-
const { templateId, formSchemaId, sectionState, themeId, ...renderOpts } = options;
|
|
10669
|
+
const { templateId, formSchemaId, sectionState, themeId, watermark, ...renderOpts } = options;
|
|
10669
10670
|
const resolved = await resolveFromForm({
|
|
10670
10671
|
templateId,
|
|
10671
10672
|
formSchemaId,
|
|
@@ -10674,7 +10675,13 @@ class PixldocsRenderer {
|
|
|
10674
10675
|
supabaseUrl: this.config.supabaseUrl,
|
|
10675
10676
|
supabaseAnonKey: this.config.supabaseAnonKey
|
|
10676
10677
|
});
|
|
10677
|
-
|
|
10678
|
+
const shouldWatermark = watermark ?? resolved.price > 0;
|
|
10679
|
+
let configToRender = resolved.config;
|
|
10680
|
+
if (shouldWatermark) {
|
|
10681
|
+
const { injectWatermark } = await import("./canvasWatermark-BgiyK4gu.js");
|
|
10682
|
+
configToRender = injectWatermark(configToRender);
|
|
10683
|
+
}
|
|
10684
|
+
return this.renderAllPages(configToRender, renderOpts);
|
|
10678
10685
|
}
|
|
10679
10686
|
/**
|
|
10680
10687
|
* Convenience: fetch by ID with simple flat data and render.
|
|
@@ -10689,50 +10696,85 @@ class PixldocsRenderer {
|
|
|
10689
10696
|
return this.render(resolved.config, options);
|
|
10690
10697
|
}
|
|
10691
10698
|
// ─── Internal: render a page using the full PreviewCanvas engine ───
|
|
10692
|
-
|
|
10693
|
-
|
|
10694
|
-
|
|
10695
|
-
|
|
10696
|
-
|
|
10697
|
-
|
|
10699
|
+
getExpectedImageCount(config, pageIndex) {
|
|
10700
|
+
const page = config.pages[pageIndex];
|
|
10701
|
+
if (!(page == null ? void 0 : page.children)) return 0;
|
|
10702
|
+
let count = 0;
|
|
10703
|
+
const walk = (nodes) => {
|
|
10704
|
+
for (const node of nodes) {
|
|
10705
|
+
if (!node || node.visible === false) continue;
|
|
10706
|
+
const src = typeof node.src === "string" ? node.src.trim() : "";
|
|
10707
|
+
const imageUrl = typeof node.imageUrl === "string" ? node.imageUrl.trim() : "";
|
|
10708
|
+
if (node.type === "image" && (src || imageUrl)) count += 1;
|
|
10709
|
+
if (Array.isArray(node.children) && node.children.length > 0) {
|
|
10710
|
+
walk(node.children);
|
|
10711
|
+
}
|
|
10712
|
+
}
|
|
10713
|
+
};
|
|
10714
|
+
walk(page.children);
|
|
10715
|
+
return count;
|
|
10716
|
+
}
|
|
10717
|
+
waitForCanvasImages(container, expectedImageCount, maxWaitMs = 15e3, pollMs = 120) {
|
|
10698
10718
|
return new Promise((resolve) => {
|
|
10699
10719
|
const start = Date.now();
|
|
10720
|
+
let stableFrames = 0;
|
|
10721
|
+
const isRenderableImage = (value) => value instanceof HTMLImageElement && value.complete && value.naturalWidth > 0 && value.naturalHeight > 0;
|
|
10722
|
+
const collectRenderableImages = (obj, seen) => {
|
|
10723
|
+
if (!obj || typeof obj !== "object") return;
|
|
10724
|
+
const candidates = [obj._element, obj._originalElement, obj._filteredEl, obj._cacheCanvasEl];
|
|
10725
|
+
for (const candidate of candidates) {
|
|
10726
|
+
if (isRenderableImage(candidate)) {
|
|
10727
|
+
seen.add(candidate);
|
|
10728
|
+
} else if (candidate instanceof HTMLImageElement) {
|
|
10729
|
+
return false;
|
|
10730
|
+
}
|
|
10731
|
+
}
|
|
10732
|
+
const nested = Array.isArray(obj._objects) ? obj._objects : Array.isArray(obj.objects) ? obj.objects : [];
|
|
10733
|
+
for (const child of nested) {
|
|
10734
|
+
if (collectRenderableImages(child, seen) === false) return false;
|
|
10735
|
+
}
|
|
10736
|
+
return true;
|
|
10737
|
+
};
|
|
10738
|
+
const getFabricCanvas = () => {
|
|
10739
|
+
const registry2 = window.__fabricCanvasRegistry;
|
|
10740
|
+
if (registry2 instanceof Map) {
|
|
10741
|
+
for (const entry of registry2.values()) {
|
|
10742
|
+
const canvas = entry == null ? void 0 : entry.canvas;
|
|
10743
|
+
const el = (canvas == null ? void 0 : canvas.lowerCanvasEl) || (canvas == null ? void 0 : canvas.upperCanvasEl);
|
|
10744
|
+
if (el && container.contains(el)) return canvas;
|
|
10745
|
+
}
|
|
10746
|
+
}
|
|
10747
|
+
return null;
|
|
10748
|
+
};
|
|
10749
|
+
const settle = () => requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
10700
10750
|
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
|
-
}
|
|
10751
|
+
const elapsed = Date.now() - start;
|
|
10752
|
+
const domImages = Array.from(container.querySelectorAll("img"));
|
|
10753
|
+
const allDomLoaded = domImages.every((img) => img.complete && img.naturalWidth > 0 && img.naturalHeight > 0);
|
|
10754
|
+
const fabricCanvas = getFabricCanvas();
|
|
10755
|
+
const fabricObjects = fabricCanvas && typeof fabricCanvas.getObjects === "function" ? fabricCanvas.getObjects() : [];
|
|
10756
|
+
const renderableImages = /* @__PURE__ */ new Set();
|
|
10757
|
+
const fabricReady = fabricObjects.every((obj) => collectRenderableImages(obj, renderableImages) !== false);
|
|
10758
|
+
const actualImageCount = Math.max(domImages.length, renderableImages.size);
|
|
10759
|
+
!!fabricCanvas && !!(fabricCanvas.lowerCanvasEl || fabricCanvas.upperCanvasEl);
|
|
10760
|
+
const hasExpectedAssets = expectedImageCount === 0 ? true : actualImageCount >= expectedImageCount;
|
|
10761
|
+
const ready = allDomLoaded && fabricReady && hasExpectedAssets;
|
|
10762
|
+
if (ready) {
|
|
10763
|
+
stableFrames += 1;
|
|
10764
|
+
if (stableFrames >= 2) {
|
|
10765
|
+
settle();
|
|
10766
|
+
return;
|
|
10727
10767
|
}
|
|
10768
|
+
} else {
|
|
10769
|
+
stableFrames = 0;
|
|
10728
10770
|
}
|
|
10729
|
-
if (
|
|
10730
|
-
|
|
10771
|
+
if (elapsed >= maxWaitMs) {
|
|
10772
|
+
settle();
|
|
10731
10773
|
return;
|
|
10732
10774
|
}
|
|
10733
10775
|
setTimeout(check, pollMs);
|
|
10734
10776
|
};
|
|
10735
|
-
setTimeout(check,
|
|
10777
|
+
setTimeout(check, 0);
|
|
10736
10778
|
});
|
|
10737
10779
|
}
|
|
10738
10780
|
getNormalizedGradientStops(gradient) {
|
|
@@ -10833,7 +10875,8 @@ class PixldocsRenderer {
|
|
|
10833
10875
|
container.remove();
|
|
10834
10876
|
};
|
|
10835
10877
|
const onReady = () => {
|
|
10836
|
-
this.
|
|
10878
|
+
const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
|
|
10879
|
+
this.waitForCanvasImages(container, expectedImageCount).then(() => {
|
|
10837
10880
|
try {
|
|
10838
10881
|
const fabricCanvas = container.querySelector("canvas.upper-canvas, canvas");
|
|
10839
10882
|
if (!fabricCanvas) {
|