@pixldocs/canvas-renderer 0.5.495 → 0.5.496
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-DaaT4Mo7.cjs → index-CZtvER5z.cjs} +276 -56
- package/dist/index-CZtvER5z.cjs.map +1 -0
- package/dist/{index-Cvi3YYOq.js → index-CiSoT2Lk.js} +276 -56
- package/dist/index-CiSoT2Lk.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/{vectorPdfExport-roj_Ddzd.cjs → vectorPdfExport-B2KtFs76.cjs} +4 -4
- package/dist/{vectorPdfExport-roj_Ddzd.cjs.map → vectorPdfExport-B2KtFs76.cjs.map} +1 -1
- package/dist/{vectorPdfExport-B6m8o09g.js → vectorPdfExport-E3x8GBto.js} +4 -4
- package/dist/{vectorPdfExport-B6m8o09g.js.map → vectorPdfExport-E3x8GBto.js.map} +1 -1
- package/package.json +1 -1
- package/dist/index-Cvi3YYOq.js.map +0 -1
- package/dist/index-DaaT4Mo7.cjs.map +0 -1
|
@@ -2239,6 +2239,40 @@ function adaptLayoutGrid(grid, mode) {
|
|
|
2239
2239
|
const cells = (grid.cells ?? []).map((c) => c && c.grid ? { ...c, grid: adaptLayoutGrid(c.grid, mode) } : c);
|
|
2240
2240
|
return { ...grid, dir: grid.dir === from ? to : grid.dir, cells };
|
|
2241
2241
|
}
|
|
2242
|
+
function isAspectLockedNode(node) {
|
|
2243
|
+
const e = node;
|
|
2244
|
+
if (!e) return false;
|
|
2245
|
+
if (e.lockAspect === true) return true;
|
|
2246
|
+
if (e.clipShape === "circle") return true;
|
|
2247
|
+
const kind = e.componentKind || e.smartType;
|
|
2248
|
+
return kind === "qrcode" || kind === "barcode";
|
|
2249
|
+
}
|
|
2250
|
+
function scaleNodeForReflow(node, sx, sy, fscale) {
|
|
2251
|
+
const n = node;
|
|
2252
|
+
const el = { ...n };
|
|
2253
|
+
const hasBox = typeof n.width === "number" && typeof n.height === "number";
|
|
2254
|
+
const f = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
2255
|
+
if (hasBox && isAspectLockedNode(n) && sx !== sy) {
|
|
2256
|
+
const s = Math.min(sx, sy);
|
|
2257
|
+
const cx = (f(n.left) + n.width / 2) * sx;
|
|
2258
|
+
const cy = (f(n.top) + n.height / 2) * sy;
|
|
2259
|
+
el.width = n.width * s;
|
|
2260
|
+
el.height = n.height * s;
|
|
2261
|
+
el.left = cx - el.width / 2;
|
|
2262
|
+
el.top = cy - el.height / 2;
|
|
2263
|
+
} else {
|
|
2264
|
+
if (typeof el.left === "number") el.left = el.left * sx;
|
|
2265
|
+
if (typeof el.top === "number") el.top = el.top * sy;
|
|
2266
|
+
if (typeof el.width === "number") el.width = el.width * sx;
|
|
2267
|
+
if (typeof el.height === "number") el.height = el.height * sy;
|
|
2268
|
+
}
|
|
2269
|
+
if (typeof el.fontSize === "number") el.fontSize = Math.max(4, el.fontSize * fscale);
|
|
2270
|
+
if (typeof el.minBoxHeight === "number") el.minBoxHeight = el.minBoxHeight * sy;
|
|
2271
|
+
if (Array.isArray(el.children)) {
|
|
2272
|
+
el.children = el.children.map((c) => scaleNodeForReflow(c, sx, sy, fscale));
|
|
2273
|
+
}
|
|
2274
|
+
return el;
|
|
2275
|
+
}
|
|
2242
2276
|
function computeGridHandles(grid, box, gridPath = []) {
|
|
2243
2277
|
const out = [];
|
|
2244
2278
|
const n = grid.cells.length;
|
|
@@ -2641,16 +2675,7 @@ const reflowPagesFromBase = (base, W, H) => {
|
|
|
2641
2675
|
const fscale = Math.sqrt(Math.max(0.01, sx * sy));
|
|
2642
2676
|
const adapt = layoutAdaptationFor(base.width, base.height, W, H);
|
|
2643
2677
|
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
|
-
};
|
|
2678
|
+
const scaleNode = (node) => scaleNodeForReflow(node, sx, sy, fscale);
|
|
2654
2679
|
return base.pages.map((p) => {
|
|
2655
2680
|
const pg = p;
|
|
2656
2681
|
const page = {
|
|
@@ -3239,6 +3264,13 @@ const useEditorStore = create((set, get) => ({
|
|
|
3239
3264
|
return { canvas: nextCanvas, ...committed };
|
|
3240
3265
|
});
|
|
3241
3266
|
},
|
|
3267
|
+
getCanvasForSave: () => {
|
|
3268
|
+
const { canvas } = get();
|
|
3269
|
+
const base = sizeBaseSnapshot;
|
|
3270
|
+
if (!base) return canvas;
|
|
3271
|
+
if (canvas.width === base.width && canvas.height === base.height) return canvas;
|
|
3272
|
+
return { ...canvas, width: base.width, height: base.height, pages: base.pages };
|
|
3273
|
+
},
|
|
3242
3274
|
addSizeVariant: (variant) => set((state) => {
|
|
3243
3275
|
const sizes = state.canvas.sizes ?? [];
|
|
3244
3276
|
if (sizes.some((s) => s.id === variant.id)) return {};
|
|
@@ -6492,8 +6524,14 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
|
|
|
6492
6524
|
shape,
|
|
6493
6525
|
rx: rxRatio,
|
|
6494
6526
|
// Pass ratio, not pixel value
|
|
6495
|
-
|
|
6496
|
-
|
|
6527
|
+
// Image outline is an ELEMENT property (imageBorder*), not the generic
|
|
6528
|
+
// shape stroke — this builder forwarded only stroke/strokeWidth, so
|
|
6529
|
+
// outline/gap never reached it.
|
|
6530
|
+
stroke: (element.imageBorderWidth ?? 0) > 0 ? element.imageBorderColor ?? "#FFFFFF" : element.stroke,
|
|
6531
|
+
strokeWidth: (element.imageBorderWidth ?? 0) > 0 ? element.imageBorderWidth : element.strokeWidth,
|
|
6532
|
+
borderPadding: element.imageBorderPadding ?? 0,
|
|
6533
|
+
borderPaddingColor: element.imageBorderPaddingColor ?? "transparent",
|
|
6534
|
+
borderPosition: element.imageBorderPosition ?? "outside",
|
|
6497
6535
|
panX,
|
|
6498
6536
|
panY,
|
|
6499
6537
|
zoom
|
|
@@ -7044,10 +7082,10 @@ function finalizeCropGroupCoords(g) {
|
|
|
7044
7082
|
g.setCoords();
|
|
7045
7083
|
}
|
|
7046
7084
|
function updateCoverLayout(g) {
|
|
7047
|
-
var _a2;
|
|
7085
|
+
var _a2, _b2;
|
|
7048
7086
|
const ct = g.__cropData;
|
|
7049
7087
|
if (!ct) return;
|
|
7050
|
-
const { frameW, frameH, shape, rx: rxRatio, _img: img
|
|
7088
|
+
const { frameW, frameH, shape, rx: rxRatio, _img: img } = ct;
|
|
7051
7089
|
const minDim = Math.min(frameW, frameH);
|
|
7052
7090
|
let rx = rxRatio > 0.5 ? rxRatio : rxRatio * minDim;
|
|
7053
7091
|
rx = Math.max(0, Math.min(rx, frameW / 2, frameH / 2));
|
|
@@ -7180,25 +7218,31 @@ function updateCoverLayout(g) {
|
|
|
7180
7218
|
g.clipPath.excludeFromExport = true;
|
|
7181
7219
|
}
|
|
7182
7220
|
}
|
|
7221
|
+
const wantCircle = shape === "circle";
|
|
7222
|
+
const border = ensureRingShapeClass(g, ct, "_border", wantCircle);
|
|
7223
|
+
const mat = ensureRingShapeClass(g, ct, "_mat", wantCircle);
|
|
7183
7224
|
const bw = border ? Number(border.strokeWidth) || 0 : 0;
|
|
7184
|
-
const mat = ct._mat;
|
|
7185
7225
|
const pad = Math.max(0, Number(ct.borderPadding) || 0);
|
|
7226
|
+
const outward = (ct.borderPosition ?? "outside") === "outside";
|
|
7186
7227
|
const borderMinDim = Math.min(frameW, frameH);
|
|
7187
7228
|
let borderRx = rxRatio > 0.5 ? rxRatio : rxRatio * borderMinDim;
|
|
7188
7229
|
borderRx = Math.max(0, Math.min(borderRx, frameW / 2, frameH / 2));
|
|
7230
|
+
const geo = computeOutlineGeometry({ frameW, frameH, bw, pad, rx: borderRx, outward });
|
|
7189
7231
|
if (border) {
|
|
7190
7232
|
if (shape === "circle") {
|
|
7191
|
-
border.set({ rx:
|
|
7233
|
+
border.set({ rx: geo.border.width / 2, ry: geo.border.height / 2 });
|
|
7192
7234
|
} else {
|
|
7193
|
-
border.set({ width:
|
|
7235
|
+
border.set({ width: geo.border.width, height: geo.border.height, rx: geo.border.rx, ry: geo.border.rx });
|
|
7194
7236
|
}
|
|
7237
|
+
border.dirty = true;
|
|
7195
7238
|
}
|
|
7196
7239
|
if (mat) {
|
|
7197
7240
|
if (shape === "circle") {
|
|
7198
|
-
mat.set({ rx:
|
|
7241
|
+
mat.set({ rx: geo.mat.width / 2, ry: geo.mat.height / 2 });
|
|
7199
7242
|
} else {
|
|
7200
|
-
mat.set({ width:
|
|
7243
|
+
mat.set({ width: geo.mat.width, height: geo.mat.height, rx: geo.mat.rx, ry: geo.mat.rx });
|
|
7201
7244
|
}
|
|
7245
|
+
mat.dirty = true;
|
|
7202
7246
|
}
|
|
7203
7247
|
if (!img) {
|
|
7204
7248
|
const placeholderFrame = ct._placeholderFrame ?? ((_a2 = g._objects) == null ? void 0 : _a2.find((obj) => obj.__isPlaceholderFrame));
|
|
@@ -7227,8 +7271,9 @@ function updateCoverLayout(g) {
|
|
|
7227
7271
|
img._ct.panX = img.__panX ?? 0.5;
|
|
7228
7272
|
img._ct.panY = img.__panY ?? 0.5;
|
|
7229
7273
|
}
|
|
7230
|
-
const
|
|
7231
|
-
const
|
|
7274
|
+
const srcEl = img._originalElement ?? ((_b2 = img.getElement) == null ? void 0 : _b2.call(img));
|
|
7275
|
+
const iw = Number(srcEl == null ? void 0 : srcEl.naturalWidth) || Number(srcEl == null ? void 0 : srcEl.width) || img.width || 1;
|
|
7276
|
+
const ih = Number(srcEl == null ? void 0 : srcEl.naturalHeight) || Number(srcEl == null ? void 0 : srcEl.height) || img.height || 1;
|
|
7232
7277
|
const fitContain = ct.fit === "contain";
|
|
7233
7278
|
const baseScale = fitContain ? Math.min(frameW / iw, frameH / ih) : Math.max(frameW / iw, frameH / ih);
|
|
7234
7279
|
const zoom = fitContain ? Math.max(1, Math.min(3, ct.containScale ?? 1)) : Math.max(1, img._ct.zoom ?? 1);
|
|
@@ -7265,6 +7310,42 @@ function updateCoverLayout(g) {
|
|
|
7265
7310
|
offsetY = overflowY > 0 ? -overflowY * (panY - 0.5) : 0;
|
|
7266
7311
|
}
|
|
7267
7312
|
img.set({ left: offsetX, top: offsetY });
|
|
7313
|
+
const wantsOutline = bw > 0 || pad > 0;
|
|
7314
|
+
const shapedMask = shape === "circle" || shape === "roundRect";
|
|
7315
|
+
if (wantsOutline && shapedMask) {
|
|
7316
|
+
if (g.clipPath) {
|
|
7317
|
+
img.clipPath = g.clipPath;
|
|
7318
|
+
g.clipPath = void 0;
|
|
7319
|
+
}
|
|
7320
|
+
if (img.cropX || img.cropY || img.width !== iw) {
|
|
7321
|
+
img.set({ width: iw, height: ih, cropX: 0, cropY: 0 });
|
|
7322
|
+
}
|
|
7323
|
+
} else if (wantsOutline && !fitContain) {
|
|
7324
|
+
const regionW = Math.min(iw, frameW / finalScale);
|
|
7325
|
+
const regionH = Math.min(ih, frameH / finalScale);
|
|
7326
|
+
img.set({
|
|
7327
|
+
width: regionW,
|
|
7328
|
+
height: regionH,
|
|
7329
|
+
cropX: (iw - regionW) * panX,
|
|
7330
|
+
cropY: (ih - regionH) * panY,
|
|
7331
|
+
left: 0,
|
|
7332
|
+
top: 0
|
|
7333
|
+
});
|
|
7334
|
+
img.clipPath = void 0;
|
|
7335
|
+
g.clipPath = void 0;
|
|
7336
|
+
} else {
|
|
7337
|
+
if (img.clipPath) img.clipPath = void 0;
|
|
7338
|
+
if (img.cropX || img.cropY || img.width !== iw) {
|
|
7339
|
+
img.set({ width: iw, height: ih, cropX: 0, cropY: 0 });
|
|
7340
|
+
}
|
|
7341
|
+
}
|
|
7342
|
+
const imgClip = img.clipPath;
|
|
7343
|
+
if (imgClip && typeof imgClip.set === "function") {
|
|
7344
|
+
const csx = img.scaleX || 1;
|
|
7345
|
+
const csy = img.scaleY || 1;
|
|
7346
|
+
imgClip.set({ left: -offsetX / csx, top: -offsetY / csy, scaleX: 1 / csx, scaleY: 1 / csy });
|
|
7347
|
+
imgClip.dirty = true;
|
|
7348
|
+
}
|
|
7268
7349
|
g.dirty = true;
|
|
7269
7350
|
img.dirty = true;
|
|
7270
7351
|
if (g.clipPath) {
|
|
@@ -7615,6 +7696,51 @@ function installCanvaMaskControls(g) {
|
|
|
7615
7696
|
g.set(controlStyle);
|
|
7616
7697
|
g.setCoords();
|
|
7617
7698
|
}
|
|
7699
|
+
function ensureRingShapeClass(g, ct, key, wantCircle) {
|
|
7700
|
+
const cur = ct[key];
|
|
7701
|
+
if (!cur) return void 0;
|
|
7702
|
+
const isEllipse = cur instanceof fabric.Ellipse;
|
|
7703
|
+
if (isEllipse === wantCircle) return cur;
|
|
7704
|
+
const common = {
|
|
7705
|
+
left: 0,
|
|
7706
|
+
top: 0,
|
|
7707
|
+
originX: "center",
|
|
7708
|
+
originY: "center",
|
|
7709
|
+
fill: "transparent",
|
|
7710
|
+
stroke: cur.stroke,
|
|
7711
|
+
strokeWidth: cur.strokeWidth,
|
|
7712
|
+
selectable: false,
|
|
7713
|
+
evented: false
|
|
7714
|
+
};
|
|
7715
|
+
const next = wantCircle ? new fabric.Ellipse({ ...common, rx: 1, ry: 1, objectCaching: false }) : new fabric.Rect({ ...common, width: 1, height: 1, objectCaching: false });
|
|
7716
|
+
const objs = g._objects;
|
|
7717
|
+
const idx = objs ? objs.indexOf(cur) : -1;
|
|
7718
|
+
if (objs && idx >= 0) objs.splice(idx, 1, next);
|
|
7719
|
+
else return cur;
|
|
7720
|
+
next.group = cur.group ?? g;
|
|
7721
|
+
next.canvas = cur.canvas ?? g.canvas;
|
|
7722
|
+
cur.group = void 0;
|
|
7723
|
+
next.setCoords();
|
|
7724
|
+
ct[key] = next;
|
|
7725
|
+
g.dirty = true;
|
|
7726
|
+
return next;
|
|
7727
|
+
}
|
|
7728
|
+
function computeOutlineGeometry(opts) {
|
|
7729
|
+
const { frameW, frameH, bw, pad, rx, outward } = opts;
|
|
7730
|
+
if (outward) {
|
|
7731
|
+
const grow = (r, by) => r > 0 ? r + by : 0;
|
|
7732
|
+
return {
|
|
7733
|
+
// Ring centre-line is pad + bw/2 past the frame → inner edge exactly `pad` out.
|
|
7734
|
+
border: { width: frameW + 2 * pad + bw, height: frameH + 2 * pad + bw, rx: grow(rx, pad + bw / 2) },
|
|
7735
|
+
// The gap band is transparent; it exists only to keep the child list stable.
|
|
7736
|
+
mat: { width: frameW + pad, height: frameH + pad, rx: grow(rx, pad / 2) }
|
|
7737
|
+
};
|
|
7738
|
+
}
|
|
7739
|
+
return {
|
|
7740
|
+
border: { width: frameW - bw, height: frameH - bw, rx },
|
|
7741
|
+
mat: { width: frameW - 2 * bw - pad, height: frameH - 2 * bw - pad, rx: Math.max(0, rx - bw) }
|
|
7742
|
+
};
|
|
7743
|
+
}
|
|
7618
7744
|
async function createMaskedImageElement({
|
|
7619
7745
|
url,
|
|
7620
7746
|
image,
|
|
@@ -7643,7 +7769,8 @@ async function createMaskedImageElement({
|
|
|
7643
7769
|
containScale = 1,
|
|
7644
7770
|
shadow = null,
|
|
7645
7771
|
borderPadding = 0,
|
|
7646
|
-
borderPaddingColor = "
|
|
7772
|
+
borderPaddingColor = "transparent",
|
|
7773
|
+
borderPosition = "outside"
|
|
7647
7774
|
}) {
|
|
7648
7775
|
const img = image || (url ? await fabric.FabricImage.fromURL(getProxiedImageUrl(url), { crossOrigin: "anonymous" }) : null);
|
|
7649
7776
|
if (!img) {
|
|
@@ -7668,36 +7795,47 @@ async function createMaskedImageElement({
|
|
|
7668
7795
|
});
|
|
7669
7796
|
const bw = strokeWidth || 0;
|
|
7670
7797
|
const pad = Math.max(0, borderPadding || 0);
|
|
7798
|
+
const outward = borderPosition === "outside";
|
|
7799
|
+
const geo = computeOutlineGeometry({ frameW, frameH, bw, pad, rx, outward });
|
|
7800
|
+
const matStroke = outward ? borderPaddingColor || "transparent" : borderPaddingColor;
|
|
7801
|
+
const matW = geo.mat.width;
|
|
7802
|
+
const matH = geo.mat.height;
|
|
7803
|
+
const matRx = geo.mat.rx;
|
|
7671
7804
|
const mat = shape === "circle" ? new fabric.Ellipse({
|
|
7672
|
-
rx:
|
|
7673
|
-
ry:
|
|
7805
|
+
rx: matW / 2,
|
|
7806
|
+
ry: matH / 2,
|
|
7674
7807
|
left: 0,
|
|
7675
7808
|
top: 0,
|
|
7676
7809
|
originX: "center",
|
|
7677
7810
|
originY: "center",
|
|
7678
7811
|
fill: "transparent",
|
|
7679
|
-
stroke:
|
|
7812
|
+
stroke: matStroke,
|
|
7680
7813
|
strokeWidth: pad,
|
|
7681
7814
|
selectable: false,
|
|
7682
|
-
evented: false
|
|
7815
|
+
evented: false,
|
|
7816
|
+
objectCaching: false
|
|
7683
7817
|
}) : new fabric.Rect({
|
|
7684
|
-
width:
|
|
7685
|
-
height:
|
|
7686
|
-
rx:
|
|
7687
|
-
ry:
|
|
7818
|
+
width: matW,
|
|
7819
|
+
height: matH,
|
|
7820
|
+
rx: matRx,
|
|
7821
|
+
ry: matRx,
|
|
7688
7822
|
left: 0,
|
|
7689
7823
|
top: 0,
|
|
7690
7824
|
originX: "center",
|
|
7691
7825
|
originY: "center",
|
|
7692
7826
|
fill: "transparent",
|
|
7693
|
-
stroke:
|
|
7827
|
+
stroke: matStroke,
|
|
7694
7828
|
strokeWidth: pad,
|
|
7695
7829
|
selectable: false,
|
|
7696
|
-
evented: false
|
|
7830
|
+
evented: false,
|
|
7831
|
+
objectCaching: false
|
|
7697
7832
|
});
|
|
7833
|
+
const bordW = geo.border.width;
|
|
7834
|
+
const bordH = geo.border.height;
|
|
7835
|
+
const bordRx = geo.border.rx;
|
|
7698
7836
|
const border = shape === "circle" ? new fabric.Ellipse({
|
|
7699
|
-
rx:
|
|
7700
|
-
ry:
|
|
7837
|
+
rx: bordW / 2,
|
|
7838
|
+
ry: bordH / 2,
|
|
7701
7839
|
left: 0,
|
|
7702
7840
|
top: 0,
|
|
7703
7841
|
originX: "center",
|
|
@@ -7706,12 +7844,13 @@ async function createMaskedImageElement({
|
|
|
7706
7844
|
stroke: stroke || "transparent",
|
|
7707
7845
|
strokeWidth: bw,
|
|
7708
7846
|
selectable: false,
|
|
7709
|
-
evented: false
|
|
7847
|
+
evented: false,
|
|
7848
|
+
objectCaching: false
|
|
7710
7849
|
}) : new fabric.Rect({
|
|
7711
|
-
width:
|
|
7712
|
-
height:
|
|
7713
|
-
rx,
|
|
7714
|
-
ry:
|
|
7850
|
+
width: bordW,
|
|
7851
|
+
height: bordH,
|
|
7852
|
+
rx: bordRx,
|
|
7853
|
+
ry: bordRx,
|
|
7715
7854
|
left: 0,
|
|
7716
7855
|
top: 0,
|
|
7717
7856
|
originX: "center",
|
|
@@ -7720,7 +7859,8 @@ async function createMaskedImageElement({
|
|
|
7720
7859
|
stroke: stroke || "transparent",
|
|
7721
7860
|
strokeWidth: bw,
|
|
7722
7861
|
selectable: false,
|
|
7723
|
-
evented: false
|
|
7862
|
+
evented: false,
|
|
7863
|
+
objectCaching: false
|
|
7724
7864
|
});
|
|
7725
7865
|
img.set({
|
|
7726
7866
|
left: 0,
|
|
@@ -7814,7 +7954,9 @@ async function createMaskedImageElement({
|
|
|
7814
7954
|
_border: border,
|
|
7815
7955
|
_mat: mat,
|
|
7816
7956
|
borderPadding: pad,
|
|
7817
|
-
borderPaddingColor
|
|
7957
|
+
borderPaddingColor,
|
|
7958
|
+
// Read back by refreshMaskedImage so it recomputes with the same geometry.
|
|
7959
|
+
borderPosition
|
|
7818
7960
|
};
|
|
7819
7961
|
g._ct = g._ct || {};
|
|
7820
7962
|
g._ct.isCropGroup = true;
|
|
@@ -7848,7 +7990,12 @@ async function createMaskedImageElement({
|
|
|
7848
7990
|
});
|
|
7849
7991
|
clip.absolutePositioned = false;
|
|
7850
7992
|
clip.excludeFromExport = true;
|
|
7851
|
-
|
|
7993
|
+
if (outward) {
|
|
7994
|
+
img.clipPath = clip;
|
|
7995
|
+
g.clipPath = void 0;
|
|
7996
|
+
} else {
|
|
7997
|
+
g.clipPath = clip;
|
|
7998
|
+
}
|
|
7852
7999
|
g.set({
|
|
7853
8000
|
selectable: true,
|
|
7854
8001
|
evented: true,
|
|
@@ -23938,11 +24085,33 @@ const PageCanvas = forwardRef(
|
|
|
23938
24085
|
const wantBW = Math.max(0, Number(element.imageBorderWidth) || 0);
|
|
23939
24086
|
const wantBC = element.imageBorderColor ?? "#FFFFFF";
|
|
23940
24087
|
const wantPad = Math.max(0, Number(element.imageBorderPadding) || 0);
|
|
23941
|
-
const wantPC = element.imageBorderPaddingColor ?? "
|
|
24088
|
+
const wantPC = element.imageBorderPaddingColor ?? "transparent";
|
|
24089
|
+
const wantPos = element.imageBorderPosition ?? "outside";
|
|
23942
24090
|
if (ct._border) ct._border.set({ stroke: wantBW > 0 ? wantBC : "transparent", strokeWidth: wantBW, dirty: true });
|
|
23943
24091
|
if (ct._mat) ct._mat.set({ stroke: wantPC, strokeWidth: wantPad, dirty: true });
|
|
23944
24092
|
ct.borderPadding = wantPad;
|
|
23945
24093
|
ct.borderPaddingColor = wantPC;
|
|
24094
|
+
ct.borderPosition = wantPos;
|
|
24095
|
+
{
|
|
24096
|
+
const gMinDim = Math.min(ct.frameW, ct.frameH);
|
|
24097
|
+
const rxRaw = ct.rx || 0;
|
|
24098
|
+
const gRx = Math.max(0, Math.min(rxRaw > 0.5 ? rxRaw : rxRaw * gMinDim, ct.frameW / 2, ct.frameH / 2));
|
|
24099
|
+
const gGeo = computeOutlineGeometry({
|
|
24100
|
+
frameW: ct.frameW,
|
|
24101
|
+
frameH: ct.frameH,
|
|
24102
|
+
bw: wantBW,
|
|
24103
|
+
pad: wantPad,
|
|
24104
|
+
rx: gRx,
|
|
24105
|
+
outward: wantPos === "outside"
|
|
24106
|
+
});
|
|
24107
|
+
const isCircle = (ct.shape || "rect") === "circle";
|
|
24108
|
+
if (ct._border) {
|
|
24109
|
+
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 });
|
|
24110
|
+
}
|
|
24111
|
+
if (ct._mat) {
|
|
24112
|
+
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 });
|
|
24113
|
+
}
|
|
24114
|
+
}
|
|
23946
24115
|
const sBlur = Math.max(0, Number(element.imageShadowBlur) || 0);
|
|
23947
24116
|
const sColor = element.imageShadowColor;
|
|
23948
24117
|
if (sBlur > 0 || sColor) {
|
|
@@ -26103,7 +26272,9 @@ const PageCanvas = forwardRef(
|
|
|
26103
26272
|
strokeWidth: element.imageBorderWidth ?? 0,
|
|
26104
26273
|
// Gap between the image and the outline (the "matted photo" look).
|
|
26105
26274
|
borderPadding: element.imageBorderPadding ?? 0,
|
|
26106
|
-
|
|
26275
|
+
// Gap is empty space by default, not a white mat.
|
|
26276
|
+
borderPaddingColor: element.imageBorderPaddingColor ?? "transparent",
|
|
26277
|
+
borderPosition: element.imageBorderPosition ?? "outside",
|
|
26107
26278
|
// Optional image drop shadow (element property).
|
|
26108
26279
|
shadow: (element.imageShadowBlur ?? 0) > 0 || element.imageShadowColor ? {
|
|
26109
26280
|
color: element.imageShadowColor ?? "rgba(0,0,0,0.25)",
|
|
@@ -28865,7 +29036,9 @@ function expandBoundTables(pages, formValues) {
|
|
|
28865
29036
|
const t = node;
|
|
28866
29037
|
if (t.type === "table" && ((_a2 = t.tableData) == null ? void 0 : _a2.repeat)) {
|
|
28867
29038
|
const entries = tableEntriesFor(t.tableData.repeat.from, formValues);
|
|
28868
|
-
|
|
29039
|
+
if (entries.length > 0) {
|
|
29040
|
+
t.tableData = expandTableRepeat(t.tableData, entries);
|
|
29041
|
+
}
|
|
28869
29042
|
for (const row of t.tableData.cells) {
|
|
28870
29043
|
for (const cell of row) {
|
|
28871
29044
|
if (!cell.field) continue;
|
|
@@ -30020,7 +30193,12 @@ function pagesHaveConstantTokens(pages) {
|
|
|
30020
30193
|
return pages.some((p) => walk(p.children));
|
|
30021
30194
|
}
|
|
30022
30195
|
function substituteConstantTokens(pages, constants) {
|
|
30023
|
-
const sub = (s) => s.replace(/\{\{\s*\$([a-zA-Z0-9_]+)\s*\}\}/g, (m, name) =>
|
|
30196
|
+
const sub = (s) => s.replace(/\{\{\s*\$([a-zA-Z0-9_]+)\s*\}\}/g, (m, name) => (
|
|
30197
|
+
// Unresolved tokens are ERASED rather than left as literal braces: on a
|
|
30198
|
+
// money cell a missing symbol still reads as a number, whereas
|
|
30199
|
+
// "{{$currency}}9,500.00" is visibly broken output.
|
|
30200
|
+
Object.prototype.hasOwnProperty.call(constants, name) ? String(constants[name]) : ""
|
|
30201
|
+
));
|
|
30024
30202
|
const walk = (nodes) => {
|
|
30025
30203
|
for (const n of nodes ?? []) {
|
|
30026
30204
|
if (n.type === "text") {
|
|
@@ -30051,10 +30229,9 @@ function applyContentBoundsPagination(config) {
|
|
|
30051
30229
|
}
|
|
30052
30230
|
let mutated = continuationMasters.length > 0;
|
|
30053
30231
|
const constants = config.constants;
|
|
30054
|
-
|
|
30055
|
-
if (hasConstants && pagesHaveConstantTokens(pages)) {
|
|
30232
|
+
if (pagesHaveConstantTokens(pages)) {
|
|
30056
30233
|
pages = pages.map((p) => JSON.parse(JSON.stringify(p)));
|
|
30057
|
-
substituteConstantTokens(pages, constants);
|
|
30234
|
+
substituteConstantTokens(pages, constants && typeof constants === "object" ? constants : {});
|
|
30058
30235
|
mutated = true;
|
|
30059
30236
|
}
|
|
30060
30237
|
let resultPages = [];
|
|
@@ -32224,8 +32401,9 @@ async function resolveTemplateData(options) {
|
|
|
32224
32401
|
void 0,
|
|
32225
32402
|
repeatablePagesInput.length > 0 ? repeatablePagesInput : void 0
|
|
32226
32403
|
);
|
|
32404
|
+
const paginated = applyContentBoundsPagination(resolvedConfig);
|
|
32227
32405
|
return {
|
|
32228
|
-
config: applyThemeIfNeeded(
|
|
32406
|
+
config: applyThemeIfNeeded(paginated),
|
|
32229
32407
|
templateName: template.name || "Untitled",
|
|
32230
32408
|
templateId,
|
|
32231
32409
|
price: template.price ?? 0
|
|
@@ -33866,6 +34044,43 @@ function stampPixldocsImageIdOnSvg(svg, id) {
|
|
|
33866
34044
|
const attr = ` data-pixldocs-image-id="${escapeSvgDataAttr(id)}"`;
|
|
33867
34045
|
return svg.replace(/<image\b/i, `<image${attr}`);
|
|
33868
34046
|
}
|
|
34047
|
+
function colorHasAlpha(color) {
|
|
34048
|
+
if (typeof color !== "string") return false;
|
|
34049
|
+
const c = color.trim().toLowerCase();
|
|
34050
|
+
if (c === "transparent") return true;
|
|
34051
|
+
const rgba = c.match(/^rgba?\(([^)]+)\)$/);
|
|
34052
|
+
if (rgba) {
|
|
34053
|
+
const parts = rgba[1].split(",").map((x) => x.trim());
|
|
34054
|
+
return parts.length > 3 && Number(parts[3]) < 1;
|
|
34055
|
+
}
|
|
34056
|
+
if (/^#[0-9a-f]{8}$/.test(c)) return parseInt(c.slice(7, 9), 16) < 255;
|
|
34057
|
+
if (/^#[0-9a-f]{4}$/.test(c)) return parseInt(c[4] + c[4], 16) < 255;
|
|
34058
|
+
return false;
|
|
34059
|
+
}
|
|
34060
|
+
function paintIsAlphaGradient(paint) {
|
|
34061
|
+
const stops = paint == null ? void 0 : paint.colorStops;
|
|
34062
|
+
if (!Array.isArray(stops) || !stops.length) return false;
|
|
34063
|
+
return stops.some((st) => colorHasAlpha(st == null ? void 0 : st.color) || typeof (st == null ? void 0 : st.opacity) === "number" && st.opacity < 1);
|
|
34064
|
+
}
|
|
34065
|
+
function objectNeedsAlphaGradientRaster(obj) {
|
|
34066
|
+
if (!obj) return false;
|
|
34067
|
+
return paintIsAlphaGradient(obj.fill) || paintIsAlphaGradient(obj.stroke);
|
|
34068
|
+
}
|
|
34069
|
+
function rasterizeObjectToSvgImage(obj, multiplier) {
|
|
34070
|
+
try {
|
|
34071
|
+
if (typeof obj.toDataURL !== "function") return null;
|
|
34072
|
+
const rect = obj.getBoundingRect();
|
|
34073
|
+
if (!rect || !(rect.width > 0) || !(rect.height > 0)) return null;
|
|
34074
|
+
const url = obj.toDataURL({ multiplier, enableRetinaScaling: false });
|
|
34075
|
+
if (typeof url !== "string" || !url.startsWith("data:image")) return null;
|
|
34076
|
+
const n = (v) => Number(v.toFixed(4));
|
|
34077
|
+
return `<image x="${n(rect.left)}" y="${n(rect.top)}" width="${n(rect.width)}" height="${n(rect.height)}" preserveAspectRatio="none" xlink:href="${url}"></image>`;
|
|
34078
|
+
} catch (e) {
|
|
34079
|
+
console.warn("[canvas-svg-capture][alphaGradient] raster failed:", e);
|
|
34080
|
+
return null;
|
|
34081
|
+
}
|
|
34082
|
+
}
|
|
34083
|
+
const ALPHA_GRADIENT_RASTER_MULTIPLIER = 3;
|
|
33869
34084
|
function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight) {
|
|
33870
34085
|
const prevVPT = fabricInstance.viewportTransform ? [...fabricInstance.viewportTransform] : void 0;
|
|
33871
34086
|
const prevSvgVPT = fabricInstance.svgViewportTransformation;
|
|
@@ -33887,9 +34102,14 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
33887
34102
|
const visit = (obj) => {
|
|
33888
34103
|
if (!obj) return;
|
|
33889
34104
|
const imageId = typeof obj.__docuforgeId === "string" && hasRenderableRasterCandidate(obj) ? obj.__docuforgeId : "";
|
|
33890
|
-
|
|
34105
|
+
const alphaGradient = objectNeedsAlphaGradientRaster(obj);
|
|
34106
|
+
if ((isTextboxLike(obj) || imageId || alphaGradient) && typeof obj.toSVG === "function") {
|
|
33891
34107
|
const originalToSVG = obj.toSVG.bind(obj);
|
|
33892
34108
|
obj.toSVG = (reviver) => {
|
|
34109
|
+
if (alphaGradient) {
|
|
34110
|
+
const raster = rasterizeObjectToSvgImage(obj, ALPHA_GRADIENT_RASTER_MULTIPLIER);
|
|
34111
|
+
if (raster) return raster;
|
|
34112
|
+
}
|
|
33893
34113
|
let svg = originalToSVG(reviver);
|
|
33894
34114
|
if (isTextboxLike(obj)) svg = stampFabricLineMetricsOnTextSvg(svg, obj);
|
|
33895
34115
|
if (isTextboxLike(obj)) svg = warpTextboxSvgAlongPath(svg, obj);
|
|
@@ -33988,9 +34208,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
33988
34208
|
}
|
|
33989
34209
|
return svgString;
|
|
33990
34210
|
}
|
|
33991
|
-
const resolvedPackageVersion = "0.5.
|
|
34211
|
+
const resolvedPackageVersion = "0.5.496";
|
|
33992
34212
|
const PACKAGE_VERSION = resolvedPackageVersion;
|
|
33993
|
-
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.
|
|
34213
|
+
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.496";
|
|
33994
34214
|
const roundParityValue = (value) => {
|
|
33995
34215
|
if (typeof value !== "number") return value;
|
|
33996
34216
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -34804,7 +35024,7 @@ class PixldocsRenderer {
|
|
|
34804
35024
|
await this.waitForCanvasScene(container, cloned, i);
|
|
34805
35025
|
}
|
|
34806
35026
|
console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
|
|
34807
|
-
const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-
|
|
35027
|
+
const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-E3x8GBto.js");
|
|
34808
35028
|
const prepared = preparePagesForExport(
|
|
34809
35029
|
cloned.pages,
|
|
34810
35030
|
canvasWidth,
|
|
@@ -37124,7 +37344,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
37124
37344
|
if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
|
|
37125
37345
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
37126
37346
|
try {
|
|
37127
|
-
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-
|
|
37347
|
+
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-E3x8GBto.js");
|
|
37128
37348
|
try {
|
|
37129
37349
|
await logTextMeasurementDiagnostic(svgToDraw);
|
|
37130
37350
|
} catch {
|
|
@@ -37442,4 +37662,4 @@ export {
|
|
|
37442
37662
|
awaitFontsForConfig as y,
|
|
37443
37663
|
buildTeaserBlurFlatKeys as z
|
|
37444
37664
|
};
|
|
37445
|
-
//# sourceMappingURL=index-
|
|
37665
|
+
//# sourceMappingURL=index-CiSoT2Lk.js.map
|