@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,53 @@
1
+ /**
2
+ * Type definitions for psd.js
3
+ * https://github.com/meltingice/psd.js
4
+ */
5
+
6
+ declare module 'psd.js' {
7
+ export interface PsdHeader {
8
+ width: number;
9
+ height: number;
10
+ channels: number;
11
+ depth: number;
12
+ mode: number;
13
+ }
14
+
15
+ export interface PsdImage {
16
+ width: () => number;
17
+ height: () => number;
18
+ toPng: () => HTMLImageElement;
19
+ toBase64: () => string;
20
+ saveAsPng: (output: string) => void;
21
+ }
22
+
23
+ export interface PsdLayer {
24
+ name: string;
25
+ visible: boolean;
26
+ opacity: number;
27
+ width: number;
28
+ height: number;
29
+ top: number;
30
+ left: number;
31
+ toPng: () => HTMLImageElement;
32
+ }
33
+
34
+ export interface PsdFile {
35
+ header: PsdHeader;
36
+ image: PsdImage;
37
+ layers: PsdLayer[];
38
+ tree: () => any;
39
+ }
40
+
41
+ export function fromURL(url: string): Promise<PsdFile>;
42
+ export function fromBuffer(buffer: ArrayBuffer): Promise<PsdFile>;
43
+ export function fromFile(file: File): Promise<PsdFile>;
44
+
45
+ // Default export
46
+ const PSD: {
47
+ fromURL: typeof fromURL;
48
+ fromBuffer: typeof fromBuffer;
49
+ fromFile: typeof fromFile;
50
+ };
51
+
52
+ export default PSD;
53
+ }
package/src/types.ts ADDED
@@ -0,0 +1,247 @@
1
+ export enum FieldType {
2
+ TEXT_INPUT = 1,
3
+ SELECT = 2,
4
+ FILE_UPLOAD = 3,
5
+ TEXT_AREA = 4,
6
+ NUMBER_INPUT = 5,
7
+ CHECKBOX = 6,
8
+ RADIO = 7,
9
+ FIELD_INSTRUCTIONS = 8,
10
+ IMAGE_SELECT = 9,
11
+ COLOUR_PICKER = 10,
12
+ COLOUR_SELECT = 11,
13
+ }
14
+
15
+ export interface Draft {
16
+ id?: number;
17
+ // Add other draft properties as needed
18
+ }
19
+
20
+ export interface MerchiFile {
21
+ id?: number;
22
+ uploadId?: string;
23
+ name?: string | null;
24
+ mimetype?: string | null;
25
+ size?: number;
26
+ creationDate?: Date | null;
27
+ cachedViewUrl?: string | null;
28
+ viewUrlExpires?: Date | null;
29
+ cachedDownloadUrl?: string | null;
30
+ downloadUrlExpires?: Date | null;
31
+ viewUrl: string;
32
+ downloadUrl?: string;
33
+ thumbnailUrl?: string;
34
+ previewUrl?: string;
35
+ }
36
+
37
+ export interface DraftTemplate {
38
+ id?: number;
39
+ name?: string;
40
+ description?: string;
41
+ width?: number;
42
+ height?: number;
43
+ file?: MerchiFile;
44
+ product?: Product | null;
45
+ editedByVariationFields?: VariationField[];
46
+ selectedByVariationFieldOptions?: VariationFieldsOption[];
47
+ draftPreviewLayers?: DraftPreviewLayer[];
48
+ }
49
+
50
+ export interface DraftPreview {
51
+ id?: number;
52
+ file?: MerchiFile;
53
+ product?: Product;
54
+ description?: string | null;
55
+ name?: string | null;
56
+ date?: Date | null;
57
+ height?: number;
58
+ width?: number;
59
+ draftPreviewLayers?: DraftPreviewLayer[];
60
+ }
61
+
62
+ export interface DraftPreviewLayer {
63
+ id?: number;
64
+ layerName?: string;
65
+ draftPreview?: DraftPreview;
66
+ draftTemplate?: DraftTemplate;
67
+ }
68
+
69
+ export interface VariationFieldsOption {
70
+ id?: number;
71
+ archived?: Date | null;
72
+ value?: string | null;
73
+ colour?: string | null;
74
+ currency?: string;
75
+ default?: boolean;
76
+ include?: boolean;
77
+ noInventory?: boolean;
78
+ position?: number;
79
+ variationCost?: number;
80
+ variationUnitCost?: number;
81
+ buyUnitCost?: number;
82
+ buyCost?: number;
83
+ variationField?: VariationField | null;
84
+ linkedFile?: MerchiFile | null;
85
+ selectedByVariations?: Variation[];
86
+ }
87
+
88
+ export interface VariationField {
89
+ id?: number;
90
+ archived?: Date | null;
91
+ position?: number;
92
+ required?: boolean;
93
+ independent?: boolean;
94
+ name?: string;
95
+ instructions?: string;
96
+ placeholder?: string | null;
97
+ defaultValue?: string;
98
+ currency?: string;
99
+ fieldType?: FieldType;
100
+ margin?: number;
101
+ variationCost?: number;
102
+ variationUnitCost?: number;
103
+ buyUnitCost?: number;
104
+ buyCost?: number;
105
+ rows?: number;
106
+ fieldMin?: number | null;
107
+ fieldMax?: number | null;
108
+ allowDecimal?: boolean;
109
+ sellerProductEditable?: boolean;
110
+ multipleSelect?: boolean;
111
+ showFilePreview?: boolean;
112
+ allowFileMultiple?: boolean;
113
+ allowFileJpeg?: boolean;
114
+ allowFileGif?: boolean;
115
+ allowFilePdf?: boolean;
116
+ allowFilePng?: boolean;
117
+ allowFileAi?: boolean;
118
+ product?: Product;
119
+ variations?: Variation[];
120
+ options?: VariationFieldsOption[];
121
+ }
122
+
123
+ export interface VariationOption {
124
+ optionId?: number;
125
+ value?: string | null;
126
+ colour?: string | null;
127
+ position?: number;
128
+ available?: boolean;
129
+ default?: boolean;
130
+ include?: boolean;
131
+ linkedFile?: MerchiFile | null;
132
+ fieldName?: string;
133
+ quantity?: number;
134
+ currency?: string;
135
+ onceOffCost?: number;
136
+ unitCost?: number;
137
+ unitCostTotal?: number;
138
+ totalCost?: number;
139
+ }
140
+
141
+ export interface Variation {
142
+ id?: number;
143
+ archived?: Date | null;
144
+ value?: string | null;
145
+ currency?: string;
146
+ cost?: number;
147
+ quantity?: number;
148
+ onceOffCost?: number;
149
+ unitCost?: number;
150
+ unitCostTotal?: number;
151
+ variationField?: VariationField;
152
+ variationsGroup?: VariationsGroup | null;
153
+ job?: Job | null;
154
+ variationFiles?: MerchiFile[];
155
+ selectedOptions?: VariationOption[];
156
+ selectableOptions?: VariationOption[];
157
+ }
158
+
159
+ export interface VariationsGroup {
160
+ id?: number;
161
+ archived?: Date | null;
162
+ quantity?: number;
163
+ groupCost?: number | null;
164
+ job?: Job | null;
165
+ variations?: Variation[];
166
+ inventoryCount?: number;
167
+ inventorySufficient?: boolean;
168
+ }
169
+
170
+ export interface Product {
171
+ id?: number;
172
+ name?: string;
173
+ description?: string | null;
174
+ draftTemplates?: DraftTemplate[];
175
+ draftPreviews?: DraftPreview[];
176
+ featureImage?: MerchiFile;
177
+ groupVariationFields?: VariationField[];
178
+ independentVariationFields?: VariationField[];
179
+ images?: MerchiFile[];
180
+ }
181
+
182
+ export interface Job {
183
+ id?: number;
184
+ quantity?: number;
185
+ currency?: string;
186
+ jobInfoApprovedByClient?: boolean;
187
+ costPerUnit?: number | null;
188
+ cost?: number | null;
189
+ taxAmount?: number | null;
190
+ totalCost?: number | null;
191
+ drafts?: Draft[];
192
+ sharedDrafts?: Draft[];
193
+ ownDrafts?: Draft[];
194
+ product?: Product;
195
+ variationsGroups?: VariationsGroup[];
196
+ variations?: Variation[];
197
+ }
198
+
199
+ export interface ProductEditorProps {
200
+ product: Product;
201
+ width?: number;
202
+ height?: number;
203
+ onSave?: (editedImage: string) => void;
204
+ onCancel?: () => void;
205
+ psdTemplateUrl?: string;
206
+ }
207
+
208
+ export interface SavedCanvasObject {
209
+ fieldId: string;
210
+ fileId?: string;
211
+ uniqueId?: string; // Add uniqueId property to the interface
212
+ type: string;
213
+ left: number;
214
+ top: number;
215
+ scaleX: number;
216
+ scaleY: number;
217
+ angle: number;
218
+ text?: string;
219
+ fontSize?: number;
220
+ fontFamily?: string;
221
+ fill?: string;
222
+ width?: number;
223
+ height?: number;
224
+ src?: string;
225
+ [key: string]: any; // Allow for other properties
226
+ }
227
+
228
+ // New DraftTemplateData type definition that includes all requested properties
229
+ export interface DraftTemplateData {
230
+ template: DraftTemplate;
231
+ variationFieldIds: number[]; // List of IDs for all variation fields in this template
232
+ variationObjects: any[]; // Objects associated with the variation fields
233
+ }
234
+
235
+ export interface RenderedDraftPreview {
236
+ templateId: number;
237
+ draft: string; // base64 string of the template artwork as a draft
238
+ canvasPreview: string; // base64 string of the template rendered with the full canvas
239
+ }
240
+
241
+ export interface MappedPreview {
242
+ draftPreview: DraftPreview;
243
+ draftPreviewLayers: {
244
+ layerName: string | undefined;
245
+ renderedLayer: RenderedDraftPreview | null;
246
+ }[];
247
+ }
@@ -0,0 +1,72 @@
1
+ // add text to the canvas
2
+ import { fabric } from 'fabric';
3
+
4
+ /**
5
+ * Adds an editable text object to the canvas
6
+ * @param canvas - The Fabric.js canvas instance
7
+ * @param width - The width of the canvas
8
+ * @param height - The height of the canvas
9
+ * @param defaultText - Optional default text (defaults to "Text")
10
+ * @param fontSize - Optional font size (defaults to 24)
11
+ * @param fontFamily - Optional font family (defaults to Arial)
12
+ */
13
+ export const addText = (
14
+ canvas: fabric.Canvas,
15
+ width: number,
16
+ height: number,
17
+ defaultText: string = 'Text',
18
+ fontSize: number = 24,
19
+ fontFamily: string = 'Nunito'
20
+ ) => {
21
+ if (!canvas) return null;
22
+
23
+ try {
24
+ // Safe check if canvas is still valid
25
+ if (!canvas.getElement() || !canvas.getElement().parentNode) {
26
+ return null;
27
+ }
28
+
29
+ // Create a new text object with minimal options
30
+ const text = new fabric.IText(defaultText, {
31
+ left: width / 2,
32
+ top: height / 2,
33
+ fontFamily: fontFamily,
34
+ fontSize: fontSize,
35
+ fill: '#000000',
36
+ originX: 'center',
37
+ originY: 'center',
38
+ selectable: true,
39
+ editable: false
40
+ });
41
+
42
+ // Add the text to the canvas
43
+ canvas.add(text);
44
+
45
+ // Ensure the text is rendered
46
+ canvas.renderAll();
47
+
48
+ // Make the text active - this is critical
49
+ const setActiveTextObject = () => {
50
+ try {
51
+ // Check if canvas is still valid
52
+ if (canvas && canvas.getElement() && canvas.getElement().parentNode) {
53
+ canvas.setActiveObject(text);
54
+ canvas.renderAll();
55
+ }
56
+ } catch (err) {
57
+ console.error('Error setting active text object:', err);
58
+ }
59
+ };
60
+
61
+ // Initial selection
62
+ setActiveTextObject();
63
+
64
+ // Delayed selection to ensure text becomes active
65
+ setTimeout(setActiveTextObject, 50);
66
+
67
+ return text;
68
+ } catch (error) {
69
+ console.error('Error adding text to canvas:', error);
70
+ return null;
71
+ }
72
+ };