@merchi/product-editor 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/.turbo/turbo-build.log +1 -0
  2. package/README.md +174 -0
  3. package/dist/components/AlignMenu.d.ts +3 -0
  4. package/dist/components/AlignMenu.js +61 -0
  5. package/dist/components/FloatingToolbar.d.ts +4 -0
  6. package/dist/components/FloatingToolbar.js +97 -0
  7. package/dist/components/FormatButtons.d.ts +2 -0
  8. package/dist/components/FormatButtons.js +22 -0
  9. package/dist/components/ImageNavButton.d.ts +7 -0
  10. package/dist/components/ImageNavButton.js +14 -0
  11. package/dist/components/ImageZoomModal.d.ts +12 -0
  12. package/dist/components/ImageZoomModal.js +129 -0
  13. package/dist/components/LayerPanel.d.ts +4 -0
  14. package/dist/components/LayerPanel.js +223 -0
  15. package/dist/components/LoadingOverlay.d.ts +9 -0
  16. package/dist/components/LoadingOverlay.js +17 -0
  17. package/dist/components/ProductEditor.d.ts +4 -0
  18. package/dist/components/ProductEditor.js +67 -0
  19. package/dist/components/ProductImageGallery.d.ts +6 -0
  20. package/dist/components/ProductImageGallery.js +148 -0
  21. package/dist/components/ProductPreviews.d.ts +7 -0
  22. package/dist/components/ProductPreviews.js +281 -0
  23. package/dist/components/TextToolbar.d.ts +4 -0
  24. package/dist/components/TextToolbar.js +117 -0
  25. package/dist/components/Toolbar.d.ts +3 -0
  26. package/dist/components/Toolbar.js +47 -0
  27. package/dist/config/colorConfig.d.ts +1 -0
  28. package/dist/config/colorConfig.js +10 -0
  29. package/dist/config/fontConfig.d.ts +5 -0
  30. package/dist/config/fontConfig.js +21 -0
  31. package/dist/context/ProductEditorContext.d.ts +60 -0
  32. package/dist/context/ProductEditorContext.js +743 -0
  33. package/dist/hooks/useSwipeNavigate.d.ts +11 -0
  34. package/dist/hooks/useSwipeNavigate.js +35 -0
  35. package/dist/index.d.ts +6 -0
  36. package/dist/index.js +30 -0
  37. package/dist/styles/BottomPreviewDisplay.css +65 -0
  38. package/dist/styles/FloatingToolbar.css +41 -0
  39. package/dist/styles/ImageGallery.css +147 -0
  40. package/dist/styles/ImageNavButton.css +35 -0
  41. package/dist/styles/ImageZoomModal.css +101 -0
  42. package/dist/styles/LayerPanel.css +179 -0
  43. package/dist/styles/LoadingOverlay.css +48 -0
  44. package/dist/styles/ProductEditor.css +192 -0
  45. package/dist/styles/TextToolbar.css +327 -0
  46. package/dist/styles/Toolbar.css +125 -0
  47. package/dist/styles/index.css +5 -0
  48. package/dist/styles/textToolbarSelectStyles.d.ts +3 -0
  49. package/dist/styles/textToolbarSelectStyles.js +30 -0
  50. package/dist/types.d.ts +228 -0
  51. package/dist/types.js +17 -0
  52. package/dist/utils/canvasAddText.d.ts +11 -0
  53. package/dist/utils/canvasAddText.js +66 -0
  54. package/dist/utils/canvasUtils.d.ts +37 -0
  55. package/dist/utils/canvasUtils.js +342 -0
  56. package/dist/utils/deviceUtils.d.ts +5 -0
  57. package/dist/utils/deviceUtils.js +33 -0
  58. package/dist/utils/draftTemplateUtils.d.ts +23 -0
  59. package/dist/utils/draftTemplateUtils.js +66 -0
  60. package/dist/utils/grid.d.ts +32 -0
  61. package/dist/utils/grid.js +151 -0
  62. package/dist/utils/imageUtils.d.ts +12 -0
  63. package/dist/utils/imageUtils.js +178 -0
  64. package/dist/utils/job.d.ts +40 -0
  65. package/dist/utils/job.js +115 -0
  66. package/dist/utils/keyboard.d.ts +1 -0
  67. package/dist/utils/keyboard.js +26 -0
  68. package/dist/utils/previewUtils.d.ts +9 -0
  69. package/dist/utils/previewUtils.js +39 -0
  70. package/dist/utils/psdConverter.d.ts +40 -0
  71. package/dist/utils/psdConverter.js +516 -0
  72. package/dist/utils/psdRenderUtils.d.ts +12 -0
  73. package/dist/utils/psdRenderUtils.js +465 -0
  74. package/dist/utils/renderUtils.d.ts +2 -0
  75. package/dist/utils/renderUtils.js +85 -0
  76. package/package.json +66 -0
  77. package/src/components/AlignMenu.tsx +49 -0
  78. package/src/components/FloatingToolbar.tsx +83 -0
  79. package/src/components/FormatButtons.tsx +31 -0
  80. package/src/components/ImageNavButton.tsx +23 -0
  81. package/src/components/ImageZoomModal.tsx +163 -0
  82. package/src/components/LayerPanel.tsx +256 -0
  83. package/src/components/LoadingOverlay.tsx +27 -0
  84. package/src/components/ProductEditor.tsx +104 -0
  85. package/src/components/ProductImageGallery.tsx +181 -0
  86. package/src/components/ProductPreviews.tsx +243 -0
  87. package/src/components/TextToolbar.tsx +164 -0
  88. package/src/components/Toolbar.tsx +86 -0
  89. package/src/config/colorConfig.ts +7 -0
  90. package/src/config/fontConfig.ts +23 -0
  91. package/src/context/ProductEditorContext.tsx +829 -0
  92. package/src/hooks/useSwipeNavigate.ts +40 -0
  93. package/src/index.ts +6 -0
  94. package/src/styles/BottomPreviewDisplay.css +65 -0
  95. package/src/styles/FloatingToolbar.css +41 -0
  96. package/src/styles/ImageGallery.css +147 -0
  97. package/src/styles/ImageNavButton.css +35 -0
  98. package/src/styles/ImageZoomModal.css +101 -0
  99. package/src/styles/LayerPanel.css +179 -0
  100. package/src/styles/LoadingOverlay.css +48 -0
  101. package/src/styles/ProductEditor.css +192 -0
  102. package/src/styles/TextToolbar.css +327 -0
  103. package/src/styles/Toolbar.css +125 -0
  104. package/src/styles/index.css +5 -0
  105. package/src/styles/textToolbarSelectStyles.ts +60 -0
  106. package/src/types/ag-psd/index.d.ts +1 -0
  107. package/src/types/fabric.d.ts +14 -0
  108. package/src/types/lodash/index.d.ts +1 -0
  109. package/src/types/psd.d.ts +53 -0
  110. package/src/types.ts +247 -0
  111. package/src/utils/canvasAddText.ts +72 -0
  112. package/src/utils/canvasUtils.ts +406 -0
  113. package/src/utils/deviceUtils.ts +31 -0
  114. package/src/utils/draftTemplateUtils.ts +70 -0
  115. package/src/utils/grid.ts +154 -0
  116. package/src/utils/imageUtils.ts +218 -0
  117. package/src/utils/job.ts +128 -0
  118. package/src/utils/keyboard.ts +28 -0
  119. package/src/utils/previewUtils.ts +43 -0
  120. package/src/utils/psdConverter.ts +595 -0
  121. package/src/utils/psdRenderUtils.ts +453 -0
  122. package/src/utils/renderUtils.ts +44 -0
  123. package/tsconfig.json +17 -0
@@ -0,0 +1,516 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
50
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
51
+ if (ar || !(i in from)) {
52
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
53
+ ar[i] = from[i];
54
+ }
55
+ }
56
+ return to.concat(ar || Array.prototype.slice.call(from));
57
+ };
58
+ Object.defineProperty(exports, "__esModule", { value: true });
59
+ exports.loadPsdOntoCanvas = exports.extractPsdBaseLayer = void 0;
60
+ var fabric_1 = require("fabric");
61
+ var ag_psd_1 = require("ag-psd");
62
+ var job_1 = require("./job");
63
+ /**
64
+ * Extracts layers from a PSD file and renders them to a PNG
65
+ *
66
+ * @param psdUrl URL to the PSD file
67
+ * @returns Promise that resolves to a PNG data URL
68
+ */
69
+ var extractPsdBaseLayer = function (psdUrl) { return __awaiter(void 0, void 0, void 0, function () {
70
+ var response, arrayBuffer, firstBytes, signature, psd, canvas, ctx, designBounds, imageData, layers, designLayer, maskLayer, contentLayers, _i, layers_1, layer, renderLayer_1, processLayer_1, _a, contentLayers_1, layer, dataUrl, blob, objectUrl_1, img_1, error_1;
71
+ return __generator(this, function (_b) {
72
+ switch (_b.label) {
73
+ case 0:
74
+ _b.trys.push([0, 3, , 4]);
75
+ return [4 /*yield*/, fetch(psdUrl, {
76
+ mode: 'cors',
77
+ credentials: 'same-origin',
78
+ headers: {
79
+ 'Accept': '*/*',
80
+ }
81
+ })];
82
+ case 1:
83
+ response = _b.sent();
84
+ if (!response.ok) {
85
+ throw new Error("Failed to fetch PSD file: ".concat(response.status, " ").concat(response.statusText));
86
+ }
87
+ return [4 /*yield*/, response.arrayBuffer()];
88
+ case 2:
89
+ arrayBuffer = _b.sent();
90
+ firstBytes = new Uint8Array(arrayBuffer, 0, 4);
91
+ signature = String.fromCharCode(firstBytes[0]) +
92
+ String.fromCharCode(firstBytes[1]) +
93
+ String.fromCharCode(firstBytes[2]) +
94
+ String.fromCharCode(firstBytes[3]);
95
+ if (signature !== '8BPS') {
96
+ // TODO handle different file types
97
+ console.warn('Warning: File does not have PSD signature. Got:', signature);
98
+ // Continue anyway - the server might be returning a different format
99
+ }
100
+ try {
101
+ psd = (0, ag_psd_1.readPsd)(arrayBuffer, {
102
+ skipCompositeImageData: false,
103
+ skipLayerImageData: false,
104
+ skipThumbnail: false
105
+ });
106
+ canvas = document.createElement('canvas');
107
+ canvas.width = psd.width;
108
+ canvas.height = psd.height;
109
+ ctx = canvas.getContext('2d');
110
+ if (!ctx) {
111
+ throw new Error('Could not get canvas context');
112
+ }
113
+ designBounds = void 0;
114
+ // If there are no layers or children, try to use the document itself
115
+ if (!psd.children || psd.children.length === 0) {
116
+ if (psd.imageData) {
117
+ imageData = new ImageData(new Uint8ClampedArray(psd.imageData.data), psd.width, psd.height);
118
+ ctx.putImageData(imageData, 0, 0);
119
+ }
120
+ else {
121
+ throw new Error('No layers or composite image data found in PSD');
122
+ }
123
+ }
124
+ else {
125
+ layers = __spreadArray([], psd.children, true);
126
+ designLayer = null;
127
+ maskLayer = null;
128
+ contentLayers = [];
129
+ // First pass - identify special layers and regular content layers
130
+ for (_i = 0, layers_1 = layers; _i < layers_1.length; _i++) {
131
+ layer = layers_1[_i];
132
+ if (layer.name === 'Design') {
133
+ designLayer = layer;
134
+ // Store design layer bounds for future reference
135
+ if (typeof layer.left === 'number' &&
136
+ typeof layer.top === 'number' &&
137
+ typeof layer.right === 'number' &&
138
+ typeof layer.bottom === 'number') {
139
+ designBounds = {
140
+ left: layer.left,
141
+ top: layer.top,
142
+ right: layer.right,
143
+ bottom: layer.bottom
144
+ };
145
+ }
146
+ }
147
+ else if (layer.name === 'Mask') {
148
+ maskLayer = layer;
149
+ }
150
+ else {
151
+ contentLayers.push(layer);
152
+ }
153
+ }
154
+ renderLayer_1 = function (layer, ctx) {
155
+ // Check if the layer has a canvas
156
+ if (layer.canvas &&
157
+ typeof layer.left === 'number' &&
158
+ typeof layer.top === 'number') {
159
+ // Apply layer blending and opacity
160
+ ctx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1;
161
+ // Draw this layer onto the main canvas at its position
162
+ ctx.drawImage(layer.canvas, layer.left, layer.top);
163
+ // Reset alpha
164
+ ctx.globalAlpha = 1;
165
+ }
166
+ else if (layer.imageData &&
167
+ typeof layer.left === 'number' &&
168
+ typeof layer.top === 'number') {
169
+ // Create a temporary canvas for this layer
170
+ var layerCanvas = document.createElement('canvas');
171
+ var width = layer.right - layer.left;
172
+ var height = layer.bottom - layer.top;
173
+ layerCanvas.width = width;
174
+ layerCanvas.height = height;
175
+ var layerCtx = layerCanvas.getContext('2d');
176
+ if (layerCtx && layer.imageData) {
177
+ // Create an ImageData object from the PSD image data
178
+ var imageData = new ImageData(new Uint8ClampedArray(layer.imageData.data), width, height);
179
+ // Put the layer's image data on this canvas
180
+ layerCtx.putImageData(imageData, 0, 0);
181
+ // Apply layer blending and opacity
182
+ ctx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1;
183
+ // Draw this layer onto the main canvas at its position
184
+ ctx.drawImage(layerCanvas, layer.left, layer.top);
185
+ // Reset alpha
186
+ ctx.globalAlpha = 1;
187
+ }
188
+ }
189
+ else {
190
+ console.warn("Layer \"".concat(layer.name, "\" has no canvas or imageData"));
191
+ }
192
+ };
193
+ processLayer_1 = function (layer, ctx) {
194
+ // Skip hidden layers
195
+ if (layer.hidden) {
196
+ return;
197
+ }
198
+ // If this is a group layer with children, process its children
199
+ if (layer.children && layer.children.length > 0) {
200
+ // Process children
201
+ var children = __spreadArray([], layer.children, true);
202
+ children.forEach(function (child) { return processLayer_1(child, ctx); });
203
+ return;
204
+ }
205
+ // Render the actual layer
206
+ renderLayer_1(layer, ctx);
207
+ };
208
+ // Render in the correct order:
209
+ // 1. First render the "Design" layer (margins/boundaries)
210
+ if (designLayer) {
211
+ processLayer_1(designLayer, ctx);
212
+ }
213
+ // 2. Then render all content layers
214
+ for (_a = 0, contentLayers_1 = contentLayers; _a < contentLayers_1.length; _a++) {
215
+ layer = contentLayers_1[_a];
216
+ processLayer_1(layer, ctx);
217
+ }
218
+ // 3. Finally render the "Mask" layer on top to hide overflow
219
+ if (maskLayer) {
220
+ processLayer_1(maskLayer, ctx);
221
+ }
222
+ }
223
+ dataUrl = canvas.toDataURL('image/png');
224
+ // Return both the data URL and the design bounds if found
225
+ return [2 /*return*/, { dataUrl: dataUrl, designBounds: designBounds }];
226
+ }
227
+ catch (parseError) {
228
+ blob = new Blob([arrayBuffer], {
229
+ type: response.headers.get('content-type') || 'application/octet-stream'
230
+ });
231
+ objectUrl_1 = URL.createObjectURL(blob);
232
+ img_1 = new Image();
233
+ return [2 /*return*/, new Promise(function (resolve, reject) {
234
+ img_1.onload = function () {
235
+ var canvas = document.createElement('canvas');
236
+ canvas.width = img_1.width;
237
+ canvas.height = img_1.height;
238
+ var ctx = canvas.getContext('2d');
239
+ if (!ctx) {
240
+ reject(new Error('Could not get canvas context'));
241
+ return;
242
+ }
243
+ ctx.drawImage(img_1, 0, 0);
244
+ var dataUrl = canvas.toDataURL('image/png');
245
+ URL.revokeObjectURL(objectUrl_1);
246
+ resolve({ dataUrl: dataUrl });
247
+ };
248
+ img_1.onerror = function () {
249
+ URL.revokeObjectURL(objectUrl_1);
250
+ reject(new Error('Could not parse PSD or load as image'));
251
+ };
252
+ img_1.src = objectUrl_1;
253
+ })];
254
+ }
255
+ return [3 /*break*/, 4];
256
+ case 3:
257
+ error_1 = _b.sent();
258
+ throw error_1;
259
+ case 4: return [2 /*return*/];
260
+ }
261
+ });
262
+ }); };
263
+ exports.extractPsdBaseLayer = extractPsdBaseLayer;
264
+ /**
265
+ * Loads a PSD file onto a fabric.js canvas
266
+ *
267
+ * @param canvas fabric.js Canvas instance
268
+ * @param psdUrl URL to the PSD file
269
+ * @param width Canvas width
270
+ * @param height Canvas height
271
+ * @returns Promise that resolves when the image is added to the canvas
272
+ */
273
+ var loadPsdOntoCanvas = function (canvas, psdUrl, variations, savedObjects, width, height) { return __awaiter(void 0, void 0, void 0, function () {
274
+ var canvasRef_1, _a, dataUrl_1, designBounds_1, error_2;
275
+ return __generator(this, function (_b) {
276
+ switch (_b.label) {
277
+ case 0:
278
+ _b.trys.push([0, 2, , 3]);
279
+ canvasRef_1 = canvas;
280
+ // Store the current psdUrl on the canvas to help track which operation is active
281
+ canvasRef_1.psdUrl = psdUrl;
282
+ return [4 /*yield*/, (0, exports.extractPsdBaseLayer)(psdUrl)];
283
+ case 1:
284
+ _a = _b.sent(), dataUrl_1 = _a.dataUrl, designBounds_1 = _a.designBounds;
285
+ return [2 /*return*/, new Promise(function (resolve, reject) {
286
+ // Check if the canvas is still the same one that requested this operation
287
+ if (!canvasRef_1 || canvasRef_1.psdUrl !== psdUrl) {
288
+ console.warn('Canvas changed or disposed during PSD processing, aborting.');
289
+ resolve();
290
+ return;
291
+ }
292
+ fabric_1.fabric.Image.fromURL(dataUrl_1, function (img) {
293
+ // Check again if the canvas is still valid
294
+ if (!canvasRef_1 || canvasRef_1.psdUrl !== psdUrl) {
295
+ console.warn('Canvas changed or disposed during image loading, aborting.');
296
+ resolve();
297
+ return;
298
+ }
299
+ if (!img || !img.width || !img.height) {
300
+ reject(new Error('Failed to create fabric image from PSD'));
301
+ return;
302
+ }
303
+ // Scale image to fit canvas
304
+ var scale = Math.min(width / img.width, height / img.height);
305
+ // Center the image - important for design bounds calculation
306
+ var imgLeft = (width - img.width * scale) / 2;
307
+ var imgTop = (height - img.height * scale) / 2;
308
+ // Set image scale and position
309
+ img.scaleX = scale;
310
+ img.scaleY = scale;
311
+ img.left = imgLeft;
312
+ img.top = imgTop;
313
+ img.selectable = false;
314
+ img.evented = false;
315
+ // Add image to canvas - check canvas validity first
316
+ if (!canvasRef_1 || canvasRef_1.psdUrl !== psdUrl) {
317
+ console.warn('Canvas changed or disposed before adding image, aborting.');
318
+ resolve();
319
+ return;
320
+ }
321
+ canvasRef_1.add(img);
322
+ // If we have design bounds, store them for reference
323
+ if (designBounds_1) {
324
+ // Calculate scaled design bounds
325
+ var scaledDesignBounds_1 = {
326
+ left: imgLeft + (designBounds_1.left * scale),
327
+ top: imgTop + (designBounds_1.top * scale),
328
+ width: (designBounds_1.right - designBounds_1.left) * scale,
329
+ height: (designBounds_1.bottom - designBounds_1.top) * scale,
330
+ right: imgLeft + (designBounds_1.right * scale),
331
+ bottom: imgTop + (designBounds_1.bottom * scale)
332
+ };
333
+ // Check canvas validity before continuing
334
+ if (!canvasRef_1 || canvasRef_1.psdUrl !== psdUrl) {
335
+ console.warn('Canvas changed or disposed before adding design bounds, aborting.');
336
+ resolve();
337
+ return;
338
+ }
339
+ // Store on the canvas for future reference
340
+ canvasRef_1.designBounds = scaledDesignBounds_1;
341
+ // Add a visual indicator of the design area
342
+ var boundaryRect = new fabric_1.fabric.Rect({
343
+ left: scaledDesignBounds_1.left,
344
+ top: scaledDesignBounds_1.top,
345
+ width: scaledDesignBounds_1.width,
346
+ height: scaledDesignBounds_1.height,
347
+ fill: 'transparent',
348
+ stroke: 'rgba(255, 0, 0, 0.5)',
349
+ strokeWidth: 1,
350
+ strokeDashArray: [5, 5],
351
+ selectable: false,
352
+ evented: false,
353
+ id: 'design-boundary-rect'
354
+ });
355
+ // Check canvas validity before adding rect
356
+ if (!canvasRef_1 || canvasRef_1.psdUrl !== psdUrl) {
357
+ console.warn('Canvas changed or disposed before adding boundary rect, aborting.');
358
+ resolve();
359
+ return;
360
+ }
361
+ canvasRef_1.add(boundaryRect);
362
+ // Create a clip path for the text based on design bounds
363
+ var clipPath_1 = new fabric_1.fabric.Rect({
364
+ left: scaledDesignBounds_1.left,
365
+ top: scaledDesignBounds_1.top,
366
+ width: scaledDesignBounds_1.width,
367
+ height: scaledDesignBounds_1.height,
368
+ absolutePositioned: true
369
+ });
370
+ // Convert variations into canvas objects which obay the design bounds here
371
+ if (variations && variations.length > 0) {
372
+ // Process each variation to create appropriate canvas objects
373
+ variations.forEach(function (variation) {
374
+ if (!variation) {
375
+ return; // Skip invalid variations
376
+ }
377
+ // Get common positioning within design bounds
378
+ var objectLeft = scaledDesignBounds_1.left + scaledDesignBounds_1.width / 2;
379
+ var objectTop = scaledDesignBounds_1.top + scaledDesignBounds_1.height / 2;
380
+ // Extract the field type and value from the variation
381
+ var canvasObjectType = variation.canvasObjectType, file = variation.file, fieldId = variation.fieldId, fontFamily = variation.fontFamily, fontSize = variation.fontSize;
382
+ var value = variation.value;
383
+ // Check if this variation exists in savedObjects
384
+ var savedObject = savedObjects.find(function (obj) { return obj.fieldId === fieldId; });
385
+ // Create canvas
386
+ var canvasObject;
387
+ // Handle text variations
388
+ if (canvasObjectType === 'text') {
389
+ // Create the text object with either saved or defaults
390
+ if (savedObject) {
391
+ // Create text with default first
392
+ canvasObject = new fabric_1.fabric.IText((value === null || value === void 0 ? void 0 : value.toString()) || 'Text', __assign(__assign({}, savedObject), { left: savedObject.left || objectLeft, top: savedObject.top || objectTop, fontFamily: savedObject.fontFamily || fontFamily, fontSize: savedObject.fontSize || fontSize, fill: savedObject.fill || '#000000', originX: savedObject.originX || 'center', originY: savedObject.originY || 'center', selectable: true, editable: true, text: value === null || value === void 0 ? void 0 : value.toString(), scaleX: savedObject.scaleX || 1, scaleY: savedObject.scaleY || 1, angle: savedObject.angle || 0 }));
393
+ }
394
+ else {
395
+ // Create with default properties
396
+ canvasObject = new fabric_1.fabric.IText((value === null || value === void 0 ? void 0 : value.toString()) || 'Text', {
397
+ left: objectLeft,
398
+ top: objectTop,
399
+ fontFamily: fontFamily,
400
+ fontSize: fontSize,
401
+ fill: '#000000',
402
+ originX: 'center',
403
+ originY: 'center',
404
+ selectable: true,
405
+ editable: false,
406
+ text: value === null || value === void 0 ? void 0 : value.toString(),
407
+ });
408
+ }
409
+ // Store fieldId as a custom property
410
+ canvasObject.fieldId = fieldId;
411
+ // Store uniqueId if it exists in the saved object
412
+ canvasObject.uniqueId = (savedObject === null || savedObject === void 0 ? void 0 : savedObject.uniqueId) || (0, job_1.generateUniqueId)();
413
+ // Apply the clip path to the text
414
+ // Omit clip path for now to restore movability
415
+ canvasObject.clipPath = clipPath_1;
416
+ canvasRef_1.add(canvasObject);
417
+ }
418
+ // Handle image variations
419
+ else if (canvasObjectType === "image") {
420
+ // Get the file ID for comparison with saved objects
421
+ var fileId_1 = file === null || file === void 0 ? void 0 : file.id;
422
+ // Find by both fieldId and fileId for images
423
+ var savedImageObject_1 = fileId_1 ?
424
+ savedObjects.find(function (obj) { return obj.fieldId === fieldId && obj.fileId === fileId_1; }) :
425
+ savedObject;
426
+ if (file && file.viewUrl) {
427
+ fabric_1.fabric.Image.fromURL(file.viewUrl, function (img) {
428
+ if (!img)
429
+ return;
430
+ // Default scaling to fit design bounds
431
+ var maxWidth = scaledDesignBounds_1.width * 0.8;
432
+ var maxHeight = scaledDesignBounds_1.height * 0.8;
433
+ var defaultScale = Math.min(maxWidth / img.width, maxHeight / img.height, 1);
434
+ if (savedImageObject_1) {
435
+ // Apply saved properties
436
+ img.set(__assign(__assign({}, savedImageObject_1), { left: savedImageObject_1.left || objectLeft, top: savedImageObject_1.top || objectTop, scaleX: savedImageObject_1.scaleX || defaultScale, scaleY: savedImageObject_1.scaleY || defaultScale, angle: savedImageObject_1.angle || 0, originX: savedImageObject_1.originX || 'center', originY: savedImageObject_1.originY || 'center', cornerSize: 8, borderColor: '#303DBF', cornerColor: '#303DBF', cornerStrokeColor: '#303DBF', transparentCorners: false, selectable: true, crossOrigin: 'anonymous' }));
437
+ // Store uniqueId if it exists
438
+ img.uniqueId = (savedImageObject_1 === null || savedImageObject_1 === void 0 ? void 0 : savedImageObject_1.uniqueId) || (0, job_1.generateUniqueId)();
439
+ }
440
+ else {
441
+ // Apply default properties
442
+ img.scale(defaultScale);
443
+ img.set({
444
+ left: objectLeft,
445
+ top: objectTop,
446
+ originX: 'center',
447
+ originY: 'center',
448
+ cornerSize: 8,
449
+ borderColor: '#303DBF',
450
+ cornerColor: '#303DBF',
451
+ cornerStrokeColor: '#303DBF',
452
+ transparentCorners: false,
453
+ selectable: true,
454
+ crossOrigin: 'anonymous',
455
+ });
456
+ }
457
+ // Store fieldId and fileId as custom properties
458
+ img.fieldId = fieldId;
459
+ if (fileId_1) {
460
+ img.fileId = fileId_1;
461
+ }
462
+ img.uniqueId = (0, job_1.generateUniqueId)();
463
+ // Apply clip path
464
+ var imageClipPath = new fabric_1.fabric.Rect({
465
+ left: scaledDesignBounds_1.left,
466
+ top: scaledDesignBounds_1.top,
467
+ width: scaledDesignBounds_1.width,
468
+ height: scaledDesignBounds_1.height,
469
+ absolutePositioned: true
470
+ });
471
+ img.clipPath = imageClipPath;
472
+ // Check canvas validity before adding
473
+ if (!canvasRef_1 || canvasRef_1.psdUrl !== psdUrl) {
474
+ return;
475
+ }
476
+ canvasRef_1.add(img);
477
+ canvasRef_1.renderAll();
478
+ }, { crossOrigin: 'anonymous' });
479
+ }
480
+ }
481
+ });
482
+ }
483
+ // Check canvas validity before adding text
484
+ if (!canvasRef_1 || canvasRef_1.psdUrl !== psdUrl) {
485
+ console.warn('Canvas changed or disposed before adding test text, aborting.');
486
+ resolve();
487
+ return;
488
+ }
489
+ }
490
+ // Final check before renderAll
491
+ if (!canvasRef_1 || canvasRef_1.psdUrl !== psdUrl) {
492
+ console.warn('Canvas changed or disposed before final render, aborting.');
493
+ resolve();
494
+ return;
495
+ }
496
+ // Try to render the canvas, with error handling
497
+ try {
498
+ if (canvasRef_1 && canvasRef_1.renderAll) {
499
+ canvasRef_1.renderAll();
500
+ }
501
+ }
502
+ catch (e) {
503
+ console.error('Error rendering canvas:', e);
504
+ }
505
+ resolve();
506
+ }, { crossOrigin: 'anonymous' });
507
+ })];
508
+ case 2:
509
+ error_2 = _b.sent();
510
+ console.error('Error loading PSD onto canvas:', error_2);
511
+ throw error_2;
512
+ case 3: return [2 /*return*/];
513
+ }
514
+ });
515
+ }); };
516
+ exports.loadPsdOntoCanvas = loadPsdOntoCanvas;
@@ -0,0 +1,12 @@
1
+ import { MappedPreview } from '../types';
2
+ /**
3
+ * Process mapped previews, replacing layers in PSD files with rendered layers
4
+ * and converting the results to PNG images
5
+ *
6
+ * @param mappedPreviews Array of mapped previews with draftPreview and draftPreviewLayers
7
+ * @returns Promise that resolves to an array of processed previews with PNG data URLs
8
+ */
9
+ export declare function renderDraftPreviewsWithLayers(mappedPreviews: MappedPreview[]): Promise<Array<{
10
+ draftPreviewId: number | undefined;
11
+ pngDataUrl: string;
12
+ }>>;