@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,281 @@
|
|
|
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 __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
46
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
47
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
48
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
49
|
+
function step(op) {
|
|
50
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
51
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
52
|
+
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;
|
|
53
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
54
|
+
switch (op[0]) {
|
|
55
|
+
case 0: case 1: t = op; break;
|
|
56
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
57
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
58
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
59
|
+
default:
|
|
60
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
61
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
62
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
63
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
64
|
+
if (t[2]) _.ops.pop();
|
|
65
|
+
_.trys.pop(); continue;
|
|
66
|
+
}
|
|
67
|
+
op = body.call(thisArg, _);
|
|
68
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
69
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
73
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
74
|
+
if (ar || !(i in from)) {
|
|
75
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
76
|
+
ar[i] = from[i];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
80
|
+
};
|
|
81
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
82
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
83
|
+
};
|
|
84
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
85
|
+
var react_1 = __importStar(require("react"));
|
|
86
|
+
var ImageZoomModal_1 = __importDefault(require("./ImageZoomModal"));
|
|
87
|
+
require("../styles/ProductEditor.css");
|
|
88
|
+
require("../styles/BottomPreviewDisplay.css");
|
|
89
|
+
var ProductEditorContext_1 = require("../context/ProductEditorContext");
|
|
90
|
+
var draftTemplateUtils_1 = require("../utils/draftTemplateUtils");
|
|
91
|
+
var psdRenderUtils_1 = require("../utils/psdRenderUtils");
|
|
92
|
+
var ProductPreviews = function () {
|
|
93
|
+
var _a, _b;
|
|
94
|
+
var _c = (0, ProductEditorContext_1.useProductEditor)(), draftTemplates = _c.draftTemplates, draftPreviews = _c.draftPreviews, loadingPreviews = _c.loadingPreviews, renderedDraftPreviews = _c.renderedDraftPreviews;
|
|
95
|
+
var _d = (0, react_1.useState)(false), isModalOpen = _d[0], setIsModalOpen = _d[1];
|
|
96
|
+
var _e = (0, react_1.useState)(0), selectedPreviewIndex = _e[0], setSelectedPreviewIndex = _e[1];
|
|
97
|
+
var _f = (0, react_1.useState)([]), renderedPreviews = _f[0], setRenderedPreviews = _f[1];
|
|
98
|
+
var _g = (0, react_1.useState)(false), isProcessing = _g[0], setIsProcessing = _g[1];
|
|
99
|
+
// Use refs instead of state to track processed data without causing re-renders
|
|
100
|
+
var processedPreviewIdsRef = (0, react_1.useRef)(new Set());
|
|
101
|
+
// Track which template versions we've already processed
|
|
102
|
+
var processedTemplateVersionsRef = (0, react_1.useRef)(new Map());
|
|
103
|
+
// For debugging
|
|
104
|
+
var renderCountRef = (0, react_1.useRef)(0);
|
|
105
|
+
// Track if this is first mount
|
|
106
|
+
var isFirstMountRef = (0, react_1.useRef)(true);
|
|
107
|
+
// When mappedPreviews or renderedDraftPreviews changes, update our rendered PNGs
|
|
108
|
+
(0, react_1.useEffect)(function () {
|
|
109
|
+
// Skip first render to avoid processing before renderedDraftPreviews are available
|
|
110
|
+
if (isFirstMountRef.current) {
|
|
111
|
+
isFirstMountRef.current = false;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
renderCountRef.current++;
|
|
115
|
+
var processPreviewsWithLayers = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
116
|
+
var mappedPreviews, changedTemplateIds, previewsToProcess, processedResults_1, error_1;
|
|
117
|
+
return __generator(this, function (_a) {
|
|
118
|
+
switch (_a.label) {
|
|
119
|
+
case 0:
|
|
120
|
+
// Skip if we're already processing or if we don't have previews
|
|
121
|
+
if (isProcessing || !draftPreviews || draftPreviews.length === 0) {
|
|
122
|
+
return [2 /*return*/];
|
|
123
|
+
}
|
|
124
|
+
mappedPreviews = (0, draftTemplateUtils_1.mapPreviewsWithRendered)(draftTemplates, draftPreviews, renderedDraftPreviews);
|
|
125
|
+
// Skip if there are no mappedPreviews to process
|
|
126
|
+
if (!mappedPreviews || mappedPreviews.length === 0) {
|
|
127
|
+
return [2 /*return*/];
|
|
128
|
+
}
|
|
129
|
+
changedTemplateIds = new Set();
|
|
130
|
+
renderedDraftPreviews.forEach(function (rdp) {
|
|
131
|
+
var templateId = rdp.templateId;
|
|
132
|
+
var templateVersion = rdp.draft; // Use the image data URL as a version identifier
|
|
133
|
+
var previousVersion = processedTemplateVersionsRef.current.get(templateId);
|
|
134
|
+
if (previousVersion !== templateVersion) {
|
|
135
|
+
changedTemplateIds.add(templateId);
|
|
136
|
+
// Update the stored version
|
|
137
|
+
processedTemplateVersionsRef.current.set(templateId, templateVersion);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
previewsToProcess = mappedPreviews.filter(function (mp) {
|
|
141
|
+
var previewId = mp.draftPreview.id;
|
|
142
|
+
// Always process if we haven't processed this preview yet
|
|
143
|
+
if (!processedPreviewIdsRef.current.has(previewId)) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
// If no templates have changed, skip reprocessing
|
|
147
|
+
if (changedTemplateIds.size === 0) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
// Check if this preview uses any templates that have changed
|
|
151
|
+
var shouldProcess = mp.draftPreviewLayers.some(function (layer) {
|
|
152
|
+
return layer.renderedLayer && changedTemplateIds.has(layer.renderedLayer.templateId);
|
|
153
|
+
});
|
|
154
|
+
return shouldProcess;
|
|
155
|
+
});
|
|
156
|
+
// Skip if there's nothing new to process
|
|
157
|
+
if (previewsToProcess.length === 0) {
|
|
158
|
+
return [2 /*return*/];
|
|
159
|
+
}
|
|
160
|
+
setIsProcessing(true);
|
|
161
|
+
_a.label = 1;
|
|
162
|
+
case 1:
|
|
163
|
+
_a.trys.push([1, 3, 4, 5]);
|
|
164
|
+
return [4 /*yield*/, (0, psdRenderUtils_1.renderDraftPreviewsWithLayers)(previewsToProcess)];
|
|
165
|
+
case 2:
|
|
166
|
+
processedResults_1 = _a.sent();
|
|
167
|
+
// Update our rendered previews state
|
|
168
|
+
setRenderedPreviews(function (prevRendered) {
|
|
169
|
+
var newRendered = __spreadArray([], prevRendered, true);
|
|
170
|
+
processedResults_1.forEach(function (result) {
|
|
171
|
+
var existingIndex = newRendered.findIndex(function (r) { return r.draftPreviewId === result.draftPreviewId; });
|
|
172
|
+
if (existingIndex !== -1) {
|
|
173
|
+
// Update existing preview
|
|
174
|
+
newRendered[existingIndex] = result;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// Add new preview
|
|
178
|
+
newRendered.push(result);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
return newRendered;
|
|
182
|
+
});
|
|
183
|
+
// Update our processed IDs ref (not state)
|
|
184
|
+
processedResults_1.forEach(function (result) {
|
|
185
|
+
if (result.draftPreviewId !== undefined) {
|
|
186
|
+
processedPreviewIdsRef.current.add(result.draftPreviewId);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
return [3 /*break*/, 5];
|
|
190
|
+
case 3:
|
|
191
|
+
error_1 = _a.sent();
|
|
192
|
+
console.error('Failed to process previews with layers:', error_1);
|
|
193
|
+
return [3 /*break*/, 5];
|
|
194
|
+
case 4:
|
|
195
|
+
setIsProcessing(false);
|
|
196
|
+
return [7 /*endfinally*/];
|
|
197
|
+
case 5: return [2 /*return*/];
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}); };
|
|
201
|
+
processPreviewsWithLayers();
|
|
202
|
+
}, [draftTemplates, draftPreviews, renderedDraftPreviews, isProcessing]);
|
|
203
|
+
// One-time initialization to handle initial rendering of previews
|
|
204
|
+
// when component mounts and renderedDraftPreviews are available
|
|
205
|
+
(0, react_1.useEffect)(function () {
|
|
206
|
+
if ((draftPreviews === null || draftPreviews === void 0 ? void 0 : draftPreviews.length) > 0 && (renderedDraftPreviews === null || renderedDraftPreviews === void 0 ? void 0 : renderedDraftPreviews.length) > 0 && renderedPreviews.length === 0) {
|
|
207
|
+
var mappedPreviews_1 = (0, draftTemplateUtils_1.mapPreviewsWithRendered)(draftTemplates, draftPreviews, renderedDraftPreviews);
|
|
208
|
+
if ((mappedPreviews_1 === null || mappedPreviews_1 === void 0 ? void 0 : mappedPreviews_1.length) > 0) {
|
|
209
|
+
(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
210
|
+
var processedResults, error_2;
|
|
211
|
+
return __generator(this, function (_a) {
|
|
212
|
+
switch (_a.label) {
|
|
213
|
+
case 0:
|
|
214
|
+
setIsProcessing(true);
|
|
215
|
+
_a.label = 1;
|
|
216
|
+
case 1:
|
|
217
|
+
_a.trys.push([1, 3, 4, 5]);
|
|
218
|
+
return [4 /*yield*/, (0, psdRenderUtils_1.renderDraftPreviewsWithLayers)(mappedPreviews_1)];
|
|
219
|
+
case 2:
|
|
220
|
+
processedResults = _a.sent();
|
|
221
|
+
// Store initial results
|
|
222
|
+
setRenderedPreviews(processedResults);
|
|
223
|
+
// Mark these previews as processed
|
|
224
|
+
processedResults.forEach(function (result) {
|
|
225
|
+
if (result.draftPreviewId !== undefined) {
|
|
226
|
+
processedPreviewIdsRef.current.add(result.draftPreviewId);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
// Store initial template versions
|
|
230
|
+
renderedDraftPreviews.forEach(function (rdp) {
|
|
231
|
+
processedTemplateVersionsRef.current.set(rdp.templateId, rdp.draft);
|
|
232
|
+
});
|
|
233
|
+
return [3 /*break*/, 5];
|
|
234
|
+
case 3:
|
|
235
|
+
error_2 = _a.sent();
|
|
236
|
+
console.error('[Initialization] Error processing previews:', error_2);
|
|
237
|
+
return [3 /*break*/, 5];
|
|
238
|
+
case 4:
|
|
239
|
+
setIsProcessing(false);
|
|
240
|
+
return [7 /*endfinally*/];
|
|
241
|
+
case 5: return [2 /*return*/];
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}); })();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}, [draftPreviews, renderedDraftPreviews, draftTemplates, renderedPreviews.length]);
|
|
248
|
+
var openModal = function (index) {
|
|
249
|
+
setSelectedPreviewIndex(index);
|
|
250
|
+
setIsModalOpen(true);
|
|
251
|
+
};
|
|
252
|
+
var closeModal = function () {
|
|
253
|
+
setIsModalOpen(false);
|
|
254
|
+
};
|
|
255
|
+
// Determine the URL to display for each preview
|
|
256
|
+
var previewUrlsForDisplay = draftPreviews.length > 0
|
|
257
|
+
? draftPreviews.map(function (preview) {
|
|
258
|
+
// If we have a rendered PNG for this preview, use it
|
|
259
|
+
var renderedPreview = renderedPreviews.find(function (rp) { return rp.draftPreviewId === preview.id; });
|
|
260
|
+
return (renderedPreview === null || renderedPreview === void 0 ? void 0 : renderedPreview.pngDataUrl) || '';
|
|
261
|
+
})
|
|
262
|
+
: renderedDraftPreviews.map(function (preview) {
|
|
263
|
+
// If we have a rendered PNG for this preview, use it
|
|
264
|
+
return preview.canvasPreview;
|
|
265
|
+
});
|
|
266
|
+
var previews = (draftPreviews === null || draftPreviews === void 0 ? void 0 : draftPreviews.length) > 0 ? draftPreviews : renderedDraftPreviews;
|
|
267
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
268
|
+
!isModalOpen && (react_1.default.createElement("div", { className: "bottom-preview-section" },
|
|
269
|
+
react_1.default.createElement("div", { className: "preview-images" }, previews.map(function (preview, index) {
|
|
270
|
+
var _a;
|
|
271
|
+
return loadingPreviews || isProcessing ? (react_1.default.createElement("div", { key: "loading-".concat(preview.id || index), className: 'preview-image-box' },
|
|
272
|
+
react_1.default.createElement("div", { className: "preview-image-box-loading-spinner" }))) : (react_1.default.createElement("div", { key: preview.id || "preview-".concat(index), className: "preview-image-box", onClick: function () { return openModal(index); }, style: {
|
|
273
|
+
backgroundImage: "url(".concat(previewUrlsForDisplay[index] || ((_a = preview.file) === null || _a === void 0 ? void 0 : _a.viewUrl) || '', ")"),
|
|
274
|
+
backgroundSize: 'contain',
|
|
275
|
+
backgroundRepeat: 'no-repeat',
|
|
276
|
+
backgroundPosition: 'center center'
|
|
277
|
+
}, title: "Preview ".concat(index + 1) }));
|
|
278
|
+
})))),
|
|
279
|
+
react_1.default.createElement(ImageZoomModal_1.default, { isOpen: isModalOpen, onClose: closeModal, imageUrl: previewUrlsForDisplay[selectedPreviewIndex] || ((_b = (_a = previews[selectedPreviewIndex]) === null || _a === void 0 ? void 0 : _a.file) === null || _b === void 0 ? void 0 : _b.viewUrl) || '', productName: "Preview", totalImages: previews.length, currentIndex: selectedPreviewIndex, allImages: previews.map(function (preview, index) { return (__assign(__assign({}, preview), { key: preview.id || "modal-preview-".concat(index) })); }) })));
|
|
280
|
+
};
|
|
281
|
+
exports.default = ProductPreviews;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
var react_1 = __importStar(require("react"));
|
|
30
|
+
var react_select_1 = __importDefault(require("react-select"));
|
|
31
|
+
var react_color_1 = require("react-color");
|
|
32
|
+
var ProductEditorContext_1 = require("../context/ProductEditorContext");
|
|
33
|
+
var textToolbarSelectStyles_1 = require("../styles/textToolbarSelectStyles");
|
|
34
|
+
require("../styles/TextToolbar.css");
|
|
35
|
+
var FormatButtons_1 = require("./FormatButtons");
|
|
36
|
+
var AlignMenu_1 = require("./AlignMenu");
|
|
37
|
+
var TextToolbar = function () {
|
|
38
|
+
var _a = (0, ProductEditorContext_1.useProductEditor)(), selectedTextObject = _a.selectedTextObject, updateSelectedText = _a.updateSelectedText, fontOptions = _a.fontOptions, colorPalette = _a.colorPalette;
|
|
39
|
+
var _b = (0, react_1.useState)(false), displayColorPicker = _b[0], setDisplayColorPicker = _b[1];
|
|
40
|
+
var _c = (0, react_1.useState)('palette'), pickerMode = _c[0], setPickerMode = _c[1];
|
|
41
|
+
var colorPickerRef = (0, react_1.useRef)(null);
|
|
42
|
+
(0, react_1.useEffect)(function () {
|
|
43
|
+
var handleClickOutside = function (event) {
|
|
44
|
+
if (colorPickerRef.current && !colorPickerRef.current.contains(event.target)) {
|
|
45
|
+
setDisplayColorPicker(false);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
49
|
+
return function () {
|
|
50
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
51
|
+
};
|
|
52
|
+
}, []);
|
|
53
|
+
if (!selectedTextObject || !updateSelectedText) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
var currentFontValue = selectedTextObject.fontFamily || 'Nunito';
|
|
57
|
+
var currentColor = typeof selectedTextObject.fill === 'string' ? selectedTextObject.fill : '#000000';
|
|
58
|
+
var handleFontChange = function (selectedOption) {
|
|
59
|
+
if (selectedOption) {
|
|
60
|
+
updateSelectedText({ fontFamily: selectedOption.value });
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var handlePaletteColorClick = function (color) {
|
|
64
|
+
updateSelectedText({ fill: color });
|
|
65
|
+
setDisplayColorPicker(false);
|
|
66
|
+
setPickerMode('palette');
|
|
67
|
+
};
|
|
68
|
+
var handleCustomColorChange = function (color) {
|
|
69
|
+
updateSelectedText({ fill: color.hex });
|
|
70
|
+
};
|
|
71
|
+
var handleSwatchClick = function () {
|
|
72
|
+
var currentlyVisible = displayColorPicker;
|
|
73
|
+
setDisplayColorPicker(!currentlyVisible);
|
|
74
|
+
if (!currentlyVisible) {
|
|
75
|
+
setPickerMode('palette');
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
var handleCustomTriggerClick = function () {
|
|
79
|
+
setPickerMode('custom');
|
|
80
|
+
setDisplayColorPicker(true);
|
|
81
|
+
};
|
|
82
|
+
var currentFontOption = fontOptions.find(function (option) { return option.value === currentFontValue; }) || fontOptions[0];
|
|
83
|
+
return (react_1.default.createElement("div", { className: "text-toolbar" },
|
|
84
|
+
react_1.default.createElement(react_select_1.default, { options: fontOptions, styles: textToolbarSelectStyles_1.customStyles, value: currentFontOption, onChange: handleFontChange, isSearchable: true, placeholder: "Select or search font...", className: "react-select-container", classNamePrefix: "react-select" }),
|
|
85
|
+
react_1.default.createElement("div", { className: "color-picker-trigger", onClick: handleSwatchClick, title: "Change text color" },
|
|
86
|
+
react_1.default.createElement("div", { className: "color-picker-swatch", style: {
|
|
87
|
+
backgroundColor: currentColor,
|
|
88
|
+
borderRadius: '50%',
|
|
89
|
+
width: '28px',
|
|
90
|
+
height: '28px',
|
|
91
|
+
minWidth: '28px',
|
|
92
|
+
minHeight: '28px',
|
|
93
|
+
flexShrink: 0
|
|
94
|
+
} }),
|
|
95
|
+
react_1.default.createElement("span", { className: "color-picker-label" }, "Color")),
|
|
96
|
+
displayColorPicker && (react_1.default.createElement("div", { className: "color-picker-container", ref: colorPickerRef },
|
|
97
|
+
react_1.default.createElement("div", { className: "color-picker-popover" }, pickerMode === 'palette' ? (react_1.default.createElement("div", { className: "palette-grid" }, colorPalette.flat().map(function (color, index) {
|
|
98
|
+
if (color === null) {
|
|
99
|
+
return (react_1.default.createElement("button", { key: "custom-trigger", className: "palette-trigger-swatch", onClick: handleCustomTriggerClick, title: "Choose custom color" }, "+"));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
return (react_1.default.createElement("button", { key: "".concat(color, "-").concat(index), className: "palette-swatch", style: { backgroundColor: color }, onClick: function () { return handlePaletteColorClick(color); }, title: color }));
|
|
103
|
+
}
|
|
104
|
+
}))) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
105
|
+
react_1.default.createElement(react_color_1.ChromePicker, { color: currentColor, onChange: handleCustomColorChange, disableAlpha: true, styles: {
|
|
106
|
+
default: {
|
|
107
|
+
picker: {
|
|
108
|
+
boxShadow: 'none',
|
|
109
|
+
width: '250px'
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
} }),
|
|
113
|
+
react_1.default.createElement("button", { className: "color-picker-back-btn", onClick: function () { return setPickerMode('palette'); } }, "Back to Palette")))))),
|
|
114
|
+
react_1.default.createElement(FormatButtons_1.FormatButtons, null),
|
|
115
|
+
react_1.default.createElement(AlignMenu_1.AlignMenu, null)));
|
|
116
|
+
};
|
|
117
|
+
exports.default = TextToolbar;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
var react_1 = __importDefault(require("react"));
|
|
7
|
+
var grommet_icons_1 = require("grommet-icons");
|
|
8
|
+
var ProductEditorContext_1 = require("../context/ProductEditorContext");
|
|
9
|
+
var canvasUtils_1 = require("../utils/canvasUtils");
|
|
10
|
+
require("../styles/Toolbar.css");
|
|
11
|
+
function Toolbar() {
|
|
12
|
+
var _a = (0, ProductEditorContext_1.useProductEditor)(), canvas = _a.canvas, width = _a.width, setShowGrid = _a.setShowGrid, showGrid = _a.showGrid, height = _a.height, showPreview = _a.showPreview, togglePreview = _a.togglePreview, showLayerPanel = _a.showLayerPanel, toggleLayerPanel = _a.toggleLayerPanel, deleteObject = _a.deleteObject, selectedObjectId = _a.selectedObjectId, renderedDraftPreviews = _a.renderedDraftPreviews;
|
|
13
|
+
// Add handleAddText function before the return statement
|
|
14
|
+
var handleAddText = function () {
|
|
15
|
+
if (!canvas)
|
|
16
|
+
return;
|
|
17
|
+
(0, canvasUtils_1.addTextToCanvas)(canvas, width, height);
|
|
18
|
+
};
|
|
19
|
+
var toggleGrid = function () { return setShowGrid(!showGrid); };
|
|
20
|
+
// Handle delete button click
|
|
21
|
+
var handleDelete = function () {
|
|
22
|
+
if (!canvas)
|
|
23
|
+
return;
|
|
24
|
+
var activeObject = canvas.getActiveObject();
|
|
25
|
+
if (activeObject) {
|
|
26
|
+
deleteObject(activeObject);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
// Check if previews are available
|
|
30
|
+
var hasPreview = renderedDraftPreviews && renderedDraftPreviews.length > 0;
|
|
31
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
32
|
+
react_1.default.createElement("div", { className: "grid-toggle" },
|
|
33
|
+
react_1.default.createElement("div", { className: "toolbar-button ".concat(showGrid ? 'active' : ''), onClick: toggleGrid },
|
|
34
|
+
react_1.default.createElement(grommet_icons_1.Apps, { width: 24, height: 24 }),
|
|
35
|
+
react_1.default.createElement("span", null, showGrid ? 'Hide Grid' : 'Show Grid'))),
|
|
36
|
+
react_1.default.createElement("div", { className: "preview-toggle" },
|
|
37
|
+
react_1.default.createElement("div", { className: "toolbar-button ".concat(showPreview && hasPreview ? 'active' : '', " ").concat(!hasPreview ? 'disabled' : ''), onClick: hasPreview ? togglePreview : undefined },
|
|
38
|
+
react_1.default.createElement(grommet_icons_1.View, { width: 24, height: 24 }),
|
|
39
|
+
react_1.default.createElement("span", null, hasPreview && showPreview ? 'Hide Preview' : 'Show Preview'))),
|
|
40
|
+
react_1.default.createElement("div", { className: "toolbar-button ".concat(showLayerPanel ? 'active' : ''), onClick: toggleLayerPanel },
|
|
41
|
+
react_1.default.createElement(grommet_icons_1.Layer, { width: 24, height: 24 }),
|
|
42
|
+
react_1.default.createElement("span", null, "Layer")),
|
|
43
|
+
react_1.default.createElement("div", { className: "toolbar-button ".concat(!selectedObjectId ? 'disabled' : ''), onClick: handleDelete },
|
|
44
|
+
react_1.default.createElement(grommet_icons_1.Trash, { width: 24, height: 24 }),
|
|
45
|
+
react_1.default.createElement("span", null, "Delete"))));
|
|
46
|
+
}
|
|
47
|
+
exports.default = Toolbar;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const defaultPalette: (string | null)[][];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultPalette = void 0;
|
|
4
|
+
exports.defaultPalette = [
|
|
5
|
+
[null, '#000000', '#434343', '#666666', '#999999', '#CCCCCC', '#D9D9D9', '#EFEFEF'],
|
|
6
|
+
['#FFFFFF', '#F44E3B', '#FE9200', '#FCDC00', '#DBDF00', '#A4DD00', '#68CCCA', '#73D8FF'],
|
|
7
|
+
['#AEA1FF', '#FDA1FF', '#CF329A', '#FF6900', '#FCB900', '#7BDCB5', '#00D084', '#8ED1FC'],
|
|
8
|
+
['#0693E3', '#EB144C', '#F78DA7', '#9900EF', '#B80000', '#DB3E00', '#FCC400', '#27724D'],
|
|
9
|
+
['#607D8B', '#8BC34A', '#CDDC39', '#FFEB3B', '#FFC107', '#FF9800', '#FF5722', '#795548']
|
|
10
|
+
];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultFontOptions = void 0;
|
|
4
|
+
exports.defaultFontOptions = [
|
|
5
|
+
{ value: 'Arial', label: 'Arial' },
|
|
6
|
+
{ value: 'Brush Script MT', label: 'Brush Script MT' },
|
|
7
|
+
{ value: 'Courier New', label: 'Courier New' },
|
|
8
|
+
{ value: 'Garamond', label: 'Garamond' },
|
|
9
|
+
{ value: 'Georgia', label: 'Georgia' },
|
|
10
|
+
{ value: 'Lato', label: 'Lato' },
|
|
11
|
+
{ value: 'Montserrat', label: 'Montserrat' },
|
|
12
|
+
{ value: 'Nunito', label: 'Nunito' },
|
|
13
|
+
{ value: 'Open Sans', label: 'Open Sans' },
|
|
14
|
+
{ value: 'Oswald', label: 'Oswald' },
|
|
15
|
+
{ value: 'Playfair Display', label: 'Playfair Display' },
|
|
16
|
+
{ value: 'Roboto', label: 'Roboto' },
|
|
17
|
+
{ value: 'Tahoma', label: 'Tahoma' },
|
|
18
|
+
{ value: 'Times New Roman', label: 'Times New Roman' },
|
|
19
|
+
{ value: 'Trebuchet MS', label: 'Trebuchet MS' },
|
|
20
|
+
{ value: 'Verdana', label: 'Verdana' },
|
|
21
|
+
];
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { fabric } from 'fabric';
|
|
3
|
+
import { Product, Job, DraftTemplate, DraftTemplateData, DraftPreview, SavedCanvasObject, RenderedDraftPreview } from '../types';
|
|
4
|
+
import { FontOption } from '../config/fontConfig';
|
|
5
|
+
import { UseFormReturn } from 'react-hook-form';
|
|
6
|
+
interface ProductEditorContextType {
|
|
7
|
+
canvas: fabric.Canvas | null;
|
|
8
|
+
draftPreviews: DraftPreview[];
|
|
9
|
+
draftTemplates: DraftTemplateData[];
|
|
10
|
+
isCanvasLoading: boolean;
|
|
11
|
+
isMobileView: boolean;
|
|
12
|
+
loadingPreviews: boolean;
|
|
13
|
+
renderedDraftPreviews: RenderedDraftPreview[];
|
|
14
|
+
savedObjects: SavedCanvasObject[];
|
|
15
|
+
selectedTemplate: number | null;
|
|
16
|
+
selectedTextObject: fabric.IText | null;
|
|
17
|
+
showGrid: boolean;
|
|
18
|
+
showPreview: boolean;
|
|
19
|
+
setCanvas: (canvas: fabric.Canvas) => void;
|
|
20
|
+
setSelectedTemplate: (templateId: number) => void;
|
|
21
|
+
setShowGrid: (show: boolean) => void;
|
|
22
|
+
handleCancel: () => void;
|
|
23
|
+
handleSave: () => void;
|
|
24
|
+
handleTemplateChange: (draftTemplate: DraftTemplate) => void;
|
|
25
|
+
recordVariationFieldObjectsOnCanvas: () => void;
|
|
26
|
+
togglePreview: () => void;
|
|
27
|
+
updateSelectedText: (props: Partial<fabric.IText>) => void;
|
|
28
|
+
fontOptions: FontOption[];
|
|
29
|
+
colorPalette: (string | null)[][];
|
|
30
|
+
showLayerPanel: boolean;
|
|
31
|
+
toggleLayerPanel: () => void;
|
|
32
|
+
selectedObjectId: string | null;
|
|
33
|
+
setSelectedObjectId: (id: string | null) => void;
|
|
34
|
+
selectObject: (obj: fabric.Object | null) => void;
|
|
35
|
+
deleteObject: (obj: fabric.Object) => void;
|
|
36
|
+
canvasRef: React.RefObject<HTMLCanvasElement | null>;
|
|
37
|
+
groupIndex: number;
|
|
38
|
+
height: number;
|
|
39
|
+
inputName: string;
|
|
40
|
+
job: Job;
|
|
41
|
+
product: Product;
|
|
42
|
+
width: number;
|
|
43
|
+
hookForm: UseFormReturn<any> | null;
|
|
44
|
+
}
|
|
45
|
+
interface ProductEditorProviderProps {
|
|
46
|
+
children: React.ReactNode;
|
|
47
|
+
groupIndex?: number;
|
|
48
|
+
product: Product;
|
|
49
|
+
width?: number;
|
|
50
|
+
height?: number;
|
|
51
|
+
job: Job;
|
|
52
|
+
onSave: () => void;
|
|
53
|
+
onCancel: () => void;
|
|
54
|
+
hookForm?: UseFormReturn<any> | null;
|
|
55
|
+
fontOptions?: FontOption[];
|
|
56
|
+
colorPalette?: (string | null)[][];
|
|
57
|
+
}
|
|
58
|
+
export declare const ProductEditorProvider: React.FC<ProductEditorProviderProps>;
|
|
59
|
+
export declare const useProductEditor: () => ProductEditorContextType;
|
|
60
|
+
export {};
|