@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.
- package/.turbo/turbo-build.log +1 -0
- package/README.md +174 -0
- package/dist/components/AlignMenu.d.ts +3 -0
- package/dist/components/AlignMenu.js +61 -0
- package/dist/components/FloatingToolbar.d.ts +4 -0
- package/dist/components/FloatingToolbar.js +97 -0
- package/dist/components/FormatButtons.d.ts +2 -0
- package/dist/components/FormatButtons.js +22 -0
- package/dist/components/ImageNavButton.d.ts +7 -0
- package/dist/components/ImageNavButton.js +14 -0
- package/dist/components/ImageZoomModal.d.ts +12 -0
- package/dist/components/ImageZoomModal.js +129 -0
- package/dist/components/LayerPanel.d.ts +4 -0
- package/dist/components/LayerPanel.js +223 -0
- package/dist/components/LoadingOverlay.d.ts +9 -0
- package/dist/components/LoadingOverlay.js +17 -0
- package/dist/components/ProductEditor.d.ts +4 -0
- package/dist/components/ProductEditor.js +67 -0
- package/dist/components/ProductImageGallery.d.ts +6 -0
- package/dist/components/ProductImageGallery.js +148 -0
- package/dist/components/ProductPreviews.d.ts +7 -0
- package/dist/components/ProductPreviews.js +281 -0
- package/dist/components/TextToolbar.d.ts +4 -0
- package/dist/components/TextToolbar.js +117 -0
- package/dist/components/Toolbar.d.ts +3 -0
- package/dist/components/Toolbar.js +47 -0
- package/dist/config/colorConfig.d.ts +1 -0
- package/dist/config/colorConfig.js +10 -0
- package/dist/config/fontConfig.d.ts +5 -0
- package/dist/config/fontConfig.js +21 -0
- package/dist/context/ProductEditorContext.d.ts +60 -0
- package/dist/context/ProductEditorContext.js +743 -0
- package/dist/hooks/useSwipeNavigate.d.ts +11 -0
- package/dist/hooks/useSwipeNavigate.js +35 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +30 -0
- package/dist/styles/BottomPreviewDisplay.css +65 -0
- package/dist/styles/FloatingToolbar.css +41 -0
- package/dist/styles/ImageGallery.css +147 -0
- package/dist/styles/ImageNavButton.css +35 -0
- package/dist/styles/ImageZoomModal.css +101 -0
- package/dist/styles/LayerPanel.css +179 -0
- package/dist/styles/LoadingOverlay.css +48 -0
- package/dist/styles/ProductEditor.css +192 -0
- package/dist/styles/TextToolbar.css +327 -0
- package/dist/styles/Toolbar.css +125 -0
- package/dist/styles/index.css +5 -0
- package/dist/styles/textToolbarSelectStyles.d.ts +3 -0
- package/dist/styles/textToolbarSelectStyles.js +30 -0
- package/dist/types.d.ts +228 -0
- package/dist/types.js +17 -0
- package/dist/utils/canvasAddText.d.ts +11 -0
- package/dist/utils/canvasAddText.js +66 -0
- package/dist/utils/canvasUtils.d.ts +37 -0
- package/dist/utils/canvasUtils.js +342 -0
- package/dist/utils/deviceUtils.d.ts +5 -0
- package/dist/utils/deviceUtils.js +33 -0
- package/dist/utils/draftTemplateUtils.d.ts +23 -0
- package/dist/utils/draftTemplateUtils.js +66 -0
- package/dist/utils/grid.d.ts +32 -0
- package/dist/utils/grid.js +151 -0
- package/dist/utils/imageUtils.d.ts +12 -0
- package/dist/utils/imageUtils.js +178 -0
- package/dist/utils/job.d.ts +40 -0
- package/dist/utils/job.js +115 -0
- package/dist/utils/keyboard.d.ts +1 -0
- package/dist/utils/keyboard.js +26 -0
- package/dist/utils/previewUtils.d.ts +9 -0
- package/dist/utils/previewUtils.js +39 -0
- package/dist/utils/psdConverter.d.ts +40 -0
- package/dist/utils/psdConverter.js +516 -0
- package/dist/utils/psdRenderUtils.d.ts +12 -0
- package/dist/utils/psdRenderUtils.js +465 -0
- package/dist/utils/renderUtils.d.ts +2 -0
- package/dist/utils/renderUtils.js +85 -0
- package/package.json +66 -0
- package/src/components/AlignMenu.tsx +49 -0
- package/src/components/FloatingToolbar.tsx +83 -0
- package/src/components/FormatButtons.tsx +31 -0
- package/src/components/ImageNavButton.tsx +23 -0
- package/src/components/ImageZoomModal.tsx +163 -0
- package/src/components/LayerPanel.tsx +256 -0
- package/src/components/LoadingOverlay.tsx +27 -0
- package/src/components/ProductEditor.tsx +104 -0
- package/src/components/ProductImageGallery.tsx +181 -0
- package/src/components/ProductPreviews.tsx +243 -0
- package/src/components/TextToolbar.tsx +164 -0
- package/src/components/Toolbar.tsx +86 -0
- package/src/config/colorConfig.ts +7 -0
- package/src/config/fontConfig.ts +23 -0
- package/src/context/ProductEditorContext.tsx +829 -0
- package/src/hooks/useSwipeNavigate.ts +40 -0
- package/src/index.ts +6 -0
- package/src/styles/BottomPreviewDisplay.css +65 -0
- package/src/styles/FloatingToolbar.css +41 -0
- package/src/styles/ImageGallery.css +147 -0
- package/src/styles/ImageNavButton.css +35 -0
- package/src/styles/ImageZoomModal.css +101 -0
- package/src/styles/LayerPanel.css +179 -0
- package/src/styles/LoadingOverlay.css +48 -0
- package/src/styles/ProductEditor.css +192 -0
- package/src/styles/TextToolbar.css +327 -0
- package/src/styles/Toolbar.css +125 -0
- package/src/styles/index.css +5 -0
- package/src/styles/textToolbarSelectStyles.ts +60 -0
- package/src/types/ag-psd/index.d.ts +1 -0
- package/src/types/fabric.d.ts +14 -0
- package/src/types/lodash/index.d.ts +1 -0
- package/src/types/psd.d.ts +53 -0
- package/src/types.ts +247 -0
- package/src/utils/canvasAddText.ts +72 -0
- package/src/utils/canvasUtils.ts +406 -0
- package/src/utils/deviceUtils.ts +31 -0
- package/src/utils/draftTemplateUtils.ts +70 -0
- package/src/utils/grid.ts +154 -0
- package/src/utils/imageUtils.ts +218 -0
- package/src/utils/job.ts +128 -0
- package/src/utils/keyboard.ts +28 -0
- package/src/utils/previewUtils.ts +43 -0
- package/src/utils/psdConverter.ts +595 -0
- package/src/utils/psdRenderUtils.ts +453 -0
- package/src/utils/renderUtils.ts +44 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
3
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
4
|
+
if (ar || !(i in from)) {
|
|
5
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
6
|
+
ar[i] = from[i];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.renderClippedImage = exports.renderCanvasWithoutGrid = exports.addTextToCanvas = void 0;
|
|
13
|
+
var fabric_1 = require("fabric");
|
|
14
|
+
/**
|
|
15
|
+
* Adds an editable text object to the canvas
|
|
16
|
+
* @param canvas - The Fabric.js canvas instance
|
|
17
|
+
* @param width - The width of the canvas
|
|
18
|
+
* @param height - The height of the canvas
|
|
19
|
+
* @param defaultText - Optional default text (defaults to "Text")
|
|
20
|
+
* @param fontSize - Optional font size (defaults to 24)
|
|
21
|
+
* @param fontFamily - Optional font family (defaults to Arial)
|
|
22
|
+
*/
|
|
23
|
+
var addTextToCanvas = function (canvas, width, height, defaultText, fontSize, fontFamily) {
|
|
24
|
+
if (defaultText === void 0) { defaultText = 'Text'; }
|
|
25
|
+
if (fontSize === void 0) { fontSize = 24; }
|
|
26
|
+
if (fontFamily === void 0) { fontFamily = 'Nunito'; }
|
|
27
|
+
if (!canvas)
|
|
28
|
+
return null;
|
|
29
|
+
try {
|
|
30
|
+
// Safe check if canvas is still valid
|
|
31
|
+
if (!canvas.getElement() || !canvas.getElement().parentNode) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
// Create a new text object with minimal options
|
|
35
|
+
var text_1 = new fabric_1.fabric.IText(defaultText, {
|
|
36
|
+
left: width / 2,
|
|
37
|
+
top: height / 2,
|
|
38
|
+
fontFamily: fontFamily,
|
|
39
|
+
fontSize: fontSize,
|
|
40
|
+
fill: '#000000',
|
|
41
|
+
originX: 'center',
|
|
42
|
+
originY: 'center',
|
|
43
|
+
selectable: true,
|
|
44
|
+
editable: false
|
|
45
|
+
});
|
|
46
|
+
// Add the text to the canvas
|
|
47
|
+
canvas.add(text_1);
|
|
48
|
+
// Ensure the text is rendered
|
|
49
|
+
canvas.renderAll();
|
|
50
|
+
// Make the text active - this is critical
|
|
51
|
+
var setActiveTextObject = function () {
|
|
52
|
+
try {
|
|
53
|
+
// Check if canvas is still valid
|
|
54
|
+
if (canvas && canvas.getElement() && canvas.getElement().parentNode) {
|
|
55
|
+
canvas.setActiveObject(text_1);
|
|
56
|
+
canvas.renderAll();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.error('Error setting active text object:', err);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
// Initial selection
|
|
64
|
+
setActiveTextObject();
|
|
65
|
+
// Delayed selection to ensure text becomes active
|
|
66
|
+
setTimeout(setActiveTextObject, 50);
|
|
67
|
+
return text_1;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error('Error adding text to canvas:', error);
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
exports.addTextToCanvas = addTextToCanvas;
|
|
75
|
+
/**
|
|
76
|
+
* Renders the entire canvas as an image without displaying grid elements
|
|
77
|
+
*
|
|
78
|
+
* @param canvas - The Fabric.js canvas instance
|
|
79
|
+
* @param options - Optional rendering options
|
|
80
|
+
* @returns A promise that resolves to the dataURL of the canvas without grid
|
|
81
|
+
*/
|
|
82
|
+
var renderCanvasWithoutGrid = function (canvas, options) {
|
|
83
|
+
return new Promise(function (resolve) {
|
|
84
|
+
if (!canvas) {
|
|
85
|
+
console.error('Canvas is null or undefined');
|
|
86
|
+
resolve(null);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
// Get all objects on the canvas
|
|
91
|
+
var objects = canvas.getObjects();
|
|
92
|
+
// Store original visibility of each object
|
|
93
|
+
var originalVisibilities_1 = objects.map(function (obj) { return ({
|
|
94
|
+
object: obj,
|
|
95
|
+
visible: obj.visible
|
|
96
|
+
}); });
|
|
97
|
+
// Hide grid elements - typically grid elements might have a specific ID or class
|
|
98
|
+
// You may need to adjust this logic based on how grid elements are identified
|
|
99
|
+
objects.forEach(function (obj) {
|
|
100
|
+
var _a, _b, _c, _d, _e;
|
|
101
|
+
// Hide objects that represent grid elements
|
|
102
|
+
// This assumes grid elements have a property like 'type' or 'id' that identifies them
|
|
103
|
+
if (((_a = obj.id) === null || _a === void 0 ? void 0 : _a.includes('grid')) ||
|
|
104
|
+
obj.type === 'grid' ||
|
|
105
|
+
obj.isGridElement ||
|
|
106
|
+
(
|
|
107
|
+
// Add more comprehensive grid detection
|
|
108
|
+
(_b = obj.data) === null || _b === void 0 ? void 0 : _b.isGrid) ||
|
|
109
|
+
((_c = obj.name) === null || _c === void 0 ? void 0 : _c.includes('grid')) ||
|
|
110
|
+
((_d = obj.className) === null || _d === void 0 ? void 0 : _d.includes('grid')) ||
|
|
111
|
+
// Check for common grid-related properties
|
|
112
|
+
obj.strokeDashArray || // Dashed lines are often used for grids
|
|
113
|
+
// Check for line objects with evenly spaced positions (typical grid pattern)
|
|
114
|
+
(obj.type === 'line' && (obj.x1 === obj.x2 || obj.y1 === obj.y2)) ||
|
|
115
|
+
(
|
|
116
|
+
// Check for objects tagged with grid-related classes
|
|
117
|
+
(_e = obj.classes) === null || _e === void 0 ? void 0 : _e.includes('grid')) ||
|
|
118
|
+
// Check for objects with certain grid styling
|
|
119
|
+
(obj.stroke &&
|
|
120
|
+
(obj.strokeWidth === 0.5 || obj.strokeWidth === 1) &&
|
|
121
|
+
(obj.stroke === '#ddd' || obj.stroke === '#eee' || obj.stroke === 'rgba(0,0,0,0.1)'))) {
|
|
122
|
+
obj.visible = false;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
// Save the original selection state
|
|
126
|
+
var originalSelectionBorder = canvas.selectionBorderColor;
|
|
127
|
+
var originalSelectionColor = canvas.selectionColor;
|
|
128
|
+
var originalActiveObject = canvas.getActiveObject();
|
|
129
|
+
// Temporarily disable selection indicators
|
|
130
|
+
canvas.selectionBorderColor = 'transparent';
|
|
131
|
+
canvas.selectionColor = 'transparent';
|
|
132
|
+
canvas.discardActiveObject();
|
|
133
|
+
// Apply any background color if specified
|
|
134
|
+
var originalBackgroundColor = canvas.backgroundColor;
|
|
135
|
+
if ((options === null || options === void 0 ? void 0 : options.backgroundColor) !== undefined) {
|
|
136
|
+
canvas.backgroundColor = options.backgroundColor || 'transparent';
|
|
137
|
+
}
|
|
138
|
+
// Render the canvas
|
|
139
|
+
canvas.renderAll();
|
|
140
|
+
// Get rendering options
|
|
141
|
+
var format = (options === null || options === void 0 ? void 0 : options.format) || 'png';
|
|
142
|
+
var quality = (options === null || options === void 0 ? void 0 : options.quality) || 1;
|
|
143
|
+
var multiplier = (options === null || options === void 0 ? void 0 : options.multiplier) || 1;
|
|
144
|
+
// Create a data URL from the canvas
|
|
145
|
+
try {
|
|
146
|
+
var dataUrl = canvas.toDataURL({
|
|
147
|
+
format: format,
|
|
148
|
+
quality: quality,
|
|
149
|
+
multiplier: multiplier
|
|
150
|
+
});
|
|
151
|
+
// Restore the original state
|
|
152
|
+
objects.forEach(function (obj, index) {
|
|
153
|
+
obj.visible = originalVisibilities_1[index].visible;
|
|
154
|
+
});
|
|
155
|
+
// Restore selection state
|
|
156
|
+
canvas.selectionBorderColor = originalSelectionBorder;
|
|
157
|
+
canvas.selectionColor = originalSelectionColor;
|
|
158
|
+
if (originalActiveObject) {
|
|
159
|
+
canvas.setActiveObject(originalActiveObject);
|
|
160
|
+
}
|
|
161
|
+
// Restore background color
|
|
162
|
+
canvas.backgroundColor = originalBackgroundColor;
|
|
163
|
+
// Render with original state
|
|
164
|
+
canvas.renderAll();
|
|
165
|
+
resolve(dataUrl);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
console.error('Error generating data URL:', error);
|
|
169
|
+
resolve(null);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
console.error('Error rendering canvas without grid:', error);
|
|
174
|
+
resolve(null);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
exports.renderCanvasWithoutGrid = renderCanvasWithoutGrid;
|
|
179
|
+
/**
|
|
180
|
+
* Renders an image containing only what's visible inside a clipPath on the canvas
|
|
181
|
+
*
|
|
182
|
+
* @param canvas - The Fabric.js canvas instance
|
|
183
|
+
* @param options - Optional rendering options
|
|
184
|
+
* @returns A promise that resolves to the dataURL of the contents inside the clipPath, or null if no clipped object is found
|
|
185
|
+
*/
|
|
186
|
+
var renderClippedImage = function (canvas, options) {
|
|
187
|
+
return new Promise(function (resolve) {
|
|
188
|
+
if (!canvas) {
|
|
189
|
+
console.error('Canvas is null or undefined');
|
|
190
|
+
resolve(null);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
// Find objects with clipPath
|
|
195
|
+
var objects = canvas.getObjects();
|
|
196
|
+
var targetObject = null;
|
|
197
|
+
targetObject = objects.find(function (obj) { return obj.id === 'design-boundary-rect'; }) || null;
|
|
198
|
+
if (!targetObject) {
|
|
199
|
+
console.warn('No boundary object found');
|
|
200
|
+
resolve(null);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
// Get bounds of the object with clipPath
|
|
204
|
+
var objBounds = targetObject.getBoundingRect();
|
|
205
|
+
// Create a new canvas element
|
|
206
|
+
var dpr = window.devicePixelRatio || 1;
|
|
207
|
+
var tempCanvasEl = document.createElement('canvas');
|
|
208
|
+
tempCanvasEl.width = objBounds.width * dpr;
|
|
209
|
+
tempCanvasEl.height = objBounds.height * dpr;
|
|
210
|
+
tempCanvasEl.style.width = "".concat(objBounds.width, "px");
|
|
211
|
+
tempCanvasEl.style.height = "".concat(objBounds.height, "px");
|
|
212
|
+
// Explicitly set alpha to true to support transparency
|
|
213
|
+
var tempCtx = tempCanvasEl.getContext('2d', { alpha: true });
|
|
214
|
+
tempCtx && tempCtx.scale(dpr, dpr);
|
|
215
|
+
if (!tempCtx) {
|
|
216
|
+
console.error('Could not get canvas context');
|
|
217
|
+
resolve(null);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
// Clear the canvas to ensure transparency
|
|
221
|
+
tempCtx.clearRect(0, 0, tempCanvasEl.width, tempCanvasEl.height);
|
|
222
|
+
// Set background color if provided, otherwise keep transparent
|
|
223
|
+
if (options === null || options === void 0 ? void 0 : options.backgroundColor) {
|
|
224
|
+
tempCtx.fillStyle = options.backgroundColor;
|
|
225
|
+
tempCtx.fillRect(0, 0, tempCanvasEl.width, tempCanvasEl.height);
|
|
226
|
+
}
|
|
227
|
+
// Save current canvas state
|
|
228
|
+
var originalZoom = canvas.getZoom();
|
|
229
|
+
var originalViewportTransform = canvas.viewportTransform ? __spreadArray([], canvas.viewportTransform, true) : [1, 0, 0, 1, 0, 0];
|
|
230
|
+
// Save the original background color of the canvas
|
|
231
|
+
var originalBackgroundColor = canvas.backgroundColor;
|
|
232
|
+
// Temporarily set canvas background to transparent
|
|
233
|
+
canvas.backgroundColor = 'transparent';
|
|
234
|
+
// Store original object positions
|
|
235
|
+
var originalPositions = objects.map(function (obj) { return ({
|
|
236
|
+
object: obj,
|
|
237
|
+
left: obj.left,
|
|
238
|
+
top: obj.top,
|
|
239
|
+
scaleX: obj.scaleX,
|
|
240
|
+
scaleY: obj.scaleY
|
|
241
|
+
}); });
|
|
242
|
+
// Temporarily modify the canvas view to focus on our object
|
|
243
|
+
canvas.setZoom(1);
|
|
244
|
+
canvas.setViewportTransform([1, 0, 0, 1, -objBounds.left, -objBounds.top]);
|
|
245
|
+
// Temporarily hide all objects except our target and its clipped content
|
|
246
|
+
var originalVisibilities = objects.map(function (obj) { return ({ object: obj, visible: obj.visible }); });
|
|
247
|
+
objects.forEach(function (obj) {
|
|
248
|
+
if (!obj.fieldId) {
|
|
249
|
+
obj.visible = false;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
// Temporarily disable selection borders at canvas level
|
|
253
|
+
var originalSelectionBorder = canvas.selectionBorderColor;
|
|
254
|
+
var originalSelectionColor = canvas.selectionColor;
|
|
255
|
+
canvas.selectionBorderColor = 'transparent';
|
|
256
|
+
canvas.selectionColor = 'transparent';
|
|
257
|
+
// Temporarily disable selection borders at object level
|
|
258
|
+
var originalObjectStates = objects.map(function (obj) { return ({
|
|
259
|
+
object: obj,
|
|
260
|
+
borderColor: obj.borderColor,
|
|
261
|
+
cornerColor: obj.cornerColor,
|
|
262
|
+
cornerStrokeColor: obj.cornerStrokeColor,
|
|
263
|
+
transparentCorners: obj.transparentCorners,
|
|
264
|
+
hasControls: obj.hasControls,
|
|
265
|
+
hasBorders: obj.hasBorders
|
|
266
|
+
}); });
|
|
267
|
+
objects.forEach(function (obj) {
|
|
268
|
+
obj.borderColor = 'transparent';
|
|
269
|
+
obj.cornerColor = 'transparent';
|
|
270
|
+
obj.cornerStrokeColor = 'transparent';
|
|
271
|
+
obj.transparentCorners = true;
|
|
272
|
+
obj.hasControls = false;
|
|
273
|
+
obj.hasBorders = false;
|
|
274
|
+
});
|
|
275
|
+
// Render just the isolated object
|
|
276
|
+
canvas.renderAll();
|
|
277
|
+
// Draw the current canvas view to our temp canvas
|
|
278
|
+
tempCtx.drawImage(canvas.getElement(), 0, 0, objBounds.width * dpr, objBounds.height * dpr, 0, 0, objBounds.width, objBounds.height);
|
|
279
|
+
// Restore the original object positions
|
|
280
|
+
originalPositions.forEach(function (item) {
|
|
281
|
+
item.object.left = item.left;
|
|
282
|
+
item.object.top = item.top;
|
|
283
|
+
item.object.scaleX = item.scaleX;
|
|
284
|
+
item.object.scaleY = item.scaleY;
|
|
285
|
+
item.object.setCoords();
|
|
286
|
+
});
|
|
287
|
+
// Restore the original canvas state
|
|
288
|
+
canvas.setZoom(originalZoom);
|
|
289
|
+
canvas.setViewportTransform(originalViewportTransform);
|
|
290
|
+
canvas.backgroundColor = originalBackgroundColor;
|
|
291
|
+
originalVisibilities.forEach(function (item) {
|
|
292
|
+
item.object.visible = item.visible;
|
|
293
|
+
});
|
|
294
|
+
// Restore object-level selection borders
|
|
295
|
+
originalObjectStates.forEach(function (state) {
|
|
296
|
+
state.object.borderColor = state.borderColor;
|
|
297
|
+
state.object.cornerColor = state.cornerColor;
|
|
298
|
+
state.object.cornerStrokeColor = state.cornerStrokeColor;
|
|
299
|
+
state.object.transparentCorners = state.transparentCorners;
|
|
300
|
+
state.object.hasControls = state.hasControls;
|
|
301
|
+
state.object.hasBorders = state.hasBorders;
|
|
302
|
+
});
|
|
303
|
+
// Restore canvas-level selection borders
|
|
304
|
+
canvas.selectionBorderColor = originalSelectionBorder;
|
|
305
|
+
canvas.selectionColor = originalSelectionColor;
|
|
306
|
+
canvas.renderAll();
|
|
307
|
+
// Get the data URL from the temp canvas
|
|
308
|
+
var format = (options === null || options === void 0 ? void 0 : options.format) || 'png';
|
|
309
|
+
var quality = (options === null || options === void 0 ? void 0 : options.quality) || 1;
|
|
310
|
+
// Create a new canvas for final rendering with proper transparency
|
|
311
|
+
var finalCanvas = document.createElement('canvas');
|
|
312
|
+
finalCanvas.width = tempCanvasEl.width;
|
|
313
|
+
finalCanvas.height = tempCanvasEl.height;
|
|
314
|
+
var finalCtx = finalCanvas.getContext('2d', { alpha: true });
|
|
315
|
+
finalCtx && finalCtx.scale(1, 1);
|
|
316
|
+
if (!finalCtx) {
|
|
317
|
+
console.error('Could not get final canvas context');
|
|
318
|
+
resolve(null);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
// Clear the final canvas to ensure transparency
|
|
322
|
+
finalCtx.clearRect(0, 0, finalCanvas.width, finalCanvas.height);
|
|
323
|
+
// Draw the temp canvas content to the final canvas
|
|
324
|
+
finalCtx.drawImage(tempCanvasEl, 0, 0);
|
|
325
|
+
// Try to get the data URL from the final canvas
|
|
326
|
+
try {
|
|
327
|
+
// Ensure PNG format for transparency support
|
|
328
|
+
var dataUrl = finalCanvas.toDataURL("image/".concat(format === 'jpg' ? 'png' : format), quality);
|
|
329
|
+
resolve(dataUrl);
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
console.error('Error getting data URL:', error);
|
|
333
|
+
resolve(null);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
console.error('Error rendering clipped image:', error);
|
|
338
|
+
resolve(null);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
};
|
|
342
|
+
exports.renderClippedImage = renderClippedImage;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDeviceAdjustedDimensions = void 0;
|
|
4
|
+
var getDeviceAdjustedDimensions = function (defaultWidth, defaultHeight) {
|
|
5
|
+
if (defaultWidth === void 0) { defaultWidth = 800; }
|
|
6
|
+
if (defaultHeight === void 0) { defaultHeight = 600; }
|
|
7
|
+
if (typeof window === 'undefined') {
|
|
8
|
+
return {
|
|
9
|
+
isMobile: false,
|
|
10
|
+
width: defaultWidth,
|
|
11
|
+
height: defaultHeight
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
var isMobile = window.innerWidth < 480;
|
|
15
|
+
// Use default dimensions for desktop
|
|
16
|
+
if (!isMobile) {
|
|
17
|
+
return {
|
|
18
|
+
isMobile: false,
|
|
19
|
+
width: defaultWidth,
|
|
20
|
+
height: defaultHeight
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
// Calculate mobile dimensions
|
|
24
|
+
var mobileWidth = Math.min(window.innerWidth * 0.9 - 32, 400);
|
|
25
|
+
var aspectRatio = defaultWidth / defaultHeight;
|
|
26
|
+
var mobileHeight = mobileWidth / aspectRatio;
|
|
27
|
+
return {
|
|
28
|
+
isMobile: true,
|
|
29
|
+
width: mobileWidth,
|
|
30
|
+
height: mobileHeight
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
exports.getDeviceAdjustedDimensions = getDeviceAdjustedDimensions;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DraftPreview, DraftTemplateData, RenderedDraftPreview } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Compares two arrays of draft templates to determine if they've changed significantly
|
|
4
|
+
* This helps prevent unnecessary re-renders and infinite loops
|
|
5
|
+
*
|
|
6
|
+
* @param oldTemplates The previous draft templates array
|
|
7
|
+
* @param newTemplates The new draft templates array
|
|
8
|
+
* @returns True if templates have changed, false if they're effectively the same
|
|
9
|
+
*/
|
|
10
|
+
export declare function haveDraftTemplatesChanged(oldTemplates: Array<{
|
|
11
|
+
template: any;
|
|
12
|
+
variationObjects: any[];
|
|
13
|
+
}>, newTemplates: Array<{
|
|
14
|
+
template: any;
|
|
15
|
+
variationObjects: any[];
|
|
16
|
+
}>): boolean;
|
|
17
|
+
export declare function mapPreviewsWithRendered(draftTemplates: DraftTemplateData[], draftPreviews: DraftPreview[], renderedDraftPreviews: RenderedDraftPreview[]): {
|
|
18
|
+
draftPreview: DraftPreview;
|
|
19
|
+
draftPreviewLayers: {
|
|
20
|
+
layerName: string | undefined;
|
|
21
|
+
renderedLayer: RenderedDraftPreview | null;
|
|
22
|
+
}[];
|
|
23
|
+
}[];
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mapPreviewsWithRendered = exports.haveDraftTemplatesChanged = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Compares two arrays of draft templates to determine if they've changed significantly
|
|
6
|
+
* This helps prevent unnecessary re-renders and infinite loops
|
|
7
|
+
*
|
|
8
|
+
* @param oldTemplates The previous draft templates array
|
|
9
|
+
* @param newTemplates The new draft templates array
|
|
10
|
+
* @returns True if templates have changed, false if they're effectively the same
|
|
11
|
+
*/
|
|
12
|
+
function haveDraftTemplatesChanged(oldTemplates, newTemplates) {
|
|
13
|
+
// Quick length check
|
|
14
|
+
if (!oldTemplates || !newTemplates)
|
|
15
|
+
return true;
|
|
16
|
+
if (oldTemplates.length !== newTemplates.length)
|
|
17
|
+
return true;
|
|
18
|
+
// Check if template IDs are the same and in the same order
|
|
19
|
+
var oldIds = oldTemplates.map(function (dt) { return dt.template.id; }).join(',');
|
|
20
|
+
var newIds = newTemplates.map(function (dt) { return dt.template.id; }).join(',');
|
|
21
|
+
if (oldIds !== newIds)
|
|
22
|
+
return true;
|
|
23
|
+
// Deep check each template for significant changes
|
|
24
|
+
for (var i = 0; i < oldTemplates.length; i++) {
|
|
25
|
+
var oldTemplate = oldTemplates[i];
|
|
26
|
+
var newTemplate = newTemplates[i];
|
|
27
|
+
// Check for template property changes
|
|
28
|
+
if (oldTemplate.template.id !== newTemplate.template.id)
|
|
29
|
+
return true;
|
|
30
|
+
if (oldTemplate.template.name !== newTemplate.template.name)
|
|
31
|
+
return true;
|
|
32
|
+
if (oldTemplate.template.width !== newTemplate.template.width)
|
|
33
|
+
return true;
|
|
34
|
+
if (oldTemplate.template.height !== newTemplate.template.height)
|
|
35
|
+
return true;
|
|
36
|
+
// Check variation objects count
|
|
37
|
+
if (oldTemplate.variationObjects.length !== newTemplate.variationObjects.length)
|
|
38
|
+
return true;
|
|
39
|
+
// We could do more detailed checking of variation objects here,
|
|
40
|
+
// but for performance we'll assume if counts are the same and template properties
|
|
41
|
+
// are the same, the variations probably haven't changed enough to warrant a full re-render
|
|
42
|
+
}
|
|
43
|
+
// Templates are effectively the same
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
exports.haveDraftTemplatesChanged = haveDraftTemplatesChanged;
|
|
47
|
+
function mapPreviewsWithRendered(draftTemplates, draftPreviews, renderedDraftPreviews) {
|
|
48
|
+
return draftPreviews.map(function (draftPreview) {
|
|
49
|
+
// Map each draftTemplate to its associated layers and rendered layers
|
|
50
|
+
var draftPreviewLayers = draftTemplates.flatMap(function (dTD) {
|
|
51
|
+
var _a;
|
|
52
|
+
var layers = ((_a = dTD === null || dTD === void 0 ? void 0 : dTD.template) === null || _a === void 0 ? void 0 : _a.draftPreviewLayers) || [];
|
|
53
|
+
return layers
|
|
54
|
+
.filter(function (dPL) { var _a; return ((_a = dPL === null || dPL === void 0 ? void 0 : dPL.draftPreview) === null || _a === void 0 ? void 0 : _a.id) === draftPreview.id; })
|
|
55
|
+
.map(function (layer) {
|
|
56
|
+
var renderedLayer = renderedDraftPreviews.find(function (rDR) { var _a; return (rDR === null || rDR === void 0 ? void 0 : rDR.templateId) === ((_a = dTD === null || dTD === void 0 ? void 0 : dTD.template) === null || _a === void 0 ? void 0 : _a.id); });
|
|
57
|
+
return { layerName: layer === null || layer === void 0 ? void 0 : layer.layerName, renderedLayer: renderedLayer || null };
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
draftPreview: draftPreview,
|
|
62
|
+
draftPreviewLayers: draftPreviewLayers,
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
exports.mapPreviewsWithRendered = mapPreviewsWithRendered;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { fabric } from 'fabric';
|
|
2
|
+
/**
|
|
3
|
+
* @param fabricCanvas
|
|
4
|
+
* @param width
|
|
5
|
+
* @param height
|
|
6
|
+
* @param gridSize
|
|
7
|
+
* @param lineColor
|
|
8
|
+
* @param enabled
|
|
9
|
+
*/
|
|
10
|
+
export declare const drawGrid: (fabricCanvas: fabric.Canvas, width: number, height: number, gridSize?: number, lineColor?: string, enabled?: boolean) => void;
|
|
11
|
+
/**
|
|
12
|
+
* save the grid state on the canvas
|
|
13
|
+
* @param fabricCanvas
|
|
14
|
+
*/
|
|
15
|
+
export declare const saveGridState: (fabricCanvas: fabric.Canvas) => fabric.Object[];
|
|
16
|
+
/**
|
|
17
|
+
* bring grid lines to front of the canvas
|
|
18
|
+
* @param fabricCanvas
|
|
19
|
+
* @param gridLines
|
|
20
|
+
*/
|
|
21
|
+
export declare const bringGridToFront: (fabricCanvas: fabric.Canvas, gridLines: fabric.Object[]) => void;
|
|
22
|
+
/**
|
|
23
|
+
* send grid lines to back of the canvas
|
|
24
|
+
* @param fabricCanvas
|
|
25
|
+
* @param gridLines
|
|
26
|
+
*/
|
|
27
|
+
export declare const sendGridToBack: (fabricCanvas: fabric.Canvas, gridLines: fabric.Object[]) => void;
|
|
28
|
+
/**
|
|
29
|
+
* clear all objects except the grid on the canvas
|
|
30
|
+
* @param fabricCanvas
|
|
31
|
+
*/
|
|
32
|
+
export declare const clearCanvasExceptGrid: (fabricCanvas: fabric.Canvas) => void;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clearCanvasExceptGrid = exports.sendGridToBack = exports.bringGridToFront = exports.saveGridState = exports.drawGrid = void 0;
|
|
4
|
+
var fabric_1 = require("fabric");
|
|
5
|
+
/**
|
|
6
|
+
* @param fabricCanvas
|
|
7
|
+
* @param width
|
|
8
|
+
* @param height
|
|
9
|
+
* @param gridSize
|
|
10
|
+
* @param lineColor
|
|
11
|
+
* @param enabled
|
|
12
|
+
*/
|
|
13
|
+
var drawGrid = function (fabricCanvas, width, height, gridSize, lineColor, enabled) {
|
|
14
|
+
if (gridSize === void 0) { gridSize = 20; }
|
|
15
|
+
if (lineColor === void 0) { lineColor = '#e0e0e0'; }
|
|
16
|
+
if (enabled === void 0) { enabled = true; }
|
|
17
|
+
// First, make sure fabricCanvas is not null
|
|
18
|
+
if (!fabricCanvas) {
|
|
19
|
+
console.warn('drawGrid: fabricCanvas is null or undefined');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
// Make sure the canvas element exists and is valid
|
|
23
|
+
try {
|
|
24
|
+
// This will throw an error if the canvas element is no longer in the DOM
|
|
25
|
+
if (!fabricCanvas.getElement() || !fabricCanvas.getElement().parentNode) {
|
|
26
|
+
console.warn('drawGrid: Canvas element is not in the DOM');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
console.warn('drawGrid: Error checking canvas element:', e);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// remove all existing grid lines
|
|
35
|
+
var gridLines = fabricCanvas.getObjects().filter(function (obj) { var _a; return (_a = obj.data) === null || _a === void 0 ? void 0 : _a.isGrid; });
|
|
36
|
+
gridLines.forEach(function (line) { return fabricCanvas.remove(line); });
|
|
37
|
+
if (!enabled)
|
|
38
|
+
return;
|
|
39
|
+
// draw vertical lines
|
|
40
|
+
for (var i = 0; i <= width; i += gridSize) {
|
|
41
|
+
var line = new fabric_1.fabric.Line([i, 0, i, height], {
|
|
42
|
+
stroke: lineColor,
|
|
43
|
+
strokeWidth: 0.5,
|
|
44
|
+
opacity: 0.3,
|
|
45
|
+
selectable: false,
|
|
46
|
+
evented: false,
|
|
47
|
+
data: { isGrid: true }
|
|
48
|
+
});
|
|
49
|
+
fabricCanvas.add(line);
|
|
50
|
+
}
|
|
51
|
+
// draw horizontal lines
|
|
52
|
+
for (var i = 0; i <= height; i += gridSize) {
|
|
53
|
+
var line = new fabric_1.fabric.Line([0, i, width, i], {
|
|
54
|
+
stroke: lineColor,
|
|
55
|
+
strokeWidth: 0.5,
|
|
56
|
+
opacity: 0.3,
|
|
57
|
+
selectable: false,
|
|
58
|
+
evented: false,
|
|
59
|
+
data: { isGrid: true }
|
|
60
|
+
});
|
|
61
|
+
fabricCanvas.add(line);
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
fabricCanvas.renderAll();
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
console.error('drawGrid: Error rendering grid:', e);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
exports.drawGrid = drawGrid;
|
|
71
|
+
/**
|
|
72
|
+
* save the grid state on the canvas
|
|
73
|
+
* @param fabricCanvas
|
|
74
|
+
*/
|
|
75
|
+
var saveGridState = function (fabricCanvas) {
|
|
76
|
+
if (!fabricCanvas) {
|
|
77
|
+
console.warn('saveGridState: fabricCanvas is null or undefined');
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
var objs = fabricCanvas.getObjects().filter(function (obj) { return obj; });
|
|
82
|
+
return objs;
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
console.warn('saveGridState: Error getting grid objects:', e);
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
exports.saveGridState = saveGridState;
|
|
90
|
+
/**
|
|
91
|
+
* bring grid lines to front of the canvas
|
|
92
|
+
* @param fabricCanvas
|
|
93
|
+
* @param gridLines
|
|
94
|
+
*/
|
|
95
|
+
var bringGridToFront = function (fabricCanvas, gridLines) {
|
|
96
|
+
if (!fabricCanvas) {
|
|
97
|
+
console.warn('bringGridToFront: fabricCanvas is null or undefined');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (gridLines && gridLines.length > 0) {
|
|
101
|
+
try {
|
|
102
|
+
gridLines.forEach(function (line) { return fabricCanvas.bringToFront(line); });
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
console.warn('bringGridToFront: Error bringing grid to front:', e);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
exports.bringGridToFront = bringGridToFront;
|
|
110
|
+
/**
|
|
111
|
+
* send grid lines to back of the canvas
|
|
112
|
+
* @param fabricCanvas
|
|
113
|
+
* @param gridLines
|
|
114
|
+
*/
|
|
115
|
+
var sendGridToBack = function (fabricCanvas, gridLines) {
|
|
116
|
+
if (!fabricCanvas) {
|
|
117
|
+
console.warn('sendGridToBack: fabricCanvas is null or undefined');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (gridLines && gridLines.length > 0) {
|
|
121
|
+
try {
|
|
122
|
+
gridLines.forEach(function (line) { return fabricCanvas.sendToBack(line); });
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
console.warn('sendGridToBack: Error sending grid to back:', e);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
exports.sendGridToBack = sendGridToBack;
|
|
130
|
+
/**
|
|
131
|
+
* clear all objects except the grid on the canvas
|
|
132
|
+
* @param fabricCanvas
|
|
133
|
+
*/
|
|
134
|
+
var clearCanvasExceptGrid = function (fabricCanvas) {
|
|
135
|
+
if (!fabricCanvas) {
|
|
136
|
+
console.warn('clearCanvasExceptGrid: fabricCanvas is null or undefined');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
fabricCanvas.getObjects().forEach(function (obj) {
|
|
141
|
+
var _a;
|
|
142
|
+
if (!((_a = obj.data) === null || _a === void 0 ? void 0 : _a.isGrid)) {
|
|
143
|
+
fabricCanvas.remove(obj);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
console.warn('clearCanvasExceptGrid: Error clearing canvas:', e);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
exports.clearCanvasExceptGrid = clearCanvasExceptGrid;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { fabric } from 'fabric';
|
|
2
|
+
import { DraftTemplate } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Loads a template image onto a canvas with enhanced error handling and fallbacks
|
|
5
|
+
*
|
|
6
|
+
* @param fabricCanvas The Fabric.js canvas instance
|
|
7
|
+
* @param template The template containing image information
|
|
8
|
+
* @param width The canvas width
|
|
9
|
+
* @param height The canvas height
|
|
10
|
+
* @returns Promise that resolves when the image is loaded
|
|
11
|
+
*/
|
|
12
|
+
export declare const loadRegularImagePromise: (fabricCanvas: fabric.Canvas, template: DraftTemplate, width: number, height: number) => Promise<void>;
|