labellife-design-tool 1.1.6 → 1.1.8

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/README.md CHANGED
@@ -174,13 +174,43 @@ store.activePage.addElement({
174
174
  // Load templates
175
175
  await store.loadJSON(templateData);
176
176
 
177
+ // Export to blob
178
+ const pngBlob = await store.toBlob('png');
179
+ const jpgBlob = await store.toBlob('jpg');
180
+
181
+ // Download the blob
182
+ const downloadBlob = (blob: Blob, filename: string) => {
183
+ const url = URL.createObjectURL(blob);
184
+ const a = document.createElement('a');
185
+ a.href = url;
186
+ a.download = filename;
187
+ a.click();
188
+ URL.revokeObjectURL(url);
189
+ };
190
+
191
+ downloadBlob(pngBlob, 'design.png');
192
+ downloadBlob(jpgBlob, 'design.jpg');
193
+
177
194
  // Use with CanvasEditor (optional)
178
- <CanvasEditor name="Editor" config={{ panels: ["text", "elements"] }} />
195
+ <CanvasEditor
196
+ name="Editor"
197
+ store={store} // Pass the store (optional)
198
+ config={{ panels: ["text", "elements"] }}
199
+ />
179
200
 
180
201
  // Export store for use across your app
181
202
  export const store = createSimpleStore();
182
203
  ```
183
204
 
205
+ **Backward Compatibility**
206
+
207
+ If you don't pass a `store` prop, CanvasEditor will create one internally:
208
+
209
+ ```tsx
210
+ // This still works - creates internal store
211
+ <CanvasEditor name="Editor" config={{ panels: ["text", "elements"] }} />
212
+ ```
213
+
184
214
  **Option 2: Use the `useCanvasStore` hook (inside CanvasEditor only)**
185
215
 
186
216
  Any component inside `CanvasEditor` can access the store using the hook:
@@ -316,6 +346,9 @@ interface SimpleStore {
316
346
  updateDesign(updates: Partial<CanvasDesign>): void;
317
347
  loadJSON(jsonData: any): Promise<void>;
318
348
 
349
+ // Export operations
350
+ toBlob(type?: 'png' | 'jpg'): Promise<Blob>;
351
+
319
352
  // Events
320
353
  on(event: 'designChanged' | 'activePageChanged' | 'activePanelChanged', callback: Function): void;
321
354
  off(event: string): void;
@@ -3108,11 +3108,216 @@ var TemplateInputModal = ({
3108
3108
  };
3109
3109
  var TemplateInputModal_default = TemplateInputModal;
3110
3110
 
3111
+ // src/store/simpleStore.ts
3112
+ class SimpleCanvasStore {
3113
+ _design;
3114
+ _activePageId;
3115
+ _activePanelId;
3116
+ _listeners = {};
3117
+ constructor(initialDesign) {
3118
+ this._design = {
3119
+ id: initialDesign?.id || `design-${Date.now()}`,
3120
+ name: initialDesign?.name || "Untitled Design",
3121
+ width: initialDesign?.width || 800,
3122
+ height: initialDesign?.height || 600,
3123
+ pages: initialDesign?.pages || [
3124
+ {
3125
+ id: "page-1",
3126
+ name: "Page 1",
3127
+ elements: [],
3128
+ background: "#ffffff"
3129
+ }
3130
+ ],
3131
+ fonts: initialDesign?.fonts || [],
3132
+ colors: initialDesign?.colors || [],
3133
+ templateInputs: initialDesign?.templateInputs
3134
+ };
3135
+ this._activePageId = this._design.pages[0]?.id || "page-1";
3136
+ this._activePanelId = null;
3137
+ }
3138
+ on(event, callback) {
3139
+ this._listeners[event] = callback;
3140
+ }
3141
+ off(event) {
3142
+ delete this._listeners[event];
3143
+ }
3144
+ emit(event, ...args) {
3145
+ const callback = this._listeners[event];
3146
+ if (callback) {
3147
+ callback(...args);
3148
+ }
3149
+ }
3150
+ get design() {
3151
+ return this._design;
3152
+ }
3153
+ get width() {
3154
+ return this._design.width;
3155
+ }
3156
+ get height() {
3157
+ return this._design.height;
3158
+ }
3159
+ get activePage() {
3160
+ return this._design.pages.find((p) => p.id === this._activePageId) || null;
3161
+ }
3162
+ get activePageId() {
3163
+ return this._activePageId;
3164
+ }
3165
+ get activePanelId() {
3166
+ return this._activePanelId;
3167
+ }
3168
+ setDesign(design) {
3169
+ this._design = design;
3170
+ if (design.pages.find((p) => p.id === this._activePageId)) {} else if (design.pages.length > 0) {
3171
+ this._activePageId = design.pages[0].id;
3172
+ }
3173
+ this.emit("designChanged", design);
3174
+ this.emit("activePageChanged", this._activePageId);
3175
+ }
3176
+ updateDesign(updates) {
3177
+ this._design = { ...this._design, ...updates };
3178
+ this.emit("designChanged", this._design);
3179
+ }
3180
+ addPage(page) {
3181
+ const newPage = {
3182
+ id: page?.id || `page-${Date.now()}`,
3183
+ name: page?.name || `Page ${this._design.pages.length + 1}`,
3184
+ elements: page?.elements || [],
3185
+ background: page?.background || "#ffffff",
3186
+ backgroundImageObject: page?.backgroundImageObject
3187
+ };
3188
+ this._design.pages.push(newPage);
3189
+ this.emit("designChanged", this._design);
3190
+ return newPage.id;
3191
+ }
3192
+ deletePages(pageIds) {
3193
+ const remainingPages = this._design.pages.filter((p) => !pageIds.includes(p.id));
3194
+ if (remainingPages.length === 0) {
3195
+ console.warn("Cannot delete all pages. At least one page must remain.");
3196
+ return;
3197
+ }
3198
+ if (pageIds.includes(this._activePageId)) {
3199
+ this._activePageId = remainingPages[0].id;
3200
+ this.emit("activePageChanged", this._activePageId);
3201
+ }
3202
+ this._design.pages = remainingPages;
3203
+ this.emit("designChanged", this._design);
3204
+ }
3205
+ setActivePage(pageId) {
3206
+ const page = this._design.pages.find((p) => p.id === pageId);
3207
+ if (page) {
3208
+ this._activePageId = pageId;
3209
+ this.emit("activePageChanged", pageId);
3210
+ this.emit("designChanged", this._design);
3211
+ }
3212
+ }
3213
+ addElement(element) {
3214
+ const page = this.activePage;
3215
+ if (!page)
3216
+ return;
3217
+ const newElement = {
3218
+ id: element.id || `element-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
3219
+ type: element.type,
3220
+ name: element.name || `${element.type} element`,
3221
+ x: element.x || 0,
3222
+ y: element.y || 0,
3223
+ width: element.width || 100,
3224
+ height: element.height || 100,
3225
+ rotation: element.rotation || 0,
3226
+ visible: element.visible !== false,
3227
+ locked: element.locked || false,
3228
+ opacity: element.opacity || 1,
3229
+ ...element
3230
+ };
3231
+ page.elements.push(newElement);
3232
+ this.emit("designChanged", this._design);
3233
+ }
3234
+ updateElement(elementId, updates) {
3235
+ for (const page of this._design.pages) {
3236
+ const elementIndex = page.elements.findIndex((e) => e.id === elementId);
3237
+ if (elementIndex !== -1) {
3238
+ page.elements[elementIndex] = { ...page.elements[elementIndex], ...updates };
3239
+ this.emit("designChanged", this._design);
3240
+ return;
3241
+ }
3242
+ }
3243
+ }
3244
+ deleteElement(elementId) {
3245
+ for (const page of this._design.pages) {
3246
+ const elementIndex = page.elements.findIndex((e) => e.id === elementId);
3247
+ if (elementIndex !== -1) {
3248
+ page.elements.splice(elementIndex, 1);
3249
+ this.emit("designChanged", this._design);
3250
+ return;
3251
+ }
3252
+ }
3253
+ }
3254
+ openSidePanel(panelId) {
3255
+ this._activePanelId = panelId;
3256
+ this.emit("activePanelChanged", panelId);
3257
+ }
3258
+ async toBlob(type = "png") {
3259
+ return new Promise((resolve, reject) => {
3260
+ try {
3261
+ Promise.resolve().then(() => exports_exportImportUtils).then(({ canvasToBlob: canvasToBlob2 }) => {
3262
+ const canvas = document.createElement("canvas");
3263
+ canvas.width = this._design.width;
3264
+ canvas.height = this._design.height;
3265
+ const ctx = canvas.getContext("2d");
3266
+ if (!ctx) {
3267
+ reject(new Error("Failed to get canvas context"));
3268
+ return;
3269
+ }
3270
+ ctx.fillStyle = "#ffffff";
3271
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
3272
+ const mimeType = type === "jpg" ? "image/jpeg" : "image/png";
3273
+ const quality = type === "jpg" ? 0.9 : undefined;
3274
+ canvas.toBlob((blob) => {
3275
+ if (blob) {
3276
+ resolve(blob);
3277
+ } else {
3278
+ reject(new Error("Failed to create blob"));
3279
+ }
3280
+ }, mimeType, quality);
3281
+ });
3282
+ } catch (error) {
3283
+ reject(error);
3284
+ }
3285
+ });
3286
+ }
3287
+ async loadJSON(jsonData) {
3288
+ return new Promise((resolve, reject) => {
3289
+ try {
3290
+ Promise.resolve().then(() => exports_exportImportUtils).then(({ importFromJSONData: importFromJSONData2 }) => {
3291
+ importFromJSONData2(jsonData, (loadedDesign) => {
3292
+ this.setDesign(loadedDesign);
3293
+ resolve();
3294
+ }, (errorMessage) => {
3295
+ reject(new Error(errorMessage));
3296
+ }, () => {
3297
+ reject(new Error("Templates requiring user inputs are not yet supported in standalone store"));
3298
+ });
3299
+ });
3300
+ } catch (error) {
3301
+ reject(error);
3302
+ }
3303
+ });
3304
+ }
3305
+ }
3306
+ var createSimpleStore = (initialDesign) => {
3307
+ return new SimpleCanvasStore(initialDesign);
3308
+ };
3309
+
3111
3310
  // src/CanvasEditor.tsx
3112
3311
  var CanvasEditor = ({
3113
3312
  name,
3114
- config
3313
+ config,
3314
+ store: externalStore
3115
3315
  }) => {
3316
+ const store = externalStore || createSimpleStore({
3317
+ name,
3318
+ width: 800,
3319
+ height: 600
3320
+ });
3116
3321
  const [design, setDesign] = useState3({
3117
3322
  id: Date.now().toString(),
3118
3323
  name: "Untitled Design",
@@ -3517,7 +3722,7 @@ var CanvasEditor = ({
3517
3722
  id: "elements",
3518
3723
  title: "Elements",
3519
3724
  component: ElementPanel_default,
3520
- props: { onAddShape: addShape }
3725
+ props: { onAddShape: addShape, store }
3521
3726
  },
3522
3727
  {
3523
3728
  id: "text",
@@ -3527,7 +3732,8 @@ var CanvasEditor = ({
3527
3732
  selectedElement,
3528
3733
  updateElement,
3529
3734
  setTool,
3530
- onAddText: addText
3735
+ onAddText: addText,
3736
+ store
3531
3737
  }
3532
3738
  },
3533
3739
  {
@@ -3543,7 +3749,8 @@ var CanvasEditor = ({
3543
3749
  setUnsplashMode("element");
3544
3750
  },
3545
3751
  canvasWidth: design.width,
3546
- canvasHeight: design.height
3752
+ canvasHeight: design.height,
3753
+ store
3547
3754
  }
3548
3755
  },
3549
3756
  {
@@ -3560,7 +3767,8 @@ var CanvasEditor = ({
3560
3767
  setShowUnsplash(true);
3561
3768
  setUnsplashMode("background");
3562
3769
  },
3563
- config
3770
+ config,
3771
+ store
3564
3772
  }
3565
3773
  },
3566
3774
  {
@@ -3574,7 +3782,8 @@ var CanvasEditor = ({
3574
3782
  onSetUnsplashBackground: () => {
3575
3783
  setShowUnsplash(true);
3576
3784
  setUnsplashMode("background");
3577
- }
3785
+ },
3786
+ store
3578
3787
  }
3579
3788
  },
3580
3789
  ...config?.variables ? [
@@ -3585,7 +3794,8 @@ var CanvasEditor = ({
3585
3794
  props: {
3586
3795
  config,
3587
3796
  design,
3588
- setDesign
3797
+ setDesign,
3798
+ store
3589
3799
  }
3590
3800
  }
3591
3801
  ] : [],
@@ -3604,7 +3814,8 @@ var CanvasEditor = ({
3604
3814
  exportToJPG(stageRef.current, design);
3605
3815
  } : undefined,
3606
3816
  onExportToJSON: config.export?.json ? () => exportToJSON(design) : undefined,
3607
- onImportJSON: () => jsonInputRef.current?.click()
3817
+ onImportJSON: () => jsonInputRef.current?.click(),
3818
+ store
3608
3819
  }
3609
3820
  }
3610
3821
  ] : []
@@ -3824,175 +4035,6 @@ var CanvasEditor = ({
3824
4035
  }, "Enter a search term to find images")))));
3825
4036
  };
3826
4037
  var CanvasEditor_default = CanvasEditor;
3827
- // src/store/simpleStore.ts
3828
- class SimpleCanvasStore {
3829
- _design;
3830
- _activePageId;
3831
- _activePanelId;
3832
- _listeners = {};
3833
- constructor(initialDesign) {
3834
- this._design = {
3835
- id: initialDesign?.id || `design-${Date.now()}`,
3836
- name: initialDesign?.name || "Untitled Design",
3837
- width: initialDesign?.width || 800,
3838
- height: initialDesign?.height || 600,
3839
- pages: initialDesign?.pages || [
3840
- {
3841
- id: "page-1",
3842
- name: "Page 1",
3843
- elements: [],
3844
- background: "#ffffff"
3845
- }
3846
- ],
3847
- fonts: initialDesign?.fonts || [],
3848
- colors: initialDesign?.colors || [],
3849
- templateInputs: initialDesign?.templateInputs
3850
- };
3851
- this._activePageId = this._design.pages[0]?.id || "page-1";
3852
- this._activePanelId = null;
3853
- }
3854
- on(event, callback) {
3855
- this._listeners[event] = callback;
3856
- }
3857
- off(event) {
3858
- delete this._listeners[event];
3859
- }
3860
- emit(event, ...args) {
3861
- const callback = this._listeners[event];
3862
- if (callback) {
3863
- callback(...args);
3864
- }
3865
- }
3866
- get design() {
3867
- return this._design;
3868
- }
3869
- get width() {
3870
- return this._design.width;
3871
- }
3872
- get height() {
3873
- return this._design.height;
3874
- }
3875
- get activePage() {
3876
- return this._design.pages.find((p) => p.id === this._activePageId) || null;
3877
- }
3878
- get activePageId() {
3879
- return this._activePageId;
3880
- }
3881
- get activePanelId() {
3882
- return this._activePanelId;
3883
- }
3884
- setDesign(design) {
3885
- this._design = design;
3886
- if (design.pages.find((p) => p.id === this._activePageId)) {} else if (design.pages.length > 0) {
3887
- this._activePageId = design.pages[0].id;
3888
- }
3889
- this.emit("designChanged", design);
3890
- this.emit("activePageChanged", this._activePageId);
3891
- }
3892
- updateDesign(updates) {
3893
- this._design = { ...this._design, ...updates };
3894
- this.emit("designChanged", this._design);
3895
- }
3896
- addPage(page) {
3897
- const newPage = {
3898
- id: page?.id || `page-${Date.now()}`,
3899
- name: page?.name || `Page ${this._design.pages.length + 1}`,
3900
- elements: page?.elements || [],
3901
- background: page?.background || "#ffffff",
3902
- backgroundImageObject: page?.backgroundImageObject
3903
- };
3904
- this._design.pages.push(newPage);
3905
- this.emit("designChanged", this._design);
3906
- return newPage.id;
3907
- }
3908
- deletePages(pageIds) {
3909
- const remainingPages = this._design.pages.filter((p) => !pageIds.includes(p.id));
3910
- if (remainingPages.length === 0) {
3911
- console.warn("Cannot delete all pages. At least one page must remain.");
3912
- return;
3913
- }
3914
- if (pageIds.includes(this._activePageId)) {
3915
- this._activePageId = remainingPages[0].id;
3916
- this.emit("activePageChanged", this._activePageId);
3917
- }
3918
- this._design.pages = remainingPages;
3919
- this.emit("designChanged", this._design);
3920
- }
3921
- setActivePage(pageId) {
3922
- const page = this._design.pages.find((p) => p.id === pageId);
3923
- if (page) {
3924
- this._activePageId = pageId;
3925
- this.emit("activePageChanged", pageId);
3926
- this.emit("designChanged", this._design);
3927
- }
3928
- }
3929
- addElement(element) {
3930
- const page = this.activePage;
3931
- if (!page)
3932
- return;
3933
- const newElement = {
3934
- id: element.id || `element-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
3935
- type: element.type,
3936
- name: element.name || `${element.type} element`,
3937
- x: element.x || 0,
3938
- y: element.y || 0,
3939
- width: element.width || 100,
3940
- height: element.height || 100,
3941
- rotation: element.rotation || 0,
3942
- visible: element.visible !== false,
3943
- locked: element.locked || false,
3944
- opacity: element.opacity || 1,
3945
- ...element
3946
- };
3947
- page.elements.push(newElement);
3948
- this.emit("designChanged", this._design);
3949
- }
3950
- updateElement(elementId, updates) {
3951
- for (const page of this._design.pages) {
3952
- const elementIndex = page.elements.findIndex((e) => e.id === elementId);
3953
- if (elementIndex !== -1) {
3954
- page.elements[elementIndex] = { ...page.elements[elementIndex], ...updates };
3955
- this.emit("designChanged", this._design);
3956
- return;
3957
- }
3958
- }
3959
- }
3960
- deleteElement(elementId) {
3961
- for (const page of this._design.pages) {
3962
- const elementIndex = page.elements.findIndex((e) => e.id === elementId);
3963
- if (elementIndex !== -1) {
3964
- page.elements.splice(elementIndex, 1);
3965
- this.emit("designChanged", this._design);
3966
- return;
3967
- }
3968
- }
3969
- }
3970
- openSidePanel(panelId) {
3971
- this._activePanelId = panelId;
3972
- this.emit("activePanelChanged", panelId);
3973
- }
3974
- async loadJSON(jsonData) {
3975
- return new Promise((resolve, reject) => {
3976
- try {
3977
- Promise.resolve().then(() => exports_exportImportUtils).then(({ importFromJSONData: importFromJSONData2 }) => {
3978
- importFromJSONData2(jsonData, (loadedDesign) => {
3979
- this.setDesign(loadedDesign);
3980
- resolve();
3981
- }, (errorMessage) => {
3982
- reject(new Error(errorMessage));
3983
- }, () => {
3984
- reject(new Error("Templates requiring user inputs are not yet supported in standalone store"));
3985
- });
3986
- });
3987
- } catch (error) {
3988
- reject(error);
3989
- }
3990
- });
3991
- }
3992
- }
3993
- var createSimpleStore = (initialDesign) => {
3994
- return new SimpleCanvasStore(initialDesign);
3995
- };
3996
4038
  // src/context/CanvasStoreContext.tsx
3997
4039
  import { createContext, useContext } from "react";
3998
4040
  var CanvasStoreContext = createContext(null);
@@ -3108,11 +3108,216 @@ var TemplateInputModal = ({
3108
3108
  };
3109
3109
  var TemplateInputModal_default = TemplateInputModal;
3110
3110
 
3111
+ // src/store/simpleStore.ts
3112
+ class SimpleCanvasStore {
3113
+ _design;
3114
+ _activePageId;
3115
+ _activePanelId;
3116
+ _listeners = {};
3117
+ constructor(initialDesign) {
3118
+ this._design = {
3119
+ id: initialDesign?.id || `design-${Date.now()}`,
3120
+ name: initialDesign?.name || "Untitled Design",
3121
+ width: initialDesign?.width || 800,
3122
+ height: initialDesign?.height || 600,
3123
+ pages: initialDesign?.pages || [
3124
+ {
3125
+ id: "page-1",
3126
+ name: "Page 1",
3127
+ elements: [],
3128
+ background: "#ffffff"
3129
+ }
3130
+ ],
3131
+ fonts: initialDesign?.fonts || [],
3132
+ colors: initialDesign?.colors || [],
3133
+ templateInputs: initialDesign?.templateInputs
3134
+ };
3135
+ this._activePageId = this._design.pages[0]?.id || "page-1";
3136
+ this._activePanelId = null;
3137
+ }
3138
+ on(event, callback) {
3139
+ this._listeners[event] = callback;
3140
+ }
3141
+ off(event) {
3142
+ delete this._listeners[event];
3143
+ }
3144
+ emit(event, ...args) {
3145
+ const callback = this._listeners[event];
3146
+ if (callback) {
3147
+ callback(...args);
3148
+ }
3149
+ }
3150
+ get design() {
3151
+ return this._design;
3152
+ }
3153
+ get width() {
3154
+ return this._design.width;
3155
+ }
3156
+ get height() {
3157
+ return this._design.height;
3158
+ }
3159
+ get activePage() {
3160
+ return this._design.pages.find((p) => p.id === this._activePageId) || null;
3161
+ }
3162
+ get activePageId() {
3163
+ return this._activePageId;
3164
+ }
3165
+ get activePanelId() {
3166
+ return this._activePanelId;
3167
+ }
3168
+ setDesign(design) {
3169
+ this._design = design;
3170
+ if (design.pages.find((p) => p.id === this._activePageId)) {} else if (design.pages.length > 0) {
3171
+ this._activePageId = design.pages[0].id;
3172
+ }
3173
+ this.emit("designChanged", design);
3174
+ this.emit("activePageChanged", this._activePageId);
3175
+ }
3176
+ updateDesign(updates) {
3177
+ this._design = { ...this._design, ...updates };
3178
+ this.emit("designChanged", this._design);
3179
+ }
3180
+ addPage(page) {
3181
+ const newPage = {
3182
+ id: page?.id || `page-${Date.now()}`,
3183
+ name: page?.name || `Page ${this._design.pages.length + 1}`,
3184
+ elements: page?.elements || [],
3185
+ background: page?.background || "#ffffff",
3186
+ backgroundImageObject: page?.backgroundImageObject
3187
+ };
3188
+ this._design.pages.push(newPage);
3189
+ this.emit("designChanged", this._design);
3190
+ return newPage.id;
3191
+ }
3192
+ deletePages(pageIds) {
3193
+ const remainingPages = this._design.pages.filter((p) => !pageIds.includes(p.id));
3194
+ if (remainingPages.length === 0) {
3195
+ console.warn("Cannot delete all pages. At least one page must remain.");
3196
+ return;
3197
+ }
3198
+ if (pageIds.includes(this._activePageId)) {
3199
+ this._activePageId = remainingPages[0].id;
3200
+ this.emit("activePageChanged", this._activePageId);
3201
+ }
3202
+ this._design.pages = remainingPages;
3203
+ this.emit("designChanged", this._design);
3204
+ }
3205
+ setActivePage(pageId) {
3206
+ const page = this._design.pages.find((p) => p.id === pageId);
3207
+ if (page) {
3208
+ this._activePageId = pageId;
3209
+ this.emit("activePageChanged", pageId);
3210
+ this.emit("designChanged", this._design);
3211
+ }
3212
+ }
3213
+ addElement(element) {
3214
+ const page = this.activePage;
3215
+ if (!page)
3216
+ return;
3217
+ const newElement = {
3218
+ id: element.id || `element-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
3219
+ type: element.type,
3220
+ name: element.name || `${element.type} element`,
3221
+ x: element.x || 0,
3222
+ y: element.y || 0,
3223
+ width: element.width || 100,
3224
+ height: element.height || 100,
3225
+ rotation: element.rotation || 0,
3226
+ visible: element.visible !== false,
3227
+ locked: element.locked || false,
3228
+ opacity: element.opacity || 1,
3229
+ ...element
3230
+ };
3231
+ page.elements.push(newElement);
3232
+ this.emit("designChanged", this._design);
3233
+ }
3234
+ updateElement(elementId, updates) {
3235
+ for (const page of this._design.pages) {
3236
+ const elementIndex = page.elements.findIndex((e) => e.id === elementId);
3237
+ if (elementIndex !== -1) {
3238
+ page.elements[elementIndex] = { ...page.elements[elementIndex], ...updates };
3239
+ this.emit("designChanged", this._design);
3240
+ return;
3241
+ }
3242
+ }
3243
+ }
3244
+ deleteElement(elementId) {
3245
+ for (const page of this._design.pages) {
3246
+ const elementIndex = page.elements.findIndex((e) => e.id === elementId);
3247
+ if (elementIndex !== -1) {
3248
+ page.elements.splice(elementIndex, 1);
3249
+ this.emit("designChanged", this._design);
3250
+ return;
3251
+ }
3252
+ }
3253
+ }
3254
+ openSidePanel(panelId) {
3255
+ this._activePanelId = panelId;
3256
+ this.emit("activePanelChanged", panelId);
3257
+ }
3258
+ async toBlob(type = "png") {
3259
+ return new Promise((resolve, reject) => {
3260
+ try {
3261
+ Promise.resolve().then(() => exports_exportImportUtils).then(({ canvasToBlob: canvasToBlob2 }) => {
3262
+ const canvas = document.createElement("canvas");
3263
+ canvas.width = this._design.width;
3264
+ canvas.height = this._design.height;
3265
+ const ctx = canvas.getContext("2d");
3266
+ if (!ctx) {
3267
+ reject(new Error("Failed to get canvas context"));
3268
+ return;
3269
+ }
3270
+ ctx.fillStyle = "#ffffff";
3271
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
3272
+ const mimeType = type === "jpg" ? "image/jpeg" : "image/png";
3273
+ const quality = type === "jpg" ? 0.9 : undefined;
3274
+ canvas.toBlob((blob) => {
3275
+ if (blob) {
3276
+ resolve(blob);
3277
+ } else {
3278
+ reject(new Error("Failed to create blob"));
3279
+ }
3280
+ }, mimeType, quality);
3281
+ });
3282
+ } catch (error) {
3283
+ reject(error);
3284
+ }
3285
+ });
3286
+ }
3287
+ async loadJSON(jsonData) {
3288
+ return new Promise((resolve, reject) => {
3289
+ try {
3290
+ Promise.resolve().then(() => exports_exportImportUtils).then(({ importFromJSONData: importFromJSONData2 }) => {
3291
+ importFromJSONData2(jsonData, (loadedDesign) => {
3292
+ this.setDesign(loadedDesign);
3293
+ resolve();
3294
+ }, (errorMessage) => {
3295
+ reject(new Error(errorMessage));
3296
+ }, () => {
3297
+ reject(new Error("Templates requiring user inputs are not yet supported in standalone store"));
3298
+ });
3299
+ });
3300
+ } catch (error) {
3301
+ reject(error);
3302
+ }
3303
+ });
3304
+ }
3305
+ }
3306
+ var createSimpleStore = (initialDesign) => {
3307
+ return new SimpleCanvasStore(initialDesign);
3308
+ };
3309
+
3111
3310
  // src/CanvasEditor.tsx
3112
3311
  var CanvasEditor = ({
3113
3312
  name,
3114
- config
3313
+ config,
3314
+ store: externalStore
3115
3315
  }) => {
3316
+ const store = externalStore || createSimpleStore({
3317
+ name,
3318
+ width: 800,
3319
+ height: 600
3320
+ });
3116
3321
  const [design, setDesign] = useState3({
3117
3322
  id: Date.now().toString(),
3118
3323
  name: "Untitled Design",
@@ -3517,7 +3722,7 @@ var CanvasEditor = ({
3517
3722
  id: "elements",
3518
3723
  title: "Elements",
3519
3724
  component: ElementPanel_default,
3520
- props: { onAddShape: addShape }
3725
+ props: { onAddShape: addShape, store }
3521
3726
  },
3522
3727
  {
3523
3728
  id: "text",
@@ -3527,7 +3732,8 @@ var CanvasEditor = ({
3527
3732
  selectedElement,
3528
3733
  updateElement,
3529
3734
  setTool,
3530
- onAddText: addText
3735
+ onAddText: addText,
3736
+ store
3531
3737
  }
3532
3738
  },
3533
3739
  {
@@ -3543,7 +3749,8 @@ var CanvasEditor = ({
3543
3749
  setUnsplashMode("element");
3544
3750
  },
3545
3751
  canvasWidth: design.width,
3546
- canvasHeight: design.height
3752
+ canvasHeight: design.height,
3753
+ store
3547
3754
  }
3548
3755
  },
3549
3756
  {
@@ -3560,7 +3767,8 @@ var CanvasEditor = ({
3560
3767
  setShowUnsplash(true);
3561
3768
  setUnsplashMode("background");
3562
3769
  },
3563
- config
3770
+ config,
3771
+ store
3564
3772
  }
3565
3773
  },
3566
3774
  {
@@ -3574,7 +3782,8 @@ var CanvasEditor = ({
3574
3782
  onSetUnsplashBackground: () => {
3575
3783
  setShowUnsplash(true);
3576
3784
  setUnsplashMode("background");
3577
- }
3785
+ },
3786
+ store
3578
3787
  }
3579
3788
  },
3580
3789
  ...config?.variables ? [
@@ -3585,7 +3794,8 @@ var CanvasEditor = ({
3585
3794
  props: {
3586
3795
  config,
3587
3796
  design,
3588
- setDesign
3797
+ setDesign,
3798
+ store
3589
3799
  }
3590
3800
  }
3591
3801
  ] : [],
@@ -3604,7 +3814,8 @@ var CanvasEditor = ({
3604
3814
  exportToJPG(stageRef.current, design);
3605
3815
  } : undefined,
3606
3816
  onExportToJSON: config.export?.json ? () => exportToJSON(design) : undefined,
3607
- onImportJSON: () => jsonInputRef.current?.click()
3817
+ onImportJSON: () => jsonInputRef.current?.click(),
3818
+ store
3608
3819
  }
3609
3820
  }
3610
3821
  ] : []
@@ -3824,175 +4035,6 @@ var CanvasEditor = ({
3824
4035
  }, "Enter a search term to find images")))));
3825
4036
  };
3826
4037
  var CanvasEditor_default = CanvasEditor;
3827
- // src/store/simpleStore.ts
3828
- class SimpleCanvasStore {
3829
- _design;
3830
- _activePageId;
3831
- _activePanelId;
3832
- _listeners = {};
3833
- constructor(initialDesign) {
3834
- this._design = {
3835
- id: initialDesign?.id || `design-${Date.now()}`,
3836
- name: initialDesign?.name || "Untitled Design",
3837
- width: initialDesign?.width || 800,
3838
- height: initialDesign?.height || 600,
3839
- pages: initialDesign?.pages || [
3840
- {
3841
- id: "page-1",
3842
- name: "Page 1",
3843
- elements: [],
3844
- background: "#ffffff"
3845
- }
3846
- ],
3847
- fonts: initialDesign?.fonts || [],
3848
- colors: initialDesign?.colors || [],
3849
- templateInputs: initialDesign?.templateInputs
3850
- };
3851
- this._activePageId = this._design.pages[0]?.id || "page-1";
3852
- this._activePanelId = null;
3853
- }
3854
- on(event, callback) {
3855
- this._listeners[event] = callback;
3856
- }
3857
- off(event) {
3858
- delete this._listeners[event];
3859
- }
3860
- emit(event, ...args) {
3861
- const callback = this._listeners[event];
3862
- if (callback) {
3863
- callback(...args);
3864
- }
3865
- }
3866
- get design() {
3867
- return this._design;
3868
- }
3869
- get width() {
3870
- return this._design.width;
3871
- }
3872
- get height() {
3873
- return this._design.height;
3874
- }
3875
- get activePage() {
3876
- return this._design.pages.find((p) => p.id === this._activePageId) || null;
3877
- }
3878
- get activePageId() {
3879
- return this._activePageId;
3880
- }
3881
- get activePanelId() {
3882
- return this._activePanelId;
3883
- }
3884
- setDesign(design) {
3885
- this._design = design;
3886
- if (design.pages.find((p) => p.id === this._activePageId)) {} else if (design.pages.length > 0) {
3887
- this._activePageId = design.pages[0].id;
3888
- }
3889
- this.emit("designChanged", design);
3890
- this.emit("activePageChanged", this._activePageId);
3891
- }
3892
- updateDesign(updates) {
3893
- this._design = { ...this._design, ...updates };
3894
- this.emit("designChanged", this._design);
3895
- }
3896
- addPage(page) {
3897
- const newPage = {
3898
- id: page?.id || `page-${Date.now()}`,
3899
- name: page?.name || `Page ${this._design.pages.length + 1}`,
3900
- elements: page?.elements || [],
3901
- background: page?.background || "#ffffff",
3902
- backgroundImageObject: page?.backgroundImageObject
3903
- };
3904
- this._design.pages.push(newPage);
3905
- this.emit("designChanged", this._design);
3906
- return newPage.id;
3907
- }
3908
- deletePages(pageIds) {
3909
- const remainingPages = this._design.pages.filter((p) => !pageIds.includes(p.id));
3910
- if (remainingPages.length === 0) {
3911
- console.warn("Cannot delete all pages. At least one page must remain.");
3912
- return;
3913
- }
3914
- if (pageIds.includes(this._activePageId)) {
3915
- this._activePageId = remainingPages[0].id;
3916
- this.emit("activePageChanged", this._activePageId);
3917
- }
3918
- this._design.pages = remainingPages;
3919
- this.emit("designChanged", this._design);
3920
- }
3921
- setActivePage(pageId) {
3922
- const page = this._design.pages.find((p) => p.id === pageId);
3923
- if (page) {
3924
- this._activePageId = pageId;
3925
- this.emit("activePageChanged", pageId);
3926
- this.emit("designChanged", this._design);
3927
- }
3928
- }
3929
- addElement(element) {
3930
- const page = this.activePage;
3931
- if (!page)
3932
- return;
3933
- const newElement = {
3934
- id: element.id || `element-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
3935
- type: element.type,
3936
- name: element.name || `${element.type} element`,
3937
- x: element.x || 0,
3938
- y: element.y || 0,
3939
- width: element.width || 100,
3940
- height: element.height || 100,
3941
- rotation: element.rotation || 0,
3942
- visible: element.visible !== false,
3943
- locked: element.locked || false,
3944
- opacity: element.opacity || 1,
3945
- ...element
3946
- };
3947
- page.elements.push(newElement);
3948
- this.emit("designChanged", this._design);
3949
- }
3950
- updateElement(elementId, updates) {
3951
- for (const page of this._design.pages) {
3952
- const elementIndex = page.elements.findIndex((e) => e.id === elementId);
3953
- if (elementIndex !== -1) {
3954
- page.elements[elementIndex] = { ...page.elements[elementIndex], ...updates };
3955
- this.emit("designChanged", this._design);
3956
- return;
3957
- }
3958
- }
3959
- }
3960
- deleteElement(elementId) {
3961
- for (const page of this._design.pages) {
3962
- const elementIndex = page.elements.findIndex((e) => e.id === elementId);
3963
- if (elementIndex !== -1) {
3964
- page.elements.splice(elementIndex, 1);
3965
- this.emit("designChanged", this._design);
3966
- return;
3967
- }
3968
- }
3969
- }
3970
- openSidePanel(panelId) {
3971
- this._activePanelId = panelId;
3972
- this.emit("activePanelChanged", panelId);
3973
- }
3974
- async loadJSON(jsonData) {
3975
- return new Promise((resolve, reject) => {
3976
- try {
3977
- Promise.resolve().then(() => exports_exportImportUtils).then(({ importFromJSONData: importFromJSONData2 }) => {
3978
- importFromJSONData2(jsonData, (loadedDesign) => {
3979
- this.setDesign(loadedDesign);
3980
- resolve();
3981
- }, (errorMessage) => {
3982
- reject(new Error(errorMessage));
3983
- }, () => {
3984
- reject(new Error("Templates requiring user inputs are not yet supported in standalone store"));
3985
- });
3986
- });
3987
- } catch (error) {
3988
- reject(error);
3989
- }
3990
- });
3991
- }
3992
- }
3993
- var createSimpleStore = (initialDesign) => {
3994
- return new SimpleCanvasStore(initialDesign);
3995
- };
3996
4038
  // src/context/CanvasStoreContext.tsx
3997
4039
  import { createContext, useContext } from "react";
3998
4040
  var CanvasStoreContext = createContext(null);
@@ -1,8 +1,9 @@
1
1
  import React from "react";
2
- import { Config } from "./types/Config";
2
+ import { Config, CanvasStore } from "./types/Config";
3
3
  declare const CanvasEditor: React.FC<{
4
4
  name: string;
5
5
  config?: Config;
6
+ store?: CanvasStore;
6
7
  }>;
7
8
  export default CanvasEditor;
8
9
  //# sourceMappingURL=CanvasEditor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasEditor.d.ts","sourceRoot":"","sources":["../../src/CanvasEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAkFxE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA86B7D,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"CanvasEditor.d.ts","sourceRoot":"","sources":["../../src/CanvasEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAkFxE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGrD,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,CAAA;CAAE,CA27BlF,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -28,6 +28,7 @@ export declare class SimpleCanvasStore {
28
28
  updateElement(elementId: string, updates: Partial<CanvasElement>): void;
29
29
  deleteElement(elementId: string): void;
30
30
  openSidePanel(panelId: string | null): void;
31
+ toBlob(type?: 'png' | 'jpg'): Promise<Blob>;
31
32
  loadJSON(jsonData: any): Promise<void>;
32
33
  }
33
34
  export declare const createSimpleStore: (initialDesign?: Partial<CanvasDesign>) => SimpleCanvasStore;
@@ -1 +1 @@
1
- {"version":3,"file":"simpleStore.d.ts","sourceRoot":"","sources":["../../../src/store/simpleStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9C,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACtD;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,UAAU,CAAkC;gBAExC,aAAa,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC;IAyBjD,EAAE,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAI9E,GAAG,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,KAAK,EAAE,CAAC;IAI/C,OAAO,CAAC,IAAI;IAQZ,IAAI,MAAM,IAAI,YAAY,CAEzB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,UAAU,IAAI,IAAI,GAAG,IAAI,CAE5B;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,aAAa,IAAI,MAAM,GAAG,IAAI,CAEjC;IAGD,SAAS,CAAC,MAAM,EAAE,YAAY;IAa9B,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC;IAM3C,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM;IAcrC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE;IAmB7B,aAAa,CAAC,MAAM,EAAE,MAAM;IAU5B,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC;IAuB1C,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC;IAWhE,aAAa,CAAC,SAAS,EAAE,MAAM;IAY/B,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM9B,QAAQ,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;CA0B7C;AAGD,eAAO,MAAM,iBAAiB,GAAI,gBAAgB,OAAO,CAAC,YAAY,CAAC,KAAG,iBAEzE,CAAC;AAGF,MAAM,MAAM,WAAW,GAAG,iBAAiB,CAAC"}
1
+ {"version":3,"file":"simpleStore.d.ts","sourceRoot":"","sources":["../../../src/store/simpleStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9C,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACtD;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,UAAU,CAAkC;gBAExC,aAAa,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC;IAyBjD,EAAE,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAI9E,GAAG,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,KAAK,EAAE,CAAC;IAI/C,OAAO,CAAC,IAAI;IAQZ,IAAI,MAAM,IAAI,YAAY,CAEzB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,UAAU,IAAI,IAAI,GAAG,IAAI,CAE5B;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,aAAa,IAAI,MAAM,GAAG,IAAI,CAEjC;IAGD,SAAS,CAAC,MAAM,EAAE,YAAY;IAa9B,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC;IAM3C,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM;IAcrC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE;IAmB7B,aAAa,CAAC,MAAM,EAAE,MAAM;IAU5B,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC;IAuB1C,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC;IAWhE,aAAa,CAAC,SAAS,EAAE,MAAM;IAY/B,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM9B,MAAM,CAAC,IAAI,GAAE,KAAK,GAAG,KAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA2ClD,QAAQ,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;CA0B7C;AAGD,eAAO,MAAM,iBAAiB,GAAI,gBAAgB,OAAO,CAAC,YAAY,CAAC,KAAG,iBAEzE,CAAC;AAGF,MAAM,MAAM,WAAW,GAAG,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "labellife-design-tool",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "Professional canvas editor built with React, TypeScript, and Konva",
5
5
  "main": "./dist/lib/lib/index.js",
6
6
  "module": "./dist/lib/lib/index.js",