@pixldocs/canvas-renderer 0.5.172 → 0.5.174

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.
@@ -2782,6 +2782,19 @@ const EXTENDED_FONT_LIST = [
2782
2782
  { name: "Petrona", category: "Serif", local: false },
2783
2783
  { name: "Rozha One", category: "Serif", local: false },
2784
2784
  { name: "Tiro Devanagari Hindi", category: "Serif", local: false },
2785
+ // ── Newly added popular serif families ──
2786
+ { name: "Roboto Serif", category: "Serif", local: false, popular: true },
2787
+ { name: "Roboto Slab", category: "Serif", local: false, popular: true },
2788
+ { name: "Inria Serif", category: "Serif", local: false },
2789
+ { name: "Instrument Serif", category: "Serif", local: false, popular: true },
2790
+ { name: "Young Serif", category: "Serif", local: false },
2791
+ { name: "Gloock", category: "Serif", local: false },
2792
+ { name: "Castoro", category: "Serif", local: false },
2793
+ { name: "Source Serif 4", category: "Serif", local: false },
2794
+ { name: "IBM Plex Serif", category: "Serif", local: false },
2795
+ { name: "Pridi", category: "Serif", local: false },
2796
+ { name: "Eczar", category: "Serif", local: false },
2797
+ { name: "Faustina", category: "Serif", local: false },
2785
2798
  // ═══════════════════════════════════════════════════════════════════
2786
2799
  // SANS-SERIF — clean, modern, workhorse
2787
2800
  // ═══════════════════════════════════════════════════════════════════
@@ -2837,6 +2850,43 @@ const EXTENDED_FONT_LIST = [
2837
2850
  { name: "Anek Devanagari", category: "Sans-Serif", local: false },
2838
2851
  { name: "Hind", category: "Sans-Serif", local: true },
2839
2852
  { name: "Hind Vadodara", category: "Sans-Serif", local: false },
2853
+ // ── Newly added popular sans-serif families (Google Fonts; loaded on demand) ──
2854
+ { name: "Ubuntu", category: "Sans-Serif", local: false, popular: true },
2855
+ { name: "Ubuntu Condensed", category: "Sans-Serif", local: false },
2856
+ { name: "Ubuntu Sans", category: "Sans-Serif", local: false },
2857
+ { name: "Roboto Condensed", category: "Sans-Serif", local: false, popular: true },
2858
+ { name: "Roboto Flex", category: "Sans-Serif", local: false },
2859
+ { name: "Jost", category: "Sans-Serif", local: false, popular: true },
2860
+ { name: "Inter Tight", category: "Sans-Serif", local: false },
2861
+ { name: "Mona Sans", category: "Sans-Serif", local: false },
2862
+ { name: "Hubot Sans", category: "Sans-Serif", local: false },
2863
+ { name: "Funnel Sans", category: "Sans-Serif", local: false },
2864
+ { name: "Funnel Display", category: "Sans-Serif", local: false },
2865
+ { name: "Geologica", category: "Sans-Serif", local: false },
2866
+ { name: "Bricolage Grotesque", category: "Sans-Serif", local: false, popular: true },
2867
+ { name: "Familjen Grotesk", category: "Sans-Serif", local: false },
2868
+ { name: "Wix Madefor Display", category: "Sans-Serif", local: false },
2869
+ { name: "Wix Madefor Text", category: "Sans-Serif", local: false },
2870
+ { name: "Atkinson Hyperlegible", category: "Sans-Serif", local: false },
2871
+ { name: "Maven Pro", category: "Sans-Serif", local: false },
2872
+ { name: "Asap", category: "Sans-Serif", local: false },
2873
+ { name: "Asap Condensed", category: "Sans-Serif", local: false },
2874
+ { name: "Saira", category: "Sans-Serif", local: false },
2875
+ { name: "Saira Condensed", category: "Sans-Serif", local: false },
2876
+ { name: "Saira Semi Condensed", category: "Sans-Serif", local: false },
2877
+ { name: "Yanone Kaffeesatz", category: "Sans-Serif", local: false },
2878
+ { name: "Sarabun", category: "Sans-Serif", local: false },
2879
+ { name: "Prompt", category: "Sans-Serif", local: false },
2880
+ { name: "Kanit", category: "Sans-Serif", local: false, popular: true },
2881
+ { name: "Chivo", category: "Sans-Serif", local: false },
2882
+ { name: "Commissioner", category: "Sans-Serif", local: false },
2883
+ { name: "Inria Sans", category: "Sans-Serif", local: false },
2884
+ { name: "Tomorrow", category: "Sans-Serif", local: false },
2885
+ { name: "Catamaran", category: "Sans-Serif", local: false },
2886
+ { name: "Heebo", category: "Sans-Serif", local: false },
2887
+ { name: "Assistant", category: "Sans-Serif", local: false },
2888
+ { name: "Cairo", category: "Sans-Serif", local: false },
2889
+ { name: "Tajawal", category: "Sans-Serif", local: false },
2840
2890
  // ═══════════════════════════════════════════════════════════════════
2841
2891
  // DISPLAY — bold, attention-grabbing headlines
2842
2892
  // ═══════════════════════════════════════════════════════════════════
@@ -2891,6 +2941,12 @@ const EXTENDED_FONT_LIST = [
2891
2941
  { name: "Audiowide", category: "Display", local: false },
2892
2942
  { name: "Orbitron", category: "Display", local: false },
2893
2943
  { name: "Plaster", category: "Display", local: false },
2944
+ // ── Newly added display families ──
2945
+ { name: "Black Han Sans", category: "Display", local: false },
2946
+ { name: "Bungee Spice", category: "Display", local: false },
2947
+ { name: "Sansita Swashed", category: "Display", local: false },
2948
+ { name: "Honk", category: "Display", local: false },
2949
+ { name: "Sixtyfour", category: "Display", local: false },
2894
2950
  // ═══════════════════════════════════════════════════════════════════
2895
2951
  // HANDWRITING / SCRIPT — fluid, personal, calligraphic
2896
2952
  // ═══════════════════════════════════════════════════════════════════
@@ -2980,7 +3036,13 @@ const EXTENDED_FONT_LIST = [
2980
3036
  { name: "Cutive Mono", category: "Monospace", local: false },
2981
3037
  { name: "Major Mono Display", category: "Monospace", local: false },
2982
3038
  { name: "VT323", category: "Monospace", local: false },
2983
- { name: "Share Tech Mono", category: "Monospace", local: false }
3039
+ { name: "Share Tech Mono", category: "Monospace", local: false },
3040
+ // ── Newly added monospace families ──
3041
+ { name: "Ubuntu Mono", category: "Monospace", local: false, popular: true },
3042
+ { name: "Ubuntu Sans Mono", category: "Monospace", local: false },
3043
+ { name: "Noto Sans Mono", category: "Monospace", local: false },
3044
+ { name: "Martian Mono", category: "Monospace", local: false },
3045
+ { name: "Atkinson Hyperlegible Mono", category: "Monospace", local: false }
2984
3046
  ];
2985
3047
  const _fontLookupCache = /* @__PURE__ */ new Map();
2986
3048
  function findFontEntry(name) {
@@ -6206,6 +6268,87 @@ function parseTextMarkdown(input, themeColors) {
6206
6268
  }
6207
6269
  return { plainText: plain, styles, hasFormatting };
6208
6270
  }
6271
+ function angleToCoords(angleDeg) {
6272
+ const rad = angleDeg * Math.PI / 180;
6273
+ const x1 = 0.5 - Math.sin(rad) * 0.5;
6274
+ const y1 = 0.5 + Math.cos(rad) * 0.5;
6275
+ const x2 = 0.5 + Math.sin(rad) * 0.5;
6276
+ const y2 = 0.5 - Math.cos(rad) * 0.5;
6277
+ return { x1, y1, x2, y2 };
6278
+ }
6279
+ function normalizeGradientStops(stops) {
6280
+ const normalized = stops.map((stop) => ({
6281
+ color: stop.color,
6282
+ offset: Math.max(0, Math.min(1, Number(stop.offset) || 0))
6283
+ })).sort((a, b) => a.offset - b.offset);
6284
+ if (normalized.length === 0) return normalized;
6285
+ if (normalized[0].offset > 0) {
6286
+ normalized.unshift({ color: normalized[0].color, offset: 0 });
6287
+ }
6288
+ if (normalized[normalized.length - 1].offset < 1) {
6289
+ normalized.push({ color: normalized[normalized.length - 1].color, offset: 1 });
6290
+ }
6291
+ return normalized;
6292
+ }
6293
+ function gradientToFabric(gradient, width, height) {
6294
+ const colorStops = normalizeGradientStops(gradient.stops).map((s) => ({
6295
+ offset: s.offset,
6296
+ color: s.color
6297
+ }));
6298
+ if (gradient.type === "linear" || gradient.type === "conic") {
6299
+ const coords = angleToCoords(gradient.angle ?? 90);
6300
+ return new fabric.Gradient({
6301
+ type: "linear",
6302
+ coords: {
6303
+ x1: coords.x1 * width,
6304
+ y1: coords.y1 * height,
6305
+ x2: coords.x2 * width,
6306
+ y2: coords.y2 * height
6307
+ },
6308
+ colorStops
6309
+ });
6310
+ }
6311
+ const cx = (gradient.cx ?? 0.5) * width;
6312
+ const cy = (gradient.cy ?? 0.5) * height;
6313
+ const r = (gradient.r ?? 0.5) * Math.max(width, height);
6314
+ return new fabric.Gradient({
6315
+ type: "radial",
6316
+ coords: {
6317
+ x1: cx,
6318
+ y1: cy,
6319
+ r1: 0,
6320
+ x2: cx,
6321
+ y2: cy,
6322
+ r2: r
6323
+ },
6324
+ colorStops
6325
+ });
6326
+ }
6327
+ function applyInitialGradients(obj, element) {
6328
+ const w = typeof obj.width === "number" && obj.width > 0 ? obj.width : Number(element.width) || 0;
6329
+ const h = typeof obj.height === "number" && obj.height > 0 ? obj.height : Number(element.height) || 0;
6330
+ if (w <= 0 || h <= 0) return;
6331
+ const fg = element.fillGradient;
6332
+ if (fg && isGradientConfig(fg)) {
6333
+ try {
6334
+ obj.set({ fill: gradientToFabric(fg, w, h), objectCaching: false });
6335
+ obj.__lastFillGradientJson = JSON.stringify(fg);
6336
+ obj.dirty = true;
6337
+ } catch (e) {
6338
+ console.warn("[fabricObjectCreators] fillGradient apply failed:", e);
6339
+ }
6340
+ }
6341
+ const sg = element.strokeGradient;
6342
+ if (sg && isGradientConfig(sg)) {
6343
+ try {
6344
+ obj.set({ stroke: gradientToFabric(sg, w, h), objectCaching: false });
6345
+ obj.__lastStrokeGradientJson = JSON.stringify(sg);
6346
+ obj.dirty = true;
6347
+ } catch (e) {
6348
+ console.warn("[fabricObjectCreators] strokeGradient apply failed:", e);
6349
+ }
6350
+ }
6351
+ }
6209
6352
  const roundDiag = (value) => {
6210
6353
  if (typeof value !== "number") return value;
6211
6354
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -6605,6 +6748,9 @@ function createFabricObject(element) {
6605
6748
  flipY: element.flipY ?? false
6606
6749
  });
6607
6750
  setObjectData(obj, element.id);
6751
+ if (element.type === "shape" || element.type === "line" || element.type === "text") {
6752
+ applyInitialGradients(obj, element);
6753
+ }
6608
6754
  }
6609
6755
  return obj;
6610
6756
  }
@@ -6651,6 +6797,9 @@ function createFabricObjectForGroupMember(element) {
6651
6797
  flipY: element.flipY ?? false
6652
6798
  });
6653
6799
  setObjectData(obj, element.id);
6800
+ if (element.type === "shape" || element.type === "line" || element.type === "text") {
6801
+ applyInitialGradients(obj, element);
6802
+ }
6654
6803
  }
6655
6804
  return obj;
6656
6805
  }
@@ -7190,62 +7339,6 @@ function bakeEdgeFade(source, fade) {
7190
7339
  }
7191
7340
  return canvas;
7192
7341
  }
7193
- function angleToCoords(angleDeg) {
7194
- const rad = angleDeg * Math.PI / 180;
7195
- const x1 = 0.5 - Math.sin(rad) * 0.5;
7196
- const y1 = 0.5 + Math.cos(rad) * 0.5;
7197
- const x2 = 0.5 + Math.sin(rad) * 0.5;
7198
- const y2 = 0.5 - Math.cos(rad) * 0.5;
7199
- return { x1, y1, x2, y2 };
7200
- }
7201
- function normalizeGradientStops(stops) {
7202
- const normalized = stops.map((stop) => ({
7203
- color: stop.color,
7204
- offset: Math.max(0, Math.min(1, Number(stop.offset) || 0))
7205
- })).sort((a, b) => a.offset - b.offset);
7206
- if (normalized.length === 0) return normalized;
7207
- if (normalized[0].offset > 0) {
7208
- normalized.unshift({ color: normalized[0].color, offset: 0 });
7209
- }
7210
- if (normalized[normalized.length - 1].offset < 1) {
7211
- normalized.push({ color: normalized[normalized.length - 1].color, offset: 1 });
7212
- }
7213
- return normalized;
7214
- }
7215
- function gradientToFabric(gradient, width, height) {
7216
- const colorStops = normalizeGradientStops(gradient.stops).map((s) => ({
7217
- offset: s.offset,
7218
- color: s.color
7219
- }));
7220
- if (gradient.type === "linear" || gradient.type === "conic") {
7221
- const coords = angleToCoords(gradient.angle ?? 90);
7222
- return new fabric.Gradient({
7223
- type: "linear",
7224
- coords: {
7225
- x1: coords.x1 * width,
7226
- y1: coords.y1 * height,
7227
- x2: coords.x2 * width,
7228
- y2: coords.y2 * height
7229
- },
7230
- colorStops
7231
- });
7232
- }
7233
- const cx = (gradient.cx ?? 0.5) * width;
7234
- const cy = (gradient.cy ?? 0.5) * height;
7235
- const r = (gradient.r ?? 0.5) * Math.max(width, height);
7236
- return new fabric.Gradient({
7237
- type: "radial",
7238
- coords: {
7239
- x1: cx,
7240
- y1: cy,
7241
- r1: 0,
7242
- x2: cx,
7243
- y2: cy,
7244
- r2: r
7245
- },
7246
- colorStops
7247
- });
7248
- }
7249
7342
  const PageCanvas = forwardRef(
7250
7343
  ({
7251
7344
  pageId,
@@ -16238,9 +16331,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
16238
16331
  }
16239
16332
  return svgString;
16240
16333
  }
16241
- const resolvedPackageVersion = "0.5.172";
16334
+ const resolvedPackageVersion = "0.5.174";
16242
16335
  const PACKAGE_VERSION = resolvedPackageVersion;
16243
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.172";
16336
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.174";
16244
16337
  const roundParityValue = (value) => {
16245
16338
  if (typeof value !== "number") return value;
16246
16339
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -16614,7 +16707,8 @@ class PixldocsRenderer {
16614
16707
  */
16615
16708
  async renderPdf(templateConfig, options) {
16616
16709
  return this.renderPdfViaClientExport(templateConfig, {
16617
- title: options == null ? void 0 : options.title
16710
+ title: options == null ? void 0 : options.title,
16711
+ textMode: options == null ? void 0 : options.textMode
16618
16712
  });
16619
16713
  }
16620
16714
  /**
@@ -16622,7 +16716,7 @@ class PixldocsRenderer {
16622
16716
  * This is the primary PDF export API — mirrors renderFromForm() but returns a PDF.
16623
16717
  */
16624
16718
  async renderPdfFromForm(options) {
16625
- const { templateId, formSchemaId, sectionState, themeId, watermark, watermarkOptions, prefetched, title, fontBaseUrl } = options;
16719
+ const { templateId, formSchemaId, sectionState, themeId, watermark, watermarkOptions, prefetched, title, fontBaseUrl, textMode } = options;
16626
16720
  const resolved = await resolveFromForm({
16627
16721
  templateId,
16628
16722
  formSchemaId,
@@ -16640,7 +16734,8 @@ class PixldocsRenderer {
16640
16734
  }
16641
16735
  return this.renderPdfViaClientExport(configToRender, {
16642
16736
  title: title ?? resolved.config.name,
16643
- watermark: shouldWatermark
16737
+ watermark: shouldWatermark,
16738
+ textMode
16644
16739
  });
16645
16740
  }
16646
16741
  async renderById(templateId, formData, options) {
@@ -16674,6 +16769,7 @@ class PixldocsRenderer {
16674
16769
  * same fonts, same gradients, same draw order, same selectable text.
16675
16770
  */
16676
16771
  async renderPdfViaClientExport(templateConfig, options = {}) {
16772
+ var _a;
16677
16773
  await ensureFontsForResolvedConfig(templateConfig);
16678
16774
  const hasAutoShrink = configHasAutoShrinkText(templateConfig);
16679
16775
  await this.awaitFontsForConfig(templateConfig, hasAutoShrink ? 4e3 : 1800);
@@ -16738,7 +16834,7 @@ class PixldocsRenderer {
16738
16834
  await this.waitForCanvasScene(container, cloned, i);
16739
16835
  }
16740
16836
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
16741
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-wH2x4QIj.js");
16837
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-B4B0CPjW.js");
16742
16838
  const prepared = preparePagesForExport(
16743
16839
  cloned.pages,
16744
16840
  canvasWidth,
@@ -16747,7 +16843,8 @@ class PixldocsRenderer {
16747
16843
  const result = await exportMultiPagePdf(prepared, {
16748
16844
  title: options.title,
16749
16845
  watermark: !!options.watermark,
16750
- returnBlob: true
16846
+ returnBlob: true,
16847
+ pdfTextMode: options.textMode ?? (cloned == null ? void 0 : cloned.pdfTextMode) ?? ((_a = cloned.canvas) == null ? void 0 : _a.n) ?? "auto"
16751
16848
  });
16752
16849
  if (!result || typeof result === "undefined") {
16753
16850
  throw new Error("exportMultiPagePdf returned no blob (returnBlob path failed)");
@@ -18873,7 +18970,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18873
18970
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18874
18971
  sanitizeSvgTreeForPdf(svgToDraw);
18875
18972
  try {
18876
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-wH2x4QIj.js");
18973
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-B4B0CPjW.js");
18877
18974
  try {
18878
18975
  await logTextMeasurementDiagnostic(svgToDraw);
18879
18976
  } catch {
@@ -19008,7 +19105,7 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
19008
19105
  }
19009
19106
  if (shouldOutlineText) {
19010
19107
  try {
19011
- const { convertAllTextToPath } = await import("./svgTextToPath-BXAzwaaR.js");
19108
+ const { convertAllTextToPath } = await import("./svgTextToPath-ra4EhtBL.js");
19012
19109
  pageSvg = await convertAllTextToPath(pageSvg, fontBaseUrl, { mode: outlineSubMode });
19013
19110
  try {
19014
19111
  dumpSvgTextDiagnostics(pageSvg, i, PARITY_TAG, "STAGE-1b-after-text-to-path-raw");
@@ -19020,6 +19117,16 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
19020
19117
  outlineErr
19021
19118
  );
19022
19119
  }
19120
+ } else {
19121
+ try {
19122
+ const { replaceGradientTextFillsWithFirstStop } = await import("./svgTextToPath-ra4EhtBL.js");
19123
+ pageSvg = replaceGradientTextFillsWithFirstStop(pageSvg);
19124
+ } catch (gradErr) {
19125
+ console.warn(
19126
+ "[canvas-renderer][pdf] gradient-text fill resolution failed:",
19127
+ gradErr
19128
+ );
19129
+ }
19023
19130
  }
19024
19131
  let processedSvg = await prepareLiveCanvasSvgForPdf(pageSvg, page.width, page.height, `page-${i + 1}`, {
19025
19132
  stripPageBackground: shouldStripBg
@@ -19276,4 +19383,4 @@ export {
19276
19383
  collectFontDescriptorsFromConfig as y,
19277
19384
  collectFontsFromConfig as z
19278
19385
  };
19279
- //# sourceMappingURL=index-DuI8QJDd.js.map
19386
+ //# sourceMappingURL=index-DLAkGTqW.js.map