@pixldocs/canvas-renderer 0.5.171 → 0.5.173

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.
Files changed (29) hide show
  1. package/dist/{index-Cq9sQGri.js → index-ChHYFk0E.js} +306 -79
  2. package/dist/index-ChHYFk0E.js.map +1 -0
  3. package/dist/{index-BgOzEKmN.cjs → index-ZehEOqUB.cjs} +291 -64
  4. package/dist/index-ZehEOqUB.cjs.map +1 -0
  5. package/dist/index.cjs +2 -1
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.ts +31 -0
  8. package/dist/index.js +16 -15
  9. package/dist/{pdfFonts-BTEVnYX8.cjs → pdfFonts-BTj2f465.cjs} +12 -3
  10. package/dist/pdfFonts-BTj2f465.cjs.map +1 -0
  11. package/dist/{pdfFonts-b3_bv7F0.js → pdfFonts-DhEaMTZl.js} +12 -3
  12. package/dist/pdfFonts-DhEaMTZl.js.map +1 -0
  13. package/dist/{svgTextToPath-IM1f6F-f.cjs → svgTextToPath-BLk_mcqi.cjs} +85 -3
  14. package/dist/svgTextToPath-BLk_mcqi.cjs.map +1 -0
  15. package/dist/{svgTextToPath-BXAzwaaR.js → svgTextToPath-ra4EhtBL.js} +86 -4
  16. package/dist/svgTextToPath-ra4EhtBL.js.map +1 -0
  17. package/dist/{vectorPdfExport-BrwXcGkA.cjs → vectorPdfExport-BWDj55kq.cjs} +36 -10
  18. package/dist/vectorPdfExport-BWDj55kq.cjs.map +1 -0
  19. package/dist/{vectorPdfExport--EtCdnlG.js → vectorPdfExport-CyTa-D1p.js} +36 -10
  20. package/dist/vectorPdfExport-CyTa-D1p.js.map +1 -0
  21. package/package.json +1 -1
  22. package/dist/index-BgOzEKmN.cjs.map +0 -1
  23. package/dist/index-Cq9sQGri.js.map +0 -1
  24. package/dist/pdfFonts-BTEVnYX8.cjs.map +0 -1
  25. package/dist/pdfFonts-b3_bv7F0.js.map +0 -1
  26. package/dist/svgTextToPath-BXAzwaaR.js.map +0 -1
  27. package/dist/svgTextToPath-IM1f6F-f.cjs.map +0 -1
  28. package/dist/vectorPdfExport--EtCdnlG.js.map +0 -1
  29. package/dist/vectorPdfExport-BrwXcGkA.cjs.map +0 -1
@@ -2800,6 +2800,19 @@ const EXTENDED_FONT_LIST = [
2800
2800
  { name: "Petrona", category: "Serif", local: false },
2801
2801
  { name: "Rozha One", category: "Serif", local: false },
2802
2802
  { name: "Tiro Devanagari Hindi", category: "Serif", local: false },
2803
+ // ── Newly added popular serif families ──
2804
+ { name: "Roboto Serif", category: "Serif", local: false, popular: true },
2805
+ { name: "Roboto Slab", category: "Serif", local: false, popular: true },
2806
+ { name: "Inria Serif", category: "Serif", local: false },
2807
+ { name: "Instrument Serif", category: "Serif", local: false, popular: true },
2808
+ { name: "Young Serif", category: "Serif", local: false },
2809
+ { name: "Gloock", category: "Serif", local: false },
2810
+ { name: "Castoro", category: "Serif", local: false },
2811
+ { name: "Source Serif 4", category: "Serif", local: false },
2812
+ { name: "IBM Plex Serif", category: "Serif", local: false },
2813
+ { name: "Pridi", category: "Serif", local: false },
2814
+ { name: "Eczar", category: "Serif", local: false },
2815
+ { name: "Faustina", category: "Serif", local: false },
2803
2816
  // ═══════════════════════════════════════════════════════════════════
2804
2817
  // SANS-SERIF — clean, modern, workhorse
2805
2818
  // ═══════════════════════════════════════════════════════════════════
@@ -2855,6 +2868,43 @@ const EXTENDED_FONT_LIST = [
2855
2868
  { name: "Anek Devanagari", category: "Sans-Serif", local: false },
2856
2869
  { name: "Hind", category: "Sans-Serif", local: true },
2857
2870
  { name: "Hind Vadodara", category: "Sans-Serif", local: false },
2871
+ // ── Newly added popular sans-serif families (Google Fonts; loaded on demand) ──
2872
+ { name: "Ubuntu", category: "Sans-Serif", local: false, popular: true },
2873
+ { name: "Ubuntu Condensed", category: "Sans-Serif", local: false },
2874
+ { name: "Ubuntu Sans", category: "Sans-Serif", local: false },
2875
+ { name: "Roboto Condensed", category: "Sans-Serif", local: false, popular: true },
2876
+ { name: "Roboto Flex", category: "Sans-Serif", local: false },
2877
+ { name: "Jost", category: "Sans-Serif", local: false, popular: true },
2878
+ { name: "Inter Tight", category: "Sans-Serif", local: false },
2879
+ { name: "Mona Sans", category: "Sans-Serif", local: false },
2880
+ { name: "Hubot Sans", category: "Sans-Serif", local: false },
2881
+ { name: "Funnel Sans", category: "Sans-Serif", local: false },
2882
+ { name: "Funnel Display", category: "Sans-Serif", local: false },
2883
+ { name: "Geologica", category: "Sans-Serif", local: false },
2884
+ { name: "Bricolage Grotesque", category: "Sans-Serif", local: false, popular: true },
2885
+ { name: "Familjen Grotesk", category: "Sans-Serif", local: false },
2886
+ { name: "Wix Madefor Display", category: "Sans-Serif", local: false },
2887
+ { name: "Wix Madefor Text", category: "Sans-Serif", local: false },
2888
+ { name: "Atkinson Hyperlegible", category: "Sans-Serif", local: false },
2889
+ { name: "Maven Pro", category: "Sans-Serif", local: false },
2890
+ { name: "Asap", category: "Sans-Serif", local: false },
2891
+ { name: "Asap Condensed", category: "Sans-Serif", local: false },
2892
+ { name: "Saira", category: "Sans-Serif", local: false },
2893
+ { name: "Saira Condensed", category: "Sans-Serif", local: false },
2894
+ { name: "Saira Semi Condensed", category: "Sans-Serif", local: false },
2895
+ { name: "Yanone Kaffeesatz", category: "Sans-Serif", local: false },
2896
+ { name: "Sarabun", category: "Sans-Serif", local: false },
2897
+ { name: "Prompt", category: "Sans-Serif", local: false },
2898
+ { name: "Kanit", category: "Sans-Serif", local: false, popular: true },
2899
+ { name: "Chivo", category: "Sans-Serif", local: false },
2900
+ { name: "Commissioner", category: "Sans-Serif", local: false },
2901
+ { name: "Inria Sans", category: "Sans-Serif", local: false },
2902
+ { name: "Tomorrow", category: "Sans-Serif", local: false },
2903
+ { name: "Catamaran", category: "Sans-Serif", local: false },
2904
+ { name: "Heebo", category: "Sans-Serif", local: false },
2905
+ { name: "Assistant", category: "Sans-Serif", local: false },
2906
+ { name: "Cairo", category: "Sans-Serif", local: false },
2907
+ { name: "Tajawal", category: "Sans-Serif", local: false },
2858
2908
  // ═══════════════════════════════════════════════════════════════════
2859
2909
  // DISPLAY — bold, attention-grabbing headlines
2860
2910
  // ═══════════════════════════════════════════════════════════════════
@@ -2909,6 +2959,12 @@ const EXTENDED_FONT_LIST = [
2909
2959
  { name: "Audiowide", category: "Display", local: false },
2910
2960
  { name: "Orbitron", category: "Display", local: false },
2911
2961
  { name: "Plaster", category: "Display", local: false },
2962
+ // ── Newly added display families ──
2963
+ { name: "Black Han Sans", category: "Display", local: false },
2964
+ { name: "Bungee Spice", category: "Display", local: false },
2965
+ { name: "Sansita Swashed", category: "Display", local: false },
2966
+ { name: "Honk", category: "Display", local: false },
2967
+ { name: "Sixtyfour", category: "Display", local: false },
2912
2968
  // ═══════════════════════════════════════════════════════════════════
2913
2969
  // HANDWRITING / SCRIPT — fluid, personal, calligraphic
2914
2970
  // ═══════════════════════════════════════════════════════════════════
@@ -2998,7 +3054,13 @@ const EXTENDED_FONT_LIST = [
2998
3054
  { name: "Cutive Mono", category: "Monospace", local: false },
2999
3055
  { name: "Major Mono Display", category: "Monospace", local: false },
3000
3056
  { name: "VT323", category: "Monospace", local: false },
3001
- { name: "Share Tech Mono", category: "Monospace", local: false }
3057
+ { name: "Share Tech Mono", category: "Monospace", local: false },
3058
+ // ── Newly added monospace families ──
3059
+ { name: "Ubuntu Mono", category: "Monospace", local: false, popular: true },
3060
+ { name: "Ubuntu Sans Mono", category: "Monospace", local: false },
3061
+ { name: "Noto Sans Mono", category: "Monospace", local: false },
3062
+ { name: "Martian Mono", category: "Monospace", local: false },
3063
+ { name: "Atkinson Hyperlegible Mono", category: "Monospace", local: false }
3002
3064
  ];
3003
3065
  const _fontLookupCache = /* @__PURE__ */ new Map();
3004
3066
  function findFontEntry(name) {
@@ -6224,6 +6286,87 @@ function parseTextMarkdown(input, themeColors) {
6224
6286
  }
6225
6287
  return { plainText: plain, styles, hasFormatting };
6226
6288
  }
6289
+ function angleToCoords(angleDeg) {
6290
+ const rad = angleDeg * Math.PI / 180;
6291
+ const x1 = 0.5 - Math.sin(rad) * 0.5;
6292
+ const y1 = 0.5 + Math.cos(rad) * 0.5;
6293
+ const x2 = 0.5 + Math.sin(rad) * 0.5;
6294
+ const y2 = 0.5 - Math.cos(rad) * 0.5;
6295
+ return { x1, y1, x2, y2 };
6296
+ }
6297
+ function normalizeGradientStops(stops) {
6298
+ const normalized = stops.map((stop) => ({
6299
+ color: stop.color,
6300
+ offset: Math.max(0, Math.min(1, Number(stop.offset) || 0))
6301
+ })).sort((a, b) => a.offset - b.offset);
6302
+ if (normalized.length === 0) return normalized;
6303
+ if (normalized[0].offset > 0) {
6304
+ normalized.unshift({ color: normalized[0].color, offset: 0 });
6305
+ }
6306
+ if (normalized[normalized.length - 1].offset < 1) {
6307
+ normalized.push({ color: normalized[normalized.length - 1].color, offset: 1 });
6308
+ }
6309
+ return normalized;
6310
+ }
6311
+ function gradientToFabric(gradient, width, height) {
6312
+ const colorStops = normalizeGradientStops(gradient.stops).map((s) => ({
6313
+ offset: s.offset,
6314
+ color: s.color
6315
+ }));
6316
+ if (gradient.type === "linear" || gradient.type === "conic") {
6317
+ const coords = angleToCoords(gradient.angle ?? 90);
6318
+ return new fabric__namespace.Gradient({
6319
+ type: "linear",
6320
+ coords: {
6321
+ x1: coords.x1 * width,
6322
+ y1: coords.y1 * height,
6323
+ x2: coords.x2 * width,
6324
+ y2: coords.y2 * height
6325
+ },
6326
+ colorStops
6327
+ });
6328
+ }
6329
+ const cx = (gradient.cx ?? 0.5) * width;
6330
+ const cy = (gradient.cy ?? 0.5) * height;
6331
+ const r = (gradient.r ?? 0.5) * Math.max(width, height);
6332
+ return new fabric__namespace.Gradient({
6333
+ type: "radial",
6334
+ coords: {
6335
+ x1: cx,
6336
+ y1: cy,
6337
+ r1: 0,
6338
+ x2: cx,
6339
+ y2: cy,
6340
+ r2: r
6341
+ },
6342
+ colorStops
6343
+ });
6344
+ }
6345
+ function applyInitialGradients(obj, element) {
6346
+ const w = typeof obj.width === "number" && obj.width > 0 ? obj.width : Number(element.width) || 0;
6347
+ const h = typeof obj.height === "number" && obj.height > 0 ? obj.height : Number(element.height) || 0;
6348
+ if (w <= 0 || h <= 0) return;
6349
+ const fg = element.fillGradient;
6350
+ if (fg && isGradientConfig(fg)) {
6351
+ try {
6352
+ obj.set({ fill: gradientToFabric(fg, w, h), objectCaching: false });
6353
+ obj.__lastFillGradientJson = JSON.stringify(fg);
6354
+ obj.dirty = true;
6355
+ } catch (e) {
6356
+ console.warn("[fabricObjectCreators] fillGradient apply failed:", e);
6357
+ }
6358
+ }
6359
+ const sg = element.strokeGradient;
6360
+ if (sg && isGradientConfig(sg)) {
6361
+ try {
6362
+ obj.set({ stroke: gradientToFabric(sg, w, h), objectCaching: false });
6363
+ obj.__lastStrokeGradientJson = JSON.stringify(sg);
6364
+ obj.dirty = true;
6365
+ } catch (e) {
6366
+ console.warn("[fabricObjectCreators] strokeGradient apply failed:", e);
6367
+ }
6368
+ }
6369
+ }
6227
6370
  const roundDiag = (value) => {
6228
6371
  if (typeof value !== "number") return value;
6229
6372
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -6623,6 +6766,9 @@ function createFabricObject(element) {
6623
6766
  flipY: element.flipY ?? false
6624
6767
  });
6625
6768
  setObjectData(obj, element.id);
6769
+ if (element.type === "shape" || element.type === "line" || element.type === "text") {
6770
+ applyInitialGradients(obj, element);
6771
+ }
6626
6772
  }
6627
6773
  return obj;
6628
6774
  }
@@ -6669,6 +6815,9 @@ function createFabricObjectForGroupMember(element) {
6669
6815
  flipY: element.flipY ?? false
6670
6816
  });
6671
6817
  setObjectData(obj, element.id);
6818
+ if (element.type === "shape" || element.type === "line" || element.type === "text") {
6819
+ applyInitialGradients(obj, element);
6820
+ }
6672
6821
  }
6673
6822
  return obj;
6674
6823
  }
@@ -7208,62 +7357,6 @@ function bakeEdgeFade(source, fade) {
7208
7357
  }
7209
7358
  return canvas;
7210
7359
  }
7211
- function angleToCoords(angleDeg) {
7212
- const rad = angleDeg * Math.PI / 180;
7213
- const x1 = 0.5 - Math.sin(rad) * 0.5;
7214
- const y1 = 0.5 + Math.cos(rad) * 0.5;
7215
- const x2 = 0.5 + Math.sin(rad) * 0.5;
7216
- const y2 = 0.5 - Math.cos(rad) * 0.5;
7217
- return { x1, y1, x2, y2 };
7218
- }
7219
- function normalizeGradientStops(stops) {
7220
- const normalized = stops.map((stop) => ({
7221
- color: stop.color,
7222
- offset: Math.max(0, Math.min(1, Number(stop.offset) || 0))
7223
- })).sort((a, b) => a.offset - b.offset);
7224
- if (normalized.length === 0) return normalized;
7225
- if (normalized[0].offset > 0) {
7226
- normalized.unshift({ color: normalized[0].color, offset: 0 });
7227
- }
7228
- if (normalized[normalized.length - 1].offset < 1) {
7229
- normalized.push({ color: normalized[normalized.length - 1].color, offset: 1 });
7230
- }
7231
- return normalized;
7232
- }
7233
- function gradientToFabric(gradient, width, height) {
7234
- const colorStops = normalizeGradientStops(gradient.stops).map((s) => ({
7235
- offset: s.offset,
7236
- color: s.color
7237
- }));
7238
- if (gradient.type === "linear" || gradient.type === "conic") {
7239
- const coords = angleToCoords(gradient.angle ?? 90);
7240
- return new fabric__namespace.Gradient({
7241
- type: "linear",
7242
- coords: {
7243
- x1: coords.x1 * width,
7244
- y1: coords.y1 * height,
7245
- x2: coords.x2 * width,
7246
- y2: coords.y2 * height
7247
- },
7248
- colorStops
7249
- });
7250
- }
7251
- const cx = (gradient.cx ?? 0.5) * width;
7252
- const cy = (gradient.cy ?? 0.5) * height;
7253
- const r = (gradient.r ?? 0.5) * Math.max(width, height);
7254
- return new fabric__namespace.Gradient({
7255
- type: "radial",
7256
- coords: {
7257
- x1: cx,
7258
- y1: cy,
7259
- r1: 0,
7260
- x2: cx,
7261
- y2: cy,
7262
- r2: r
7263
- },
7264
- colorStops
7265
- });
7266
- }
7267
7360
  const PageCanvas = react.forwardRef(
7268
7361
  ({
7269
7362
  pageId,
@@ -12019,6 +12112,59 @@ const DEFAULT_DATA_V2_VERSION = 2;
12019
12112
  function isDefaultDataV2(data) {
12020
12113
  return typeof data === "object" && data !== null && !Array.isArray(data) && data.version === DEFAULT_DATA_V2_VERSION && typeof data.sectionState === "object" && data.sectionState !== null;
12021
12114
  }
12115
+ function defaultSectionState(sections) {
12116
+ const state = {};
12117
+ const repeatables = sections.filter((s) => s.type === "repeatable");
12118
+ const childrenByParent = /* @__PURE__ */ new Map();
12119
+ for (const section of repeatables) {
12120
+ if (!section.parentId) continue;
12121
+ if (!childrenByParent.has(section.parentId)) childrenByParent.set(section.parentId, []);
12122
+ childrenByParent.get(section.parentId).push(section);
12123
+ }
12124
+ const createEmptyEntry = (section) => {
12125
+ const entry = {};
12126
+ for (const field of section.entryFields) {
12127
+ entry[field.key] = field.type === "list" ? [] : field.type === "toggle" ? "false" : "";
12128
+ }
12129
+ return entry;
12130
+ };
12131
+ const createInitialEntries = (section) => {
12132
+ const count = Math.max(0, section.initialEntryCount ?? 1);
12133
+ return Array.from({ length: count }, () => createEmptyEntry(section));
12134
+ };
12135
+ const seedNested = (parentSection, parentStateKey, parentEntryIndex) => {
12136
+ const children = childrenByParent.get(parentSection.id) ?? [];
12137
+ for (const child of children) {
12138
+ const childStateKey = `${parentStateKey}_${parentEntryIndex}_${child.id}`;
12139
+ const childEntries = createInitialEntries(child);
12140
+ state[childStateKey] = childEntries;
12141
+ childEntries.forEach((_, childEntryIndex) => seedNested(child, childStateKey, childEntryIndex));
12142
+ }
12143
+ };
12144
+ for (const section of sections) {
12145
+ if (section.type !== "single") continue;
12146
+ const obj = {};
12147
+ for (const f of section.fields) {
12148
+ obj[f.key] = f.type === "list" ? [] : f.type === "toggle" ? "false" : "";
12149
+ }
12150
+ state[section.id] = obj;
12151
+ }
12152
+ const topLevelRepeatables = repeatables.filter((s) => !s.parentId);
12153
+ for (const section of topLevelRepeatables) {
12154
+ const entries = createInitialEntries(section);
12155
+ state[section.id] = entries;
12156
+ entries.forEach((_, entryIndex) => seedNested(section, section.id, entryIndex));
12157
+ }
12158
+ const singleSectionIds = new Set(sections.filter((s) => s.type === "single").map((s) => s.id));
12159
+ for (const section of repeatables) {
12160
+ if (section.parentId && singleSectionIds.has(section.parentId)) {
12161
+ const entries = createInitialEntries(section);
12162
+ state[section.id] = entries;
12163
+ entries.forEach((_, entryIndex) => seedNested(section, section.id, entryIndex));
12164
+ }
12165
+ }
12166
+ return state;
12167
+ }
12022
12168
  function flattenSectionStateToFormData(sectionState, sections) {
12023
12169
  const flat = {};
12024
12170
  const repeatables = sections.filter((s) => s.type === "repeatable");
@@ -15769,6 +15915,74 @@ function paintRepeatableSections(config, repeatableSections) {
15769
15915
  }
15770
15916
  }
15771
15917
  }
15918
+ async function getTemplateForm(options) {
15919
+ var _a, _b;
15920
+ const { templateId, supabaseUrl, supabaseAnonKey } = options;
15921
+ if (!supabaseUrl || !supabaseAnonKey) {
15922
+ throw new Error("[getTemplateForm] supabaseUrl and supabaseAnonKey are required");
15923
+ }
15924
+ const templateRow = await fetchRow(supabaseUrl, supabaseAnonKey, "templates", templateId);
15925
+ const templateConfig = templateRow.config;
15926
+ const templateFormSchema = templateRow.form_schema;
15927
+ const boundFormSchemaId = options.formSchemaId ?? (typeof templateRow.form_schema_id === "string" ? templateRow.form_schema_id : null);
15928
+ if (templateFormSchema) {
15929
+ if (!Array.isArray(templateConfig.dynamicFields) && Array.isArray(templateFormSchema.dynamicFields)) {
15930
+ templateConfig.dynamicFields = templateFormSchema.dynamicFields;
15931
+ }
15932
+ if (!Array.isArray(templateConfig.fieldGroups) && Array.isArray(templateFormSchema.fieldGroups)) {
15933
+ templateConfig.fieldGroups = templateFormSchema.fieldGroups;
15934
+ }
15935
+ }
15936
+ let formSchema;
15937
+ let defaultForm = null;
15938
+ if (boundFormSchemaId) {
15939
+ const [schemaRow, defForm] = await Promise.all([
15940
+ fetchRow(supabaseUrl, supabaseAnonKey, "form_schemas", boundFormSchemaId).catch(() => null),
15941
+ fetchDefaultForm(supabaseUrl, supabaseAnonKey, boundFormSchemaId)
15942
+ ]);
15943
+ formSchema = schemaRow == null ? void 0 : schemaRow.schema;
15944
+ defaultForm = defForm;
15945
+ }
15946
+ const repeatableNodeMap = /* @__PURE__ */ new Map();
15947
+ const repeatableFromSchema = templateFormSchema == null ? void 0 : templateFormSchema.repeatableSections;
15948
+ if (repeatableFromSchema) {
15949
+ for (const r of repeatableFromSchema) {
15950
+ if (!repeatableNodeMap.has(r.label)) repeatableNodeMap.set(r.label, r.nodeId);
15951
+ const labelKey = r.label.trim().toLowerCase();
15952
+ if (!repeatableNodeMap.has(labelKey)) repeatableNodeMap.set(labelKey, r.nodeId);
15953
+ }
15954
+ }
15955
+ const schemaSections = getRenderableFormSections(formSchema);
15956
+ let sections;
15957
+ if (schemaSections == null ? void 0 : schemaSections.length) {
15958
+ sections = formDefSectionsToInferred(schemaSections, repeatableNodeMap);
15959
+ } else if ((_a = templateConfig.dynamicFields) == null ? void 0 : _a.length) {
15960
+ sections = inferFormSchemaFromTemplate(
15961
+ templateConfig.dynamicFields,
15962
+ templateConfig.fieldGroups || [],
15963
+ ((_b = templateConfig.pages) == null ? void 0 : _b.length) ? { pages: templateConfig.pages } : void 0
15964
+ );
15965
+ } else {
15966
+ sections = [];
15967
+ }
15968
+ const seeded = defaultSectionState(sections);
15969
+ const templateDefaultData = templateRow.default_data;
15970
+ let overlay = null;
15971
+ if (templateDefaultData && isDefaultDataV2(templateDefaultData)) {
15972
+ overlay = templateDefaultData.sectionState;
15973
+ } else {
15974
+ overlay = extractSectionStateCandidate(defaultForm == null ? void 0 : defaultForm.values, sections) ?? extractSectionStateCandidate(defaultForm == null ? void 0 : defaultForm.saved_data, sections) ?? null;
15975
+ }
15976
+ const initialSectionState = overlay ? { ...seeded, ...overlay } : seeded;
15977
+ return {
15978
+ templateId,
15979
+ templateName: templateRow.name || "Untitled",
15980
+ price: templateRow.price ?? 0,
15981
+ formSchemaId: boundFormSchemaId,
15982
+ sections,
15983
+ initialSectionState
15984
+ };
15985
+ }
15772
15986
  const PREVIEW_DEBUG_PREFIX = "[canvas-renderer][preview-debug]";
15773
15987
  function computeFontSignature(config) {
15774
15988
  var _a;
@@ -16135,9 +16349,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
16135
16349
  }
16136
16350
  return svgString;
16137
16351
  }
16138
- const resolvedPackageVersion = "0.5.171";
16352
+ const resolvedPackageVersion = "0.5.173";
16139
16353
  const PACKAGE_VERSION = resolvedPackageVersion;
16140
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.171";
16354
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.173";
16141
16355
  const roundParityValue = (value) => {
16142
16356
  if (typeof value !== "number") return value;
16143
16357
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -16571,6 +16785,7 @@ class PixldocsRenderer {
16571
16785
  * same fonts, same gradients, same draw order, same selectable text.
16572
16786
  */
16573
16787
  async renderPdfViaClientExport(templateConfig, options = {}) {
16788
+ var _a;
16574
16789
  await ensureFontsForResolvedConfig(templateConfig);
16575
16790
  const hasAutoShrink = configHasAutoShrinkText(templateConfig);
16576
16791
  await this.awaitFontsForConfig(templateConfig, hasAutoShrink ? 4e3 : 1800);
@@ -16635,7 +16850,7 @@ class PixldocsRenderer {
16635
16850
  await this.waitForCanvasScene(container, cloned, i);
16636
16851
  }
16637
16852
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
16638
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BrwXcGkA.cjs"));
16853
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BWDj55kq.cjs"));
16639
16854
  const prepared = preparePagesForExport(
16640
16855
  cloned.pages,
16641
16856
  canvasWidth,
@@ -16644,7 +16859,8 @@ class PixldocsRenderer {
16644
16859
  const result = await exportMultiPagePdf(prepared, {
16645
16860
  title: options.title,
16646
16861
  watermark: !!options.watermark,
16647
- returnBlob: true
16862
+ returnBlob: true,
16863
+ pdfTextMode: ((_a = cloned.canvas) == null ? void 0 : _a.n) ?? "selectable"
16648
16864
  });
16649
16865
  if (!result || typeof result === "undefined") {
16650
16866
  throw new Error("exportMultiPagePdf returned no blob (returnBlob path failed)");
@@ -18770,7 +18986,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18770
18986
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18771
18987
  sanitizeSvgTreeForPdf(svgToDraw);
18772
18988
  try {
18773
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BrwXcGkA.cjs"));
18989
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BWDj55kq.cjs"));
18774
18990
  try {
18775
18991
  await logTextMeasurementDiagnostic(svgToDraw);
18776
18992
  } catch {
@@ -18905,7 +19121,7 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
18905
19121
  }
18906
19122
  if (shouldOutlineText) {
18907
19123
  try {
18908
- const { convertAllTextToPath } = await Promise.resolve().then(() => require("./svgTextToPath-IM1f6F-f.cjs"));
19124
+ const { convertAllTextToPath } = await Promise.resolve().then(() => require("./svgTextToPath-BLk_mcqi.cjs"));
18909
19125
  pageSvg = await convertAllTextToPath(pageSvg, fontBaseUrl, { mode: outlineSubMode });
18910
19126
  try {
18911
19127
  dumpSvgTextDiagnostics(pageSvg, i, PARITY_TAG, "STAGE-1b-after-text-to-path-raw");
@@ -18917,6 +19133,16 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
18917
19133
  outlineErr
18918
19134
  );
18919
19135
  }
19136
+ } else {
19137
+ try {
19138
+ const { replaceGradientTextFillsWithFirstStop } = await Promise.resolve().then(() => require("./svgTextToPath-BLk_mcqi.cjs"));
19139
+ pageSvg = replaceGradientTextFillsWithFirstStop(pageSvg);
19140
+ } catch (gradErr) {
19141
+ console.warn(
19142
+ "[canvas-renderer][pdf] gradient-text fill resolution failed:",
19143
+ gradErr
19144
+ );
19145
+ }
18920
19146
  }
18921
19147
  let processedSvg = await prepareLiveCanvasSvgForPdf(pageSvg, page.width, page.height, `page-${i + 1}`, {
18922
19148
  stripPageBackground: shouldStripBg
@@ -19148,6 +19374,7 @@ exports.getImageProxyFetchOptions = getImageProxyFetchOptions;
19148
19374
  exports.getProxiedImageUrl = getProxiedImageUrl;
19149
19375
  exports.getPublishedTemplate = getPublishedTemplate;
19150
19376
  exports.getRoundedRectRadii = getRoundedRectRadii;
19377
+ exports.getTemplateForm = getTemplateForm;
19151
19378
  exports.getTrianglePoints = getTrianglePoints;
19152
19379
  exports.hasEdgeFade = hasEdgeFade;
19153
19380
  exports.isBundledAssetUrl = isBundledAssetUrl;
@@ -19169,4 +19396,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
19169
19396
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
19170
19397
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
19171
19398
  exports.warmTemplateFromForm = warmTemplateFromForm;
19172
- //# sourceMappingURL=index-BgOzEKmN.cjs.map
19399
+ //# sourceMappingURL=index-ZehEOqUB.cjs.map