@pixldocs/canvas-renderer 0.5.164 → 0.5.167

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 CHANGED
@@ -8,7 +8,85 @@ Client-side template renderer for Pixldocs — render templates in any web app w
8
8
  npm install @pixldocs/canvas-renderer fabric react react-dom
9
9
  ```
10
10
 
11
- > **Private package**: Add `//registry.npmjs.org/:_authToken=${NPM_TOKEN}` to your `.npmrc` and configure `NPM_TOKEN` as a build secret.
11
+ > Public package no auth token or `.npmrc` needed.
12
+
13
+ ---
14
+
15
+ ## Quick Start: Build an App From a Workspace
16
+
17
+ Got a Pixldocs workspace full of published templates (e.g. social-media posts,
18
+ invitations, certificates)? You can spin up a standalone app that lists and
19
+ renders them with just the **workspace ID** + Pixldocs anon key — no per-template
20
+ wiring needed.
21
+
22
+ ```tsx
23
+ import {
24
+ listPublishedTemplates,
25
+ PixldocsRenderer,
26
+ } from '@pixldocs/canvas-renderer';
27
+
28
+ const SUPABASE_URL = 'https://ttvtjhxjxuxdeybcnjkd.supabase.co';
29
+ const SUPABASE_ANON_KEY = 'eyJ...'; // Pixldocs publishable key (safe in browser)
30
+ const WORKSPACE_ID = 'your-workspace-uuid';
31
+
32
+ // 1. List all published templates owned by a workspace
33
+ const templates = await listPublishedTemplates({
34
+ workspaceId: WORKSPACE_ID,
35
+ supabaseUrl: SUPABASE_URL,
36
+ supabaseAnonKey: SUPABASE_ANON_KEY,
37
+ // category: 'social-media', // optional filter
38
+ });
39
+
40
+ // templates: [{ id, name, thumbnail_url, category, price, ... }, ...]
41
+
42
+ // 2. Render a chosen template (form-bound or static)
43
+ const renderer = new PixldocsRenderer({
44
+ supabaseUrl: SUPABASE_URL,
45
+ supabaseAnonKey: SUPABASE_ANON_KEY,
46
+ });
47
+
48
+ const pages = await renderer.renderFromForm({
49
+ templateId: templates[0].id,
50
+ sectionState: { /* user inputs (optional for static templates) */ },
51
+ });
52
+ ```
53
+
54
+ ### Two ways to source templates
55
+
56
+ | Approach | Best for | API |
57
+ |----------|----------|-----|
58
+ | **By workspace** | Multi-template apps (template gallery, social-media post maker, certificate maker) — pick from a curated workspace | `listPublishedTemplates({ workspaceId })` |
59
+ | **By form schema** | Single-purpose apps where one form drives many template variants (e.g. BioMaker — one form, many biodata designs) | Resolve directly via `renderFromForm({ templateId, formSchemaId, sectionState })` |
60
+
61
+ Both work with the same anon key and the same renderer — choose whichever
62
+ matches your product shape.
63
+
64
+ ---
65
+
66
+ ## Templates Catalog API
67
+
68
+ ### `listPublishedTemplates(options)`
69
+
70
+ Returns every published template belonging to a workspace. Uses public RLS
71
+ (no auth needed beyond the anon key).
72
+
73
+ ```ts
74
+ const templates = await listPublishedTemplates({
75
+ workspaceId: 'uuid',
76
+ supabaseUrl: '...',
77
+ supabaseAnonKey: '...',
78
+ category: 'social-media', // optional
79
+ limit: 200, // optional (default 200)
80
+ offset: 0, // optional pagination
81
+ });
82
+ ```
83
+
84
+ Each item: `{ id, name, description, category, thumbnail_url, preview_images, price, download_count, workspace_id, sort_order, created_at, updated_at }`.
85
+
86
+ ### `getPublishedTemplate({ templateId, supabaseUrl, supabaseAnonKey })`
87
+
88
+ Fetch a single published template's catalog row (without the heavy `config`
89
+ JSON — use the renderer for that).
12
90
 
13
91
  ---
14
92
 
@@ -12078,7 +12078,7 @@ function setInTree(nodes, elementId, targetProperty, value) {
12078
12078
  }
12079
12079
  if (targetProperty === "text" && node.type === "text") {
12080
12080
  const overflowPolicy = String(node.overflowPolicy ?? "grow-and-push");
12081
- if (overflowPolicy !== "auto-shrink" && typeof node.height !== "number") {
12081
+ if (overflowPolicy !== "auto-shrink") {
12082
12082
  delete node.height;
12083
12083
  }
12084
12084
  }
@@ -15605,7 +15605,7 @@ function normalizeConfigForEC2Parity(config) {
15605
15605
  if (isStack && node.stackSpacing == null) node.stackSpacing = 8;
15606
15606
  if (node.type === "text") {
15607
15607
  const overflowPolicy = String(node.overflowPolicy ?? "grow-and-push");
15608
- if (overflowPolicy !== "auto-shrink" && typeof node.height !== "number") {
15608
+ if (overflowPolicy !== "auto-shrink") {
15609
15609
  delete node.height;
15610
15610
  }
15611
15611
  }
@@ -16018,9 +16018,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
16018
16018
  }
16019
16019
  return svgString;
16020
16020
  }
16021
- const resolvedPackageVersion = "0.5.164";
16021
+ const resolvedPackageVersion = "0.5.167";
16022
16022
  const PACKAGE_VERSION = resolvedPackageVersion;
16023
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.164";
16023
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.167";
16024
16024
  const roundParityValue = (value) => {
16025
16025
  if (typeof value !== "number") return value;
16026
16026
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -16455,7 +16455,7 @@ class PixldocsRenderer {
16455
16455
  await this.waitForCanvasScene(container, cloned, i);
16456
16456
  }
16457
16457
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
16458
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-C-XaAhxd.js");
16458
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-Ce68BOFf.js");
16459
16459
  const prepared = preparePagesForExport(
16460
16460
  cloned.pages,
16461
16461
  canvasWidth,
@@ -18557,7 +18557,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18557
18557
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18558
18558
  sanitizeSvgTreeForPdf(svgToDraw);
18559
18559
  try {
18560
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-C-XaAhxd.js");
18560
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-Ce68BOFf.js");
18561
18561
  try {
18562
18562
  await logTextMeasurementDiagnostic(svgToDraw);
18563
18563
  } catch {
@@ -18763,6 +18763,56 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
18763
18763
  pages: svgResults.map((p) => ({ width: p.width, height: p.height }))
18764
18764
  };
18765
18765
  }
18766
+ const SELECT_COLUMNS = "id,name,description,category,thumbnail_url,preview_images,price,download_count,workspace_id,sort_order,created_at,updated_at";
18767
+ async function listPublishedTemplates(options) {
18768
+ const { workspaceId, supabaseUrl, supabaseAnonKey, category, limit = 200, offset = 0 } = options;
18769
+ if (!workspaceId) throw new Error("listPublishedTemplates: workspaceId is required");
18770
+ if (!supabaseUrl || !supabaseAnonKey) {
18771
+ throw new Error("listPublishedTemplates: supabaseUrl and supabaseAnonKey are required");
18772
+ }
18773
+ const params = new URLSearchParams({
18774
+ select: SELECT_COLUMNS,
18775
+ workspace_id: `eq.${workspaceId}`,
18776
+ status: "eq.published",
18777
+ order: "sort_order.asc,updated_at.desc",
18778
+ limit: String(limit),
18779
+ offset: String(offset)
18780
+ });
18781
+ if (category) params.set("category", `eq.${category}`);
18782
+ const url = `${supabaseUrl.replace(/\/$/, "")}/rest/v1/templates?${params.toString()}`;
18783
+ const res = await fetch(url, {
18784
+ headers: {
18785
+ apikey: supabaseAnonKey,
18786
+ Authorization: `Bearer ${supabaseAnonKey}`,
18787
+ Accept: "application/json"
18788
+ }
18789
+ });
18790
+ if (!res.ok) {
18791
+ const text = await res.text().catch(() => "");
18792
+ throw new Error(`listPublishedTemplates failed: ${res.status} ${text}`);
18793
+ }
18794
+ return await res.json();
18795
+ }
18796
+ async function getPublishedTemplate(options) {
18797
+ const { templateId, supabaseUrl, supabaseAnonKey } = options;
18798
+ const params = new URLSearchParams({
18799
+ select: SELECT_COLUMNS,
18800
+ id: `eq.${templateId}`,
18801
+ status: "eq.published",
18802
+ limit: "1"
18803
+ });
18804
+ const url = `${supabaseUrl.replace(/\/$/, "")}/rest/v1/templates?${params.toString()}`;
18805
+ const res = await fetch(url, {
18806
+ headers: {
18807
+ apikey: supabaseAnonKey,
18808
+ Authorization: `Bearer ${supabaseAnonKey}`,
18809
+ Accept: "application/json"
18810
+ }
18811
+ });
18812
+ if (!res.ok) return null;
18813
+ const rows = await res.json();
18814
+ return rows[0] ?? null;
18815
+ }
18766
18816
  function collectImageUrls(config) {
18767
18817
  const urls = [];
18768
18818
  const walk = (nodes) => {
@@ -18852,7 +18902,7 @@ function setAutoShrinkDebug(enabled) {
18852
18902
  }
18853
18903
  }
18854
18904
  export {
18855
- canvasImageLoader as $,
18905
+ warmResolvedTemplateForPreview as $,
18856
18906
  API_URL as A,
18857
18907
  collectImageUrls as B,
18858
18908
  configHasAutoShrinkText$1 as C,
@@ -18865,22 +18915,24 @@ export {
18865
18915
  ensureFontsForResolvedConfig as J,
18866
18916
  extractFontFamiliesFromSvgs as K,
18867
18917
  getEmbeddedJsPDFFontName as L,
18868
- isBundledAssetUrl as M,
18869
- isFontAvailable as N,
18870
- isPrivateUrl as O,
18918
+ getPublishedTemplate as M,
18919
+ isBundledAssetUrl as N,
18920
+ isFontAvailable as O,
18871
18921
  PACKAGE_VERSION as P,
18872
- loadGoogleFontCSS as Q,
18873
- normalizeFontFamily as R,
18874
- resolveFontWeight as S,
18922
+ isPrivateUrl as Q,
18923
+ listPublishedTemplates as R,
18924
+ loadGoogleFontCSS as S,
18875
18925
  TRIANGLE_STROKE_MITER_LIMIT as T,
18876
- resolveFromForm as U,
18877
- resolveTemplateData as V,
18878
- rewriteSvgFontsForJsPDF as W,
18879
- setAutoShrinkDebug as X,
18880
- setBundledAssetPrefixes as Y,
18881
- warmResolvedTemplateForPreview as Z,
18882
- warmTemplateFromForm as _,
18926
+ normalizeFontFamily as U,
18927
+ resolveFontWeight as V,
18928
+ resolveFromForm as W,
18929
+ resolveTemplateData as X,
18930
+ rewriteSvgFontsForJsPDF as Y,
18931
+ setAutoShrinkDebug as Z,
18932
+ setBundledAssetPrefixes as _,
18883
18933
  getAbsoluteBounds as a,
18934
+ warmTemplateFromForm as a0,
18935
+ canvasImageLoader as a1,
18884
18936
  getProxiedImageUrl as b,
18885
18937
  captureFabricCanvasSvgForPdf as c,
18886
18938
  bakeEdgeFade as d,
@@ -18907,4 +18959,4 @@ export {
18907
18959
  collectFontDescriptorsFromConfig as y,
18908
18960
  collectFontsFromConfig as z
18909
18961
  };
18910
- //# sourceMappingURL=index-Gj2Xgcsf.js.map
18962
+ //# sourceMappingURL=index-7Etfiz-e.js.map