@pixldocs/canvas-renderer 0.5.495 → 0.5.497
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-Cvi3YYOq.js → index-CKhnRi3S.js} +617 -117
- package/dist/index-CKhnRi3S.js.map +1 -0
- package/dist/{index-DaaT4Mo7.cjs → index-CZm1oVfa.cjs} +600 -100
- package/dist/index-CZm1oVfa.cjs.map +1 -0
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +31 -0
- package/dist/index.js +18 -17
- package/dist/{vectorPdfExport-B6m8o09g.js → vectorPdfExport-DV-TJwjP.js} +4 -4
- package/dist/{vectorPdfExport-B6m8o09g.js.map → vectorPdfExport-DV-TJwjP.js.map} +1 -1
- package/dist/{vectorPdfExport-roj_Ddzd.cjs → vectorPdfExport-De8UFmDy.cjs} +4 -4
- package/dist/{vectorPdfExport-roj_Ddzd.cjs.map → vectorPdfExport-De8UFmDy.cjs.map} +1 -1
- package/package.json +1 -1
- package/dist/canvasWatermark-B0ab38Ok.cjs +0 -123
- package/dist/canvasWatermark-B0ab38Ok.cjs.map +0 -1
- package/dist/canvasWatermark-pkhacGge.js +0 -123
- package/dist/canvasWatermark-pkhacGge.js.map +0 -1
- package/dist/index-Cvi3YYOq.js.map +0 -1
- package/dist/index-DaaT4Mo7.cjs.map +0 -1
|
@@ -112,6 +112,15 @@ const generateId = (prefix = "el") => {
|
|
|
112
112
|
return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).substr(2, 9)}-${Math.random().toString(36).substr(2, 9)}`;
|
|
113
113
|
};
|
|
114
114
|
const createDefaultElement = (partial) => {
|
|
115
|
+
const loose = partial;
|
|
116
|
+
if (loose.type === "frame" || loose.type === "group") {
|
|
117
|
+
return createDefaultGroup({
|
|
118
|
+
layoutMode: loose.layout,
|
|
119
|
+
...partial,
|
|
120
|
+
type: "group",
|
|
121
|
+
children: Array.isArray(loose.children) ? loose.children : []
|
|
122
|
+
});
|
|
123
|
+
}
|
|
115
124
|
const isText = partial.type === "text";
|
|
116
125
|
const base = {
|
|
117
126
|
left: 48,
|
|
@@ -129,7 +138,7 @@ const createDefaultElement = (partial) => {
|
|
|
129
138
|
originY: "top",
|
|
130
139
|
opacity: 1,
|
|
131
140
|
fill: "#e2e8f0",
|
|
132
|
-
...isText ? {} : { stroke: "
|
|
141
|
+
...isText ? {} : { stroke: "transparent", strokeWidth: 0 },
|
|
133
142
|
visible: true,
|
|
134
143
|
selectable: true,
|
|
135
144
|
evented: true,
|
|
@@ -975,49 +984,15 @@ function worldPointToParentLocal(worldX, worldY, parent, pageChildren, resolveGr
|
|
|
975
984
|
);
|
|
976
985
|
return { left: local.x, top: local.y };
|
|
977
986
|
}
|
|
978
|
-
function unbakeChildrenToGroupLocal(group) {
|
|
979
|
-
const angle = getGroupAngleDeg(group);
|
|
980
|
-
if (Math.abs(angle) < 0.01) return group;
|
|
981
|
-
const { width, height } = getGroupFrameSize(group);
|
|
982
|
-
const cx = width / 2;
|
|
983
|
-
const cy = height / 2;
|
|
984
|
-
const inv = rotateAroundAffDeg(-angle, cx, cy);
|
|
985
|
-
const kids = (group.children ?? []).map((child) => {
|
|
986
|
-
const p = applyAff(inv, child.left ?? 0, child.top ?? 0);
|
|
987
|
-
const childAngle = typeof child.angle === "number" ? child.angle : 0;
|
|
988
|
-
const localAngle = normalizeAngleDeg(childAngle - angle);
|
|
989
|
-
if (isGroup(child)) {
|
|
990
|
-
const relocated = {
|
|
991
|
-
...child,
|
|
992
|
-
left: p.x,
|
|
993
|
-
top: p.y,
|
|
994
|
-
angle: localAngle
|
|
995
|
-
};
|
|
996
|
-
return Math.abs(getGroupAngleDeg(relocated)) > 0.01 ? unbakeChildrenToGroupLocal(relocated) : relocated;
|
|
997
|
-
}
|
|
998
|
-
return {
|
|
999
|
-
...child,
|
|
1000
|
-
left: p.x,
|
|
1001
|
-
top: p.y,
|
|
1002
|
-
angle: localAngle
|
|
1003
|
-
};
|
|
1004
|
-
});
|
|
1005
|
-
return { ...group, children: kids };
|
|
1006
|
-
}
|
|
1007
987
|
function migratePageTreeToGroupOwnedTransforms(nodes) {
|
|
1008
988
|
return nodes.map((node) => {
|
|
1009
989
|
if (!isGroup(node)) return node;
|
|
1010
990
|
const g = node;
|
|
1011
|
-
|
|
991
|
+
const next = {
|
|
1012
992
|
...g,
|
|
1013
993
|
children: migratePageTreeToGroupOwnedTransforms(g.children ?? [])
|
|
1014
994
|
};
|
|
1015
|
-
if (isRotatableGroup(next)
|
|
1016
|
-
if (g.groupTransformModel !== "owned-v1") {
|
|
1017
|
-
next = unbakeChildrenToGroupLocal(next);
|
|
1018
|
-
next.groupTransformModel = "owned-v1";
|
|
1019
|
-
}
|
|
1020
|
-
} else if (isRotatableGroup(next)) {
|
|
995
|
+
if (isRotatableGroup(next)) {
|
|
1021
996
|
next.groupTransformModel = "owned-v1";
|
|
1022
997
|
}
|
|
1023
998
|
return next;
|
|
@@ -2257,6 +2232,40 @@ function adaptLayoutGrid(grid, mode) {
|
|
|
2257
2232
|
const cells = (grid.cells ?? []).map((c) => c && c.grid ? { ...c, grid: adaptLayoutGrid(c.grid, mode) } : c);
|
|
2258
2233
|
return { ...grid, dir: grid.dir === from ? to : grid.dir, cells };
|
|
2259
2234
|
}
|
|
2235
|
+
function isAspectLockedNode(node) {
|
|
2236
|
+
const e = node;
|
|
2237
|
+
if (!e) return false;
|
|
2238
|
+
if (e.lockAspect === true) return true;
|
|
2239
|
+
if (e.clipShape === "circle") return true;
|
|
2240
|
+
const kind = e.componentKind || e.smartType;
|
|
2241
|
+
return kind === "qrcode" || kind === "barcode";
|
|
2242
|
+
}
|
|
2243
|
+
function scaleNodeForReflow(node, sx, sy, fscale) {
|
|
2244
|
+
const n = node;
|
|
2245
|
+
const el = { ...n };
|
|
2246
|
+
const hasBox = typeof n.width === "number" && typeof n.height === "number";
|
|
2247
|
+
const f = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
2248
|
+
if (hasBox && isAspectLockedNode(n) && sx !== sy) {
|
|
2249
|
+
const s = Math.min(sx, sy);
|
|
2250
|
+
const cx = (f(n.left) + n.width / 2) * sx;
|
|
2251
|
+
const cy = (f(n.top) + n.height / 2) * sy;
|
|
2252
|
+
el.width = n.width * s;
|
|
2253
|
+
el.height = n.height * s;
|
|
2254
|
+
el.left = cx - el.width / 2;
|
|
2255
|
+
el.top = cy - el.height / 2;
|
|
2256
|
+
} else {
|
|
2257
|
+
if (typeof el.left === "number") el.left = el.left * sx;
|
|
2258
|
+
if (typeof el.top === "number") el.top = el.top * sy;
|
|
2259
|
+
if (typeof el.width === "number") el.width = el.width * sx;
|
|
2260
|
+
if (typeof el.height === "number") el.height = el.height * sy;
|
|
2261
|
+
}
|
|
2262
|
+
if (typeof el.fontSize === "number") el.fontSize = Math.max(4, el.fontSize * fscale);
|
|
2263
|
+
if (typeof el.minBoxHeight === "number") el.minBoxHeight = el.minBoxHeight * sy;
|
|
2264
|
+
if (Array.isArray(el.children)) {
|
|
2265
|
+
el.children = el.children.map((c) => scaleNodeForReflow(c, sx, sy, fscale));
|
|
2266
|
+
}
|
|
2267
|
+
return el;
|
|
2268
|
+
}
|
|
2260
2269
|
function computeGridHandles(grid, box, gridPath = []) {
|
|
2261
2270
|
const out = [];
|
|
2262
2271
|
const n = grid.cells.length;
|
|
@@ -2659,16 +2668,7 @@ const reflowPagesFromBase = (base, W, H) => {
|
|
|
2659
2668
|
const fscale = Math.sqrt(Math.max(0.01, sx * sy));
|
|
2660
2669
|
const adapt = layoutAdaptationFor(base.width, base.height, W, H);
|
|
2661
2670
|
const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
2662
|
-
const scaleNode = (node) =>
|
|
2663
|
-
const el = { ...node };
|
|
2664
|
-
if (typeof el.left === "number") el.left = el.left * sx;
|
|
2665
|
-
if (typeof el.top === "number") el.top = el.top * sy;
|
|
2666
|
-
if (typeof el.width === "number") el.width = el.width * sx;
|
|
2667
|
-
if (typeof el.height === "number") el.height = el.height * sy;
|
|
2668
|
-
if (typeof el.fontSize === "number") el.fontSize = Math.max(4, el.fontSize * fscale);
|
|
2669
|
-
if (Array.isArray(el.children)) el.children = el.children.map(scaleNode);
|
|
2670
|
-
return el;
|
|
2671
|
-
};
|
|
2671
|
+
const scaleNode = (node) => scaleNodeForReflow(node, sx, sy, fscale);
|
|
2672
2672
|
return base.pages.map((p) => {
|
|
2673
2673
|
const pg = p;
|
|
2674
2674
|
const page = {
|
|
@@ -3257,6 +3257,13 @@ const useEditorStore = zustand.create((set, get) => ({
|
|
|
3257
3257
|
return { canvas: nextCanvas, ...committed };
|
|
3258
3258
|
});
|
|
3259
3259
|
},
|
|
3260
|
+
getCanvasForSave: () => {
|
|
3261
|
+
const { canvas } = get();
|
|
3262
|
+
const base = sizeBaseSnapshot;
|
|
3263
|
+
if (!base) return canvas;
|
|
3264
|
+
if (canvas.width === base.width && canvas.height === base.height) return canvas;
|
|
3265
|
+
return { ...canvas, width: base.width, height: base.height, pages: base.pages };
|
|
3266
|
+
},
|
|
3260
3267
|
addSizeVariant: (variant) => set((state) => {
|
|
3261
3268
|
const sizes = state.canvas.sizes ?? [];
|
|
3262
3269
|
if (sizes.some((s) => s.id === variant.id)) return {};
|
|
@@ -6354,8 +6361,13 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
|
|
|
6354
6361
|
});
|
|
6355
6362
|
const imgLoadOptions = url.startsWith("data:") || url.startsWith("blob:") ? {} : { crossOrigin: "anonymous" };
|
|
6356
6363
|
const img = await fabric__namespace.FabricImage.fromURL(url, imgLoadOptions);
|
|
6357
|
-
if (!fabricRef.current) return;
|
|
6364
|
+
if (fabricRef && !fabricRef.current) return;
|
|
6358
6365
|
await normalizeSvgImageDimensions(img, imageUrl, element.sourceFormat);
|
|
6366
|
+
const natW = img.width ?? 0;
|
|
6367
|
+
const natH = img.height ?? 0;
|
|
6368
|
+
if (natW <= 1 && natH <= 1 && Number(element.width) > 8 && Number(element.height) > 8) {
|
|
6369
|
+
throw new Error(`image decoded to ${natW}x${natH} — treating as failed load`);
|
|
6370
|
+
}
|
|
6359
6371
|
const isHidden = !element.visible;
|
|
6360
6372
|
img.set({
|
|
6361
6373
|
originX: "left",
|
|
@@ -6510,8 +6522,14 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
|
|
|
6510
6522
|
shape,
|
|
6511
6523
|
rx: rxRatio,
|
|
6512
6524
|
// Pass ratio, not pixel value
|
|
6513
|
-
|
|
6514
|
-
|
|
6525
|
+
// Image outline is an ELEMENT property (imageBorder*), not the generic
|
|
6526
|
+
// shape stroke — this builder forwarded only stroke/strokeWidth, so
|
|
6527
|
+
// outline/gap never reached it.
|
|
6528
|
+
stroke: (element.imageBorderWidth ?? 0) > 0 ? element.imageBorderColor ?? "#FFFFFF" : element.stroke,
|
|
6529
|
+
strokeWidth: (element.imageBorderWidth ?? 0) > 0 ? element.imageBorderWidth : element.strokeWidth,
|
|
6530
|
+
borderPadding: element.imageBorderPadding ?? 0,
|
|
6531
|
+
borderPaddingColor: element.imageBorderPaddingColor ?? "transparent",
|
|
6532
|
+
borderPosition: element.imageBorderPosition ?? "outside",
|
|
6515
6533
|
panX,
|
|
6516
6534
|
panY,
|
|
6517
6535
|
zoom
|
|
@@ -6547,9 +6565,111 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
|
|
|
6547
6565
|
proxiedUrl: getProxiedImageUrl(imageUrl).slice(0, 240),
|
|
6548
6566
|
error: error instanceof Error ? error.message : String(error)
|
|
6549
6567
|
});
|
|
6568
|
+
if (fc.__pixldocsEditMode === true) {
|
|
6569
|
+
try {
|
|
6570
|
+
markPlaceholderAsBrokenImage(placeholder);
|
|
6571
|
+
fc.requestRenderAll();
|
|
6572
|
+
} catch {
|
|
6573
|
+
}
|
|
6574
|
+
}
|
|
6550
6575
|
return;
|
|
6551
6576
|
}
|
|
6552
6577
|
}
|
|
6578
|
+
function markPlaceholderAsBrokenImage(placeholder) {
|
|
6579
|
+
if (!(placeholder instanceof fabric__namespace.Group)) return;
|
|
6580
|
+
const group = placeholder;
|
|
6581
|
+
if (group.__pixldocsBrokenImage) return;
|
|
6582
|
+
group.__pixldocsBrokenImage = true;
|
|
6583
|
+
const frameChild = group.getObjects().find(
|
|
6584
|
+
(o) => o.__isPlaceholderFrame
|
|
6585
|
+
);
|
|
6586
|
+
const w = Math.max(1, (frameChild == null ? void 0 : frameChild.width) ?? group.width ?? 1);
|
|
6587
|
+
const h = Math.max(1, (frameChild == null ? void 0 : frameChild.height) ?? group.height ?? 1);
|
|
6588
|
+
const center = group.getCenterPoint();
|
|
6589
|
+
const cx = center.x;
|
|
6590
|
+
const cy = center.y;
|
|
6591
|
+
const prevPose = { left: group.left, top: group.top, width: group.width, height: group.height };
|
|
6592
|
+
const bg = new fabric__namespace.Rect({
|
|
6593
|
+
originX: "center",
|
|
6594
|
+
originY: "center",
|
|
6595
|
+
left: cx,
|
|
6596
|
+
top: cy,
|
|
6597
|
+
width: w,
|
|
6598
|
+
height: h,
|
|
6599
|
+
fill: "rgba(148, 163, 184, 0.12)",
|
|
6600
|
+
stroke: "#94A3B8",
|
|
6601
|
+
strokeWidth: 1.5,
|
|
6602
|
+
strokeDashArray: [6, 4]
|
|
6603
|
+
});
|
|
6604
|
+
const s = Math.max(16, Math.min(w, h) * 0.28);
|
|
6605
|
+
const glyphStroke = { stroke: "#64748B", strokeWidth: Math.max(1.5, s / 12), fill: "transparent" };
|
|
6606
|
+
const iconFrame = new fabric__namespace.Rect({
|
|
6607
|
+
originX: "center",
|
|
6608
|
+
originY: "center",
|
|
6609
|
+
left: cx,
|
|
6610
|
+
top: cy,
|
|
6611
|
+
width: s,
|
|
6612
|
+
height: s * 0.8,
|
|
6613
|
+
rx: s * 0.08,
|
|
6614
|
+
ry: s * 0.08,
|
|
6615
|
+
...glyphStroke
|
|
6616
|
+
});
|
|
6617
|
+
const mountain = new fabric__namespace.Polyline(
|
|
6618
|
+
[
|
|
6619
|
+
{ x: -s * 0.38, y: s * 0.24 },
|
|
6620
|
+
{ x: -s * 0.1, y: -s * 0.08 },
|
|
6621
|
+
{ x: s * 0.08, y: s * 0.1 },
|
|
6622
|
+
{ x: s * 0.22, y: -s * 0.02 },
|
|
6623
|
+
{ x: s * 0.38, y: s * 0.24 }
|
|
6624
|
+
],
|
|
6625
|
+
{ originX: "center", originY: "center", left: cx, top: cy + s * 0.08, ...glyphStroke }
|
|
6626
|
+
);
|
|
6627
|
+
const slash = new fabric__namespace.Line([cx - s * 0.55, cy - s * 0.5, cx + s * 0.55, cy + s * 0.5], {
|
|
6628
|
+
...glyphStroke,
|
|
6629
|
+
originX: "center",
|
|
6630
|
+
originY: "center",
|
|
6631
|
+
left: cx,
|
|
6632
|
+
top: cy
|
|
6633
|
+
});
|
|
6634
|
+
for (const obj of [bg, iconFrame, mountain, slash]) {
|
|
6635
|
+
obj.set({ selectable: false, evented: false, excludeFromExport: true });
|
|
6636
|
+
obj.__pixldocsEditorChrome = true;
|
|
6637
|
+
group.add(obj);
|
|
6638
|
+
}
|
|
6639
|
+
group.set(prevPose);
|
|
6640
|
+
group.setCoords();
|
|
6641
|
+
group.dirty = true;
|
|
6642
|
+
}
|
|
6643
|
+
function hideEditorChromeForExport(fc) {
|
|
6644
|
+
const hidden = [];
|
|
6645
|
+
const walk = (objs) => {
|
|
6646
|
+
var _a2;
|
|
6647
|
+
for (const o of objs) {
|
|
6648
|
+
if (o.__pixldocsEditorChrome && o.visible !== false) {
|
|
6649
|
+
o.visible = false;
|
|
6650
|
+
hidden.push(o);
|
|
6651
|
+
}
|
|
6652
|
+
const kids = (_a2 = o.getObjects) == null ? void 0 : _a2.call(o);
|
|
6653
|
+
if (kids == null ? void 0 : kids.length) walk(kids);
|
|
6654
|
+
}
|
|
6655
|
+
};
|
|
6656
|
+
walk(fc.getObjects());
|
|
6657
|
+
if (hidden.length) {
|
|
6658
|
+
for (const o of hidden) {
|
|
6659
|
+
const g = o.group;
|
|
6660
|
+
if (g) g.dirty = true;
|
|
6661
|
+
}
|
|
6662
|
+
fc.renderAll();
|
|
6663
|
+
}
|
|
6664
|
+
return () => {
|
|
6665
|
+
for (const o of hidden) {
|
|
6666
|
+
o.visible = true;
|
|
6667
|
+
const g = o.group;
|
|
6668
|
+
if (g) g.dirty = true;
|
|
6669
|
+
}
|
|
6670
|
+
if (hidden.length) fc.requestRenderAll();
|
|
6671
|
+
};
|
|
6672
|
+
}
|
|
6553
6673
|
const canvasImageLoader = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
6554
6674
|
__proto__: null,
|
|
6555
6675
|
SVG_DECODE_HARD_CAP,
|
|
@@ -6559,12 +6679,14 @@ const canvasImageLoader = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.d
|
|
|
6559
6679
|
fetchSvgTextPublic,
|
|
6560
6680
|
getNormalizedSvgUrl,
|
|
6561
6681
|
getProxiedImageUrl,
|
|
6682
|
+
hideEditorChromeForExport,
|
|
6562
6683
|
isBundledAssetUrl,
|
|
6563
6684
|
isEmptyImagePlaceholderGroup,
|
|
6564
6685
|
isPrivateUrl,
|
|
6565
6686
|
isSvgImage,
|
|
6566
6687
|
loadImageAsync,
|
|
6567
6688
|
loadSvgDimensions,
|
|
6689
|
+
markPlaceholderAsBrokenImage,
|
|
6568
6690
|
normalizeSvgImageDimensions,
|
|
6569
6691
|
parseSvgDimensionsFromText,
|
|
6570
6692
|
preloadImage,
|
|
@@ -7062,10 +7184,10 @@ function finalizeCropGroupCoords(g) {
|
|
|
7062
7184
|
g.setCoords();
|
|
7063
7185
|
}
|
|
7064
7186
|
function updateCoverLayout(g) {
|
|
7065
|
-
var _a2;
|
|
7187
|
+
var _a2, _b2;
|
|
7066
7188
|
const ct = g.__cropData;
|
|
7067
7189
|
if (!ct) return;
|
|
7068
|
-
const { frameW, frameH, shape, rx: rxRatio, _img: img
|
|
7190
|
+
const { frameW, frameH, shape, rx: rxRatio, _img: img } = ct;
|
|
7069
7191
|
const minDim = Math.min(frameW, frameH);
|
|
7070
7192
|
let rx = rxRatio > 0.5 ? rxRatio : rxRatio * minDim;
|
|
7071
7193
|
rx = Math.max(0, Math.min(rx, frameW / 2, frameH / 2));
|
|
@@ -7198,25 +7320,31 @@ function updateCoverLayout(g) {
|
|
|
7198
7320
|
g.clipPath.excludeFromExport = true;
|
|
7199
7321
|
}
|
|
7200
7322
|
}
|
|
7323
|
+
const wantCircle = shape === "circle";
|
|
7324
|
+
const border = ensureRingShapeClass(g, ct, "_border", wantCircle);
|
|
7325
|
+
const mat = ensureRingShapeClass(g, ct, "_mat", wantCircle);
|
|
7201
7326
|
const bw = border ? Number(border.strokeWidth) || 0 : 0;
|
|
7202
|
-
const mat = ct._mat;
|
|
7203
7327
|
const pad = Math.max(0, Number(ct.borderPadding) || 0);
|
|
7328
|
+
const outward = (ct.borderPosition ?? "outside") === "outside";
|
|
7204
7329
|
const borderMinDim = Math.min(frameW, frameH);
|
|
7205
7330
|
let borderRx = rxRatio > 0.5 ? rxRatio : rxRatio * borderMinDim;
|
|
7206
7331
|
borderRx = Math.max(0, Math.min(borderRx, frameW / 2, frameH / 2));
|
|
7332
|
+
const geo = computeOutlineGeometry({ frameW, frameH, bw, pad, rx: borderRx, outward });
|
|
7207
7333
|
if (border) {
|
|
7208
7334
|
if (shape === "circle") {
|
|
7209
|
-
border.set({ rx:
|
|
7335
|
+
border.set({ rx: geo.border.width / 2, ry: geo.border.height / 2 });
|
|
7210
7336
|
} else {
|
|
7211
|
-
border.set({ width:
|
|
7337
|
+
border.set({ width: geo.border.width, height: geo.border.height, rx: geo.border.rx, ry: geo.border.rx });
|
|
7212
7338
|
}
|
|
7339
|
+
border.dirty = true;
|
|
7213
7340
|
}
|
|
7214
7341
|
if (mat) {
|
|
7215
7342
|
if (shape === "circle") {
|
|
7216
|
-
mat.set({ rx:
|
|
7343
|
+
mat.set({ rx: geo.mat.width / 2, ry: geo.mat.height / 2 });
|
|
7217
7344
|
} else {
|
|
7218
|
-
mat.set({ width:
|
|
7345
|
+
mat.set({ width: geo.mat.width, height: geo.mat.height, rx: geo.mat.rx, ry: geo.mat.rx });
|
|
7219
7346
|
}
|
|
7347
|
+
mat.dirty = true;
|
|
7220
7348
|
}
|
|
7221
7349
|
if (!img) {
|
|
7222
7350
|
const placeholderFrame = ct._placeholderFrame ?? ((_a2 = g._objects) == null ? void 0 : _a2.find((obj) => obj.__isPlaceholderFrame));
|
|
@@ -7245,8 +7373,9 @@ function updateCoverLayout(g) {
|
|
|
7245
7373
|
img._ct.panX = img.__panX ?? 0.5;
|
|
7246
7374
|
img._ct.panY = img.__panY ?? 0.5;
|
|
7247
7375
|
}
|
|
7248
|
-
const
|
|
7249
|
-
const
|
|
7376
|
+
const srcEl = img._originalElement ?? ((_b2 = img.getElement) == null ? void 0 : _b2.call(img));
|
|
7377
|
+
const iw = Number(srcEl == null ? void 0 : srcEl.naturalWidth) || Number(srcEl == null ? void 0 : srcEl.width) || img.width || 1;
|
|
7378
|
+
const ih = Number(srcEl == null ? void 0 : srcEl.naturalHeight) || Number(srcEl == null ? void 0 : srcEl.height) || img.height || 1;
|
|
7250
7379
|
const fitContain = ct.fit === "contain";
|
|
7251
7380
|
const baseScale = fitContain ? Math.min(frameW / iw, frameH / ih) : Math.max(frameW / iw, frameH / ih);
|
|
7252
7381
|
const zoom = fitContain ? Math.max(1, Math.min(3, ct.containScale ?? 1)) : Math.max(1, img._ct.zoom ?? 1);
|
|
@@ -7283,6 +7412,42 @@ function updateCoverLayout(g) {
|
|
|
7283
7412
|
offsetY = overflowY > 0 ? -overflowY * (panY - 0.5) : 0;
|
|
7284
7413
|
}
|
|
7285
7414
|
img.set({ left: offsetX, top: offsetY });
|
|
7415
|
+
const wantsOutline = bw > 0 || pad > 0;
|
|
7416
|
+
const shapedMask = shape === "circle" || shape === "roundRect";
|
|
7417
|
+
if (wantsOutline && shapedMask) {
|
|
7418
|
+
if (g.clipPath) {
|
|
7419
|
+
img.clipPath = g.clipPath;
|
|
7420
|
+
g.clipPath = void 0;
|
|
7421
|
+
}
|
|
7422
|
+
if (img.cropX || img.cropY || img.width !== iw) {
|
|
7423
|
+
img.set({ width: iw, height: ih, cropX: 0, cropY: 0 });
|
|
7424
|
+
}
|
|
7425
|
+
} else if (wantsOutline && !fitContain) {
|
|
7426
|
+
const regionW = Math.min(iw, frameW / finalScale);
|
|
7427
|
+
const regionH = Math.min(ih, frameH / finalScale);
|
|
7428
|
+
img.set({
|
|
7429
|
+
width: regionW,
|
|
7430
|
+
height: regionH,
|
|
7431
|
+
cropX: (iw - regionW) * panX,
|
|
7432
|
+
cropY: (ih - regionH) * panY,
|
|
7433
|
+
left: 0,
|
|
7434
|
+
top: 0
|
|
7435
|
+
});
|
|
7436
|
+
img.clipPath = void 0;
|
|
7437
|
+
g.clipPath = void 0;
|
|
7438
|
+
} else {
|
|
7439
|
+
if (img.clipPath) img.clipPath = void 0;
|
|
7440
|
+
if (img.cropX || img.cropY || img.width !== iw) {
|
|
7441
|
+
img.set({ width: iw, height: ih, cropX: 0, cropY: 0 });
|
|
7442
|
+
}
|
|
7443
|
+
}
|
|
7444
|
+
const imgClip = img.clipPath;
|
|
7445
|
+
if (imgClip && typeof imgClip.set === "function") {
|
|
7446
|
+
const csx = img.scaleX || 1;
|
|
7447
|
+
const csy = img.scaleY || 1;
|
|
7448
|
+
imgClip.set({ left: -offsetX / csx, top: -offsetY / csy, scaleX: 1 / csx, scaleY: 1 / csy });
|
|
7449
|
+
imgClip.dirty = true;
|
|
7450
|
+
}
|
|
7286
7451
|
g.dirty = true;
|
|
7287
7452
|
img.dirty = true;
|
|
7288
7453
|
if (g.clipPath) {
|
|
@@ -7633,6 +7798,51 @@ function installCanvaMaskControls(g) {
|
|
|
7633
7798
|
g.set(controlStyle);
|
|
7634
7799
|
g.setCoords();
|
|
7635
7800
|
}
|
|
7801
|
+
function ensureRingShapeClass(g, ct, key, wantCircle) {
|
|
7802
|
+
const cur = ct[key];
|
|
7803
|
+
if (!cur) return void 0;
|
|
7804
|
+
const isEllipse = cur instanceof fabric__namespace.Ellipse;
|
|
7805
|
+
if (isEllipse === wantCircle) return cur;
|
|
7806
|
+
const common = {
|
|
7807
|
+
left: 0,
|
|
7808
|
+
top: 0,
|
|
7809
|
+
originX: "center",
|
|
7810
|
+
originY: "center",
|
|
7811
|
+
fill: "transparent",
|
|
7812
|
+
stroke: cur.stroke,
|
|
7813
|
+
strokeWidth: cur.strokeWidth,
|
|
7814
|
+
selectable: false,
|
|
7815
|
+
evented: false
|
|
7816
|
+
};
|
|
7817
|
+
const next = wantCircle ? new fabric__namespace.Ellipse({ ...common, rx: 1, ry: 1, objectCaching: false }) : new fabric__namespace.Rect({ ...common, width: 1, height: 1, objectCaching: false });
|
|
7818
|
+
const objs = g._objects;
|
|
7819
|
+
const idx = objs ? objs.indexOf(cur) : -1;
|
|
7820
|
+
if (objs && idx >= 0) objs.splice(idx, 1, next);
|
|
7821
|
+
else return cur;
|
|
7822
|
+
next.group = cur.group ?? g;
|
|
7823
|
+
next.canvas = cur.canvas ?? g.canvas;
|
|
7824
|
+
cur.group = void 0;
|
|
7825
|
+
next.setCoords();
|
|
7826
|
+
ct[key] = next;
|
|
7827
|
+
g.dirty = true;
|
|
7828
|
+
return next;
|
|
7829
|
+
}
|
|
7830
|
+
function computeOutlineGeometry(opts) {
|
|
7831
|
+
const { frameW, frameH, bw, pad, rx, outward } = opts;
|
|
7832
|
+
if (outward) {
|
|
7833
|
+
const grow = (r, by) => r > 0 ? r + by : 0;
|
|
7834
|
+
return {
|
|
7835
|
+
// Ring centre-line is pad + bw/2 past the frame → inner edge exactly `pad` out.
|
|
7836
|
+
border: { width: frameW + 2 * pad + bw, height: frameH + 2 * pad + bw, rx: grow(rx, pad + bw / 2) },
|
|
7837
|
+
// The gap band is transparent; it exists only to keep the child list stable.
|
|
7838
|
+
mat: { width: frameW + pad, height: frameH + pad, rx: grow(rx, pad / 2) }
|
|
7839
|
+
};
|
|
7840
|
+
}
|
|
7841
|
+
return {
|
|
7842
|
+
border: { width: frameW - bw, height: frameH - bw, rx },
|
|
7843
|
+
mat: { width: frameW - 2 * bw - pad, height: frameH - 2 * bw - pad, rx: Math.max(0, rx - bw) }
|
|
7844
|
+
};
|
|
7845
|
+
}
|
|
7636
7846
|
async function createMaskedImageElement({
|
|
7637
7847
|
url,
|
|
7638
7848
|
image,
|
|
@@ -7661,7 +7871,8 @@ async function createMaskedImageElement({
|
|
|
7661
7871
|
containScale = 1,
|
|
7662
7872
|
shadow = null,
|
|
7663
7873
|
borderPadding = 0,
|
|
7664
|
-
borderPaddingColor = "
|
|
7874
|
+
borderPaddingColor = "transparent",
|
|
7875
|
+
borderPosition = "outside"
|
|
7665
7876
|
}) {
|
|
7666
7877
|
const img = image || (url ? await fabric__namespace.FabricImage.fromURL(getProxiedImageUrl(url), { crossOrigin: "anonymous" }) : null);
|
|
7667
7878
|
if (!img) {
|
|
@@ -7686,36 +7897,47 @@ async function createMaskedImageElement({
|
|
|
7686
7897
|
});
|
|
7687
7898
|
const bw = strokeWidth || 0;
|
|
7688
7899
|
const pad = Math.max(0, borderPadding || 0);
|
|
7900
|
+
const outward = borderPosition === "outside";
|
|
7901
|
+
const geo = computeOutlineGeometry({ frameW, frameH, bw, pad, rx, outward });
|
|
7902
|
+
const matStroke = outward ? borderPaddingColor || "transparent" : borderPaddingColor;
|
|
7903
|
+
const matW = geo.mat.width;
|
|
7904
|
+
const matH = geo.mat.height;
|
|
7905
|
+
const matRx = geo.mat.rx;
|
|
7689
7906
|
const mat = shape === "circle" ? new fabric__namespace.Ellipse({
|
|
7690
|
-
rx:
|
|
7691
|
-
ry:
|
|
7907
|
+
rx: matW / 2,
|
|
7908
|
+
ry: matH / 2,
|
|
7692
7909
|
left: 0,
|
|
7693
7910
|
top: 0,
|
|
7694
7911
|
originX: "center",
|
|
7695
7912
|
originY: "center",
|
|
7696
7913
|
fill: "transparent",
|
|
7697
|
-
stroke:
|
|
7914
|
+
stroke: matStroke,
|
|
7698
7915
|
strokeWidth: pad,
|
|
7699
7916
|
selectable: false,
|
|
7700
|
-
evented: false
|
|
7917
|
+
evented: false,
|
|
7918
|
+
objectCaching: false
|
|
7701
7919
|
}) : new fabric__namespace.Rect({
|
|
7702
|
-
width:
|
|
7703
|
-
height:
|
|
7704
|
-
rx:
|
|
7705
|
-
ry:
|
|
7920
|
+
width: matW,
|
|
7921
|
+
height: matH,
|
|
7922
|
+
rx: matRx,
|
|
7923
|
+
ry: matRx,
|
|
7706
7924
|
left: 0,
|
|
7707
7925
|
top: 0,
|
|
7708
7926
|
originX: "center",
|
|
7709
7927
|
originY: "center",
|
|
7710
7928
|
fill: "transparent",
|
|
7711
|
-
stroke:
|
|
7929
|
+
stroke: matStroke,
|
|
7712
7930
|
strokeWidth: pad,
|
|
7713
7931
|
selectable: false,
|
|
7714
|
-
evented: false
|
|
7932
|
+
evented: false,
|
|
7933
|
+
objectCaching: false
|
|
7715
7934
|
});
|
|
7935
|
+
const bordW = geo.border.width;
|
|
7936
|
+
const bordH = geo.border.height;
|
|
7937
|
+
const bordRx = geo.border.rx;
|
|
7716
7938
|
const border = shape === "circle" ? new fabric__namespace.Ellipse({
|
|
7717
|
-
rx:
|
|
7718
|
-
ry:
|
|
7939
|
+
rx: bordW / 2,
|
|
7940
|
+
ry: bordH / 2,
|
|
7719
7941
|
left: 0,
|
|
7720
7942
|
top: 0,
|
|
7721
7943
|
originX: "center",
|
|
@@ -7724,12 +7946,13 @@ async function createMaskedImageElement({
|
|
|
7724
7946
|
stroke: stroke || "transparent",
|
|
7725
7947
|
strokeWidth: bw,
|
|
7726
7948
|
selectable: false,
|
|
7727
|
-
evented: false
|
|
7949
|
+
evented: false,
|
|
7950
|
+
objectCaching: false
|
|
7728
7951
|
}) : new fabric__namespace.Rect({
|
|
7729
|
-
width:
|
|
7730
|
-
height:
|
|
7731
|
-
rx,
|
|
7732
|
-
ry:
|
|
7952
|
+
width: bordW,
|
|
7953
|
+
height: bordH,
|
|
7954
|
+
rx: bordRx,
|
|
7955
|
+
ry: bordRx,
|
|
7733
7956
|
left: 0,
|
|
7734
7957
|
top: 0,
|
|
7735
7958
|
originX: "center",
|
|
@@ -7738,7 +7961,8 @@ async function createMaskedImageElement({
|
|
|
7738
7961
|
stroke: stroke || "transparent",
|
|
7739
7962
|
strokeWidth: bw,
|
|
7740
7963
|
selectable: false,
|
|
7741
|
-
evented: false
|
|
7964
|
+
evented: false,
|
|
7965
|
+
objectCaching: false
|
|
7742
7966
|
});
|
|
7743
7967
|
img.set({
|
|
7744
7968
|
left: 0,
|
|
@@ -7832,7 +8056,9 @@ async function createMaskedImageElement({
|
|
|
7832
8056
|
_border: border,
|
|
7833
8057
|
_mat: mat,
|
|
7834
8058
|
borderPadding: pad,
|
|
7835
|
-
borderPaddingColor
|
|
8059
|
+
borderPaddingColor,
|
|
8060
|
+
// Read back by refreshMaskedImage so it recomputes with the same geometry.
|
|
8061
|
+
borderPosition
|
|
7836
8062
|
};
|
|
7837
8063
|
g._ct = g._ct || {};
|
|
7838
8064
|
g._ct.isCropGroup = true;
|
|
@@ -7866,7 +8092,12 @@ async function createMaskedImageElement({
|
|
|
7866
8092
|
});
|
|
7867
8093
|
clip.absolutePositioned = false;
|
|
7868
8094
|
clip.excludeFromExport = true;
|
|
7869
|
-
|
|
8095
|
+
if (outward) {
|
|
8096
|
+
img.clipPath = clip;
|
|
8097
|
+
g.clipPath = void 0;
|
|
8098
|
+
} else {
|
|
8099
|
+
g.clipPath = clip;
|
|
8100
|
+
}
|
|
7870
8101
|
g.set({
|
|
7871
8102
|
selectable: true,
|
|
7872
8103
|
evented: true,
|
|
@@ -17967,6 +18198,7 @@ const PageCanvas = react.forwardRef(
|
|
|
17967
18198
|
// Transparent so underlay (page bg + group bgs) shows through
|
|
17968
18199
|
backgroundColor: "transparent"
|
|
17969
18200
|
});
|
|
18201
|
+
fabricCanvas.__pixldocsEditMode = isEditorMode && !isPreviewMode;
|
|
17970
18202
|
fabricCanvas.hoverCursor = "default";
|
|
17971
18203
|
fabricCanvas.moveCursor = "move";
|
|
17972
18204
|
const suppressTextEditForClick = (textbox) => {
|
|
@@ -23956,11 +24188,33 @@ const PageCanvas = react.forwardRef(
|
|
|
23956
24188
|
const wantBW = Math.max(0, Number(element.imageBorderWidth) || 0);
|
|
23957
24189
|
const wantBC = element.imageBorderColor ?? "#FFFFFF";
|
|
23958
24190
|
const wantPad = Math.max(0, Number(element.imageBorderPadding) || 0);
|
|
23959
|
-
const wantPC = element.imageBorderPaddingColor ?? "
|
|
24191
|
+
const wantPC = element.imageBorderPaddingColor ?? "transparent";
|
|
24192
|
+
const wantPos = element.imageBorderPosition ?? "outside";
|
|
23960
24193
|
if (ct._border) ct._border.set({ stroke: wantBW > 0 ? wantBC : "transparent", strokeWidth: wantBW, dirty: true });
|
|
23961
24194
|
if (ct._mat) ct._mat.set({ stroke: wantPC, strokeWidth: wantPad, dirty: true });
|
|
23962
24195
|
ct.borderPadding = wantPad;
|
|
23963
24196
|
ct.borderPaddingColor = wantPC;
|
|
24197
|
+
ct.borderPosition = wantPos;
|
|
24198
|
+
{
|
|
24199
|
+
const gMinDim = Math.min(ct.frameW, ct.frameH);
|
|
24200
|
+
const rxRaw = ct.rx || 0;
|
|
24201
|
+
const gRx = Math.max(0, Math.min(rxRaw > 0.5 ? rxRaw : rxRaw * gMinDim, ct.frameW / 2, ct.frameH / 2));
|
|
24202
|
+
const gGeo = computeOutlineGeometry({
|
|
24203
|
+
frameW: ct.frameW,
|
|
24204
|
+
frameH: ct.frameH,
|
|
24205
|
+
bw: wantBW,
|
|
24206
|
+
pad: wantPad,
|
|
24207
|
+
rx: gRx,
|
|
24208
|
+
outward: wantPos === "outside"
|
|
24209
|
+
});
|
|
24210
|
+
const isCircle = (ct.shape || "rect") === "circle";
|
|
24211
|
+
if (ct._border) {
|
|
24212
|
+
ct._border.set(isCircle ? { rx: gGeo.border.width / 2, ry: gGeo.border.height / 2 } : { width: gGeo.border.width, height: gGeo.border.height, rx: gGeo.border.rx, ry: gGeo.border.rx });
|
|
24213
|
+
}
|
|
24214
|
+
if (ct._mat) {
|
|
24215
|
+
ct._mat.set(isCircle ? { rx: gGeo.mat.width / 2, ry: gGeo.mat.height / 2 } : { width: gGeo.mat.width, height: gGeo.mat.height, rx: gGeo.mat.rx, ry: gGeo.mat.rx });
|
|
24216
|
+
}
|
|
24217
|
+
}
|
|
23964
24218
|
const sBlur = Math.max(0, Number(element.imageShadowBlur) || 0);
|
|
23965
24219
|
const sColor = element.imageShadowColor;
|
|
23966
24220
|
if (sBlur > 0 || sColor) {
|
|
@@ -25270,6 +25524,7 @@ const PageCanvas = react.forwardRef(
|
|
|
25270
25524
|
} else if (obj instanceof fabric__namespace.Textbox) {
|
|
25271
25525
|
const overflowPolicy = element.overflowPolicy || "grow-and-push";
|
|
25272
25526
|
let text = element.text != null && element.text !== "" ? element.text : " ";
|
|
25527
|
+
text = applyElementTextCase(text, element.textCase);
|
|
25273
25528
|
let parsedStyles = null;
|
|
25274
25529
|
if (element.formattingEnabled === true) {
|
|
25275
25530
|
const parsed = parseTextMarkdown(text);
|
|
@@ -25914,6 +26169,13 @@ const PageCanvas = react.forwardRef(
|
|
|
25914
26169
|
const img = await fabric__namespace.FabricImage.fromURL(url, { crossOrigin: "anonymous" });
|
|
25915
26170
|
if (!fabricRef.current || !isLatestRequest()) return;
|
|
25916
26171
|
await normalizeSvgImageDimensions(img, imageUrl, element.sourceFormat, svgDecodeTarget);
|
|
26172
|
+
{
|
|
26173
|
+
const natW = img.width ?? 0;
|
|
26174
|
+
const natH = img.height ?? 0;
|
|
26175
|
+
if (natW <= 1 && natH <= 1 && Number(element.width) > 8 && Number(element.height) > 8) {
|
|
26176
|
+
throw new Error(`image decoded to ${natW}x${natH} — treating as failed load`);
|
|
26177
|
+
}
|
|
26178
|
+
}
|
|
25917
26179
|
if (!isLatestRequest()) return;
|
|
25918
26180
|
const imageFitForFade = element.imageFit || ((_a2 = element.style) == null ? void 0 : _a2.imageFit) || "cover";
|
|
25919
26181
|
const clipShapeForFade = element.clipShape ?? ((_b2 = element.style) == null ? void 0 : _b2.imageFrameShape) ?? (isPreviewMode ? "rectangle" : "none");
|
|
@@ -26121,7 +26383,9 @@ const PageCanvas = react.forwardRef(
|
|
|
26121
26383
|
strokeWidth: element.imageBorderWidth ?? 0,
|
|
26122
26384
|
// Gap between the image and the outline (the "matted photo" look).
|
|
26123
26385
|
borderPadding: element.imageBorderPadding ?? 0,
|
|
26124
|
-
|
|
26386
|
+
// Gap is empty space by default, not a white mat.
|
|
26387
|
+
borderPaddingColor: element.imageBorderPaddingColor ?? "transparent",
|
|
26388
|
+
borderPosition: element.imageBorderPosition ?? "outside",
|
|
26125
26389
|
// Optional image drop shadow (element property).
|
|
26126
26390
|
shadow: (element.imageShadowBlur ?? 0) > 0 || element.imageShadowColor ? {
|
|
26127
26391
|
color: element.imageShadowColor ?? "rgba(0,0,0,0.25)",
|
|
@@ -26278,6 +26542,19 @@ const PageCanvas = react.forwardRef(
|
|
|
26278
26542
|
}
|
|
26279
26543
|
fc.requestRenderAll();
|
|
26280
26544
|
} catch (error) {
|
|
26545
|
+
console.error("[PageCanvas] image failed to load", {
|
|
26546
|
+
id: element.id,
|
|
26547
|
+
url: (element.src || element.imageUrl || "").slice(0, 200),
|
|
26548
|
+
error: error instanceof Error ? error.message : String(error)
|
|
26549
|
+
});
|
|
26550
|
+
const fcNow = fabricRef.current;
|
|
26551
|
+
if (fcNow && fcNow.__pixldocsEditMode === true) {
|
|
26552
|
+
try {
|
|
26553
|
+
markPlaceholderAsBrokenImage(placeholder);
|
|
26554
|
+
fcNow.requestRenderAll();
|
|
26555
|
+
} catch {
|
|
26556
|
+
}
|
|
26557
|
+
}
|
|
26281
26558
|
}
|
|
26282
26559
|
};
|
|
26283
26560
|
const handleCanvasClick = react.useCallback(
|
|
@@ -28883,7 +29160,9 @@ function expandBoundTables(pages, formValues) {
|
|
|
28883
29160
|
const t = node;
|
|
28884
29161
|
if (t.type === "table" && ((_a2 = t.tableData) == null ? void 0 : _a2.repeat)) {
|
|
28885
29162
|
const entries = tableEntriesFor(t.tableData.repeat.from, formValues);
|
|
28886
|
-
|
|
29163
|
+
if (entries.length > 0) {
|
|
29164
|
+
t.tableData = expandTableRepeat(t.tableData, entries);
|
|
29165
|
+
}
|
|
28887
29166
|
for (const row of t.tableData.cells) {
|
|
28888
29167
|
for (const cell of row) {
|
|
28889
29168
|
if (!cell.field) continue;
|
|
@@ -30038,7 +30317,12 @@ function pagesHaveConstantTokens(pages) {
|
|
|
30038
30317
|
return pages.some((p) => walk(p.children));
|
|
30039
30318
|
}
|
|
30040
30319
|
function substituteConstantTokens(pages, constants) {
|
|
30041
|
-
const sub = (s) => s.replace(/\{\{\s*\$([a-zA-Z0-9_]+)\s*\}\}/g, (m, name) =>
|
|
30320
|
+
const sub = (s) => s.replace(/\{\{\s*\$([a-zA-Z0-9_]+)\s*\}\}/g, (m, name) => (
|
|
30321
|
+
// Unresolved tokens are ERASED rather than left as literal braces: on a
|
|
30322
|
+
// money cell a missing symbol still reads as a number, whereas
|
|
30323
|
+
// "{{$currency}}9,500.00" is visibly broken output.
|
|
30324
|
+
Object.prototype.hasOwnProperty.call(constants, name) ? String(constants[name]) : ""
|
|
30325
|
+
));
|
|
30042
30326
|
const walk = (nodes) => {
|
|
30043
30327
|
for (const n of nodes ?? []) {
|
|
30044
30328
|
if (n.type === "text") {
|
|
@@ -30069,10 +30353,9 @@ function applyContentBoundsPagination(config) {
|
|
|
30069
30353
|
}
|
|
30070
30354
|
let mutated = continuationMasters.length > 0;
|
|
30071
30355
|
const constants = config.constants;
|
|
30072
|
-
|
|
30073
|
-
if (hasConstants && pagesHaveConstantTokens(pages)) {
|
|
30356
|
+
if (pagesHaveConstantTokens(pages)) {
|
|
30074
30357
|
pages = pages.map((p) => JSON.parse(JSON.stringify(p)));
|
|
30075
|
-
substituteConstantTokens(pages, constants);
|
|
30358
|
+
substituteConstantTokens(pages, constants && typeof constants === "object" ? constants : {});
|
|
30076
30359
|
mutated = true;
|
|
30077
30360
|
}
|
|
30078
30361
|
let resultPages = [];
|
|
@@ -32242,8 +32525,9 @@ async function resolveTemplateData(options) {
|
|
|
32242
32525
|
void 0,
|
|
32243
32526
|
repeatablePagesInput.length > 0 ? repeatablePagesInput : void 0
|
|
32244
32527
|
);
|
|
32528
|
+
const paginated = applyContentBoundsPagination(resolvedConfig);
|
|
32245
32529
|
return {
|
|
32246
|
-
config: applyThemeIfNeeded(
|
|
32530
|
+
config: applyThemeIfNeeded(paginated),
|
|
32247
32531
|
templateName: template.name || "Untitled",
|
|
32248
32532
|
templateId,
|
|
32249
32533
|
price: template.price ?? 0
|
|
@@ -33884,6 +34168,43 @@ function stampPixldocsImageIdOnSvg(svg, id) {
|
|
|
33884
34168
|
const attr = ` data-pixldocs-image-id="${escapeSvgDataAttr(id)}"`;
|
|
33885
34169
|
return svg.replace(/<image\b/i, `<image${attr}`);
|
|
33886
34170
|
}
|
|
34171
|
+
function colorHasAlpha(color) {
|
|
34172
|
+
if (typeof color !== "string") return false;
|
|
34173
|
+
const c = color.trim().toLowerCase();
|
|
34174
|
+
if (c === "transparent") return true;
|
|
34175
|
+
const rgba = c.match(/^rgba?\(([^)]+)\)$/);
|
|
34176
|
+
if (rgba) {
|
|
34177
|
+
const parts = rgba[1].split(",").map((x) => x.trim());
|
|
34178
|
+
return parts.length > 3 && Number(parts[3]) < 1;
|
|
34179
|
+
}
|
|
34180
|
+
if (/^#[0-9a-f]{8}$/.test(c)) return parseInt(c.slice(7, 9), 16) < 255;
|
|
34181
|
+
if (/^#[0-9a-f]{4}$/.test(c)) return parseInt(c[4] + c[4], 16) < 255;
|
|
34182
|
+
return false;
|
|
34183
|
+
}
|
|
34184
|
+
function paintIsAlphaGradient(paint) {
|
|
34185
|
+
const stops = paint == null ? void 0 : paint.colorStops;
|
|
34186
|
+
if (!Array.isArray(stops) || !stops.length) return false;
|
|
34187
|
+
return stops.some((st) => colorHasAlpha(st == null ? void 0 : st.color) || typeof (st == null ? void 0 : st.opacity) === "number" && st.opacity < 1);
|
|
34188
|
+
}
|
|
34189
|
+
function objectNeedsAlphaGradientRaster(obj) {
|
|
34190
|
+
if (!obj) return false;
|
|
34191
|
+
return paintIsAlphaGradient(obj.fill) || paintIsAlphaGradient(obj.stroke);
|
|
34192
|
+
}
|
|
34193
|
+
function rasterizeObjectToSvgImage(obj, multiplier) {
|
|
34194
|
+
try {
|
|
34195
|
+
if (typeof obj.toDataURL !== "function") return null;
|
|
34196
|
+
const rect = obj.getBoundingRect();
|
|
34197
|
+
if (!rect || !(rect.width > 0) || !(rect.height > 0)) return null;
|
|
34198
|
+
const url = obj.toDataURL({ multiplier, enableRetinaScaling: false });
|
|
34199
|
+
if (typeof url !== "string" || !url.startsWith("data:image")) return null;
|
|
34200
|
+
const n = (v) => Number(v.toFixed(4));
|
|
34201
|
+
return `<image x="${n(rect.left)}" y="${n(rect.top)}" width="${n(rect.width)}" height="${n(rect.height)}" preserveAspectRatio="none" xlink:href="${url}"></image>`;
|
|
34202
|
+
} catch (e) {
|
|
34203
|
+
console.warn("[canvas-svg-capture][alphaGradient] raster failed:", e);
|
|
34204
|
+
return null;
|
|
34205
|
+
}
|
|
34206
|
+
}
|
|
34207
|
+
const ALPHA_GRADIENT_RASTER_MULTIPLIER = 3;
|
|
33887
34208
|
function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight) {
|
|
33888
34209
|
const prevVPT = fabricInstance.viewportTransform ? [...fabricInstance.viewportTransform] : void 0;
|
|
33889
34210
|
const prevSvgVPT = fabricInstance.svgViewportTransformation;
|
|
@@ -33904,10 +34225,23 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
33904
34225
|
try {
|
|
33905
34226
|
const visit = (obj) => {
|
|
33906
34227
|
if (!obj) return;
|
|
34228
|
+
if (obj.__pixldocsEditorChrome) {
|
|
34229
|
+
const originalToSVG = typeof obj.toSVG === "function" ? obj.toSVG.bind(obj) : null;
|
|
34230
|
+
if (originalToSVG) {
|
|
34231
|
+
obj.toSVG = () => "";
|
|
34232
|
+
svgPatchRecords.push({ obj, originalToSVG });
|
|
34233
|
+
}
|
|
34234
|
+
return;
|
|
34235
|
+
}
|
|
33907
34236
|
const imageId = typeof obj.__docuforgeId === "string" && hasRenderableRasterCandidate(obj) ? obj.__docuforgeId : "";
|
|
33908
|
-
|
|
34237
|
+
const alphaGradient = objectNeedsAlphaGradientRaster(obj);
|
|
34238
|
+
if ((isTextboxLike(obj) || imageId || alphaGradient) && typeof obj.toSVG === "function") {
|
|
33909
34239
|
const originalToSVG = obj.toSVG.bind(obj);
|
|
33910
34240
|
obj.toSVG = (reviver) => {
|
|
34241
|
+
if (alphaGradient) {
|
|
34242
|
+
const raster = rasterizeObjectToSvgImage(obj, ALPHA_GRADIENT_RASTER_MULTIPLIER);
|
|
34243
|
+
if (raster) return raster;
|
|
34244
|
+
}
|
|
33911
34245
|
let svg = originalToSVG(reviver);
|
|
33912
34246
|
if (isTextboxLike(obj)) svg = stampFabricLineMetricsOnTextSvg(svg, obj);
|
|
33913
34247
|
if (isTextboxLike(obj)) svg = warpTextboxSvgAlongPath(svg, obj);
|
|
@@ -34006,9 +34340,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
34006
34340
|
}
|
|
34007
34341
|
return svgString;
|
|
34008
34342
|
}
|
|
34009
|
-
const resolvedPackageVersion = "0.5.
|
|
34343
|
+
const resolvedPackageVersion = "0.5.497";
|
|
34010
34344
|
const PACKAGE_VERSION = resolvedPackageVersion;
|
|
34011
|
-
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.
|
|
34345
|
+
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.497";
|
|
34012
34346
|
const roundParityValue = (value) => {
|
|
34013
34347
|
if (typeof value !== "number") return value;
|
|
34014
34348
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -34447,6 +34781,11 @@ class PixldocsRenderer {
|
|
|
34447
34781
|
* Mounts a hidden PreviewCanvas component and captures the Fabric canvas output.
|
|
34448
34782
|
*/
|
|
34449
34783
|
async render(templateConfig, options = {}) {
|
|
34784
|
+
if (options.watermark === true && !templateConfig.__pixldocsWatermarked) {
|
|
34785
|
+
const { injectWatermark: injectWatermark2 } = await Promise.resolve().then(() => canvasWatermark);
|
|
34786
|
+
templateConfig = injectWatermark2(templateConfig, options.watermarkOptions);
|
|
34787
|
+
templateConfig.__pixldocsWatermarked = true;
|
|
34788
|
+
}
|
|
34450
34789
|
const pageIndex = options.pageIndex ?? 0;
|
|
34451
34790
|
const format = options.format ?? "png";
|
|
34452
34791
|
const quality = options.quality ?? 0.92;
|
|
@@ -34462,6 +34801,7 @@ class PixldocsRenderer {
|
|
|
34462
34801
|
const hasAutoShrink = configHasAutoShrinkText(templateConfig);
|
|
34463
34802
|
const defaultWait = hasAutoShrink ? 4e3 : 1800;
|
|
34464
34803
|
await this.awaitFontsForConfig(templateConfig, options.waitForFontsMs ?? defaultWait);
|
|
34804
|
+
this.flushTextMeasurementCaches();
|
|
34465
34805
|
}
|
|
34466
34806
|
const { setPackageApiUrl: setPackageApiUrl2 } = await Promise.resolve().then(() => appApi);
|
|
34467
34807
|
setPackageApiUrl2(this.config.imageProxyUrl);
|
|
@@ -34489,6 +34829,7 @@ class PixldocsRenderer {
|
|
|
34489
34829
|
const hasAutoShrink = configHasAutoShrinkText(templateConfig);
|
|
34490
34830
|
const defaultWait = hasAutoShrink ? 4e3 : 1800;
|
|
34491
34831
|
await this.awaitFontsForConfig(templateConfig, options.waitForFontsMs ?? defaultWait);
|
|
34832
|
+
this.flushTextMeasurementCaches();
|
|
34492
34833
|
}
|
|
34493
34834
|
const results = [];
|
|
34494
34835
|
for (let i = 0; i < templateConfig.pages.length; i++) {
|
|
@@ -34515,8 +34856,8 @@ class PixldocsRenderer {
|
|
|
34515
34856
|
const shouldWatermark = watermark ?? resolved.price > 0;
|
|
34516
34857
|
let configToRender = resolved.config;
|
|
34517
34858
|
if (shouldWatermark) {
|
|
34518
|
-
const { injectWatermark } = await Promise.resolve().then(() =>
|
|
34519
|
-
configToRender =
|
|
34859
|
+
const { injectWatermark: injectWatermark2 } = await Promise.resolve().then(() => canvasWatermark);
|
|
34860
|
+
configToRender = injectWatermark2(configToRender, watermarkOptions);
|
|
34520
34861
|
const { injectPreviewBlur: injectPreviewBlur2 } = await Promise.resolve().then(() => previewBlur);
|
|
34521
34862
|
configToRender = injectPreviewBlur2(configToRender);
|
|
34522
34863
|
}
|
|
@@ -34575,8 +34916,8 @@ class PixldocsRenderer {
|
|
|
34575
34916
|
const shouldWatermark = watermark ?? resolved.price > 0;
|
|
34576
34917
|
let configToRender = resolved.config;
|
|
34577
34918
|
if (shouldWatermark) {
|
|
34578
|
-
const { injectWatermark } = await Promise.resolve().then(() =>
|
|
34579
|
-
configToRender =
|
|
34919
|
+
const { injectWatermark: injectWatermark2 } = await Promise.resolve().then(() => canvasWatermark);
|
|
34920
|
+
configToRender = injectWatermark2(configToRender, watermarkOptions);
|
|
34580
34921
|
const { injectPreviewBlur: injectPreviewBlur2 } = await Promise.resolve().then(() => previewBlur);
|
|
34581
34922
|
configToRender = injectPreviewBlur2(configToRender);
|
|
34582
34923
|
}
|
|
@@ -34596,6 +34937,10 @@ class PixldocsRenderer {
|
|
|
34596
34937
|
* exporter, which is what `renderPdfViaClientExport` does below.
|
|
34597
34938
|
*/
|
|
34598
34939
|
async renderPdf(templateConfig, options) {
|
|
34940
|
+
if ((options == null ? void 0 : options.watermark) === true) {
|
|
34941
|
+
const { injectWatermark: injectWatermark2 } = await Promise.resolve().then(() => canvasWatermark);
|
|
34942
|
+
templateConfig = injectWatermark2(templateConfig, options.watermarkOptions);
|
|
34943
|
+
}
|
|
34599
34944
|
return this.renderPdfViaClientExport(templateConfig, {
|
|
34600
34945
|
title: options == null ? void 0 : options.title,
|
|
34601
34946
|
textMode: options == null ? void 0 : options.textMode,
|
|
@@ -34624,8 +34969,8 @@ class PixldocsRenderer {
|
|
|
34624
34969
|
const shouldWatermark = watermark ?? resolved.price > 0;
|
|
34625
34970
|
let configToRender = resolved.config;
|
|
34626
34971
|
if (shouldWatermark) {
|
|
34627
|
-
const { injectWatermark } = await Promise.resolve().then(() =>
|
|
34628
|
-
configToRender =
|
|
34972
|
+
const { injectWatermark: injectWatermark2 } = await Promise.resolve().then(() => canvasWatermark);
|
|
34973
|
+
configToRender = injectWatermark2(configToRender, watermarkOptions);
|
|
34629
34974
|
const { injectPreviewBlur: injectPreviewBlur2 } = await Promise.resolve().then(() => previewBlur);
|
|
34630
34975
|
configToRender = injectPreviewBlur2(configToRender);
|
|
34631
34976
|
}
|
|
@@ -34822,7 +35167,7 @@ class PixldocsRenderer {
|
|
|
34822
35167
|
await this.waitForCanvasScene(container, cloned, i);
|
|
34823
35168
|
}
|
|
34824
35169
|
console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
|
|
34825
|
-
const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-
|
|
35170
|
+
const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-De8UFmDy.cjs"));
|
|
34826
35171
|
const prepared = preparePagesForExport(
|
|
34827
35172
|
cloned.pages,
|
|
34828
35173
|
canvasWidth,
|
|
@@ -35100,6 +35445,37 @@ class PixldocsRenderer {
|
|
|
35100
35445
|
new Promise((r) => setTimeout(r, Math.min(500, maxWaitMs)))
|
|
35101
35446
|
]);
|
|
35102
35447
|
}
|
|
35448
|
+
/**
|
|
35449
|
+
* Flush BOTH process-global text-measurement caches after fonts are ready
|
|
35450
|
+
* and BEFORE the capture canvas mounts.
|
|
35451
|
+
*
|
|
35452
|
+
* Why: anything that measured text before the webfonts finished loading —
|
|
35453
|
+
* most notably `applyContentBoundsPagination` running inside
|
|
35454
|
+
* `resolveFromForm` on a cold page (the EC2/MCP flow: resolve + render in
|
|
35455
|
+
* one browser context) — populates the app measurement cache and Fabric's
|
|
35456
|
+
* global char-width cache with FALLBACK metrics. `createText` then places
|
|
35457
|
+
* center/right-aligned lines from those stale widths, so a right-aligned
|
|
35458
|
+
* grid cell on a continuation page drew shifted left by
|
|
35459
|
+
* (fallbackWidth − realWidth) px vs the editor (caught by
|
|
35460
|
+
* tests/parity `auto-paginate`, a 9px shift). The later
|
|
35461
|
+
* `waitForStableTextMetrics` pass re-primes glyph bounds but never moves
|
|
35462
|
+
* the already-positioned box, so the flush must happen pre-mount.
|
|
35463
|
+
*
|
|
35464
|
+
* Only called from the headless PNG paths (`render`/`renderAllPages`),
|
|
35465
|
+
* which already default to clearing the global char cache in
|
|
35466
|
+
* `waitForStableTextMetrics` — the live-preview-adjacent PDF path keeps
|
|
35467
|
+
* its `clearGlobalCharCache: false` behaviour untouched.
|
|
35468
|
+
*/
|
|
35469
|
+
flushTextMeasurementCaches() {
|
|
35470
|
+
try {
|
|
35471
|
+
clearMeasurementCache();
|
|
35472
|
+
} catch {
|
|
35473
|
+
}
|
|
35474
|
+
try {
|
|
35475
|
+
clearFabricCharCache();
|
|
35476
|
+
} catch {
|
|
35477
|
+
}
|
|
35478
|
+
}
|
|
35103
35479
|
getNormalizedGradientStops(gradient) {
|
|
35104
35480
|
const stops = Array.isArray(gradient == null ? void 0 : gradient.stops) ? gradient.stops.map((stop) => ({
|
|
35105
35481
|
offset: Math.max(0, Math.min(1, Number((stop == null ? void 0 : stop.offset) ?? 0))),
|
|
@@ -37142,7 +37518,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
37142
37518
|
if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
|
|
37143
37519
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
37144
37520
|
try {
|
|
37145
|
-
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-
|
|
37521
|
+
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-De8UFmDy.cjs"));
|
|
37146
37522
|
try {
|
|
37147
37523
|
await logTextMeasurementDiagnostic(svgToDraw);
|
|
37148
37524
|
} catch {
|
|
@@ -37390,6 +37766,129 @@ async function getPublishedTemplate(options) {
|
|
|
37390
37766
|
const rows = await res.json();
|
|
37391
37767
|
return rows[0] ?? null;
|
|
37392
37768
|
}
|
|
37769
|
+
const WATERMARK_ID_PREFIX = "__wm_";
|
|
37770
|
+
const DEFAULT_WATERMARK_OPACITY = 0.14;
|
|
37771
|
+
const DEFAULT_WATERMARK_FONT_SIZE = 18;
|
|
37772
|
+
const DEFAULT_WATERMARK_ANGLE = -30;
|
|
37773
|
+
function getWatermarkText() {
|
|
37774
|
+
try {
|
|
37775
|
+
const host = window.location.hostname;
|
|
37776
|
+
if (host.includes("biomaker")) return "biomaker.app";
|
|
37777
|
+
} catch {
|
|
37778
|
+
}
|
|
37779
|
+
return "pixldocs.com";
|
|
37780
|
+
}
|
|
37781
|
+
function getLuminance(color) {
|
|
37782
|
+
if (!color || color === "transparent" || color === "none") return 1;
|
|
37783
|
+
let r = 255, g = 255, b = 255;
|
|
37784
|
+
if (color.startsWith("#")) {
|
|
37785
|
+
const hex = color.slice(1);
|
|
37786
|
+
const full = hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex;
|
|
37787
|
+
const n = parseInt(full, 16);
|
|
37788
|
+
r = n >> 16 & 255;
|
|
37789
|
+
g = n >> 8 & 255;
|
|
37790
|
+
b = n & 255;
|
|
37791
|
+
} else {
|
|
37792
|
+
const m = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
37793
|
+
if (m) {
|
|
37794
|
+
r = +m[1];
|
|
37795
|
+
g = +m[2];
|
|
37796
|
+
b = +m[3];
|
|
37797
|
+
}
|
|
37798
|
+
}
|
|
37799
|
+
return (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
37800
|
+
}
|
|
37801
|
+
function getWatermarkColor(bgColor) {
|
|
37802
|
+
const lum = getLuminance(bgColor);
|
|
37803
|
+
return lum < 0.45 ? "#cccccc" : "#808080";
|
|
37804
|
+
}
|
|
37805
|
+
function getPageBgColor(page, canvasBg) {
|
|
37806
|
+
var _a2, _b2;
|
|
37807
|
+
const settingsBg = (_a2 = page.settings) == null ? void 0 : _a2.backgroundColor;
|
|
37808
|
+
if (settingsBg && settingsBg !== "transparent" && settingsBg !== "none") {
|
|
37809
|
+
return settingsBg;
|
|
37810
|
+
}
|
|
37811
|
+
const children = page.children || [];
|
|
37812
|
+
for (const child of children) {
|
|
37813
|
+
if (child.type === "shape" && child.fill && child.fill !== "transparent" && child.fill !== "none") {
|
|
37814
|
+
return child.fill;
|
|
37815
|
+
}
|
|
37816
|
+
if ((_b2 = child.children) == null ? void 0 : _b2.length) {
|
|
37817
|
+
for (const gc of child.children) {
|
|
37818
|
+
if (gc.type === "shape" && gc.fill && gc.fill !== "transparent" && gc.fill !== "none") {
|
|
37819
|
+
return gc.fill;
|
|
37820
|
+
}
|
|
37821
|
+
}
|
|
37822
|
+
}
|
|
37823
|
+
}
|
|
37824
|
+
return canvasBg;
|
|
37825
|
+
}
|
|
37826
|
+
function generateWatermarkElements(canvasWidth, canvasHeight, wmColor, options = {}) {
|
|
37827
|
+
const elements = [];
|
|
37828
|
+
const text = options.text ?? getWatermarkText();
|
|
37829
|
+
const fontSize = options.fontSize ?? DEFAULT_WATERMARK_FONT_SIZE;
|
|
37830
|
+
const angle = options.angle ?? DEFAULT_WATERMARK_ANGLE;
|
|
37831
|
+
const opacity = options.opacity ?? DEFAULT_WATERMARK_OPACITY;
|
|
37832
|
+
const estimatedTextWidth = text.length * fontSize * 0.55;
|
|
37833
|
+
const spacingX = Math.max(160, estimatedTextWidth + 30);
|
|
37834
|
+
const spacingY = 90;
|
|
37835
|
+
const startX = -canvasWidth * 0.3;
|
|
37836
|
+
const startY = -canvasHeight * 0.3;
|
|
37837
|
+
const endX = canvasWidth * 1.5;
|
|
37838
|
+
const endY = canvasHeight * 1.5;
|
|
37839
|
+
let idx = 0;
|
|
37840
|
+
for (let y = startY; y < endY; y += spacingY) {
|
|
37841
|
+
for (let x = startX; x < endX; x += spacingX) {
|
|
37842
|
+
elements.push({
|
|
37843
|
+
id: `${WATERMARK_ID_PREFIX}${idx++}`,
|
|
37844
|
+
type: "text",
|
|
37845
|
+
left: x,
|
|
37846
|
+
top: y,
|
|
37847
|
+
width: 200,
|
|
37848
|
+
height: 40,
|
|
37849
|
+
text,
|
|
37850
|
+
fontFamily: "Montserrat",
|
|
37851
|
+
fontSize,
|
|
37852
|
+
fontWeight: "600",
|
|
37853
|
+
fill: wmColor,
|
|
37854
|
+
angle,
|
|
37855
|
+
selectable: false,
|
|
37856
|
+
locked: true,
|
|
37857
|
+
visible: true,
|
|
37858
|
+
opacity,
|
|
37859
|
+
scaleX: 1,
|
|
37860
|
+
scaleY: 1,
|
|
37861
|
+
letterSpacing: 4
|
|
37862
|
+
});
|
|
37863
|
+
}
|
|
37864
|
+
}
|
|
37865
|
+
return elements;
|
|
37866
|
+
}
|
|
37867
|
+
function injectWatermark(config, options = {}) {
|
|
37868
|
+
var _a2, _b2, _c2;
|
|
37869
|
+
const canvasWidth = ((_a2 = config.canvas) == null ? void 0 : _a2.width) || 612;
|
|
37870
|
+
const canvasHeight = ((_b2 = config.canvas) == null ? void 0 : _b2.height) || 792;
|
|
37871
|
+
const canvasBg = (_c2 = config.canvas) == null ? void 0 : _c2.backgroundColor;
|
|
37872
|
+
return {
|
|
37873
|
+
...config,
|
|
37874
|
+
pages: config.pages.map((page) => {
|
|
37875
|
+
const pageBg = getPageBgColor(page, canvasBg);
|
|
37876
|
+
const wmColor = getWatermarkColor(pageBg);
|
|
37877
|
+
const watermarkElements = generateWatermarkElements(canvasWidth, canvasHeight, wmColor, options);
|
|
37878
|
+
return {
|
|
37879
|
+
...page,
|
|
37880
|
+
children: [
|
|
37881
|
+
...page.children || [],
|
|
37882
|
+
...watermarkElements
|
|
37883
|
+
]
|
|
37884
|
+
};
|
|
37885
|
+
})
|
|
37886
|
+
};
|
|
37887
|
+
}
|
|
37888
|
+
const canvasWatermark = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
37889
|
+
__proto__: null,
|
|
37890
|
+
injectWatermark
|
|
37891
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
37393
37892
|
function setAutoShrinkDebug(enabled) {
|
|
37394
37893
|
if (typeof window !== "undefined") {
|
|
37395
37894
|
window.__pixldocsDebugAutoShrink = !!enabled;
|
|
@@ -37436,6 +37935,7 @@ exports.getWorldAngleDeg = getWorldAngleDeg$1;
|
|
|
37436
37935
|
exports.hasAnyPreviewBlur = hasAnyPreviewBlur;
|
|
37437
37936
|
exports.hasEdgeFade = hasEdgeFade;
|
|
37438
37937
|
exports.injectPreviewBlur = injectPreviewBlur;
|
|
37938
|
+
exports.injectWatermark = injectWatermark;
|
|
37439
37939
|
exports.isBundledAssetUrl = isBundledAssetUrl;
|
|
37440
37940
|
exports.isElement = isElement;
|
|
37441
37941
|
exports.isFontAvailable = isFontAvailable;
|
|
@@ -37457,4 +37957,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
|
|
|
37457
37957
|
exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
|
|
37458
37958
|
exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
|
|
37459
37959
|
exports.warmTemplateFromForm = warmTemplateFromForm;
|
|
37460
|
-
//# sourceMappingURL=index-
|
|
37960
|
+
//# sourceMappingURL=index-CZm1oVfa.cjs.map
|