@bluepic/embed 0.6.3 → 0.6.6

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.
@@ -76,6 +76,31 @@ export type ExportSessionContext = {
76
76
  * times the underlying data changed.
77
77
  */
78
78
  tabSessionId: string;
79
+ /**
80
+ * Canvases v2: the canvas the editor showed when Export was pressed (the
81
+ * export's PRIMARY canvas). Absent for single-format templates.
82
+ */
83
+ canvasId?: string;
84
+ /** Pixel size of the primary canvas (= the serial size for single-format templates). */
85
+ canvasWidth?: number;
86
+ canvasHeight?: number;
87
+ /** Formats the template offers. 1 = single-format; >= 2 = true multi-format template. */
88
+ availableCanvasCount: number;
89
+ };
90
+ /** One canvas (format) an output carried, with the files it produced (segments ⇒ > 1). */
91
+ export type DeliveredCanvas = {
92
+ id: string;
93
+ width: number;
94
+ height: number;
95
+ fileCount: number;
96
+ };
97
+ /**
98
+ * What an output (action / social step) actually delivered. One click is still
99
+ * ONE event — a multi-format export says here how many formats it carried.
100
+ */
101
+ export type DeliveryContext = {
102
+ deliveredCanvases?: DeliveredCanvas[];
103
+ deliveredCanvasCount?: number;
79
104
  };
80
105
  /**
81
106
  * Result of the render. Attached to every event emitted AFTER the render
@@ -105,7 +130,7 @@ export type RenderFailureEvent = ExportSessionContext & RenderOutcome & {
105
130
  error: string;
106
131
  };
107
132
  /** An actional destination ran (download / webhook / redirect). */
108
- export type ActionEvent = ExportSessionContext & RenderOutcome & {
133
+ export type ActionEvent = ExportSessionContext & RenderOutcome & DeliveryContext & {
109
134
  type: 'action';
110
135
  kind: ExportActionKind;
111
136
  trigger: ExportActionTrigger;
@@ -117,7 +142,7 @@ export type ActionEvent = ExportSessionContext & RenderOutcome & {
117
142
  redirectHost?: string;
118
143
  };
119
144
  /** User picked a social network — usually just opens its share dialog. */
120
- export type SocialAttemptEvent = ExportSessionContext & RenderOutcome & {
145
+ export type SocialAttemptEvent = ExportSessionContext & RenderOutcome & DeliveryContext & {
121
146
  type: 'social_attempt';
122
147
  platform: SocialPlatform;
123
148
  /** LinkedIn is verifiable (we get a real postUrl back); others aren't. */
@@ -126,7 +151,7 @@ export type SocialAttemptEvent = ExportSessionContext & RenderOutcome & {
126
151
  nativeShare: boolean;
127
152
  };
128
153
  /** The final social step: LinkedIn post confirmed, or platform handed off. */
129
- export type SocialCheckoutEvent = ExportSessionContext & RenderOutcome & {
154
+ export type SocialCheckoutEvent = ExportSessionContext & RenderOutcome & DeliveryContext & {
130
155
  type: 'social_checkout';
131
156
  platform: SocialPlatform;
132
157
  verifiable: boolean;
@@ -204,9 +229,17 @@ export declare class ExportAnalytics {
204
229
  private readonly sink?;
205
230
  private readonly session;
206
231
  private renderOutcome?;
232
+ private delivered?;
207
233
  constructor(sink: ExportAnalyticsSink | undefined, context: Omit<ExportSessionContext, 'exportId'>, exportId?: string);
208
234
  /** Render outcome folded into post-render events (falls back to `unknown`). */
209
235
  private outcome;
236
+ /**
237
+ * The canvases the NEXT outputs carry. Set by the export flow whenever the
238
+ * selection changes (the popup's format checkboxes), so every action / social
239
+ * event reports exactly what left the tab with it.
240
+ */
241
+ setDelivered(canvases: DeliveredCanvas[]): void;
242
+ private delivery;
210
243
  private emit;
211
244
  attempt(): void;
212
245
  renderSuccess(args: RenderSuccessArgs): void;
@@ -0,0 +1,7 @@
1
+ /** What a snapshot depends on besides the canvas itself. */
2
+ export declare function snapshotStamp(data: unknown, watermark: boolean): string;
3
+ /** The cached snapshot when it was rendered from exactly this stamp. */
4
+ export declare function cachedSnapshot(templateId: string, canvasId: string, stamp: string): string | undefined;
5
+ /** The latest snapshot regardless of stamp (a close stand-in while a fresh one renders). */
6
+ export declare function latestSnapshot(templateId: string, canvasId: string): string | undefined;
7
+ export declare function storeSnapshot(templateId: string, canvasId: string, stamp: string, blob: Blob): string;
@@ -0,0 +1,76 @@
1
+ import type { Template } from '@bluepic/types';
2
+ /**
3
+ * Multi-format templates (canvases v2) as the editor sees them.
4
+ *
5
+ * A canvases-v2 template is ONE template: fields, bindings and therefore the
6
+ * user's data are shared, only `{ context, fill }` and the size differ per
7
+ * canvas. That is what makes switching formats inside the editor — and
8
+ * exporting several formats from one data-state — safe. Legacy name-collision
9
+ * groups are distinct templates and never arrive here: the host passes
10
+ * `canvases` only for a true multi-format template (>= 2 canvases).
11
+ */
12
+ export type EditorCanvas = {
13
+ /** Opaque storage id (`default`, a nanoid, `legacy-<n>`) — what render requests address. */
14
+ id: string;
15
+ width: number;
16
+ height: number;
17
+ /** `x * y` separate graphics per render. Absent = `{1,1}`. */
18
+ segments?: {
19
+ x: number;
20
+ y: number;
21
+ };
22
+ /**
23
+ * Stand-in until the live snapshot exists: the canvas's committed server
24
+ * preview (generic, fast) …
25
+ */
26
+ preview?: string | null;
27
+ /**
28
+ * … with an already-ISSUED personalized server render on top when the page
29
+ * was prepopulated (`?p=` / `?data`). Never built from the user's edits —
30
+ * the live snapshot is the only thing that shows those.
31
+ */
32
+ personalizedPreview?: string | null;
33
+ /**
34
+ * The render-ready (materialized, root-shape) serial of THIS canvas. Called
35
+ * lazily (switcher opened / export pressed) and at most once per canvas.
36
+ */
37
+ loadSerial: () => Promise<Template.Serial>;
38
+ };
39
+ /** Every format picker labels a canvas by its size ("1080×1350"). */
40
+ export declare function canvasLabel(canvas: {
41
+ width: number;
42
+ height: number;
43
+ }): string;
44
+ /** File-name-safe size token ("1080x1350") — same form as the canvas route segment. */
45
+ export declare function canvasSizeToken(canvas: {
46
+ width: number;
47
+ height: number;
48
+ }): string;
49
+ /**
50
+ * Fit a canvas into a `max × max` box: the long side becomes `max`, the short
51
+ * side follows the aspect ratio (so it is always <= max).
52
+ */
53
+ export declare function fitCanvasBox(canvas: {
54
+ width: number;
55
+ height: number;
56
+ }, max?: number): {
57
+ width: number;
58
+ height: number;
59
+ };
60
+ /** What one canvas contributes to an export output. */
61
+ export type CanvasDeliverable = {
62
+ canvas: Pick<EditorCanvas, 'id' | 'width' | 'height'>;
63
+ files: Blob[];
64
+ };
65
+ /**
66
+ * File names for an export output.
67
+ *
68
+ * Exactly one canvas delivered → today's names, byte-identical (`<base>.png`,
69
+ * segments `<base>_1.png`, …): nothing changes for anyone who never ticks a
70
+ * second format. Several canvases → every file carries its size so the zip is
71
+ * self-explanatory: `<base>_1080x1350.png`, segments `<base>_1080x1350_1.png`.
72
+ */
73
+ export declare function deliverableFileNames(deliverables: CanvasDeliverable[], baseName: string): {
74
+ blob: Blob;
75
+ name: string;
76
+ }[];
@@ -3,6 +3,18 @@ import { Ref } from 'vue';
3
3
  import { z } from '@hono/zod-openapi';
4
4
  import BxLiveTemplate from '../components/TemplateEditor/BxLiveTemplate.vue';
5
5
  import { type ExportAnalyticsSink, type RenderLocation } from './analytics';
6
+ import { type CanvasDeliverable, type EditorCanvas } from './canvases';
7
+ /** What the export pipeline needs from the hidden sibling renderers (CanvasSiblings). */
8
+ export type CanvasSiblingsApi = {
9
+ activate: () => void;
10
+ demand: () => () => void;
11
+ renderer: (id: string) => Promise<{
12
+ live: InstanceType<typeof BxLiveTemplate>;
13
+ serial: Template.Serial;
14
+ }>;
15
+ snapshots: Record<string, string>;
16
+ snapshotFailed: Record<string, boolean>;
17
+ };
6
18
  export declare const imageFormats: {
7
19
  png: "image/png";
8
20
  jpeg: "image/jpeg";
@@ -50,7 +62,9 @@ canvasId?: string): Promise<{
50
62
  files: string[];
51
63
  creditsConsumed: number;
52
64
  }>;
53
- export declare function renderSerialAsImages(bxLiveTemplateComponent: InstanceType<typeof BxLiveTemplate>, serial: Template.Serial, data: {
65
+ export declare function renderSerialAsImages(
66
+ /** Undefined = no local renderer available → server render (addressed by `canvasId`). */
67
+ bxLiveTemplateComponent: InstanceType<typeof BxLiveTemplate> | undefined, serial: Template.Serial, data: {
54
68
  [k: string]: unknown;
55
69
  }, format: keyof typeof imageFormats, campaignId: number, templateId: string, remoteOptions: RenderRemoteOptions, enforceServerSideRendering: boolean, watermark: boolean, sessionState: string,
56
70
  /** Multi-canvas: the selected canvas — remote render only; the LOCAL path already renders the materialized `serial`. */
@@ -91,7 +105,14 @@ canvasId?: Ref<string | undefined>,
91
105
  * fonts/images. Kept host-settable precisely so that trade-off can be measured
92
106
  * rather than guessed.
93
107
  */
94
- svgLoadWaitDelay?: Ref<number | undefined>): {
108
+ svgLoadWaitDelay?: Ref<number | undefined>,
109
+ /**
110
+ * True multi-format templates (canvases v2, >= 2 canvases): every canvas of
111
+ * the template. Undefined / < 2 = single-format, today's behaviour exactly.
112
+ */
113
+ canvases?: Ref<EditorCanvas[] | undefined>,
114
+ /** Hidden live renderers of the sibling canvases (see CanvasSiblings). */
115
+ siblings?: Ref<CanvasSiblingsApi | undefined>): {
95
116
  triggerExport: () => Promise<void>;
96
117
  consumeOutputFor: (rowData: {
97
118
  [k: string]: unknown;
@@ -114,15 +135,32 @@ usage?: Studio.ConsumeRenderCreditsUsage,
114
135
  assets?: BillingV3.BillableUsageAsset[]): Promise<void>;
115
136
  export declare function hasMobileShareCapability(files: File[]): boolean;
116
137
  export declare function blobsToShareFiles(files: Blob[], baseName: string): File[];
138
+ export declare function namedToShareFiles(named: {
139
+ blob: Blob;
140
+ name: string;
141
+ }[]): File[];
117
142
  export declare function performDownload(files: Blob[], baseName: string): Promise<void>;
143
+ /** Download what an export delivered — every canvas, named (see `deliverableFileNames`). */
144
+ export declare function performDeliverablesDownload(deliverables: CanvasDeliverable[], baseName: string): Promise<void>;
118
145
  export type ActionContext = {
119
146
  templateId: string;
120
147
  campaignId: number;
121
148
  data: {
122
149
  [k: string]: unknown;
123
150
  };
151
+ /** Every delivered file, flat (all canvases, in canvas order). */
124
152
  assets: string[];
125
153
  caption?: string;
154
+ /**
155
+ * Multi-format exports only: the same assets grouped by canvas. Absent for a
156
+ * single-format export, so that payload stays exactly what it was.
157
+ */
158
+ canvases?: {
159
+ canvasId: string;
160
+ width: number;
161
+ height: number;
162
+ assets: string[];
163
+ }[];
126
164
  };
127
165
  export declare function performWebhook(webhookUrl: string, context: ActionContext): Promise<void>;
128
166
  export declare function performRedirect(redirectUrl: string, context: ActionContext): Promise<void>;
@@ -0,0 +1,58 @@
1
+ import { type ComputedRef } from 'vue';
2
+ import type { EditorCanvas, CanvasDeliverable } from './canvases';
3
+ import type { DeliveredCanvas } from './analytics';
4
+ /**
5
+ * One export press of a true multi-format template, as the export popup sees it.
6
+ *
7
+ * The press renders the ACTIVE canvas (exactly as before); the popup then shows
8
+ * every other canvas next to it, greyed out until ticked. A ticked sibling is
9
+ * rendered from the same data-state (local first, server fallback — the same
10
+ * path as the active one), and every output action (download / share / webhook
11
+ * / redirect) delivers the ticked set. Billing is per delivered canvas.
12
+ *
13
+ * Built by `useTemplateExport`, which owns rendering, uploading and billing;
14
+ * this object only holds the per-press state and the selection rules.
15
+ */
16
+ export type CanvasExportItemState = 'idle' | 'rendering' | 'ready' | 'error';
17
+ export type CanvasExportItem = {
18
+ canvas: EditorCanvas;
19
+ /** The canvas the editor showed when Export was pressed. Rendered up-front. */
20
+ primary: boolean;
21
+ selected: boolean;
22
+ state: CanvasExportItemState;
23
+ error?: string;
24
+ files: Blob[];
25
+ };
26
+ export type MultiCanvasExportDeps = {
27
+ canvases: EditorCanvas[];
28
+ primaryCanvasId: string;
29
+ primaryFiles: Blob[];
30
+ /** The primary's uploads, if the export already started them. */
31
+ primaryRemote?: Promise<string>[];
32
+ /** Full-resolution render of a sibling canvas with the export's data-state. */
33
+ renderCanvas: (canvas: EditorCanvas) => Promise<Blob[]>;
34
+ /** Upload a canvas's files for URL consumers (webhook / redirect / socials). */
35
+ upload: (files: Blob[]) => Promise<string>[];
36
+ /** Per-canvas output consumer (idempotent per session + data-state + canvas). */
37
+ consume: (canvas: EditorCanvas) => Promise<void>;
38
+ /**
39
+ * Render siblings in the background as soon as the popup opens, so ticking
40
+ * is instant. True for formats that render locally (cheap, never billed);
41
+ * false for server-side formats, which render only when ticked.
42
+ */
43
+ prerender: boolean;
44
+ /** Called whenever the delivered set changes (analytics). */
45
+ onSelectionChange?: (delivered: DeliveredCanvas[]) => void;
46
+ };
47
+ export type MultiCanvasExport = ReturnType<typeof createMultiCanvasExport>;
48
+ export declare function createMultiCanvasExport(deps: MultiCanvasExportDeps): {
49
+ items: import("vue").Reactive<CanvasExportItem[]>;
50
+ selected: ComputedRef<CanvasExportItem[]>;
51
+ busy: ComputedRef<boolean>;
52
+ setSelected: (id: string, value: boolean) => void;
53
+ prerenderAll: () => Promise<void>;
54
+ deliverables: () => Promise<CanvasDeliverable[]>;
55
+ remote: (deliverable: CanvasDeliverable) => Promise<string>[];
56
+ consume: (deliverablesList: CanvasDeliverable[]) => Promise<void>;
57
+ delivered: () => DeliveredCanvas[];
58
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bluepic/embed",
3
- "version": "0.6.3",
3
+ "version": "0.6.6",
4
4
  "description": "Bluepic embed sdk",
5
5
  "type": "module",
6
6
  "sideEffects": false,