@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
|
@@ -2257,6 +2257,40 @@ function adaptLayoutGrid(grid, mode) {
|
|
|
2257
2257
|
const cells = (grid.cells ?? []).map((c) => c && c.grid ? { ...c, grid: adaptLayoutGrid(c.grid, mode) } : c);
|
|
2258
2258
|
return { ...grid, dir: grid.dir === from ? to : grid.dir, cells };
|
|
2259
2259
|
}
|
|
2260
|
+
function isAspectLockedNode(node) {
|
|
2261
|
+
const e = node;
|
|
2262
|
+
if (!e) return false;
|
|
2263
|
+
if (e.lockAspect === true) return true;
|
|
2264
|
+
if (e.clipShape === "circle") return true;
|
|
2265
|
+
const kind = e.componentKind || e.smartType;
|
|
2266
|
+
return kind === "qrcode" || kind === "barcode";
|
|
2267
|
+
}
|
|
2268
|
+
function scaleNodeForReflow(node, sx, sy, fscale) {
|
|
2269
|
+
const n = node;
|
|
2270
|
+
const el = { ...n };
|
|
2271
|
+
const hasBox = typeof n.width === "number" && typeof n.height === "number";
|
|
2272
|
+
const f = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
2273
|
+
if (hasBox && isAspectLockedNode(n) && sx !== sy) {
|
|
2274
|
+
const s = Math.min(sx, sy);
|
|
2275
|
+
const cx = (f(n.left) + n.width / 2) * sx;
|
|
2276
|
+
const cy = (f(n.top) + n.height / 2) * sy;
|
|
2277
|
+
el.width = n.width * s;
|
|
2278
|
+
el.height = n.height * s;
|
|
2279
|
+
el.left = cx - el.width / 2;
|
|
2280
|
+
el.top = cy - el.height / 2;
|
|
2281
|
+
} else {
|
|
2282
|
+
if (typeof el.left === "number") el.left = el.left * sx;
|
|
2283
|
+
if (typeof el.top === "number") el.top = el.top * sy;
|
|
2284
|
+
if (typeof el.width === "number") el.width = el.width * sx;
|
|
2285
|
+
if (typeof el.height === "number") el.height = el.height * sy;
|
|
2286
|
+
}
|
|
2287
|
+
if (typeof el.fontSize === "number") el.fontSize = Math.max(4, el.fontSize * fscale);
|
|
2288
|
+
if (typeof el.minBoxHeight === "number") el.minBoxHeight = el.minBoxHeight * sy;
|
|
2289
|
+
if (Array.isArray(el.children)) {
|
|
2290
|
+
el.children = el.children.map((c) => scaleNodeForReflow(c, sx, sy, fscale));
|
|
2291
|
+
}
|
|
2292
|
+
return el;
|
|
2293
|
+
}
|
|
2260
2294
|
function computeGridHandles(grid, box, gridPath = []) {
|
|
2261
2295
|
const out = [];
|
|
2262
2296
|
const n = grid.cells.length;
|
|
@@ -2659,16 +2693,7 @@ const reflowPagesFromBase = (base, W, H) => {
|
|
|
2659
2693
|
const fscale = Math.sqrt(Math.max(0.01, sx * sy));
|
|
2660
2694
|
const adapt = layoutAdaptationFor(base.width, base.height, W, H);
|
|
2661
2695
|
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
|
-
};
|
|
2696
|
+
const scaleNode = (node) => scaleNodeForReflow(node, sx, sy, fscale);
|
|
2672
2697
|
return base.pages.map((p) => {
|
|
2673
2698
|
const pg = p;
|
|
2674
2699
|
const page = {
|
|
@@ -3257,6 +3282,13 @@ const useEditorStore = zustand.create((set, get) => ({
|
|
|
3257
3282
|
return { canvas: nextCanvas, ...committed };
|
|
3258
3283
|
});
|
|
3259
3284
|
},
|
|
3285
|
+
getCanvasForSave: () => {
|
|
3286
|
+
const { canvas } = get();
|
|
3287
|
+
const base = sizeBaseSnapshot;
|
|
3288
|
+
if (!base) return canvas;
|
|
3289
|
+
if (canvas.width === base.width && canvas.height === base.height) return canvas;
|
|
3290
|
+
return { ...canvas, width: base.width, height: base.height, pages: base.pages };
|
|
3291
|
+
},
|
|
3260
3292
|
addSizeVariant: (variant) => set((state) => {
|
|
3261
3293
|
const sizes = state.canvas.sizes ?? [];
|
|
3262
3294
|
if (sizes.some((s) => s.id === variant.id)) return {};
|
|
@@ -6510,8 +6542,14 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
|
|
|
6510
6542
|
shape,
|
|
6511
6543
|
rx: rxRatio,
|
|
6512
6544
|
// Pass ratio, not pixel value
|
|
6513
|
-
|
|
6514
|
-
|
|
6545
|
+
// Image outline is an ELEMENT property (imageBorder*), not the generic
|
|
6546
|
+
// shape stroke — this builder forwarded only stroke/strokeWidth, so
|
|
6547
|
+
// outline/gap never reached it.
|
|
6548
|
+
stroke: (element.imageBorderWidth ?? 0) > 0 ? element.imageBorderColor ?? "#FFFFFF" : element.stroke,
|
|
6549
|
+
strokeWidth: (element.imageBorderWidth ?? 0) > 0 ? element.imageBorderWidth : element.strokeWidth,
|
|
6550
|
+
borderPadding: element.imageBorderPadding ?? 0,
|
|
6551
|
+
borderPaddingColor: element.imageBorderPaddingColor ?? "transparent",
|
|
6552
|
+
borderPosition: element.imageBorderPosition ?? "outside",
|
|
6515
6553
|
panX,
|
|
6516
6554
|
panY,
|
|
6517
6555
|
zoom
|
|
@@ -7062,10 +7100,10 @@ function finalizeCropGroupCoords(g) {
|
|
|
7062
7100
|
g.setCoords();
|
|
7063
7101
|
}
|
|
7064
7102
|
function updateCoverLayout(g) {
|
|
7065
|
-
var _a2;
|
|
7103
|
+
var _a2, _b2;
|
|
7066
7104
|
const ct = g.__cropData;
|
|
7067
7105
|
if (!ct) return;
|
|
7068
|
-
const { frameW, frameH, shape, rx: rxRatio, _img: img
|
|
7106
|
+
const { frameW, frameH, shape, rx: rxRatio, _img: img } = ct;
|
|
7069
7107
|
const minDim = Math.min(frameW, frameH);
|
|
7070
7108
|
let rx = rxRatio > 0.5 ? rxRatio : rxRatio * minDim;
|
|
7071
7109
|
rx = Math.max(0, Math.min(rx, frameW / 2, frameH / 2));
|
|
@@ -7198,25 +7236,31 @@ function updateCoverLayout(g) {
|
|
|
7198
7236
|
g.clipPath.excludeFromExport = true;
|
|
7199
7237
|
}
|
|
7200
7238
|
}
|
|
7239
|
+
const wantCircle = shape === "circle";
|
|
7240
|
+
const border = ensureRingShapeClass(g, ct, "_border", wantCircle);
|
|
7241
|
+
const mat = ensureRingShapeClass(g, ct, "_mat", wantCircle);
|
|
7201
7242
|
const bw = border ? Number(border.strokeWidth) || 0 : 0;
|
|
7202
|
-
const mat = ct._mat;
|
|
7203
7243
|
const pad = Math.max(0, Number(ct.borderPadding) || 0);
|
|
7244
|
+
const outward = (ct.borderPosition ?? "outside") === "outside";
|
|
7204
7245
|
const borderMinDim = Math.min(frameW, frameH);
|
|
7205
7246
|
let borderRx = rxRatio > 0.5 ? rxRatio : rxRatio * borderMinDim;
|
|
7206
7247
|
borderRx = Math.max(0, Math.min(borderRx, frameW / 2, frameH / 2));
|
|
7248
|
+
const geo = computeOutlineGeometry({ frameW, frameH, bw, pad, rx: borderRx, outward });
|
|
7207
7249
|
if (border) {
|
|
7208
7250
|
if (shape === "circle") {
|
|
7209
|
-
border.set({ rx:
|
|
7251
|
+
border.set({ rx: geo.border.width / 2, ry: geo.border.height / 2 });
|
|
7210
7252
|
} else {
|
|
7211
|
-
border.set({ width:
|
|
7253
|
+
border.set({ width: geo.border.width, height: geo.border.height, rx: geo.border.rx, ry: geo.border.rx });
|
|
7212
7254
|
}
|
|
7255
|
+
border.dirty = true;
|
|
7213
7256
|
}
|
|
7214
7257
|
if (mat) {
|
|
7215
7258
|
if (shape === "circle") {
|
|
7216
|
-
mat.set({ rx:
|
|
7259
|
+
mat.set({ rx: geo.mat.width / 2, ry: geo.mat.height / 2 });
|
|
7217
7260
|
} else {
|
|
7218
|
-
mat.set({ width:
|
|
7261
|
+
mat.set({ width: geo.mat.width, height: geo.mat.height, rx: geo.mat.rx, ry: geo.mat.rx });
|
|
7219
7262
|
}
|
|
7263
|
+
mat.dirty = true;
|
|
7220
7264
|
}
|
|
7221
7265
|
if (!img) {
|
|
7222
7266
|
const placeholderFrame = ct._placeholderFrame ?? ((_a2 = g._objects) == null ? void 0 : _a2.find((obj) => obj.__isPlaceholderFrame));
|
|
@@ -7245,8 +7289,9 @@ function updateCoverLayout(g) {
|
|
|
7245
7289
|
img._ct.panX = img.__panX ?? 0.5;
|
|
7246
7290
|
img._ct.panY = img.__panY ?? 0.5;
|
|
7247
7291
|
}
|
|
7248
|
-
const
|
|
7249
|
-
const
|
|
7292
|
+
const srcEl = img._originalElement ?? ((_b2 = img.getElement) == null ? void 0 : _b2.call(img));
|
|
7293
|
+
const iw = Number(srcEl == null ? void 0 : srcEl.naturalWidth) || Number(srcEl == null ? void 0 : srcEl.width) || img.width || 1;
|
|
7294
|
+
const ih = Number(srcEl == null ? void 0 : srcEl.naturalHeight) || Number(srcEl == null ? void 0 : srcEl.height) || img.height || 1;
|
|
7250
7295
|
const fitContain = ct.fit === "contain";
|
|
7251
7296
|
const baseScale = fitContain ? Math.min(frameW / iw, frameH / ih) : Math.max(frameW / iw, frameH / ih);
|
|
7252
7297
|
const zoom = fitContain ? Math.max(1, Math.min(3, ct.containScale ?? 1)) : Math.max(1, img._ct.zoom ?? 1);
|
|
@@ -7283,6 +7328,42 @@ function updateCoverLayout(g) {
|
|
|
7283
7328
|
offsetY = overflowY > 0 ? -overflowY * (panY - 0.5) : 0;
|
|
7284
7329
|
}
|
|
7285
7330
|
img.set({ left: offsetX, top: offsetY });
|
|
7331
|
+
const wantsOutline = bw > 0 || pad > 0;
|
|
7332
|
+
const shapedMask = shape === "circle" || shape === "roundRect";
|
|
7333
|
+
if (wantsOutline && shapedMask) {
|
|
7334
|
+
if (g.clipPath) {
|
|
7335
|
+
img.clipPath = g.clipPath;
|
|
7336
|
+
g.clipPath = void 0;
|
|
7337
|
+
}
|
|
7338
|
+
if (img.cropX || img.cropY || img.width !== iw) {
|
|
7339
|
+
img.set({ width: iw, height: ih, cropX: 0, cropY: 0 });
|
|
7340
|
+
}
|
|
7341
|
+
} else if (wantsOutline && !fitContain) {
|
|
7342
|
+
const regionW = Math.min(iw, frameW / finalScale);
|
|
7343
|
+
const regionH = Math.min(ih, frameH / finalScale);
|
|
7344
|
+
img.set({
|
|
7345
|
+
width: regionW,
|
|
7346
|
+
height: regionH,
|
|
7347
|
+
cropX: (iw - regionW) * panX,
|
|
7348
|
+
cropY: (ih - regionH) * panY,
|
|
7349
|
+
left: 0,
|
|
7350
|
+
top: 0
|
|
7351
|
+
});
|
|
7352
|
+
img.clipPath = void 0;
|
|
7353
|
+
g.clipPath = void 0;
|
|
7354
|
+
} else {
|
|
7355
|
+
if (img.clipPath) img.clipPath = void 0;
|
|
7356
|
+
if (img.cropX || img.cropY || img.width !== iw) {
|
|
7357
|
+
img.set({ width: iw, height: ih, cropX: 0, cropY: 0 });
|
|
7358
|
+
}
|
|
7359
|
+
}
|
|
7360
|
+
const imgClip = img.clipPath;
|
|
7361
|
+
if (imgClip && typeof imgClip.set === "function") {
|
|
7362
|
+
const csx = img.scaleX || 1;
|
|
7363
|
+
const csy = img.scaleY || 1;
|
|
7364
|
+
imgClip.set({ left: -offsetX / csx, top: -offsetY / csy, scaleX: 1 / csx, scaleY: 1 / csy });
|
|
7365
|
+
imgClip.dirty = true;
|
|
7366
|
+
}
|
|
7286
7367
|
g.dirty = true;
|
|
7287
7368
|
img.dirty = true;
|
|
7288
7369
|
if (g.clipPath) {
|
|
@@ -7633,6 +7714,51 @@ function installCanvaMaskControls(g) {
|
|
|
7633
7714
|
g.set(controlStyle);
|
|
7634
7715
|
g.setCoords();
|
|
7635
7716
|
}
|
|
7717
|
+
function ensureRingShapeClass(g, ct, key, wantCircle) {
|
|
7718
|
+
const cur = ct[key];
|
|
7719
|
+
if (!cur) return void 0;
|
|
7720
|
+
const isEllipse = cur instanceof fabric__namespace.Ellipse;
|
|
7721
|
+
if (isEllipse === wantCircle) return cur;
|
|
7722
|
+
const common = {
|
|
7723
|
+
left: 0,
|
|
7724
|
+
top: 0,
|
|
7725
|
+
originX: "center",
|
|
7726
|
+
originY: "center",
|
|
7727
|
+
fill: "transparent",
|
|
7728
|
+
stroke: cur.stroke,
|
|
7729
|
+
strokeWidth: cur.strokeWidth,
|
|
7730
|
+
selectable: false,
|
|
7731
|
+
evented: false
|
|
7732
|
+
};
|
|
7733
|
+
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 });
|
|
7734
|
+
const objs = g._objects;
|
|
7735
|
+
const idx = objs ? objs.indexOf(cur) : -1;
|
|
7736
|
+
if (objs && idx >= 0) objs.splice(idx, 1, next);
|
|
7737
|
+
else return cur;
|
|
7738
|
+
next.group = cur.group ?? g;
|
|
7739
|
+
next.canvas = cur.canvas ?? g.canvas;
|
|
7740
|
+
cur.group = void 0;
|
|
7741
|
+
next.setCoords();
|
|
7742
|
+
ct[key] = next;
|
|
7743
|
+
g.dirty = true;
|
|
7744
|
+
return next;
|
|
7745
|
+
}
|
|
7746
|
+
function computeOutlineGeometry(opts) {
|
|
7747
|
+
const { frameW, frameH, bw, pad, rx, outward } = opts;
|
|
7748
|
+
if (outward) {
|
|
7749
|
+
const grow = (r, by) => r > 0 ? r + by : 0;
|
|
7750
|
+
return {
|
|
7751
|
+
// Ring centre-line is pad + bw/2 past the frame → inner edge exactly `pad` out.
|
|
7752
|
+
border: { width: frameW + 2 * pad + bw, height: frameH + 2 * pad + bw, rx: grow(rx, pad + bw / 2) },
|
|
7753
|
+
// The gap band is transparent; it exists only to keep the child list stable.
|
|
7754
|
+
mat: { width: frameW + pad, height: frameH + pad, rx: grow(rx, pad / 2) }
|
|
7755
|
+
};
|
|
7756
|
+
}
|
|
7757
|
+
return {
|
|
7758
|
+
border: { width: frameW - bw, height: frameH - bw, rx },
|
|
7759
|
+
mat: { width: frameW - 2 * bw - pad, height: frameH - 2 * bw - pad, rx: Math.max(0, rx - bw) }
|
|
7760
|
+
};
|
|
7761
|
+
}
|
|
7636
7762
|
async function createMaskedImageElement({
|
|
7637
7763
|
url,
|
|
7638
7764
|
image,
|
|
@@ -7661,7 +7787,8 @@ async function createMaskedImageElement({
|
|
|
7661
7787
|
containScale = 1,
|
|
7662
7788
|
shadow = null,
|
|
7663
7789
|
borderPadding = 0,
|
|
7664
|
-
borderPaddingColor = "
|
|
7790
|
+
borderPaddingColor = "transparent",
|
|
7791
|
+
borderPosition = "outside"
|
|
7665
7792
|
}) {
|
|
7666
7793
|
const img = image || (url ? await fabric__namespace.FabricImage.fromURL(getProxiedImageUrl(url), { crossOrigin: "anonymous" }) : null);
|
|
7667
7794
|
if (!img) {
|
|
@@ -7686,36 +7813,47 @@ async function createMaskedImageElement({
|
|
|
7686
7813
|
});
|
|
7687
7814
|
const bw = strokeWidth || 0;
|
|
7688
7815
|
const pad = Math.max(0, borderPadding || 0);
|
|
7816
|
+
const outward = borderPosition === "outside";
|
|
7817
|
+
const geo = computeOutlineGeometry({ frameW, frameH, bw, pad, rx, outward });
|
|
7818
|
+
const matStroke = outward ? borderPaddingColor || "transparent" : borderPaddingColor;
|
|
7819
|
+
const matW = geo.mat.width;
|
|
7820
|
+
const matH = geo.mat.height;
|
|
7821
|
+
const matRx = geo.mat.rx;
|
|
7689
7822
|
const mat = shape === "circle" ? new fabric__namespace.Ellipse({
|
|
7690
|
-
rx:
|
|
7691
|
-
ry:
|
|
7823
|
+
rx: matW / 2,
|
|
7824
|
+
ry: matH / 2,
|
|
7692
7825
|
left: 0,
|
|
7693
7826
|
top: 0,
|
|
7694
7827
|
originX: "center",
|
|
7695
7828
|
originY: "center",
|
|
7696
7829
|
fill: "transparent",
|
|
7697
|
-
stroke:
|
|
7830
|
+
stroke: matStroke,
|
|
7698
7831
|
strokeWidth: pad,
|
|
7699
7832
|
selectable: false,
|
|
7700
|
-
evented: false
|
|
7833
|
+
evented: false,
|
|
7834
|
+
objectCaching: false
|
|
7701
7835
|
}) : new fabric__namespace.Rect({
|
|
7702
|
-
width:
|
|
7703
|
-
height:
|
|
7704
|
-
rx:
|
|
7705
|
-
ry:
|
|
7836
|
+
width: matW,
|
|
7837
|
+
height: matH,
|
|
7838
|
+
rx: matRx,
|
|
7839
|
+
ry: matRx,
|
|
7706
7840
|
left: 0,
|
|
7707
7841
|
top: 0,
|
|
7708
7842
|
originX: "center",
|
|
7709
7843
|
originY: "center",
|
|
7710
7844
|
fill: "transparent",
|
|
7711
|
-
stroke:
|
|
7845
|
+
stroke: matStroke,
|
|
7712
7846
|
strokeWidth: pad,
|
|
7713
7847
|
selectable: false,
|
|
7714
|
-
evented: false
|
|
7848
|
+
evented: false,
|
|
7849
|
+
objectCaching: false
|
|
7715
7850
|
});
|
|
7851
|
+
const bordW = geo.border.width;
|
|
7852
|
+
const bordH = geo.border.height;
|
|
7853
|
+
const bordRx = geo.border.rx;
|
|
7716
7854
|
const border = shape === "circle" ? new fabric__namespace.Ellipse({
|
|
7717
|
-
rx:
|
|
7718
|
-
ry:
|
|
7855
|
+
rx: bordW / 2,
|
|
7856
|
+
ry: bordH / 2,
|
|
7719
7857
|
left: 0,
|
|
7720
7858
|
top: 0,
|
|
7721
7859
|
originX: "center",
|
|
@@ -7724,12 +7862,13 @@ async function createMaskedImageElement({
|
|
|
7724
7862
|
stroke: stroke || "transparent",
|
|
7725
7863
|
strokeWidth: bw,
|
|
7726
7864
|
selectable: false,
|
|
7727
|
-
evented: false
|
|
7865
|
+
evented: false,
|
|
7866
|
+
objectCaching: false
|
|
7728
7867
|
}) : new fabric__namespace.Rect({
|
|
7729
|
-
width:
|
|
7730
|
-
height:
|
|
7731
|
-
rx,
|
|
7732
|
-
ry:
|
|
7868
|
+
width: bordW,
|
|
7869
|
+
height: bordH,
|
|
7870
|
+
rx: bordRx,
|
|
7871
|
+
ry: bordRx,
|
|
7733
7872
|
left: 0,
|
|
7734
7873
|
top: 0,
|
|
7735
7874
|
originX: "center",
|
|
@@ -7738,7 +7877,8 @@ async function createMaskedImageElement({
|
|
|
7738
7877
|
stroke: stroke || "transparent",
|
|
7739
7878
|
strokeWidth: bw,
|
|
7740
7879
|
selectable: false,
|
|
7741
|
-
evented: false
|
|
7880
|
+
evented: false,
|
|
7881
|
+
objectCaching: false
|
|
7742
7882
|
});
|
|
7743
7883
|
img.set({
|
|
7744
7884
|
left: 0,
|
|
@@ -7832,7 +7972,9 @@ async function createMaskedImageElement({
|
|
|
7832
7972
|
_border: border,
|
|
7833
7973
|
_mat: mat,
|
|
7834
7974
|
borderPadding: pad,
|
|
7835
|
-
borderPaddingColor
|
|
7975
|
+
borderPaddingColor,
|
|
7976
|
+
// Read back by refreshMaskedImage so it recomputes with the same geometry.
|
|
7977
|
+
borderPosition
|
|
7836
7978
|
};
|
|
7837
7979
|
g._ct = g._ct || {};
|
|
7838
7980
|
g._ct.isCropGroup = true;
|
|
@@ -7866,7 +8008,12 @@ async function createMaskedImageElement({
|
|
|
7866
8008
|
});
|
|
7867
8009
|
clip.absolutePositioned = false;
|
|
7868
8010
|
clip.excludeFromExport = true;
|
|
7869
|
-
|
|
8011
|
+
if (outward) {
|
|
8012
|
+
img.clipPath = clip;
|
|
8013
|
+
g.clipPath = void 0;
|
|
8014
|
+
} else {
|
|
8015
|
+
g.clipPath = clip;
|
|
8016
|
+
}
|
|
7870
8017
|
g.set({
|
|
7871
8018
|
selectable: true,
|
|
7872
8019
|
evented: true,
|
|
@@ -23956,11 +24103,33 @@ const PageCanvas = react.forwardRef(
|
|
|
23956
24103
|
const wantBW = Math.max(0, Number(element.imageBorderWidth) || 0);
|
|
23957
24104
|
const wantBC = element.imageBorderColor ?? "#FFFFFF";
|
|
23958
24105
|
const wantPad = Math.max(0, Number(element.imageBorderPadding) || 0);
|
|
23959
|
-
const wantPC = element.imageBorderPaddingColor ?? "
|
|
24106
|
+
const wantPC = element.imageBorderPaddingColor ?? "transparent";
|
|
24107
|
+
const wantPos = element.imageBorderPosition ?? "outside";
|
|
23960
24108
|
if (ct._border) ct._border.set({ stroke: wantBW > 0 ? wantBC : "transparent", strokeWidth: wantBW, dirty: true });
|
|
23961
24109
|
if (ct._mat) ct._mat.set({ stroke: wantPC, strokeWidth: wantPad, dirty: true });
|
|
23962
24110
|
ct.borderPadding = wantPad;
|
|
23963
24111
|
ct.borderPaddingColor = wantPC;
|
|
24112
|
+
ct.borderPosition = wantPos;
|
|
24113
|
+
{
|
|
24114
|
+
const gMinDim = Math.min(ct.frameW, ct.frameH);
|
|
24115
|
+
const rxRaw = ct.rx || 0;
|
|
24116
|
+
const gRx = Math.max(0, Math.min(rxRaw > 0.5 ? rxRaw : rxRaw * gMinDim, ct.frameW / 2, ct.frameH / 2));
|
|
24117
|
+
const gGeo = computeOutlineGeometry({
|
|
24118
|
+
frameW: ct.frameW,
|
|
24119
|
+
frameH: ct.frameH,
|
|
24120
|
+
bw: wantBW,
|
|
24121
|
+
pad: wantPad,
|
|
24122
|
+
rx: gRx,
|
|
24123
|
+
outward: wantPos === "outside"
|
|
24124
|
+
});
|
|
24125
|
+
const isCircle = (ct.shape || "rect") === "circle";
|
|
24126
|
+
if (ct._border) {
|
|
24127
|
+
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 });
|
|
24128
|
+
}
|
|
24129
|
+
if (ct._mat) {
|
|
24130
|
+
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 });
|
|
24131
|
+
}
|
|
24132
|
+
}
|
|
23964
24133
|
const sBlur = Math.max(0, Number(element.imageShadowBlur) || 0);
|
|
23965
24134
|
const sColor = element.imageShadowColor;
|
|
23966
24135
|
if (sBlur > 0 || sColor) {
|
|
@@ -26121,7 +26290,9 @@ const PageCanvas = react.forwardRef(
|
|
|
26121
26290
|
strokeWidth: element.imageBorderWidth ?? 0,
|
|
26122
26291
|
// Gap between the image and the outline (the "matted photo" look).
|
|
26123
26292
|
borderPadding: element.imageBorderPadding ?? 0,
|
|
26124
|
-
|
|
26293
|
+
// Gap is empty space by default, not a white mat.
|
|
26294
|
+
borderPaddingColor: element.imageBorderPaddingColor ?? "transparent",
|
|
26295
|
+
borderPosition: element.imageBorderPosition ?? "outside",
|
|
26125
26296
|
// Optional image drop shadow (element property).
|
|
26126
26297
|
shadow: (element.imageShadowBlur ?? 0) > 0 || element.imageShadowColor ? {
|
|
26127
26298
|
color: element.imageShadowColor ?? "rgba(0,0,0,0.25)",
|
|
@@ -28883,7 +29054,9 @@ function expandBoundTables(pages, formValues) {
|
|
|
28883
29054
|
const t = node;
|
|
28884
29055
|
if (t.type === "table" && ((_a2 = t.tableData) == null ? void 0 : _a2.repeat)) {
|
|
28885
29056
|
const entries = tableEntriesFor(t.tableData.repeat.from, formValues);
|
|
28886
|
-
|
|
29057
|
+
if (entries.length > 0) {
|
|
29058
|
+
t.tableData = expandTableRepeat(t.tableData, entries);
|
|
29059
|
+
}
|
|
28887
29060
|
for (const row of t.tableData.cells) {
|
|
28888
29061
|
for (const cell of row) {
|
|
28889
29062
|
if (!cell.field) continue;
|
|
@@ -30038,7 +30211,12 @@ function pagesHaveConstantTokens(pages) {
|
|
|
30038
30211
|
return pages.some((p) => walk(p.children));
|
|
30039
30212
|
}
|
|
30040
30213
|
function substituteConstantTokens(pages, constants) {
|
|
30041
|
-
const sub = (s) => s.replace(/\{\{\s*\$([a-zA-Z0-9_]+)\s*\}\}/g, (m, name) =>
|
|
30214
|
+
const sub = (s) => s.replace(/\{\{\s*\$([a-zA-Z0-9_]+)\s*\}\}/g, (m, name) => (
|
|
30215
|
+
// Unresolved tokens are ERASED rather than left as literal braces: on a
|
|
30216
|
+
// money cell a missing symbol still reads as a number, whereas
|
|
30217
|
+
// "{{$currency}}9,500.00" is visibly broken output.
|
|
30218
|
+
Object.prototype.hasOwnProperty.call(constants, name) ? String(constants[name]) : ""
|
|
30219
|
+
));
|
|
30042
30220
|
const walk = (nodes) => {
|
|
30043
30221
|
for (const n of nodes ?? []) {
|
|
30044
30222
|
if (n.type === "text") {
|
|
@@ -30069,10 +30247,9 @@ function applyContentBoundsPagination(config) {
|
|
|
30069
30247
|
}
|
|
30070
30248
|
let mutated = continuationMasters.length > 0;
|
|
30071
30249
|
const constants = config.constants;
|
|
30072
|
-
|
|
30073
|
-
if (hasConstants && pagesHaveConstantTokens(pages)) {
|
|
30250
|
+
if (pagesHaveConstantTokens(pages)) {
|
|
30074
30251
|
pages = pages.map((p) => JSON.parse(JSON.stringify(p)));
|
|
30075
|
-
substituteConstantTokens(pages, constants);
|
|
30252
|
+
substituteConstantTokens(pages, constants && typeof constants === "object" ? constants : {});
|
|
30076
30253
|
mutated = true;
|
|
30077
30254
|
}
|
|
30078
30255
|
let resultPages = [];
|
|
@@ -32242,8 +32419,9 @@ async function resolveTemplateData(options) {
|
|
|
32242
32419
|
void 0,
|
|
32243
32420
|
repeatablePagesInput.length > 0 ? repeatablePagesInput : void 0
|
|
32244
32421
|
);
|
|
32422
|
+
const paginated = applyContentBoundsPagination(resolvedConfig);
|
|
32245
32423
|
return {
|
|
32246
|
-
config: applyThemeIfNeeded(
|
|
32424
|
+
config: applyThemeIfNeeded(paginated),
|
|
32247
32425
|
templateName: template.name || "Untitled",
|
|
32248
32426
|
templateId,
|
|
32249
32427
|
price: template.price ?? 0
|
|
@@ -33884,6 +34062,43 @@ function stampPixldocsImageIdOnSvg(svg, id) {
|
|
|
33884
34062
|
const attr = ` data-pixldocs-image-id="${escapeSvgDataAttr(id)}"`;
|
|
33885
34063
|
return svg.replace(/<image\b/i, `<image${attr}`);
|
|
33886
34064
|
}
|
|
34065
|
+
function colorHasAlpha(color) {
|
|
34066
|
+
if (typeof color !== "string") return false;
|
|
34067
|
+
const c = color.trim().toLowerCase();
|
|
34068
|
+
if (c === "transparent") return true;
|
|
34069
|
+
const rgba = c.match(/^rgba?\(([^)]+)\)$/);
|
|
34070
|
+
if (rgba) {
|
|
34071
|
+
const parts = rgba[1].split(",").map((x) => x.trim());
|
|
34072
|
+
return parts.length > 3 && Number(parts[3]) < 1;
|
|
34073
|
+
}
|
|
34074
|
+
if (/^#[0-9a-f]{8}$/.test(c)) return parseInt(c.slice(7, 9), 16) < 255;
|
|
34075
|
+
if (/^#[0-9a-f]{4}$/.test(c)) return parseInt(c[4] + c[4], 16) < 255;
|
|
34076
|
+
return false;
|
|
34077
|
+
}
|
|
34078
|
+
function paintIsAlphaGradient(paint) {
|
|
34079
|
+
const stops = paint == null ? void 0 : paint.colorStops;
|
|
34080
|
+
if (!Array.isArray(stops) || !stops.length) return false;
|
|
34081
|
+
return stops.some((st) => colorHasAlpha(st == null ? void 0 : st.color) || typeof (st == null ? void 0 : st.opacity) === "number" && st.opacity < 1);
|
|
34082
|
+
}
|
|
34083
|
+
function objectNeedsAlphaGradientRaster(obj) {
|
|
34084
|
+
if (!obj) return false;
|
|
34085
|
+
return paintIsAlphaGradient(obj.fill) || paintIsAlphaGradient(obj.stroke);
|
|
34086
|
+
}
|
|
34087
|
+
function rasterizeObjectToSvgImage(obj, multiplier) {
|
|
34088
|
+
try {
|
|
34089
|
+
if (typeof obj.toDataURL !== "function") return null;
|
|
34090
|
+
const rect = obj.getBoundingRect();
|
|
34091
|
+
if (!rect || !(rect.width > 0) || !(rect.height > 0)) return null;
|
|
34092
|
+
const url = obj.toDataURL({ multiplier, enableRetinaScaling: false });
|
|
34093
|
+
if (typeof url !== "string" || !url.startsWith("data:image")) return null;
|
|
34094
|
+
const n = (v) => Number(v.toFixed(4));
|
|
34095
|
+
return `<image x="${n(rect.left)}" y="${n(rect.top)}" width="${n(rect.width)}" height="${n(rect.height)}" preserveAspectRatio="none" xlink:href="${url}"></image>`;
|
|
34096
|
+
} catch (e) {
|
|
34097
|
+
console.warn("[canvas-svg-capture][alphaGradient] raster failed:", e);
|
|
34098
|
+
return null;
|
|
34099
|
+
}
|
|
34100
|
+
}
|
|
34101
|
+
const ALPHA_GRADIENT_RASTER_MULTIPLIER = 3;
|
|
33887
34102
|
function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight) {
|
|
33888
34103
|
const prevVPT = fabricInstance.viewportTransform ? [...fabricInstance.viewportTransform] : void 0;
|
|
33889
34104
|
const prevSvgVPT = fabricInstance.svgViewportTransformation;
|
|
@@ -33905,9 +34120,14 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
33905
34120
|
const visit = (obj) => {
|
|
33906
34121
|
if (!obj) return;
|
|
33907
34122
|
const imageId = typeof obj.__docuforgeId === "string" && hasRenderableRasterCandidate(obj) ? obj.__docuforgeId : "";
|
|
33908
|
-
|
|
34123
|
+
const alphaGradient = objectNeedsAlphaGradientRaster(obj);
|
|
34124
|
+
if ((isTextboxLike(obj) || imageId || alphaGradient) && typeof obj.toSVG === "function") {
|
|
33909
34125
|
const originalToSVG = obj.toSVG.bind(obj);
|
|
33910
34126
|
obj.toSVG = (reviver) => {
|
|
34127
|
+
if (alphaGradient) {
|
|
34128
|
+
const raster = rasterizeObjectToSvgImage(obj, ALPHA_GRADIENT_RASTER_MULTIPLIER);
|
|
34129
|
+
if (raster) return raster;
|
|
34130
|
+
}
|
|
33911
34131
|
let svg = originalToSVG(reviver);
|
|
33912
34132
|
if (isTextboxLike(obj)) svg = stampFabricLineMetricsOnTextSvg(svg, obj);
|
|
33913
34133
|
if (isTextboxLike(obj)) svg = warpTextboxSvgAlongPath(svg, obj);
|
|
@@ -34006,9 +34226,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
34006
34226
|
}
|
|
34007
34227
|
return svgString;
|
|
34008
34228
|
}
|
|
34009
|
-
const resolvedPackageVersion = "0.5.
|
|
34229
|
+
const resolvedPackageVersion = "0.5.496";
|
|
34010
34230
|
const PACKAGE_VERSION = resolvedPackageVersion;
|
|
34011
|
-
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.
|
|
34231
|
+
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.496";
|
|
34012
34232
|
const roundParityValue = (value) => {
|
|
34013
34233
|
if (typeof value !== "number") return value;
|
|
34014
34234
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -34822,7 +35042,7 @@ class PixldocsRenderer {
|
|
|
34822
35042
|
await this.waitForCanvasScene(container, cloned, i);
|
|
34823
35043
|
}
|
|
34824
35044
|
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-
|
|
35045
|
+
const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-B2KtFs76.cjs"));
|
|
34826
35046
|
const prepared = preparePagesForExport(
|
|
34827
35047
|
cloned.pages,
|
|
34828
35048
|
canvasWidth,
|
|
@@ -37142,7 +37362,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
37142
37362
|
if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
|
|
37143
37363
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
37144
37364
|
try {
|
|
37145
|
-
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-
|
|
37365
|
+
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-B2KtFs76.cjs"));
|
|
37146
37366
|
try {
|
|
37147
37367
|
await logTextMeasurementDiagnostic(svgToDraw);
|
|
37148
37368
|
} catch {
|
|
@@ -37457,4 +37677,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
|
|
|
37457
37677
|
exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
|
|
37458
37678
|
exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
|
|
37459
37679
|
exports.warmTemplateFromForm = warmTemplateFromForm;
|
|
37460
|
-
//# sourceMappingURL=index-
|
|
37680
|
+
//# sourceMappingURL=index-CZtvER5z.cjs.map
|