@overtone-art/canvas-editor-core 0.2.8 → 0.3.0
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/dist/{chunk-ORZZ6MGQ.mjs → chunk-MCBRZQ4M.mjs} +34 -1
- package/dist/chunk-MCBRZQ4M.mjs.map +1 -0
- package/dist/index.d.mts +172 -4
- package/dist/index.d.ts +172 -4
- package/dist/index.global.js +67 -67
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +710 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +644 -22
- package/dist/index.mjs.map +1 -1
- package/dist/node.d.mts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js.map +1 -1
- package/dist/node.mjs +1 -1
- package/dist/{types-D60CfxL9.d.mts → types-Dh1unrzT.d.mts} +28 -1
- package/dist/{types-D60CfxL9.d.ts → types-Dh1unrzT.d.ts} +28 -1
- package/package.json +6 -4
- package/dist/chunk-ORZZ6MGQ.mjs.map +0 -1
|
@@ -106,6 +106,38 @@ async function exportIsolatedPNG(source, objects, options = {}) {
|
|
|
106
106
|
canvas.dispose();
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
+
async function exportPrintArea(source, area, options = {}) {
|
|
110
|
+
const { multiplier = 1, format = "png", quality = 1 } = options;
|
|
111
|
+
const width = source.getWidth();
|
|
112
|
+
const height = source.getHeight();
|
|
113
|
+
const clip = computePrintAreaClip(
|
|
114
|
+
area,
|
|
115
|
+
multiplier,
|
|
116
|
+
multiplier,
|
|
117
|
+
width * multiplier,
|
|
118
|
+
height * multiplier
|
|
119
|
+
);
|
|
120
|
+
if (clip.width <= 0 || clip.height <= 0) {
|
|
121
|
+
throw new Error("Print area does not overlap the canvas");
|
|
122
|
+
}
|
|
123
|
+
const element = source.lowerCanvasEl.ownerDocument.createElement("canvas");
|
|
124
|
+
const canvas = new StaticCanvas(element, { width, height });
|
|
125
|
+
try {
|
|
126
|
+
const clones = await Promise.all(source.getObjects().map((object) => object.clone()));
|
|
127
|
+
if (clones.length) canvas.add(...clones);
|
|
128
|
+
canvas.requestRenderAll();
|
|
129
|
+
const rendered = canvas.toCanvasElement(multiplier);
|
|
130
|
+
const output = rendered.ownerDocument.createElement("canvas");
|
|
131
|
+
output.width = Math.max(1, Math.round(clip.width));
|
|
132
|
+
output.height = Math.max(1, Math.round(clip.height));
|
|
133
|
+
const context = output.getContext("2d");
|
|
134
|
+
if (!context) throw new Error("2D canvas context is unavailable");
|
|
135
|
+
context.drawImage(rendered, -clip.left, -clip.top);
|
|
136
|
+
return await canvasElementToBlob(output, format, quality);
|
|
137
|
+
} finally {
|
|
138
|
+
canvas.dispose();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
109
141
|
async function exportMockup(canvas, mockup, options = {}) {
|
|
110
142
|
const { multiplier = 1, format = "png", quality = 1 } = options;
|
|
111
143
|
const design = canvas.toCanvasElement(multiplier);
|
|
@@ -221,8 +253,9 @@ export {
|
|
|
221
253
|
computeCoverPlacement,
|
|
222
254
|
exportPNG,
|
|
223
255
|
exportIsolatedPNG,
|
|
256
|
+
exportPrintArea,
|
|
224
257
|
exportMockup,
|
|
225
258
|
exportSVG,
|
|
226
259
|
exportDataURL
|
|
227
260
|
};
|
|
228
|
-
//# sourceMappingURL=chunk-
|
|
261
|
+
//# sourceMappingURL=chunk-MCBRZQ4M.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/displacement.ts","../src/export.ts"],"sourcesContent":["import type { MockupDisplacement, MockupDisplacementChannel } from './types';\n\nconst CHANNEL_INDEX: Record<MockupDisplacementChannel, number> = {\n red: 0,\n green: 1,\n blue: 2,\n alpha: 3,\n};\n\nfunction finiteScale(value: number | undefined, fallback: number, label: string): number {\n const resolved = value ?? fallback;\n if (!Number.isFinite(resolved)) throw new Error(`${label} must be finite`);\n return resolved;\n}\n\nfunction sample(\n source: Uint8ClampedArray,\n width: number,\n height: number,\n x: number,\n y: number,\n channel: number,\n): number {\n const clampedX = Math.max(0, Math.min(width - 1, x));\n const clampedY = Math.max(0, Math.min(height - 1, y));\n const x0 = Math.floor(clampedX);\n const y0 = Math.floor(clampedY);\n const x1 = Math.min(width - 1, x0 + 1);\n const y1 = Math.min(height - 1, y0 + 1);\n const tx = clampedX - x0;\n const ty = clampedY - y0;\n const top =\n source[(y0 * width + x0) * 4 + channel] * (1 - tx) +\n source[(y0 * width + x1) * 4 + channel] * tx;\n const bottom =\n source[(y1 * width + x0) * 4 + channel] * (1 - tx) +\n source[(y1 * width + x1) * 4 + channel] * tx;\n return top * (1 - ty) + bottom * ty;\n}\n\n/**\n * Warp RGBA pixels with an equally sized channel map. A channel value of 128\n * is neutral; 0 and 255 move by the configured negative/positive maximum.\n */\nexport function displaceRgba(\n source: Uint8ClampedArray,\n map: Uint8ClampedArray,\n width: number,\n height: number,\n options: Omit<MockupDisplacement, 'image'>,\n): Uint8ClampedArray {\n if (!Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0) {\n throw new Error('Displacement dimensions must be positive integers');\n }\n const expectedLength = width * height * 4;\n if (source.length !== expectedLength || map.length !== expectedLength) {\n throw new Error('Displacement source and map must match the requested dimensions');\n }\n\n const scaleX = finiteScale(options.scaleX, 10, 'Displacement scaleX');\n const scaleY = finiteScale(options.scaleY, 10, 'Displacement scaleY');\n const channelX = CHANNEL_INDEX[options.channelX ?? 'red'];\n const channelY = CHANNEL_INDEX[options.channelY ?? 'green'];\n const output = new Uint8ClampedArray(expectedLength);\n\n for (let y = 0; y < height; y += 1) {\n for (let x = 0; x < width; x += 1) {\n const offset = (y * width + x) * 4;\n const sourceX = x + ((map[offset + channelX] - 128) / 127) * scaleX;\n const sourceY = y + ((map[offset + channelY] - 128) / 127) * scaleY;\n for (let channel = 0; channel < 4; channel += 1) {\n output[offset + channel] = Math.round(\n sample(source, width, height, sourceX, sourceY, channel),\n );\n }\n }\n }\n return output;\n}\n","import { StaticCanvas } from 'fabric';\nimport type { Canvas, FabricObject, ImageFormat } from 'fabric';\nimport type { MockupConfig, MockupPrintArea } from './types';\nimport { displaceRgba } from './displacement';\n\nexport interface PngExportOptions {\n multiplier?: number;\n format?: ImageFormat;\n quality?: number;\n}\n\nexport interface CoverPlacement {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\nexport function computePrintAreaClip(\n area: MockupPrintArea,\n scaleX: number,\n scaleY: number,\n targetWidth: number,\n targetHeight: number,\n): MockupPrintArea {\n const left = Math.max(0, Math.min(targetWidth, area.left * scaleX));\n const top = Math.max(0, Math.min(targetHeight, area.top * scaleY));\n const right = Math.max(left, Math.min(targetWidth, (area.left + area.width) * scaleX));\n const bottom = Math.max(top, Math.min(targetHeight, (area.top + area.height) * scaleY));\n return { left, top, width: right - left, height: bottom - top };\n}\n\n/** Object-fit: cover geometry, exported for deterministic preview/composite tests. */\nexport function computeCoverPlacement(\n sourceWidth: number,\n sourceHeight: number,\n targetWidth: number,\n targetHeight: number,\n): CoverPlacement {\n if (sourceWidth <= 0 || sourceHeight <= 0 || targetWidth <= 0 || targetHeight <= 0) {\n throw new Error('Cover dimensions must be positive');\n }\n const scale = Math.max(targetWidth / sourceWidth, targetHeight / sourceHeight);\n const width = sourceWidth * scale;\n const height = sourceHeight * scale;\n return {\n left: (targetWidth - width) / 2,\n top: (targetHeight - height) / 2,\n width,\n height,\n };\n}\n\nfunction canvasElementToBlob(\n output: HTMLCanvasElement,\n format: ImageFormat,\n quality: number,\n): Promise<Blob> {\n const mime = format === 'jpeg' ? 'image/jpeg' : `image/${format}`;\n return new Promise<Blob>((resolve, reject) => {\n output.toBlob(\n (blob) => (blob ? resolve(blob) : reject(new Error(`Failed to export ${format}`))),\n mime,\n quality,\n );\n });\n}\n\nexport async function exportPNG(canvas: Canvas, options: PngExportOptions = {}): Promise<Blob> {\n const { multiplier = 1, format = 'png' as ImageFormat, quality = 1 } = options;\n const output = canvas.toCanvasElement(multiplier);\n return canvasElementToBlob(output, format, quality);\n}\n\n/** Render cloned objects without mutating the live editor canvas. */\nexport async function exportIsolatedPNG(\n source: Canvas,\n objects: FabricObject[],\n options: PngExportOptions & {\n width?: number;\n height?: number;\n backgroundColor?: string;\n backgroundImage?: FabricObject | null;\n cloneObjects?: boolean;\n } = {},\n): Promise<Blob> {\n const element = source.lowerCanvasEl.ownerDocument.createElement('canvas');\n const canvas = new StaticCanvas(element, {\n width: options.width ?? source.getWidth(),\n height: options.height ?? source.getHeight(),\n backgroundColor: options.backgroundColor || undefined,\n });\n try {\n const clones =\n options.cloneObjects === false\n ? objects\n : await Promise.all(objects.map((object) => object.clone()));\n if (clones.length) canvas.add(...clones);\n if (options.backgroundImage) canvas.backgroundImage = await options.backgroundImage.clone();\n canvas.requestRenderAll();\n // Awaited, not returned: `finally` would otherwise dispose the canvas while\n // the export is still reading from it.\n return await exportPNG(canvas as unknown as Canvas, options);\n } finally {\n canvas.dispose();\n }\n}\n\n/**\n * Render just the print-area rectangle, on transparency.\n *\n * This is the file a print provider receives: the design alone, cropped to the\n * printable rectangle, with no garment behind it and no canvas background baked\n * in — so it is rendered from cloned objects rather than off the live canvas.\n */\nexport async function exportPrintArea(\n source: Canvas,\n area: MockupPrintArea,\n options: PngExportOptions = {},\n): Promise<Blob> {\n const { multiplier = 1, format = 'png' as ImageFormat, quality = 1 } = options;\n const width = source.getWidth();\n const height = source.getHeight();\n const clip = computePrintAreaClip(\n area,\n multiplier,\n multiplier,\n width * multiplier,\n height * multiplier,\n );\n if (clip.width <= 0 || clip.height <= 0) {\n throw new Error('Print area does not overlap the canvas');\n }\n\n const element = source.lowerCanvasEl.ownerDocument.createElement('canvas');\n const canvas = new StaticCanvas(element, { width, height });\n try {\n const clones = await Promise.all(source.getObjects().map((object) => object.clone()));\n if (clones.length) canvas.add(...clones);\n canvas.requestRenderAll();\n const rendered = canvas.toCanvasElement(multiplier);\n const output = rendered.ownerDocument.createElement('canvas');\n output.width = Math.max(1, Math.round(clip.width));\n output.height = Math.max(1, Math.round(clip.height));\n const context = output.getContext('2d');\n if (!context) throw new Error('2D canvas context is unavailable');\n context.drawImage(rendered, -clip.left, -clip.top);\n // Awaited, not returned: `finally` would dispose the canvas mid-read.\n return await canvasElementToBlob(output, format, quality);\n } finally {\n canvas.dispose();\n }\n}\n\n/** Rasterize the browser mockup preview together with the transparent design. */\nexport async function exportMockup(\n canvas: Canvas,\n mockup: MockupConfig,\n options: PngExportOptions = {},\n): Promise<Blob> {\n const { multiplier = 1, format = 'png' as ImageFormat, quality = 1 } = options;\n const design = canvas.toCanvasElement(multiplier);\n const output = design.ownerDocument.createElement('canvas');\n output.width = design.width;\n output.height = design.height;\n const context = output.getContext('2d');\n if (!context) throw new Error('2D canvas context is unavailable');\n\n const loadImage = (url: string) =>\n new Promise<HTMLImageElement>((resolve, reject) => {\n const element = new Image();\n element.crossOrigin = 'anonymous';\n element.onload = () => resolve(element);\n element.onerror = () => reject(new Error(`Failed to load mockup image: ${url}`));\n element.src = url;\n });\n const drawCover = (\n image: HTMLImageElement,\n targetContext: CanvasRenderingContext2D = context,\n ) => {\n const placement = computeCoverPlacement(\n image.naturalWidth || image.width,\n image.naturalHeight || image.height,\n output.width,\n output.height,\n );\n targetContext.drawImage(\n image,\n placement.left,\n placement.top,\n placement.width,\n placement.height,\n );\n };\n\n // Full-size scratch buffers, released explicitly in the finally below: a\n // detached canvas element can hold its backing store well past its last\n // reference, and a 4K mockup allocates three of them per export.\n const scratch: HTMLCanvasElement[] = [design];\n try {\n drawCover(await loadImage(mockup.image));\n let compositedDesign: CanvasImageSource = design;\n if (mockup.displacement) {\n const sourceContext = design.getContext('2d');\n if (!sourceContext) throw new Error('2D design context is unavailable');\n const mapCanvas = design.ownerDocument.createElement('canvas');\n scratch.push(mapCanvas);\n mapCanvas.width = design.width;\n mapCanvas.height = design.height;\n const mapContext = mapCanvas.getContext('2d');\n if (!mapContext) throw new Error('2D displacement-map context is unavailable');\n drawCover(await loadImage(mockup.displacement.image), mapContext);\n\n const warped = design.ownerDocument.createElement('canvas');\n scratch.push(warped);\n warped.width = design.width;\n warped.height = design.height;\n const warpedContext = warped.getContext('2d');\n if (!warpedContext) throw new Error('2D displaced-design context is unavailable');\n let sourcePixels: Uint8ClampedArray;\n let mapPixels: Uint8ClampedArray;\n try {\n sourcePixels = sourceContext.getImageData(0, 0, design.width, design.height).data;\n mapPixels = mapContext.getImageData(0, 0, design.width, design.height).data;\n } catch (error) {\n throw new Error('Failed to apply mockup displacement map; verify image CORS access', {\n cause: error,\n });\n }\n const pixels = displaceRgba(sourcePixels, mapPixels, design.width, design.height, {\n ...mockup.displacement,\n scaleX: (mockup.displacement.scaleX ?? 10) * multiplier,\n scaleY: (mockup.displacement.scaleY ?? 10) * multiplier,\n });\n const imageData = warpedContext.createImageData(design.width, design.height);\n imageData.data.set(pixels);\n warpedContext.putImageData(imageData, 0, 0);\n compositedDesign = warped;\n }\n context.save();\n if (mockup.printArea && mockup.clipToPrintArea !== false) {\n const clip = computePrintAreaClip(\n mockup.printArea,\n output.width / canvas.getWidth(),\n output.height / canvas.getHeight(),\n output.width,\n output.height,\n );\n context.beginPath();\n context.rect(clip.left, clip.top, clip.width, clip.height);\n context.clip();\n }\n context.globalAlpha = Math.max(0, Math.min(1, mockup.designOpacity ?? 1));\n context.globalCompositeOperation =\n !mockup.designBlendMode || mockup.designBlendMode === 'normal'\n ? 'source-over'\n : mockup.designBlendMode;\n context.drawImage(compositedDesign, 0, 0);\n context.restore();\n\n if (mockup.overlay) {\n context.save();\n context.globalAlpha = Math.max(0, Math.min(1, mockup.overlay.opacity ?? 1));\n context.globalCompositeOperation =\n mockup.overlay.blendMode === 'normal'\n ? 'source-over'\n : (mockup.overlay.blendMode ?? 'multiply');\n drawCover(await loadImage(mockup.overlay.image));\n context.restore();\n }\n return await canvasElementToBlob(output, format, quality);\n } finally {\n for (const element of scratch) {\n element.width = 0;\n element.height = 0;\n }\n }\n}\n\nexport function exportSVG(canvas: Canvas): string {\n return canvas.toSVG();\n}\n\nexport function exportDataURL(canvas: Canvas, format: ImageFormat = 'png', multiplier = 1): string {\n return canvas.toDataURL({ format, multiplier });\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Canvas, FabricObject, ImageFormat } from 'fabric';
|
|
2
|
-
import { b as EditorEvents,
|
|
3
|
-
export { D as DEFAULT_PATTERN_CONFIG, d as ExportFormat, f as ImageAttribution,
|
|
2
|
+
import { b as EditorEvents, m as LayerType, k as LayerMeta, L as LayerData, W as SerializedLayer, J as PatternSourceResolver, P as PatternConfig, H as PatternLocks, a0 as TextCurveConfig, r as MaskPresetId, X as ShapeMaskPresetId, a1 as TextureMaskPresetId, a3 as Unit, G as MockupPrintArea, x as MockupConfig, e as FontDefinition, n as LicenseConfig, p as LicenseStatus, S as ProjectState, M as MaskBrushOptions, q as MaskPoint, t as MaskRefinementProvider, s as MaskRefinementPrompt, v as MaskRefinementResult, E as EditorConfig, Y as ShapePlugin, _ as TemplateDefinition, I as ImageAdjustments, c as EditorState, U as SemanticExportOptions, Z as SvgExportOptions, Q as PrintifyPositioning, N as NormalizedLayerPosition, O as PositioningAdapter, h as ImageProviderResult, i as ImageSearchOptions, j as ImageSearchResult, F as FileAdapter, g as ImageProvider, V as SerializedBackgroundImageOptions, B as BackgroundImageOptions, T as ResizeOptions, a as DpiIssue, l as LayerShadowConfig, C as CanvasSizePreset, y as MockupDisplacement } from './types-Dh1unrzT.mjs';
|
|
3
|
+
export { D as DEFAULT_PATTERN_CONFIG, d as ExportFormat, f as ImageAttribution, o as LicensePayload, u as MaskRefinementRequest, w as MockupBlendMode, z as MockupDisplacementChannel, A as MockupOverlay, K as PatternState, R as ProjectPage, $ as TemplateParameter, a2 as TileMode } from './types-Dh1unrzT.mjs';
|
|
4
4
|
|
|
5
5
|
type EventHandler<T> = (data: T) => void;
|
|
6
6
|
declare class EventEmitter<TEvents extends {} = Record<string, unknown>> {
|
|
@@ -246,6 +246,107 @@ interface CanvasRenderingProtocol {
|
|
|
246
246
|
drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
/** Straight text — the state every text layer starts in. */
|
|
250
|
+
declare const DEFAULT_TEXT_CURVE: TextCurveConfig;
|
|
251
|
+
interface CurvePath {
|
|
252
|
+
/** SVG path data the text is laid out along. */
|
|
253
|
+
data: string;
|
|
254
|
+
/** Length of that path, used to centre the run on it. */
|
|
255
|
+
length: number;
|
|
256
|
+
}
|
|
257
|
+
/** Path the given curve traces for a text run of `width` px, or null when straight. */
|
|
258
|
+
declare function buildCurvePathData(config: TextCurveConfig, width: number, fontSize: number): CurvePath | null;
|
|
259
|
+
/**
|
|
260
|
+
* Bends a text layer's baseline along a generated path.
|
|
261
|
+
*
|
|
262
|
+
* The curve lives on the fabric object as a real text path, so it survives
|
|
263
|
+
* export and serialization with no extra machinery. The parameters that
|
|
264
|
+
* produced it are kept in `layer.meta.curve` so the UI can show them and so the
|
|
265
|
+
* path can be rebuilt when the text, font or size changes.
|
|
266
|
+
*/
|
|
267
|
+
declare class TextCurveManager {
|
|
268
|
+
private canvas;
|
|
269
|
+
private layers;
|
|
270
|
+
private history;
|
|
271
|
+
private events;
|
|
272
|
+
constructor(canvas: Canvas, layers: LayerManager, history: HistoryManager, events: EventEmitter<EditorEvents>);
|
|
273
|
+
/** Curve parameters for a layer, or null when it is not curved text. */
|
|
274
|
+
get(layerId: string): TextCurveConfig | null;
|
|
275
|
+
isCurved(layerId: string): boolean;
|
|
276
|
+
/** Apply (or update) the curve on a text layer. Zeroed config clears it. */
|
|
277
|
+
apply(layerId: string, config: Partial<TextCurveConfig>, save?: boolean): boolean;
|
|
278
|
+
/** Remove the curve, restoring the authored text box width. */
|
|
279
|
+
clear(layerId: string, save?: boolean): boolean;
|
|
280
|
+
/**
|
|
281
|
+
* Rebuild the path from the stored parameters. Text content, font family and
|
|
282
|
+
* font size all change the run's width, and the path is sized to that width —
|
|
283
|
+
* without this the curve keeps the geometry of the text it was created from.
|
|
284
|
+
*/
|
|
285
|
+
refresh(layerId: string, save?: boolean): boolean;
|
|
286
|
+
/** Rebuild every curved layer — used after a state restore. */
|
|
287
|
+
refreshAll(): void;
|
|
288
|
+
private detach;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
declare function isMaskPresetId(value: unknown): value is MaskPresetId;
|
|
292
|
+
/**
|
|
293
|
+
* Clips a layer to a preset silhouette or soft texture.
|
|
294
|
+
*
|
|
295
|
+
* The preset is installed as the fabric object's `clipPath`, so it renders,
|
|
296
|
+
* exports and serializes through the same path fabric already uses. The chosen
|
|
297
|
+
* id is kept in `layer.meta.maskPreset` so the UI can show the active preset
|
|
298
|
+
* and so the clip can be rebuilt when the layer is resized.
|
|
299
|
+
*
|
|
300
|
+
* A pattern strips and restores the layer's clip while it is enabled (see
|
|
301
|
+
* `PatternManager`), so a mask preset is suspended for the duration of one.
|
|
302
|
+
*/
|
|
303
|
+
declare class MaskPresetManager {
|
|
304
|
+
private canvas;
|
|
305
|
+
private layers;
|
|
306
|
+
private history;
|
|
307
|
+
private events;
|
|
308
|
+
constructor(canvas: Canvas, layers: LayerManager, history: HistoryManager, events: EventEmitter<EditorEvents>);
|
|
309
|
+
get(layerId: string): MaskPresetId | null;
|
|
310
|
+
/** Clip the layer to `id`. Passing null (or an unknown id) clears the clip. */
|
|
311
|
+
apply(layerId: string, id: MaskPresetId | null, save?: boolean): boolean;
|
|
312
|
+
clear(layerId: string, save?: boolean): boolean;
|
|
313
|
+
/**
|
|
314
|
+
* Re-fit the clip to the layer's current size. The clip is built for the
|
|
315
|
+
* object's dimensions at the time it was applied; editing text or replacing an
|
|
316
|
+
* image changes them, and a stale clip would crop the wrong region.
|
|
317
|
+
*/
|
|
318
|
+
refresh(layerId: string, save?: boolean): boolean;
|
|
319
|
+
/** Re-fit every masked layer — used after a state restore. */
|
|
320
|
+
refreshAll(): void;
|
|
321
|
+
private buildClip;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** Silhouette masks, authored on a 0–100 square so they scale to any layer. */
|
|
325
|
+
declare const SHAPE_MASK_IDS: readonly ["circle", "square", "triangle", "star", "heart", "octagram", "arch", "zigzag"];
|
|
326
|
+
type ShapeMaskId = ShapeMaskPresetId;
|
|
327
|
+
declare function isShapeMaskId(value: unknown): value is ShapeMaskId;
|
|
328
|
+
/** SVG path data for a shape mask, on a 100×100 box. */
|
|
329
|
+
declare function shapeMaskPathData(id: ShapeMaskId): string;
|
|
330
|
+
/** Nominal authoring box every shape mask path is drawn in. */
|
|
331
|
+
declare const SHAPE_MASK_BOX = 100;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Procedural alpha textures used as soft layer masks.
|
|
335
|
+
*
|
|
336
|
+
* Each renders white-on-transparent at a fixed resolution; the opaque parts are
|
|
337
|
+
* what survives masking. They are deterministic (seeded PRNG, no `Math.random`)
|
|
338
|
+
* so a design renders identically on every load and in every export.
|
|
339
|
+
*/
|
|
340
|
+
declare const TEXTURE_MASK_IDS: readonly ["vignette", "halftone", "spray", "grunge", "torn", "band"];
|
|
341
|
+
type TextureMaskId = TextureMaskPresetId;
|
|
342
|
+
declare function isTextureMaskId(value: unknown): value is TextureMaskId;
|
|
343
|
+
/** Square resolution every texture is rendered at before being scaled to fit. */
|
|
344
|
+
declare const TEXTURE_MASK_SIZE = 320;
|
|
345
|
+
/** Render (and memoize) a texture mask. Browser-only: needs a 2D canvas. */
|
|
346
|
+
declare function renderTextureMask(id: TextureMaskId): HTMLCanvasElement;
|
|
347
|
+
/** Drop memoized textures — used by tests and by long-lived editors on dispose. */
|
|
348
|
+
declare function clearTextureMaskCache(): void;
|
|
349
|
+
|
|
249
350
|
declare class UnitConverter {
|
|
250
351
|
private unit;
|
|
251
352
|
private dpi;
|
|
@@ -273,6 +374,14 @@ declare function computePrintAreaClip(area: MockupPrintArea, scaleX: number, sca
|
|
|
273
374
|
/** Object-fit: cover geometry, exported for deterministic preview/composite tests. */
|
|
274
375
|
declare function computeCoverPlacement(sourceWidth: number, sourceHeight: number, targetWidth: number, targetHeight: number): CoverPlacement;
|
|
275
376
|
declare function exportPNG(canvas: Canvas, options?: PngExportOptions): Promise<Blob>;
|
|
377
|
+
/**
|
|
378
|
+
* Render just the print-area rectangle, on transparency.
|
|
379
|
+
*
|
|
380
|
+
* This is the file a print provider receives: the design alone, cropped to the
|
|
381
|
+
* printable rectangle, with no garment behind it and no canvas background baked
|
|
382
|
+
* in — so it is rendered from cloned objects rather than off the live canvas.
|
|
383
|
+
*/
|
|
384
|
+
declare function exportPrintArea(source: Canvas, area: MockupPrintArea, options?: PngExportOptions): Promise<Blob>;
|
|
276
385
|
/** Rasterize the browser mockup preview together with the transparent design. */
|
|
277
386
|
declare function exportMockup(canvas: Canvas, mockup: MockupConfig, options?: PngExportOptions): Promise<Blob>;
|
|
278
387
|
declare function exportSVG(canvas: Canvas): string;
|
|
@@ -390,6 +499,8 @@ declare class CanvasEditor {
|
|
|
390
499
|
readonly snapping: SnapManager;
|
|
391
500
|
readonly crop: CropController;
|
|
392
501
|
readonly patterns: PatternManager;
|
|
502
|
+
readonly curves: TextCurveManager;
|
|
503
|
+
readonly maskPresets: MaskPresetManager;
|
|
393
504
|
readonly fonts: FontRegistry;
|
|
394
505
|
readonly licensing: LicenseManager;
|
|
395
506
|
readonly pages: ProjectManager;
|
|
@@ -433,6 +544,12 @@ declare class CanvasEditor {
|
|
|
433
544
|
toSVG(): string;
|
|
434
545
|
toSVGAsync(options?: SvgExportOptions): Promise<string>;
|
|
435
546
|
toDataURL(format?: ImageFormat, multiplier?: number): string;
|
|
547
|
+
/**
|
|
548
|
+
* Export the print file: the design cropped to the mockup's print area, on
|
|
549
|
+
* transparency. Without a print area this is the whole canvas, still
|
|
550
|
+
* transparent — a print file never carries the design background.
|
|
551
|
+
*/
|
|
552
|
+
toPrintFile(options?: PngExportOptions): Promise<Blob>;
|
|
436
553
|
/** Export the current product-preview composite. Advanced warping is host-defined. */
|
|
437
554
|
toMockupImage(options?: PngExportOptions): Promise<Blob>;
|
|
438
555
|
/**
|
|
@@ -484,13 +601,64 @@ declare class CanvasEditor {
|
|
|
484
601
|
zoomToSelection(padding?: number): void;
|
|
485
602
|
applyPattern(layerId: string, config: PatternConfig): Promise<void>;
|
|
486
603
|
clearPattern(layerId: string): Promise<void>;
|
|
487
|
-
|
|
604
|
+
applyTextCurve(layerId: string, config: Partial<TextCurveConfig>): boolean;
|
|
605
|
+
clearTextCurve(layerId: string): boolean;
|
|
606
|
+
getTextCurve(layerId: string): TextCurveConfig | null;
|
|
607
|
+
applyMaskPreset(layerId: string, id: MaskPresetId | null): boolean;
|
|
608
|
+
clearMaskPreset(layerId: string): boolean;
|
|
609
|
+
getMaskPreset(layerId: string): MaskPresetId | null;
|
|
610
|
+
/**
|
|
611
|
+
* Constrain a layer to its current proportions. Persisted on the layer so a
|
|
612
|
+
* reopened design still resizes the way it was set up to.
|
|
613
|
+
*/
|
|
614
|
+
setLayerAspectLock(layerId: string, locked: boolean): boolean;
|
|
615
|
+
getLayerAspectLock(layerId: string): boolean;
|
|
616
|
+
/** Re-apply every stored aspect lock — control visibility is not serialized. */
|
|
617
|
+
restoreAspectLocks(): void;
|
|
618
|
+
/** Drop scale, rotation, skew and flips; the layer stays where it is. */
|
|
619
|
+
resetLayerTransform(layerId: string): boolean;
|
|
620
|
+
setLayerShadow(layerId: string, config: Partial<LayerShadowConfig>): boolean;
|
|
621
|
+
getLayerShadow(layerId: string): LayerShadowConfig | null;
|
|
622
|
+
/**
|
|
623
|
+
* Show (or clear) the product preview. Pass `history: false` for preview-only
|
|
624
|
+
* changes such as swapping a colourway — those are not design edits and
|
|
625
|
+
* should not fill the undo stack.
|
|
626
|
+
*/
|
|
627
|
+
setMockup(mockup: MockupConfig | null, options?: {
|
|
628
|
+
history?: boolean;
|
|
629
|
+
}): void;
|
|
488
630
|
clearMockup(): void;
|
|
489
631
|
getMockup(): MockupConfig | null;
|
|
490
632
|
dispose(): void;
|
|
491
633
|
private setupCanvasEvents;
|
|
492
634
|
}
|
|
493
635
|
|
|
636
|
+
declare const DEFAULT_LAYER_SHADOW: LayerShadowConfig;
|
|
637
|
+
/**
|
|
638
|
+
* Read a layer's drop shadow back off its fabric object.
|
|
639
|
+
*
|
|
640
|
+
* Fabric serializes `shadow` with the object, so the object — not layer meta —
|
|
641
|
+
* is the source of truth; nothing extra has to round-trip through the editor
|
|
642
|
+
* state for a shadow to survive save/load.
|
|
643
|
+
*/
|
|
644
|
+
declare function readLayerShadow(object: FabricObject): LayerShadowConfig;
|
|
645
|
+
/** Install (or remove) a drop shadow on a fabric object. */
|
|
646
|
+
declare function applyLayerShadow(object: FabricObject, config: Partial<LayerShadowConfig>): void;
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Constrain (or release) a layer's proportions.
|
|
650
|
+
*
|
|
651
|
+
* Fabric already scales uniformly from the corners (`canvas.uniformScaling`),
|
|
652
|
+
* so the lock is enforced by taking away the single-axis handles — every
|
|
653
|
+
* remaining control keeps the ratio.
|
|
654
|
+
*/
|
|
655
|
+
declare function applyAspectLock(object: FabricObject, locked: boolean): void;
|
|
656
|
+
/**
|
|
657
|
+
* Undo scaling, rotation, skew and flips, leaving the layer where it sits.
|
|
658
|
+
* Position is deliberately kept: this is "reset the shape", not "move it back".
|
|
659
|
+
*/
|
|
660
|
+
declare function resetTransform(object: FabricObject): void;
|
|
661
|
+
|
|
494
662
|
declare const generateId: () => string;
|
|
495
663
|
|
|
496
664
|
declare function clamp(v: number, min: number, max: number): number;
|
|
@@ -590,4 +758,4 @@ declare class AnnotationOverlay {
|
|
|
590
758
|
*/
|
|
591
759
|
declare function displaceRgba(source: Uint8ClampedArray, map: Uint8ClampedArray, width: number, height: number, options: Omit<MockupDisplacement, 'image'>): Uint8ClampedArray;
|
|
592
760
|
|
|
593
|
-
export { AnnotationOverlay, type AnnotationPrimitive, BackgroundImageOptions, CANVAS_SIZE_PRESETS, CanvasEditor, CanvasSizePreset, type CoverPlacement, CropController, DpiIssue, EditorConfig, EditorEvents, EditorState, EventEmitter, FileAdapter, FontDefinition, FontRegistry, HistoryManager, ImageAdjustments, ImageProvider, ImageProviderResult, ImageSearchOptions, ImageSearchResult, Layer, LayerData, LayerManager, LayerMeta, LayerType, LicenseConfig, LicenseManager, LicenseStatus, MaskBrushOptions, MaskController, type MaskPerformanceSample, MaskPoint, MaskRefinementError, type MaskRefinementErrorCode, MaskRefinementPrompt, MaskRefinementProvider, MaskRefinementResult, MockupConfig, MockupDisplacement, MockupPrintArea, NormalizedLayerPosition, PatternConfig, PatternLocks, PatternManager, PatternSourceResolver, type PngExportOptions, PositioningAdapter, PrintifyPositioning, ProjectManager, ProjectState, ResizeOptions, SemanticExportOptions, SerializedBackgroundImageOptions, SerializedLayer, ShapePlugin, SnapManager, SvgExportOptions, TemplateDefinition, type TilePlacement, Unit, UnitConverter, type ViewportTransform, applyPatternLocks, buildPatternDataURL, captureLocks, clamp, clearPatternImageCache, computeCoverPlacement, computePrintAreaClip, computeTilePositions, deserializeEditor, displaceRgba, drawTiles, escapeXml, exportDataURL, exportMockup, exportPNG, exportSVG, generateId, isCssColor, loadPatternImage, restoreLocks, round2, sanitizeSvg, serializeEditor };
|
|
761
|
+
export { AnnotationOverlay, type AnnotationPrimitive, BackgroundImageOptions, CANVAS_SIZE_PRESETS, CanvasEditor, CanvasSizePreset, type CoverPlacement, CropController, DEFAULT_LAYER_SHADOW, DEFAULT_TEXT_CURVE, DpiIssue, EditorConfig, EditorEvents, EditorState, EventEmitter, FileAdapter, FontDefinition, FontRegistry, HistoryManager, ImageAdjustments, ImageProvider, ImageProviderResult, ImageSearchOptions, ImageSearchResult, Layer, LayerData, LayerManager, LayerMeta, LayerShadowConfig, LayerType, LicenseConfig, LicenseManager, LicenseStatus, MaskBrushOptions, MaskController, type MaskPerformanceSample, MaskPoint, MaskPresetId, MaskPresetManager, MaskRefinementError, type MaskRefinementErrorCode, MaskRefinementPrompt, MaskRefinementProvider, MaskRefinementResult, MockupConfig, MockupDisplacement, MockupPrintArea, NormalizedLayerPosition, PatternConfig, PatternLocks, PatternManager, PatternSourceResolver, type PngExportOptions, PositioningAdapter, PrintifyPositioning, ProjectManager, ProjectState, ResizeOptions, SHAPE_MASK_BOX, SHAPE_MASK_IDS, SemanticExportOptions, SerializedBackgroundImageOptions, SerializedLayer, ShapeMaskPresetId, ShapePlugin, SnapManager, SvgExportOptions, TEXTURE_MASK_IDS, TEXTURE_MASK_SIZE, TemplateDefinition, TextCurveConfig, TextCurveManager, TextureMaskPresetId, type TilePlacement, Unit, UnitConverter, type ViewportTransform, applyAspectLock, applyLayerShadow, applyPatternLocks, buildCurvePathData, buildPatternDataURL, captureLocks, clamp, clearPatternImageCache, clearTextureMaskCache, computeCoverPlacement, computePrintAreaClip, computeTilePositions, deserializeEditor, displaceRgba, drawTiles, escapeXml, exportDataURL, exportMockup, exportPNG, exportPrintArea, exportSVG, generateId, isCssColor, isMaskPresetId, isShapeMaskId, isTextureMaskId, loadPatternImage, readLayerShadow, renderTextureMask, resetTransform, restoreLocks, round2, sanitizeSvg, serializeEditor, shapeMaskPathData };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Canvas, FabricObject, ImageFormat } from 'fabric';
|
|
2
|
-
import { b as EditorEvents,
|
|
3
|
-
export { D as DEFAULT_PATTERN_CONFIG, d as ExportFormat, f as ImageAttribution,
|
|
2
|
+
import { b as EditorEvents, m as LayerType, k as LayerMeta, L as LayerData, W as SerializedLayer, J as PatternSourceResolver, P as PatternConfig, H as PatternLocks, a0 as TextCurveConfig, r as MaskPresetId, X as ShapeMaskPresetId, a1 as TextureMaskPresetId, a3 as Unit, G as MockupPrintArea, x as MockupConfig, e as FontDefinition, n as LicenseConfig, p as LicenseStatus, S as ProjectState, M as MaskBrushOptions, q as MaskPoint, t as MaskRefinementProvider, s as MaskRefinementPrompt, v as MaskRefinementResult, E as EditorConfig, Y as ShapePlugin, _ as TemplateDefinition, I as ImageAdjustments, c as EditorState, U as SemanticExportOptions, Z as SvgExportOptions, Q as PrintifyPositioning, N as NormalizedLayerPosition, O as PositioningAdapter, h as ImageProviderResult, i as ImageSearchOptions, j as ImageSearchResult, F as FileAdapter, g as ImageProvider, V as SerializedBackgroundImageOptions, B as BackgroundImageOptions, T as ResizeOptions, a as DpiIssue, l as LayerShadowConfig, C as CanvasSizePreset, y as MockupDisplacement } from './types-Dh1unrzT.js';
|
|
3
|
+
export { D as DEFAULT_PATTERN_CONFIG, d as ExportFormat, f as ImageAttribution, o as LicensePayload, u as MaskRefinementRequest, w as MockupBlendMode, z as MockupDisplacementChannel, A as MockupOverlay, K as PatternState, R as ProjectPage, $ as TemplateParameter, a2 as TileMode } from './types-Dh1unrzT.js';
|
|
4
4
|
|
|
5
5
|
type EventHandler<T> = (data: T) => void;
|
|
6
6
|
declare class EventEmitter<TEvents extends {} = Record<string, unknown>> {
|
|
@@ -246,6 +246,107 @@ interface CanvasRenderingProtocol {
|
|
|
246
246
|
drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
/** Straight text — the state every text layer starts in. */
|
|
250
|
+
declare const DEFAULT_TEXT_CURVE: TextCurveConfig;
|
|
251
|
+
interface CurvePath {
|
|
252
|
+
/** SVG path data the text is laid out along. */
|
|
253
|
+
data: string;
|
|
254
|
+
/** Length of that path, used to centre the run on it. */
|
|
255
|
+
length: number;
|
|
256
|
+
}
|
|
257
|
+
/** Path the given curve traces for a text run of `width` px, or null when straight. */
|
|
258
|
+
declare function buildCurvePathData(config: TextCurveConfig, width: number, fontSize: number): CurvePath | null;
|
|
259
|
+
/**
|
|
260
|
+
* Bends a text layer's baseline along a generated path.
|
|
261
|
+
*
|
|
262
|
+
* The curve lives on the fabric object as a real text path, so it survives
|
|
263
|
+
* export and serialization with no extra machinery. The parameters that
|
|
264
|
+
* produced it are kept in `layer.meta.curve` so the UI can show them and so the
|
|
265
|
+
* path can be rebuilt when the text, font or size changes.
|
|
266
|
+
*/
|
|
267
|
+
declare class TextCurveManager {
|
|
268
|
+
private canvas;
|
|
269
|
+
private layers;
|
|
270
|
+
private history;
|
|
271
|
+
private events;
|
|
272
|
+
constructor(canvas: Canvas, layers: LayerManager, history: HistoryManager, events: EventEmitter<EditorEvents>);
|
|
273
|
+
/** Curve parameters for a layer, or null when it is not curved text. */
|
|
274
|
+
get(layerId: string): TextCurveConfig | null;
|
|
275
|
+
isCurved(layerId: string): boolean;
|
|
276
|
+
/** Apply (or update) the curve on a text layer. Zeroed config clears it. */
|
|
277
|
+
apply(layerId: string, config: Partial<TextCurveConfig>, save?: boolean): boolean;
|
|
278
|
+
/** Remove the curve, restoring the authored text box width. */
|
|
279
|
+
clear(layerId: string, save?: boolean): boolean;
|
|
280
|
+
/**
|
|
281
|
+
* Rebuild the path from the stored parameters. Text content, font family and
|
|
282
|
+
* font size all change the run's width, and the path is sized to that width —
|
|
283
|
+
* without this the curve keeps the geometry of the text it was created from.
|
|
284
|
+
*/
|
|
285
|
+
refresh(layerId: string, save?: boolean): boolean;
|
|
286
|
+
/** Rebuild every curved layer — used after a state restore. */
|
|
287
|
+
refreshAll(): void;
|
|
288
|
+
private detach;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
declare function isMaskPresetId(value: unknown): value is MaskPresetId;
|
|
292
|
+
/**
|
|
293
|
+
* Clips a layer to a preset silhouette or soft texture.
|
|
294
|
+
*
|
|
295
|
+
* The preset is installed as the fabric object's `clipPath`, so it renders,
|
|
296
|
+
* exports and serializes through the same path fabric already uses. The chosen
|
|
297
|
+
* id is kept in `layer.meta.maskPreset` so the UI can show the active preset
|
|
298
|
+
* and so the clip can be rebuilt when the layer is resized.
|
|
299
|
+
*
|
|
300
|
+
* A pattern strips and restores the layer's clip while it is enabled (see
|
|
301
|
+
* `PatternManager`), so a mask preset is suspended for the duration of one.
|
|
302
|
+
*/
|
|
303
|
+
declare class MaskPresetManager {
|
|
304
|
+
private canvas;
|
|
305
|
+
private layers;
|
|
306
|
+
private history;
|
|
307
|
+
private events;
|
|
308
|
+
constructor(canvas: Canvas, layers: LayerManager, history: HistoryManager, events: EventEmitter<EditorEvents>);
|
|
309
|
+
get(layerId: string): MaskPresetId | null;
|
|
310
|
+
/** Clip the layer to `id`. Passing null (or an unknown id) clears the clip. */
|
|
311
|
+
apply(layerId: string, id: MaskPresetId | null, save?: boolean): boolean;
|
|
312
|
+
clear(layerId: string, save?: boolean): boolean;
|
|
313
|
+
/**
|
|
314
|
+
* Re-fit the clip to the layer's current size. The clip is built for the
|
|
315
|
+
* object's dimensions at the time it was applied; editing text or replacing an
|
|
316
|
+
* image changes them, and a stale clip would crop the wrong region.
|
|
317
|
+
*/
|
|
318
|
+
refresh(layerId: string, save?: boolean): boolean;
|
|
319
|
+
/** Re-fit every masked layer — used after a state restore. */
|
|
320
|
+
refreshAll(): void;
|
|
321
|
+
private buildClip;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** Silhouette masks, authored on a 0–100 square so they scale to any layer. */
|
|
325
|
+
declare const SHAPE_MASK_IDS: readonly ["circle", "square", "triangle", "star", "heart", "octagram", "arch", "zigzag"];
|
|
326
|
+
type ShapeMaskId = ShapeMaskPresetId;
|
|
327
|
+
declare function isShapeMaskId(value: unknown): value is ShapeMaskId;
|
|
328
|
+
/** SVG path data for a shape mask, on a 100×100 box. */
|
|
329
|
+
declare function shapeMaskPathData(id: ShapeMaskId): string;
|
|
330
|
+
/** Nominal authoring box every shape mask path is drawn in. */
|
|
331
|
+
declare const SHAPE_MASK_BOX = 100;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Procedural alpha textures used as soft layer masks.
|
|
335
|
+
*
|
|
336
|
+
* Each renders white-on-transparent at a fixed resolution; the opaque parts are
|
|
337
|
+
* what survives masking. They are deterministic (seeded PRNG, no `Math.random`)
|
|
338
|
+
* so a design renders identically on every load and in every export.
|
|
339
|
+
*/
|
|
340
|
+
declare const TEXTURE_MASK_IDS: readonly ["vignette", "halftone", "spray", "grunge", "torn", "band"];
|
|
341
|
+
type TextureMaskId = TextureMaskPresetId;
|
|
342
|
+
declare function isTextureMaskId(value: unknown): value is TextureMaskId;
|
|
343
|
+
/** Square resolution every texture is rendered at before being scaled to fit. */
|
|
344
|
+
declare const TEXTURE_MASK_SIZE = 320;
|
|
345
|
+
/** Render (and memoize) a texture mask. Browser-only: needs a 2D canvas. */
|
|
346
|
+
declare function renderTextureMask(id: TextureMaskId): HTMLCanvasElement;
|
|
347
|
+
/** Drop memoized textures — used by tests and by long-lived editors on dispose. */
|
|
348
|
+
declare function clearTextureMaskCache(): void;
|
|
349
|
+
|
|
249
350
|
declare class UnitConverter {
|
|
250
351
|
private unit;
|
|
251
352
|
private dpi;
|
|
@@ -273,6 +374,14 @@ declare function computePrintAreaClip(area: MockupPrintArea, scaleX: number, sca
|
|
|
273
374
|
/** Object-fit: cover geometry, exported for deterministic preview/composite tests. */
|
|
274
375
|
declare function computeCoverPlacement(sourceWidth: number, sourceHeight: number, targetWidth: number, targetHeight: number): CoverPlacement;
|
|
275
376
|
declare function exportPNG(canvas: Canvas, options?: PngExportOptions): Promise<Blob>;
|
|
377
|
+
/**
|
|
378
|
+
* Render just the print-area rectangle, on transparency.
|
|
379
|
+
*
|
|
380
|
+
* This is the file a print provider receives: the design alone, cropped to the
|
|
381
|
+
* printable rectangle, with no garment behind it and no canvas background baked
|
|
382
|
+
* in — so it is rendered from cloned objects rather than off the live canvas.
|
|
383
|
+
*/
|
|
384
|
+
declare function exportPrintArea(source: Canvas, area: MockupPrintArea, options?: PngExportOptions): Promise<Blob>;
|
|
276
385
|
/** Rasterize the browser mockup preview together with the transparent design. */
|
|
277
386
|
declare function exportMockup(canvas: Canvas, mockup: MockupConfig, options?: PngExportOptions): Promise<Blob>;
|
|
278
387
|
declare function exportSVG(canvas: Canvas): string;
|
|
@@ -390,6 +499,8 @@ declare class CanvasEditor {
|
|
|
390
499
|
readonly snapping: SnapManager;
|
|
391
500
|
readonly crop: CropController;
|
|
392
501
|
readonly patterns: PatternManager;
|
|
502
|
+
readonly curves: TextCurveManager;
|
|
503
|
+
readonly maskPresets: MaskPresetManager;
|
|
393
504
|
readonly fonts: FontRegistry;
|
|
394
505
|
readonly licensing: LicenseManager;
|
|
395
506
|
readonly pages: ProjectManager;
|
|
@@ -433,6 +544,12 @@ declare class CanvasEditor {
|
|
|
433
544
|
toSVG(): string;
|
|
434
545
|
toSVGAsync(options?: SvgExportOptions): Promise<string>;
|
|
435
546
|
toDataURL(format?: ImageFormat, multiplier?: number): string;
|
|
547
|
+
/**
|
|
548
|
+
* Export the print file: the design cropped to the mockup's print area, on
|
|
549
|
+
* transparency. Without a print area this is the whole canvas, still
|
|
550
|
+
* transparent — a print file never carries the design background.
|
|
551
|
+
*/
|
|
552
|
+
toPrintFile(options?: PngExportOptions): Promise<Blob>;
|
|
436
553
|
/** Export the current product-preview composite. Advanced warping is host-defined. */
|
|
437
554
|
toMockupImage(options?: PngExportOptions): Promise<Blob>;
|
|
438
555
|
/**
|
|
@@ -484,13 +601,64 @@ declare class CanvasEditor {
|
|
|
484
601
|
zoomToSelection(padding?: number): void;
|
|
485
602
|
applyPattern(layerId: string, config: PatternConfig): Promise<void>;
|
|
486
603
|
clearPattern(layerId: string): Promise<void>;
|
|
487
|
-
|
|
604
|
+
applyTextCurve(layerId: string, config: Partial<TextCurveConfig>): boolean;
|
|
605
|
+
clearTextCurve(layerId: string): boolean;
|
|
606
|
+
getTextCurve(layerId: string): TextCurveConfig | null;
|
|
607
|
+
applyMaskPreset(layerId: string, id: MaskPresetId | null): boolean;
|
|
608
|
+
clearMaskPreset(layerId: string): boolean;
|
|
609
|
+
getMaskPreset(layerId: string): MaskPresetId | null;
|
|
610
|
+
/**
|
|
611
|
+
* Constrain a layer to its current proportions. Persisted on the layer so a
|
|
612
|
+
* reopened design still resizes the way it was set up to.
|
|
613
|
+
*/
|
|
614
|
+
setLayerAspectLock(layerId: string, locked: boolean): boolean;
|
|
615
|
+
getLayerAspectLock(layerId: string): boolean;
|
|
616
|
+
/** Re-apply every stored aspect lock — control visibility is not serialized. */
|
|
617
|
+
restoreAspectLocks(): void;
|
|
618
|
+
/** Drop scale, rotation, skew and flips; the layer stays where it is. */
|
|
619
|
+
resetLayerTransform(layerId: string): boolean;
|
|
620
|
+
setLayerShadow(layerId: string, config: Partial<LayerShadowConfig>): boolean;
|
|
621
|
+
getLayerShadow(layerId: string): LayerShadowConfig | null;
|
|
622
|
+
/**
|
|
623
|
+
* Show (or clear) the product preview. Pass `history: false` for preview-only
|
|
624
|
+
* changes such as swapping a colourway — those are not design edits and
|
|
625
|
+
* should not fill the undo stack.
|
|
626
|
+
*/
|
|
627
|
+
setMockup(mockup: MockupConfig | null, options?: {
|
|
628
|
+
history?: boolean;
|
|
629
|
+
}): void;
|
|
488
630
|
clearMockup(): void;
|
|
489
631
|
getMockup(): MockupConfig | null;
|
|
490
632
|
dispose(): void;
|
|
491
633
|
private setupCanvasEvents;
|
|
492
634
|
}
|
|
493
635
|
|
|
636
|
+
declare const DEFAULT_LAYER_SHADOW: LayerShadowConfig;
|
|
637
|
+
/**
|
|
638
|
+
* Read a layer's drop shadow back off its fabric object.
|
|
639
|
+
*
|
|
640
|
+
* Fabric serializes `shadow` with the object, so the object — not layer meta —
|
|
641
|
+
* is the source of truth; nothing extra has to round-trip through the editor
|
|
642
|
+
* state for a shadow to survive save/load.
|
|
643
|
+
*/
|
|
644
|
+
declare function readLayerShadow(object: FabricObject): LayerShadowConfig;
|
|
645
|
+
/** Install (or remove) a drop shadow on a fabric object. */
|
|
646
|
+
declare function applyLayerShadow(object: FabricObject, config: Partial<LayerShadowConfig>): void;
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Constrain (or release) a layer's proportions.
|
|
650
|
+
*
|
|
651
|
+
* Fabric already scales uniformly from the corners (`canvas.uniformScaling`),
|
|
652
|
+
* so the lock is enforced by taking away the single-axis handles — every
|
|
653
|
+
* remaining control keeps the ratio.
|
|
654
|
+
*/
|
|
655
|
+
declare function applyAspectLock(object: FabricObject, locked: boolean): void;
|
|
656
|
+
/**
|
|
657
|
+
* Undo scaling, rotation, skew and flips, leaving the layer where it sits.
|
|
658
|
+
* Position is deliberately kept: this is "reset the shape", not "move it back".
|
|
659
|
+
*/
|
|
660
|
+
declare function resetTransform(object: FabricObject): void;
|
|
661
|
+
|
|
494
662
|
declare const generateId: () => string;
|
|
495
663
|
|
|
496
664
|
declare function clamp(v: number, min: number, max: number): number;
|
|
@@ -590,4 +758,4 @@ declare class AnnotationOverlay {
|
|
|
590
758
|
*/
|
|
591
759
|
declare function displaceRgba(source: Uint8ClampedArray, map: Uint8ClampedArray, width: number, height: number, options: Omit<MockupDisplacement, 'image'>): Uint8ClampedArray;
|
|
592
760
|
|
|
593
|
-
export { AnnotationOverlay, type AnnotationPrimitive, BackgroundImageOptions, CANVAS_SIZE_PRESETS, CanvasEditor, CanvasSizePreset, type CoverPlacement, CropController, DpiIssue, EditorConfig, EditorEvents, EditorState, EventEmitter, FileAdapter, FontDefinition, FontRegistry, HistoryManager, ImageAdjustments, ImageProvider, ImageProviderResult, ImageSearchOptions, ImageSearchResult, Layer, LayerData, LayerManager, LayerMeta, LayerType, LicenseConfig, LicenseManager, LicenseStatus, MaskBrushOptions, MaskController, type MaskPerformanceSample, MaskPoint, MaskRefinementError, type MaskRefinementErrorCode, MaskRefinementPrompt, MaskRefinementProvider, MaskRefinementResult, MockupConfig, MockupDisplacement, MockupPrintArea, NormalizedLayerPosition, PatternConfig, PatternLocks, PatternManager, PatternSourceResolver, type PngExportOptions, PositioningAdapter, PrintifyPositioning, ProjectManager, ProjectState, ResizeOptions, SemanticExportOptions, SerializedBackgroundImageOptions, SerializedLayer, ShapePlugin, SnapManager, SvgExportOptions, TemplateDefinition, type TilePlacement, Unit, UnitConverter, type ViewportTransform, applyPatternLocks, buildPatternDataURL, captureLocks, clamp, clearPatternImageCache, computeCoverPlacement, computePrintAreaClip, computeTilePositions, deserializeEditor, displaceRgba, drawTiles, escapeXml, exportDataURL, exportMockup, exportPNG, exportSVG, generateId, isCssColor, loadPatternImage, restoreLocks, round2, sanitizeSvg, serializeEditor };
|
|
761
|
+
export { AnnotationOverlay, type AnnotationPrimitive, BackgroundImageOptions, CANVAS_SIZE_PRESETS, CanvasEditor, CanvasSizePreset, type CoverPlacement, CropController, DEFAULT_LAYER_SHADOW, DEFAULT_TEXT_CURVE, DpiIssue, EditorConfig, EditorEvents, EditorState, EventEmitter, FileAdapter, FontDefinition, FontRegistry, HistoryManager, ImageAdjustments, ImageProvider, ImageProviderResult, ImageSearchOptions, ImageSearchResult, Layer, LayerData, LayerManager, LayerMeta, LayerShadowConfig, LayerType, LicenseConfig, LicenseManager, LicenseStatus, MaskBrushOptions, MaskController, type MaskPerformanceSample, MaskPoint, MaskPresetId, MaskPresetManager, MaskRefinementError, type MaskRefinementErrorCode, MaskRefinementPrompt, MaskRefinementProvider, MaskRefinementResult, MockupConfig, MockupDisplacement, MockupPrintArea, NormalizedLayerPosition, PatternConfig, PatternLocks, PatternManager, PatternSourceResolver, type PngExportOptions, PositioningAdapter, PrintifyPositioning, ProjectManager, ProjectState, ResizeOptions, SHAPE_MASK_BOX, SHAPE_MASK_IDS, SemanticExportOptions, SerializedBackgroundImageOptions, SerializedLayer, ShapeMaskPresetId, ShapePlugin, SnapManager, SvgExportOptions, TEXTURE_MASK_IDS, TEXTURE_MASK_SIZE, TemplateDefinition, TextCurveConfig, TextCurveManager, TextureMaskPresetId, type TilePlacement, Unit, UnitConverter, type ViewportTransform, applyAspectLock, applyLayerShadow, applyPatternLocks, buildCurvePathData, buildPatternDataURL, captureLocks, clamp, clearPatternImageCache, clearTextureMaskCache, computeCoverPlacement, computePrintAreaClip, computeTilePositions, deserializeEditor, displaceRgba, drawTiles, escapeXml, exportDataURL, exportMockup, exportPNG, exportPrintArea, exportSVG, generateId, isCssColor, isMaskPresetId, isShapeMaskId, isTextureMaskId, loadPatternImage, readLayerShadow, renderTextureMask, resetTransform, restoreLocks, round2, sanitizeSvg, serializeEditor, shapeMaskPathData };
|