@pixldocs/canvas-renderer 0.5.496 → 0.5.498
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-CZtvER5z.cjs → index-CUZInOyk.cjs} +435 -74
- package/dist/index-CUZInOyk.cjs.map +1 -0
- package/dist/{index-CiSoT2Lk.js → index-lbU-Xs_t.js} +452 -91
- package/dist/index-lbU-Xs_t.js.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-B2KtFs76.cjs → vectorPdfExport-6Hi7Og4W.cjs} +4 -4
- package/dist/{vectorPdfExport-B2KtFs76.cjs.map → vectorPdfExport-6Hi7Og4W.cjs.map} +1 -1
- package/dist/{vectorPdfExport-E3x8GBto.js → vectorPdfExport-D8iQi9WT.js} +4 -4
- package/dist/{vectorPdfExport-E3x8GBto.js.map → vectorPdfExport-D8iQi9WT.js.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-CZtvER5z.cjs.map +0 -1
- package/dist/index-CiSoT2Lk.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const WATERMARK_ID_PREFIX = "__wm_";
|
|
4
|
-
const DEFAULT_WATERMARK_OPACITY = 0.14;
|
|
5
|
-
const DEFAULT_WATERMARK_FONT_SIZE = 18;
|
|
6
|
-
const DEFAULT_WATERMARK_ANGLE = -30;
|
|
7
|
-
function getWatermarkText() {
|
|
8
|
-
try {
|
|
9
|
-
const host = window.location.hostname;
|
|
10
|
-
if (host.includes("biomaker")) return "biomaker.app";
|
|
11
|
-
} catch {
|
|
12
|
-
}
|
|
13
|
-
return "pixldocs.com";
|
|
14
|
-
}
|
|
15
|
-
function getLuminance(color) {
|
|
16
|
-
if (!color || color === "transparent" || color === "none") return 1;
|
|
17
|
-
let r = 255, g = 255, b = 255;
|
|
18
|
-
if (color.startsWith("#")) {
|
|
19
|
-
const hex = color.slice(1);
|
|
20
|
-
const full = hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex;
|
|
21
|
-
const n = parseInt(full, 16);
|
|
22
|
-
r = n >> 16 & 255;
|
|
23
|
-
g = n >> 8 & 255;
|
|
24
|
-
b = n & 255;
|
|
25
|
-
} else {
|
|
26
|
-
const m = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
27
|
-
if (m) {
|
|
28
|
-
r = +m[1];
|
|
29
|
-
g = +m[2];
|
|
30
|
-
b = +m[3];
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
34
|
-
}
|
|
35
|
-
function getWatermarkColor(bgColor) {
|
|
36
|
-
const lum = getLuminance(bgColor);
|
|
37
|
-
return lum < 0.45 ? "#cccccc" : "#808080";
|
|
38
|
-
}
|
|
39
|
-
function getPageBgColor(page, canvasBg) {
|
|
40
|
-
var _a, _b;
|
|
41
|
-
const settingsBg = (_a = page.settings) == null ? void 0 : _a.backgroundColor;
|
|
42
|
-
if (settingsBg && settingsBg !== "transparent" && settingsBg !== "none") {
|
|
43
|
-
return settingsBg;
|
|
44
|
-
}
|
|
45
|
-
const children = page.children || [];
|
|
46
|
-
for (const child of children) {
|
|
47
|
-
if (child.type === "shape" && child.fill && child.fill !== "transparent" && child.fill !== "none") {
|
|
48
|
-
return child.fill;
|
|
49
|
-
}
|
|
50
|
-
if ((_b = child.children) == null ? void 0 : _b.length) {
|
|
51
|
-
for (const gc of child.children) {
|
|
52
|
-
if (gc.type === "shape" && gc.fill && gc.fill !== "transparent" && gc.fill !== "none") {
|
|
53
|
-
return gc.fill;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return canvasBg;
|
|
59
|
-
}
|
|
60
|
-
function generateWatermarkElements(canvasWidth, canvasHeight, wmColor, options = {}) {
|
|
61
|
-
const elements = [];
|
|
62
|
-
const text = options.text ?? getWatermarkText();
|
|
63
|
-
const fontSize = options.fontSize ?? DEFAULT_WATERMARK_FONT_SIZE;
|
|
64
|
-
const angle = options.angle ?? DEFAULT_WATERMARK_ANGLE;
|
|
65
|
-
const opacity = options.opacity ?? DEFAULT_WATERMARK_OPACITY;
|
|
66
|
-
const estimatedTextWidth = text.length * fontSize * 0.55;
|
|
67
|
-
const spacingX = Math.max(160, estimatedTextWidth + 30);
|
|
68
|
-
const spacingY = 90;
|
|
69
|
-
const startX = -canvasWidth * 0.3;
|
|
70
|
-
const startY = -canvasHeight * 0.3;
|
|
71
|
-
const endX = canvasWidth * 1.5;
|
|
72
|
-
const endY = canvasHeight * 1.5;
|
|
73
|
-
let idx = 0;
|
|
74
|
-
for (let y = startY; y < endY; y += spacingY) {
|
|
75
|
-
for (let x = startX; x < endX; x += spacingX) {
|
|
76
|
-
elements.push({
|
|
77
|
-
id: `${WATERMARK_ID_PREFIX}${idx++}`,
|
|
78
|
-
type: "text",
|
|
79
|
-
left: x,
|
|
80
|
-
top: y,
|
|
81
|
-
width: 200,
|
|
82
|
-
height: 40,
|
|
83
|
-
text,
|
|
84
|
-
fontFamily: "Montserrat",
|
|
85
|
-
fontSize,
|
|
86
|
-
fontWeight: "600",
|
|
87
|
-
fill: wmColor,
|
|
88
|
-
angle,
|
|
89
|
-
selectable: false,
|
|
90
|
-
locked: true,
|
|
91
|
-
visible: true,
|
|
92
|
-
opacity,
|
|
93
|
-
scaleX: 1,
|
|
94
|
-
scaleY: 1,
|
|
95
|
-
letterSpacing: 4
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return elements;
|
|
100
|
-
}
|
|
101
|
-
function injectWatermark(config, options = {}) {
|
|
102
|
-
var _a, _b, _c;
|
|
103
|
-
const canvasWidth = ((_a = config.canvas) == null ? void 0 : _a.width) || 612;
|
|
104
|
-
const canvasHeight = ((_b = config.canvas) == null ? void 0 : _b.height) || 792;
|
|
105
|
-
const canvasBg = (_c = config.canvas) == null ? void 0 : _c.backgroundColor;
|
|
106
|
-
return {
|
|
107
|
-
...config,
|
|
108
|
-
pages: config.pages.map((page) => {
|
|
109
|
-
const pageBg = getPageBgColor(page, canvasBg);
|
|
110
|
-
const wmColor = getWatermarkColor(pageBg);
|
|
111
|
-
const watermarkElements = generateWatermarkElements(canvasWidth, canvasHeight, wmColor, options);
|
|
112
|
-
return {
|
|
113
|
-
...page,
|
|
114
|
-
children: [
|
|
115
|
-
...page.children || [],
|
|
116
|
-
...watermarkElements
|
|
117
|
-
]
|
|
118
|
-
};
|
|
119
|
-
})
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
exports.injectWatermark = injectWatermark;
|
|
123
|
-
//# sourceMappingURL=canvasWatermark-B0ab38Ok.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"canvasWatermark-B0ab38Ok.cjs","sources":["../../../src/lib/canvasWatermark.ts"],"sourcesContent":["/**\n * Injects diagonal \"PixlDocs\" watermark text elements into a TemplateConfig's pages.\n * The watermark elements are rendered as actual canvas text objects,\n * making them impossible to remove via browser inspect.\n */\n\nimport type { TemplateConfig, CanvasElement } from '@/types/editor';\n\nconst WATERMARK_ID_PREFIX = '__wm_';\n\n/** Optional overrides for watermark appearance. */\nexport interface WatermarkOptions {\n /** Override the watermark text. Defaults to domain-based ('pixldocs.com' / 'biomaker.app'). */\n text?: string;\n /** Opacity 0–1. Default: 0.14 */\n opacity?: number;\n /** Font size in px. Default: 18 */\n fontSize?: number;\n /** Rotation angle in degrees. Default: -30 */\n angle?: number;\n}\n\nconst DEFAULT_WATERMARK_OPACITY = 0.14;\nconst DEFAULT_WATERMARK_FONT_SIZE = 18;\nconst DEFAULT_WATERMARK_ANGLE = -30;\n\n/** Determine watermark text based on current domain */\nfunction getWatermarkText(): string {\n try {\n const host = window.location.hostname;\n if (host.includes('biomaker')) return 'biomaker.app';\n } catch {}\n return 'pixldocs.com';\n}\n\n/** Parse a hex/rgb color to luminance (0=black, 1=white) */\nfunction getLuminance(color: string | undefined): number {\n if (!color || color === 'transparent' || color === 'none') return 1; // assume light\n let r = 255, g = 255, b = 255;\n if (color.startsWith('#')) {\n const hex = color.slice(1);\n const full = hex.length === 3 ? hex.split('').map(c => c + c).join('') : hex;\n const n = parseInt(full, 16);\n r = (n >> 16) & 255;\n g = (n >> 8) & 255;\n b = n & 255;\n } else {\n const m = color.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/);\n if (m) { r = +m[1]; g = +m[2]; b = +m[3]; }\n }\n return (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n}\n\n/** Pick watermark color that contrasts with page background */\nfunction getWatermarkColor(bgColor: string | undefined): string {\n const lum = getLuminance(bgColor);\n // Dark bg → light watermark, Light bg → dark watermark\n return lum < 0.45 ? '#cccccc' : '#808080';\n}\n\n/** Find the dominant background color of a page */\nfunction getPageBgColor(page: { children?: any[]; settings?: { backgroundColor?: string } }, canvasBg?: string): string | undefined {\n // 1. Check page-level settings (theme-applied bg lives here)\n const settingsBg = page.settings?.backgroundColor;\n if (settingsBg && settingsBg !== 'transparent' && settingsBg !== 'none') {\n return settingsBg;\n }\n // 2. Check first background shape fill\n const children = page.children || [];\n for (const child of children) {\n if (child.type === 'shape' && child.fill && child.fill !== 'transparent' && child.fill !== 'none') {\n return child.fill;\n }\n // Check inside groups (background groups)\n if (child.children?.length) {\n for (const gc of child.children) {\n if (gc.type === 'shape' && gc.fill && gc.fill !== 'transparent' && gc.fill !== 'none') {\n return gc.fill;\n }\n }\n }\n }\n return canvasBg;\n}\n\n/** Generate watermark text elements for a given canvas size */\nfunction generateWatermarkElements(\n canvasWidth: number,\n canvasHeight: number,\n wmColor: string,\n options: WatermarkOptions = {},\n): CanvasElement[] {\n const elements: CanvasElement[] = [];\n const text = options.text ?? getWatermarkText();\n const fontSize = options.fontSize ?? DEFAULT_WATERMARK_FONT_SIZE;\n const angle = options.angle ?? DEFAULT_WATERMARK_ANGLE;\n const opacity = options.opacity ?? DEFAULT_WATERMARK_OPACITY;\n // Adjust spacing based on text length to prevent overlap\n const estimatedTextWidth = text.length * fontSize * 0.55;\n const spacingX = Math.max(160, estimatedTextWidth + 30);\n const spacingY = 90;\n\n const startX = -canvasWidth * 0.3;\n const startY = -canvasHeight * 0.3;\n const endX = canvasWidth * 1.5;\n const endY = canvasHeight * 1.5;\n\n let idx = 0;\n for (let y = startY; y < endY; y += spacingY) {\n for (let x = startX; x < endX; x += spacingX) {\n elements.push({\n id: `${WATERMARK_ID_PREFIX}${idx++}`,\n type: 'text',\n left: x,\n top: y,\n width: 200,\n height: 40,\n text,\n fontFamily: 'Montserrat',\n fontSize,\n fontWeight: '600',\n fill: wmColor,\n angle,\n selectable: false,\n locked: true,\n visible: true,\n opacity,\n scaleX: 1,\n scaleY: 1,\n letterSpacing: 4,\n } as CanvasElement);\n }\n }\n return elements;\n}\n\n/**\n * Returns a new config with watermark elements injected into every page.\n * The original config is NOT mutated.\n */\nexport function injectWatermark(\n config: TemplateConfig,\n options: WatermarkOptions = {},\n): TemplateConfig {\n const canvasWidth = config.canvas?.width || 612;\n const canvasHeight = config.canvas?.height || 792;\n const canvasBg = (config.canvas as any)?.backgroundColor;\n\n return {\n ...config,\n pages: config.pages.map((page) => {\n const pageBg = getPageBgColor(page as any, canvasBg);\n const wmColor = getWatermarkColor(pageBg);\n const watermarkElements = generateWatermarkElements(canvasWidth, canvasHeight, wmColor, options);\n return {\n ...page,\n children: [\n ...(page.children || []),\n ...watermarkElements,\n ],\n };\n }),\n };\n}\n\n/** Check if an element ID is a watermark element */\nexport function isWatermarkElement(id: string): boolean {\n return id.startsWith(WATERMARK_ID_PREFIX);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
const WATERMARK_ID_PREFIX = "__wm_";
|
|
2
|
-
const DEFAULT_WATERMARK_OPACITY = 0.14;
|
|
3
|
-
const DEFAULT_WATERMARK_FONT_SIZE = 18;
|
|
4
|
-
const DEFAULT_WATERMARK_ANGLE = -30;
|
|
5
|
-
function getWatermarkText() {
|
|
6
|
-
try {
|
|
7
|
-
const host = window.location.hostname;
|
|
8
|
-
if (host.includes("biomaker")) return "biomaker.app";
|
|
9
|
-
} catch {
|
|
10
|
-
}
|
|
11
|
-
return "pixldocs.com";
|
|
12
|
-
}
|
|
13
|
-
function getLuminance(color) {
|
|
14
|
-
if (!color || color === "transparent" || color === "none") return 1;
|
|
15
|
-
let r = 255, g = 255, b = 255;
|
|
16
|
-
if (color.startsWith("#")) {
|
|
17
|
-
const hex = color.slice(1);
|
|
18
|
-
const full = hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex;
|
|
19
|
-
const n = parseInt(full, 16);
|
|
20
|
-
r = n >> 16 & 255;
|
|
21
|
-
g = n >> 8 & 255;
|
|
22
|
-
b = n & 255;
|
|
23
|
-
} else {
|
|
24
|
-
const m = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
25
|
-
if (m) {
|
|
26
|
-
r = +m[1];
|
|
27
|
-
g = +m[2];
|
|
28
|
-
b = +m[3];
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
32
|
-
}
|
|
33
|
-
function getWatermarkColor(bgColor) {
|
|
34
|
-
const lum = getLuminance(bgColor);
|
|
35
|
-
return lum < 0.45 ? "#cccccc" : "#808080";
|
|
36
|
-
}
|
|
37
|
-
function getPageBgColor(page, canvasBg) {
|
|
38
|
-
var _a, _b;
|
|
39
|
-
const settingsBg = (_a = page.settings) == null ? void 0 : _a.backgroundColor;
|
|
40
|
-
if (settingsBg && settingsBg !== "transparent" && settingsBg !== "none") {
|
|
41
|
-
return settingsBg;
|
|
42
|
-
}
|
|
43
|
-
const children = page.children || [];
|
|
44
|
-
for (const child of children) {
|
|
45
|
-
if (child.type === "shape" && child.fill && child.fill !== "transparent" && child.fill !== "none") {
|
|
46
|
-
return child.fill;
|
|
47
|
-
}
|
|
48
|
-
if ((_b = child.children) == null ? void 0 : _b.length) {
|
|
49
|
-
for (const gc of child.children) {
|
|
50
|
-
if (gc.type === "shape" && gc.fill && gc.fill !== "transparent" && gc.fill !== "none") {
|
|
51
|
-
return gc.fill;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return canvasBg;
|
|
57
|
-
}
|
|
58
|
-
function generateWatermarkElements(canvasWidth, canvasHeight, wmColor, options = {}) {
|
|
59
|
-
const elements = [];
|
|
60
|
-
const text = options.text ?? getWatermarkText();
|
|
61
|
-
const fontSize = options.fontSize ?? DEFAULT_WATERMARK_FONT_SIZE;
|
|
62
|
-
const angle = options.angle ?? DEFAULT_WATERMARK_ANGLE;
|
|
63
|
-
const opacity = options.opacity ?? DEFAULT_WATERMARK_OPACITY;
|
|
64
|
-
const estimatedTextWidth = text.length * fontSize * 0.55;
|
|
65
|
-
const spacingX = Math.max(160, estimatedTextWidth + 30);
|
|
66
|
-
const spacingY = 90;
|
|
67
|
-
const startX = -canvasWidth * 0.3;
|
|
68
|
-
const startY = -canvasHeight * 0.3;
|
|
69
|
-
const endX = canvasWidth * 1.5;
|
|
70
|
-
const endY = canvasHeight * 1.5;
|
|
71
|
-
let idx = 0;
|
|
72
|
-
for (let y = startY; y < endY; y += spacingY) {
|
|
73
|
-
for (let x = startX; x < endX; x += spacingX) {
|
|
74
|
-
elements.push({
|
|
75
|
-
id: `${WATERMARK_ID_PREFIX}${idx++}`,
|
|
76
|
-
type: "text",
|
|
77
|
-
left: x,
|
|
78
|
-
top: y,
|
|
79
|
-
width: 200,
|
|
80
|
-
height: 40,
|
|
81
|
-
text,
|
|
82
|
-
fontFamily: "Montserrat",
|
|
83
|
-
fontSize,
|
|
84
|
-
fontWeight: "600",
|
|
85
|
-
fill: wmColor,
|
|
86
|
-
angle,
|
|
87
|
-
selectable: false,
|
|
88
|
-
locked: true,
|
|
89
|
-
visible: true,
|
|
90
|
-
opacity,
|
|
91
|
-
scaleX: 1,
|
|
92
|
-
scaleY: 1,
|
|
93
|
-
letterSpacing: 4
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return elements;
|
|
98
|
-
}
|
|
99
|
-
function injectWatermark(config, options = {}) {
|
|
100
|
-
var _a, _b, _c;
|
|
101
|
-
const canvasWidth = ((_a = config.canvas) == null ? void 0 : _a.width) || 612;
|
|
102
|
-
const canvasHeight = ((_b = config.canvas) == null ? void 0 : _b.height) || 792;
|
|
103
|
-
const canvasBg = (_c = config.canvas) == null ? void 0 : _c.backgroundColor;
|
|
104
|
-
return {
|
|
105
|
-
...config,
|
|
106
|
-
pages: config.pages.map((page) => {
|
|
107
|
-
const pageBg = getPageBgColor(page, canvasBg);
|
|
108
|
-
const wmColor = getWatermarkColor(pageBg);
|
|
109
|
-
const watermarkElements = generateWatermarkElements(canvasWidth, canvasHeight, wmColor, options);
|
|
110
|
-
return {
|
|
111
|
-
...page,
|
|
112
|
-
children: [
|
|
113
|
-
...page.children || [],
|
|
114
|
-
...watermarkElements
|
|
115
|
-
]
|
|
116
|
-
};
|
|
117
|
-
})
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
export {
|
|
121
|
-
injectWatermark
|
|
122
|
-
};
|
|
123
|
-
//# sourceMappingURL=canvasWatermark-pkhacGge.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"canvasWatermark-pkhacGge.js","sources":["../../../src/lib/canvasWatermark.ts"],"sourcesContent":["/**\n * Injects diagonal \"PixlDocs\" watermark text elements into a TemplateConfig's pages.\n * The watermark elements are rendered as actual canvas text objects,\n * making them impossible to remove via browser inspect.\n */\n\nimport type { TemplateConfig, CanvasElement } from '@/types/editor';\n\nconst WATERMARK_ID_PREFIX = '__wm_';\n\n/** Optional overrides for watermark appearance. */\nexport interface WatermarkOptions {\n /** Override the watermark text. Defaults to domain-based ('pixldocs.com' / 'biomaker.app'). */\n text?: string;\n /** Opacity 0–1. Default: 0.14 */\n opacity?: number;\n /** Font size in px. Default: 18 */\n fontSize?: number;\n /** Rotation angle in degrees. Default: -30 */\n angle?: number;\n}\n\nconst DEFAULT_WATERMARK_OPACITY = 0.14;\nconst DEFAULT_WATERMARK_FONT_SIZE = 18;\nconst DEFAULT_WATERMARK_ANGLE = -30;\n\n/** Determine watermark text based on current domain */\nfunction getWatermarkText(): string {\n try {\n const host = window.location.hostname;\n if (host.includes('biomaker')) return 'biomaker.app';\n } catch {}\n return 'pixldocs.com';\n}\n\n/** Parse a hex/rgb color to luminance (0=black, 1=white) */\nfunction getLuminance(color: string | undefined): number {\n if (!color || color === 'transparent' || color === 'none') return 1; // assume light\n let r = 255, g = 255, b = 255;\n if (color.startsWith('#')) {\n const hex = color.slice(1);\n const full = hex.length === 3 ? hex.split('').map(c => c + c).join('') : hex;\n const n = parseInt(full, 16);\n r = (n >> 16) & 255;\n g = (n >> 8) & 255;\n b = n & 255;\n } else {\n const m = color.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/);\n if (m) { r = +m[1]; g = +m[2]; b = +m[3]; }\n }\n return (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n}\n\n/** Pick watermark color that contrasts with page background */\nfunction getWatermarkColor(bgColor: string | undefined): string {\n const lum = getLuminance(bgColor);\n // Dark bg → light watermark, Light bg → dark watermark\n return lum < 0.45 ? '#cccccc' : '#808080';\n}\n\n/** Find the dominant background color of a page */\nfunction getPageBgColor(page: { children?: any[]; settings?: { backgroundColor?: string } }, canvasBg?: string): string | undefined {\n // 1. Check page-level settings (theme-applied bg lives here)\n const settingsBg = page.settings?.backgroundColor;\n if (settingsBg && settingsBg !== 'transparent' && settingsBg !== 'none') {\n return settingsBg;\n }\n // 2. Check first background shape fill\n const children = page.children || [];\n for (const child of children) {\n if (child.type === 'shape' && child.fill && child.fill !== 'transparent' && child.fill !== 'none') {\n return child.fill;\n }\n // Check inside groups (background groups)\n if (child.children?.length) {\n for (const gc of child.children) {\n if (gc.type === 'shape' && gc.fill && gc.fill !== 'transparent' && gc.fill !== 'none') {\n return gc.fill;\n }\n }\n }\n }\n return canvasBg;\n}\n\n/** Generate watermark text elements for a given canvas size */\nfunction generateWatermarkElements(\n canvasWidth: number,\n canvasHeight: number,\n wmColor: string,\n options: WatermarkOptions = {},\n): CanvasElement[] {\n const elements: CanvasElement[] = [];\n const text = options.text ?? getWatermarkText();\n const fontSize = options.fontSize ?? DEFAULT_WATERMARK_FONT_SIZE;\n const angle = options.angle ?? DEFAULT_WATERMARK_ANGLE;\n const opacity = options.opacity ?? DEFAULT_WATERMARK_OPACITY;\n // Adjust spacing based on text length to prevent overlap\n const estimatedTextWidth = text.length * fontSize * 0.55;\n const spacingX = Math.max(160, estimatedTextWidth + 30);\n const spacingY = 90;\n\n const startX = -canvasWidth * 0.3;\n const startY = -canvasHeight * 0.3;\n const endX = canvasWidth * 1.5;\n const endY = canvasHeight * 1.5;\n\n let idx = 0;\n for (let y = startY; y < endY; y += spacingY) {\n for (let x = startX; x < endX; x += spacingX) {\n elements.push({\n id: `${WATERMARK_ID_PREFIX}${idx++}`,\n type: 'text',\n left: x,\n top: y,\n width: 200,\n height: 40,\n text,\n fontFamily: 'Montserrat',\n fontSize,\n fontWeight: '600',\n fill: wmColor,\n angle,\n selectable: false,\n locked: true,\n visible: true,\n opacity,\n scaleX: 1,\n scaleY: 1,\n letterSpacing: 4,\n } as CanvasElement);\n }\n }\n return elements;\n}\n\n/**\n * Returns a new config with watermark elements injected into every page.\n * The original config is NOT mutated.\n */\nexport function injectWatermark(\n config: TemplateConfig,\n options: WatermarkOptions = {},\n): TemplateConfig {\n const canvasWidth = config.canvas?.width || 612;\n const canvasHeight = config.canvas?.height || 792;\n const canvasBg = (config.canvas as any)?.backgroundColor;\n\n return {\n ...config,\n pages: config.pages.map((page) => {\n const pageBg = getPageBgColor(page as any, canvasBg);\n const wmColor = getWatermarkColor(pageBg);\n const watermarkElements = generateWatermarkElements(canvasWidth, canvasHeight, wmColor, options);\n return {\n ...page,\n children: [\n ...(page.children || []),\n ...watermarkElements,\n ],\n };\n }),\n };\n}\n\n/** Check if an element ID is a watermark element */\nexport function isWatermarkElement(id: string): boolean {\n return id.startsWith(WATERMARK_ID_PREFIX);\n}\n"],"names":[],"mappings":"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"}
|