vibrant-tool 0.1.9 → 0.1.10
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/dist/lib/hooks/useKeyboardEvents.d.ts +1 -1
- package/dist/lib/services/crop-image.service.d.ts +1 -0
- package/dist/lib/utils/background-utils.d.ts +2 -1
- package/dist/lib/utils/grid-manager.d.ts +4 -0
- package/dist/modules/icons/gridicon/index.d.ts +4 -0
- package/dist/modules/toolbar/text-toolbar/index.d.ts +4 -0
- package/dist/vibrant-tool.css +19 -11
- package/dist/vibrant-tool.es.js +705 -219
- package/dist/vibrant-tool.umd.js +705 -219
- package/dist/zustand/editorStore.d.ts +3 -0
- package/package.json +1 -1
package/dist/vibrant-tool.umd.js
CHANGED
|
@@ -1124,11 +1124,25 @@
|
|
|
1124
1124
|
back: null
|
|
1125
1125
|
},
|
|
1126
1126
|
templateData: null,
|
|
1127
|
+
// Grid state
|
|
1128
|
+
showGrid: false,
|
|
1129
|
+
setShowGrid: (showGrid) => set({ showGrid }),
|
|
1130
|
+
toggleGrid: () => set((state) => ({ showGrid: !state.showGrid })),
|
|
1127
1131
|
history: [],
|
|
1128
1132
|
historyIndex: -1,
|
|
1129
1133
|
// Crop state
|
|
1130
1134
|
isCropping: false,
|
|
1131
|
-
startCropping: () =>
|
|
1135
|
+
startCropping: () => {
|
|
1136
|
+
const canvas2 = get().canvas;
|
|
1137
|
+
if (canvas2 && canvas2.isDrawingMode) {
|
|
1138
|
+
canvas2.isDrawingMode = false;
|
|
1139
|
+
canvas2.selection = true;
|
|
1140
|
+
canvas2.defaultCursor = "default";
|
|
1141
|
+
canvas2._isCurrentlyDrawing = false;
|
|
1142
|
+
canvas2.requestRenderAll();
|
|
1143
|
+
}
|
|
1144
|
+
set({ isCropping: true });
|
|
1145
|
+
},
|
|
1132
1146
|
stopCropping: () => set({ isCropping: false }),
|
|
1133
1147
|
// Canvas setter (NO history here)
|
|
1134
1148
|
setCanvas: (canvas2) => {
|
|
@@ -8443,6 +8457,7 @@
|
|
|
8443
8457
|
originX: "left",
|
|
8444
8458
|
originY: "top",
|
|
8445
8459
|
fill: overlayColor,
|
|
8460
|
+
opacity: 0.6,
|
|
8446
8461
|
strokeWidth: 0,
|
|
8447
8462
|
selectable: false,
|
|
8448
8463
|
evented: false,
|
|
@@ -8494,6 +8509,7 @@
|
|
|
8494
8509
|
originX: "left",
|
|
8495
8510
|
originY: "top",
|
|
8496
8511
|
fill: overlayColor,
|
|
8512
|
+
opacity: 0.6,
|
|
8497
8513
|
strokeWidth: 0,
|
|
8498
8514
|
selectable: false,
|
|
8499
8515
|
evented: false,
|
|
@@ -8790,6 +8806,7 @@
|
|
|
8790
8806
|
const overlayColor = canvas2.backgroundColor || "#F3F4F6";
|
|
8791
8807
|
const makeOverlay = (props) => new jr({
|
|
8792
8808
|
fill: overlayColor,
|
|
8809
|
+
opacity: 0.6,
|
|
8793
8810
|
selectable: false,
|
|
8794
8811
|
evented: false,
|
|
8795
8812
|
excludeFromExport: true,
|
|
@@ -8863,10 +8880,14 @@
|
|
|
8863
8880
|
canvas2.requestRenderAll();
|
|
8864
8881
|
}
|
|
8865
8882
|
function bringOverlaysToFront(canvas2) {
|
|
8883
|
+
if (!canvas2) return;
|
|
8884
|
+
canvas2.preserveObjectStacking = true;
|
|
8885
|
+
canvas2.controlsAboveOverlay = true;
|
|
8866
8886
|
const overlays = canvas2.getObjects().filter((o2) => o2.name?.startsWith("overlay-"));
|
|
8867
8887
|
const guidelines = canvas2.getObjects().filter((o2) => o2.name?.startsWith("guideline-"));
|
|
8868
8888
|
overlays.forEach((overlay) => canvas2.bringObjectToFront(overlay));
|
|
8869
8889
|
guidelines.forEach((g2) => canvas2.bringObjectToFront(g2));
|
|
8890
|
+
canvas2.requestRenderAll();
|
|
8870
8891
|
}
|
|
8871
8892
|
const BASE_URL = "https://www.api.vibrantprintshop.com";
|
|
8872
8893
|
const IMAGE_UPLOAD_URL = "https://upload.vibrantprint.com";
|
|
@@ -9103,12 +9124,16 @@
|
|
|
9103
9124
|
}
|
|
9104
9125
|
}
|
|
9105
9126
|
createOverlays(canvas2, workarea, currentSide);
|
|
9127
|
+
if (bgImg) {
|
|
9128
|
+
canvas2.sendObjectToBack(bgImg);
|
|
9129
|
+
}
|
|
9106
9130
|
canvas2.sendObjectToBack(workarea);
|
|
9107
9131
|
}
|
|
9108
9132
|
canvas2.getObjects().forEach((obj) => {
|
|
9109
9133
|
const isWorkarea = obj.name === "workarea";
|
|
9110
9134
|
const isOverlayOrGuide = obj.name?.startsWith("overlay-") || obj.name?.startsWith("guideline-");
|
|
9111
|
-
|
|
9135
|
+
const isBgImage = obj.name === "bg-image";
|
|
9136
|
+
if (!isWorkarea && !isOverlayOrGuide && !isBgImage) {
|
|
9112
9137
|
obj.set({
|
|
9113
9138
|
selectable: true,
|
|
9114
9139
|
evented: true,
|
|
@@ -9246,6 +9271,77 @@
|
|
|
9246
9271
|
return "";
|
|
9247
9272
|
}
|
|
9248
9273
|
}
|
|
9274
|
+
const useDrawStore = create((set) => ({
|
|
9275
|
+
drawTool: "select",
|
|
9276
|
+
strokeWidth: 5,
|
|
9277
|
+
opacity: 100,
|
|
9278
|
+
color: "#000000",
|
|
9279
|
+
setDrawTool: (tool) => set(() => {
|
|
9280
|
+
if (tool === "highlighter") {
|
|
9281
|
+
return { drawTool: tool, opacity: 50 };
|
|
9282
|
+
}
|
|
9283
|
+
if (tool === "brush") {
|
|
9284
|
+
return { drawTool: tool, opacity: 100 };
|
|
9285
|
+
}
|
|
9286
|
+
return { drawTool: tool };
|
|
9287
|
+
}),
|
|
9288
|
+
setStrokeWidth: (v2) => set({ strokeWidth: v2 }),
|
|
9289
|
+
setOpacity: (v2) => set({ opacity: v2 }),
|
|
9290
|
+
setColor: (v2) => set({ color: v2 })
|
|
9291
|
+
}));
|
|
9292
|
+
function deriveType(objects) {
|
|
9293
|
+
if (objects.length === 0) return "none";
|
|
9294
|
+
if (objects.length > 1) return "multiple";
|
|
9295
|
+
const obj = objects[0];
|
|
9296
|
+
const t2 = obj.type?.toLowerCase();
|
|
9297
|
+
if (t2 === "activeselection") return "multiple";
|
|
9298
|
+
if (t2 === "group") {
|
|
9299
|
+
if (obj.name === "qr") return "qr";
|
|
9300
|
+
if (obj.name === "barcode") return "barcode";
|
|
9301
|
+
return "group";
|
|
9302
|
+
}
|
|
9303
|
+
if (t2 === "textbox" || t2 === "i-text" || t2 === "text") return "textbox";
|
|
9304
|
+
if (t2 === "image") return "image";
|
|
9305
|
+
return t2 || "none";
|
|
9306
|
+
}
|
|
9307
|
+
const useSelectionStore = create((set) => ({
|
|
9308
|
+
type: "none",
|
|
9309
|
+
objects: [],
|
|
9310
|
+
activeColor: null,
|
|
9311
|
+
activeColorIndex: 0,
|
|
9312
|
+
setSelection: (objects) => {
|
|
9313
|
+
if (objects && objects.length > 0) {
|
|
9314
|
+
const drawState = useDrawStore.getState();
|
|
9315
|
+
if (drawState.drawTool !== "select") {
|
|
9316
|
+
drawState.setDrawTool("select");
|
|
9317
|
+
}
|
|
9318
|
+
const canvas2 = useEditorStore.getState().canvas;
|
|
9319
|
+
if (canvas2 && canvas2.isDrawingMode) {
|
|
9320
|
+
canvas2.isDrawingMode = false;
|
|
9321
|
+
canvas2.selection = true;
|
|
9322
|
+
canvas2.defaultCursor = "default";
|
|
9323
|
+
canvas2._isCurrentlyDrawing = false;
|
|
9324
|
+
canvas2.requestRenderAll();
|
|
9325
|
+
}
|
|
9326
|
+
}
|
|
9327
|
+
set({
|
|
9328
|
+
objects,
|
|
9329
|
+
type: deriveType(objects),
|
|
9330
|
+
activeColor: null,
|
|
9331
|
+
activeColorIndex: 0
|
|
9332
|
+
});
|
|
9333
|
+
},
|
|
9334
|
+
setActiveColor: (color, index = 0) => set({
|
|
9335
|
+
activeColor: color,
|
|
9336
|
+
activeColorIndex: index
|
|
9337
|
+
}),
|
|
9338
|
+
clearSelection: () => set({
|
|
9339
|
+
type: "none",
|
|
9340
|
+
objects: [],
|
|
9341
|
+
activeColor: null,
|
|
9342
|
+
activeColorIndex: 0
|
|
9343
|
+
})
|
|
9344
|
+
}));
|
|
9249
9345
|
const HISTORY_CUSTOM_PROPERTIES = [
|
|
9250
9346
|
"name",
|
|
9251
9347
|
"id",
|
|
@@ -9256,6 +9352,9 @@
|
|
|
9256
9352
|
"lockMovementY",
|
|
9257
9353
|
"rx",
|
|
9258
9354
|
"ry",
|
|
9355
|
+
"src",
|
|
9356
|
+
"crossOrigin",
|
|
9357
|
+
"__maskPath",
|
|
9259
9358
|
"__radiusOfCanvas",
|
|
9260
9359
|
"__shapeType",
|
|
9261
9360
|
"__pageSide",
|
|
@@ -9266,7 +9365,8 @@
|
|
|
9266
9365
|
"__initialZoom",
|
|
9267
9366
|
"__borderRect",
|
|
9268
9367
|
"__rotationControlSize",
|
|
9269
|
-
"__showDegree"
|
|
9368
|
+
"__showDegree",
|
|
9369
|
+
"textAlign"
|
|
9270
9370
|
];
|
|
9271
9371
|
const useHistoryStore = create((set, get) => ({
|
|
9272
9372
|
canvas: null,
|
|
@@ -9289,11 +9389,12 @@
|
|
|
9289
9389
|
setPage: (page) => set({ currentPage: page }),
|
|
9290
9390
|
saveState: () => {
|
|
9291
9391
|
const { canvas: canvas2, currentPage, pages, isRestoring } = get();
|
|
9292
|
-
|
|
9293
|
-
|
|
9392
|
+
const targetCanvas = canvas2 || useEditorStore.getState().canvas;
|
|
9393
|
+
if (!targetCanvas || isRestoring) return;
|
|
9394
|
+
const rawJson = targetCanvas.toObject(HISTORY_CUSTOM_PROPERTIES);
|
|
9294
9395
|
const cleanObjects = (rawJson.objects || []).filter((obj) => {
|
|
9295
9396
|
const name = obj.name || "";
|
|
9296
|
-
return name !== "watermark" && !name.startsWith("overlay-") && !name.startsWith("guideline-");
|
|
9397
|
+
return name !== "watermark" && !name.startsWith("overlay-") && !name.startsWith("guideline-") && name !== "canvas-grid";
|
|
9297
9398
|
});
|
|
9298
9399
|
const json = { ...rawJson, objects: cleanObjects };
|
|
9299
9400
|
const history = pages[currentPage]?.history ?? [];
|
|
@@ -9313,10 +9414,12 @@
|
|
|
9313
9414
|
},
|
|
9314
9415
|
undo: async () => {
|
|
9315
9416
|
const { canvas: canvas2, currentPage, pages, isRestoring } = get();
|
|
9316
|
-
|
|
9417
|
+
const targetCanvas = canvas2 || useEditorStore.getState().canvas;
|
|
9418
|
+
if (!targetCanvas || isRestoring) return;
|
|
9317
9419
|
const page = pages[currentPage];
|
|
9318
9420
|
if (!page || page.history.length <= 1) return;
|
|
9319
|
-
|
|
9421
|
+
targetCanvas.discardActiveObject();
|
|
9422
|
+
useSelectionStore.getState().clearSelection();
|
|
9320
9423
|
const current = page.history.at(-1);
|
|
9321
9424
|
const previous = page.history.at(-2);
|
|
9322
9425
|
set({
|
|
@@ -9330,8 +9433,8 @@
|
|
|
9330
9433
|
}
|
|
9331
9434
|
});
|
|
9332
9435
|
try {
|
|
9333
|
-
await loadPageToCanvas(
|
|
9334
|
-
|
|
9436
|
+
await loadPageToCanvas(targetCanvas, previous, currentPage);
|
|
9437
|
+
targetCanvas.requestRenderAll();
|
|
9335
9438
|
const editorStore = useEditorStore.getState();
|
|
9336
9439
|
if (editorStore.pages) {
|
|
9337
9440
|
editorStore.setPages({
|
|
@@ -9347,10 +9450,12 @@
|
|
|
9347
9450
|
},
|
|
9348
9451
|
redoAction: async () => {
|
|
9349
9452
|
const { canvas: canvas2, currentPage, pages, isRestoring } = get();
|
|
9350
|
-
|
|
9453
|
+
const targetCanvas = canvas2 || useEditorStore.getState().canvas;
|
|
9454
|
+
if (!targetCanvas || isRestoring) return;
|
|
9351
9455
|
const page = pages[currentPage];
|
|
9352
9456
|
if (!page || page.redo.length === 0) return;
|
|
9353
|
-
|
|
9457
|
+
targetCanvas.discardActiveObject();
|
|
9458
|
+
useSelectionStore.getState().clearSelection();
|
|
9354
9459
|
const next = page.redo[0];
|
|
9355
9460
|
set({
|
|
9356
9461
|
isRestoring: true,
|
|
@@ -9363,8 +9468,8 @@
|
|
|
9363
9468
|
}
|
|
9364
9469
|
});
|
|
9365
9470
|
try {
|
|
9366
|
-
await loadPageToCanvas(
|
|
9367
|
-
|
|
9471
|
+
await loadPageToCanvas(targetCanvas, next, currentPage);
|
|
9472
|
+
targetCanvas.requestRenderAll();
|
|
9368
9473
|
const editorStore = useEditorStore.getState();
|
|
9369
9474
|
if (editorStore.pages) {
|
|
9370
9475
|
editorStore.setPages({
|
|
@@ -9664,7 +9769,7 @@
|
|
|
9664
9769
|
}
|
|
9665
9770
|
function exportDesignJSON(canvas2, workarea) {
|
|
9666
9771
|
const objects = canvas2.getObjects();
|
|
9667
|
-
const children = objects.filter((obj) => obj.name !== "workarea" && !obj.name?.startsWith("overlay-")).map((obj) => {
|
|
9772
|
+
const children = objects.filter((obj) => obj.name !== "workarea" && !obj.name?.startsWith("overlay-") && !obj.name?.startsWith("guideline-") && obj.name !== "canvas-grid").map((obj) => {
|
|
9668
9773
|
const base = obj.toObject();
|
|
9669
9774
|
return {
|
|
9670
9775
|
id: obj.id || crypto.randomUUID(),
|
|
@@ -9889,6 +9994,7 @@
|
|
|
9889
9994
|
});
|
|
9890
9995
|
canvas2.add(img);
|
|
9891
9996
|
canvas2.setActiveObject(img);
|
|
9997
|
+
bringOverlaysToFront(canvas2);
|
|
9892
9998
|
canvas2.requestRenderAll();
|
|
9893
9999
|
}).catch((err) => {
|
|
9894
10000
|
console.warn("Fabric failed to load image from URL:", url, err);
|
|
@@ -9911,7 +10017,7 @@
|
|
|
9911
10017
|
canvas2.renderAll();
|
|
9912
10018
|
const originalProps = /* @__PURE__ */ new Map();
|
|
9913
10019
|
objects.forEach((obj) => {
|
|
9914
|
-
const isExcluded = obj.excludeFromExport || obj.name?.startsWith("overlay-") || obj.name?.startsWith("guide-") || obj.name?.startsWith("guideline-") || obj.name === "crop-grid";
|
|
10020
|
+
const isExcluded = obj.excludeFromExport || obj.name?.startsWith("overlay-") || obj.name?.startsWith("guide-") || obj.name?.startsWith("guideline-") || obj.name === "canvas-grid" || obj.name === "crop-grid";
|
|
9915
10021
|
if (isExcluded && obj !== targetWorkarea) {
|
|
9916
10022
|
originalProps.set(obj, {
|
|
9917
10023
|
visible: obj.visible,
|
|
@@ -102391,7 +102497,23 @@ end`);
|
|
|
102391
102497
|
const useSidePanelStore = create(
|
|
102392
102498
|
(set) => ({
|
|
102393
102499
|
activePanel: null,
|
|
102394
|
-
setActivePanel: (val) =>
|
|
102500
|
+
setActivePanel: (val) => {
|
|
102501
|
+
if (val !== "draw") {
|
|
102502
|
+
const drawState = useDrawStore.getState();
|
|
102503
|
+
if (drawState.drawTool !== "select") {
|
|
102504
|
+
drawState.setDrawTool("select");
|
|
102505
|
+
}
|
|
102506
|
+
const canvas2 = useEditorStore.getState().canvas;
|
|
102507
|
+
if (canvas2 && canvas2.isDrawingMode) {
|
|
102508
|
+
canvas2.isDrawingMode = false;
|
|
102509
|
+
canvas2.selection = true;
|
|
102510
|
+
canvas2.defaultCursor = "default";
|
|
102511
|
+
canvas2._isCurrentlyDrawing = false;
|
|
102512
|
+
canvas2.requestRenderAll();
|
|
102513
|
+
}
|
|
102514
|
+
}
|
|
102515
|
+
set({ activePanel: val });
|
|
102516
|
+
}
|
|
102395
102517
|
})
|
|
102396
102518
|
);
|
|
102397
102519
|
function Panel({ panelName }) {
|
|
@@ -102457,43 +102579,6 @@ end`);
|
|
|
102457
102579
|
] })
|
|
102458
102580
|
] });
|
|
102459
102581
|
}
|
|
102460
|
-
function deriveType(objects) {
|
|
102461
|
-
if (objects.length === 0) return "none";
|
|
102462
|
-
if (objects.length > 1) return "multiple";
|
|
102463
|
-
const obj = objects[0];
|
|
102464
|
-
const t2 = obj.type?.toLowerCase();
|
|
102465
|
-
if (t2 === "activeselection") return "multiple";
|
|
102466
|
-
if (t2 === "group") {
|
|
102467
|
-
if (obj.name === "qr") return "qr";
|
|
102468
|
-
if (obj.name === "barcode") return "barcode";
|
|
102469
|
-
return "group";
|
|
102470
|
-
}
|
|
102471
|
-
if (t2 === "textbox" || t2 === "i-text" || t2 === "text") return "textbox";
|
|
102472
|
-
if (t2 === "image") return "image";
|
|
102473
|
-
return t2 || "none";
|
|
102474
|
-
}
|
|
102475
|
-
const useSelectionStore = create((set) => ({
|
|
102476
|
-
type: "none",
|
|
102477
|
-
objects: [],
|
|
102478
|
-
activeColor: null,
|
|
102479
|
-
activeColorIndex: 0,
|
|
102480
|
-
setSelection: (objects) => set({
|
|
102481
|
-
objects,
|
|
102482
|
-
type: deriveType(objects),
|
|
102483
|
-
activeColor: null,
|
|
102484
|
-
activeColorIndex: 0
|
|
102485
|
-
}),
|
|
102486
|
-
setActiveColor: (color, index = 0) => set({
|
|
102487
|
-
activeColor: color,
|
|
102488
|
-
activeColorIndex: index
|
|
102489
|
-
}),
|
|
102490
|
-
clearSelection: () => set({
|
|
102491
|
-
type: "none",
|
|
102492
|
-
objects: [],
|
|
102493
|
-
activeColor: null,
|
|
102494
|
-
activeColorIndex: 0
|
|
102495
|
-
})
|
|
102496
|
-
}));
|
|
102497
102582
|
function TemplatesPanel() {
|
|
102498
102583
|
const { productData } = useProductStore();
|
|
102499
102584
|
const { startLoading, stopLoading, isLoading } = useLoaderStore();
|
|
@@ -102934,6 +103019,7 @@ end`);
|
|
|
102934
103019
|
svg.setCoords();
|
|
102935
103020
|
canvas2.add(svg);
|
|
102936
103021
|
canvas2.setActiveObject(svg);
|
|
103022
|
+
bringOverlaysToFront(canvas2);
|
|
102937
103023
|
useSelectionStore.getState().setSelection([svg]);
|
|
102938
103024
|
canvas2.requestRenderAll();
|
|
102939
103025
|
}
|
|
@@ -102984,6 +103070,7 @@ end`);
|
|
|
102984
103070
|
group.setCoords();
|
|
102985
103071
|
canvas2.add(group);
|
|
102986
103072
|
canvas2.setActiveObject(group);
|
|
103073
|
+
bringOverlaysToFront(canvas2);
|
|
102987
103074
|
useSelectionStore.getState().setSelection([group]);
|
|
102988
103075
|
canvas2.requestRenderAll();
|
|
102989
103076
|
return group;
|
|
@@ -103388,7 +103475,7 @@ end`);
|
|
|
103388
103475
|
if (!workarea) return;
|
|
103389
103476
|
const workareaCenter = workarea.getCenterPoint();
|
|
103390
103477
|
const workareaBounds = workarea.getBoundingRect();
|
|
103391
|
-
const maxTextWidth = Math.max(40, workareaBounds.width * 0.
|
|
103478
|
+
const maxTextWidth = Math.max(40, workareaBounds.width * 0.85);
|
|
103392
103479
|
const textWidth = Math.min(width, maxTextWidth);
|
|
103393
103480
|
const text = new Uo(textName, {
|
|
103394
103481
|
fontSize,
|
|
@@ -103401,19 +103488,26 @@ end`);
|
|
|
103401
103488
|
strokeWidth: 0,
|
|
103402
103489
|
hasRotatingPoint: true,
|
|
103403
103490
|
centerTransform: true,
|
|
103404
|
-
padding:
|
|
103491
|
+
padding: 0,
|
|
103405
103492
|
strokeUniform: true,
|
|
103406
103493
|
paintFirst: "stroke",
|
|
103407
103494
|
objectCaching: false
|
|
103408
103495
|
// Ensure maximum sharpness
|
|
103409
103496
|
});
|
|
103497
|
+
const measuredWidth = Math.ceil(text.calcTextWidth());
|
|
103498
|
+
if (measuredWidth > 0 && !textName.includes("\n")) {
|
|
103499
|
+
text.set({ width: Math.min(Math.max(measuredWidth + 4, 20), maxTextWidth) });
|
|
103500
|
+
text.initDimensions();
|
|
103501
|
+
}
|
|
103410
103502
|
canvas2.add(text);
|
|
103411
103503
|
text.set({
|
|
103412
103504
|
left: workareaCenter.x - text.getScaledWidth() / 2,
|
|
103413
103505
|
top: workareaCenter.y - text.getScaledHeight() / 2
|
|
103414
103506
|
});
|
|
103415
103507
|
canvas2.setActiveObject(text);
|
|
103508
|
+
bringOverlaysToFront(canvas2);
|
|
103416
103509
|
canvas2.requestRenderAll();
|
|
103510
|
+
useHistoryStore.getState().saveState();
|
|
103417
103511
|
}
|
|
103418
103512
|
async function addTextTemplate(id) {
|
|
103419
103513
|
try {
|
|
@@ -103445,6 +103539,7 @@ end`);
|
|
|
103445
103539
|
canvas2.add(...fabricObjects);
|
|
103446
103540
|
canvas2.renderOnAddRemove = true;
|
|
103447
103541
|
canvas2.requestRenderAll();
|
|
103542
|
+
useHistoryStore.getState().saveState();
|
|
103448
103543
|
} catch (err) {
|
|
103449
103544
|
console.error("Failed to add text template:", err);
|
|
103450
103545
|
}
|
|
@@ -104212,11 +104307,20 @@ end`);
|
|
|
104212
104307
|
}) : !isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-full py-8 text-center text-xs text-gray-500", children: "No images found" }) : null }) })
|
|
104213
104308
|
] });
|
|
104214
104309
|
}
|
|
104310
|
+
let bgSaveTimer = null;
|
|
104311
|
+
function flushBackgroundSave() {
|
|
104312
|
+
if (bgSaveTimer) {
|
|
104313
|
+
clearTimeout(bgSaveTimer);
|
|
104314
|
+
bgSaveTimer = null;
|
|
104315
|
+
useHistoryStore.getState().saveState();
|
|
104316
|
+
}
|
|
104317
|
+
}
|
|
104215
104318
|
async function addBackgroundImage(url) {
|
|
104216
104319
|
const canvas2 = useEditorStore.getState().canvas;
|
|
104217
104320
|
if (!canvas2) return;
|
|
104218
104321
|
const workarea = canvas2.getObjects().find((o2) => o2.name === "workarea");
|
|
104219
104322
|
if (!workarea) return;
|
|
104323
|
+
flushBackgroundSave();
|
|
104220
104324
|
workarea.set("fill", "#ffffff");
|
|
104221
104325
|
canvas2.getObjects("image").forEach((o2) => {
|
|
104222
104326
|
if (o2.name === "bg-image") canvas2.remove(o2);
|
|
@@ -104228,7 +104332,16 @@ end`);
|
|
|
104228
104332
|
const activeSide = workarea.__pageSide || useHistoryStore.getState().currentPage || "front";
|
|
104229
104333
|
const baseRx = (workarea.rx || workarea.__radiusOfCanvas || 0) * (workarea.scaleX || 1);
|
|
104230
104334
|
const baseRy = (workarea.ry || workarea.__radiusOfCanvas || 0) * (workarea.scaleY || 1);
|
|
104231
|
-
|
|
104335
|
+
let finalUrl = url;
|
|
104336
|
+
try {
|
|
104337
|
+
const b64 = await getBase64ImageFromURL(url);
|
|
104338
|
+
if (b64 && (b64.startsWith("data:image/png") || b64.startsWith("data:image/jpeg"))) {
|
|
104339
|
+
finalUrl = b64;
|
|
104340
|
+
}
|
|
104341
|
+
} catch {
|
|
104342
|
+
}
|
|
104343
|
+
try {
|
|
104344
|
+
const img = await oa.fromURL(finalUrl, { crossOrigin: "anonymous" });
|
|
104232
104345
|
const imgW = img.width || 1;
|
|
104233
104346
|
const imgH = img.height || 1;
|
|
104234
104347
|
const scale2 = Math.max(waW / imgW, waH / imgH);
|
|
@@ -104264,12 +104377,14 @@ end`);
|
|
|
104264
104377
|
canvas2.add(img);
|
|
104265
104378
|
canvas2.sendObjectToBack(img);
|
|
104266
104379
|
canvas2.sendObjectToBack(workarea);
|
|
104380
|
+
bringOverlaysToFront(canvas2);
|
|
104267
104381
|
canvas2.requestRenderAll();
|
|
104268
|
-
|
|
104382
|
+
useHistoryStore.getState().saveState();
|
|
104383
|
+
} catch (err) {
|
|
104269
104384
|
console.warn("Fabric failed to load background image:", url, err);
|
|
104270
|
-
}
|
|
104385
|
+
}
|
|
104271
104386
|
}
|
|
104272
|
-
async function addBackgroundColor(color) {
|
|
104387
|
+
async function addBackgroundColor(color, immediate = false) {
|
|
104273
104388
|
const canvas2 = useEditorStore.getState().canvas;
|
|
104274
104389
|
if (!canvas2) return;
|
|
104275
104390
|
const workarea = canvas2.getObjects().find((o2) => o2.name === "workarea");
|
|
@@ -104278,7 +104393,20 @@ end`);
|
|
|
104278
104393
|
if (o2.name === "bg-image") canvas2.remove(o2);
|
|
104279
104394
|
});
|
|
104280
104395
|
workarea.set("fill", color);
|
|
104396
|
+
bringOverlaysToFront(canvas2);
|
|
104281
104397
|
canvas2.requestRenderAll();
|
|
104398
|
+
if (bgSaveTimer) {
|
|
104399
|
+
clearTimeout(bgSaveTimer);
|
|
104400
|
+
bgSaveTimer = null;
|
|
104401
|
+
}
|
|
104402
|
+
if (immediate) {
|
|
104403
|
+
useHistoryStore.getState().saveState();
|
|
104404
|
+
} else {
|
|
104405
|
+
bgSaveTimer = setTimeout(() => {
|
|
104406
|
+
useHistoryStore.getState().saveState();
|
|
104407
|
+
bgSaveTimer = null;
|
|
104408
|
+
}, 120);
|
|
104409
|
+
}
|
|
104282
104410
|
}
|
|
104283
104411
|
function normalizeHexColor(c2) {
|
|
104284
104412
|
if (!c2 || typeof c2 !== "string" || c2 === "none" || c2 === "transparent" || c2.trim() === "") return null;
|
|
@@ -106038,11 +106166,11 @@ end`);
|
|
|
106038
106166
|
const [hasMore, setHasMore] = React.useState(true);
|
|
106039
106167
|
const [page, setPage] = React.useState(1);
|
|
106040
106168
|
const scrollRef = React.useRef(null);
|
|
106041
|
-
const handleApplyBackground = (type, value) => {
|
|
106169
|
+
const handleApplyBackground = async (type, value, immediate = false) => {
|
|
106042
106170
|
if (type === "color") {
|
|
106043
|
-
addBackgroundColor(value);
|
|
106171
|
+
await addBackgroundColor(value, immediate);
|
|
106044
106172
|
} else {
|
|
106045
|
-
addBackgroundImage(value);
|
|
106173
|
+
await addBackgroundImage(value);
|
|
106046
106174
|
}
|
|
106047
106175
|
if (window.innerWidth < 768) {
|
|
106048
106176
|
setActivePanel(null);
|
|
@@ -106095,7 +106223,7 @@ end`);
|
|
|
106095
106223
|
CMYKColorPicker,
|
|
106096
106224
|
{
|
|
106097
106225
|
value: "#ffffff",
|
|
106098
|
-
onChange: (hex) => handleApplyBackground("color", hex)
|
|
106226
|
+
onChange: (hex) => handleApplyBackground("color", hex, false)
|
|
106099
106227
|
}
|
|
106100
106228
|
),
|
|
106101
106229
|
CMYK_SAFE_COLORS.map(({ hex, label }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -106103,7 +106231,7 @@ end`);
|
|
|
106103
106231
|
{
|
|
106104
106232
|
className: "w-8 h-8 rounded border border-neutral-600 cursor-pointer transition-transform hover:scale-110",
|
|
106105
106233
|
style: { backgroundColor: hex },
|
|
106106
|
-
onClick: () => handleApplyBackground("color", hex),
|
|
106234
|
+
onClick: () => handleApplyBackground("color", hex, true),
|
|
106107
106235
|
title: label
|
|
106108
106236
|
},
|
|
106109
106237
|
hex
|
|
@@ -106119,7 +106247,7 @@ end`);
|
|
|
106119
106247
|
const image = await ShapeService.convertImages(item.largeImage);
|
|
106120
106248
|
const imageUrl = image?.success ? image?.url : null;
|
|
106121
106249
|
if (!imageUrl) return;
|
|
106122
|
-
handleApplyBackground("image", imageUrl);
|
|
106250
|
+
await handleApplyBackground("image", imageUrl);
|
|
106123
106251
|
if (window.innerWidth < 768) {
|
|
106124
106252
|
useSidePanelStore.getState().setActivePanel(null);
|
|
106125
106253
|
}
|
|
@@ -106215,24 +106343,6 @@ end`);
|
|
|
106215
106343
|
)) })
|
|
106216
106344
|
] });
|
|
106217
106345
|
}
|
|
106218
|
-
const useDrawStore = create((set) => ({
|
|
106219
|
-
drawTool: "select",
|
|
106220
|
-
strokeWidth: 5,
|
|
106221
|
-
opacity: 100,
|
|
106222
|
-
color: "#000000",
|
|
106223
|
-
setDrawTool: (tool) => set(() => {
|
|
106224
|
-
if (tool === "highlighter") {
|
|
106225
|
-
return { drawTool: tool, opacity: 50 };
|
|
106226
|
-
}
|
|
106227
|
-
if (tool === "brush") {
|
|
106228
|
-
return { drawTool: tool, opacity: 100 };
|
|
106229
|
-
}
|
|
106230
|
-
return { drawTool: tool };
|
|
106231
|
-
}),
|
|
106232
|
-
setStrokeWidth: (v2) => set({ strokeWidth: v2 }),
|
|
106233
|
-
setOpacity: (v2) => set({ opacity: v2 }),
|
|
106234
|
-
setColor: (v2) => set({ color: v2 })
|
|
106235
|
-
}));
|
|
106236
106346
|
function DrawPanel() {
|
|
106237
106347
|
const {
|
|
106238
106348
|
drawTool,
|
|
@@ -106247,7 +106357,7 @@ end`);
|
|
|
106247
106357
|
const isDisabled = drawTool === "select";
|
|
106248
106358
|
const TOOLS = [
|
|
106249
106359
|
{ key: "select", label: "✦ Selection" },
|
|
106250
|
-
{ key: "brush", label: "
|
|
106360
|
+
{ key: "brush", label: "✏️ Brush" },
|
|
106251
106361
|
{ key: "highlighter", label: "✎ Highlighter" }
|
|
106252
106362
|
];
|
|
106253
106363
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-4 select-none", children: [
|
|
@@ -111038,8 +111148,8 @@ END:VCARD`;
|
|
|
111038
111148
|
const objWidth = obj.width ?? 1;
|
|
111039
111149
|
const objHeight = obj.height ?? 1;
|
|
111040
111150
|
const pathDims = clipPath.getBoundingRect();
|
|
111041
|
-
const scaleX = objWidth / pathDims.width;
|
|
111042
|
-
const scaleY = objHeight / pathDims.height;
|
|
111151
|
+
const scaleX = objWidth / (clipPath.width || pathDims.width);
|
|
111152
|
+
const scaleY = objHeight / (clipPath.height || pathDims.height);
|
|
111043
111153
|
clipPath.set({
|
|
111044
111154
|
scaleX,
|
|
111045
111155
|
scaleY,
|
|
@@ -111048,6 +111158,8 @@ END:VCARD`;
|
|
|
111048
111158
|
angle: 0
|
|
111049
111159
|
// Should not inherit angle since the parent handles rotation
|
|
111050
111160
|
});
|
|
111161
|
+
clipPath.__maskPath = svgPath;
|
|
111162
|
+
obj.__maskPath = svgPath;
|
|
111051
111163
|
obj.set({ clipPath });
|
|
111052
111164
|
obj.setCoords();
|
|
111053
111165
|
canvas2.requestRenderAll();
|
|
@@ -156998,7 +157110,7 @@ ${elements2.join("\n")}
|
|
|
156998
157110
|
id: item.id,
|
|
156999
157111
|
item,
|
|
157000
157112
|
isActive: activePanel === item.id,
|
|
157001
|
-
onClick: () => setActivePanel(item.id)
|
|
157113
|
+
onClick: () => setActivePanel(activePanel === item.id ? null : item.id)
|
|
157002
157114
|
},
|
|
157003
157115
|
item.id
|
|
157004
157116
|
)
|
|
@@ -157013,7 +157125,7 @@ ${elements2.join("\n")}
|
|
|
157013
157125
|
item,
|
|
157014
157126
|
variant: "mobile",
|
|
157015
157127
|
isActive: activePanel === item.id,
|
|
157016
|
-
onClick: () => setActivePanel(item.id)
|
|
157128
|
+
onClick: () => setActivePanel(activePanel === item.id ? null : item.id)
|
|
157017
157129
|
},
|
|
157018
157130
|
item.id
|
|
157019
157131
|
)
|
|
@@ -157139,20 +157251,48 @@ ${elements2.join("\n")}
|
|
|
157139
157251
|
}
|
|
157140
157252
|
);
|
|
157141
157253
|
}
|
|
157142
|
-
function
|
|
157254
|
+
function TextAlignGroup({
|
|
157143
157255
|
value,
|
|
157144
157256
|
onChange
|
|
157145
157257
|
}) {
|
|
157146
|
-
const
|
|
157258
|
+
const current = value === "center" || value === "right" ? value : "left";
|
|
157147
157259
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
157148
|
-
"
|
|
157260
|
+
"div",
|
|
157149
157261
|
{
|
|
157150
|
-
|
|
157151
|
-
|
|
157262
|
+
className: "flex items-center bg-neutral-800 rounded p-0.5 gap-0.5 border border-neutral-700",
|
|
157263
|
+
role: "group",
|
|
157264
|
+
"aria-label": "Text alignment",
|
|
157152
157265
|
children: [
|
|
157153
|
-
|
|
157154
|
-
|
|
157155
|
-
|
|
157266
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
157267
|
+
"button",
|
|
157268
|
+
{
|
|
157269
|
+
type: "button",
|
|
157270
|
+
title: "Align Left",
|
|
157271
|
+
onClick: () => onChange("left"),
|
|
157272
|
+
className: `p-1 rounded transition-colors ${current === "left" ? "bg-neutral-600 text-white shadow-sm" : "text-neutral-400 hover:text-white hover:bg-neutral-700"}`,
|
|
157273
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(AlignLeftIcon$1, {})
|
|
157274
|
+
}
|
|
157275
|
+
),
|
|
157276
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
157277
|
+
"button",
|
|
157278
|
+
{
|
|
157279
|
+
type: "button",
|
|
157280
|
+
title: "Align Center",
|
|
157281
|
+
onClick: () => onChange("center"),
|
|
157282
|
+
className: `p-1 rounded transition-colors ${current === "center" ? "bg-neutral-600 text-white shadow-sm" : "text-neutral-400 hover:text-white hover:bg-neutral-700"}`,
|
|
157283
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(AlignCenterIcon$1, {})
|
|
157284
|
+
}
|
|
157285
|
+
),
|
|
157286
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
157287
|
+
"button",
|
|
157288
|
+
{
|
|
157289
|
+
type: "button",
|
|
157290
|
+
title: "Align Right",
|
|
157291
|
+
onClick: () => onChange("right"),
|
|
157292
|
+
className: `p-1 rounded transition-colors ${current === "right" ? "bg-neutral-600 text-white shadow-sm" : "text-neutral-400 hover:text-white hover:bg-neutral-700"}`,
|
|
157293
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(AlignRightIcon$1, {})
|
|
157294
|
+
}
|
|
157295
|
+
)
|
|
157156
157296
|
]
|
|
157157
157297
|
}
|
|
157158
157298
|
);
|
|
@@ -157205,15 +157345,29 @@ ${elements2.join("\n")}
|
|
|
157205
157345
|
}, [type, objects]);
|
|
157206
157346
|
React.useEffect(() => {
|
|
157207
157347
|
if (!text) return;
|
|
157208
|
-
|
|
157209
|
-
|
|
157210
|
-
|
|
157211
|
-
|
|
157212
|
-
|
|
157213
|
-
|
|
157214
|
-
|
|
157215
|
-
|
|
157216
|
-
|
|
157348
|
+
const syncProps = () => {
|
|
157349
|
+
setFontSize(text.fontSize ?? 18);
|
|
157350
|
+
setLineHeight2((text.lineHeight ?? 1) * 100);
|
|
157351
|
+
setCharSpacing(text.charSpacing ?? 0);
|
|
157352
|
+
setAlign(text.textAlign ?? "left");
|
|
157353
|
+
const dashArray = text.strokeDashArray;
|
|
157354
|
+
const currentStrokeStyle = Array.isArray(dashArray) && dashArray.length === 2 && dashArray[0] === 2 && dashArray[1] === 4 ? "Dotted" : Array.isArray(dashArray) && dashArray.length === 2 && dashArray[0] === 10 && dashArray[1] === 5 ? "Dashed" : "Line";
|
|
157355
|
+
setStrokeColor(typeof text.stroke === "string" && text.stroke ? text.stroke : "#000000");
|
|
157356
|
+
setStrokeSize(Math.max(0, Number(text.strokeWidth ?? 0)));
|
|
157357
|
+
setStrokeStyle(currentStrokeStyle);
|
|
157358
|
+
};
|
|
157359
|
+
syncProps();
|
|
157360
|
+
const canvas2 = text.canvas;
|
|
157361
|
+
if (canvas2) {
|
|
157362
|
+
canvas2.on("object:modified", syncProps);
|
|
157363
|
+
canvas2.on("selection:updated", syncProps);
|
|
157364
|
+
}
|
|
157365
|
+
return () => {
|
|
157366
|
+
if (canvas2) {
|
|
157367
|
+
canvas2.off("object:modified", syncProps);
|
|
157368
|
+
canvas2.off("selection:updated", syncProps);
|
|
157369
|
+
}
|
|
157370
|
+
};
|
|
157217
157371
|
}, [text]);
|
|
157218
157372
|
const updateText = React.useCallback(
|
|
157219
157373
|
(props) => {
|
|
@@ -157221,6 +157375,11 @@ ${elements2.join("\n")}
|
|
|
157221
157375
|
const canvas2 = text.canvas;
|
|
157222
157376
|
if (!canvas2) return;
|
|
157223
157377
|
text.set(props);
|
|
157378
|
+
if (props.textAlign) {
|
|
157379
|
+
text.dirty = true;
|
|
157380
|
+
text.initDimensions?.();
|
|
157381
|
+
text.setCoords();
|
|
157382
|
+
}
|
|
157224
157383
|
canvas2.requestRenderAll();
|
|
157225
157384
|
useHistoryStore.getState().saveState();
|
|
157226
157385
|
},
|
|
@@ -157277,7 +157436,7 @@ ${elements2.join("\n")}
|
|
|
157277
157436
|
}
|
|
157278
157437
|
),
|
|
157279
157438
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
157280
|
-
|
|
157439
|
+
TextAlignGroup,
|
|
157281
157440
|
{
|
|
157282
157441
|
value: align,
|
|
157283
157442
|
onChange: (v2) => {
|
|
@@ -157533,6 +157692,7 @@ ${elements2.join("\n")}
|
|
|
157533
157692
|
darkOverlay = null;
|
|
157534
157693
|
focusedImage = null;
|
|
157535
157694
|
cropZone = null;
|
|
157695
|
+
maskPath = null;
|
|
157536
157696
|
onEnd = null;
|
|
157537
157697
|
init(canvas2) {
|
|
157538
157698
|
this.canvas = canvas2;
|
|
@@ -157544,6 +157704,7 @@ ${elements2.join("\n")}
|
|
|
157544
157704
|
this.cleanup();
|
|
157545
157705
|
this.targetImage = image;
|
|
157546
157706
|
this.onEnd = onEnd || null;
|
|
157707
|
+
this.maskPath = image.__maskPath || image.clipPath?.__maskPath || null;
|
|
157547
157708
|
const canvas2 = this.canvas;
|
|
157548
157709
|
canvas2.renderOnAddRemove = false;
|
|
157549
157710
|
canvas2.discardActiveObject();
|
|
@@ -157560,7 +157721,8 @@ ${elements2.join("\n")}
|
|
|
157560
157721
|
width: naturalWidth,
|
|
157561
157722
|
height: naturalHeight,
|
|
157562
157723
|
selectable: false,
|
|
157563
|
-
evented: false
|
|
157724
|
+
evented: false,
|
|
157725
|
+
clipPath: void 0
|
|
157564
157726
|
});
|
|
157565
157727
|
const cropX = image.cropX || 0;
|
|
157566
157728
|
const cropY = image.cropY || 0;
|
|
@@ -157691,14 +157853,31 @@ ${elements2.join("\n")}
|
|
|
157691
157853
|
const local = Mn.transformPoint(center, inv);
|
|
157692
157854
|
const localW = zone.getScaledWidth() / Math.abs(img.scaleX);
|
|
157693
157855
|
const localH = zone.getScaledHeight() / Math.abs(img.scaleY);
|
|
157694
|
-
|
|
157695
|
-
|
|
157696
|
-
|
|
157697
|
-
|
|
157698
|
-
|
|
157699
|
-
|
|
157700
|
-
|
|
157701
|
-
|
|
157856
|
+
if (this.maskPath) {
|
|
157857
|
+
const maskClip = new no(this.maskPath, {
|
|
157858
|
+
originX: "center",
|
|
157859
|
+
originY: "center"
|
|
157860
|
+
});
|
|
157861
|
+
const pathW = maskClip.width || 1;
|
|
157862
|
+
const pathH = maskClip.height || 1;
|
|
157863
|
+
maskClip.set({
|
|
157864
|
+
left: local.x,
|
|
157865
|
+
top: local.y,
|
|
157866
|
+
scaleX: localW / pathW,
|
|
157867
|
+
scaleY: localH / pathH,
|
|
157868
|
+
angle: 0
|
|
157869
|
+
});
|
|
157870
|
+
img.clipPath = maskClip;
|
|
157871
|
+
} else {
|
|
157872
|
+
img.clipPath = new jr({
|
|
157873
|
+
left: local.x,
|
|
157874
|
+
top: local.y,
|
|
157875
|
+
width: localW,
|
|
157876
|
+
height: localH,
|
|
157877
|
+
originX: "center",
|
|
157878
|
+
originY: "center"
|
|
157879
|
+
});
|
|
157880
|
+
}
|
|
157702
157881
|
img.dirty = true;
|
|
157703
157882
|
}
|
|
157704
157883
|
/* ======================= APPLY CROP ======================= */
|
|
@@ -157723,11 +157902,13 @@ ${elements2.join("\n")}
|
|
|
157723
157902
|
const minY = Math.min(...ys2);
|
|
157724
157903
|
const maxX = Math.max(...xs2);
|
|
157725
157904
|
const maxY = Math.max(...ys2);
|
|
157905
|
+
const newW = Math.min(full.width, maxX - minX);
|
|
157906
|
+
const newH = Math.min(full.height, maxY - minY);
|
|
157726
157907
|
img.set({
|
|
157727
157908
|
cropX: Math.max(0, minX),
|
|
157728
157909
|
cropY: Math.max(0, minY),
|
|
157729
|
-
width:
|
|
157730
|
-
height:
|
|
157910
|
+
width: newW,
|
|
157911
|
+
height: newH,
|
|
157731
157912
|
scaleX: full.scaleX,
|
|
157732
157913
|
scaleY: full.scaleY,
|
|
157733
157914
|
angle: full.angle,
|
|
@@ -157739,6 +157920,35 @@ ${elements2.join("\n")}
|
|
|
157739
157920
|
selectable: true,
|
|
157740
157921
|
evented: true
|
|
157741
157922
|
});
|
|
157923
|
+
if (this.maskPath) {
|
|
157924
|
+
const newClip = new no(this.maskPath, {
|
|
157925
|
+
originX: "center",
|
|
157926
|
+
originY: "center"
|
|
157927
|
+
});
|
|
157928
|
+
const pathW = newClip.width || 1;
|
|
157929
|
+
const pathH = newClip.height || 1;
|
|
157930
|
+
newClip.set({
|
|
157931
|
+
scaleX: newW / pathW,
|
|
157932
|
+
scaleY: newH / pathH,
|
|
157933
|
+
left: 0,
|
|
157934
|
+
top: 0,
|
|
157935
|
+
angle: 0
|
|
157936
|
+
});
|
|
157937
|
+
newClip.__maskPath = this.maskPath;
|
|
157938
|
+
img.__maskPath = this.maskPath;
|
|
157939
|
+
img.set({ clipPath: newClip });
|
|
157940
|
+
} else if (img.clipPath && img.clipPath.type === "path") {
|
|
157941
|
+
const pW = img.clipPath.width || 1;
|
|
157942
|
+
const pH = img.clipPath.height || 1;
|
|
157943
|
+
img.clipPath.set({
|
|
157944
|
+
scaleX: newW / pW,
|
|
157945
|
+
scaleY: newH / pH,
|
|
157946
|
+
left: 0,
|
|
157947
|
+
top: 0,
|
|
157948
|
+
originX: "center",
|
|
157949
|
+
originY: "center"
|
|
157950
|
+
});
|
|
157951
|
+
}
|
|
157742
157952
|
img.setPositionByOrigin(
|
|
157743
157953
|
new ot(zone.left, zone.top),
|
|
157744
157954
|
"center",
|
|
@@ -157747,7 +157957,9 @@ ${elements2.join("\n")}
|
|
|
157747
157957
|
img.setCoords();
|
|
157748
157958
|
this.cleanup();
|
|
157749
157959
|
this.canvas.setActiveObject(img);
|
|
157960
|
+
bringOverlaysToFront(this.canvas);
|
|
157750
157961
|
this.canvas.requestRenderAll();
|
|
157962
|
+
useHistoryStore.getState().saveState();
|
|
157751
157963
|
this.onEnd?.();
|
|
157752
157964
|
}
|
|
157753
157965
|
/* ======================== CANCEL ========================== */
|
|
@@ -157783,6 +157995,7 @@ ${elements2.join("\n")}
|
|
|
157783
157995
|
this.fullImage = null;
|
|
157784
157996
|
this.darkOverlay = null;
|
|
157785
157997
|
this.targetImage = null;
|
|
157998
|
+
this.maskPath = null;
|
|
157786
157999
|
}
|
|
157787
158000
|
}
|
|
157788
158001
|
const cropService = new CropService();
|
|
@@ -157869,7 +158082,7 @@ ${elements2.join("\n")}
|
|
|
157869
158082
|
const [isRemovingBg, setIsRemovingBg] = React.useState(false);
|
|
157870
158083
|
const [bgStatus, setBgStatus] = React.useState(null);
|
|
157871
158084
|
const activeObj = canvas2?.getActiveObject();
|
|
157872
|
-
const hasMask = !!activeObj?.clipPath;
|
|
158085
|
+
const hasMask = !!activeObj?.clipPath || !!activeObj?.__maskPath;
|
|
157873
158086
|
activeObj && (activeObj.type === "image" || activeObj.isType?.("image"));
|
|
157874
158087
|
const isBgRemoved = !!activeObj?.__originalSrc || !!activeObj?.__isBgRemoved;
|
|
157875
158088
|
if (type !== "image" || objects?.[0]?.name === "qr" || objects?.[0]?.name === "barcode")
|
|
@@ -157878,8 +158091,9 @@ ${elements2.join("\n")}
|
|
|
157878
158091
|
if (!canvas2) return;
|
|
157879
158092
|
const obj = canvas2.getActiveObject();
|
|
157880
158093
|
if (!obj) return;
|
|
157881
|
-
if (obj.clipPath) {
|
|
158094
|
+
if (obj.clipPath || obj.__maskPath) {
|
|
157882
158095
|
obj.set({ clipPath: null });
|
|
158096
|
+
obj.__maskPath = null;
|
|
157883
158097
|
obj.setCoords();
|
|
157884
158098
|
canvas2.requestRenderAll();
|
|
157885
158099
|
saveState();
|
|
@@ -158170,6 +158384,7 @@ ${elements2.join("\n")}
|
|
|
158170
158384
|
);
|
|
158171
158385
|
const newSelection = clones.length > 1 ? new Qo(clones, { canvas: canvas2 }) : clones[0];
|
|
158172
158386
|
canvas2.setActiveObject(newSelection);
|
|
158387
|
+
bringOverlaysToFront(canvas2);
|
|
158173
158388
|
canvas2.requestRenderAll();
|
|
158174
158389
|
saveState();
|
|
158175
158390
|
return;
|
|
@@ -158185,6 +158400,7 @@ ${elements2.join("\n")}
|
|
|
158185
158400
|
canvas2.discardActiveObject();
|
|
158186
158401
|
canvas2.add(cloned);
|
|
158187
158402
|
canvas2.setActiveObject(cloned);
|
|
158403
|
+
bringOverlaysToFront(canvas2);
|
|
158188
158404
|
canvas2.requestRenderAll();
|
|
158189
158405
|
};
|
|
158190
158406
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -158738,44 +158954,50 @@ ${elements2.join("\n")}
|
|
|
158738
158954
|
if (!active) return [];
|
|
158739
158955
|
return active.type?.toLowerCase() === "activeselection" ? active.getObjects() : [active];
|
|
158740
158956
|
};
|
|
158741
|
-
const
|
|
158742
|
-
const normalizeOrigin = (obj) => {
|
|
158743
|
-
if (obj.originX === "left" && obj.originY === "top") return;
|
|
158744
|
-
const point = obj.getPointByOrigin("left", "top");
|
|
158745
|
-
obj.set({ originX: "left", originY: "top" });
|
|
158746
|
-
obj.setPositionByOrigin(point, "left", "top");
|
|
158747
|
-
};
|
|
158957
|
+
const getAlignmentBoundary = () => canvas2.getObjects().find((o2) => o2.name === "workarea");
|
|
158748
158958
|
const applyAlign = (align) => {
|
|
158749
|
-
const
|
|
158750
|
-
if (!
|
|
158751
|
-
const
|
|
158752
|
-
const
|
|
158753
|
-
const
|
|
158754
|
-
const
|
|
158959
|
+
const boundary = getAlignmentBoundary();
|
|
158960
|
+
if (!boundary) return;
|
|
158961
|
+
const bBounds = boundary.getBoundingRect();
|
|
158962
|
+
const bLeft = bBounds.left;
|
|
158963
|
+
const bTop = bBounds.top;
|
|
158964
|
+
const bWidth = bBounds.width;
|
|
158965
|
+
const bHeight = bBounds.height;
|
|
158755
158966
|
getTargets().forEach((obj) => {
|
|
158756
|
-
|
|
158757
|
-
const
|
|
158758
|
-
const
|
|
158967
|
+
const objBounds = obj.getBoundingRect();
|
|
158968
|
+
const pad = obj.padding || 0;
|
|
158969
|
+
const effLeft = objBounds.left - pad;
|
|
158970
|
+
const effTop = objBounds.top - pad;
|
|
158971
|
+
const effWidth = objBounds.width + pad * 2;
|
|
158972
|
+
const effHeight = objBounds.height + pad * 2;
|
|
158973
|
+
let dx = 0;
|
|
158974
|
+
let dy = 0;
|
|
158759
158975
|
switch (align) {
|
|
158760
158976
|
case "left":
|
|
158761
|
-
|
|
158977
|
+
dx = bLeft - effLeft;
|
|
158762
158978
|
break;
|
|
158763
158979
|
case "center":
|
|
158764
|
-
|
|
158980
|
+
dx = bLeft + (bWidth - effWidth) / 2 - effLeft;
|
|
158765
158981
|
break;
|
|
158766
158982
|
case "right":
|
|
158767
|
-
|
|
158983
|
+
dx = bLeft + bWidth - effWidth - effLeft;
|
|
158768
158984
|
break;
|
|
158769
158985
|
case "top":
|
|
158770
|
-
|
|
158986
|
+
dy = bTop - effTop;
|
|
158771
158987
|
break;
|
|
158772
158988
|
case "middle":
|
|
158773
|
-
|
|
158989
|
+
dy = bTop + (bHeight - effHeight) / 2 - effTop;
|
|
158774
158990
|
break;
|
|
158775
158991
|
case "bottom":
|
|
158776
|
-
|
|
158992
|
+
dy = bTop + bHeight - effHeight - effTop;
|
|
158777
158993
|
break;
|
|
158778
158994
|
}
|
|
158995
|
+
if (dx !== 0) {
|
|
158996
|
+
obj.set({ left: (obj.left ?? 0) + dx });
|
|
158997
|
+
}
|
|
158998
|
+
if (dy !== 0) {
|
|
158999
|
+
obj.set({ top: (obj.top ?? 0) + dy });
|
|
159000
|
+
}
|
|
158779
159001
|
obj.setCoords();
|
|
158780
159002
|
});
|
|
158781
159003
|
canvas2.requestRenderAll();
|
|
@@ -158798,42 +159020,40 @@ ${elements2.join("\n")}
|
|
|
158798
159020
|
const objects = active.getObjects();
|
|
158799
159021
|
if (objects.length && objects.length > 1) {
|
|
158800
159022
|
objects.forEach(function(obj) {
|
|
158801
|
-
const itemWidth = obj.
|
|
159023
|
+
const itemWidth = obj.getScaledWidth();
|
|
159024
|
+
const itemHeight = obj.getScaledHeight();
|
|
159025
|
+
obj.set({ originX: "center", originY: "center" });
|
|
158802
159026
|
switch (align) {
|
|
158803
159027
|
case "left":
|
|
158804
|
-
obj.set({ left: -
|
|
159028
|
+
obj.set({ left: -groupWidth / 2 + itemWidth / 2 });
|
|
158805
159029
|
break;
|
|
158806
159030
|
case "center":
|
|
158807
|
-
obj.set({ left: 0
|
|
159031
|
+
obj.set({ left: 0 });
|
|
158808
159032
|
break;
|
|
158809
159033
|
case "right":
|
|
158810
|
-
obj.set({
|
|
158811
|
-
left: groupWidth / 2 - itemWidth / 2,
|
|
158812
|
-
originX: "center"
|
|
158813
|
-
});
|
|
159034
|
+
obj.set({ left: groupWidth / 2 - itemWidth / 2 });
|
|
158814
159035
|
break;
|
|
158815
159036
|
case "top":
|
|
158816
|
-
obj.set({
|
|
158817
|
-
break;
|
|
158818
|
-
case "bottom":
|
|
158819
|
-
obj.set({ originY: "bottom", top: groupHeight / 2 });
|
|
159037
|
+
obj.set({ top: -groupHeight / 2 + itemHeight / 2 });
|
|
158820
159038
|
break;
|
|
158821
159039
|
case "middle":
|
|
158822
|
-
obj.set({
|
|
158823
|
-
|
|
158824
|
-
|
|
158825
|
-
});
|
|
159040
|
+
obj.set({ top: 0 });
|
|
159041
|
+
break;
|
|
159042
|
+
case "bottom":
|
|
159043
|
+
obj.set({ top: groupHeight / 2 - itemHeight / 2 });
|
|
158826
159044
|
break;
|
|
158827
159045
|
}
|
|
158828
159046
|
obj.setCoords();
|
|
158829
|
-
canvas2.requestRenderAll();
|
|
158830
|
-
saveState();
|
|
158831
159047
|
});
|
|
159048
|
+
active.setCoords();
|
|
159049
|
+
canvas2.requestRenderAll();
|
|
159050
|
+
saveState();
|
|
158832
159051
|
}
|
|
158833
159052
|
};
|
|
158834
159053
|
const bringForward = () => {
|
|
158835
159054
|
const objects = canvas2.getObjects();
|
|
158836
159055
|
[...getTargets()].sort((a2, b2) => objects.indexOf(a2) - objects.indexOf(b2)).reverse().forEach((obj) => canvas2.bringObjectForward(obj, true));
|
|
159056
|
+
bringOverlaysToFront(canvas2);
|
|
158837
159057
|
canvas2.requestRenderAll();
|
|
158838
159058
|
saveState();
|
|
158839
159059
|
};
|
|
@@ -158862,6 +159082,7 @@ ${elements2.join("\n")}
|
|
|
158862
159082
|
const bringToFront = () => {
|
|
158863
159083
|
const objects = canvas2.getObjects();
|
|
158864
159084
|
[...getTargets()].sort((a2, b2) => objects.indexOf(a2) - objects.indexOf(b2)).reverse().forEach((obj) => canvas2.bringObjectToFront(obj));
|
|
159085
|
+
bringOverlaysToFront(canvas2);
|
|
158865
159086
|
canvas2.requestRenderAll();
|
|
158866
159087
|
saveState();
|
|
158867
159088
|
};
|
|
@@ -159216,6 +159437,7 @@ ${elements2.join("\n")}
|
|
|
159216
159437
|
canvas2.add(group);
|
|
159217
159438
|
}
|
|
159218
159439
|
canvas2.setActiveObject(group);
|
|
159440
|
+
bringOverlaysToFront(canvas2);
|
|
159219
159441
|
canvas2.requestRenderAll();
|
|
159220
159442
|
useSelectionStore.getState().setSelection([group]);
|
|
159221
159443
|
saveState();
|
|
@@ -159367,6 +159589,9 @@ ${elements2.join("\n")}
|
|
|
159367
159589
|
obj.__rotationControlSize = rotationSize;
|
|
159368
159590
|
obj.controls.mtr = createRotateControl(rotationSize, rotationOffset);
|
|
159369
159591
|
const textObject = isTextObject(obj);
|
|
159592
|
+
if (textObject) {
|
|
159593
|
+
obj.set({ padding: 0 });
|
|
159594
|
+
}
|
|
159370
159595
|
if (!obj.controls.mb) {
|
|
159371
159596
|
obj.controls.mb = new ai({
|
|
159372
159597
|
x: 0,
|
|
@@ -159485,6 +159710,7 @@ ${elements2.join("\n")}
|
|
|
159485
159710
|
});
|
|
159486
159711
|
canvas2.discardActiveObject();
|
|
159487
159712
|
useSelectionStore.getState().clearSelection();
|
|
159713
|
+
bringOverlaysToFront(canvas2);
|
|
159488
159714
|
canvas2.requestRenderAll();
|
|
159489
159715
|
saveState();
|
|
159490
159716
|
};
|
|
@@ -159594,12 +159820,31 @@ ${elements2.join("\n")}
|
|
|
159594
159820
|
) });
|
|
159595
159821
|
}
|
|
159596
159822
|
function applyOpacity(hex, opacity) {
|
|
159597
|
-
const alpha = Math.max(0, Math.min(1, opacity / 100));
|
|
159598
|
-
|
|
159599
|
-
|
|
159600
|
-
|
|
159601
|
-
|
|
159602
|
-
|
|
159823
|
+
const alpha = Math.max(0, Math.min(1, (opacity ?? 100) / 100));
|
|
159824
|
+
if (!hex) return `rgba(0, 0, 0, ${alpha})`;
|
|
159825
|
+
let clean = hex.trim();
|
|
159826
|
+
if (clean.startsWith("#")) {
|
|
159827
|
+
clean = clean.slice(1);
|
|
159828
|
+
if (clean.length === 3) {
|
|
159829
|
+
clean = clean.split("").map((c2) => c2 + c2).join("");
|
|
159830
|
+
}
|
|
159831
|
+
if (clean.length >= 6) {
|
|
159832
|
+
const r2 = parseInt(clean.slice(0, 2), 16) || 0;
|
|
159833
|
+
const g2 = parseInt(clean.slice(2, 4), 16) || 0;
|
|
159834
|
+
const b2 = parseInt(clean.slice(4, 6), 16) || 0;
|
|
159835
|
+
return `rgba(${r2}, ${g2}, ${b2}, ${alpha})`;
|
|
159836
|
+
}
|
|
159837
|
+
}
|
|
159838
|
+
return clean;
|
|
159839
|
+
}
|
|
159840
|
+
const PENCIL_CURSOR_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
159841
|
+
<path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" fill="#ffffff" stroke="#ffffff" stroke-width="2.5" stroke-linejoin="round"/>
|
|
159842
|
+
<path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" fill="#1e293b" stroke="#0f172a" stroke-width="1.2" stroke-linejoin="round"/>
|
|
159843
|
+
<polygon points="2,22 5.5,20 4,18.5" fill="#f59e0b"/>
|
|
159844
|
+
<polygon points="2,22 3.2,21.3 2.7,20.8" fill="#000000"/>
|
|
159845
|
+
<path d="m15 5 4 4" stroke="#94a3b8" stroke-width="1.2" stroke-linecap="round"/>
|
|
159846
|
+
</svg>`;
|
|
159847
|
+
const PENCIL_CURSOR = `url("data:image/svg+xml;utf8,${encodeURIComponent(PENCIL_CURSOR_SVG)}") 2 22, crosshair`;
|
|
159603
159848
|
function useFabricDrawing() {
|
|
159604
159849
|
const { drawTool, strokeWidth, opacity, color } = useDrawStore();
|
|
159605
159850
|
React.useEffect(() => {
|
|
@@ -159609,19 +159854,99 @@ ${elements2.join("\n")}
|
|
|
159609
159854
|
canvas2.isDrawingMode = false;
|
|
159610
159855
|
canvas2.selection = true;
|
|
159611
159856
|
canvas2.defaultCursor = "default";
|
|
159857
|
+
canvas2.freeDrawingCursor = "default";
|
|
159858
|
+
canvas2.setCursor("default");
|
|
159859
|
+
if (canvas2.upperCanvasEl) {
|
|
159860
|
+
canvas2.upperCanvasEl.style.cursor = "default";
|
|
159861
|
+
}
|
|
159862
|
+
canvas2._isCurrentlyDrawing = false;
|
|
159612
159863
|
return;
|
|
159613
159864
|
}
|
|
159865
|
+
if (canvas2.getActiveObject()) {
|
|
159866
|
+
canvas2.discardActiveObject();
|
|
159867
|
+
useSelectionStore.getState().clearSelection();
|
|
159868
|
+
canvas2.requestRenderAll();
|
|
159869
|
+
}
|
|
159870
|
+
const activeCursor = drawTool === "brush" ? PENCIL_CURSOR : "crosshair";
|
|
159614
159871
|
canvas2.isDrawingMode = true;
|
|
159615
159872
|
canvas2.selection = false;
|
|
159616
|
-
canvas2.defaultCursor =
|
|
159873
|
+
canvas2.defaultCursor = activeCursor;
|
|
159874
|
+
canvas2.freeDrawingCursor = activeCursor;
|
|
159875
|
+
canvas2.setCursor(activeCursor);
|
|
159876
|
+
if (canvas2.upperCanvasEl) {
|
|
159877
|
+
canvas2.upperCanvasEl.style.cursor = activeCursor;
|
|
159878
|
+
}
|
|
159617
159879
|
const brush = new oo(canvas2);
|
|
159618
|
-
brush.width = strokeWidth;
|
|
159619
|
-
brush.color = applyOpacity(color, opacity);
|
|
159620
159880
|
if (drawTool === "highlighter") {
|
|
159621
159881
|
brush.width = strokeWidth * 1.5;
|
|
159622
|
-
brush.color = applyOpacity(color,
|
|
159882
|
+
brush.color = applyOpacity(color, opacity ?? 50);
|
|
159883
|
+
} else {
|
|
159884
|
+
brush.width = strokeWidth;
|
|
159885
|
+
brush.color = applyOpacity(color, opacity ?? 100);
|
|
159623
159886
|
}
|
|
159624
159887
|
canvas2.freeDrawingBrush = brush;
|
|
159888
|
+
const handleMouseDownBefore = (opt) => {
|
|
159889
|
+
if (!canvas2.isDrawingMode) return;
|
|
159890
|
+
const target = opt.target || canvas2.findTarget(opt.e);
|
|
159891
|
+
if (!target) return;
|
|
159892
|
+
const name = target.name || "";
|
|
159893
|
+
if (name === "workarea" || name === "watermark" || name.startsWith("overlay-") || name.startsWith("guideline-")) {
|
|
159894
|
+
return;
|
|
159895
|
+
}
|
|
159896
|
+
if (target.isDrawingPath || name === "drawing-path") {
|
|
159897
|
+
return;
|
|
159898
|
+
}
|
|
159899
|
+
if (target.selectable !== false && target.evented !== false) {
|
|
159900
|
+
canvas2.isDrawingMode = false;
|
|
159901
|
+
canvas2.selection = true;
|
|
159902
|
+
canvas2.defaultCursor = "default";
|
|
159903
|
+
canvas2.freeDrawingCursor = "default";
|
|
159904
|
+
canvas2.setCursor("default");
|
|
159905
|
+
if (canvas2.upperCanvasEl) {
|
|
159906
|
+
canvas2.upperCanvasEl.style.cursor = "default";
|
|
159907
|
+
}
|
|
159908
|
+
canvas2._isCurrentlyDrawing = false;
|
|
159909
|
+
useDrawStore.getState().setDrawTool("select");
|
|
159910
|
+
canvas2.setActiveObject(target);
|
|
159911
|
+
canvas2.requestRenderAll();
|
|
159912
|
+
}
|
|
159913
|
+
};
|
|
159914
|
+
const handlePathCreated = (e2) => {
|
|
159915
|
+
if (e2?.path) {
|
|
159916
|
+
e2.path.name = "drawing-path";
|
|
159917
|
+
e2.path.isDrawingPath = true;
|
|
159918
|
+
}
|
|
159919
|
+
};
|
|
159920
|
+
const handleSelectionChange = () => {
|
|
159921
|
+
if (useDrawStore.getState().drawTool !== "select") {
|
|
159922
|
+
useDrawStore.getState().setDrawTool("select");
|
|
159923
|
+
}
|
|
159924
|
+
if (canvas2.isDrawingMode) {
|
|
159925
|
+
canvas2.isDrawingMode = false;
|
|
159926
|
+
canvas2.selection = true;
|
|
159927
|
+
canvas2.defaultCursor = "default";
|
|
159928
|
+
canvas2.freeDrawingCursor = "default";
|
|
159929
|
+
canvas2.setCursor("default");
|
|
159930
|
+
if (canvas2.upperCanvasEl) {
|
|
159931
|
+
canvas2.upperCanvasEl.style.cursor = "default";
|
|
159932
|
+
}
|
|
159933
|
+
canvas2._isCurrentlyDrawing = false;
|
|
159934
|
+
canvas2.requestRenderAll();
|
|
159935
|
+
}
|
|
159936
|
+
};
|
|
159937
|
+
canvas2.on("mouse:down:before", handleMouseDownBefore);
|
|
159938
|
+
canvas2.on("path:created", handlePathCreated);
|
|
159939
|
+
canvas2.on("selection:created", handleSelectionChange);
|
|
159940
|
+
canvas2.on("selection:updated", handleSelectionChange);
|
|
159941
|
+
return () => {
|
|
159942
|
+
canvas2.off("mouse:down:before", handleMouseDownBefore);
|
|
159943
|
+
canvas2.off("path:created", handlePathCreated);
|
|
159944
|
+
canvas2.off("selection:created", handleSelectionChange);
|
|
159945
|
+
canvas2.off("selection:updated", handleSelectionChange);
|
|
159946
|
+
if (canvas2.upperCanvasEl) {
|
|
159947
|
+
canvas2.upperCanvasEl.style.cursor = "default";
|
|
159948
|
+
}
|
|
159949
|
+
};
|
|
159625
159950
|
}, [drawTool, strokeWidth, opacity, color]);
|
|
159626
159951
|
}
|
|
159627
159952
|
function PointerIcon() {
|
|
@@ -159652,6 +159977,89 @@ ${elements2.join("\n")}
|
|
|
159652
159977
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15" })
|
|
159653
159978
|
] });
|
|
159654
159979
|
}
|
|
159980
|
+
function GridIcon({
|
|
159981
|
+
size = 18,
|
|
159982
|
+
className = ""
|
|
159983
|
+
}) {
|
|
159984
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
159985
|
+
"svg",
|
|
159986
|
+
{
|
|
159987
|
+
width: size,
|
|
159988
|
+
height: size,
|
|
159989
|
+
viewBox: "0 0 24 24",
|
|
159990
|
+
fill: "none",
|
|
159991
|
+
stroke: "currentColor",
|
|
159992
|
+
strokeWidth: "2",
|
|
159993
|
+
strokeLinecap: "round",
|
|
159994
|
+
strokeLinejoin: "round",
|
|
159995
|
+
className,
|
|
159996
|
+
children: [
|
|
159997
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }),
|
|
159998
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 9h18" }),
|
|
159999
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 15h18" }),
|
|
160000
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 3v18" }),
|
|
160001
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 3v18" })
|
|
160002
|
+
]
|
|
160003
|
+
}
|
|
160004
|
+
);
|
|
160005
|
+
}
|
|
160006
|
+
function getGridStep(width, height) {
|
|
160007
|
+
const minDim = Math.min(width, height);
|
|
160008
|
+
if (minDim <= 200) return 10;
|
|
160009
|
+
if (minDim <= 400) return 20;
|
|
160010
|
+
if (minDim <= 800) return 25;
|
|
160011
|
+
return 40;
|
|
160012
|
+
}
|
|
160013
|
+
function renderGrid(canvas2) {
|
|
160014
|
+
if (!canvas2) return;
|
|
160015
|
+
canvas2.getObjects().forEach((o2) => {
|
|
160016
|
+
if (o2.name === "canvas-grid") {
|
|
160017
|
+
canvas2.remove(o2);
|
|
160018
|
+
}
|
|
160019
|
+
});
|
|
160020
|
+
const showGrid = useEditorStore.getState().showGrid;
|
|
160021
|
+
if (!showGrid) {
|
|
160022
|
+
canvas2.requestRenderAll();
|
|
160023
|
+
return;
|
|
160024
|
+
}
|
|
160025
|
+
const workarea = canvas2.getObjects().find((o2) => o2.name === "workarea");
|
|
160026
|
+
if (!workarea) {
|
|
160027
|
+
canvas2.requestRenderAll();
|
|
160028
|
+
return;
|
|
160029
|
+
}
|
|
160030
|
+
const waL = workarea.left ?? 0;
|
|
160031
|
+
const waT = workarea.top ?? 0;
|
|
160032
|
+
const waW = workarea.getScaledWidth();
|
|
160033
|
+
const waH = workarea.getScaledHeight();
|
|
160034
|
+
if (waW <= 0 || waH <= 0) return;
|
|
160035
|
+
const step = getGridStep(waW, waH);
|
|
160036
|
+
let pathData = "";
|
|
160037
|
+
for (let x2 = step; x2 < waW; x2 += step) {
|
|
160038
|
+
const roundX = Math.round(x2 * 100) / 100;
|
|
160039
|
+
pathData += `M ${roundX} 0 V ${waH} `;
|
|
160040
|
+
}
|
|
160041
|
+
for (let y2 = step; y2 < waH; y2 += step) {
|
|
160042
|
+
const roundY = Math.round(y2 * 100) / 100;
|
|
160043
|
+
pathData += `M 0 ${roundY} H ${waW} `;
|
|
160044
|
+
}
|
|
160045
|
+
if (!pathData) return;
|
|
160046
|
+
const gridPath = new no(pathData, {
|
|
160047
|
+
name: "canvas-grid",
|
|
160048
|
+
left: waL,
|
|
160049
|
+
top: waT,
|
|
160050
|
+
originX: "left",
|
|
160051
|
+
originY: "top",
|
|
160052
|
+
stroke: "rgba(100, 116, 139, 0.28)",
|
|
160053
|
+
strokeWidth: 1,
|
|
160054
|
+
fill: "",
|
|
160055
|
+
selectable: false,
|
|
160056
|
+
evented: false,
|
|
160057
|
+
excludeFromExport: true
|
|
160058
|
+
});
|
|
160059
|
+
canvas2.add(gridPath);
|
|
160060
|
+
bringOverlaysToFront(canvas2);
|
|
160061
|
+
canvas2.requestRenderAll();
|
|
160062
|
+
}
|
|
159655
160063
|
function enablePanMode(canvas2) {
|
|
159656
160064
|
let isDragging = false;
|
|
159657
160065
|
let lastClientX = 0;
|
|
@@ -159919,10 +160327,11 @@ ${elements2.join("\n")}
|
|
|
159919
160327
|
const target = e2?.target;
|
|
159920
160328
|
if (!target) return;
|
|
159921
160329
|
const name = target.name || "";
|
|
159922
|
-
if (name === "workarea" || name === "watermark" || name.startsWith("overlay-") || name.startsWith("guideline-")) {
|
|
160330
|
+
if (name === "workarea" || name === "watermark" || name === "bg-image" || name.startsWith("overlay-") || name.startsWith("guideline-") || name === "canvas-grid") {
|
|
159923
160331
|
return;
|
|
159924
160332
|
}
|
|
159925
160333
|
if (useHistoryStore.getState().isRestoring) return;
|
|
160334
|
+
flushBackgroundSave();
|
|
159926
160335
|
if (modifiedTimer) {
|
|
159927
160336
|
clearTimeout(modifiedTimer);
|
|
159928
160337
|
modifiedTimer = null;
|
|
@@ -159937,7 +160346,7 @@ ${elements2.join("\n")}
|
|
|
159937
160346
|
const target = e2?.target;
|
|
159938
160347
|
if (!target) return;
|
|
159939
160348
|
const name = target.name || "";
|
|
159940
|
-
if (name === "workarea" || name === "watermark" || name.startsWith("overlay-") || name.startsWith("guideline-")) {
|
|
160349
|
+
if (name === "workarea" || name === "watermark" || name.startsWith("overlay-") || name.startsWith("guideline-") || name === "canvas-grid") {
|
|
159941
160350
|
return;
|
|
159942
160351
|
}
|
|
159943
160352
|
if (useHistoryStore.getState().isRestoring) return;
|
|
@@ -159960,6 +160369,12 @@ ${elements2.join("\n")}
|
|
|
159960
160369
|
}
|
|
159961
160370
|
function setupDoublClickCrop(canvas2) {
|
|
159962
160371
|
const handleDoubleClick = (e2) => {
|
|
160372
|
+
const isCropping = useEditorStore.getState().isCropping;
|
|
160373
|
+
if (isCropping) {
|
|
160374
|
+
applyCrop(canvas2);
|
|
160375
|
+
useEditorStore.getState().stopCropping();
|
|
160376
|
+
return;
|
|
160377
|
+
}
|
|
159963
160378
|
const target = e2.target;
|
|
159964
160379
|
if (target && target.type === "image" && target.name !== "bg-image") {
|
|
159965
160380
|
useEditorStore.getState().startCropping();
|
|
@@ -160005,6 +160420,13 @@ ${elements2.join("\n")}
|
|
|
160005
160420
|
canvas2.requestRenderAll();
|
|
160006
160421
|
};
|
|
160007
160422
|
canvas2.on("selection:created", (e2) => {
|
|
160423
|
+
if (useDrawStore.getState().drawTool !== "select") {
|
|
160424
|
+
useDrawStore.getState().setDrawTool("select");
|
|
160425
|
+
canvas2.isDrawingMode = false;
|
|
160426
|
+
canvas2.selection = true;
|
|
160427
|
+
canvas2.defaultCursor = "default";
|
|
160428
|
+
canvas2._isCurrentlyDrawing = false;
|
|
160429
|
+
}
|
|
160008
160430
|
if (e2.selected) {
|
|
160009
160431
|
e2.selected.forEach((o2) => {
|
|
160010
160432
|
o2.__showDegree = false;
|
|
@@ -160012,8 +160434,16 @@ ${elements2.join("\n")}
|
|
|
160012
160434
|
}
|
|
160013
160435
|
updateSelection();
|
|
160014
160436
|
configureSelectionControls();
|
|
160437
|
+
bringOverlaysToFront(canvas2);
|
|
160015
160438
|
});
|
|
160016
160439
|
canvas2.on("selection:updated", (e2) => {
|
|
160440
|
+
if (useDrawStore.getState().drawTool !== "select") {
|
|
160441
|
+
useDrawStore.getState().setDrawTool("select");
|
|
160442
|
+
canvas2.isDrawingMode = false;
|
|
160443
|
+
canvas2.selection = true;
|
|
160444
|
+
canvas2.defaultCursor = "default";
|
|
160445
|
+
canvas2._isCurrentlyDrawing = false;
|
|
160446
|
+
}
|
|
160017
160447
|
const active = canvas2.getActiveObject();
|
|
160018
160448
|
const bgImg = canvas2.getObjects().find((o2) => o2.name === "bg-image");
|
|
160019
160449
|
if (bgImg && active !== bgImg) {
|
|
@@ -160034,6 +160464,7 @@ ${elements2.join("\n")}
|
|
|
160034
160464
|
}
|
|
160035
160465
|
updateSelection();
|
|
160036
160466
|
configureSelectionControls();
|
|
160467
|
+
bringOverlaysToFront(canvas2);
|
|
160037
160468
|
});
|
|
160038
160469
|
canvas2.on("object:scaling", configureSelectionControls);
|
|
160039
160470
|
canvas2.on("object:rotating", (e2) => {
|
|
@@ -160050,7 +160481,12 @@ ${elements2.join("\n")}
|
|
|
160050
160481
|
o2.__showDegree = false;
|
|
160051
160482
|
});
|
|
160052
160483
|
configureSelectionControls();
|
|
160484
|
+
bringOverlaysToFront(canvas2);
|
|
160485
|
+
};
|
|
160486
|
+
const handleObjectMoving = () => {
|
|
160487
|
+
bringOverlaysToFront(canvas2);
|
|
160053
160488
|
};
|
|
160489
|
+
canvas2.on("object:moving", handleObjectMoving);
|
|
160054
160490
|
canvas2.on("object:modified", hideDegree);
|
|
160055
160491
|
canvas2.on("mouse:up", hideDegree);
|
|
160056
160492
|
canvas2.on("selection:cleared", () => {
|
|
@@ -160067,6 +160503,7 @@ ${elements2.join("\n")}
|
|
|
160067
160503
|
}
|
|
160068
160504
|
}
|
|
160069
160505
|
hideDegree();
|
|
160506
|
+
bringOverlaysToFront(canvas2);
|
|
160070
160507
|
clearSelection();
|
|
160071
160508
|
});
|
|
160072
160509
|
return () => {
|
|
@@ -160074,6 +160511,7 @@ ${elements2.join("\n")}
|
|
|
160074
160511
|
canvas2.off("selection:updated");
|
|
160075
160512
|
canvas2.off("object:scaling", configureSelectionControls);
|
|
160076
160513
|
canvas2.off("object:rotating");
|
|
160514
|
+
canvas2.off("object:moving", handleObjectMoving);
|
|
160077
160515
|
canvas2.off("object:modified", hideDegree);
|
|
160078
160516
|
canvas2.off("mouse:up", hideDegree);
|
|
160079
160517
|
canvas2.off("selection:cleared");
|
|
@@ -160082,7 +160520,9 @@ ${elements2.join("\n")}
|
|
|
160082
160520
|
function setupObjectAddedHandler(canvas2) {
|
|
160083
160521
|
const handleObjectAdded = (e2) => {
|
|
160084
160522
|
const obj = e2.target;
|
|
160085
|
-
if (!obj || obj.name === "workarea")
|
|
160523
|
+
if (!obj || obj.name === "workarea" || obj.name?.startsWith("overlay-") || obj.name?.startsWith("guideline-")) {
|
|
160524
|
+
return;
|
|
160525
|
+
}
|
|
160086
160526
|
configureObjectControls(obj);
|
|
160087
160527
|
bringOverlaysToFront(canvas2);
|
|
160088
160528
|
};
|
|
@@ -160576,21 +161016,27 @@ ${elements2.join("\n")}
|
|
|
160576
161016
|
] }) });
|
|
160577
161017
|
}
|
|
160578
161018
|
const OFFSET = 20;
|
|
160579
|
-
function useKeyboardEvents(
|
|
161019
|
+
function useKeyboardEvents(canvasParam) {
|
|
160580
161020
|
const clipboardRef = React.useRef(null);
|
|
161021
|
+
const storeCanvas = useEditorStore((s2) => s2.canvas);
|
|
161022
|
+
const historyCanvas = useHistoryStore((s2) => s2.canvas);
|
|
161023
|
+
const canvas2 = canvasParam || storeCanvas || historyCanvas;
|
|
160581
161024
|
const saveState = useHistoryStore((s2) => s2.saveState);
|
|
160582
161025
|
React.useEffect(() => {
|
|
160583
|
-
|
|
161026
|
+
const getActiveCanvas = () => canvas2 || useEditorStore.getState().canvas || useHistoryStore.getState().canvas;
|
|
160584
161027
|
const handleCopy = async () => {
|
|
160585
|
-
const
|
|
161028
|
+
const activeCanvas = getActiveCanvas();
|
|
161029
|
+
if (!activeCanvas) return;
|
|
161030
|
+
const activeObject = activeCanvas.getActiveObject();
|
|
160586
161031
|
if (!activeObject || activeObject.name === "workarea") return;
|
|
160587
161032
|
const cloned = await activeObject.clone();
|
|
160588
161033
|
clipboardRef.current = cloned;
|
|
160589
161034
|
};
|
|
160590
161035
|
const handlePaste = async () => {
|
|
160591
|
-
|
|
161036
|
+
const activeCanvas = getActiveCanvas();
|
|
161037
|
+
if (!activeCanvas || !clipboardRef.current) return;
|
|
160592
161038
|
const clonedObj = await clipboardRef.current.clone();
|
|
160593
|
-
|
|
161039
|
+
activeCanvas.discardActiveObject();
|
|
160594
161040
|
clonedObj.set({
|
|
160595
161041
|
left: (clonedObj.left ?? 0) + OFFSET,
|
|
160596
161042
|
top: (clonedObj.top ?? 0) + OFFSET,
|
|
@@ -160601,16 +161047,17 @@ ${elements2.join("\n")}
|
|
|
160601
161047
|
top: (clipboardRef.current.top ?? 0) + OFFSET
|
|
160602
161048
|
});
|
|
160603
161049
|
if (clonedObj.type?.toLowerCase() === "activeselection") {
|
|
160604
|
-
clonedObj.canvas =
|
|
161050
|
+
clonedObj.canvas = activeCanvas;
|
|
160605
161051
|
clonedObj.forEachObject((obj) => {
|
|
160606
|
-
|
|
161052
|
+
activeCanvas.add(obj);
|
|
160607
161053
|
});
|
|
160608
161054
|
clonedObj.setCoords();
|
|
160609
161055
|
} else {
|
|
160610
|
-
|
|
161056
|
+
activeCanvas.add(clonedObj);
|
|
160611
161057
|
}
|
|
160612
|
-
|
|
160613
|
-
|
|
161058
|
+
activeCanvas.setActiveObject(clonedObj);
|
|
161059
|
+
bringOverlaysToFront(activeCanvas);
|
|
161060
|
+
activeCanvas.requestRenderAll();
|
|
160614
161061
|
saveState();
|
|
160615
161062
|
};
|
|
160616
161063
|
const handleKeyDown = (e2) => {
|
|
@@ -160618,25 +161065,36 @@ ${elements2.join("\n")}
|
|
|
160618
161065
|
const isInput = activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement || activeElement?.isContentEditable;
|
|
160619
161066
|
if (isInput) return;
|
|
160620
161067
|
const isModifier = e2.ctrlKey || e2.metaKey;
|
|
160621
|
-
if (isModifier
|
|
161068
|
+
if (!isModifier) return;
|
|
161069
|
+
const isZ = e2.key?.toLowerCase() === "z" || e2.code === "KeyZ";
|
|
161070
|
+
const isY = e2.key?.toLowerCase() === "y" || e2.code === "KeyY";
|
|
161071
|
+
const isC = e2.key?.toLowerCase() === "c" || e2.code === "KeyC";
|
|
161072
|
+
const isV = e2.key?.toLowerCase() === "v" || e2.code === "KeyV";
|
|
161073
|
+
if (isZ && !e2.shiftKey) {
|
|
160622
161074
|
e2.preventDefault();
|
|
160623
|
-
|
|
161075
|
+
useHistoryStore.getState().undo();
|
|
161076
|
+
return;
|
|
160624
161077
|
}
|
|
160625
|
-
if (
|
|
161078
|
+
if (isZ && e2.shiftKey || isY) {
|
|
160626
161079
|
e2.preventDefault();
|
|
160627
|
-
|
|
161080
|
+
useHistoryStore.getState().redoAction();
|
|
161081
|
+
return;
|
|
160628
161082
|
}
|
|
160629
|
-
if (
|
|
161083
|
+
if (isC) {
|
|
160630
161084
|
e2.preventDefault();
|
|
160631
|
-
|
|
160632
|
-
|
|
160633
|
-
} else {
|
|
160634
|
-
useHistoryStore.getState().undo();
|
|
160635
|
-
}
|
|
161085
|
+
handleCopy();
|
|
161086
|
+
return;
|
|
160636
161087
|
}
|
|
160637
|
-
if (
|
|
161088
|
+
if (isV) {
|
|
160638
161089
|
e2.preventDefault();
|
|
160639
|
-
|
|
161090
|
+
handlePaste();
|
|
161091
|
+
return;
|
|
161092
|
+
}
|
|
161093
|
+
const isQuote = e2.key === "'" || e2.code === "Quote";
|
|
161094
|
+
if (isQuote) {
|
|
161095
|
+
e2.preventDefault();
|
|
161096
|
+
useEditorStore.getState().toggleGrid();
|
|
161097
|
+
return;
|
|
160640
161098
|
}
|
|
160641
161099
|
};
|
|
160642
161100
|
window.addEventListener("keydown", handleKeyDown);
|
|
@@ -160652,9 +161110,14 @@ ${elements2.join("\n")}
|
|
|
160652
161110
|
const workareaRef = React.useRef(null);
|
|
160653
161111
|
const panHandlersRef = React.useRef(null);
|
|
160654
161112
|
const isCropping = useEditorStore((s2) => s2.isCropping);
|
|
161113
|
+
const canvas2 = useEditorStore((s2) => s2.canvas);
|
|
160655
161114
|
const setCanvas = useEditorStore((s2) => s2.setCanvas);
|
|
161115
|
+
const showGrid = useEditorStore((s2) => s2.showGrid);
|
|
161116
|
+
const toggleGrid = useEditorStore((s2) => s2.toggleGrid);
|
|
160656
161117
|
const setSelection = useSelectionStore((s2) => s2.setSelection);
|
|
160657
161118
|
const clearSelection = useSelectionStore((s2) => s2.clearSelection);
|
|
161119
|
+
const drawTool = useDrawStore((s2) => s2.drawTool);
|
|
161120
|
+
const setDrawTool = useDrawStore((s2) => s2.setDrawTool);
|
|
160658
161121
|
const productData = useProductStore((s2) => s2.productData);
|
|
160659
161122
|
const isTwoSided = productData?.optionsMap?.printing === "4/4";
|
|
160660
161123
|
const [currentPage, setCurrentPage] = React.useState("front");
|
|
@@ -160704,20 +161167,20 @@ ${elements2.join("\n")}
|
|
|
160704
161167
|
}
|
|
160705
161168
|
if (!isMounted || !canvasRef.current || !containerRef.current || fabricRef.current) return;
|
|
160706
161169
|
initializeRotateImage();
|
|
160707
|
-
const
|
|
160708
|
-
fabricRef.current =
|
|
160709
|
-
setCanvas(
|
|
160710
|
-
useHistoryStore.getState().setCanvas(
|
|
160711
|
-
const workarea = createWorkarea(
|
|
161170
|
+
const canvas22 = initializeCanvas(canvasRef.current, containerRef.current);
|
|
161171
|
+
fabricRef.current = canvas22;
|
|
161172
|
+
setCanvas(canvas22);
|
|
161173
|
+
useHistoryStore.getState().setCanvas(canvas22);
|
|
161174
|
+
const workarea = createWorkarea(canvas22, containerRef.current, product);
|
|
160712
161175
|
workareaRef.current = workarea;
|
|
160713
|
-
const cleanupHistory = setupHistoryRecording(
|
|
160714
|
-
const cleanupCrop = setupDoublClickCrop(
|
|
161176
|
+
const cleanupHistory = setupHistoryRecording(canvas22);
|
|
161177
|
+
const cleanupCrop = setupDoublClickCrop(canvas22);
|
|
160715
161178
|
const cleanupSelection = setupSelectionHandlers(
|
|
160716
|
-
|
|
161179
|
+
canvas22,
|
|
160717
161180
|
setSelection,
|
|
160718
161181
|
clearSelection
|
|
160719
161182
|
);
|
|
160720
|
-
const cleanupObjectAdded = setupObjectAddedHandler(
|
|
161183
|
+
const cleanupObjectAdded = setupObjectAddedHandler(canvas22);
|
|
160721
161184
|
if (isTextDesign && templateId) {
|
|
160722
161185
|
const item = await ShapeService.getTextTemplateById(templateId);
|
|
160723
161186
|
if (item?.jsonData) {
|
|
@@ -160725,7 +161188,7 @@ ${elements2.join("\n")}
|
|
|
160725
161188
|
pageJSON.current.front = parsed;
|
|
160726
161189
|
await loadTemplateFontsIntoHead(null, parsed);
|
|
160727
161190
|
useHistoryStore.setState({ isRestoring: true });
|
|
160728
|
-
await loadPageToCanvas(
|
|
161191
|
+
await loadPageToCanvas(canvas22, parsed);
|
|
160729
161192
|
useHistoryStore.setState({ isRestoring: false });
|
|
160730
161193
|
useHistoryStore.getState().saveState();
|
|
160731
161194
|
}
|
|
@@ -160746,7 +161209,7 @@ ${elements2.join("\n")}
|
|
|
160746
161209
|
if (frontData) {
|
|
160747
161210
|
pageJSON.current.front = frontData;
|
|
160748
161211
|
useHistoryStore.setState({ isRestoring: true });
|
|
160749
|
-
await loadPageToCanvas(
|
|
161212
|
+
await loadPageToCanvas(canvas22, frontData);
|
|
160750
161213
|
useHistoryStore.setState({ isRestoring: false });
|
|
160751
161214
|
useHistoryStore.getState().saveState();
|
|
160752
161215
|
}
|
|
@@ -160763,10 +161226,10 @@ ${elements2.join("\n")}
|
|
|
160763
161226
|
cleanupCrop();
|
|
160764
161227
|
cleanupSelection();
|
|
160765
161228
|
cleanupObjectAdded();
|
|
160766
|
-
if (
|
|
160767
|
-
|
|
161229
|
+
if (canvas22.__cleanupResizeObserver) {
|
|
161230
|
+
canvas22.__cleanupResizeObserver();
|
|
160768
161231
|
}
|
|
160769
|
-
|
|
161232
|
+
canvas22.dispose();
|
|
160770
161233
|
fabricRef.current = null;
|
|
160771
161234
|
setCanvas(null);
|
|
160772
161235
|
clearSelection();
|
|
@@ -160804,23 +161267,30 @@ ${elements2.join("\n")}
|
|
|
160804
161267
|
return setupBorderSync(fabricRef.current);
|
|
160805
161268
|
}, [fabricRef.current]);
|
|
160806
161269
|
React.useEffect(() => {
|
|
160807
|
-
const
|
|
160808
|
-
if (!
|
|
160809
|
-
removePanHandlers(
|
|
161270
|
+
const canvas22 = fabricRef.current;
|
|
161271
|
+
if (!canvas22) return;
|
|
161272
|
+
removePanHandlers(canvas22, panHandlersRef.current);
|
|
160810
161273
|
panHandlersRef.current = null;
|
|
160811
161274
|
if (isPanning) {
|
|
160812
|
-
panHandlersRef.current = enablePanMode(
|
|
161275
|
+
panHandlersRef.current = enablePanMode(canvas22);
|
|
160813
161276
|
} else {
|
|
160814
|
-
disablePanMode(
|
|
161277
|
+
disablePanMode(canvas22);
|
|
160815
161278
|
}
|
|
160816
161279
|
return () => {
|
|
160817
|
-
removePanHandlers(
|
|
161280
|
+
removePanHandlers(canvas22, panHandlersRef.current);
|
|
160818
161281
|
};
|
|
160819
161282
|
}, [isPanning]);
|
|
160820
161283
|
useFabricDrawing();
|
|
160821
|
-
useKeyboardEvents(fabricRef.current);
|
|
161284
|
+
useKeyboardEvents(canvas2 || fabricRef.current);
|
|
161285
|
+
React.useEffect(() => {
|
|
161286
|
+
const activeCanvas = canvas2 || fabricRef.current;
|
|
161287
|
+
if (activeCanvas) {
|
|
161288
|
+
renderGrid(activeCanvas);
|
|
161289
|
+
}
|
|
161290
|
+
}, [showGrid, canvas2, currentPage]);
|
|
160822
161291
|
const switchPage = async (page) => {
|
|
160823
161292
|
if (!fabricRef.current) return;
|
|
161293
|
+
setDrawTool("select");
|
|
160824
161294
|
await switchCanvasPage(
|
|
160825
161295
|
fabricRef.current,
|
|
160826
161296
|
currentPage,
|
|
@@ -160831,6 +161301,7 @@ ${elements2.join("\n")}
|
|
|
160831
161301
|
);
|
|
160832
161302
|
useEditorStore.getState().setPages({ ...pageJSON.current });
|
|
160833
161303
|
setCurrentPage(page);
|
|
161304
|
+
renderGrid(fabricRef.current);
|
|
160834
161305
|
};
|
|
160835
161306
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
160836
161307
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-6 z-50 flex items-center bg-white/80 backdrop-blur-xl rounded-2xl shadow-[0_8px_32px_rgba(0,0,0,0.12)] px-1.5 py-1.5 border border-white/40 ring-1 ring-black/5", children: [
|
|
@@ -160857,20 +161328,35 @@ ${elements2.join("\n")}
|
|
|
160857
161328
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
160858
161329
|
"button",
|
|
160859
161330
|
{
|
|
160860
|
-
onClick: () =>
|
|
161331
|
+
onClick: () => {
|
|
161332
|
+
setIsPanning(false);
|
|
161333
|
+
setDrawTool("select");
|
|
161334
|
+
},
|
|
160861
161335
|
title: "Selection Mode",
|
|
160862
|
-
className: `p-2 rounded-xl transition-all duration-200 ${!isPanning ? "bg-[#02bc71] text-white shadow-lg shadow-
|
|
161336
|
+
className: `p-2 rounded-xl transition-all duration-200 cursor-pointer ${!isPanning && drawTool === "select" ? "bg-[#02bc71] text-white shadow-lg shadow-green-200" : "text-gray-400 hover:bg-gray-100 hover:text-gray-600"}`,
|
|
160863
161337
|
children: /* @__PURE__ */ jsxRuntime.jsx(PointerIcon, {})
|
|
160864
161338
|
}
|
|
160865
161339
|
),
|
|
160866
161340
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
160867
161341
|
"button",
|
|
160868
161342
|
{
|
|
160869
|
-
onClick: () =>
|
|
161343
|
+
onClick: () => {
|
|
161344
|
+
setIsPanning(true);
|
|
161345
|
+
setDrawTool("select");
|
|
161346
|
+
},
|
|
160870
161347
|
title: "Hand Mode",
|
|
160871
|
-
className: `p-2 rounded-xl transition-all duration-200 ${isPanning ? "bg-[#02bc71] text-white shadow-lg shadow-
|
|
161348
|
+
className: `p-2 rounded-xl transition-all duration-200 cursor-pointer ${isPanning ? "bg-[#02bc71] text-white shadow-lg shadow-green-200" : "text-gray-400 hover:bg-gray-100 hover:text-gray-600"}`,
|
|
160872
161349
|
children: /* @__PURE__ */ jsxRuntime.jsx(HandIcon, {})
|
|
160873
161350
|
}
|
|
161351
|
+
),
|
|
161352
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
161353
|
+
"button",
|
|
161354
|
+
{
|
|
161355
|
+
onClick: () => toggleGrid(),
|
|
161356
|
+
title: showGrid ? "Hide Grid (Ctrl+')" : "Show Grid (Ctrl+')",
|
|
161357
|
+
className: `p-2 rounded-xl transition-all duration-200 cursor-pointer ${showGrid ? "bg-[#02bc71] text-white shadow-lg shadow-green-200" : "text-gray-400 hover:bg-gray-100 hover:text-gray-600"}`,
|
|
161358
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(GridIcon, {})
|
|
161359
|
+
}
|
|
160874
161360
|
)
|
|
160875
161361
|
] }),
|
|
160876
161362
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[1px] h-6 bg-gray-300/50 mx-3" }),
|