@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
|
@@ -94,6 +94,15 @@ const generateId = (prefix = "el") => {
|
|
|
94
94
|
return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).substr(2, 9)}-${Math.random().toString(36).substr(2, 9)}`;
|
|
95
95
|
};
|
|
96
96
|
const createDefaultElement = (partial) => {
|
|
97
|
+
const loose = partial;
|
|
98
|
+
if (loose.type === "frame" || loose.type === "group") {
|
|
99
|
+
return createDefaultGroup({
|
|
100
|
+
layoutMode: loose.layout,
|
|
101
|
+
...partial,
|
|
102
|
+
type: "group",
|
|
103
|
+
children: Array.isArray(loose.children) ? loose.children : []
|
|
104
|
+
});
|
|
105
|
+
}
|
|
97
106
|
const isText = partial.type === "text";
|
|
98
107
|
const base = {
|
|
99
108
|
left: 48,
|
|
@@ -111,7 +120,7 @@ const createDefaultElement = (partial) => {
|
|
|
111
120
|
originY: "top",
|
|
112
121
|
opacity: 1,
|
|
113
122
|
fill: "#e2e8f0",
|
|
114
|
-
...isText ? {} : { stroke: "
|
|
123
|
+
...isText ? {} : { stroke: "transparent", strokeWidth: 0 },
|
|
115
124
|
visible: true,
|
|
116
125
|
selectable: true,
|
|
117
126
|
evented: true,
|
|
@@ -957,49 +966,15 @@ function worldPointToParentLocal(worldX, worldY, parent, pageChildren, resolveGr
|
|
|
957
966
|
);
|
|
958
967
|
return { left: local.x, top: local.y };
|
|
959
968
|
}
|
|
960
|
-
function unbakeChildrenToGroupLocal(group) {
|
|
961
|
-
const angle = getGroupAngleDeg(group);
|
|
962
|
-
if (Math.abs(angle) < 0.01) return group;
|
|
963
|
-
const { width, height } = getGroupFrameSize(group);
|
|
964
|
-
const cx = width / 2;
|
|
965
|
-
const cy = height / 2;
|
|
966
|
-
const inv = rotateAroundAffDeg(-angle, cx, cy);
|
|
967
|
-
const kids = (group.children ?? []).map((child) => {
|
|
968
|
-
const p = applyAff(inv, child.left ?? 0, child.top ?? 0);
|
|
969
|
-
const childAngle = typeof child.angle === "number" ? child.angle : 0;
|
|
970
|
-
const localAngle = normalizeAngleDeg(childAngle - angle);
|
|
971
|
-
if (isGroup(child)) {
|
|
972
|
-
const relocated = {
|
|
973
|
-
...child,
|
|
974
|
-
left: p.x,
|
|
975
|
-
top: p.y,
|
|
976
|
-
angle: localAngle
|
|
977
|
-
};
|
|
978
|
-
return Math.abs(getGroupAngleDeg(relocated)) > 0.01 ? unbakeChildrenToGroupLocal(relocated) : relocated;
|
|
979
|
-
}
|
|
980
|
-
return {
|
|
981
|
-
...child,
|
|
982
|
-
left: p.x,
|
|
983
|
-
top: p.y,
|
|
984
|
-
angle: localAngle
|
|
985
|
-
};
|
|
986
|
-
});
|
|
987
|
-
return { ...group, children: kids };
|
|
988
|
-
}
|
|
989
969
|
function migratePageTreeToGroupOwnedTransforms(nodes) {
|
|
990
970
|
return nodes.map((node) => {
|
|
991
971
|
if (!isGroup(node)) return node;
|
|
992
972
|
const g = node;
|
|
993
|
-
|
|
973
|
+
const next = {
|
|
994
974
|
...g,
|
|
995
975
|
children: migratePageTreeToGroupOwnedTransforms(g.children ?? [])
|
|
996
976
|
};
|
|
997
|
-
if (isRotatableGroup(next)
|
|
998
|
-
if (g.groupTransformModel !== "owned-v1") {
|
|
999
|
-
next = unbakeChildrenToGroupLocal(next);
|
|
1000
|
-
next.groupTransformModel = "owned-v1";
|
|
1001
|
-
}
|
|
1002
|
-
} else if (isRotatableGroup(next)) {
|
|
977
|
+
if (isRotatableGroup(next)) {
|
|
1003
978
|
next.groupTransformModel = "owned-v1";
|
|
1004
979
|
}
|
|
1005
980
|
return next;
|
|
@@ -2239,6 +2214,40 @@ function adaptLayoutGrid(grid, mode) {
|
|
|
2239
2214
|
const cells = (grid.cells ?? []).map((c) => c && c.grid ? { ...c, grid: adaptLayoutGrid(c.grid, mode) } : c);
|
|
2240
2215
|
return { ...grid, dir: grid.dir === from ? to : grid.dir, cells };
|
|
2241
2216
|
}
|
|
2217
|
+
function isAspectLockedNode(node) {
|
|
2218
|
+
const e = node;
|
|
2219
|
+
if (!e) return false;
|
|
2220
|
+
if (e.lockAspect === true) return true;
|
|
2221
|
+
if (e.clipShape === "circle") return true;
|
|
2222
|
+
const kind = e.componentKind || e.smartType;
|
|
2223
|
+
return kind === "qrcode" || kind === "barcode";
|
|
2224
|
+
}
|
|
2225
|
+
function scaleNodeForReflow(node, sx, sy, fscale) {
|
|
2226
|
+
const n = node;
|
|
2227
|
+
const el = { ...n };
|
|
2228
|
+
const hasBox = typeof n.width === "number" && typeof n.height === "number";
|
|
2229
|
+
const f = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
2230
|
+
if (hasBox && isAspectLockedNode(n) && sx !== sy) {
|
|
2231
|
+
const s = Math.min(sx, sy);
|
|
2232
|
+
const cx = (f(n.left) + n.width / 2) * sx;
|
|
2233
|
+
const cy = (f(n.top) + n.height / 2) * sy;
|
|
2234
|
+
el.width = n.width * s;
|
|
2235
|
+
el.height = n.height * s;
|
|
2236
|
+
el.left = cx - el.width / 2;
|
|
2237
|
+
el.top = cy - el.height / 2;
|
|
2238
|
+
} else {
|
|
2239
|
+
if (typeof el.left === "number") el.left = el.left * sx;
|
|
2240
|
+
if (typeof el.top === "number") el.top = el.top * sy;
|
|
2241
|
+
if (typeof el.width === "number") el.width = el.width * sx;
|
|
2242
|
+
if (typeof el.height === "number") el.height = el.height * sy;
|
|
2243
|
+
}
|
|
2244
|
+
if (typeof el.fontSize === "number") el.fontSize = Math.max(4, el.fontSize * fscale);
|
|
2245
|
+
if (typeof el.minBoxHeight === "number") el.minBoxHeight = el.minBoxHeight * sy;
|
|
2246
|
+
if (Array.isArray(el.children)) {
|
|
2247
|
+
el.children = el.children.map((c) => scaleNodeForReflow(c, sx, sy, fscale));
|
|
2248
|
+
}
|
|
2249
|
+
return el;
|
|
2250
|
+
}
|
|
2242
2251
|
function computeGridHandles(grid, box, gridPath = []) {
|
|
2243
2252
|
const out = [];
|
|
2244
2253
|
const n = grid.cells.length;
|
|
@@ -2641,16 +2650,7 @@ const reflowPagesFromBase = (base, W, H) => {
|
|
|
2641
2650
|
const fscale = Math.sqrt(Math.max(0.01, sx * sy));
|
|
2642
2651
|
const adapt = layoutAdaptationFor(base.width, base.height, W, H);
|
|
2643
2652
|
const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
2644
|
-
const scaleNode = (node) =>
|
|
2645
|
-
const el = { ...node };
|
|
2646
|
-
if (typeof el.left === "number") el.left = el.left * sx;
|
|
2647
|
-
if (typeof el.top === "number") el.top = el.top * sy;
|
|
2648
|
-
if (typeof el.width === "number") el.width = el.width * sx;
|
|
2649
|
-
if (typeof el.height === "number") el.height = el.height * sy;
|
|
2650
|
-
if (typeof el.fontSize === "number") el.fontSize = Math.max(4, el.fontSize * fscale);
|
|
2651
|
-
if (Array.isArray(el.children)) el.children = el.children.map(scaleNode);
|
|
2652
|
-
return el;
|
|
2653
|
-
};
|
|
2653
|
+
const scaleNode = (node) => scaleNodeForReflow(node, sx, sy, fscale);
|
|
2654
2654
|
return base.pages.map((p) => {
|
|
2655
2655
|
const pg = p;
|
|
2656
2656
|
const page = {
|
|
@@ -3239,6 +3239,13 @@ const useEditorStore = create((set, get) => ({
|
|
|
3239
3239
|
return { canvas: nextCanvas, ...committed };
|
|
3240
3240
|
});
|
|
3241
3241
|
},
|
|
3242
|
+
getCanvasForSave: () => {
|
|
3243
|
+
const { canvas } = get();
|
|
3244
|
+
const base = sizeBaseSnapshot;
|
|
3245
|
+
if (!base) return canvas;
|
|
3246
|
+
if (canvas.width === base.width && canvas.height === base.height) return canvas;
|
|
3247
|
+
return { ...canvas, width: base.width, height: base.height, pages: base.pages };
|
|
3248
|
+
},
|
|
3242
3249
|
addSizeVariant: (variant) => set((state) => {
|
|
3243
3250
|
const sizes = state.canvas.sizes ?? [];
|
|
3244
3251
|
if (sizes.some((s) => s.id === variant.id)) return {};
|
|
@@ -6336,8 +6343,13 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
|
|
|
6336
6343
|
});
|
|
6337
6344
|
const imgLoadOptions = url.startsWith("data:") || url.startsWith("blob:") ? {} : { crossOrigin: "anonymous" };
|
|
6338
6345
|
const img = await fabric.FabricImage.fromURL(url, imgLoadOptions);
|
|
6339
|
-
if (!fabricRef.current) return;
|
|
6346
|
+
if (fabricRef && !fabricRef.current) return;
|
|
6340
6347
|
await normalizeSvgImageDimensions(img, imageUrl, element.sourceFormat);
|
|
6348
|
+
const natW = img.width ?? 0;
|
|
6349
|
+
const natH = img.height ?? 0;
|
|
6350
|
+
if (natW <= 1 && natH <= 1 && Number(element.width) > 8 && Number(element.height) > 8) {
|
|
6351
|
+
throw new Error(`image decoded to ${natW}x${natH} — treating as failed load`);
|
|
6352
|
+
}
|
|
6341
6353
|
const isHidden = !element.visible;
|
|
6342
6354
|
img.set({
|
|
6343
6355
|
originX: "left",
|
|
@@ -6492,8 +6504,14 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
|
|
|
6492
6504
|
shape,
|
|
6493
6505
|
rx: rxRatio,
|
|
6494
6506
|
// Pass ratio, not pixel value
|
|
6495
|
-
|
|
6496
|
-
|
|
6507
|
+
// Image outline is an ELEMENT property (imageBorder*), not the generic
|
|
6508
|
+
// shape stroke — this builder forwarded only stroke/strokeWidth, so
|
|
6509
|
+
// outline/gap never reached it.
|
|
6510
|
+
stroke: (element.imageBorderWidth ?? 0) > 0 ? element.imageBorderColor ?? "#FFFFFF" : element.stroke,
|
|
6511
|
+
strokeWidth: (element.imageBorderWidth ?? 0) > 0 ? element.imageBorderWidth : element.strokeWidth,
|
|
6512
|
+
borderPadding: element.imageBorderPadding ?? 0,
|
|
6513
|
+
borderPaddingColor: element.imageBorderPaddingColor ?? "transparent",
|
|
6514
|
+
borderPosition: element.imageBorderPosition ?? "outside",
|
|
6497
6515
|
panX,
|
|
6498
6516
|
panY,
|
|
6499
6517
|
zoom
|
|
@@ -6529,9 +6547,111 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
|
|
|
6529
6547
|
proxiedUrl: getProxiedImageUrl(imageUrl).slice(0, 240),
|
|
6530
6548
|
error: error instanceof Error ? error.message : String(error)
|
|
6531
6549
|
});
|
|
6550
|
+
if (fc.__pixldocsEditMode === true) {
|
|
6551
|
+
try {
|
|
6552
|
+
markPlaceholderAsBrokenImage(placeholder);
|
|
6553
|
+
fc.requestRenderAll();
|
|
6554
|
+
} catch {
|
|
6555
|
+
}
|
|
6556
|
+
}
|
|
6532
6557
|
return;
|
|
6533
6558
|
}
|
|
6534
6559
|
}
|
|
6560
|
+
function markPlaceholderAsBrokenImage(placeholder) {
|
|
6561
|
+
if (!(placeholder instanceof fabric.Group)) return;
|
|
6562
|
+
const group = placeholder;
|
|
6563
|
+
if (group.__pixldocsBrokenImage) return;
|
|
6564
|
+
group.__pixldocsBrokenImage = true;
|
|
6565
|
+
const frameChild = group.getObjects().find(
|
|
6566
|
+
(o) => o.__isPlaceholderFrame
|
|
6567
|
+
);
|
|
6568
|
+
const w = Math.max(1, (frameChild == null ? void 0 : frameChild.width) ?? group.width ?? 1);
|
|
6569
|
+
const h = Math.max(1, (frameChild == null ? void 0 : frameChild.height) ?? group.height ?? 1);
|
|
6570
|
+
const center = group.getCenterPoint();
|
|
6571
|
+
const cx = center.x;
|
|
6572
|
+
const cy = center.y;
|
|
6573
|
+
const prevPose = { left: group.left, top: group.top, width: group.width, height: group.height };
|
|
6574
|
+
const bg = new fabric.Rect({
|
|
6575
|
+
originX: "center",
|
|
6576
|
+
originY: "center",
|
|
6577
|
+
left: cx,
|
|
6578
|
+
top: cy,
|
|
6579
|
+
width: w,
|
|
6580
|
+
height: h,
|
|
6581
|
+
fill: "rgba(148, 163, 184, 0.12)",
|
|
6582
|
+
stroke: "#94A3B8",
|
|
6583
|
+
strokeWidth: 1.5,
|
|
6584
|
+
strokeDashArray: [6, 4]
|
|
6585
|
+
});
|
|
6586
|
+
const s = Math.max(16, Math.min(w, h) * 0.28);
|
|
6587
|
+
const glyphStroke = { stroke: "#64748B", strokeWidth: Math.max(1.5, s / 12), fill: "transparent" };
|
|
6588
|
+
const iconFrame = new fabric.Rect({
|
|
6589
|
+
originX: "center",
|
|
6590
|
+
originY: "center",
|
|
6591
|
+
left: cx,
|
|
6592
|
+
top: cy,
|
|
6593
|
+
width: s,
|
|
6594
|
+
height: s * 0.8,
|
|
6595
|
+
rx: s * 0.08,
|
|
6596
|
+
ry: s * 0.08,
|
|
6597
|
+
...glyphStroke
|
|
6598
|
+
});
|
|
6599
|
+
const mountain = new fabric.Polyline(
|
|
6600
|
+
[
|
|
6601
|
+
{ x: -s * 0.38, y: s * 0.24 },
|
|
6602
|
+
{ x: -s * 0.1, y: -s * 0.08 },
|
|
6603
|
+
{ x: s * 0.08, y: s * 0.1 },
|
|
6604
|
+
{ x: s * 0.22, y: -s * 0.02 },
|
|
6605
|
+
{ x: s * 0.38, y: s * 0.24 }
|
|
6606
|
+
],
|
|
6607
|
+
{ originX: "center", originY: "center", left: cx, top: cy + s * 0.08, ...glyphStroke }
|
|
6608
|
+
);
|
|
6609
|
+
const slash = new fabric.Line([cx - s * 0.55, cy - s * 0.5, cx + s * 0.55, cy + s * 0.5], {
|
|
6610
|
+
...glyphStroke,
|
|
6611
|
+
originX: "center",
|
|
6612
|
+
originY: "center",
|
|
6613
|
+
left: cx,
|
|
6614
|
+
top: cy
|
|
6615
|
+
});
|
|
6616
|
+
for (const obj of [bg, iconFrame, mountain, slash]) {
|
|
6617
|
+
obj.set({ selectable: false, evented: false, excludeFromExport: true });
|
|
6618
|
+
obj.__pixldocsEditorChrome = true;
|
|
6619
|
+
group.add(obj);
|
|
6620
|
+
}
|
|
6621
|
+
group.set(prevPose);
|
|
6622
|
+
group.setCoords();
|
|
6623
|
+
group.dirty = true;
|
|
6624
|
+
}
|
|
6625
|
+
function hideEditorChromeForExport(fc) {
|
|
6626
|
+
const hidden = [];
|
|
6627
|
+
const walk = (objs) => {
|
|
6628
|
+
var _a2;
|
|
6629
|
+
for (const o of objs) {
|
|
6630
|
+
if (o.__pixldocsEditorChrome && o.visible !== false) {
|
|
6631
|
+
o.visible = false;
|
|
6632
|
+
hidden.push(o);
|
|
6633
|
+
}
|
|
6634
|
+
const kids = (_a2 = o.getObjects) == null ? void 0 : _a2.call(o);
|
|
6635
|
+
if (kids == null ? void 0 : kids.length) walk(kids);
|
|
6636
|
+
}
|
|
6637
|
+
};
|
|
6638
|
+
walk(fc.getObjects());
|
|
6639
|
+
if (hidden.length) {
|
|
6640
|
+
for (const o of hidden) {
|
|
6641
|
+
const g = o.group;
|
|
6642
|
+
if (g) g.dirty = true;
|
|
6643
|
+
}
|
|
6644
|
+
fc.renderAll();
|
|
6645
|
+
}
|
|
6646
|
+
return () => {
|
|
6647
|
+
for (const o of hidden) {
|
|
6648
|
+
o.visible = true;
|
|
6649
|
+
const g = o.group;
|
|
6650
|
+
if (g) g.dirty = true;
|
|
6651
|
+
}
|
|
6652
|
+
if (hidden.length) fc.requestRenderAll();
|
|
6653
|
+
};
|
|
6654
|
+
}
|
|
6535
6655
|
const canvasImageLoader = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
6536
6656
|
__proto__: null,
|
|
6537
6657
|
SVG_DECODE_HARD_CAP,
|
|
@@ -6541,12 +6661,14 @@ const canvasImageLoader = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.d
|
|
|
6541
6661
|
fetchSvgTextPublic,
|
|
6542
6662
|
getNormalizedSvgUrl,
|
|
6543
6663
|
getProxiedImageUrl,
|
|
6664
|
+
hideEditorChromeForExport,
|
|
6544
6665
|
isBundledAssetUrl,
|
|
6545
6666
|
isEmptyImagePlaceholderGroup,
|
|
6546
6667
|
isPrivateUrl,
|
|
6547
6668
|
isSvgImage,
|
|
6548
6669
|
loadImageAsync,
|
|
6549
6670
|
loadSvgDimensions,
|
|
6671
|
+
markPlaceholderAsBrokenImage,
|
|
6550
6672
|
normalizeSvgImageDimensions,
|
|
6551
6673
|
parseSvgDimensionsFromText,
|
|
6552
6674
|
preloadImage,
|
|
@@ -7044,10 +7166,10 @@ function finalizeCropGroupCoords(g) {
|
|
|
7044
7166
|
g.setCoords();
|
|
7045
7167
|
}
|
|
7046
7168
|
function updateCoverLayout(g) {
|
|
7047
|
-
var _a2;
|
|
7169
|
+
var _a2, _b2;
|
|
7048
7170
|
const ct = g.__cropData;
|
|
7049
7171
|
if (!ct) return;
|
|
7050
|
-
const { frameW, frameH, shape, rx: rxRatio, _img: img
|
|
7172
|
+
const { frameW, frameH, shape, rx: rxRatio, _img: img } = ct;
|
|
7051
7173
|
const minDim = Math.min(frameW, frameH);
|
|
7052
7174
|
let rx = rxRatio > 0.5 ? rxRatio : rxRatio * minDim;
|
|
7053
7175
|
rx = Math.max(0, Math.min(rx, frameW / 2, frameH / 2));
|
|
@@ -7180,25 +7302,31 @@ function updateCoverLayout(g) {
|
|
|
7180
7302
|
g.clipPath.excludeFromExport = true;
|
|
7181
7303
|
}
|
|
7182
7304
|
}
|
|
7305
|
+
const wantCircle = shape === "circle";
|
|
7306
|
+
const border = ensureRingShapeClass(g, ct, "_border", wantCircle);
|
|
7307
|
+
const mat = ensureRingShapeClass(g, ct, "_mat", wantCircle);
|
|
7183
7308
|
const bw = border ? Number(border.strokeWidth) || 0 : 0;
|
|
7184
|
-
const mat = ct._mat;
|
|
7185
7309
|
const pad = Math.max(0, Number(ct.borderPadding) || 0);
|
|
7310
|
+
const outward = (ct.borderPosition ?? "outside") === "outside";
|
|
7186
7311
|
const borderMinDim = Math.min(frameW, frameH);
|
|
7187
7312
|
let borderRx = rxRatio > 0.5 ? rxRatio : rxRatio * borderMinDim;
|
|
7188
7313
|
borderRx = Math.max(0, Math.min(borderRx, frameW / 2, frameH / 2));
|
|
7314
|
+
const geo = computeOutlineGeometry({ frameW, frameH, bw, pad, rx: borderRx, outward });
|
|
7189
7315
|
if (border) {
|
|
7190
7316
|
if (shape === "circle") {
|
|
7191
|
-
border.set({ rx:
|
|
7317
|
+
border.set({ rx: geo.border.width / 2, ry: geo.border.height / 2 });
|
|
7192
7318
|
} else {
|
|
7193
|
-
border.set({ width:
|
|
7319
|
+
border.set({ width: geo.border.width, height: geo.border.height, rx: geo.border.rx, ry: geo.border.rx });
|
|
7194
7320
|
}
|
|
7321
|
+
border.dirty = true;
|
|
7195
7322
|
}
|
|
7196
7323
|
if (mat) {
|
|
7197
7324
|
if (shape === "circle") {
|
|
7198
|
-
mat.set({ rx:
|
|
7325
|
+
mat.set({ rx: geo.mat.width / 2, ry: geo.mat.height / 2 });
|
|
7199
7326
|
} else {
|
|
7200
|
-
mat.set({ width:
|
|
7327
|
+
mat.set({ width: geo.mat.width, height: geo.mat.height, rx: geo.mat.rx, ry: geo.mat.rx });
|
|
7201
7328
|
}
|
|
7329
|
+
mat.dirty = true;
|
|
7202
7330
|
}
|
|
7203
7331
|
if (!img) {
|
|
7204
7332
|
const placeholderFrame = ct._placeholderFrame ?? ((_a2 = g._objects) == null ? void 0 : _a2.find((obj) => obj.__isPlaceholderFrame));
|
|
@@ -7227,8 +7355,9 @@ function updateCoverLayout(g) {
|
|
|
7227
7355
|
img._ct.panX = img.__panX ?? 0.5;
|
|
7228
7356
|
img._ct.panY = img.__panY ?? 0.5;
|
|
7229
7357
|
}
|
|
7230
|
-
const
|
|
7231
|
-
const
|
|
7358
|
+
const srcEl = img._originalElement ?? ((_b2 = img.getElement) == null ? void 0 : _b2.call(img));
|
|
7359
|
+
const iw = Number(srcEl == null ? void 0 : srcEl.naturalWidth) || Number(srcEl == null ? void 0 : srcEl.width) || img.width || 1;
|
|
7360
|
+
const ih = Number(srcEl == null ? void 0 : srcEl.naturalHeight) || Number(srcEl == null ? void 0 : srcEl.height) || img.height || 1;
|
|
7232
7361
|
const fitContain = ct.fit === "contain";
|
|
7233
7362
|
const baseScale = fitContain ? Math.min(frameW / iw, frameH / ih) : Math.max(frameW / iw, frameH / ih);
|
|
7234
7363
|
const zoom = fitContain ? Math.max(1, Math.min(3, ct.containScale ?? 1)) : Math.max(1, img._ct.zoom ?? 1);
|
|
@@ -7265,6 +7394,42 @@ function updateCoverLayout(g) {
|
|
|
7265
7394
|
offsetY = overflowY > 0 ? -overflowY * (panY - 0.5) : 0;
|
|
7266
7395
|
}
|
|
7267
7396
|
img.set({ left: offsetX, top: offsetY });
|
|
7397
|
+
const wantsOutline = bw > 0 || pad > 0;
|
|
7398
|
+
const shapedMask = shape === "circle" || shape === "roundRect";
|
|
7399
|
+
if (wantsOutline && shapedMask) {
|
|
7400
|
+
if (g.clipPath) {
|
|
7401
|
+
img.clipPath = g.clipPath;
|
|
7402
|
+
g.clipPath = void 0;
|
|
7403
|
+
}
|
|
7404
|
+
if (img.cropX || img.cropY || img.width !== iw) {
|
|
7405
|
+
img.set({ width: iw, height: ih, cropX: 0, cropY: 0 });
|
|
7406
|
+
}
|
|
7407
|
+
} else if (wantsOutline && !fitContain) {
|
|
7408
|
+
const regionW = Math.min(iw, frameW / finalScale);
|
|
7409
|
+
const regionH = Math.min(ih, frameH / finalScale);
|
|
7410
|
+
img.set({
|
|
7411
|
+
width: regionW,
|
|
7412
|
+
height: regionH,
|
|
7413
|
+
cropX: (iw - regionW) * panX,
|
|
7414
|
+
cropY: (ih - regionH) * panY,
|
|
7415
|
+
left: 0,
|
|
7416
|
+
top: 0
|
|
7417
|
+
});
|
|
7418
|
+
img.clipPath = void 0;
|
|
7419
|
+
g.clipPath = void 0;
|
|
7420
|
+
} else {
|
|
7421
|
+
if (img.clipPath) img.clipPath = void 0;
|
|
7422
|
+
if (img.cropX || img.cropY || img.width !== iw) {
|
|
7423
|
+
img.set({ width: iw, height: ih, cropX: 0, cropY: 0 });
|
|
7424
|
+
}
|
|
7425
|
+
}
|
|
7426
|
+
const imgClip = img.clipPath;
|
|
7427
|
+
if (imgClip && typeof imgClip.set === "function") {
|
|
7428
|
+
const csx = img.scaleX || 1;
|
|
7429
|
+
const csy = img.scaleY || 1;
|
|
7430
|
+
imgClip.set({ left: -offsetX / csx, top: -offsetY / csy, scaleX: 1 / csx, scaleY: 1 / csy });
|
|
7431
|
+
imgClip.dirty = true;
|
|
7432
|
+
}
|
|
7268
7433
|
g.dirty = true;
|
|
7269
7434
|
img.dirty = true;
|
|
7270
7435
|
if (g.clipPath) {
|
|
@@ -7615,6 +7780,51 @@ function installCanvaMaskControls(g) {
|
|
|
7615
7780
|
g.set(controlStyle);
|
|
7616
7781
|
g.setCoords();
|
|
7617
7782
|
}
|
|
7783
|
+
function ensureRingShapeClass(g, ct, key, wantCircle) {
|
|
7784
|
+
const cur = ct[key];
|
|
7785
|
+
if (!cur) return void 0;
|
|
7786
|
+
const isEllipse = cur instanceof fabric.Ellipse;
|
|
7787
|
+
if (isEllipse === wantCircle) return cur;
|
|
7788
|
+
const common = {
|
|
7789
|
+
left: 0,
|
|
7790
|
+
top: 0,
|
|
7791
|
+
originX: "center",
|
|
7792
|
+
originY: "center",
|
|
7793
|
+
fill: "transparent",
|
|
7794
|
+
stroke: cur.stroke,
|
|
7795
|
+
strokeWidth: cur.strokeWidth,
|
|
7796
|
+
selectable: false,
|
|
7797
|
+
evented: false
|
|
7798
|
+
};
|
|
7799
|
+
const next = wantCircle ? new fabric.Ellipse({ ...common, rx: 1, ry: 1, objectCaching: false }) : new fabric.Rect({ ...common, width: 1, height: 1, objectCaching: false });
|
|
7800
|
+
const objs = g._objects;
|
|
7801
|
+
const idx = objs ? objs.indexOf(cur) : -1;
|
|
7802
|
+
if (objs && idx >= 0) objs.splice(idx, 1, next);
|
|
7803
|
+
else return cur;
|
|
7804
|
+
next.group = cur.group ?? g;
|
|
7805
|
+
next.canvas = cur.canvas ?? g.canvas;
|
|
7806
|
+
cur.group = void 0;
|
|
7807
|
+
next.setCoords();
|
|
7808
|
+
ct[key] = next;
|
|
7809
|
+
g.dirty = true;
|
|
7810
|
+
return next;
|
|
7811
|
+
}
|
|
7812
|
+
function computeOutlineGeometry(opts) {
|
|
7813
|
+
const { frameW, frameH, bw, pad, rx, outward } = opts;
|
|
7814
|
+
if (outward) {
|
|
7815
|
+
const grow = (r, by) => r > 0 ? r + by : 0;
|
|
7816
|
+
return {
|
|
7817
|
+
// Ring centre-line is pad + bw/2 past the frame → inner edge exactly `pad` out.
|
|
7818
|
+
border: { width: frameW + 2 * pad + bw, height: frameH + 2 * pad + bw, rx: grow(rx, pad + bw / 2) },
|
|
7819
|
+
// The gap band is transparent; it exists only to keep the child list stable.
|
|
7820
|
+
mat: { width: frameW + pad, height: frameH + pad, rx: grow(rx, pad / 2) }
|
|
7821
|
+
};
|
|
7822
|
+
}
|
|
7823
|
+
return {
|
|
7824
|
+
border: { width: frameW - bw, height: frameH - bw, rx },
|
|
7825
|
+
mat: { width: frameW - 2 * bw - pad, height: frameH - 2 * bw - pad, rx: Math.max(0, rx - bw) }
|
|
7826
|
+
};
|
|
7827
|
+
}
|
|
7618
7828
|
async function createMaskedImageElement({
|
|
7619
7829
|
url,
|
|
7620
7830
|
image,
|
|
@@ -7643,7 +7853,8 @@ async function createMaskedImageElement({
|
|
|
7643
7853
|
containScale = 1,
|
|
7644
7854
|
shadow = null,
|
|
7645
7855
|
borderPadding = 0,
|
|
7646
|
-
borderPaddingColor = "
|
|
7856
|
+
borderPaddingColor = "transparent",
|
|
7857
|
+
borderPosition = "outside"
|
|
7647
7858
|
}) {
|
|
7648
7859
|
const img = image || (url ? await fabric.FabricImage.fromURL(getProxiedImageUrl(url), { crossOrigin: "anonymous" }) : null);
|
|
7649
7860
|
if (!img) {
|
|
@@ -7668,36 +7879,47 @@ async function createMaskedImageElement({
|
|
|
7668
7879
|
});
|
|
7669
7880
|
const bw = strokeWidth || 0;
|
|
7670
7881
|
const pad = Math.max(0, borderPadding || 0);
|
|
7882
|
+
const outward = borderPosition === "outside";
|
|
7883
|
+
const geo = computeOutlineGeometry({ frameW, frameH, bw, pad, rx, outward });
|
|
7884
|
+
const matStroke = outward ? borderPaddingColor || "transparent" : borderPaddingColor;
|
|
7885
|
+
const matW = geo.mat.width;
|
|
7886
|
+
const matH = geo.mat.height;
|
|
7887
|
+
const matRx = geo.mat.rx;
|
|
7671
7888
|
const mat = shape === "circle" ? new fabric.Ellipse({
|
|
7672
|
-
rx:
|
|
7673
|
-
ry:
|
|
7889
|
+
rx: matW / 2,
|
|
7890
|
+
ry: matH / 2,
|
|
7674
7891
|
left: 0,
|
|
7675
7892
|
top: 0,
|
|
7676
7893
|
originX: "center",
|
|
7677
7894
|
originY: "center",
|
|
7678
7895
|
fill: "transparent",
|
|
7679
|
-
stroke:
|
|
7896
|
+
stroke: matStroke,
|
|
7680
7897
|
strokeWidth: pad,
|
|
7681
7898
|
selectable: false,
|
|
7682
|
-
evented: false
|
|
7899
|
+
evented: false,
|
|
7900
|
+
objectCaching: false
|
|
7683
7901
|
}) : new fabric.Rect({
|
|
7684
|
-
width:
|
|
7685
|
-
height:
|
|
7686
|
-
rx:
|
|
7687
|
-
ry:
|
|
7902
|
+
width: matW,
|
|
7903
|
+
height: matH,
|
|
7904
|
+
rx: matRx,
|
|
7905
|
+
ry: matRx,
|
|
7688
7906
|
left: 0,
|
|
7689
7907
|
top: 0,
|
|
7690
7908
|
originX: "center",
|
|
7691
7909
|
originY: "center",
|
|
7692
7910
|
fill: "transparent",
|
|
7693
|
-
stroke:
|
|
7911
|
+
stroke: matStroke,
|
|
7694
7912
|
strokeWidth: pad,
|
|
7695
7913
|
selectable: false,
|
|
7696
|
-
evented: false
|
|
7914
|
+
evented: false,
|
|
7915
|
+
objectCaching: false
|
|
7697
7916
|
});
|
|
7917
|
+
const bordW = geo.border.width;
|
|
7918
|
+
const bordH = geo.border.height;
|
|
7919
|
+
const bordRx = geo.border.rx;
|
|
7698
7920
|
const border = shape === "circle" ? new fabric.Ellipse({
|
|
7699
|
-
rx:
|
|
7700
|
-
ry:
|
|
7921
|
+
rx: bordW / 2,
|
|
7922
|
+
ry: bordH / 2,
|
|
7701
7923
|
left: 0,
|
|
7702
7924
|
top: 0,
|
|
7703
7925
|
originX: "center",
|
|
@@ -7706,12 +7928,13 @@ async function createMaskedImageElement({
|
|
|
7706
7928
|
stroke: stroke || "transparent",
|
|
7707
7929
|
strokeWidth: bw,
|
|
7708
7930
|
selectable: false,
|
|
7709
|
-
evented: false
|
|
7931
|
+
evented: false,
|
|
7932
|
+
objectCaching: false
|
|
7710
7933
|
}) : new fabric.Rect({
|
|
7711
|
-
width:
|
|
7712
|
-
height:
|
|
7713
|
-
rx,
|
|
7714
|
-
ry:
|
|
7934
|
+
width: bordW,
|
|
7935
|
+
height: bordH,
|
|
7936
|
+
rx: bordRx,
|
|
7937
|
+
ry: bordRx,
|
|
7715
7938
|
left: 0,
|
|
7716
7939
|
top: 0,
|
|
7717
7940
|
originX: "center",
|
|
@@ -7720,7 +7943,8 @@ async function createMaskedImageElement({
|
|
|
7720
7943
|
stroke: stroke || "transparent",
|
|
7721
7944
|
strokeWidth: bw,
|
|
7722
7945
|
selectable: false,
|
|
7723
|
-
evented: false
|
|
7946
|
+
evented: false,
|
|
7947
|
+
objectCaching: false
|
|
7724
7948
|
});
|
|
7725
7949
|
img.set({
|
|
7726
7950
|
left: 0,
|
|
@@ -7814,7 +8038,9 @@ async function createMaskedImageElement({
|
|
|
7814
8038
|
_border: border,
|
|
7815
8039
|
_mat: mat,
|
|
7816
8040
|
borderPadding: pad,
|
|
7817
|
-
borderPaddingColor
|
|
8041
|
+
borderPaddingColor,
|
|
8042
|
+
// Read back by refreshMaskedImage so it recomputes with the same geometry.
|
|
8043
|
+
borderPosition
|
|
7818
8044
|
};
|
|
7819
8045
|
g._ct = g._ct || {};
|
|
7820
8046
|
g._ct.isCropGroup = true;
|
|
@@ -7848,7 +8074,12 @@ async function createMaskedImageElement({
|
|
|
7848
8074
|
});
|
|
7849
8075
|
clip.absolutePositioned = false;
|
|
7850
8076
|
clip.excludeFromExport = true;
|
|
7851
|
-
|
|
8077
|
+
if (outward) {
|
|
8078
|
+
img.clipPath = clip;
|
|
8079
|
+
g.clipPath = void 0;
|
|
8080
|
+
} else {
|
|
8081
|
+
g.clipPath = clip;
|
|
8082
|
+
}
|
|
7852
8083
|
g.set({
|
|
7853
8084
|
selectable: true,
|
|
7854
8085
|
evented: true,
|
|
@@ -17949,6 +18180,7 @@ const PageCanvas = forwardRef(
|
|
|
17949
18180
|
// Transparent so underlay (page bg + group bgs) shows through
|
|
17950
18181
|
backgroundColor: "transparent"
|
|
17951
18182
|
});
|
|
18183
|
+
fabricCanvas.__pixldocsEditMode = isEditorMode && !isPreviewMode;
|
|
17952
18184
|
fabricCanvas.hoverCursor = "default";
|
|
17953
18185
|
fabricCanvas.moveCursor = "move";
|
|
17954
18186
|
const suppressTextEditForClick = (textbox) => {
|
|
@@ -23938,11 +24170,33 @@ const PageCanvas = forwardRef(
|
|
|
23938
24170
|
const wantBW = Math.max(0, Number(element.imageBorderWidth) || 0);
|
|
23939
24171
|
const wantBC = element.imageBorderColor ?? "#FFFFFF";
|
|
23940
24172
|
const wantPad = Math.max(0, Number(element.imageBorderPadding) || 0);
|
|
23941
|
-
const wantPC = element.imageBorderPaddingColor ?? "
|
|
24173
|
+
const wantPC = element.imageBorderPaddingColor ?? "transparent";
|
|
24174
|
+
const wantPos = element.imageBorderPosition ?? "outside";
|
|
23942
24175
|
if (ct._border) ct._border.set({ stroke: wantBW > 0 ? wantBC : "transparent", strokeWidth: wantBW, dirty: true });
|
|
23943
24176
|
if (ct._mat) ct._mat.set({ stroke: wantPC, strokeWidth: wantPad, dirty: true });
|
|
23944
24177
|
ct.borderPadding = wantPad;
|
|
23945
24178
|
ct.borderPaddingColor = wantPC;
|
|
24179
|
+
ct.borderPosition = wantPos;
|
|
24180
|
+
{
|
|
24181
|
+
const gMinDim = Math.min(ct.frameW, ct.frameH);
|
|
24182
|
+
const rxRaw = ct.rx || 0;
|
|
24183
|
+
const gRx = Math.max(0, Math.min(rxRaw > 0.5 ? rxRaw : rxRaw * gMinDim, ct.frameW / 2, ct.frameH / 2));
|
|
24184
|
+
const gGeo = computeOutlineGeometry({
|
|
24185
|
+
frameW: ct.frameW,
|
|
24186
|
+
frameH: ct.frameH,
|
|
24187
|
+
bw: wantBW,
|
|
24188
|
+
pad: wantPad,
|
|
24189
|
+
rx: gRx,
|
|
24190
|
+
outward: wantPos === "outside"
|
|
24191
|
+
});
|
|
24192
|
+
const isCircle = (ct.shape || "rect") === "circle";
|
|
24193
|
+
if (ct._border) {
|
|
24194
|
+
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 });
|
|
24195
|
+
}
|
|
24196
|
+
if (ct._mat) {
|
|
24197
|
+
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 });
|
|
24198
|
+
}
|
|
24199
|
+
}
|
|
23946
24200
|
const sBlur = Math.max(0, Number(element.imageShadowBlur) || 0);
|
|
23947
24201
|
const sColor = element.imageShadowColor;
|
|
23948
24202
|
if (sBlur > 0 || sColor) {
|
|
@@ -25252,6 +25506,7 @@ const PageCanvas = forwardRef(
|
|
|
25252
25506
|
} else if (obj instanceof fabric.Textbox) {
|
|
25253
25507
|
const overflowPolicy = element.overflowPolicy || "grow-and-push";
|
|
25254
25508
|
let text = element.text != null && element.text !== "" ? element.text : " ";
|
|
25509
|
+
text = applyElementTextCase(text, element.textCase);
|
|
25255
25510
|
let parsedStyles = null;
|
|
25256
25511
|
if (element.formattingEnabled === true) {
|
|
25257
25512
|
const parsed = parseTextMarkdown(text);
|
|
@@ -25896,6 +26151,13 @@ const PageCanvas = forwardRef(
|
|
|
25896
26151
|
const img = await fabric.FabricImage.fromURL(url, { crossOrigin: "anonymous" });
|
|
25897
26152
|
if (!fabricRef.current || !isLatestRequest()) return;
|
|
25898
26153
|
await normalizeSvgImageDimensions(img, imageUrl, element.sourceFormat, svgDecodeTarget);
|
|
26154
|
+
{
|
|
26155
|
+
const natW = img.width ?? 0;
|
|
26156
|
+
const natH = img.height ?? 0;
|
|
26157
|
+
if (natW <= 1 && natH <= 1 && Number(element.width) > 8 && Number(element.height) > 8) {
|
|
26158
|
+
throw new Error(`image decoded to ${natW}x${natH} — treating as failed load`);
|
|
26159
|
+
}
|
|
26160
|
+
}
|
|
25899
26161
|
if (!isLatestRequest()) return;
|
|
25900
26162
|
const imageFitForFade = element.imageFit || ((_a2 = element.style) == null ? void 0 : _a2.imageFit) || "cover";
|
|
25901
26163
|
const clipShapeForFade = element.clipShape ?? ((_b2 = element.style) == null ? void 0 : _b2.imageFrameShape) ?? (isPreviewMode ? "rectangle" : "none");
|
|
@@ -26103,7 +26365,9 @@ const PageCanvas = forwardRef(
|
|
|
26103
26365
|
strokeWidth: element.imageBorderWidth ?? 0,
|
|
26104
26366
|
// Gap between the image and the outline (the "matted photo" look).
|
|
26105
26367
|
borderPadding: element.imageBorderPadding ?? 0,
|
|
26106
|
-
|
|
26368
|
+
// Gap is empty space by default, not a white mat.
|
|
26369
|
+
borderPaddingColor: element.imageBorderPaddingColor ?? "transparent",
|
|
26370
|
+
borderPosition: element.imageBorderPosition ?? "outside",
|
|
26107
26371
|
// Optional image drop shadow (element property).
|
|
26108
26372
|
shadow: (element.imageShadowBlur ?? 0) > 0 || element.imageShadowColor ? {
|
|
26109
26373
|
color: element.imageShadowColor ?? "rgba(0,0,0,0.25)",
|
|
@@ -26260,6 +26524,19 @@ const PageCanvas = forwardRef(
|
|
|
26260
26524
|
}
|
|
26261
26525
|
fc.requestRenderAll();
|
|
26262
26526
|
} catch (error) {
|
|
26527
|
+
console.error("[PageCanvas] image failed to load", {
|
|
26528
|
+
id: element.id,
|
|
26529
|
+
url: (element.src || element.imageUrl || "").slice(0, 200),
|
|
26530
|
+
error: error instanceof Error ? error.message : String(error)
|
|
26531
|
+
});
|
|
26532
|
+
const fcNow = fabricRef.current;
|
|
26533
|
+
if (fcNow && fcNow.__pixldocsEditMode === true) {
|
|
26534
|
+
try {
|
|
26535
|
+
markPlaceholderAsBrokenImage(placeholder);
|
|
26536
|
+
fcNow.requestRenderAll();
|
|
26537
|
+
} catch {
|
|
26538
|
+
}
|
|
26539
|
+
}
|
|
26263
26540
|
}
|
|
26264
26541
|
};
|
|
26265
26542
|
const handleCanvasClick = useCallback(
|
|
@@ -28865,7 +29142,9 @@ function expandBoundTables(pages, formValues) {
|
|
|
28865
29142
|
const t = node;
|
|
28866
29143
|
if (t.type === "table" && ((_a2 = t.tableData) == null ? void 0 : _a2.repeat)) {
|
|
28867
29144
|
const entries = tableEntriesFor(t.tableData.repeat.from, formValues);
|
|
28868
|
-
|
|
29145
|
+
if (entries.length > 0) {
|
|
29146
|
+
t.tableData = expandTableRepeat(t.tableData, entries);
|
|
29147
|
+
}
|
|
28869
29148
|
for (const row of t.tableData.cells) {
|
|
28870
29149
|
for (const cell of row) {
|
|
28871
29150
|
if (!cell.field) continue;
|
|
@@ -30020,7 +30299,12 @@ function pagesHaveConstantTokens(pages) {
|
|
|
30020
30299
|
return pages.some((p) => walk(p.children));
|
|
30021
30300
|
}
|
|
30022
30301
|
function substituteConstantTokens(pages, constants) {
|
|
30023
|
-
const sub = (s) => s.replace(/\{\{\s*\$([a-zA-Z0-9_]+)\s*\}\}/g, (m, name) =>
|
|
30302
|
+
const sub = (s) => s.replace(/\{\{\s*\$([a-zA-Z0-9_]+)\s*\}\}/g, (m, name) => (
|
|
30303
|
+
// Unresolved tokens are ERASED rather than left as literal braces: on a
|
|
30304
|
+
// money cell a missing symbol still reads as a number, whereas
|
|
30305
|
+
// "{{$currency}}9,500.00" is visibly broken output.
|
|
30306
|
+
Object.prototype.hasOwnProperty.call(constants, name) ? String(constants[name]) : ""
|
|
30307
|
+
));
|
|
30024
30308
|
const walk = (nodes) => {
|
|
30025
30309
|
for (const n of nodes ?? []) {
|
|
30026
30310
|
if (n.type === "text") {
|
|
@@ -30051,10 +30335,9 @@ function applyContentBoundsPagination(config) {
|
|
|
30051
30335
|
}
|
|
30052
30336
|
let mutated = continuationMasters.length > 0;
|
|
30053
30337
|
const constants = config.constants;
|
|
30054
|
-
|
|
30055
|
-
if (hasConstants && pagesHaveConstantTokens(pages)) {
|
|
30338
|
+
if (pagesHaveConstantTokens(pages)) {
|
|
30056
30339
|
pages = pages.map((p) => JSON.parse(JSON.stringify(p)));
|
|
30057
|
-
substituteConstantTokens(pages, constants);
|
|
30340
|
+
substituteConstantTokens(pages, constants && typeof constants === "object" ? constants : {});
|
|
30058
30341
|
mutated = true;
|
|
30059
30342
|
}
|
|
30060
30343
|
let resultPages = [];
|
|
@@ -32224,8 +32507,9 @@ async function resolveTemplateData(options) {
|
|
|
32224
32507
|
void 0,
|
|
32225
32508
|
repeatablePagesInput.length > 0 ? repeatablePagesInput : void 0
|
|
32226
32509
|
);
|
|
32510
|
+
const paginated = applyContentBoundsPagination(resolvedConfig);
|
|
32227
32511
|
return {
|
|
32228
|
-
config: applyThemeIfNeeded(
|
|
32512
|
+
config: applyThemeIfNeeded(paginated),
|
|
32229
32513
|
templateName: template.name || "Untitled",
|
|
32230
32514
|
templateId,
|
|
32231
32515
|
price: template.price ?? 0
|
|
@@ -33866,6 +34150,43 @@ function stampPixldocsImageIdOnSvg(svg, id) {
|
|
|
33866
34150
|
const attr = ` data-pixldocs-image-id="${escapeSvgDataAttr(id)}"`;
|
|
33867
34151
|
return svg.replace(/<image\b/i, `<image${attr}`);
|
|
33868
34152
|
}
|
|
34153
|
+
function colorHasAlpha(color) {
|
|
34154
|
+
if (typeof color !== "string") return false;
|
|
34155
|
+
const c = color.trim().toLowerCase();
|
|
34156
|
+
if (c === "transparent") return true;
|
|
34157
|
+
const rgba = c.match(/^rgba?\(([^)]+)\)$/);
|
|
34158
|
+
if (rgba) {
|
|
34159
|
+
const parts = rgba[1].split(",").map((x) => x.trim());
|
|
34160
|
+
return parts.length > 3 && Number(parts[3]) < 1;
|
|
34161
|
+
}
|
|
34162
|
+
if (/^#[0-9a-f]{8}$/.test(c)) return parseInt(c.slice(7, 9), 16) < 255;
|
|
34163
|
+
if (/^#[0-9a-f]{4}$/.test(c)) return parseInt(c[4] + c[4], 16) < 255;
|
|
34164
|
+
return false;
|
|
34165
|
+
}
|
|
34166
|
+
function paintIsAlphaGradient(paint) {
|
|
34167
|
+
const stops = paint == null ? void 0 : paint.colorStops;
|
|
34168
|
+
if (!Array.isArray(stops) || !stops.length) return false;
|
|
34169
|
+
return stops.some((st) => colorHasAlpha(st == null ? void 0 : st.color) || typeof (st == null ? void 0 : st.opacity) === "number" && st.opacity < 1);
|
|
34170
|
+
}
|
|
34171
|
+
function objectNeedsAlphaGradientRaster(obj) {
|
|
34172
|
+
if (!obj) return false;
|
|
34173
|
+
return paintIsAlphaGradient(obj.fill) || paintIsAlphaGradient(obj.stroke);
|
|
34174
|
+
}
|
|
34175
|
+
function rasterizeObjectToSvgImage(obj, multiplier) {
|
|
34176
|
+
try {
|
|
34177
|
+
if (typeof obj.toDataURL !== "function") return null;
|
|
34178
|
+
const rect = obj.getBoundingRect();
|
|
34179
|
+
if (!rect || !(rect.width > 0) || !(rect.height > 0)) return null;
|
|
34180
|
+
const url = obj.toDataURL({ multiplier, enableRetinaScaling: false });
|
|
34181
|
+
if (typeof url !== "string" || !url.startsWith("data:image")) return null;
|
|
34182
|
+
const n = (v) => Number(v.toFixed(4));
|
|
34183
|
+
return `<image x="${n(rect.left)}" y="${n(rect.top)}" width="${n(rect.width)}" height="${n(rect.height)}" preserveAspectRatio="none" xlink:href="${url}"></image>`;
|
|
34184
|
+
} catch (e) {
|
|
34185
|
+
console.warn("[canvas-svg-capture][alphaGradient] raster failed:", e);
|
|
34186
|
+
return null;
|
|
34187
|
+
}
|
|
34188
|
+
}
|
|
34189
|
+
const ALPHA_GRADIENT_RASTER_MULTIPLIER = 3;
|
|
33869
34190
|
function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight) {
|
|
33870
34191
|
const prevVPT = fabricInstance.viewportTransform ? [...fabricInstance.viewportTransform] : void 0;
|
|
33871
34192
|
const prevSvgVPT = fabricInstance.svgViewportTransformation;
|
|
@@ -33886,10 +34207,23 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
33886
34207
|
try {
|
|
33887
34208
|
const visit = (obj) => {
|
|
33888
34209
|
if (!obj) return;
|
|
34210
|
+
if (obj.__pixldocsEditorChrome) {
|
|
34211
|
+
const originalToSVG = typeof obj.toSVG === "function" ? obj.toSVG.bind(obj) : null;
|
|
34212
|
+
if (originalToSVG) {
|
|
34213
|
+
obj.toSVG = () => "";
|
|
34214
|
+
svgPatchRecords.push({ obj, originalToSVG });
|
|
34215
|
+
}
|
|
34216
|
+
return;
|
|
34217
|
+
}
|
|
33889
34218
|
const imageId = typeof obj.__docuforgeId === "string" && hasRenderableRasterCandidate(obj) ? obj.__docuforgeId : "";
|
|
33890
|
-
|
|
34219
|
+
const alphaGradient = objectNeedsAlphaGradientRaster(obj);
|
|
34220
|
+
if ((isTextboxLike(obj) || imageId || alphaGradient) && typeof obj.toSVG === "function") {
|
|
33891
34221
|
const originalToSVG = obj.toSVG.bind(obj);
|
|
33892
34222
|
obj.toSVG = (reviver) => {
|
|
34223
|
+
if (alphaGradient) {
|
|
34224
|
+
const raster = rasterizeObjectToSvgImage(obj, ALPHA_GRADIENT_RASTER_MULTIPLIER);
|
|
34225
|
+
if (raster) return raster;
|
|
34226
|
+
}
|
|
33893
34227
|
let svg = originalToSVG(reviver);
|
|
33894
34228
|
if (isTextboxLike(obj)) svg = stampFabricLineMetricsOnTextSvg(svg, obj);
|
|
33895
34229
|
if (isTextboxLike(obj)) svg = warpTextboxSvgAlongPath(svg, obj);
|
|
@@ -33988,9 +34322,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
33988
34322
|
}
|
|
33989
34323
|
return svgString;
|
|
33990
34324
|
}
|
|
33991
|
-
const resolvedPackageVersion = "0.5.
|
|
34325
|
+
const resolvedPackageVersion = "0.5.497";
|
|
33992
34326
|
const PACKAGE_VERSION = resolvedPackageVersion;
|
|
33993
|
-
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.
|
|
34327
|
+
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.497";
|
|
33994
34328
|
const roundParityValue = (value) => {
|
|
33995
34329
|
if (typeof value !== "number") return value;
|
|
33996
34330
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -34429,6 +34763,11 @@ class PixldocsRenderer {
|
|
|
34429
34763
|
* Mounts a hidden PreviewCanvas component and captures the Fabric canvas output.
|
|
34430
34764
|
*/
|
|
34431
34765
|
async render(templateConfig, options = {}) {
|
|
34766
|
+
if (options.watermark === true && !templateConfig.__pixldocsWatermarked) {
|
|
34767
|
+
const { injectWatermark: injectWatermark2 } = await Promise.resolve().then(() => canvasWatermark);
|
|
34768
|
+
templateConfig = injectWatermark2(templateConfig, options.watermarkOptions);
|
|
34769
|
+
templateConfig.__pixldocsWatermarked = true;
|
|
34770
|
+
}
|
|
34432
34771
|
const pageIndex = options.pageIndex ?? 0;
|
|
34433
34772
|
const format = options.format ?? "png";
|
|
34434
34773
|
const quality = options.quality ?? 0.92;
|
|
@@ -34444,6 +34783,7 @@ class PixldocsRenderer {
|
|
|
34444
34783
|
const hasAutoShrink = configHasAutoShrinkText(templateConfig);
|
|
34445
34784
|
const defaultWait = hasAutoShrink ? 4e3 : 1800;
|
|
34446
34785
|
await this.awaitFontsForConfig(templateConfig, options.waitForFontsMs ?? defaultWait);
|
|
34786
|
+
this.flushTextMeasurementCaches();
|
|
34447
34787
|
}
|
|
34448
34788
|
const { setPackageApiUrl: setPackageApiUrl2 } = await Promise.resolve().then(() => appApi);
|
|
34449
34789
|
setPackageApiUrl2(this.config.imageProxyUrl);
|
|
@@ -34471,6 +34811,7 @@ class PixldocsRenderer {
|
|
|
34471
34811
|
const hasAutoShrink = configHasAutoShrinkText(templateConfig);
|
|
34472
34812
|
const defaultWait = hasAutoShrink ? 4e3 : 1800;
|
|
34473
34813
|
await this.awaitFontsForConfig(templateConfig, options.waitForFontsMs ?? defaultWait);
|
|
34814
|
+
this.flushTextMeasurementCaches();
|
|
34474
34815
|
}
|
|
34475
34816
|
const results = [];
|
|
34476
34817
|
for (let i = 0; i < templateConfig.pages.length; i++) {
|
|
@@ -34497,8 +34838,8 @@ class PixldocsRenderer {
|
|
|
34497
34838
|
const shouldWatermark = watermark ?? resolved.price > 0;
|
|
34498
34839
|
let configToRender = resolved.config;
|
|
34499
34840
|
if (shouldWatermark) {
|
|
34500
|
-
const { injectWatermark } = await
|
|
34501
|
-
configToRender =
|
|
34841
|
+
const { injectWatermark: injectWatermark2 } = await Promise.resolve().then(() => canvasWatermark);
|
|
34842
|
+
configToRender = injectWatermark2(configToRender, watermarkOptions);
|
|
34502
34843
|
const { injectPreviewBlur: injectPreviewBlur2 } = await Promise.resolve().then(() => previewBlur);
|
|
34503
34844
|
configToRender = injectPreviewBlur2(configToRender);
|
|
34504
34845
|
}
|
|
@@ -34557,8 +34898,8 @@ class PixldocsRenderer {
|
|
|
34557
34898
|
const shouldWatermark = watermark ?? resolved.price > 0;
|
|
34558
34899
|
let configToRender = resolved.config;
|
|
34559
34900
|
if (shouldWatermark) {
|
|
34560
|
-
const { injectWatermark } = await
|
|
34561
|
-
configToRender =
|
|
34901
|
+
const { injectWatermark: injectWatermark2 } = await Promise.resolve().then(() => canvasWatermark);
|
|
34902
|
+
configToRender = injectWatermark2(configToRender, watermarkOptions);
|
|
34562
34903
|
const { injectPreviewBlur: injectPreviewBlur2 } = await Promise.resolve().then(() => previewBlur);
|
|
34563
34904
|
configToRender = injectPreviewBlur2(configToRender);
|
|
34564
34905
|
}
|
|
@@ -34578,6 +34919,10 @@ class PixldocsRenderer {
|
|
|
34578
34919
|
* exporter, which is what `renderPdfViaClientExport` does below.
|
|
34579
34920
|
*/
|
|
34580
34921
|
async renderPdf(templateConfig, options) {
|
|
34922
|
+
if ((options == null ? void 0 : options.watermark) === true) {
|
|
34923
|
+
const { injectWatermark: injectWatermark2 } = await Promise.resolve().then(() => canvasWatermark);
|
|
34924
|
+
templateConfig = injectWatermark2(templateConfig, options.watermarkOptions);
|
|
34925
|
+
}
|
|
34581
34926
|
return this.renderPdfViaClientExport(templateConfig, {
|
|
34582
34927
|
title: options == null ? void 0 : options.title,
|
|
34583
34928
|
textMode: options == null ? void 0 : options.textMode,
|
|
@@ -34606,8 +34951,8 @@ class PixldocsRenderer {
|
|
|
34606
34951
|
const shouldWatermark = watermark ?? resolved.price > 0;
|
|
34607
34952
|
let configToRender = resolved.config;
|
|
34608
34953
|
if (shouldWatermark) {
|
|
34609
|
-
const { injectWatermark } = await
|
|
34610
|
-
configToRender =
|
|
34954
|
+
const { injectWatermark: injectWatermark2 } = await Promise.resolve().then(() => canvasWatermark);
|
|
34955
|
+
configToRender = injectWatermark2(configToRender, watermarkOptions);
|
|
34611
34956
|
const { injectPreviewBlur: injectPreviewBlur2 } = await Promise.resolve().then(() => previewBlur);
|
|
34612
34957
|
configToRender = injectPreviewBlur2(configToRender);
|
|
34613
34958
|
}
|
|
@@ -34804,7 +35149,7 @@ class PixldocsRenderer {
|
|
|
34804
35149
|
await this.waitForCanvasScene(container, cloned, i);
|
|
34805
35150
|
}
|
|
34806
35151
|
console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
|
|
34807
|
-
const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-
|
|
35152
|
+
const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-DV-TJwjP.js");
|
|
34808
35153
|
const prepared = preparePagesForExport(
|
|
34809
35154
|
cloned.pages,
|
|
34810
35155
|
canvasWidth,
|
|
@@ -35082,6 +35427,37 @@ class PixldocsRenderer {
|
|
|
35082
35427
|
new Promise((r) => setTimeout(r, Math.min(500, maxWaitMs)))
|
|
35083
35428
|
]);
|
|
35084
35429
|
}
|
|
35430
|
+
/**
|
|
35431
|
+
* Flush BOTH process-global text-measurement caches after fonts are ready
|
|
35432
|
+
* and BEFORE the capture canvas mounts.
|
|
35433
|
+
*
|
|
35434
|
+
* Why: anything that measured text before the webfonts finished loading —
|
|
35435
|
+
* most notably `applyContentBoundsPagination` running inside
|
|
35436
|
+
* `resolveFromForm` on a cold page (the EC2/MCP flow: resolve + render in
|
|
35437
|
+
* one browser context) — populates the app measurement cache and Fabric's
|
|
35438
|
+
* global char-width cache with FALLBACK metrics. `createText` then places
|
|
35439
|
+
* center/right-aligned lines from those stale widths, so a right-aligned
|
|
35440
|
+
* grid cell on a continuation page drew shifted left by
|
|
35441
|
+
* (fallbackWidth − realWidth) px vs the editor (caught by
|
|
35442
|
+
* tests/parity `auto-paginate`, a 9px shift). The later
|
|
35443
|
+
* `waitForStableTextMetrics` pass re-primes glyph bounds but never moves
|
|
35444
|
+
* the already-positioned box, so the flush must happen pre-mount.
|
|
35445
|
+
*
|
|
35446
|
+
* Only called from the headless PNG paths (`render`/`renderAllPages`),
|
|
35447
|
+
* which already default to clearing the global char cache in
|
|
35448
|
+
* `waitForStableTextMetrics` — the live-preview-adjacent PDF path keeps
|
|
35449
|
+
* its `clearGlobalCharCache: false` behaviour untouched.
|
|
35450
|
+
*/
|
|
35451
|
+
flushTextMeasurementCaches() {
|
|
35452
|
+
try {
|
|
35453
|
+
clearMeasurementCache();
|
|
35454
|
+
} catch {
|
|
35455
|
+
}
|
|
35456
|
+
try {
|
|
35457
|
+
clearFabricCharCache();
|
|
35458
|
+
} catch {
|
|
35459
|
+
}
|
|
35460
|
+
}
|
|
35085
35461
|
getNormalizedGradientStops(gradient) {
|
|
35086
35462
|
const stops = Array.isArray(gradient == null ? void 0 : gradient.stops) ? gradient.stops.map((stop) => ({
|
|
35087
35463
|
offset: Math.max(0, Math.min(1, Number((stop == null ? void 0 : stop.offset) ?? 0))),
|
|
@@ -37124,7 +37500,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
37124
37500
|
if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
|
|
37125
37501
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
37126
37502
|
try {
|
|
37127
|
-
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-
|
|
37503
|
+
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-DV-TJwjP.js");
|
|
37128
37504
|
try {
|
|
37129
37505
|
await logTextMeasurementDiagnostic(svgToDraw);
|
|
37130
37506
|
} catch {
|
|
@@ -37372,13 +37748,136 @@ async function getPublishedTemplate(options) {
|
|
|
37372
37748
|
const rows = await res.json();
|
|
37373
37749
|
return rows[0] ?? null;
|
|
37374
37750
|
}
|
|
37751
|
+
const WATERMARK_ID_PREFIX = "__wm_";
|
|
37752
|
+
const DEFAULT_WATERMARK_OPACITY = 0.14;
|
|
37753
|
+
const DEFAULT_WATERMARK_FONT_SIZE = 18;
|
|
37754
|
+
const DEFAULT_WATERMARK_ANGLE = -30;
|
|
37755
|
+
function getWatermarkText() {
|
|
37756
|
+
try {
|
|
37757
|
+
const host = window.location.hostname;
|
|
37758
|
+
if (host.includes("biomaker")) return "biomaker.app";
|
|
37759
|
+
} catch {
|
|
37760
|
+
}
|
|
37761
|
+
return "pixldocs.com";
|
|
37762
|
+
}
|
|
37763
|
+
function getLuminance(color) {
|
|
37764
|
+
if (!color || color === "transparent" || color === "none") return 1;
|
|
37765
|
+
let r = 255, g = 255, b = 255;
|
|
37766
|
+
if (color.startsWith("#")) {
|
|
37767
|
+
const hex = color.slice(1);
|
|
37768
|
+
const full = hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex;
|
|
37769
|
+
const n = parseInt(full, 16);
|
|
37770
|
+
r = n >> 16 & 255;
|
|
37771
|
+
g = n >> 8 & 255;
|
|
37772
|
+
b = n & 255;
|
|
37773
|
+
} else {
|
|
37774
|
+
const m = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
37775
|
+
if (m) {
|
|
37776
|
+
r = +m[1];
|
|
37777
|
+
g = +m[2];
|
|
37778
|
+
b = +m[3];
|
|
37779
|
+
}
|
|
37780
|
+
}
|
|
37781
|
+
return (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
37782
|
+
}
|
|
37783
|
+
function getWatermarkColor(bgColor) {
|
|
37784
|
+
const lum = getLuminance(bgColor);
|
|
37785
|
+
return lum < 0.45 ? "#cccccc" : "#808080";
|
|
37786
|
+
}
|
|
37787
|
+
function getPageBgColor(page, canvasBg) {
|
|
37788
|
+
var _a2, _b2;
|
|
37789
|
+
const settingsBg = (_a2 = page.settings) == null ? void 0 : _a2.backgroundColor;
|
|
37790
|
+
if (settingsBg && settingsBg !== "transparent" && settingsBg !== "none") {
|
|
37791
|
+
return settingsBg;
|
|
37792
|
+
}
|
|
37793
|
+
const children = page.children || [];
|
|
37794
|
+
for (const child of children) {
|
|
37795
|
+
if (child.type === "shape" && child.fill && child.fill !== "transparent" && child.fill !== "none") {
|
|
37796
|
+
return child.fill;
|
|
37797
|
+
}
|
|
37798
|
+
if ((_b2 = child.children) == null ? void 0 : _b2.length) {
|
|
37799
|
+
for (const gc of child.children) {
|
|
37800
|
+
if (gc.type === "shape" && gc.fill && gc.fill !== "transparent" && gc.fill !== "none") {
|
|
37801
|
+
return gc.fill;
|
|
37802
|
+
}
|
|
37803
|
+
}
|
|
37804
|
+
}
|
|
37805
|
+
}
|
|
37806
|
+
return canvasBg;
|
|
37807
|
+
}
|
|
37808
|
+
function generateWatermarkElements(canvasWidth, canvasHeight, wmColor, options = {}) {
|
|
37809
|
+
const elements = [];
|
|
37810
|
+
const text = options.text ?? getWatermarkText();
|
|
37811
|
+
const fontSize = options.fontSize ?? DEFAULT_WATERMARK_FONT_SIZE;
|
|
37812
|
+
const angle = options.angle ?? DEFAULT_WATERMARK_ANGLE;
|
|
37813
|
+
const opacity = options.opacity ?? DEFAULT_WATERMARK_OPACITY;
|
|
37814
|
+
const estimatedTextWidth = text.length * fontSize * 0.55;
|
|
37815
|
+
const spacingX = Math.max(160, estimatedTextWidth + 30);
|
|
37816
|
+
const spacingY = 90;
|
|
37817
|
+
const startX = -canvasWidth * 0.3;
|
|
37818
|
+
const startY = -canvasHeight * 0.3;
|
|
37819
|
+
const endX = canvasWidth * 1.5;
|
|
37820
|
+
const endY = canvasHeight * 1.5;
|
|
37821
|
+
let idx = 0;
|
|
37822
|
+
for (let y = startY; y < endY; y += spacingY) {
|
|
37823
|
+
for (let x = startX; x < endX; x += spacingX) {
|
|
37824
|
+
elements.push({
|
|
37825
|
+
id: `${WATERMARK_ID_PREFIX}${idx++}`,
|
|
37826
|
+
type: "text",
|
|
37827
|
+
left: x,
|
|
37828
|
+
top: y,
|
|
37829
|
+
width: 200,
|
|
37830
|
+
height: 40,
|
|
37831
|
+
text,
|
|
37832
|
+
fontFamily: "Montserrat",
|
|
37833
|
+
fontSize,
|
|
37834
|
+
fontWeight: "600",
|
|
37835
|
+
fill: wmColor,
|
|
37836
|
+
angle,
|
|
37837
|
+
selectable: false,
|
|
37838
|
+
locked: true,
|
|
37839
|
+
visible: true,
|
|
37840
|
+
opacity,
|
|
37841
|
+
scaleX: 1,
|
|
37842
|
+
scaleY: 1,
|
|
37843
|
+
letterSpacing: 4
|
|
37844
|
+
});
|
|
37845
|
+
}
|
|
37846
|
+
}
|
|
37847
|
+
return elements;
|
|
37848
|
+
}
|
|
37849
|
+
function injectWatermark(config, options = {}) {
|
|
37850
|
+
var _a2, _b2, _c2;
|
|
37851
|
+
const canvasWidth = ((_a2 = config.canvas) == null ? void 0 : _a2.width) || 612;
|
|
37852
|
+
const canvasHeight = ((_b2 = config.canvas) == null ? void 0 : _b2.height) || 792;
|
|
37853
|
+
const canvasBg = (_c2 = config.canvas) == null ? void 0 : _c2.backgroundColor;
|
|
37854
|
+
return {
|
|
37855
|
+
...config,
|
|
37856
|
+
pages: config.pages.map((page) => {
|
|
37857
|
+
const pageBg = getPageBgColor(page, canvasBg);
|
|
37858
|
+
const wmColor = getWatermarkColor(pageBg);
|
|
37859
|
+
const watermarkElements = generateWatermarkElements(canvasWidth, canvasHeight, wmColor, options);
|
|
37860
|
+
return {
|
|
37861
|
+
...page,
|
|
37862
|
+
children: [
|
|
37863
|
+
...page.children || [],
|
|
37864
|
+
...watermarkElements
|
|
37865
|
+
]
|
|
37866
|
+
};
|
|
37867
|
+
})
|
|
37868
|
+
};
|
|
37869
|
+
}
|
|
37870
|
+
const canvasWatermark = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
37871
|
+
__proto__: null,
|
|
37872
|
+
injectWatermark
|
|
37873
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
37375
37874
|
function setAutoShrinkDebug(enabled) {
|
|
37376
37875
|
if (typeof window !== "undefined") {
|
|
37377
37876
|
window.__pixldocsDebugAutoShrink = !!enabled;
|
|
37378
37877
|
}
|
|
37379
37878
|
}
|
|
37380
37879
|
export {
|
|
37381
|
-
|
|
37880
|
+
resolveBlurElementExactIdsFromFlatFormKeys as $,
|
|
37382
37881
|
API_URL as A,
|
|
37383
37882
|
collectFontDescriptorsFromConfig as B,
|
|
37384
37883
|
collectFontsFromConfig as C,
|
|
@@ -37399,23 +37898,24 @@ export {
|
|
|
37399
37898
|
hasAnyPreviewBlur as R,
|
|
37400
37899
|
injectPreviewBlur as S,
|
|
37401
37900
|
TRIANGLE_STROKE_MITER_LIMIT as T,
|
|
37402
|
-
|
|
37403
|
-
|
|
37404
|
-
|
|
37405
|
-
|
|
37406
|
-
|
|
37407
|
-
|
|
37408
|
-
|
|
37901
|
+
injectWatermark as U,
|
|
37902
|
+
isBundledAssetUrl as V,
|
|
37903
|
+
isFontAvailable as W,
|
|
37904
|
+
isPrivateUrl as X,
|
|
37905
|
+
listPublishedTemplates as Y,
|
|
37906
|
+
loadGoogleFontCSS as Z,
|
|
37907
|
+
normalizeFontFamily as _,
|
|
37409
37908
|
getAbsoluteBounds as a,
|
|
37410
|
-
|
|
37411
|
-
|
|
37412
|
-
|
|
37413
|
-
|
|
37414
|
-
|
|
37415
|
-
|
|
37416
|
-
|
|
37417
|
-
|
|
37418
|
-
|
|
37909
|
+
resolveFontWeight as a0,
|
|
37910
|
+
resolveForRender as a1,
|
|
37911
|
+
resolveFromForm as a2,
|
|
37912
|
+
resolveTemplateData as a3,
|
|
37913
|
+
rewriteSvgFontsForJsPDF as a4,
|
|
37914
|
+
setAutoShrinkDebug as a5,
|
|
37915
|
+
setBundledAssetPrefixes as a6,
|
|
37916
|
+
warmResolvedTemplateForPreview as a7,
|
|
37917
|
+
warmTemplateFromForm as a8,
|
|
37918
|
+
canvasImageLoader as a9,
|
|
37419
37919
|
getProxiedImageUrl as b,
|
|
37420
37920
|
captureFabricCanvasSvgForPdf as c,
|
|
37421
37921
|
getImageProxyFetchOptions as d,
|
|
@@ -37442,4 +37942,4 @@ export {
|
|
|
37442
37942
|
awaitFontsForConfig as y,
|
|
37443
37943
|
buildTeaserBlurFlatKeys as z
|
|
37444
37944
|
};
|
|
37445
|
-
//# sourceMappingURL=index-
|
|
37945
|
+
//# sourceMappingURL=index-CKhnRi3S.js.map
|