@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,223 @@
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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
26
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
27
+ if (ar || !(i in from)) {
28
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
29
+ ar[i] = from[i];
30
+ }
31
+ }
32
+ return to.concat(ar || Array.prototype.slice.call(from));
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ var react_1 = __importStar(require("react"));
36
+ var ProductEditorContext_1 = require("../context/ProductEditorContext");
37
+ var grommet_icons_1 = require("grommet-icons");
38
+ require("../styles/LayerPanel.css");
39
+ var reorder = function (list, startIndex, endIndex) {
40
+ var result = Array.from(list);
41
+ var removed = result.splice(startIndex, 1)[0];
42
+ result.splice(endIndex, 0, removed);
43
+ return result;
44
+ };
45
+ var LAYER_ITEM_HEIGHT_PX = 45;
46
+ var LayerPanel = function () {
47
+ var _a = (0, ProductEditorContext_1.useProductEditor)(), canvas = _a.canvas, toggleLayerPanel = _a.toggleLayerPanel, selectedObjectId = _a.selectedObjectId, selectObject = _a.selectObject, isMobileView = _a.isMobileView;
48
+ var _b = (0, react_1.useState)([]), layers = _b[0], setLayers = _b[1];
49
+ var dragItemIndex = (0, react_1.useRef)(null);
50
+ var dragOverItemIndex = (0, react_1.useRef)(null);
51
+ var _c = (0, react_1.useState)(false), isDraggingOver = _c[0], setIsDraggingOver = _c[1];
52
+ var _d = (0, react_1.useState)(null), dragOverIndexVisual = _d[0], setDragOverIndexVisual = _d[1];
53
+ (0, react_1.useEffect)(function () {
54
+ if (canvas) {
55
+ var updateLayers_1 = function () {
56
+ var filteredObjects = canvas.getObjects().filter(function (obj) {
57
+ return (obj.type === 'i-text' || obj.type === 'image') && obj.selectable;
58
+ });
59
+ setLayers(__spreadArray([], filteredObjects, true).reverse());
60
+ };
61
+ updateLayers_1();
62
+ var handleCanvasChange_1 = function () { return updateLayers_1(); };
63
+ canvas.on('object:added', handleCanvasChange_1);
64
+ canvas.on('object:removed', handleCanvasChange_1);
65
+ canvas.on('stack:changed', handleCanvasChange_1);
66
+ canvas.on('selection:created', handleCanvasChange_1);
67
+ canvas.on('selection:updated', handleCanvasChange_1);
68
+ canvas.on('selection:cleared', handleCanvasChange_1);
69
+ return function () {
70
+ canvas.off('object:added', handleCanvasChange_1);
71
+ canvas.off('object:removed', handleCanvasChange_1);
72
+ canvas.off('stack:changed', handleCanvasChange_1);
73
+ canvas.off('selection:created', handleCanvasChange_1);
74
+ canvas.off('selection:updated', handleCanvasChange_1);
75
+ canvas.off('selection:cleared', handleCanvasChange_1);
76
+ };
77
+ }
78
+ }, [canvas]);
79
+ var getLayerInfo = function (object) {
80
+ var _a, _b;
81
+ if (object.type === 'i-text') {
82
+ return {
83
+ name: ((_a = object.text) === null || _a === void 0 ? void 0 : _a.substring(0, 20)) || 'Text',
84
+ icon: react_1.default.createElement(grommet_icons_1.TextAlignCenter, { size: "medium" })
85
+ };
86
+ }
87
+ if (object.type === 'image') {
88
+ var imageObject = object;
89
+ var src = imageObject.getSrc();
90
+ return {
91
+ name: object.name || (src ? (_b = src.split('/').pop()) === null || _b === void 0 ? void 0 : _b.substring(0, 20) : undefined) || 'Image',
92
+ icon: react_1.default.createElement("img", { src: src, alt: "layer thumb", className: "layer-thumbnail" })
93
+ };
94
+ }
95
+ return { name: 'Unknown Layer', icon: react_1.default.createElement(react_1.default.Fragment, null) };
96
+ };
97
+ var handleDragStart = function (e, index) {
98
+ if (isMobileView)
99
+ return;
100
+ dragItemIndex.current = index;
101
+ e.dataTransfer.effectAllowed = 'move';
102
+ setTimeout(function () { return setIsDraggingOver(true); }, 0);
103
+ };
104
+ var handleDragEnterItem = function (e, index) {
105
+ if (isMobileView)
106
+ return;
107
+ e.preventDefault();
108
+ dragOverItemIndex.current = index;
109
+ setDragOverIndexVisual(index);
110
+ };
111
+ var handleDragLeaveList = function (e) {
112
+ if (isMobileView)
113
+ return;
114
+ if (!e.currentTarget.contains(e.relatedTarget)) {
115
+ dragOverItemIndex.current = null;
116
+ setDragOverIndexVisual(null);
117
+ }
118
+ };
119
+ var handleDragOverList = function (e) {
120
+ if (isMobileView)
121
+ return;
122
+ e.preventDefault();
123
+ e.dataTransfer.dropEffect = 'move';
124
+ };
125
+ var handleDrop = function (e) {
126
+ if (isMobileView)
127
+ return;
128
+ e.preventDefault();
129
+ var sourceIndex = dragItemIndex.current;
130
+ var destinationIndex = dragOverItemIndex.current;
131
+ setIsDraggingOver(false);
132
+ setDragOverIndexVisual(null);
133
+ dragItemIndex.current = null;
134
+ dragOverItemIndex.current = null;
135
+ if (sourceIndex === null || destinationIndex === null || sourceIndex === destinationIndex) {
136
+ return;
137
+ }
138
+ var reorderedLayers = reorder(layers, sourceIndex, destinationIndex);
139
+ var objectToMove = layers[sourceIndex];
140
+ setLayers(reorderedLayers);
141
+ if (canvas && objectToMove) {
142
+ var totalObjects = canvas.getObjects().length;
143
+ var fabricTargetIndex = totalObjects - 1 - destinationIndex;
144
+ canvas.moveTo(objectToMove, fabricTargetIndex);
145
+ canvas.requestRenderAll();
146
+ }
147
+ };
148
+ var handleDragEnd = function (e) {
149
+ if (isMobileView)
150
+ return;
151
+ setIsDraggingOver(false);
152
+ setDragOverIndexVisual(null);
153
+ dragItemIndex.current = null;
154
+ dragOverItemIndex.current = null;
155
+ };
156
+ var moveLayerUp = function (index) {
157
+ if (index <= 0 || !canvas)
158
+ return;
159
+ var objectToMove = layers[index];
160
+ var objectAbove = layers[index - 1];
161
+ var fabricIndexOfAbove = canvas.getObjects().indexOf(objectAbove);
162
+ if (fabricIndexOfAbove < 0) {
163
+ console.error("Could not find objectAbove in canvas stack for moveLayerUp");
164
+ return;
165
+ }
166
+ var targetFabricIndex = fabricIndexOfAbove;
167
+ canvas.moveTo(objectToMove, targetFabricIndex);
168
+ setLayers(function (prevLayers) { return reorder(prevLayers, index, index - 1); });
169
+ canvas.requestRenderAll();
170
+ };
171
+ var moveLayerDown = function (index) {
172
+ if (index >= layers.length - 1 || !canvas)
173
+ return;
174
+ var objectToMove = layers[index];
175
+ var objectBelow = layers[index + 1];
176
+ var fabricIndexOfBelow = canvas.getObjects().indexOf(objectBelow);
177
+ if (fabricIndexOfBelow < 0) {
178
+ console.error("Could not find objectBelow in canvas stack for moveLayerDown");
179
+ return;
180
+ }
181
+ var targetFabricIndex = fabricIndexOfBelow;
182
+ canvas.moveTo(objectToMove, targetFabricIndex);
183
+ setLayers(function (prevLayers) { return reorder(prevLayers, index, index + 1); });
184
+ canvas.requestRenderAll();
185
+ };
186
+ var handleLayerClick = function (layer) {
187
+ selectObject(layer);
188
+ };
189
+ return (react_1.default.createElement("div", { className: "layer-panel" },
190
+ react_1.default.createElement("div", { className: "layer-panel-header" },
191
+ react_1.default.createElement("h3", null, "Layers"),
192
+ react_1.default.createElement("button", { onClick: toggleLayerPanel, className: "close-button", title: "Close Panel" },
193
+ react_1.default.createElement(grommet_icons_1.Close, { size: "small" }))),
194
+ react_1.default.createElement("ul", { className: "layer-list ".concat(isDraggingOver ? 'is-dragging-active' : ''), onDragOver: handleDragOverList, onDrop: handleDrop, onDragLeave: handleDragLeaveList },
195
+ layers.map(function (layer, index) {
196
+ var layerInfo = getLayerInfo(layer);
197
+ var layerId = layer.id;
198
+ var isSelected = layerId && layerId === selectedObjectId;
199
+ var isDraggingThisItem = !isMobileView && isDraggingOver && dragItemIndex.current === index;
200
+ var transformStyle = 'translateY(0px)';
201
+ if (!isMobileView && isDraggingOver && dragItemIndex.current !== null && dragOverIndexVisual !== null && !isDraggingThisItem) {
202
+ var draggingFromIndex = dragItemIndex.current;
203
+ var hoveringOverIndex = dragOverIndexVisual;
204
+ if (index > draggingFromIndex && index <= hoveringOverIndex) {
205
+ transformStyle = "translateY(-".concat(LAYER_ITEM_HEIGHT_PX, "px)");
206
+ }
207
+ else if (index < draggingFromIndex && index >= hoveringOverIndex) {
208
+ transformStyle = "translateY(".concat(LAYER_ITEM_HEIGHT_PX, "px)");
209
+ }
210
+ }
211
+ return (react_1.default.createElement("li", { key: "layer-".concat(layerId || index), draggable: !isMobileView, onDragStart: function (e) { return handleDragStart(e, index); }, onDragEnter: function (e) { return handleDragEnterItem(e, index); }, onDragEnd: handleDragEnd, onClick: function () { return handleLayerClick(layer); }, className: "layer-item ".concat(isSelected ? 'selected' : '', " ").concat(isDraggingThisItem ? 'is-dragging-item' : ''), style: { transform: transformStyle } },
212
+ react_1.default.createElement("span", { className: "layer-icon" }, layerInfo.icon),
213
+ react_1.default.createElement("span", { className: "layer-name" }, layerInfo.name),
214
+ isMobileView ? (react_1.default.createElement("div", { className: "layer-mobile-controls" },
215
+ react_1.default.createElement("button", { className: "layer-move-button", onClick: function (e) { e.stopPropagation(); moveLayerUp(index); }, disabled: index === 0, title: "Move Up" },
216
+ react_1.default.createElement(grommet_icons_1.Up, { size: "small" })),
217
+ react_1.default.createElement("button", { className: "layer-move-button", onClick: function (e) { e.stopPropagation(); moveLayerDown(index); }, disabled: index === layers.length - 1, title: "Move Down" },
218
+ react_1.default.createElement(grommet_icons_1.Down, { size: "small" })))) : (react_1.default.createElement("span", { className: "layer-drag-indicator" },
219
+ react_1.default.createElement(grommet_icons_1.Drag, { size: "small" })))));
220
+ }),
221
+ layers.length === 0 && react_1.default.createElement("li", { className: "no-layers" }, "No layers found"))));
222
+ };
223
+ exports.default = LayerPanel;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import '../styles/LoadingOverlay.css';
3
+ interface LoadingOverlayProps {
4
+ isLoading: boolean;
5
+ message?: string;
6
+ className?: string;
7
+ }
8
+ declare const LoadingOverlay: React.FC<LoadingOverlayProps>;
9
+ export default LoadingOverlay;
@@ -0,0 +1,17 @@
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
+ require("../styles/LoadingOverlay.css");
8
+ var LoadingOverlay = function (_a) {
9
+ var isLoading = _a.isLoading, _b = _a.message, message = _b === void 0 ? "Loading Canvas..." : _b, _c = _a.className, className = _c === void 0 ? "" : _c;
10
+ if (!isLoading) {
11
+ return null;
12
+ }
13
+ return (react_1.default.createElement("div", { className: "loading-overlay ".concat(className) },
14
+ react_1.default.createElement("div", { className: "loading-spinner" }),
15
+ react_1.default.createElement("p", null, message)));
16
+ };
17
+ exports.default = LoadingOverlay;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import '../styles/ProductEditor.css';
3
+ declare const ProductEditor: React.FC;
4
+ export default ProductEditor;
@@ -0,0 +1,67 @@
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 __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ var react_1 = __importDefault(require("react"));
18
+ var ProductEditorContext_1 = require("../context/ProductEditorContext");
19
+ var FloatingToolbar_1 = __importDefault(require("./FloatingToolbar"));
20
+ var ProductPreviews_1 = __importDefault(require("./ProductPreviews"));
21
+ var Toolbar_1 = __importDefault(require("./Toolbar"));
22
+ var LoadingOverlay_1 = __importDefault(require("./LoadingOverlay"));
23
+ var TextToolbar_1 = __importDefault(require("./TextToolbar"));
24
+ var LayerPanel_1 = __importDefault(require("./LayerPanel"));
25
+ require("../styles/ProductEditor.css");
26
+ var ProductEditor = function () {
27
+ var _a = (0, ProductEditorContext_1.useProductEditor)(), canvasRef = _a.canvasRef, draftTemplates = _a.draftTemplates, groupIndex = _a.groupIndex, handleTemplateChange = _a.handleTemplateChange, isMobileView = _a.isMobileView, selectedTemplate = _a.selectedTemplate, showPreview = _a.showPreview, inputName = _a.inputName, isCanvasLoading = _a.isCanvasLoading, hookForm = _a.hookForm, selectedTextObject = _a.selectedTextObject, showLayerPanel = _a.showLayerPanel, renderedDraftPreviews = _a.renderedDraftPreviews;
28
+ var disableCanvasEvents = function (e) {
29
+ if (e.target.closest('.floating-toolbar') ||
30
+ e.target.closest('.bottom-preview-section') ||
31
+ e.target.closest('.mobile-bottom-toolbar')) {
32
+ return;
33
+ }
34
+ e.stopPropagation();
35
+ };
36
+ var getTemplatePreviewImage = function (templateId) {
37
+ if (!templateId)
38
+ return null;
39
+ var renderedPreview = renderedDraftPreviews === null || renderedDraftPreviews === void 0 ? void 0 : renderedDraftPreviews.find(function (preview) { return preview.templateId === templateId; });
40
+ if (renderedPreview === null || renderedPreview === void 0 ? void 0 : renderedPreview.canvasPreview) {
41
+ return renderedPreview.canvasPreview;
42
+ }
43
+ return null;
44
+ };
45
+ var register = hookForm === null || hookForm === void 0 ? void 0 : hookForm.register;
46
+ return (react_1.default.createElement("div", { className: "product-editor" },
47
+ register && (react_1.default.createElement("input", __assign({}, register(inputName), { type: 'hidden' }))),
48
+ !isCanvasLoading && draftTemplates.length > 0 && (react_1.default.createElement("div", { className: "template-buttons" }, draftTemplates.map(function (_a) {
49
+ var _b;
50
+ var template = _a.template;
51
+ return (react_1.default.createElement("div", { key: template.id, className: "template-button ".concat(selectedTemplate === template.id ? 'selected' : ''), onClick: function () { return handleTemplateChange(template); } },
52
+ !isMobileView && (getTemplatePreviewImage(template.id) || (template.file && template.file.viewUrl)) && (react_1.default.createElement("img", { src: getTemplatePreviewImage(template.id) || (((_b = template.file) === null || _b === void 0 ? void 0 : _b.viewUrl) || ''), alt: template.name || "Template ".concat(template.id), className: "template-thumbnail" })),
53
+ react_1.default.createElement("span", { className: "template-name" }, template.name || "Template ".concat(template.id))));
54
+ }))),
55
+ react_1.default.createElement("div", { className: "main-editor-layout", style: { position: 'relative' } },
56
+ react_1.default.createElement(LoadingOverlay_1.default, { isLoading: isCanvasLoading, className: "canvas-loading" }),
57
+ react_1.default.createElement("div", { className: "editor-container ".concat(isMobileView && showPreview ? 'has-bottom-padding' : '') },
58
+ selectedTextObject && react_1.default.createElement(TextToolbar_1.default, null),
59
+ react_1.default.createElement("div", { className: "canvas-area", onClick: disableCanvasEvents },
60
+ react_1.default.createElement("canvas", { ref: canvasRef })),
61
+ !isMobileView && !isCanvasLoading && react_1.default.createElement(FloatingToolbar_1.default, null),
62
+ showLayerPanel && react_1.default.createElement(LayerPanel_1.default, null)),
63
+ showPreview && react_1.default.createElement(ProductPreviews_1.default, null)),
64
+ isMobileView && !isCanvasLoading && (react_1.default.createElement("div", { className: "mobile-bottom-toolbar" },
65
+ react_1.default.createElement(Toolbar_1.default, null)))));
66
+ };
67
+ exports.default = ProductEditor;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ interface ImageGalleryProps {
3
+ fallbackImageUrl?: string;
4
+ }
5
+ declare const ProductImageGallery: React.FC<ImageGalleryProps>;
6
+ export default ProductImageGallery;
@@ -0,0 +1,148 @@
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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
37
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
38
+ if (ar || !(i in from)) {
39
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
40
+ ar[i] = from[i];
41
+ }
42
+ }
43
+ return to.concat(ar || Array.prototype.slice.call(from));
44
+ };
45
+ var __importDefault = (this && this.__importDefault) || function (mod) {
46
+ return (mod && mod.__esModule) ? mod : { "default": mod };
47
+ };
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ var react_1 = __importStar(require("react"));
50
+ var framer_motion_1 = require("framer-motion");
51
+ var ImageNavButton_1 = __importDefault(require("./ImageNavButton"));
52
+ var ImageZoomModal_1 = __importDefault(require("./ImageZoomModal"));
53
+ var grommet_icons_1 = require("grommet-icons");
54
+ var ProductEditorContext_1 = require("../context/ProductEditorContext");
55
+ var useSwipeNavigate_1 = require("../hooks/useSwipeNavigate");
56
+ var ProductImageGallery = function (_a) {
57
+ var _b;
58
+ var _c = _a.fallbackImageUrl, fallbackImageUrl = _c === void 0 ? '' : _c;
59
+ var product = (0, ProductEditorContext_1.useProductEditor)().product;
60
+ var _d = product.featureImage, featureImage = _d === void 0 ? null : _d, _e = product.images, images = _e === void 0 ? [] : _e, _f = product.name, productName = _f === void 0 ? 'Loading...' : _f;
61
+ var _images = featureImage ? __spreadArray([featureImage], images, true) : images;
62
+ var allImages = _images.map(function (image) {
63
+ if (!image)
64
+ return { viewUrl: '/blueman_white.png' };
65
+ return { viewUrl: image.viewUrl };
66
+ });
67
+ var totalImages = allImages.length;
68
+ // image browser related states
69
+ var _g = (0, react_1.useState)('right'), slideDirection = _g[0], setSlideDirection = _g[1];
70
+ var _h = (0, react_1.useState)(false), isZoomModalOpen = _h[0], setIsZoomModalOpen = _h[1];
71
+ var _j = (0, react_1.useState)(true), isImageLoading = _j[0], setIsImageLoading = _j[1];
72
+ var _k = (0, react_1.useState)(0), currentIndex = _k[0], setCurrentIndex = _k[1];
73
+ var _l = (0, react_1.useState)(((_b = allImages[currentIndex]) === null || _b === void 0 ? void 0 : _b.viewUrl) || fallbackImageUrl || '/blueman_white.png'), currentImageUrl = _l[0], setCurrentImageUrl = _l[1];
74
+ (0, react_1.useEffect)(function () {
75
+ var _a;
76
+ // set current image URL (for normal image mode)
77
+ if (allImages && allImages.length > 0) {
78
+ setCurrentImageUrl(((_a = allImages[currentIndex]) === null || _a === void 0 ? void 0 : _a.viewUrl) || '/blueman_white.png');
79
+ }
80
+ }, [allImages, currentIndex, fallbackImageUrl]);
81
+ var handleNavigation = function (newDirection) {
82
+ var _a;
83
+ if (!allImages || allImages.length <= 1)
84
+ return;
85
+ setSlideDirection(newDirection === 'left' ? 'left' : 'right');
86
+ var newIndex;
87
+ var actualTotalImages = Math.min(totalImages, allImages.length);
88
+ if (newDirection === 'left') {
89
+ newIndex = currentIndex === 0 ? actualTotalImages - 1 : currentIndex - 1;
90
+ }
91
+ else {
92
+ newIndex = currentIndex === actualTotalImages - 1 ? 0 : currentIndex + 1;
93
+ }
94
+ setCurrentIndex(newIndex);
95
+ setCurrentImageUrl(((_a = allImages[newIndex]) === null || _a === void 0 ? void 0 : _a.viewUrl) || '/blueman_white.png');
96
+ };
97
+ var handleThumbnailClick = function (index) {
98
+ var _a;
99
+ setCurrentIndex(index);
100
+ setCurrentImageUrl(((_a = allImages[index]) === null || _a === void 0 ? void 0 : _a.viewUrl) || '/blueman_white.png');
101
+ };
102
+ // Use the swipe hook
103
+ var swipeHandlers = (0, useSwipeNavigate_1.useSwipeNavigate)({
104
+ onSwipeLeft: function () { return handleNavigation('right'); },
105
+ onSwipeRight: function () { return handleNavigation('left'); },
106
+ });
107
+ var slideVariants = {
108
+ enter: function (direction) { return ({
109
+ x: direction === 'left' ? -1000 : 1000,
110
+ opacity: 0
111
+ }); },
112
+ center: {
113
+ zIndex: 1,
114
+ x: 0,
115
+ opacity: 1
116
+ },
117
+ exit: function (direction) { return ({
118
+ zIndex: 0,
119
+ x: direction === 'left' ? 1000 : -1000,
120
+ opacity: 0
121
+ }); }
122
+ };
123
+ return (react_1.default.createElement(react_1.default.Fragment, null,
124
+ react_1.default.createElement("div", { className: "image-gallery-container relative" },
125
+ react_1.default.createElement("div", { className: "image-container overflow-hidden" },
126
+ react_1.default.createElement(framer_motion_1.AnimatePresence, { initial: false, custom: slideDirection },
127
+ react_1.default.createElement(framer_motion_1.motion.div, __assign({ key: currentIndex, custom: slideDirection, variants: slideVariants, initial: "enter", animate: "center", exit: "exit", transition: {
128
+ x: { type: "spring", stiffness: 300, damping: 30 },
129
+ opacity: { duration: 0.2 }
130
+ }, className: "image-slide" }, swipeHandlers),
131
+ react_1.default.createElement("img", { src: currentImageUrl, alt: productName || "Product Image", className: "gallery-image ".concat(isImageLoading ? '' : 'image-loaded'), onLoad: function () { return setIsImageLoading(false); } }),
132
+ isImageLoading && (react_1.default.createElement("div", { className: "loading-indicator" },
133
+ react_1.default.createElement("div", { className: "loading-spinner" }))))),
134
+ react_1.default.createElement("button", { onClick: function () { return setIsZoomModalOpen(true); }, className: "zoom-button", type: "button" },
135
+ react_1.default.createElement(grommet_icons_1.ZoomIn, { className: "zoom-icon" }))),
136
+ allImages.length > 1 && (react_1.default.createElement("div", { className: "nav-buttons-container" },
137
+ react_1.default.createElement(ImageNavButton_1.default, { direction: "left", onClick: function () { return handleNavigation('left'); } }),
138
+ react_1.default.createElement(ImageNavButton_1.default, { direction: "right", onClick: function () { return handleNavigation('right'); } })))),
139
+ allImages.length > 1 && (react_1.default.createElement("div", { className: "thumbnails-container" },
140
+ react_1.default.createElement("div", { className: "thumbnails-row" }, allImages.slice(0, 5).map(function (image, index) {
141
+ var imageSrc = image.viewUrl || "/blueman_white.png";
142
+ var isSelected = index === currentIndex;
143
+ return (react_1.default.createElement("button", { key: index, onClick: function () { return handleThumbnailClick(index); }, className: "thumbnail-button ".concat(isSelected ? 'selected' : ''), type: "button" },
144
+ react_1.default.createElement("img", { src: imageSrc, loading: "lazy", alt: "Product Image ".concat(index + 1), className: "thumbnail-image" })));
145
+ })))),
146
+ react_1.default.createElement(ImageZoomModal_1.default, { isOpen: isZoomModalOpen, onClose: function () { return setIsZoomModalOpen(false); }, imageUrl: currentImageUrl, productName: productName, totalImages: allImages.length, currentIndex: currentIndex, allImages: allImages })));
147
+ };
148
+ exports.default = ProductImageGallery;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import '../styles/ProductEditor.css';
3
+ import '../styles/BottomPreviewDisplay.css';
4
+ interface BottomPreviewDisplayProps {
5
+ }
6
+ declare const ProductPreviews: React.FC<BottomPreviewDisplayProps>;
7
+ export default ProductPreviews;