@pixldocs/canvas-renderer 0.5.39 → 0.5.41

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixldocs/canvas-renderer",
3
- "version": "0.5.39",
3
+ "version": "0.5.41",
4
4
  "description": "Client-side template renderer for Pixldocs — React component + imperative API for rendering templates in any web app",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -1 +0,0 @@
1
- {"version":3,"file":"canvasWatermark-CM85x4k7.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/** 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): CanvasElement[] {\n const elements: CanvasElement[] = [];\n const text = getWatermarkText();\n const fontSize = 18;\n const angle = -30;\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: 0.14,\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(config: TemplateConfig): 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);\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 +0,0 @@
1
- {"version":3,"file":"canvasWatermark-DAZIQ_IR.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/** 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): CanvasElement[] {\n const elements: CanvasElement[] = [];\n const text = getWatermarkText();\n const fontSize = 18;\n const angle = -30;\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: 0.14,\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(config: TemplateConfig): 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);\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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"}