@pooder/vue 4.2.3 → 4.2.5

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/index.es.js CHANGED
@@ -1,119 +1,143 @@
1
- import { defineComponent as T, ref as M, onMounted as U, onUnmounted as E, createElementBlock as B, openBlock as O, createElementVNode as V, provide as G, createVNode as J } from "vue";
2
- import { Pooder as $ } from "@pooder/core";
1
+ import { defineComponent as O, ref as M, onMounted as K, onUnmounted as Y, createElementBlock as R, openBlock as X, createElementVNode as Q, provide as Z, createVNode as ee } from "vue";
2
+ import { Pooder as te } from "@pooder/core";
3
3
  export * from "@pooder/core";
4
- import { CanvasService as q, BackgroundTool as K, SizeTool as Q, SceneLayoutService as Z, SceneVisibilityService as ee, ImageTool as te, WhiteInkTool as ne, MirrorTool as ae, DielineTool as ie, RulerTool as oe, FeatureTool as ce } from "@pooder/kit";
4
+ import { CanvasService as ne, SceneLayoutService as ie, SceneVisibilityService as oe, BackgroundTool as ae, SizeTool as re, ImageTool as ce, WhiteInkTool as se, MirrorTool as de, DielineTool as ue, RulerTool as me, FeatureTool as ge } from "@pooder/kit";
5
5
  export * from "@pooder/kit";
6
- const re = /* @__PURE__ */ T({
6
+ const le = /* @__PURE__ */ O({
7
7
  __name: "CanvasArea",
8
8
  emits: ["canvas-ready", "resize"],
9
9
  setup(p, { emit: v }) {
10
- const u = v, o = M(null), r = M(null);
11
- let s = null;
12
- return U(() => {
13
- if (o.value && r.value) {
14
- const { clientWidth: h, clientHeight: w } = o.value;
15
- r.value.width = h, r.value.height = w, u("canvas-ready", r.value), s = new ResizeObserver((C) => {
16
- for (const b of C) {
10
+ const g = v, a = M(null), c = M(null);
11
+ let d = null;
12
+ return K(() => {
13
+ if (a.value && c.value) {
14
+ const { clientWidth: f, clientHeight: C } = a.value;
15
+ c.value.width = f, c.value.height = C, g("canvas-ready", c.value), d = new ResizeObserver((w) => {
16
+ for (const b of w) {
17
17
  const { width: S, height: x } = b.contentRect;
18
- u("resize", S, x);
18
+ g("resize", S, x);
19
19
  }
20
- }), s.observe(o.value);
20
+ }), d.observe(a.value);
21
21
  }
22
- }), E(() => {
23
- s && s.disconnect();
24
- }), (h, w) => (O(), B("div", {
22
+ }), Y(() => {
23
+ d && d.disconnect();
24
+ }), (f, C) => (X(), R("div", {
25
25
  ref_key: "container",
26
- ref: o,
26
+ ref: a,
27
27
  class: "pooder-canvas-area"
28
28
  }, [
29
- V("canvas", {
29
+ Q("canvas", {
30
30
  ref_key: "canvas",
31
- ref: r
31
+ ref: c
32
32
  }, null, 512)
33
33
  ], 512));
34
34
  }
35
- }), k = (p, v) => {
36
- const u = p.__vccOpts || p;
37
- for (const [o, r] of v)
38
- u[o] = r;
39
- return u;
40
- }, se = /* @__PURE__ */ k(re, [["__scopeId", "data-v-dc60e8d6"]]), de = { class: "pooder-editor" }, me = "image.user", ue = /* @__PURE__ */ T({
35
+ }), A = (p, v) => {
36
+ const g = p.__vccOpts || p;
37
+ for (const [a, c] of v)
38
+ g[a] = c;
39
+ return g;
40
+ }, he = /* @__PURE__ */ A(le, [["__scopeId", "data-v-203ff8d9"]]), fe = { class: "pooder-editor" }, T = "SceneLayoutService", B = "SceneVisibilityService", ve = "image.user", pe = /* @__PURE__ */ O({
41
41
  __name: "PooderEditor",
42
42
  emits: ["image-change"],
43
- setup(p, { expose: v, emit: u }) {
44
- const o = new $();
45
- G("pooder", o);
46
- const r = o.getService("CommandService"), s = o.getService("ConfigurationService"), h = o.getService("WorkbenchService"), w = u, C = s.onAnyChange((e) => {
47
- e.key === "image.items" && w("image-change", e.value);
43
+ setup(p, { expose: v, emit: g }) {
44
+ const a = new te();
45
+ Z("pooder", a);
46
+ const c = a.getService("CommandService"), d = a.getService("ConfigurationService"), f = a.getService("WorkbenchService"), C = g, w = d.onAnyChange((e) => {
47
+ e.key === "image.items" && C("image-change", e.value);
48
48
  }), b = (e) => {
49
- s.import(e);
50
- }, S = () => s.export(), x = () => s.get("image.items", []), A = async (e) => {
49
+ d.import(e);
50
+ }, S = () => d.export(), x = () => d.get("image.items", []), k = async (e) => {
51
51
  try {
52
- const t = await r.executeCommand(
52
+ const t = await c.executeCommand(
53
53
  "exportCutImage",
54
54
  e
55
55
  );
56
56
  return t || console.warn("[PooderEditor] generateCutImage returned null", {
57
57
  options: e,
58
- imageCount: (s.get("image.items") || []).length,
59
- hasCanvasService: !!o.getService("CanvasService")
58
+ imageCount: (d.get("image.items") || []).length,
59
+ hasCanvasService: !!a.getService("CanvasService")
60
60
  }), t;
61
61
  } catch (t) {
62
62
  throw console.error("[PooderEditor] generateCutImage failed", t), t;
63
63
  }
64
- }, N = async (e, t) => await r.executeCommand("upsertImage", e, {
64
+ }, _ = async (e, t) => await c.executeCommand("upsertImage", e, {
65
65
  id: t?.id,
66
66
  mode: t?.mode,
67
- createIfMissing: t?.createIfMissing,
68
67
  addOptions: t?.addOptions,
69
68
  fitOnAdd: t?.fitOnAdd
70
- }), F = async (e, t) => (await N(e, {
69
+ }), I = async (e, t) => (await _(e, {
71
70
  mode: "add",
72
71
  addOptions: t,
73
72
  fitOnAdd: !0
74
- })).id, R = async (e, t) => await r.executeCommand("updateImage", e, t), z = async () => await r.executeCommand("clearImages"), D = (e) => Math.max(-1, Math.min(2, e)), X = (e) => {
73
+ })).id, W = async (e, t) => await c.executeCommand("updateImage", e, t), z = async () => await c.executeCommand("clearImages"), N = async (e) => await c.executeCommand(
74
+ "exportUserCroppedImage",
75
+ e
76
+ ), P = async (e, t) => await c.executeCommand("focusImage", e, t), D = (e) => Math.max(-1, Math.min(2, e)), H = (e) => {
75
77
  const t = e?.cutRect;
76
78
  if (!t) return null;
77
- const n = Number(t.width), a = Number(t.height), i = Number(t.left), c = Number(t.top);
78
- return !Number.isFinite(n) || !Number.isFinite(a) || !Number.isFinite(i) || !Number.isFinite(c) || n <= 0 || a <= 0 ? null : { left: i, top: c, width: n, height: a };
79
- }, y = (e) => {
79
+ const n = Number(t.width), i = Number(t.height), r = Number(t.left), o = Number(t.top);
80
+ return !Number.isFinite(n) || !Number.isFinite(i) || !Number.isFinite(r) || !Number.isFinite(o) || n <= 0 || i <= 0 ? null : { left: r, top: o, width: n, height: i };
81
+ }, E = (e) => {
80
82
  if (!e) return [];
81
83
  const t = e.canvas.getObjects(), n = [];
82
- for (const a of t) {
83
- if (a?.data?.layerId !== me) continue;
84
- const i = a?.data?.id;
85
- if (typeof i != "string") continue;
86
- const c = a.getCenterPoint ? a.getCenterPoint() : null, d = Number(c?.x ?? a.left), m = Number(c?.y ?? a.top), f = Number(a.scaleX), g = Number(a.width), l = Number(a.height);
87
- !Number.isFinite(d) || !Number.isFinite(m) || !Number.isFinite(f) || !Number.isFinite(g) || !Number.isFinite(l) || g <= 0 || l <= 0 || n.push({
88
- id: i,
89
- centerX: d,
90
- centerY: m,
91
- objectScale: f,
92
- sourceWidth: g,
93
- sourceHeight: l
84
+ for (const i of t) {
85
+ if (i?.data?.layerId !== ve) continue;
86
+ const r = i?.data?.id;
87
+ if (typeof r != "string") continue;
88
+ const o = i.getCenterPoint ? i.getCenterPoint() : null, s = Number(o?.x ?? i.left), u = Number(o?.y ?? i.top), m = Number(i.scaleX), l = Number(i.width), h = Number(i.height);
89
+ !Number.isFinite(s) || !Number.isFinite(u) || !Number.isFinite(m) || !Number.isFinite(l) || !Number.isFinite(h) || l <= 0 || h <= 0 || n.push({
90
+ id: r,
91
+ centerX: s,
92
+ centerY: u,
93
+ objectScale: m,
94
+ sourceWidth: l,
95
+ sourceHeight: h
94
96
  });
95
97
  }
96
98
  return n;
97
- }, _ = (e) => {
98
- s.update("dieline.shape", "custom"), s.update("dieline.pathData", e.pathData), s.update("size.cutMode", "trim"), s.update("size.cutMarginMm", 0);
99
- }, Y = (e, t) => {
100
- const n = e.rawBounds || e.baseBounds, a = Number(e.imageWidth ?? 0), i = Number(e.imageHeight ?? 0);
101
- if (!n || !Number.isFinite(n.x) || !Number.isFinite(n.y) || !Number.isFinite(n.width) || !Number.isFinite(n.height) || n.width <= 0 || n.height <= 0 || a <= 0 || i <= 0)
99
+ }, y = (e) => {
100
+ d.update("dieline.shape", "custom"), d.update("dieline.pathData", e.pathData), d.update("dieline.features", []), d.update("size.cutMode", "trim"), d.update("size.cutMarginMm", 0);
101
+ }, j = (e, t) => {
102
+ const n = e.rawBounds || e.baseBounds || null;
103
+ if (!n)
104
+ return {
105
+ sourceWidth: t.width,
106
+ sourceHeight: t.height,
107
+ detectedBounds: null,
108
+ centerOffsetX: 0,
109
+ centerOffsetY: 0,
110
+ coverageX: 0,
111
+ coverageY: 0
112
+ };
113
+ const i = t.width / 2, r = t.height / 2, o = n.x + n.width / 2, s = n.y + n.height / 2;
114
+ return {
115
+ sourceWidth: t.width,
116
+ sourceHeight: t.height,
117
+ detectedBounds: n,
118
+ centerOffsetX: o - i,
119
+ centerOffsetY: s - r,
120
+ coverageX: t.width > 0 ? n.width / t.width : 0,
121
+ coverageY: t.height > 0 ? n.height / t.height : 0
122
+ };
123
+ }, L = (e, t) => {
124
+ const n = e.rawBounds || e.baseBounds, i = Number(e.imageWidth ?? 0), r = Number(e.imageHeight ?? 0);
125
+ if (!n || !Number.isFinite(n.x) || !Number.isFinite(n.y) || !Number.isFinite(n.width) || !Number.isFinite(n.height) || n.width <= 0 || n.height <= 0 || i <= 0 || r <= 0)
102
126
  return { shiftX: 0, shiftY: 0 };
103
- const c = t.width / n.width, d = t.height / n.height, m = n.x + n.width / 2, f = n.y + n.height / 2, g = a / 2, l = i / 2;
127
+ const o = t.width / n.width, s = t.height / n.height, u = n.x + n.width / 2, m = n.y + n.height / 2, l = i / 2, h = r / 2;
104
128
  return {
105
- shiftX: (m - g) * c,
106
- shiftY: (f - l) * d
129
+ shiftX: (u - l) * o,
130
+ shiftY: (m - h) * s
107
131
  };
108
- }, I = async (e, t, n = !1) => {
132
+ }, F = async (e, t, n = !1, i = "auto") => {
109
133
  if (!t.length) return;
110
- const a = await r.executeCommand("getSceneLayout"), i = X(a);
111
- if (!i) return;
112
- const { shiftX: c, shiftY: d } = Y(e, i);
134
+ const r = await c.executeCommand("getSceneLayout"), o = H(r);
135
+ if (!o) return;
136
+ const { shiftX: s, shiftY: u } = L(e, o);
113
137
  n && console.info("[PooderEditor] detectDieline alignment", {
114
- frame: i,
115
- shiftX: c,
116
- shiftY: d,
138
+ frame: o,
139
+ shiftX: s,
140
+ shiftY: u,
117
141
  snapshotCount: t.length,
118
142
  baseBounds: e.baseBounds,
119
143
  rawBounds: e.rawBounds,
@@ -121,32 +145,41 @@ const re = /* @__PURE__ */ T({
121
145
  imageHeight: e.imageHeight
122
146
  });
123
147
  for (const m of t) {
124
- const f = Math.max(
125
- i.width / Math.max(1, m.sourceWidth),
126
- i.height / Math.max(1, m.sourceHeight)
127
- ), g = Math.max(0.05, m.objectScale / f), l = m.centerX - c, P = m.centerY - d, H = D(
128
- (l - i.left) / Math.max(1, i.width)
129
- ), L = D(
130
- (P - i.top) / Math.max(1, i.height)
148
+ const l = Math.max(
149
+ o.width / Math.max(1, m.sourceWidth),
150
+ o.height / Math.max(1, m.sourceHeight)
151
+ ), h = Math.max(0.05, m.objectScale / l), q = m.centerX - s, G = m.centerY - u, J = D(
152
+ (q - o.left) / Math.max(1, o.width)
153
+ ), $ = D(
154
+ (G - o.top) / Math.max(1, o.height)
155
+ );
156
+ await c.executeCommand(
157
+ "updateImage",
158
+ m.id,
159
+ {
160
+ scale: h,
161
+ left: J,
162
+ top: $
163
+ },
164
+ {
165
+ target: i
166
+ }
131
167
  );
132
- await r.executeCommand("updateImage", m.id, {
133
- scale: g,
134
- left: H,
135
- top: L
136
- });
137
168
  }
138
169
  };
139
170
  v({
140
171
  importConfig: b,
141
172
  exportConfig: S,
142
173
  getImages: x,
143
- generateCutImage: A,
144
- addImage: F,
145
- upsertImage: N,
146
- updateImage: R,
174
+ generateCutImage: k,
175
+ addImage: I,
176
+ upsertImage: _,
177
+ updateImage: W,
147
178
  clearImages: z,
179
+ exportUserCroppedImage: N,
180
+ focusImage: P,
148
181
  detectDieline: async (e) => {
149
- const t = o.getService("CanvasService"), n = y(t), a = await r.executeCommand("detectEdge", e, {
182
+ const t = a.getService("CanvasService"), n = E(t), i = await c.executeCommand("detectEdge", e, {
150
183
  expand: 10,
151
184
  // 安全距离(像素)
152
185
  smoothing: !0,
@@ -154,94 +187,126 @@ const re = /* @__PURE__ */ T({
154
187
  simplifyTolerance: 2
155
188
  // 平滑度容差,值越大越圆润
156
189
  });
157
- if (a) {
158
- _(a);
159
- const c = (s.get("image.items") || []).find((d) => d.url === e);
160
- if (c?.id) {
161
- const d = n.filter(
162
- (m) => m.id === c.id
190
+ if (i) {
191
+ y(i);
192
+ const o = (d.get("image.items") || []).find((s) => s.url === e);
193
+ if (o?.id) {
194
+ const s = n.filter(
195
+ (u) => u.id === o.id
163
196
  );
164
- await I(a, d);
197
+ await F(i, s);
165
198
  }
166
- return a.pathData;
199
+ return i.pathData;
167
200
  }
168
201
  return null;
169
202
  },
170
203
  detectDielineFromFrame: async (e) => {
171
- const t = e?.detect?.debug === !0, n = o.getService("CanvasService"), a = y(n), { url: i } = await r.executeCommand("exportImageFrameUrl", {
172
- multiplier: 2,
173
- format: "png"
174
- });
204
+ const t = e?.detect?.debug === !0, n = e?.inspect?.includeCroppedImage === !0, i = e?.inspect?.includeDiagnostics === !0, r = await N({
205
+ multiplier: e?.export?.multiplier ?? 2,
206
+ format: e?.export?.format ?? "png",
207
+ imageIds: e?.export?.imageIds
208
+ }), o = r?.url;
209
+ if (!o) return null;
175
210
  try {
176
- const c = await r.executeCommand("detectEdge", i, {
177
- expand: e?.detect?.expand ?? 30,
211
+ t && console.info("[PooderEditor] detectDielineFromFrame sourceImage", {
212
+ width: r.width,
213
+ height: r.height,
214
+ format: r.format,
215
+ multiplier: r.multiplier,
216
+ imageCount: r.imageIds.length
217
+ });
218
+ const s = await c.executeCommand("detectEdge", o, {
219
+ expand: e?.detect?.expand ?? 0,
178
220
  smoothing: e?.detect?.smoothing ?? !0,
179
221
  simplifyTolerance: e?.detect?.simplifyTolerance ?? 2,
222
+ threshold: e?.detect?.threshold,
223
+ morphologyRadius: e?.detect?.morphologyRadius,
224
+ connectRadiusMax: e?.detect?.connectRadiusMax,
225
+ maskMode: e?.detect?.maskMode,
226
+ whiteThreshold: e?.detect?.whiteThreshold,
227
+ alphaOpaqueCutoff: e?.detect?.alphaOpaqueCutoff,
228
+ noChannels: e?.detect?.noChannels,
229
+ componentMode: e?.detect?.componentMode ?? "all",
230
+ minComponentArea: e?.detect?.minComponentArea,
231
+ forceConnected: e?.detect?.forceConnected ?? !0,
180
232
  debug: t
181
233
  });
182
- return c ? (e?.commit === !1 || (_(c), await I(c, a, t)), c) : null;
234
+ if (!s) return null;
235
+ const u = j(s, r);
236
+ return t && console.info(
237
+ "[PooderEditor] detectDielineFromFrame diagnostics",
238
+ u
239
+ ), e?.commit === !1 ? {
240
+ ...s,
241
+ ...n ? { sourceImage: r } : {},
242
+ ...i ? { diagnostics: u } : {}
243
+ } : (y(s), {
244
+ ...s,
245
+ ...n ? { sourceImage: r } : {},
246
+ ...i ? { diagnostics: u } : {}
247
+ });
183
248
  } finally {
184
- i && URL.revokeObjectURL(i);
249
+ o && !n && URL.revokeObjectURL(o);
185
250
  }
186
251
  },
187
252
  uploadAndDetectEdge: async (e, t) => {
188
- const n = o.getService("CanvasService"), a = await F(e), i = y(n).filter(
189
- (d) => d.id === a
190
- ), c = await r.executeCommand("detectEdge", e, {
253
+ const n = a.getService("CanvasService"), i = await I(e), r = E(n).filter(
254
+ (s) => s.id === i
255
+ ), o = await c.executeCommand("detectEdge", e, {
191
256
  expand: t?.expand ?? 10,
192
257
  smoothing: t?.smoothing ?? !0,
193
258
  simplifyTolerance: t?.simplifyTolerance ?? 2
194
259
  });
195
- return c ? (_(c), await I(c, i), { imageId: a, url: e, pathData: c.pathData }) : null;
260
+ return o ? (y(o), await F(o, r), { imageId: i, url: e, pathData: o.pathData }) : null;
196
261
  },
197
- activateTool: async (e) => await h.switchTool(e),
198
- deactivateTool: async () => await h.deactivate(),
199
- on: (e, t) => o.eventBus.on(e, t),
200
- off: (e, t) => o.eventBus.off(e, t),
201
- emit: (e, t) => o.eventBus.emit(e, t),
202
- executeCommand: (e, ...t) => r.executeCommand(e, ...t),
203
- getConfig: (e) => s.get(e),
204
- updateConfig: (e, t) => s.update(e, t),
262
+ activateTool: async (e) => await f.switchTool(e),
263
+ deactivateTool: async () => await f.deactivate(),
264
+ on: (e, t) => a.eventBus.on(e, t),
265
+ off: (e, t) => a.eventBus.off(e, t),
266
+ emit: (e, t) => a.eventBus.emit(e, t),
267
+ executeCommand: (e, ...t) => c.executeCommand(e, ...t),
268
+ getConfig: (e) => d.get(e),
269
+ updateConfig: (e, t) => d.update(e, t),
205
270
  services: {
206
- workbench: h,
207
- command: r,
208
- config: s
271
+ workbench: f,
272
+ command: c,
273
+ config: d
209
274
  }
210
275
  });
211
- const W = (e) => {
212
- const t = new q(e, {
213
- eventBus: o.eventBus
276
+ const U = (e) => {
277
+ const t = new ne(e, {
278
+ eventBus: a.eventBus
214
279
  });
215
- o.registerService(t, "CanvasService"), [
216
- new K(),
217
- new Q(),
218
- new Z(),
219
- new ee(),
220
- new te(),
221
- // new FilmTool(),
222
- new ne(),
223
- new ae(),
224
- new ie(),
280
+ a.registerService(t, "CanvasService"), a.registerService(new ie(), T), a.registerService(
225
281
  new oe(),
226
- new ce()
227
- ].forEach((a) => {
228
- o.extensionManager.register(a);
282
+ B
283
+ ), [
284
+ new ae(),
285
+ new re(),
286
+ new ce(),
287
+ // new FilmTool(),
288
+ new se(),
289
+ new de(),
290
+ new ue(),
291
+ new me(),
292
+ new ge()
293
+ ].forEach((i) => {
294
+ a.extensionManager.register(i);
229
295
  });
230
- }, j = (e, t) => {
231
- const n = o.getService("CanvasService");
296
+ }, V = (e, t) => {
297
+ const n = a.getService("CanvasService");
232
298
  n && n.resize(e, t);
233
299
  };
234
- return E(() => {
235
- const e = o.getService("CanvasService");
236
- e && e.dispose(), C.dispose(), o.extensionManager.destroy();
237
- }), (e, t) => (O(), B("div", de, [
238
- J(se, {
239
- onCanvasReady: W,
240
- onResize: j
300
+ return Y(() => {
301
+ w.dispose(), a.extensionManager.destroy(), a.unregisterService(B), a.unregisterService(T), a.unregisterService("CanvasService");
302
+ }), (e, t) => (X(), R("div", fe, [
303
+ ee(he, {
304
+ onCanvasReady: U,
305
+ onResize: V
241
306
  })
242
307
  ]));
243
308
  }
244
- }), we = /* @__PURE__ */ k(ue, [["__scopeId", "data-v-234847f9"]]);
309
+ }), _e = /* @__PURE__ */ A(pe, [["__scopeId", "data-v-2149abdf"]]);
245
310
  export {
246
- we as PooderEditor
311
+ _e as PooderEditor
247
312
  };
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(u,s){typeof exports=="object"&&typeof module<"u"?s(exports,require("vue"),require("@pooder/core"),require("@pooder/kit")):typeof define=="function"&&define.amd?define(["exports","vue","@pooder/core","@pooder/kit"],s):(u=typeof globalThis<"u"?globalThis:u||self,s(u.PooderVue={},u.Vue,u.PooderCore,u.PooderKit))})(this,(function(u,s,S,g){"use strict";const P=s.defineComponent({__name:"CanvasArea",emits:["canvas-ready","resize"],setup(m,{emit:y}){const h=y,i=s.ref(null),c=s.ref(null);let d=null;return s.onMounted(()=>{if(i.value&&c.value){const{clientWidth:b,clientHeight:C}=i.value;c.value.width=b,c.value.height=C,h("canvas-ready",c.value),d=new ResizeObserver(x=>{for(const _ of x){const{width:I,height:N}=_.contentRect;h("resize",I,N)}}),d.observe(i.value)}}),s.onUnmounted(()=>{d&&d.disconnect()}),(b,C)=>(s.openBlock(),s.createElementBlock("div",{ref_key:"container",ref:i,class:"pooder-canvas-area"},[s.createElementVNode("canvas",{ref_key:"canvas",ref:c},null,512)],512))}}),E=(m,y)=>{const h=m.__vccOpts||m;for(const[i,c]of y)h[i]=c;return h},j=E(P,[["__scopeId","data-v-dc60e8d6"]]),A={class:"pooder-editor"},R="image.user",z=E(s.defineComponent({__name:"PooderEditor",emits:["image-change"],setup(m,{expose:y,emit:h}){const i=new S.Pooder;s.provide("pooder",i);const c=i.getService("CommandService"),d=i.getService("ConfigurationService"),b=i.getService("WorkbenchService"),C=h,x=d.onAnyChange(e=>{e.key==="image.items"&&C("image-change",e.value)}),_=e=>{d.import(e)},I=()=>d.export(),N=()=>d.get("image.items",[]),X=async e=>{try{const t=await c.executeCommand("exportCutImage",e);return t||console.warn("[PooderEditor] generateCutImage returned null",{options:e,imageCount:(d.get("image.items")||[]).length,hasCanvasService:!!i.getService("CanvasService")}),t}catch(t){throw console.error("[PooderEditor] generateCutImage failed",t),t}},T=async(e,t)=>await c.executeCommand("upsertImage",e,{id:t?.id,mode:t?.mode,createIfMissing:t?.createIfMissing,addOptions:t?.addOptions,fitOnAdd:t?.fitOnAdd}),M=async(e,t)=>(await T(e,{mode:"add",addOptions:t,fitOnAdd:!0})).id,Y=async(e,t)=>await c.executeCommand("updateImage",e,t),W=async()=>await c.executeCommand("clearImages"),B=e=>Math.max(-1,Math.min(2,e)),H=e=>{const t=e?.cutRect;if(!t)return null;const n=Number(t.width),o=Number(t.height),a=Number(t.left),r=Number(t.top);return!Number.isFinite(n)||!Number.isFinite(o)||!Number.isFinite(a)||!Number.isFinite(r)||n<=0||o<=0?null:{left:a,top:r,width:n,height:o}},F=e=>{if(!e)return[];const t=e.canvas.getObjects(),n=[];for(const o of t){if(o?.data?.layerId!==R)continue;const a=o?.data?.id;if(typeof a!="string")continue;const r=o.getCenterPoint?o.getCenterPoint():null,l=Number(r?.x??o.left),f=Number(r?.y??o.top),w=Number(o.scaleX),p=Number(o.width),v=Number(o.height);!Number.isFinite(l)||!Number.isFinite(f)||!Number.isFinite(w)||!Number.isFinite(p)||!Number.isFinite(v)||p<=0||v<=0||n.push({id:a,centerX:l,centerY:f,objectScale:w,sourceWidth:p,sourceHeight:v})}return n},O=e=>{d.update("dieline.shape","custom"),d.update("dieline.pathData",e.pathData),d.update("size.cutMode","trim"),d.update("size.cutMarginMm",0)},L=(e,t)=>{const n=e.rawBounds||e.baseBounds,o=Number(e.imageWidth??0),a=Number(e.imageHeight??0);if(!n||!Number.isFinite(n.x)||!Number.isFinite(n.y)||!Number.isFinite(n.width)||!Number.isFinite(n.height)||n.width<=0||n.height<=0||o<=0||a<=0)return{shiftX:0,shiftY:0};const r=t.width/n.width,l=t.height/n.height,f=n.x+n.width/2,w=n.y+n.height/2,p=o/2,v=a/2;return{shiftX:(f-p)*r,shiftY:(w-v)*l}},D=async(e,t,n=!1)=>{if(!t.length)return;const o=await c.executeCommand("getSceneLayout"),a=H(o);if(!a)return;const{shiftX:r,shiftY:l}=L(e,a);n&&console.info("[PooderEditor] detectDieline alignment",{frame:a,shiftX:r,shiftY:l,snapshotCount:t.length,baseBounds:e.baseBounds,rawBounds:e.rawBounds,imageWidth:e.imageWidth,imageHeight:e.imageHeight});for(const f of t){const w=Math.max(a.width/Math.max(1,f.sourceWidth),a.height/Math.max(1,f.sourceHeight)),p=Math.max(.05,f.objectScale/w),v=f.centerX-r,q=f.centerY-l,G=B((v-a.left)/Math.max(1,a.width)),J=B((q-a.top)/Math.max(1,a.height));await c.executeCommand("updateImage",f.id,{scale:p,left:G,top:J})}};y({importConfig:_,exportConfig:I,getImages:N,generateCutImage:X,addImage:M,upsertImage:T,updateImage:Y,clearImages:W,detectDieline:async e=>{const t=i.getService("CanvasService"),n=F(t),o=await c.executeCommand("detectEdge",e,{expand:10,smoothing:!0,simplifyTolerance:2});if(o){O(o);const r=(d.get("image.items")||[]).find(l=>l.url===e);if(r?.id){const l=n.filter(f=>f.id===r.id);await D(o,l)}return o.pathData}return null},detectDielineFromFrame:async e=>{const t=e?.detect?.debug===!0,n=i.getService("CanvasService"),o=F(n),{url:a}=await c.executeCommand("exportImageFrameUrl",{multiplier:2,format:"png"});try{const r=await c.executeCommand("detectEdge",a,{expand:e?.detect?.expand??30,smoothing:e?.detect?.smoothing??!0,simplifyTolerance:e?.detect?.simplifyTolerance??2,debug:t});return r?(e?.commit===!1||(O(r),await D(r,o,t)),r):null}finally{a&&URL.revokeObjectURL(a)}},uploadAndDetectEdge:async(e,t)=>{const n=i.getService("CanvasService"),o=await M(e),a=F(n).filter(l=>l.id===o),r=await c.executeCommand("detectEdge",e,{expand:t?.expand??10,smoothing:t?.smoothing??!0,simplifyTolerance:t?.simplifyTolerance??2});return r?(O(r),await D(r,a),{imageId:o,url:e,pathData:r.pathData}):null},activateTool:async e=>await b.switchTool(e),deactivateTool:async()=>await b.deactivate(),on:(e,t)=>i.eventBus.on(e,t),off:(e,t)=>i.eventBus.off(e,t),emit:(e,t)=>i.eventBus.emit(e,t),executeCommand:(e,...t)=>c.executeCommand(e,...t),getConfig:e=>d.get(e),updateConfig:(e,t)=>d.update(e,t),services:{workbench:b,command:c,config:d}});const U=e=>{const t=new g.CanvasService(e,{eventBus:i.eventBus});i.registerService(t,"CanvasService"),[new g.BackgroundTool,new g.SizeTool,new g.SceneLayoutService,new g.SceneVisibilityService,new g.ImageTool,new g.WhiteInkTool,new g.MirrorTool,new g.DielineTool,new g.RulerTool,new g.FeatureTool].forEach(o=>{i.extensionManager.register(o)})},V=(e,t)=>{const n=i.getService("CanvasService");n&&n.resize(e,t)};return s.onUnmounted(()=>{const e=i.getService("CanvasService");e&&e.dispose(),x.dispose(),i.extensionManager.destroy()}),(e,t)=>(s.openBlock(),s.createElementBlock("div",A,[s.createVNode(j,{onCanvasReady:U,onResize:V})]))}}),[["__scopeId","data-v-234847f9"]]);u.PooderEditor=z,Object.keys(S).forEach(m=>{m!=="default"&&!Object.prototype.hasOwnProperty.call(u,m)&&Object.defineProperty(u,m,{enumerable:!0,get:()=>S[m]})}),Object.keys(g).forEach(m=>{m!=="default"&&!Object.prototype.hasOwnProperty.call(u,m)&&Object.defineProperty(u,m,{enumerable:!0,get:()=>g[m]})}),Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(l,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("vue"),require("@pooder/core"),require("@pooder/kit")):typeof define=="function"&&define.amd?define(["exports","vue","@pooder/core","@pooder/kit"],u):(l=typeof globalThis<"u"?globalThis:l||self,u(l.PooderVue={},l.Vue,l.PooderCore,l.PooderKit))})(this,(function(l,u,S,h){"use strict";const j=u.defineComponent({__name:"CanvasArea",emits:["canvas-ready","resize"],setup(m,{emit:b}){const p=b,r=u.ref(null),c=u.ref(null);let d=null;return u.onMounted(()=>{if(r.value&&c.value){const{clientWidth:w,clientHeight:y}=r.value;c.value.width=w,c.value.height=y,p("canvas-ready",c.value),d=new ResizeObserver(x=>{for(const _ of x){const{width:I,height:E}=_.contentRect;p("resize",I,E)}}),d.observe(r.value)}}),u.onUnmounted(()=>{d&&d.disconnect()}),(w,y)=>(u.openBlock(),u.createElementBlock("div",{ref_key:"container",ref:r,class:"pooder-canvas-area"},[u.createElementVNode("canvas",{ref_key:"canvas",ref:c},null,512)],512))}}),D=(m,b)=>{const p=m.__vccOpts||m;for(const[r,c]of b)p[r]=c;return p},X=D(j,[["__scopeId","data-v-203ff8d9"]]),A={class:"pooder-editor"},O="SceneLayoutService",F="SceneVisibilityService",W="image.user",z=D(u.defineComponent({__name:"PooderEditor",emits:["image-change"],setup(m,{expose:b,emit:p}){const r=new S.Pooder;u.provide("pooder",r);const c=r.getService("CommandService"),d=r.getService("ConfigurationService"),w=r.getService("WorkbenchService"),y=p,x=d.onAnyChange(e=>{e.key==="image.items"&&y("image-change",e.value)}),_=e=>{d.import(e)},I=()=>d.export(),E=()=>d.get("image.items",[]),H=async e=>{try{const t=await c.executeCommand("exportCutImage",e);return t||console.warn("[PooderEditor] generateCutImage returned null",{options:e,imageCount:(d.get("image.items")||[]).length,hasCanvasService:!!r.getService("CanvasService")}),t}catch(t){throw console.error("[PooderEditor] generateCutImage failed",t),t}},T=async(e,t)=>await c.executeCommand("upsertImage",e,{id:t?.id,mode:t?.mode,addOptions:t?.addOptions,fitOnAdd:t?.fitOnAdd}),M=async(e,t)=>(await T(e,{mode:"add",addOptions:t,fitOnAdd:!0})).id,V=async(e,t)=>await c.executeCommand("updateImage",e,t),L=async()=>await c.executeCommand("clearImages"),B=async e=>await c.executeCommand("exportUserCroppedImage",e),U=async(e,t)=>await c.executeCommand("focusImage",e,t),P=e=>Math.max(-1,Math.min(2,e)),q=e=>{const t=e?.cutRect;if(!t)return null;const n=Number(t.width),o=Number(t.height),a=Number(t.left),i=Number(t.top);return!Number.isFinite(n)||!Number.isFinite(o)||!Number.isFinite(a)||!Number.isFinite(i)||n<=0||o<=0?null:{left:a,top:i,width:n,height:o}},Y=e=>{if(!e)return[];const t=e.canvas.getObjects(),n=[];for(const o of t){if(o?.data?.layerId!==W)continue;const a=o?.data?.id;if(typeof a!="string")continue;const i=o.getCenterPoint?o.getCenterPoint():null,s=Number(i?.x??o.left),g=Number(i?.y??o.top),f=Number(o.scaleX),v=Number(o.width),C=Number(o.height);!Number.isFinite(s)||!Number.isFinite(g)||!Number.isFinite(f)||!Number.isFinite(v)||!Number.isFinite(C)||v<=0||C<=0||n.push({id:a,centerX:s,centerY:g,objectScale:f,sourceWidth:v,sourceHeight:C})}return n},N=e=>{d.update("dieline.shape","custom"),d.update("dieline.pathData",e.pathData),d.update("dieline.features",[]),d.update("size.cutMode","trim"),d.update("size.cutMarginMm",0)},k=(e,t)=>{const n=e.rawBounds||e.baseBounds||null;if(!n)return{sourceWidth:t.width,sourceHeight:t.height,detectedBounds:null,centerOffsetX:0,centerOffsetY:0,coverageX:0,coverageY:0};const o=t.width/2,a=t.height/2,i=n.x+n.width/2,s=n.y+n.height/2;return{sourceWidth:t.width,sourceHeight:t.height,detectedBounds:n,centerOffsetX:i-o,centerOffsetY:s-a,coverageX:t.width>0?n.width/t.width:0,coverageY:t.height>0?n.height/t.height:0}},G=(e,t)=>{const n=e.rawBounds||e.baseBounds,o=Number(e.imageWidth??0),a=Number(e.imageHeight??0);if(!n||!Number.isFinite(n.x)||!Number.isFinite(n.y)||!Number.isFinite(n.width)||!Number.isFinite(n.height)||n.width<=0||n.height<=0||o<=0||a<=0)return{shiftX:0,shiftY:0};const i=t.width/n.width,s=t.height/n.height,g=n.x+n.width/2,f=n.y+n.height/2,v=o/2,C=a/2;return{shiftX:(g-v)*i,shiftY:(f-C)*s}},R=async(e,t,n=!1,o="auto")=>{if(!t.length)return;const a=await c.executeCommand("getSceneLayout"),i=q(a);if(!i)return;const{shiftX:s,shiftY:g}=G(e,i);n&&console.info("[PooderEditor] detectDieline alignment",{frame:i,shiftX:s,shiftY:g,snapshotCount:t.length,baseBounds:e.baseBounds,rawBounds:e.rawBounds,imageWidth:e.imageWidth,imageHeight:e.imageHeight});for(const f of t){const v=Math.max(i.width/Math.max(1,f.sourceWidth),i.height/Math.max(1,f.sourceHeight)),C=Math.max(.05,f.objectScale/v),$=f.centerX-s,Q=f.centerY-g,Z=P(($-i.left)/Math.max(1,i.width)),ee=P((Q-i.top)/Math.max(1,i.height));await c.executeCommand("updateImage",f.id,{scale:C,left:Z,top:ee},{target:o})}};b({importConfig:_,exportConfig:I,getImages:E,generateCutImage:H,addImage:M,upsertImage:T,updateImage:V,clearImages:L,exportUserCroppedImage:B,focusImage:U,detectDieline:async e=>{const t=r.getService("CanvasService"),n=Y(t),o=await c.executeCommand("detectEdge",e,{expand:10,smoothing:!0,simplifyTolerance:2});if(o){N(o);const i=(d.get("image.items")||[]).find(s=>s.url===e);if(i?.id){const s=n.filter(g=>g.id===i.id);await R(o,s)}return o.pathData}return null},detectDielineFromFrame:async e=>{const t=e?.detect?.debug===!0,n=e?.inspect?.includeCroppedImage===!0,o=e?.inspect?.includeDiagnostics===!0,a=await B({multiplier:e?.export?.multiplier??2,format:e?.export?.format??"png",imageIds:e?.export?.imageIds}),i=a?.url;if(!i)return null;try{t&&console.info("[PooderEditor] detectDielineFromFrame sourceImage",{width:a.width,height:a.height,format:a.format,multiplier:a.multiplier,imageCount:a.imageIds.length});const s=await c.executeCommand("detectEdge",i,{expand:e?.detect?.expand??0,smoothing:e?.detect?.smoothing??!0,simplifyTolerance:e?.detect?.simplifyTolerance??2,threshold:e?.detect?.threshold,morphologyRadius:e?.detect?.morphologyRadius,connectRadiusMax:e?.detect?.connectRadiusMax,maskMode:e?.detect?.maskMode,whiteThreshold:e?.detect?.whiteThreshold,alphaOpaqueCutoff:e?.detect?.alphaOpaqueCutoff,noChannels:e?.detect?.noChannels,componentMode:e?.detect?.componentMode??"all",minComponentArea:e?.detect?.minComponentArea,forceConnected:e?.detect?.forceConnected??!0,debug:t});if(!s)return null;const g=k(s,a);return t&&console.info("[PooderEditor] detectDielineFromFrame diagnostics",g),e?.commit===!1?{...s,...n?{sourceImage:a}:{},...o?{diagnostics:g}:{}}:(N(s),{...s,...n?{sourceImage:a}:{},...o?{diagnostics:g}:{}})}finally{i&&!n&&URL.revokeObjectURL(i)}},uploadAndDetectEdge:async(e,t)=>{const n=r.getService("CanvasService"),o=await M(e),a=Y(n).filter(s=>s.id===o),i=await c.executeCommand("detectEdge",e,{expand:t?.expand??10,smoothing:t?.smoothing??!0,simplifyTolerance:t?.simplifyTolerance??2});return i?(N(i),await R(i,a),{imageId:o,url:e,pathData:i.pathData}):null},activateTool:async e=>await w.switchTool(e),deactivateTool:async()=>await w.deactivate(),on:(e,t)=>r.eventBus.on(e,t),off:(e,t)=>r.eventBus.off(e,t),emit:(e,t)=>r.eventBus.emit(e,t),executeCommand:(e,...t)=>c.executeCommand(e,...t),getConfig:e=>d.get(e),updateConfig:(e,t)=>d.update(e,t),services:{workbench:w,command:c,config:d}});const J=e=>{const t=new h.CanvasService(e,{eventBus:r.eventBus});r.registerService(t,"CanvasService"),r.registerService(new h.SceneLayoutService,O),r.registerService(new h.SceneVisibilityService,F),[new h.BackgroundTool,new h.SizeTool,new h.ImageTool,new h.WhiteInkTool,new h.MirrorTool,new h.DielineTool,new h.RulerTool,new h.FeatureTool].forEach(o=>{r.extensionManager.register(o)})},K=(e,t)=>{const n=r.getService("CanvasService");n&&n.resize(e,t)};return u.onUnmounted(()=>{x.dispose(),r.extensionManager.destroy(),r.unregisterService(F),r.unregisterService(O),r.unregisterService("CanvasService")}),(e,t)=>(u.openBlock(),u.createElementBlock("div",A,[u.createVNode(X,{onCanvasReady:J,onResize:K})]))}}),[["__scopeId","data-v-2149abdf"]]);l.PooderEditor=z,Object.keys(S).forEach(m=>{m!=="default"&&!Object.prototype.hasOwnProperty.call(l,m)&&Object.defineProperty(l,m,{enumerable:!0,get:()=>S[m]})}),Object.keys(h).forEach(m=>{m!=="default"&&!Object.prototype.hasOwnProperty.call(l,m)&&Object.defineProperty(l,m,{enumerable:!0,get:()=>h[m]})}),Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
@@ -5,12 +5,22 @@ interface DetectBounds {
5
5
  width: number;
6
6
  height: number;
7
7
  }
8
- interface DetectEdgeResult {
9
- pathData: string;
10
- rawBounds?: DetectBounds;
11
- baseBounds?: DetectBounds;
12
- imageWidth?: number;
13
- imageHeight?: number;
8
+ interface DetectFrameDiagnostics {
9
+ sourceWidth: number;
10
+ sourceHeight: number;
11
+ detectedBounds: DetectBounds | null;
12
+ centerOffsetX: number;
13
+ centerOffsetY: number;
14
+ coverageX: number;
15
+ coverageY: number;
16
+ }
17
+ interface ExportUserCroppedImageResult {
18
+ url: string;
19
+ width: number;
20
+ height: number;
21
+ multiplier: number;
22
+ format: "png" | "jpeg";
23
+ imageIds: string[];
14
24
  }
15
25
  declare const _default: import('vue').DefineComponent<{}, {
16
26
  importConfig: (config: Record<string, any>) => void;
@@ -22,23 +32,57 @@ declare const _default: import('vue').DefineComponent<{}, {
22
32
  addImage: (url: string, options?: any) => Promise<any>;
23
33
  upsertImage: (url: string, options?: {
24
34
  id?: string;
25
- mode?: "auto" | "replace" | "add";
26
- createIfMissing?: boolean;
35
+ mode?: "replace" | "add";
27
36
  addOptions?: any;
28
37
  fitOnAdd?: boolean;
29
38
  }) => Promise<any>;
30
39
  updateImage: (id: string, options?: any) => Promise<any>;
31
40
  clearImages: () => Promise<any>;
41
+ exportUserCroppedImage: (options?: {
42
+ multiplier?: number;
43
+ format?: "png" | "jpeg";
44
+ imageIds?: string[];
45
+ }) => Promise<ExportUserCroppedImageResult>;
46
+ focusImage: (id: string | null, options?: {
47
+ syncCanvasSelection?: boolean;
48
+ }) => Promise<any>;
32
49
  detectDieline: (url: string) => Promise<string | null>;
33
50
  detectDielineFromFrame: (options?: {
34
51
  detect?: {
35
52
  expand?: number;
36
53
  smoothing?: boolean;
37
54
  simplifyTolerance?: number;
55
+ threshold?: number;
56
+ morphologyRadius?: number;
57
+ connectRadiusMax?: number;
58
+ maskMode?: "auto" | "alpha" | "whitebg";
59
+ whiteThreshold?: number;
60
+ alphaOpaqueCutoff?: number;
61
+ noChannels?: boolean;
62
+ componentMode?: "largest" | "all";
63
+ minComponentArea?: number;
64
+ forceConnected?: boolean;
38
65
  debug?: boolean;
39
66
  };
67
+ export?: {
68
+ multiplier?: number;
69
+ format?: "png" | "jpeg";
70
+ imageIds?: string[];
71
+ };
72
+ inspect?: {
73
+ includeCroppedImage?: boolean;
74
+ includeDiagnostics?: boolean;
75
+ };
40
76
  commit?: boolean;
41
- }) => Promise<DetectEdgeResult | null>;
77
+ }) => Promise<{
78
+ diagnostics?: DetectFrameDiagnostics | undefined;
79
+ sourceImage?: ExportUserCroppedImageResult | undefined;
80
+ pathData: string;
81
+ rawBounds?: DetectBounds;
82
+ baseBounds?: DetectBounds;
83
+ imageWidth?: number;
84
+ imageHeight?: number;
85
+ } | null>;
42
86
  uploadAndDetectEdge: (url: string, options?: {
43
87
  expand?: number;
44
88
  smoothing?: boolean;
package/dist/vue.css CHANGED
@@ -1 +1 @@
1
- .pooder-canvas-area[data-v-dc60e8d6]{flex:1;width:100%;height:100%;min-height:650px;min-width:650px;overflow:hidden;background:#f5f5f5;position:relative}canvas[data-v-dc60e8d6]{display:block}.pooder-editor[data-v-234847f9]{display:flex;width:100%;height:100%;overflow:hidden}
1
+ .pooder-canvas-area[data-v-203ff8d9]{flex:1;width:100%;height:100%;min-height:650px;min-width:650px;overflow:hidden;background:#ececec;position:relative}canvas[data-v-203ff8d9]{display:block}.pooder-editor[data-v-2149abdf]{display:flex;width:100%;height:100%;overflow:hidden}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pooder/vue",
3
- "version": "4.2.3",
3
+ "version": "4.2.5",
4
4
  "main": "./dist/index.umd.js",
5
5
  "module": "./dist/index.es.js",
6
6
  "types": "./dist/index.d.ts",
@@ -19,8 +19,8 @@
19
19
  "access": "public"
20
20
  },
21
21
  "dependencies": {
22
- "@pooder/core": "2.1.0",
23
- "@pooder/kit": "5.0.3"
22
+ "@pooder/core": "2.2.0",
23
+ "@pooder/kit": "5.1.0"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "vue": "^3.0.0"