@pixldocs/canvas-renderer 0.5.187 → 0.5.189
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/README.md +59 -9
- package/dist/{index-DgMi1JSR.cjs → index-CmrxeQ_K.cjs} +200 -132
- package/dist/index-CmrxeQ_K.cjs.map +1 -0
- package/dist/{index-C9H38u7P.js → index-lQXXPpb8.js} +231 -163
- package/dist/index-lQXXPpb8.js.map +1 -0
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -20
- package/dist/index.js +32 -31
- package/dist/{vectorPdfExport-BknzMTNP.cjs → vectorPdfExport-BAAJU0RL.cjs} +4 -4
- package/dist/{vectorPdfExport-BknzMTNP.cjs.map → vectorPdfExport-BAAJU0RL.cjs.map} +1 -1
- package/dist/{vectorPdfExport-BkERGCkM.js → vectorPdfExport-Ch-qwcNJ.js} +4 -4
- package/dist/{vectorPdfExport-BkERGCkM.js.map → vectorPdfExport-Ch-qwcNJ.js.map} +1 -1
- package/package.json +1 -1
- package/dist/index-C9H38u7P.js.map +0 -1
- package/dist/index-DgMi1JSR.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -483,7 +483,7 @@ const blurFieldIds = ['text-reference-name', 'text-phone', 'text-address'];
|
|
|
483
483
|
the resolved config before handing it to the imperative renderer, so the
|
|
484
484
|
blur is baked into the exported pixels.
|
|
485
485
|
|
|
486
|
-
### Biodata teaser previews — blur by flat form key (v0.5.187
|
|
486
|
+
### Biodata teaser previews — blur by flat form key (v0.5.187+, hardened in v0.5.189)
|
|
487
487
|
|
|
488
488
|
Form-driven apps (BioMaker, the pixldocs.com Use page, etc.) already
|
|
489
489
|
speak the **flat form-key** language produced by `applyFormDataToConfig`
|
|
@@ -499,7 +499,10 @@ Instead of reverse-engineering `config.__cloneIdMap` keys or the
|
|
|
499
499
|
flat keys straight to `<PixldocsPreview>` and the package resolves them:
|
|
500
500
|
|
|
501
501
|
```tsx
|
|
502
|
-
import {
|
|
502
|
+
import {
|
|
503
|
+
PixldocsPreview,
|
|
504
|
+
buildTeaserBlurFlatKeys,
|
|
505
|
+
} from '@pixldocs/canvas-renderer';
|
|
503
506
|
|
|
504
507
|
// e.g. for a biodata teaser: blur every detail-row VALUE after row 3.
|
|
505
508
|
const blurFlatFormKeys = buildTeaserBlurFlatKeys(sectionState, schema, {
|
|
@@ -509,11 +512,14 @@ const blurFlatFormKeys = buildTeaserBlurFlatKeys(sectionState, schema, {
|
|
|
509
512
|
|
|
510
513
|
<PixldocsPreview
|
|
511
514
|
config={displayConfig}
|
|
515
|
+
pageIndex={pageIndex}
|
|
512
516
|
frostedBlur
|
|
513
517
|
blurFlatFormKeys={blurFlatFormKeys}
|
|
514
518
|
// Optional — defaults to { bindings: 'value' } so only `*_value` keys
|
|
515
|
-
// are honoured. Pass 'all' to blur labels / titles too.
|
|
516
|
-
|
|
519
|
+
// are honoured. Pass 'all' to blur labels / titles too. `pageIndex` is
|
|
520
|
+
// forwarded into the resolver so verification scopes to the page
|
|
521
|
+
// currently being rendered (recommended for stacked multi-page previews).
|
|
522
|
+
blurFlatFormKeyOptions={{ bindings: 'value', pageIndex }}
|
|
517
523
|
/>
|
|
518
524
|
```
|
|
519
525
|
|
|
@@ -521,10 +527,22 @@ Notes:
|
|
|
521
527
|
|
|
522
528
|
- Matching is done on `config.__cloneIdMap` and handles all alias
|
|
523
529
|
variants (`grp-…_4_value`, `…_4_field_detail_section_N_field_N_value`,
|
|
524
|
-
with or without the wrapper `field_` prefix).
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
530
|
+
with or without the wrapper `field_` prefix). **As of v0.5.189**
|
|
531
|
+
every resolved id is then verified against the actual rendered page
|
|
532
|
+
tree (`config.pages[*]`) — stale or alias map entries that don't
|
|
533
|
+
match a real element are dropped silently. This eliminates the
|
|
534
|
+
"phantom frost rectangle near a section title" class of bug that
|
|
535
|
+
showed up in templates with nested repeatables, where
|
|
536
|
+
`__cloneIdMap` returned ids like `text-…__cgroup-…_e4` but the
|
|
537
|
+
rendered tree used `text-…__cgrp-…_pN_grp-…_eN`.
|
|
538
|
+
- Pass `pageIndex` in `blurFlatFormKeyOptions` to scope verification
|
|
539
|
+
to a single page — clones that landed on a different page will not
|
|
540
|
+
contribute overlays to this page. This is the recommended pattern
|
|
541
|
+
for stacked multi-page previews. Default is `'all'` (verify across
|
|
542
|
+
every page).
|
|
543
|
+
- Use `skipTreeVerification: true` only if you fully trust your
|
|
544
|
+
`__cloneIdMap` (e.g. you just built the config in-process and
|
|
545
|
+
haven't mutated the tree since).
|
|
528
546
|
- Defaults to `bindings: 'value'`, i.e. only flat keys whose last
|
|
529
547
|
segment is `value` resolve. This is exactly the biodata teaser
|
|
530
548
|
pattern: blur row values, leave labels / section titles / full-name /
|
|
@@ -533,6 +551,26 @@ Notes:
|
|
|
533
551
|
PNG/PDF download path, resolve the same keys to exact ids and bake
|
|
534
552
|
them in (see below).
|
|
535
553
|
|
|
554
|
+
#### `buildTeaserBlurFlatKeys(sectionState, sections, options)`
|
|
555
|
+
|
|
556
|
+
Emits the flat form-keys for every repeatable-section entry **after**
|
|
557
|
+
`afterRow` (1-indexed). Walks nested repeatables recursively.
|
|
558
|
+
|
|
559
|
+
- `sectionState` — the same `SectionFormState` you'd hand to
|
|
560
|
+
`resolveFromForm` / `<PixldocsPreview sectionState={…}>`.
|
|
561
|
+
- `sections` — `InferredSection[]` for the active form schema (you
|
|
562
|
+
already have these from `inferFormSchemaFromTemplate` or from the
|
|
563
|
+
`form_schemas` row converted via `fromFormDefSections`).
|
|
564
|
+
- `options.afterRow` — keep the first N entries sharp; blur entries
|
|
565
|
+
`N+1, N+2, …`.
|
|
566
|
+
- `options.bindings` — `'value'` (default) emits only `_value` keys
|
|
567
|
+
(the canonical biodata teaser pattern); `'all'` emits every entry
|
|
568
|
+
field key.
|
|
569
|
+
|
|
570
|
+
Returned keys can be fed straight into the `blurFlatFormKeys` prop
|
|
571
|
+
above and into `resolveBlurElementExactIdsFromFlatFormKeys` for the
|
|
572
|
+
watermarked download path below.
|
|
573
|
+
|
|
536
574
|
#### Watermarked downloads — same resolver + `injectPreviewBlur`
|
|
537
575
|
|
|
538
576
|
```ts
|
|
@@ -544,7 +582,9 @@ import {
|
|
|
544
582
|
const exactIds = resolveBlurElementExactIdsFromFlatFormKeys(
|
|
545
583
|
resolvedConfig,
|
|
546
584
|
blurFlatFormKeys,
|
|
547
|
-
// { bindings: 'value' } by default
|
|
585
|
+
// { bindings: 'value', pageIndex: 'all' } by default. For the
|
|
586
|
+
// download path you usually want 'all' since the export covers
|
|
587
|
+
// every page.
|
|
548
588
|
);
|
|
549
589
|
|
|
550
590
|
const exportConfig = injectPreviewBlur(resolvedConfig, {
|
|
@@ -556,3 +596,13 @@ const exportConfig = injectPreviewBlur(resolvedConfig, {
|
|
|
556
596
|
|
|
557
597
|
Same resolution path as the live preview — so the on-screen overlay and
|
|
558
598
|
the downloaded PNG/PDF blur exactly the same elements.
|
|
599
|
+
|
|
600
|
+
#### Parity note
|
|
601
|
+
|
|
602
|
+
The pixldocs.com **Use page** (the in-app paid-template preview, including
|
|
603
|
+
the Biodata preset's 🔒 per-field checkboxes) and external consumers
|
|
604
|
+
(BioMaker, etc.) both call **the same `resolveBlurElementExactIdsFromFlatFormKeys`**
|
|
605
|
+
function — there is now exactly one resolver shared across the entire
|
|
606
|
+
stack. Anything that blurs correctly in one place blurs identically in
|
|
607
|
+
the other; visual/UX bugs introduced in one pipeline cannot diverge
|
|
608
|
+
silently from the other.
|
|
@@ -16133,10 +16133,122 @@ async function getTemplateForm(options) {
|
|
|
16133
16133
|
initialSectionState
|
|
16134
16134
|
};
|
|
16135
16135
|
}
|
|
16136
|
+
const OVERLAY_ID_PREFIX = "__pb_";
|
|
16137
|
+
function getNumber(v, fallback = 0) {
|
|
16138
|
+
return typeof v === "number" && Number.isFinite(v) ? v : fallback;
|
|
16139
|
+
}
|
|
16140
|
+
function resolveSize(node, key) {
|
|
16141
|
+
const v = node == null ? void 0 : node[key];
|
|
16142
|
+
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
16143
|
+
return 0;
|
|
16144
|
+
}
|
|
16145
|
+
function collectOverlays(node, parentLeft, parentTop, inheritedBlur, extraBaseIds, extraExactIds, out) {
|
|
16146
|
+
if (!node || typeof node !== "object") return;
|
|
16147
|
+
const matchesBase = !!(extraBaseIds && typeof node.id === "string" && extraBaseIds.has(baseId(node.id)));
|
|
16148
|
+
const matchesExact = !!(extraExactIds && typeof node.id === "string" && extraExactIds.has(node.id));
|
|
16149
|
+
const isBlurred = inheritedBlur || node.previewBlur === true || matchesBase || matchesExact;
|
|
16150
|
+
const absLeft = parentLeft + getNumber(node.left, 0);
|
|
16151
|
+
const absTop = parentTop + getNumber(node.top, 0);
|
|
16152
|
+
if (node.type === "group") {
|
|
16153
|
+
const children = node.children || node.elements;
|
|
16154
|
+
if (Array.isArray(children)) {
|
|
16155
|
+
for (const child of children) {
|
|
16156
|
+
collectOverlays(child, absLeft, absTop, isBlurred, extraBaseIds, extraExactIds, out);
|
|
16157
|
+
}
|
|
16158
|
+
}
|
|
16159
|
+
return;
|
|
16160
|
+
}
|
|
16161
|
+
if (!isBlurred) return;
|
|
16162
|
+
const scaleX = getNumber(node.scaleX, 1) || 1;
|
|
16163
|
+
const scaleY = getNumber(node.scaleY, 1) || 1;
|
|
16164
|
+
const w = Math.max(4, resolveSize(node, "width") * scaleX);
|
|
16165
|
+
const h = Math.max(4, resolveSize(node, "height") * scaleY);
|
|
16166
|
+
out.push({
|
|
16167
|
+
left: absLeft,
|
|
16168
|
+
top: absTop,
|
|
16169
|
+
width: w,
|
|
16170
|
+
height: h,
|
|
16171
|
+
hintFill: typeof node.fill === "string" ? node.fill : void 0
|
|
16172
|
+
});
|
|
16173
|
+
}
|
|
16174
|
+
function parseColor$1(c) {
|
|
16175
|
+
if (!c) return null;
|
|
16176
|
+
const s = c.trim();
|
|
16177
|
+
const hex = s.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
|
|
16178
|
+
if (hex) {
|
|
16179
|
+
let h = hex[1];
|
|
16180
|
+
if (h.length === 3) h = h.split("").map((x) => x + x).join("");
|
|
16181
|
+
return {
|
|
16182
|
+
r: parseInt(h.slice(0, 2), 16),
|
|
16183
|
+
g: parseInt(h.slice(2, 4), 16),
|
|
16184
|
+
b: parseInt(h.slice(4, 6), 16)
|
|
16185
|
+
};
|
|
16186
|
+
}
|
|
16187
|
+
const rgb = s.match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/i);
|
|
16188
|
+
if (rgb) return { r: +rgb[1], g: +rgb[2], b: +rgb[3] };
|
|
16189
|
+
return null;
|
|
16190
|
+
}
|
|
16191
|
+
function buildOverlay(b, idx) {
|
|
16192
|
+
const c = parseColor$1(b.hintFill);
|
|
16193
|
+
const lum = c ? (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) / 255 : 0.2;
|
|
16194
|
+
const isLightGlass = lum < 0.5;
|
|
16195
|
+
const baseFill = isLightGlass ? "rgba(245,245,245,0.68)" : "rgba(30,30,30,0.62)";
|
|
16196
|
+
return {
|
|
16197
|
+
id: `${OVERLAY_ID_PREFIX}${idx}`,
|
|
16198
|
+
type: "shape",
|
|
16199
|
+
shapeType: "rounded-rect",
|
|
16200
|
+
left: b.left,
|
|
16201
|
+
top: b.top,
|
|
16202
|
+
width: b.width,
|
|
16203
|
+
height: b.height,
|
|
16204
|
+
cornerRadius: 0,
|
|
16205
|
+
fill: baseFill,
|
|
16206
|
+
stroke: "transparent",
|
|
16207
|
+
strokeWidth: 0,
|
|
16208
|
+
opacity: 1,
|
|
16209
|
+
selectable: false,
|
|
16210
|
+
locked: true,
|
|
16211
|
+
visible: true,
|
|
16212
|
+
scaleX: 1,
|
|
16213
|
+
scaleY: 1
|
|
16214
|
+
};
|
|
16215
|
+
}
|
|
16216
|
+
function injectPreviewBlur(config, options) {
|
|
16217
|
+
const cloned = typeof structuredClone === "function" ? structuredClone(config) : JSON.parse(JSON.stringify(config));
|
|
16218
|
+
const extraBase = (options == null ? void 0 : options.extraElementBaseIds) && options.extraElementBaseIds.size > 0 ? options.extraElementBaseIds : void 0;
|
|
16219
|
+
const extraExact = (options == null ? void 0 : options.extraElementExactIds) && options.extraElementExactIds.size > 0 ? options.extraElementExactIds : void 0;
|
|
16220
|
+
let idx = 0;
|
|
16221
|
+
for (const page of cloned.pages || []) {
|
|
16222
|
+
const children = page.children || page.elements;
|
|
16223
|
+
if (!Array.isArray(children)) continue;
|
|
16224
|
+
const overlays = [];
|
|
16225
|
+
for (const child of children) {
|
|
16226
|
+
collectOverlays(child, 0, 0, false, extraBase, extraExact, overlays);
|
|
16227
|
+
}
|
|
16228
|
+
if (overlays.length === 0) continue;
|
|
16229
|
+
for (const b of overlays) {
|
|
16230
|
+
children.push(buildOverlay(b, idx++));
|
|
16231
|
+
}
|
|
16232
|
+
}
|
|
16233
|
+
return cloned;
|
|
16234
|
+
}
|
|
16235
|
+
function hasAnyPreviewBlur(config) {
|
|
16236
|
+
function walk(node) {
|
|
16237
|
+
if (!node || typeof node !== "object") return false;
|
|
16238
|
+
if (node.previewBlur === true) return true;
|
|
16239
|
+
const children = node.children || node.elements;
|
|
16240
|
+
if (Array.isArray(children)) {
|
|
16241
|
+
for (const c of children) if (walk(c)) return true;
|
|
16242
|
+
}
|
|
16243
|
+
return false;
|
|
16244
|
+
}
|
|
16245
|
+
for (const page of config.pages || []) if (walk(page)) return true;
|
|
16246
|
+
return false;
|
|
16247
|
+
}
|
|
16136
16248
|
function stripFieldPrefix(s) {
|
|
16137
16249
|
return s.startsWith("field_") ? s.slice("field_".length) : s;
|
|
16138
16250
|
}
|
|
16139
|
-
function
|
|
16251
|
+
function addAllToSet(val, out) {
|
|
16140
16252
|
if (!val) return false;
|
|
16141
16253
|
if (Array.isArray(val)) {
|
|
16142
16254
|
for (const v of val) out.add(v);
|
|
@@ -16145,6 +16257,23 @@ function addAll(val, out) {
|
|
|
16145
16257
|
out.add(val);
|
|
16146
16258
|
return true;
|
|
16147
16259
|
}
|
|
16260
|
+
function collectPageTreeElementIds(config, pageIndex = "all") {
|
|
16261
|
+
const out = /* @__PURE__ */ new Set();
|
|
16262
|
+
const pages = config == null ? void 0 : config.pages;
|
|
16263
|
+
if (!Array.isArray(pages)) return out;
|
|
16264
|
+
const targets = pageIndex === "all" ? pages : pages[pageIndex] != null ? [pages[pageIndex]] : [];
|
|
16265
|
+
const walk = (node) => {
|
|
16266
|
+
if (!node || typeof node !== "object") return;
|
|
16267
|
+
if (typeof node.id === "string") out.add(node.id);
|
|
16268
|
+
const children = node.children || node.elements;
|
|
16269
|
+
if (Array.isArray(children)) for (const c of children) walk(c);
|
|
16270
|
+
};
|
|
16271
|
+
for (const page of targets) {
|
|
16272
|
+
const children = (page == null ? void 0 : page.children) || (page == null ? void 0 : page.elements);
|
|
16273
|
+
if (Array.isArray(children)) for (const c of children) walk(c);
|
|
16274
|
+
}
|
|
16275
|
+
return out;
|
|
16276
|
+
}
|
|
16148
16277
|
function resolveBlurElementExactIdsFromFlatFormKeys(config, flatFormKeys, options) {
|
|
16149
16278
|
const cloneIdMap = (config == null ? void 0 : config.__cloneIdMap) || {};
|
|
16150
16279
|
if (!cloneIdMap || typeof cloneIdMap !== "object") return [];
|
|
@@ -16165,12 +16294,67 @@ function resolveBlurElementExactIdsFromFlatFormKeys(config, flatFormKeys, option
|
|
|
16165
16294
|
}
|
|
16166
16295
|
for (const k of candidates) {
|
|
16167
16296
|
if (k in cloneIdMap) {
|
|
16168
|
-
if (
|
|
16297
|
+
if (addAllToSet(cloneIdMap[k], out)) break;
|
|
16169
16298
|
}
|
|
16170
16299
|
}
|
|
16171
16300
|
}
|
|
16172
|
-
|
|
16301
|
+
if (out.size === 0) return [];
|
|
16302
|
+
if (options == null ? void 0 : options.skipTreeVerification) return Array.from(out);
|
|
16303
|
+
const treeIds = collectPageTreeElementIds(
|
|
16304
|
+
config,
|
|
16305
|
+
(options == null ? void 0 : options.pageIndex) ?? "all"
|
|
16306
|
+
);
|
|
16307
|
+
if (treeIds.size === 0) return Array.from(out);
|
|
16308
|
+
const verified = [];
|
|
16309
|
+
for (const id of out) if (treeIds.has(id)) verified.push(id);
|
|
16310
|
+
return verified;
|
|
16311
|
+
}
|
|
16312
|
+
function buildTeaserBlurFlatKeys(sectionState, sections, options) {
|
|
16313
|
+
const afterRow = Math.max(0, options.afterRow | 0);
|
|
16314
|
+
const bindings = options.bindings ?? "value";
|
|
16315
|
+
const out = [];
|
|
16316
|
+
if (!sectionState || !Array.isArray(sections)) return out;
|
|
16317
|
+
const repeatables = sections.filter((s) => (s == null ? void 0 : s.type) === "repeatable");
|
|
16318
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
16319
|
+
for (const r of repeatables) {
|
|
16320
|
+
if (!r.parentId) continue;
|
|
16321
|
+
const arr = childrenByParent.get(r.parentId) || [];
|
|
16322
|
+
arr.push(r);
|
|
16323
|
+
childrenByParent.set(r.parentId, arr);
|
|
16324
|
+
}
|
|
16325
|
+
const emitForEntryFields = (section, keyPrefix, entryIdx1) => {
|
|
16326
|
+
const fields = section.entryFields || [];
|
|
16327
|
+
for (const f of fields) {
|
|
16328
|
+
if (!(f == null ? void 0 : f.key)) continue;
|
|
16329
|
+
if (bindings === "value" && f.key !== "value") continue;
|
|
16330
|
+
out.push(`${keyPrefix}_${f.key}`);
|
|
16331
|
+
}
|
|
16332
|
+
};
|
|
16333
|
+
const walkRepeatable = (section, parentKeyPrefix) => {
|
|
16334
|
+
const entries = sectionState == null ? void 0 : sectionState[section.id];
|
|
16335
|
+
if (!Array.isArray(entries)) return;
|
|
16336
|
+
for (let i = 0; i < entries.length; i++) {
|
|
16337
|
+
const entryIdx1 = i + 1;
|
|
16338
|
+
const isBlurred = entryIdx1 > afterRow;
|
|
16339
|
+
const keyPrefix = parentKeyPrefix ? `${parentKeyPrefix}_field_${section.id}_${entryIdx1}` : `field_${section.id}_${entryIdx1}`;
|
|
16340
|
+
if (isBlurred) emitForEntryFields(section, keyPrefix);
|
|
16341
|
+
const children = childrenByParent.get(section.id) || [];
|
|
16342
|
+
for (const child of children) walkRepeatable(child, keyPrefix);
|
|
16343
|
+
}
|
|
16344
|
+
};
|
|
16345
|
+
for (const r of repeatables) {
|
|
16346
|
+
if (r.parentId) continue;
|
|
16347
|
+
walkRepeatable(r, "");
|
|
16348
|
+
}
|
|
16349
|
+
return out;
|
|
16173
16350
|
}
|
|
16351
|
+
const previewBlur = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
16352
|
+
__proto__: null,
|
|
16353
|
+
buildTeaserBlurFlatKeys,
|
|
16354
|
+
hasAnyPreviewBlur,
|
|
16355
|
+
injectPreviewBlur,
|
|
16356
|
+
resolveBlurElementExactIdsFromFlatFormKeys
|
|
16357
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
16174
16358
|
const PREVIEW_DEBUG_PREFIX = "[canvas-renderer][preview-debug]";
|
|
16175
16359
|
function computeFontSignature(config) {
|
|
16176
16360
|
var _a;
|
|
@@ -16651,9 +16835,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
16651
16835
|
}
|
|
16652
16836
|
return svgString;
|
|
16653
16837
|
}
|
|
16654
|
-
const resolvedPackageVersion = "0.5.
|
|
16838
|
+
const resolvedPackageVersion = "0.5.189";
|
|
16655
16839
|
const PACKAGE_VERSION = resolvedPackageVersion;
|
|
16656
|
-
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.
|
|
16840
|
+
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.189";
|
|
16657
16841
|
const roundParityValue = (value) => {
|
|
16658
16842
|
if (typeof value !== "number") return value;
|
|
16659
16843
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -17161,7 +17345,7 @@ class PixldocsRenderer {
|
|
|
17161
17345
|
await this.waitForCanvasScene(container, cloned, i);
|
|
17162
17346
|
}
|
|
17163
17347
|
console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
|
|
17164
|
-
const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-
|
|
17348
|
+
const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BAAJU0RL.cjs"));
|
|
17165
17349
|
const prepared = preparePagesForExport(
|
|
17166
17350
|
cloned.pages,
|
|
17167
17351
|
canvasWidth,
|
|
@@ -18003,7 +18187,7 @@ function collectFontSpecsFromMarkup(markup) {
|
|
|
18003
18187
|
}
|
|
18004
18188
|
return Array.from(specs);
|
|
18005
18189
|
}
|
|
18006
|
-
function parseColor
|
|
18190
|
+
function parseColor(color) {
|
|
18007
18191
|
if (!color) return null;
|
|
18008
18192
|
const raw = color.trim().toLowerCase();
|
|
18009
18193
|
if (!raw || raw === "transparent" || raw === "none") return null;
|
|
@@ -18556,7 +18740,7 @@ function stripSuspiciousFullPageOverlayNodes(svg) {
|
|
|
18556
18740
|
if (!(pageWidth > 0 && pageHeight > 0)) return;
|
|
18557
18741
|
const isNear = (a, b, tolerance = 0.75) => Math.abs(a - b) <= tolerance;
|
|
18558
18742
|
const isDarkPaint = (value) => {
|
|
18559
|
-
const rgb = value ? parseColor
|
|
18743
|
+
const rgb = value ? parseColor(value) : null;
|
|
18560
18744
|
return rgb ? rgb.r <= 32 && rgb.g <= 32 && rgb.b <= 32 : false;
|
|
18561
18745
|
};
|
|
18562
18746
|
const removeIfSuspicious = (el) => {
|
|
@@ -18669,13 +18853,13 @@ function inlineComputedStyles(svg) {
|
|
|
18669
18853
|
const fill = cs.fill;
|
|
18670
18854
|
const stroke = cs.stroke;
|
|
18671
18855
|
if (fill && fill !== "none" && fill !== "rgba(0, 0, 0, 0)") {
|
|
18672
|
-
const parsed = parseColor
|
|
18856
|
+
const parsed = parseColor(fill);
|
|
18673
18857
|
if (parsed) el.setAttribute("fill", rgbToHex(parsed.r, parsed.g, parsed.b));
|
|
18674
18858
|
} else if (fill === "rgba(0, 0, 0, 0)" || fill === "transparent") {
|
|
18675
18859
|
el.setAttribute("fill", "none");
|
|
18676
18860
|
}
|
|
18677
18861
|
if (stroke && stroke !== "none" && stroke !== "rgba(0, 0, 0, 0)") {
|
|
18678
|
-
const parsed = parseColor
|
|
18862
|
+
const parsed = parseColor(stroke);
|
|
18679
18863
|
if (parsed) el.setAttribute("stroke", rgbToHex(parsed.r, parsed.g, parsed.b));
|
|
18680
18864
|
}
|
|
18681
18865
|
}
|
|
@@ -18823,7 +19007,7 @@ function setPdfColorFromSvg(pdf, svg, _elementId) {
|
|
|
18823
19007
|
const { fill, stroke } = getFirstExplicitColorFromSvg(svg);
|
|
18824
19008
|
const setColor = (hex, setter) => {
|
|
18825
19009
|
if (!hex) return;
|
|
18826
|
-
const c = parseColor
|
|
19010
|
+
const c = parseColor(hex);
|
|
18827
19011
|
if (c) pdf[setter](c.r, c.g, c.b);
|
|
18828
19012
|
};
|
|
18829
19013
|
setColor(fill, "setFillColor");
|
|
@@ -19306,7 +19490,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
19306
19490
|
if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
|
|
19307
19491
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
19308
19492
|
try {
|
|
19309
|
-
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-
|
|
19493
|
+
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BAAJU0RL.cjs"));
|
|
19310
19494
|
try {
|
|
19311
19495
|
await logTextMeasurementDiagnostic(svgToDraw);
|
|
19312
19496
|
} catch {
|
|
@@ -19326,7 +19510,7 @@ function drawPageBackground(pdf, pageIndex, pageWidth, pageHeight, backgroundCol
|
|
|
19326
19510
|
if (backgroundGradient && ((_a = backgroundGradient.stops) == null ? void 0 : _a.length) >= 2) {
|
|
19327
19511
|
const grad = backgroundGradient;
|
|
19328
19512
|
const colorStops = grad.stops.map((s) => {
|
|
19329
|
-
const c = parseColor
|
|
19513
|
+
const c = parseColor(s.color);
|
|
19330
19514
|
return {
|
|
19331
19515
|
offset: Math.max(0, Math.min(1, Number(s.offset))),
|
|
19332
19516
|
color: c ? [c.r, c.g, c.b] : [0, 0, 0]
|
|
@@ -19382,7 +19566,7 @@ function drawPageBackground(pdf, pageIndex, pageWidth, pageHeight, backgroundCol
|
|
|
19382
19566
|
pdf.rect(0, 0, pageWidth, pageHeight, "F");
|
|
19383
19567
|
}
|
|
19384
19568
|
} else {
|
|
19385
|
-
const bgColor = parseColor
|
|
19569
|
+
const bgColor = parseColor(backgroundColor && backgroundColor !== "transparent" ? backgroundColor : "#ffffff");
|
|
19386
19570
|
if (bgColor) {
|
|
19387
19571
|
pdf.setFillColor(bgColor.r, bgColor.g, bgColor.b);
|
|
19388
19572
|
pdf.rect(0, 0, pageWidth, pageHeight, "F");
|
|
@@ -19505,123 +19689,6 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
|
|
|
19505
19689
|
pages: svgResults.map((p) => ({ width: p.width, height: p.height }))
|
|
19506
19690
|
};
|
|
19507
19691
|
}
|
|
19508
|
-
const OVERLAY_ID_PREFIX = "__pb_";
|
|
19509
|
-
function getNumber(v, fallback = 0) {
|
|
19510
|
-
return typeof v === "number" && Number.isFinite(v) ? v : fallback;
|
|
19511
|
-
}
|
|
19512
|
-
function resolveSize(node, key) {
|
|
19513
|
-
const v = node == null ? void 0 : node[key];
|
|
19514
|
-
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
19515
|
-
return 0;
|
|
19516
|
-
}
|
|
19517
|
-
function collectOverlays(node, parentLeft, parentTop, inheritedBlur, extraBaseIds, extraExactIds, out) {
|
|
19518
|
-
if (!node || typeof node !== "object") return;
|
|
19519
|
-
const matchesBase = !!(extraBaseIds && typeof node.id === "string" && extraBaseIds.has(baseId(node.id)));
|
|
19520
|
-
const matchesExact = !!(extraExactIds && typeof node.id === "string" && extraExactIds.has(node.id));
|
|
19521
|
-
const isBlurred = inheritedBlur || node.previewBlur === true || matchesBase || matchesExact;
|
|
19522
|
-
const absLeft = parentLeft + getNumber(node.left, 0);
|
|
19523
|
-
const absTop = parentTop + getNumber(node.top, 0);
|
|
19524
|
-
if (node.type === "group") {
|
|
19525
|
-
const children = node.children || node.elements;
|
|
19526
|
-
if (Array.isArray(children)) {
|
|
19527
|
-
for (const child of children) {
|
|
19528
|
-
collectOverlays(child, absLeft, absTop, isBlurred, extraBaseIds, extraExactIds, out);
|
|
19529
|
-
}
|
|
19530
|
-
}
|
|
19531
|
-
return;
|
|
19532
|
-
}
|
|
19533
|
-
if (!isBlurred) return;
|
|
19534
|
-
const scaleX = getNumber(node.scaleX, 1) || 1;
|
|
19535
|
-
const scaleY = getNumber(node.scaleY, 1) || 1;
|
|
19536
|
-
const w = Math.max(4, resolveSize(node, "width") * scaleX);
|
|
19537
|
-
const h = Math.max(4, resolveSize(node, "height") * scaleY);
|
|
19538
|
-
out.push({
|
|
19539
|
-
left: absLeft,
|
|
19540
|
-
top: absTop,
|
|
19541
|
-
width: w,
|
|
19542
|
-
height: h,
|
|
19543
|
-
hintFill: typeof node.fill === "string" ? node.fill : void 0
|
|
19544
|
-
});
|
|
19545
|
-
}
|
|
19546
|
-
function parseColor(c) {
|
|
19547
|
-
if (!c) return null;
|
|
19548
|
-
const s = c.trim();
|
|
19549
|
-
const hex = s.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
|
|
19550
|
-
if (hex) {
|
|
19551
|
-
let h = hex[1];
|
|
19552
|
-
if (h.length === 3) h = h.split("").map((x) => x + x).join("");
|
|
19553
|
-
return {
|
|
19554
|
-
r: parseInt(h.slice(0, 2), 16),
|
|
19555
|
-
g: parseInt(h.slice(2, 4), 16),
|
|
19556
|
-
b: parseInt(h.slice(4, 6), 16)
|
|
19557
|
-
};
|
|
19558
|
-
}
|
|
19559
|
-
const rgb = s.match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/i);
|
|
19560
|
-
if (rgb) return { r: +rgb[1], g: +rgb[2], b: +rgb[3] };
|
|
19561
|
-
return null;
|
|
19562
|
-
}
|
|
19563
|
-
function buildOverlay(b, idx) {
|
|
19564
|
-
const c = parseColor(b.hintFill);
|
|
19565
|
-
const lum = c ? (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) / 255 : 0.2;
|
|
19566
|
-
const isLightGlass = lum < 0.5;
|
|
19567
|
-
const baseFill = isLightGlass ? "rgba(245,245,245,0.68)" : "rgba(30,30,30,0.62)";
|
|
19568
|
-
return {
|
|
19569
|
-
id: `${OVERLAY_ID_PREFIX}${idx}`,
|
|
19570
|
-
type: "shape",
|
|
19571
|
-
shapeType: "rounded-rect",
|
|
19572
|
-
left: b.left,
|
|
19573
|
-
top: b.top,
|
|
19574
|
-
width: b.width,
|
|
19575
|
-
height: b.height,
|
|
19576
|
-
cornerRadius: 0,
|
|
19577
|
-
fill: baseFill,
|
|
19578
|
-
stroke: "transparent",
|
|
19579
|
-
strokeWidth: 0,
|
|
19580
|
-
opacity: 1,
|
|
19581
|
-
selectable: false,
|
|
19582
|
-
locked: true,
|
|
19583
|
-
visible: true,
|
|
19584
|
-
scaleX: 1,
|
|
19585
|
-
scaleY: 1
|
|
19586
|
-
};
|
|
19587
|
-
}
|
|
19588
|
-
function injectPreviewBlur(config, options) {
|
|
19589
|
-
const cloned = typeof structuredClone === "function" ? structuredClone(config) : JSON.parse(JSON.stringify(config));
|
|
19590
|
-
const extraBase = (options == null ? void 0 : options.extraElementBaseIds) && options.extraElementBaseIds.size > 0 ? options.extraElementBaseIds : void 0;
|
|
19591
|
-
const extraExact = (options == null ? void 0 : options.extraElementExactIds) && options.extraElementExactIds.size > 0 ? options.extraElementExactIds : void 0;
|
|
19592
|
-
let idx = 0;
|
|
19593
|
-
for (const page of cloned.pages || []) {
|
|
19594
|
-
const children = page.children || page.elements;
|
|
19595
|
-
if (!Array.isArray(children)) continue;
|
|
19596
|
-
const overlays = [];
|
|
19597
|
-
for (const child of children) {
|
|
19598
|
-
collectOverlays(child, 0, 0, false, extraBase, extraExact, overlays);
|
|
19599
|
-
}
|
|
19600
|
-
if (overlays.length === 0) continue;
|
|
19601
|
-
for (const b of overlays) {
|
|
19602
|
-
children.push(buildOverlay(b, idx++));
|
|
19603
|
-
}
|
|
19604
|
-
}
|
|
19605
|
-
return cloned;
|
|
19606
|
-
}
|
|
19607
|
-
function hasAnyPreviewBlur(config) {
|
|
19608
|
-
function walk(node) {
|
|
19609
|
-
if (!node || typeof node !== "object") return false;
|
|
19610
|
-
if (node.previewBlur === true) return true;
|
|
19611
|
-
const children = node.children || node.elements;
|
|
19612
|
-
if (Array.isArray(children)) {
|
|
19613
|
-
for (const c of children) if (walk(c)) return true;
|
|
19614
|
-
}
|
|
19615
|
-
return false;
|
|
19616
|
-
}
|
|
19617
|
-
for (const page of config.pages || []) if (walk(page)) return true;
|
|
19618
|
-
return false;
|
|
19619
|
-
}
|
|
19620
|
-
const previewBlur = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
19621
|
-
__proto__: null,
|
|
19622
|
-
hasAnyPreviewBlur,
|
|
19623
|
-
injectPreviewBlur
|
|
19624
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
19625
19692
|
const SELECT_COLUMNS = "id,name,description,category,thumbnail_url,preview_images,price,download_count,workspace_id,sort_order,created_at,updated_at";
|
|
19626
19693
|
async function listPublishedTemplates(options) {
|
|
19627
19694
|
const { workspaceId, supabaseUrl, supabaseAnonKey, category, limit = 200, offset = 0 } = options;
|
|
@@ -19774,6 +19841,7 @@ exports.assemblePdfFromSvgs = assemblePdfFromSvgs;
|
|
|
19774
19841
|
exports.awaitFontsForConfig = awaitFontsForConfig;
|
|
19775
19842
|
exports.bakeEdgeFade = bakeEdgeFade;
|
|
19776
19843
|
exports.buildRoundedTrianglePath = buildRoundedTrianglePath;
|
|
19844
|
+
exports.buildTeaserBlurFlatKeys = buildTeaserBlurFlatKeys;
|
|
19777
19845
|
exports.canvasImageLoader = canvasImageLoader;
|
|
19778
19846
|
exports.captureFabricCanvasSvgForPdf = captureFabricCanvasSvgForPdf;
|
|
19779
19847
|
exports.collectFontDescriptorsFromConfig = collectFontDescriptorsFromConfig;
|
|
@@ -19819,4 +19887,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
|
|
|
19819
19887
|
exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
|
|
19820
19888
|
exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
|
|
19821
19889
|
exports.warmTemplateFromForm = warmTemplateFromForm;
|
|
19822
|
-
//# sourceMappingURL=index-
|
|
19890
|
+
//# sourceMappingURL=index-CmrxeQ_K.cjs.map
|