@printine/designer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/README.md +146 -0
  2. package/dist/DesignerRuntimeContext.d.ts +3 -0
  3. package/dist/PrintineDesigner.d.ts +9 -0
  4. package/dist/api/client.d.ts +8 -0
  5. package/dist/api/client.js +82 -0
  6. package/dist/api/common-endpoints.d.ts +12 -0
  7. package/dist/api/design-endpoints.d.ts +18 -0
  8. package/dist/api/endpoints.d.ts +33 -0
  9. package/dist/api/endpoints.js +46 -0
  10. package/dist/api/files-endpoints.d.ts +1 -0
  11. package/dist/assets/icons/aspect_ratio.d.ts +3 -0
  12. package/dist/assets/icons/delete.d.ts +3 -0
  13. package/dist/assets/icons/fit_screen.d.ts +3 -0
  14. package/dist/assets/icons/index.d.ts +11 -0
  15. package/dist/assets/icons/loading_1.d.ts +3 -0
  16. package/dist/assets/icons/loading_2.d.ts +3 -0
  17. package/dist/assets/icons/loading_3.d.ts +3 -0
  18. package/dist/assets/icons/pan.d.ts +3 -0
  19. package/dist/assets/icons/setting.d.ts +3 -0
  20. package/dist/assets/icons/text_color.d.ts +3 -0
  21. package/dist/assets/icons/text_h.d.ts +3 -0
  22. package/dist/assets/icons/text_v.d.ts +3 -0
  23. package/dist/bundled-assets.d.ts +4 -0
  24. package/dist/components/add-design.d.ts +8 -0
  25. package/dist/components/assets-dialog.d.ts +21 -0
  26. package/dist/components/canvas-context-menu.d.ts +6 -0
  27. package/dist/components/color-picker/index.d.ts +10 -0
  28. package/dist/components/context.d.ts +24 -0
  29. package/dist/components/design.d.ts +9 -0
  30. package/dist/components/fonts.d.ts +26 -0
  31. package/dist/components/image-crop.d.ts +4 -0
  32. package/dist/components/image-edit.d.ts +1 -0
  33. package/dist/components/layout/aside.d.ts +3 -0
  34. package/dist/components/layout/bottom-nav/element-menu-sheet.d.ts +11 -0
  35. package/dist/components/layout/bottom-nav/element-sheet.d.ts +11 -0
  36. package/dist/components/layout/bottom-nav/index.d.ts +1 -0
  37. package/dist/components/layout/header.d.ts +5 -0
  38. package/dist/components/loading.d.ts +3 -0
  39. package/dist/components/menus/ai.d.ts +5 -0
  40. package/dist/components/menus/background.d.ts +6 -0
  41. package/dist/components/menus/clipart.d.ts +6 -0
  42. package/dist/components/menus/files.d.ts +7 -0
  43. package/dist/components/menus/image.d.ts +8 -0
  44. package/dist/components/menus/index.d.ts +13 -0
  45. package/dist/components/menus/layer.d.ts +5 -0
  46. package/dist/components/menus/product.d.ts +3 -0
  47. package/dist/components/menus/sca.d.ts +5 -0
  48. package/dist/components/menus/shapes.d.ts +6 -0
  49. package/dist/components/menus/templates.d.ts +6 -0
  50. package/dist/components/menus/text-effects.d.ts +5 -0
  51. package/dist/components/menus/text.d.ts +6 -0
  52. package/dist/components/placement-tab.d.ts +7 -0
  53. package/dist/components/preview/3d.d.ts +7 -0
  54. package/dist/components/preview/graphic.d.ts +7 -0
  55. package/dist/components/preview/index.d.ts +18 -0
  56. package/dist/components/preview/open.d.ts +7 -0
  57. package/dist/components/preview/real-time/3d.d.ts +12 -0
  58. package/dist/components/preview/real-time/graphic.d.ts +18 -0
  59. package/dist/components/preview/real-time/index.d.ts +11 -0
  60. package/dist/components/scale-tools.d.ts +7 -0
  61. package/dist/components/semi-deisgn-config.d.ts +13 -0
  62. package/dist/components/semi-design-link.d.ts +9 -0
  63. package/dist/components/store.d.ts +1 -0
  64. package/dist/components/toolbar.d.ts +2 -0
  65. package/dist/config-D2qm60gf.js +16 -0
  66. package/dist/contracts/api-design.d.ts +176 -0
  67. package/dist/contracts/design.d.ts +86 -0
  68. package/dist/design-7zRpRtv9.js +20331 -0
  69. package/dist/engine/canvas-designer.d.ts +101 -0
  70. package/dist/engine/canvas-designer.js +313 -0
  71. package/dist/engine/constants.d.ts +27 -0
  72. package/dist/engine/constants.js +148 -0
  73. package/dist/engine/editor.d.ts +186 -0
  74. package/dist/engine/editor.js +734 -0
  75. package/dist/engine/events.d.ts +34 -0
  76. package/dist/engine/events.js +7 -0
  77. package/dist/engine/extensions/curved-text.d.ts +59 -0
  78. package/dist/engine/fabric.d.ts +4 -0
  79. package/dist/engine/fabric.js +187 -0
  80. package/dist/engine/history.d.ts +27 -0
  81. package/dist/engine/history.js +56 -0
  82. package/dist/engine/managers/event.d.ts +101 -0
  83. package/dist/engine/managers/event.js +410 -0
  84. package/dist/engine/managers/resize.d.ts +24 -0
  85. package/dist/engine/managers/resize.js +63 -0
  86. package/dist/engine/managers/snapline.d.ts +70 -0
  87. package/dist/engine/managers/snapline.js +124 -0
  88. package/dist/engine/managers/workspace.d.ts +26 -0
  89. package/dist/engine/managers/workspace.js +53 -0
  90. package/dist/engine/processors/image.d.ts +88 -0
  91. package/dist/engine/processors/image.js +473 -0
  92. package/dist/engine/processors/template.d.ts +45 -0
  93. package/dist/engine/processors/template.js +314 -0
  94. package/dist/engine/processors/text.d.ts +74 -0
  95. package/dist/engine/processors/text.js +215 -0
  96. package/dist/engine/semi-export-editor.d.ts +199 -0
  97. package/dist/engine/types.d.ts +28 -0
  98. package/dist/engine/utils/common.d.ts +25 -0
  99. package/dist/engine/utils/common.js +68 -0
  100. package/dist/engine/utils/dialog.d.ts +25 -0
  101. package/dist/engine/utils/font.d.ts +5 -0
  102. package/dist/engine/utils/font.js +39 -0
  103. package/dist/engine/utils/image.d.ts +8 -0
  104. package/dist/engine/utils/image.js +50 -0
  105. package/dist/engine/utils/loading.d.ts +17 -0
  106. package/dist/engine/utils/loading.js +71 -0
  107. package/dist/engine/utils/measure.d.ts +6 -0
  108. package/dist/engine/utils/measure.js +6 -0
  109. package/dist/engine/utils/mockup.d.ts +59 -0
  110. package/dist/engine/utils/setting.d.ts +4 -0
  111. package/dist/engine/utils/setting.js +73 -0
  112. package/dist/fabric-types.d.ts +59 -0
  113. package/dist/full-designer.js +14 -0
  114. package/dist/hooks/pagination.d.ts +19 -0
  115. package/dist/hooks/use-adobe-express.d.ts +50 -0
  116. package/dist/hooks/use-before-unload.d.ts +1 -0
  117. package/dist/hooks/use-image-drop.d.ts +18 -0
  118. package/dist/hooks/use-oss-upload.d.ts +34 -0
  119. package/dist/hooks/use-screen.d.ts +1 -0
  120. package/dist/i18n/index.d.ts +12 -0
  121. package/dist/images/design/asset_empty.png +0 -0
  122. package/dist/images/design/design/background.svg +3 -0
  123. package/dist/images/design/design/color-picker.svg +15 -0
  124. package/dist/images/design/design/computer.svg +1 -0
  125. package/dist/images/design/design/copy.svg +1 -0
  126. package/dist/images/design/design/image.svg +10 -0
  127. package/dist/images/design/design/line.svg +1 -0
  128. package/dist/images/design/design/text.svg +1 -0
  129. package/dist/images/design/design/title.svg +1 -0
  130. package/dist/images/design/empty.png +0 -0
  131. package/dist/images/design/layer_empty.png +0 -0
  132. package/dist/images/design/menu/ai.svg +1 -0
  133. package/dist/images/design/menu/back.svg +4 -0
  134. package/dist/images/design/menu/background.svg +6 -0
  135. package/dist/images/design/menu/clipart.svg +6 -0
  136. package/dist/images/design/menu/file.svg +4 -0
  137. package/dist/images/design/menu/fill.svg +1 -0
  138. package/dist/images/design/menu/image.svg +7 -0
  139. package/dist/images/design/menu/layer.svg +6 -0
  140. package/dist/images/design/menu/product.svg +3 -0
  141. package/dist/images/design/menu/sca.svg +5 -0
  142. package/dist/images/design/menu/shapes.svg +5 -0
  143. package/dist/images/design/menu/templates.svg +6 -0
  144. package/dist/images/design/menu/text.svg +6 -0
  145. package/dist/images/design/menu/uploads.svg +7 -0
  146. package/dist/images/design/spinner.svg +3 -0
  147. package/dist/images/design/spinners.svg +17 -0
  148. package/dist/images/design/transparent_pattern.svg +5 -0
  149. package/dist/index.d.ts +39 -0
  150. package/dist/index.js +127 -0
  151. package/dist/lib/analytics.d.ts +17 -0
  152. package/dist/lib/cn.d.ts +3 -0
  153. package/dist/lib/common.d.ts +16 -0
  154. package/dist/lib/config.d.ts +14 -0
  155. package/dist/lib/navigation.d.ts +2 -0
  156. package/dist/renderer/ThreeDPreview.d.ts +14 -0
  157. package/dist/renderer/sticker.js +1731 -0
  158. package/dist/renderer/three-d-preview.js +32 -0
  159. package/dist/state/designer-store.d.ts +43 -0
  160. package/dist/state/designer-store.js +85 -0
  161. package/dist/style.css +1 -0
  162. package/dist/types.d.ts +184 -0
  163. package/dist/ui/accordion.d.ts +7 -0
  164. package/dist/ui/button-group.d.ts +11 -0
  165. package/dist/ui/button.d.ts +10 -0
  166. package/dist/ui/checkbox.d.ts +4 -0
  167. package/dist/ui/command.d.ts +18 -0
  168. package/dist/ui/confirm-dialog.d.ts +15 -0
  169. package/dist/ui/context-menu.d.ts +25 -0
  170. package/dist/ui/dialog.d.ts +15 -0
  171. package/dist/ui/drawer.d.ts +15 -0
  172. package/dist/ui/editable-combobox.d.ts +10 -0
  173. package/dist/ui/hint.d.ts +8 -0
  174. package/dist/ui/image.d.ts +24 -0
  175. package/dist/ui/input-group.d.ts +16 -0
  176. package/dist/ui/input-with-addon.d.ts +17 -0
  177. package/dist/ui/input.d.ts +3 -0
  178. package/dist/ui/label.d.ts +4 -0
  179. package/dist/ui/loading-button.d.ts +15 -0
  180. package/dist/ui/popover.d.ts +9 -0
  181. package/dist/ui/scroll-area.d.ts +5 -0
  182. package/dist/ui/select.d.ts +22 -0
  183. package/dist/ui/separator.d.ts +4 -0
  184. package/dist/ui/shared-loading-button.d.ts +20 -0
  185. package/dist/ui/simple-dialog.d.ts +19 -0
  186. package/dist/ui/simple-popover.d.ts +13 -0
  187. package/dist/ui/simple-select.d.ts +20 -0
  188. package/dist/ui/skeleton.d.ts +2 -0
  189. package/dist/ui/slider.d.ts +4 -0
  190. package/dist/ui/spinner-box.d.ts +12 -0
  191. package/dist/ui/spinner.d.ts +2 -0
  192. package/dist/ui/switch.d.ts +6 -0
  193. package/dist/ui/tab/index.d.ts +15 -0
  194. package/dist/ui/textarea.d.ts +3 -0
  195. package/dist/ui/tooltip.d.ts +7 -0
  196. package/dist/workers/image-resize.worker.d.ts +1 -0
  197. package/dist/workers/mockup.worker.d.ts +5 -0
  198. package/dist/workers/render.worker.d.ts +1 -0
  199. package/package.json +201 -0
@@ -0,0 +1,101 @@
1
+ import { fabric } from 'fabric';
2
+ import '../fabric-types';
3
+ import type { Mockup, TemplateBaseInfo } from '../contracts/api-design';
4
+ import type { FontStyle } from '../contracts/design';
5
+ export type CanvasDesignState = Record<string, unknown> & {
6
+ objects?: unknown[];
7
+ background?: string;
8
+ };
9
+ export interface CanvasDesignerOptions {
10
+ canvas: HTMLCanvasElement;
11
+ width: number;
12
+ height: number;
13
+ overlayScale?: number;
14
+ onChange?: () => void;
15
+ }
16
+ export interface PlacementPreviewOptions {
17
+ placements: Mockup[];
18
+ designData: Record<string, CanvasDesignState>;
19
+ backgroundColor?: string;
20
+ width?: number;
21
+ height?: number;
22
+ }
23
+ /**
24
+ * Framework-independent Fabric runtime used by `PrintineDesigner`.
25
+ *
26
+ * It deliberately stores the same Fabric JSON shape that the existing
27
+ * `products/design-save` endpoint already receives, so a host never needs to
28
+ * translate editor data before saving it.
29
+ */
30
+ export declare class CanvasDesigner {
31
+ readonly canvas: fabric.Canvas;
32
+ private readonly onChange?;
33
+ private readonly overlayScale;
34
+ private placement?;
35
+ private placementStates;
36
+ private history;
37
+ private future;
38
+ private isRestoring;
39
+ private cropTarget?;
40
+ private cropRect?;
41
+ constructor({ canvas, width, height, overlayScale, onChange }: CanvasDesignerOptions);
42
+ get activeObject(): fabric.Object | null;
43
+ get currentPlacement(): Mockup | undefined;
44
+ get isCropping(): boolean;
45
+ resize(width: number, height: number): void;
46
+ switchPlacement(placement: Mockup, color?: string, state?: CanvasDesignState): Promise<void>;
47
+ setBackground(color: string): Promise<void>;
48
+ addText(config?: {
49
+ text?: string;
50
+ fontFamily?: string;
51
+ fontSize?: number;
52
+ fill?: string;
53
+ fontPath?: string;
54
+ fontWeight?: number;
55
+ fontStyle?: FontStyle;
56
+ }): Promise<fabric.AdvancedIText>;
57
+ addImage(url: string, name?: string): Promise<fabric.Image>;
58
+ addSvg(url: string, name?: string): Promise<fabric.Group>;
59
+ addFile(file: File): Promise<fabric.Image | fabric.Group>;
60
+ /** Adds a saved Printine template without converting its existing JSON contract. */
61
+ addTemplate(template: TemplateBaseInfo): Promise<void>;
62
+ deleteActive(): void;
63
+ /** Starts a non-destructive Fabric clip-path crop for the selected bitmap image. */
64
+ beginCrop(): boolean;
65
+ applyCrop(): boolean;
66
+ cancelCrop(): boolean;
67
+ duplicateActive(): void;
68
+ bringForward(): void;
69
+ sendBackwards(): void;
70
+ setActiveFill(fill: string): void;
71
+ setActiveTextStyle(config: {
72
+ fontFamily: string;
73
+ fontPath?: string;
74
+ fontWeight?: number;
75
+ fontStyle?: FontStyle;
76
+ }): Promise<boolean>;
77
+ setActiveTextCurve(radius: number, spacing?: number): boolean;
78
+ getDesignData(): {
79
+ [k: string]: CanvasDesignState;
80
+ };
81
+ setDesignData(data: Record<string, CanvasDesignState>): void;
82
+ exportPreview(): string;
83
+ undo(): Promise<void>;
84
+ redo(): Promise<void>;
85
+ destroy(): void;
86
+ private renderOverlay;
87
+ private placeImage;
88
+ private persistCurrentPlacement;
89
+ private readState;
90
+ private serializeCanvas;
91
+ private recordChange;
92
+ private restoreSerialized;
93
+ private loadState;
94
+ private removeCropRect;
95
+ }
96
+ /**
97
+ * Renders every printable placement in an offscreen Fabric canvas. The result
98
+ * is keyed by both placement name and id so it can feed existing 2D and 3D
99
+ * render area contracts without a host-side translation layer.
100
+ */
101
+ export declare function renderPlacementPreviews({ placements, designData, backgroundColor, width, height, }: PlacementPreviewOptions): Promise<Record<string, string>>;
@@ -0,0 +1,313 @@
1
+ import { fabric as h } from "fabric";
2
+ import { loadImage as d, loadSvgImage as f, loadOverlaySvgImage as p } from "./utils/image.js";
3
+ import { setDefaultControls as m } from "./utils/setting.js";
4
+ import { loadFontface as u } from "./utils/font.js";
5
+ class y {
6
+ constructor({ canvas: t, width: e, height: s, overlayScale: i = 0.85, onChange: n }) {
7
+ this.placementStates = /* @__PURE__ */ new Map(), this.history = [], this.future = [], this.isRestoring = !1, m(), this.canvas = new h.Canvas(t, {
8
+ enableRetinaScaling: !0,
9
+ width: e,
10
+ height: s,
11
+ preserveObjectStacking: !0,
12
+ centeredRotation: !0,
13
+ hoverCursor: "grab",
14
+ moveCursor: "grabbing",
15
+ selection: !0,
16
+ controlsAboveOverlay: !0,
17
+ fireRightClick: !0
18
+ }), this.onChange = n, this.overlayScale = i;
19
+ const a = () => this.recordChange();
20
+ this.canvas.on("object:added", a), this.canvas.on("object:modified", a), this.canvas.on("object:removed", a), this.canvas.on("text:changed", a), this.recordChange();
21
+ }
22
+ get activeObject() {
23
+ return this.canvas.getActiveObject();
24
+ }
25
+ get currentPlacement() {
26
+ return this.placement;
27
+ }
28
+ get isCropping() {
29
+ return !!this.cropRect;
30
+ }
31
+ resize(t, e) {
32
+ this.canvas.setDimensions({ width: t, height: e }), this.placement && this.renderOverlay(this.placement);
33
+ }
34
+ async switchPlacement(t, e = "", s) {
35
+ this.cropRect && this.applyCrop(), this.persistCurrentPlacement(), this.placement = t, this.isRestoring = !0, this.canvas.clear(), await this.setBackground(e), await this.renderOverlay(t);
36
+ const i = s ?? this.placementStates.get(t.name);
37
+ i && await this.loadState(i, !1), this.history = [this.serializeCanvas()], this.future = [], this.isRestoring = !1, this.onChange?.();
38
+ }
39
+ async setBackground(t) {
40
+ await new Promise((e) => this.canvas.setBackgroundColor(t || "transparent", () => e())), this.canvas.requestRenderAll();
41
+ }
42
+ async addText(t = {}) {
43
+ t.fontPath && t.fontFamily && await u({
44
+ family: t.fontFamily,
45
+ url: t.fontPath,
46
+ weight: t.fontWeight || 400,
47
+ style: t.fontStyle || "normal"
48
+ });
49
+ const e = new h.AdvancedIText(t.text || "Entry Text", {
50
+ left: this.canvas.getWidth() / 2,
51
+ top: this.canvas.getHeight() / 2,
52
+ originX: "center",
53
+ originY: "center",
54
+ fontFamily: t.fontFamily || "Arial",
55
+ fontWeight: t.fontWeight || 400,
56
+ fontStyle: t.fontStyle || "normal",
57
+ fontPath: t.fontPath || "",
58
+ fontSize: t.fontSize || 32,
59
+ fill: t.fill || "#111827",
60
+ editable: !0
61
+ });
62
+ return this.canvas.add(e), this.canvas.setActiveObject(e), this.canvas.requestRenderAll(), e.enterEditing().selectAll(), e;
63
+ }
64
+ async addImage(t, e) {
65
+ const s = await d(t);
66
+ return this.placeImage(s, t, e), s;
67
+ }
68
+ async addSvg(t, e) {
69
+ const s = await f(t);
70
+ return this.placeImage(s, t, e), s;
71
+ }
72
+ async addFile(t) {
73
+ const e = await new Promise((s, i) => {
74
+ const n = new FileReader();
75
+ n.onload = () => s(String(n.result)), n.onerror = () => i(n.error || new Error("Unable to read image file")), n.readAsDataURL(t);
76
+ });
77
+ return t.type === "image/svg+xml" || t.name.toLowerCase().endsWith(".svg") ? this.addSvg(e, t.name) : this.addImage(e, t.name);
78
+ }
79
+ /** Adds a saved Printine template without converting its existing JSON contract. */
80
+ async addTemplate(t) {
81
+ if (!t.areaWidth || !t.areaHeight) return;
82
+ const e = Math.min(
83
+ 1,
84
+ this.canvas.getWidth() * 0.7 / t.areaWidth,
85
+ this.canvas.getHeight() * 0.7 / t.areaHeight
86
+ ), s = (this.canvas.getWidth() - t.areaWidth * e) / 2, i = (this.canvas.getHeight() - t.areaHeight * e) / 2, n = [];
87
+ for (const a of t.elements) {
88
+ const r = a.position;
89
+ if (a.text) {
90
+ const l = await this.addText({
91
+ text: a.text.text,
92
+ fontFamily: a.text.fontFamily,
93
+ fontPath: a.text.fontPath,
94
+ fontWeight: typeof a.text.fontWeight == "number" ? a.text.fontWeight : Number(a.text.fontWeight) || 400,
95
+ fontStyle: a.text.fontStyle,
96
+ fontSize: Math.max(8, a.text.fontSize * e),
97
+ fill: a.text.color
98
+ });
99
+ l.set({
100
+ left: s + r.left * e,
101
+ top: i + r.top * e,
102
+ originX: "left",
103
+ originY: "top",
104
+ angle: r.rotation || 0,
105
+ scaleX: e,
106
+ scaleY: e
107
+ }), n.push(l);
108
+ continue;
109
+ }
110
+ if (!a.image?.url) continue;
111
+ const c = a.image.url, o = c.toLowerCase().includes(".svg") || c.startsWith("data:image/svg") ? await f(c) : await d(c);
112
+ o.set({
113
+ left: s + r.left * e,
114
+ top: i + r.top * e,
115
+ originX: "left",
116
+ originY: "top",
117
+ angle: r.rotation || 0,
118
+ scaleX: e,
119
+ scaleY: e,
120
+ flipX: a.image.flipX || !1,
121
+ flipY: a.image.flipY || !1,
122
+ originSrc: c
123
+ }), this.canvas.add(o), n.push(o);
124
+ }
125
+ n.length > 1 ? this.canvas.setActiveObject(new h.ActiveSelection(n, { canvas: this.canvas })) : n[0] && this.canvas.setActiveObject(n[0]), this.canvas.requestRenderAll();
126
+ }
127
+ deleteActive() {
128
+ const t = this.canvas.getActiveObjects();
129
+ t.length && (t.forEach((e) => this.canvas.remove(e)), this.canvas.discardActiveObject(), this.canvas.requestRenderAll());
130
+ }
131
+ /** Starts a non-destructive Fabric clip-path crop for the selected bitmap image. */
132
+ beginCrop() {
133
+ const t = this.canvas.getActiveObject();
134
+ if (!t || t.type !== "image" || this.cropRect) return !1;
135
+ const e = t, s = e.getBoundingRect(!0, !0), i = new h.Rect({
136
+ left: s.left,
137
+ top: s.top,
138
+ width: s.width,
139
+ height: s.height,
140
+ fill: "rgba(53, 64, 165, 0.08)",
141
+ stroke: "#3540a5",
142
+ strokeWidth: 2,
143
+ strokeDashArray: [6, 4],
144
+ originX: "left",
145
+ originY: "top",
146
+ lockRotation: !0,
147
+ name: "__printine_crop__",
148
+ excludeFromExport: !0
149
+ });
150
+ return e.set({ selectable: !1, evented: !1 }), this.cropTarget = e, this.cropRect = i, this.canvas.add(i), this.canvas.setActiveObject(i), this.canvas.requestRenderAll(), !0;
151
+ }
152
+ applyCrop() {
153
+ const t = this.cropTarget, e = this.cropRect;
154
+ if (!t || !e) return !1;
155
+ const s = new h.Rect({
156
+ left: e.left,
157
+ top: e.top,
158
+ width: e.width,
159
+ height: e.height,
160
+ scaleX: e.scaleX,
161
+ scaleY: e.scaleY,
162
+ angle: e.angle,
163
+ originX: e.originX,
164
+ originY: e.originY,
165
+ selectable: !1,
166
+ evented: !1,
167
+ fill: "#000",
168
+ absolutePositioned: !0
169
+ });
170
+ return t.set({ clipPath: s, selectable: !0, evented: !0 }), this.removeCropRect(), this.canvas.setActiveObject(t), this.canvas.requestRenderAll(), this.recordChange(), !0;
171
+ }
172
+ cancelCrop() {
173
+ const t = this.cropTarget;
174
+ return !this.cropRect || !t ? !1 : (t.set({ selectable: !0, evented: !0 }), this.removeCropRect(), this.canvas.setActiveObject(t), this.canvas.requestRenderAll(), !0);
175
+ }
176
+ duplicateActive() {
177
+ const t = this.canvas.getActiveObject();
178
+ t && t.clone((e) => {
179
+ e.set({ left: (e.left || 0) + 16, top: (e.top || 0) + 16 }), this.canvas.add(e), this.canvas.setActiveObject(e), this.canvas.requestRenderAll();
180
+ }, ["id", "originSrc", "fontPath", "radius", "spacing"]);
181
+ }
182
+ bringForward() {
183
+ const t = this.canvas.getActiveObject();
184
+ t && this.canvas.bringForward(t), this.canvas.requestRenderAll();
185
+ }
186
+ sendBackwards() {
187
+ const t = this.canvas.getActiveObject();
188
+ t && this.canvas.sendBackwards(t), this.canvas.requestRenderAll();
189
+ }
190
+ setActiveFill(t) {
191
+ const e = this.canvas.getActiveObject();
192
+ e && (e.set("fill", t), this.canvas.requestRenderAll(), this.recordChange());
193
+ }
194
+ async setActiveTextStyle(t) {
195
+ const e = this.canvas.getActiveObject();
196
+ return !e || !e.type?.includes("text") ? !1 : (t.fontPath && await u({
197
+ family: t.fontFamily,
198
+ url: t.fontPath,
199
+ weight: t.fontWeight || 400,
200
+ style: t.fontStyle || "normal"
201
+ }), e.set({
202
+ fontFamily: t.fontFamily,
203
+ fontPath: t.fontPath || "",
204
+ fontWeight: t.fontWeight || 400,
205
+ fontStyle: t.fontStyle || "normal"
206
+ }), this.canvas.requestRenderAll(), this.recordChange(), !0);
207
+ }
208
+ setActiveTextCurve(t, e = 0) {
209
+ const s = this.canvas.getActiveObject();
210
+ return !s || s.type !== "advanced-i-text" ? !1 : (s.set({ radius: t, spacing: e }), s.setCoords(), this.canvas.requestRenderAll(), this.recordChange(), !0);
211
+ }
212
+ getDesignData() {
213
+ return this.cropRect && this.applyCrop(), this.persistCurrentPlacement(), Object.fromEntries(this.placementStates.entries());
214
+ }
215
+ setDesignData(t) {
216
+ this.placementStates = new Map(Object.entries(t));
217
+ }
218
+ exportPreview() {
219
+ return this.canvas.toDataURL({ format: "png", multiplier: 2, enableRetinaScaling: !0 });
220
+ }
221
+ async undo() {
222
+ if (this.history.length < 2) return;
223
+ const t = this.history.pop();
224
+ t && this.future.push(t);
225
+ const e = this.history[this.history.length - 1];
226
+ e && await this.restoreSerialized(e);
227
+ }
228
+ async redo() {
229
+ const t = this.future.pop();
230
+ t && (this.history.push(t), await this.restoreSerialized(t));
231
+ }
232
+ destroy() {
233
+ this.cancelCrop(), this.placementStates.clear(), this.history = [], this.future = [], this.canvas.dispose();
234
+ }
235
+ async renderOverlay(t) {
236
+ const { image: e } = await p(t.image), s = Math.min(this.canvas.getWidth(), this.canvas.getHeight()) * this.overlayScale, i = Math.min(s / (e.width || 1), s / (e.height || 1));
237
+ e.set({
238
+ scaleX: i,
239
+ scaleY: i,
240
+ left: (this.canvas.getWidth() - (e.width || 0) * i) / 2,
241
+ top: (this.canvas.getHeight() - (e.height || 0) * i) / 2,
242
+ selectable: !1,
243
+ evented: !1
244
+ }), await new Promise((n) => this.canvas.setOverlayImage(e, () => n())), this.canvas.requestRenderAll();
245
+ }
246
+ placeImage(t, e, s) {
247
+ const i = Math.min(this.canvas.getWidth(), this.canvas.getHeight()) * 0.55, n = t.width || i, a = t.height || i, r = Math.min(1, i / Math.max(n, a));
248
+ t.set({
249
+ left: this.canvas.getWidth() / 2,
250
+ top: this.canvas.getHeight() / 2,
251
+ originX: "center",
252
+ originY: "center",
253
+ scaleX: r,
254
+ scaleY: r,
255
+ name: s || e.split("/").pop() || "image",
256
+ originSrc: e
257
+ }), this.canvas.add(t), this.canvas.setActiveObject(t), this.canvas.requestRenderAll();
258
+ }
259
+ persistCurrentPlacement() {
260
+ this.placement && this.placementStates.set(this.placement.name, this.readState());
261
+ }
262
+ readState() {
263
+ return {
264
+ ...this.canvas.toJSON(["id", "name", "originSrc", "fontPath", "radius", "spacing"]),
265
+ color: typeof this.canvas.backgroundColor == "string" ? this.canvas.backgroundColor : ""
266
+ };
267
+ }
268
+ serializeCanvas() {
269
+ return JSON.stringify(this.readState());
270
+ }
271
+ recordChange() {
272
+ if (this.isRestoring || this.cropRect) return;
273
+ const t = this.serializeCanvas();
274
+ this.history[this.history.length - 1] !== t && (this.history.push(t), this.history.length > 50 && this.history.shift(), this.future = []), this.persistCurrentPlacement(), this.onChange?.();
275
+ }
276
+ async restoreSerialized(t) {
277
+ await this.loadState(JSON.parse(t), !0), this.persistCurrentPlacement(), this.onChange?.();
278
+ }
279
+ async loadState(t, e) {
280
+ this.isRestoring = !0;
281
+ const s = e ? this.canvas.overlayImage : void 0;
282
+ await new Promise((i) => this.canvas.loadFromJSON(t, () => i())), s && this.canvas.setOverlayImage(s, () => {
283
+ }), await this.setBackground(typeof t.color == "string" ? t.color : ""), this.canvas.requestRenderAll(), this.isRestoring = !1;
284
+ }
285
+ removeCropRect() {
286
+ this.cropRect && this.canvas.remove(this.cropRect), this.cropRect = void 0, this.cropTarget = void 0;
287
+ }
288
+ }
289
+ async function A({
290
+ placements: v,
291
+ designData: t,
292
+ backgroundColor: e = "",
293
+ width: s = 900,
294
+ height: i = 900
295
+ }) {
296
+ const n = document.createElement("canvas"), a = new y({ canvas: n, width: s, height: i, overlayScale: 0.85 }), r = {};
297
+ try {
298
+ a.setDesignData(t);
299
+ for (const c of v) {
300
+ const o = t[c.name], l = typeof o?.color == "string" ? o.color : e;
301
+ await a.switchPlacement(c, l, o);
302
+ const g = a.exportPreview();
303
+ r[c.name] = g, r[String(c.id)] = g;
304
+ }
305
+ return r;
306
+ } finally {
307
+ a.destroy();
308
+ }
309
+ }
310
+ export {
311
+ y as CanvasDesigner,
312
+ A as renderPlacementPreviews
313
+ };
@@ -0,0 +1,27 @@
1
+ import type { DesignerElementType } from './types';
2
+ import { BLEND_MODES } from 'pixi.js';
3
+ /** Fabric helper objects that must never be exposed as editable design layers. */
4
+ export declare const LAYER_BLACK_LIST: string[];
5
+ /** Text sizes offered by the toolbar, expressed as a fraction of the print area. */
6
+ export declare const DEFAULT_FONT_SIZE: number[];
7
+ export declare const ALIGN_TYPES: ('left' | 'center' | 'right')[];
8
+ /** Human labels for the font weight/style variants returned by the fonts endpoint. */
9
+ export declare const FONT_WEIGHT: Record<string, string>;
10
+ export declare const DEFAULT_FILL_COLOR_LIST: string[];
11
+ /** Pixi blend modes accepted by mockup render-area configuration. */
12
+ export declare const BLEND_MODES_MAP: {
13
+ normal: BLEND_MODES;
14
+ multiply: BLEND_MODES;
15
+ screen: BLEND_MODES;
16
+ overlay: BLEND_MODES;
17
+ 'soft-light': BLEND_MODES;
18
+ 'hard-light': BLEND_MODES;
19
+ 'color-dodge': BLEND_MODES;
20
+ 'color-burn': BLEND_MODES;
21
+ darken: BLEND_MODES;
22
+ lighten: BLEND_MODES;
23
+ difference: BLEND_MODES;
24
+ exclusion: BLEND_MODES;
25
+ };
26
+ /** Panel titles for each editor tool. */
27
+ export declare const ELEMENT_TITLE_MAP: Record<DesignerElementType, string>;
@@ -0,0 +1,148 @@
1
+ import { BLEND_MODES as E } from "pixi.js";
2
+ const t = ["cropRect", "cropOverlay", "workspace", "loading", "bg"], i = [0.01, 0.02, 0.03, 0.04, 0.05, 0.07, 0.09, 0.1, 0.12], a = ["left", "center", "right"], l = {
3
+ 100: "Thin",
4
+ 200: "Extra Light",
5
+ 300: "Light",
6
+ 400: "Regular",
7
+ 500: "Medium",
8
+ 600: "Semi Bold",
9
+ 700: "Bold",
10
+ 800: "Extra Bold",
11
+ 900: "Black",
12
+ "100italic": "Thin Italic",
13
+ "200italic": "Extra Light Italic",
14
+ "300italic": "Light Italic",
15
+ "400italic": "Italic",
16
+ "500italic": "Medium Italic",
17
+ "600italic": "Semi Bold Italic",
18
+ "700italic": "Bold Italic",
19
+ "800italic": "Extra Bold Italic",
20
+ "900italic": "Black Italic"
21
+ }, B = [
22
+ "#000000",
23
+ "#FFFFFF",
24
+ "#FAFAFA",
25
+ "#F5F5F5",
26
+ "#EEEEEE",
27
+ "#E0E0E0",
28
+ "#BDBDBD",
29
+ "#9E9E9E",
30
+ "#757575",
31
+ "#616161",
32
+ "#424242",
33
+ "#FFEbEE",
34
+ "#FFCDD2",
35
+ "#EF9A9A",
36
+ "#E57373",
37
+ "#EF5350",
38
+ "#F44336",
39
+ "#E53935",
40
+ "#D32F2F",
41
+ "#C62828",
42
+ "#B71C1C",
43
+ "#FCE4EC",
44
+ "#F8BBD9",
45
+ "#F48FB1",
46
+ "#F06292",
47
+ "#EC407A",
48
+ "#E91E63",
49
+ "#D81B60",
50
+ "#C2185B",
51
+ "#AD1457",
52
+ "#880E4F",
53
+ "#FFF3E0",
54
+ "#FFE0B2",
55
+ "#FFCC80",
56
+ "#FFB74D",
57
+ "#FFA726",
58
+ "#FF9800",
59
+ "#FB8C00",
60
+ "#F57C00",
61
+ "#EF6C00",
62
+ "#E65100",
63
+ "#EFEBE9",
64
+ "#D7CCC8",
65
+ "#BCAAA4",
66
+ "#A1887F",
67
+ "#8D6E63",
68
+ "#795548",
69
+ "#6D4C41",
70
+ "#5D4037",
71
+ "#4E342E",
72
+ "#3E2723",
73
+ "#E8F5E8",
74
+ "#C8E6C9",
75
+ "#A5D6A7",
76
+ "#81C784",
77
+ "#66BB6A",
78
+ "#4CAF50",
79
+ "#43A047",
80
+ "#388E3C",
81
+ "#2E7D32",
82
+ "#1B5E20",
83
+ "#E0F2F1",
84
+ "#B2DFDB",
85
+ "#80CBC4",
86
+ "#4DB6AC",
87
+ "#26A69A",
88
+ "#009688",
89
+ "#00897B",
90
+ "#00796B",
91
+ "#00695C",
92
+ "#004D40",
93
+ "#E3F2FD",
94
+ "#BBDEFB",
95
+ "#90CAF9",
96
+ "#64B5F6",
97
+ "#42A5F5",
98
+ "#2196F3",
99
+ "#1E88E5",
100
+ "#1976D2",
101
+ "#1565C0",
102
+ "#0D47A1",
103
+ "#F3E5F5",
104
+ "#E1BEE7",
105
+ "#CE93D8",
106
+ "#BA68C8",
107
+ "#AB47BC",
108
+ "#9C27B0",
109
+ "#8E24AA",
110
+ "#7B1FA2",
111
+ "#6A1B9A",
112
+ "#4A148C"
113
+ ], c = {
114
+ normal: E.NORMAL,
115
+ multiply: E.MULTIPLY,
116
+ screen: E.SCREEN,
117
+ overlay: E.OVERLAY,
118
+ "soft-light": E.SOFT_LIGHT,
119
+ "hard-light": E.HARD_LIGHT,
120
+ "color-dodge": E.COLOR_DODGE,
121
+ "color-burn": E.COLOR_BURN,
122
+ darken: E.DARKEN,
123
+ lighten: E.LIGHTEN,
124
+ difference: E.DIFFERENCE,
125
+ exclusion: E.EXCLUSION
126
+ }, e = {
127
+ product: "Product information",
128
+ shapes: "Shapes",
129
+ images: "Upload images",
130
+ text: "Text",
131
+ textEffects: "Text effects",
132
+ layer: "Layers",
133
+ templates: "Designs",
134
+ clipart: "Clipart",
135
+ ai: "AI image generator",
136
+ files: "My files",
137
+ background: "Background color",
138
+ sca: "Custom"
139
+ };
140
+ export {
141
+ a as ALIGN_TYPES,
142
+ c as BLEND_MODES_MAP,
143
+ B as DEFAULT_FILL_COLOR_LIST,
144
+ i as DEFAULT_FONT_SIZE,
145
+ e as ELEMENT_TITLE_MAP,
146
+ l as FONT_WEIGHT,
147
+ t as LAYER_BLACK_LIST
148
+ };