@nextcloud/image-editor 1.0.0-beta.1 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -3
- package/dist/assets/index.css +61 -43
- package/dist/index.cjs +420 -104
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.mjs +421 -105
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import './assets/index.css';
|
|
2
|
-
import { shallowRef, computed, defineComponent, openBlock, createElementBlock, normalizeClass, renderSlot, mergeProps, createElementVNode, toDisplayString, createCommentVNode, createTextVNode, watch, provide, inject, Fragment, renderList, createVNode, withCtx, createBlock, resolveDynamicComponent, unref, normalizeStyle, ref, useTemplateRef, onMounted, withDirectives, withKeys, withModifiers, vModelText, onBeforeUnmount } from "vue";
|
|
2
|
+
import { shallowRef, computed, defineComponent, openBlock, createElementBlock, normalizeClass, renderSlot, mergeProps, createElementVNode, toDisplayString, createCommentVNode, createTextVNode, watch, provide, inject, Fragment, renderList, createVNode, withCtx, createBlock, resolveDynamicComponent, unref, normalizeStyle, createSlots, ref, useTemplateRef, onMounted, withDirectives, withKeys, withModifiers, vModelText, onBeforeUnmount } from "vue";
|
|
3
3
|
import Konva from "konva";
|
|
4
4
|
import NcButton from "@nextcloud/vue/components/NcButton";
|
|
5
5
|
import NcLoadingIcon from "@nextcloud/vue/components/NcLoadingIcon";
|
|
@@ -67,14 +67,21 @@ function createInitialState() {
|
|
|
67
67
|
flipX: false,
|
|
68
68
|
flipY: false,
|
|
69
69
|
crop: null,
|
|
70
|
-
adjustments: {
|
|
70
|
+
adjustments: {
|
|
71
|
+
exposure: 0,
|
|
72
|
+
brightness: 0,
|
|
73
|
+
contrast: 0,
|
|
74
|
+
saturation: 0,
|
|
75
|
+
temperature: 0,
|
|
76
|
+
tint: 0,
|
|
77
|
+
sharpen: 0
|
|
78
|
+
},
|
|
71
79
|
preset: "none",
|
|
72
80
|
annotations: []
|
|
73
81
|
};
|
|
74
82
|
}
|
|
75
83
|
function isPristine(state) {
|
|
76
|
-
|
|
77
|
-
return state.rotation === 0 && state.fineRotation === 0 && state.zoom === 1 && !state.flipX && !state.flipY && state.crop === null && adjustments.brightness === 0 && adjustments.contrast === 0 && adjustments.saturation === 0 && state.preset === "none" && state.annotations.length === 0;
|
|
84
|
+
return state.rotation === 0 && state.fineRotation === 0 && state.zoom === 1 && !state.flipX && !state.flipY && state.crop === null && Object.values(state.adjustments).every((value) => value === 0) && state.preset === "none" && state.annotations.length === 0;
|
|
78
85
|
}
|
|
79
86
|
function orientedSize(natural, rotation) {
|
|
80
87
|
return rotation % 180 === 0 ? { width: natural.width, height: natural.height } : { width: natural.height, height: natural.width };
|
|
@@ -109,6 +116,7 @@ function mapAnnotationCW(annotation, height) {
|
|
|
109
116
|
case "draw":
|
|
110
117
|
return { ...annotation, points: mapPointsCW(annotation.points, height) };
|
|
111
118
|
case "arrow":
|
|
119
|
+
case "line":
|
|
112
120
|
return { ...annotation, points: mapPointsCW(annotation.points, height) };
|
|
113
121
|
case "rectangle":
|
|
114
122
|
case "ellipse":
|
|
@@ -140,7 +148,8 @@ function rotateCW(state, oriented) {
|
|
|
140
148
|
function mapAnnotationFlipX(annotation, width) {
|
|
141
149
|
switch (annotation.type) {
|
|
142
150
|
case "draw":
|
|
143
|
-
case "arrow":
|
|
151
|
+
case "arrow":
|
|
152
|
+
case "line": {
|
|
144
153
|
const points = annotation.points.map((value, i) => i % 2 === 0 ? width - value : value);
|
|
145
154
|
return { ...annotation, points };
|
|
146
155
|
}
|
|
@@ -185,7 +194,8 @@ function flipHorizontal(state, oriented) {
|
|
|
185
194
|
function mapAnnotationFlipY(annotation, height) {
|
|
186
195
|
switch (annotation.type) {
|
|
187
196
|
case "draw":
|
|
188
|
-
case "arrow":
|
|
197
|
+
case "arrow":
|
|
198
|
+
case "line": {
|
|
189
199
|
const points = annotation.points.map((value, i) => i % 2 === 1 ? height - value : value);
|
|
190
200
|
return { ...annotation, points };
|
|
191
201
|
}
|
|
@@ -230,7 +240,8 @@ function flipVertical(state, oriented) {
|
|
|
230
240
|
function translateAnnotation(annotation, dx, dy) {
|
|
231
241
|
switch (annotation.type) {
|
|
232
242
|
case "draw":
|
|
233
|
-
case "arrow":
|
|
243
|
+
case "arrow":
|
|
244
|
+
case "line": {
|
|
234
245
|
const points = annotation.points.map((value, i) => value + (i % 2 === 0 ? dx : dy));
|
|
235
246
|
return { ...annotation, points };
|
|
236
247
|
}
|
|
@@ -249,7 +260,7 @@ function translateAnnotation(annotation, dx, dy) {
|
|
|
249
260
|
function duplicateAnnotation(annotation, offset = 16) {
|
|
250
261
|
return { ...translateAnnotation(annotation, offset, offset), id: newId() };
|
|
251
262
|
}
|
|
252
|
-
const _sfc_main$
|
|
263
|
+
const _sfc_main$N = /* @__PURE__ */ defineComponent({
|
|
253
264
|
__name: "GlassSurface",
|
|
254
265
|
props: {
|
|
255
266
|
variant: {}
|
|
@@ -271,8 +282,51 @@ const _export_sfc = (sfc, props) => {
|
|
|
271
282
|
}
|
|
272
283
|
return target;
|
|
273
284
|
};
|
|
274
|
-
const GlassSurface = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
275
|
-
const _sfc_main$
|
|
285
|
+
const GlassSurface = /* @__PURE__ */ _export_sfc(_sfc_main$N, [["__scopeId", "data-v-b60e81d9"]]);
|
|
286
|
+
const _sfc_main$M = {
|
|
287
|
+
name: "CameraIrisIcon",
|
|
288
|
+
emits: ["click"],
|
|
289
|
+
props: {
|
|
290
|
+
title: {
|
|
291
|
+
type: String
|
|
292
|
+
},
|
|
293
|
+
fillColor: {
|
|
294
|
+
type: String,
|
|
295
|
+
default: "currentColor"
|
|
296
|
+
},
|
|
297
|
+
size: {
|
|
298
|
+
type: Number,
|
|
299
|
+
default: 24
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
const _hoisted_1$J = ["aria-hidden", "aria-label"];
|
|
304
|
+
const _hoisted_2$E = ["fill", "width", "height"];
|
|
305
|
+
const _hoisted_3$B = { d: "M13.73,15L9.83,21.76C10.53,21.91 11.25,22 12,22C14.4,22 16.6,21.15 18.32,19.75L14.66,13.4M2.46,15C3.38,17.92 5.61,20.26 8.45,21.34L12.12,15M8.54,12L4.64,5.25C3,7 2,9.39 2,12C2,12.68 2.07,13.35 2.2,14H9.69M21.8,10H14.31L14.6,10.5L19.36,18.75C21,16.97 22,14.6 22,12C22,11.31 21.93,10.64 21.8,10M21.54,9C20.62,6.07 18.39,3.74 15.55,2.66L11.88,9M9.4,10.5L14.17,2.24C13.47,2.09 12.75,2 12,2C9.6,2 7.4,2.84 5.68,4.25L9.34,10.6L9.4,10.5Z" };
|
|
306
|
+
const _hoisted_4$A = { key: 0 };
|
|
307
|
+
function _sfc_render$w(_ctx, _cache, $props, $setup, $data, $options) {
|
|
308
|
+
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
309
|
+
"aria-hidden": $props.title ? null : "true",
|
|
310
|
+
"aria-label": $props.title,
|
|
311
|
+
class: "material-design-icon camera-iris-icon",
|
|
312
|
+
role: "img",
|
|
313
|
+
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
|
|
314
|
+
}), [
|
|
315
|
+
(openBlock(), createElementBlock("svg", {
|
|
316
|
+
fill: $props.fillColor,
|
|
317
|
+
class: "material-design-icon__svg",
|
|
318
|
+
width: $props.size,
|
|
319
|
+
height: $props.size,
|
|
320
|
+
viewBox: "0 0 24 24"
|
|
321
|
+
}, [
|
|
322
|
+
createElementVNode("path", _hoisted_3$B, [
|
|
323
|
+
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$A, toDisplayString($props.title), 1)) : createCommentVNode("", true)
|
|
324
|
+
])
|
|
325
|
+
], 8, _hoisted_2$E))
|
|
326
|
+
], 16, _hoisted_1$J);
|
|
327
|
+
}
|
|
328
|
+
const CameraIris = /* @__PURE__ */ _export_sfc(_sfc_main$M, [["render", _sfc_render$w]]);
|
|
329
|
+
const _sfc_main$L = {
|
|
276
330
|
name: "ContrastCircleIcon",
|
|
277
331
|
emits: ["click"],
|
|
278
332
|
props: {
|
|
@@ -289,11 +343,11 @@ const _sfc_main$H = {
|
|
|
289
343
|
}
|
|
290
344
|
}
|
|
291
345
|
};
|
|
292
|
-
const _hoisted_1$
|
|
293
|
-
const _hoisted_2$
|
|
294
|
-
const _hoisted_3$
|
|
295
|
-
const _hoisted_4$
|
|
296
|
-
function _sfc_render$
|
|
346
|
+
const _hoisted_1$I = ["aria-hidden", "aria-label"];
|
|
347
|
+
const _hoisted_2$D = ["fill", "width", "height"];
|
|
348
|
+
const _hoisted_3$A = { d: "M12,20C9.79,20 7.79,19.1 6.34,17.66L17.66,6.34C19.1,7.79 20,9.79 20,12A8,8 0 0,1 12,20M6,8H8V6H9.5V8H11.5V9.5H9.5V11.5H8V9.5H6M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,16H17V14.5H12V16Z" };
|
|
349
|
+
const _hoisted_4$z = { key: 0 };
|
|
350
|
+
function _sfc_render$v(_ctx, _cache, $props, $setup, $data, $options) {
|
|
297
351
|
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
298
352
|
"aria-hidden": $props.title ? null : "true",
|
|
299
353
|
"aria-label": $props.title,
|
|
@@ -308,14 +362,57 @@ function _sfc_render$r(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
308
362
|
height: $props.size,
|
|
309
363
|
viewBox: "0 0 24 24"
|
|
310
364
|
}, [
|
|
311
|
-
createElementVNode("path", _hoisted_3$
|
|
312
|
-
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$
|
|
365
|
+
createElementVNode("path", _hoisted_3$A, [
|
|
366
|
+
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$z, toDisplayString($props.title), 1)) : createCommentVNode("", true)
|
|
313
367
|
])
|
|
314
|
-
], 8, _hoisted_2$
|
|
315
|
-
], 16, _hoisted_1$
|
|
368
|
+
], 8, _hoisted_2$D))
|
|
369
|
+
], 16, _hoisted_1$I);
|
|
316
370
|
}
|
|
317
|
-
const ContrastCircle = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
318
|
-
const _sfc_main$
|
|
371
|
+
const ContrastCircle = /* @__PURE__ */ _export_sfc(_sfc_main$L, [["render", _sfc_render$v]]);
|
|
372
|
+
const _sfc_main$K = {
|
|
373
|
+
name: "ImageFilterCenterFocusIcon",
|
|
374
|
+
emits: ["click"],
|
|
375
|
+
props: {
|
|
376
|
+
title: {
|
|
377
|
+
type: String
|
|
378
|
+
},
|
|
379
|
+
fillColor: {
|
|
380
|
+
type: String,
|
|
381
|
+
default: "currentColor"
|
|
382
|
+
},
|
|
383
|
+
size: {
|
|
384
|
+
type: Number,
|
|
385
|
+
default: 24
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
const _hoisted_1$H = ["aria-hidden", "aria-label"];
|
|
390
|
+
const _hoisted_2$C = ["fill", "width", "height"];
|
|
391
|
+
const _hoisted_3$z = { d: "M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M19,19H15V21H19A2,2 0 0,0 21,19V15H19M19,3H15V5H19V9H21V5A2,2 0 0,0 19,3M5,5H9V3H5A2,2 0 0,0 3,5V9H5M5,15H3V19A2,2 0 0,0 5,21H9V19H5V15Z" };
|
|
392
|
+
const _hoisted_4$y = { key: 0 };
|
|
393
|
+
function _sfc_render$u(_ctx, _cache, $props, $setup, $data, $options) {
|
|
394
|
+
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
395
|
+
"aria-hidden": $props.title ? null : "true",
|
|
396
|
+
"aria-label": $props.title,
|
|
397
|
+
class: "material-design-icon image-filter-center-focus-icon",
|
|
398
|
+
role: "img",
|
|
399
|
+
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
|
|
400
|
+
}), [
|
|
401
|
+
(openBlock(), createElementBlock("svg", {
|
|
402
|
+
fill: $props.fillColor,
|
|
403
|
+
class: "material-design-icon__svg",
|
|
404
|
+
width: $props.size,
|
|
405
|
+
height: $props.size,
|
|
406
|
+
viewBox: "0 0 24 24"
|
|
407
|
+
}, [
|
|
408
|
+
createElementVNode("path", _hoisted_3$z, [
|
|
409
|
+
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$y, toDisplayString($props.title), 1)) : createCommentVNode("", true)
|
|
410
|
+
])
|
|
411
|
+
], 8, _hoisted_2$C))
|
|
412
|
+
], 16, _hoisted_1$H);
|
|
413
|
+
}
|
|
414
|
+
const ImageFilterCenterFocus = /* @__PURE__ */ _export_sfc(_sfc_main$K, [["render", _sfc_render$u]]);
|
|
415
|
+
const _sfc_main$J = {
|
|
319
416
|
name: "InvertColorsIcon",
|
|
320
417
|
emits: ["click"],
|
|
321
418
|
props: {
|
|
@@ -332,11 +429,11 @@ const _sfc_main$G = {
|
|
|
332
429
|
}
|
|
333
430
|
}
|
|
334
431
|
};
|
|
335
|
-
const _hoisted_1$
|
|
336
|
-
const _hoisted_2$
|
|
337
|
-
const _hoisted_3$
|
|
338
|
-
const _hoisted_4$
|
|
339
|
-
function _sfc_render$
|
|
432
|
+
const _hoisted_1$G = ["aria-hidden", "aria-label"];
|
|
433
|
+
const _hoisted_2$B = ["fill", "width", "height"];
|
|
434
|
+
const _hoisted_3$y = { d: "M12,19.58V19.58C10.4,19.58 8.89,18.96 7.76,17.83C6.62,16.69 6,15.19 6,13.58C6,12 6.62,10.47 7.76,9.34L12,5.1M17.66,7.93L12,2.27V2.27L6.34,7.93C3.22,11.05 3.22,16.12 6.34,19.24C7.9,20.8 9.95,21.58 12,21.58C14.05,21.58 16.1,20.8 17.66,19.24C20.78,16.12 20.78,11.05 17.66,7.93Z" };
|
|
435
|
+
const _hoisted_4$x = { key: 0 };
|
|
436
|
+
function _sfc_render$t(_ctx, _cache, $props, $setup, $data, $options) {
|
|
340
437
|
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
341
438
|
"aria-hidden": $props.title ? null : "true",
|
|
342
439
|
"aria-label": $props.title,
|
|
@@ -351,14 +448,100 @@ function _sfc_render$q(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
351
448
|
height: $props.size,
|
|
352
449
|
viewBox: "0 0 24 24"
|
|
353
450
|
}, [
|
|
354
|
-
createElementVNode("path", _hoisted_3$
|
|
355
|
-
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$
|
|
451
|
+
createElementVNode("path", _hoisted_3$y, [
|
|
452
|
+
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$x, toDisplayString($props.title), 1)) : createCommentVNode("", true)
|
|
356
453
|
])
|
|
357
|
-
], 8, _hoisted_2$
|
|
358
|
-
], 16, _hoisted_1$
|
|
454
|
+
], 8, _hoisted_2$B))
|
|
455
|
+
], 16, _hoisted_1$G);
|
|
456
|
+
}
|
|
457
|
+
const InvertColors = /* @__PURE__ */ _export_sfc(_sfc_main$J, [["render", _sfc_render$t]]);
|
|
458
|
+
const _sfc_main$I = {
|
|
459
|
+
name: "ThermometerIcon",
|
|
460
|
+
emits: ["click"],
|
|
461
|
+
props: {
|
|
462
|
+
title: {
|
|
463
|
+
type: String
|
|
464
|
+
},
|
|
465
|
+
fillColor: {
|
|
466
|
+
type: String,
|
|
467
|
+
default: "currentColor"
|
|
468
|
+
},
|
|
469
|
+
size: {
|
|
470
|
+
type: Number,
|
|
471
|
+
default: 24
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
const _hoisted_1$F = ["aria-hidden", "aria-label"];
|
|
476
|
+
const _hoisted_2$A = ["fill", "width", "height"];
|
|
477
|
+
const _hoisted_3$x = { d: "M15 13V5A3 3 0 0 0 9 5V13A5 5 0 1 0 15 13M12 4A1 1 0 0 1 13 5V8H11V5A1 1 0 0 1 12 4Z" };
|
|
478
|
+
const _hoisted_4$w = { key: 0 };
|
|
479
|
+
function _sfc_render$s(_ctx, _cache, $props, $setup, $data, $options) {
|
|
480
|
+
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
481
|
+
"aria-hidden": $props.title ? null : "true",
|
|
482
|
+
"aria-label": $props.title,
|
|
483
|
+
class: "material-design-icon thermometer-icon",
|
|
484
|
+
role: "img",
|
|
485
|
+
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
|
|
486
|
+
}), [
|
|
487
|
+
(openBlock(), createElementBlock("svg", {
|
|
488
|
+
fill: $props.fillColor,
|
|
489
|
+
class: "material-design-icon__svg",
|
|
490
|
+
width: $props.size,
|
|
491
|
+
height: $props.size,
|
|
492
|
+
viewBox: "0 0 24 24"
|
|
493
|
+
}, [
|
|
494
|
+
createElementVNode("path", _hoisted_3$x, [
|
|
495
|
+
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$w, toDisplayString($props.title), 1)) : createCommentVNode("", true)
|
|
496
|
+
])
|
|
497
|
+
], 8, _hoisted_2$A))
|
|
498
|
+
], 16, _hoisted_1$F);
|
|
359
499
|
}
|
|
360
|
-
const
|
|
361
|
-
const _sfc_main$
|
|
500
|
+
const Thermometer = /* @__PURE__ */ _export_sfc(_sfc_main$I, [["render", _sfc_render$s]]);
|
|
501
|
+
const _sfc_main$H = {
|
|
502
|
+
name: "WhiteBalanceIridescentIcon",
|
|
503
|
+
emits: ["click"],
|
|
504
|
+
props: {
|
|
505
|
+
title: {
|
|
506
|
+
type: String
|
|
507
|
+
},
|
|
508
|
+
fillColor: {
|
|
509
|
+
type: String,
|
|
510
|
+
default: "currentColor"
|
|
511
|
+
},
|
|
512
|
+
size: {
|
|
513
|
+
type: Number,
|
|
514
|
+
default: 24
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
const _hoisted_1$E = ["aria-hidden", "aria-label"];
|
|
519
|
+
const _hoisted_2$z = ["fill", "width", "height"];
|
|
520
|
+
const _hoisted_3$w = { d: "M4.96,19.95L6.76,18.15L5.34,16.74L3.55,18.53M3.55,4.46L5.34,6.26L6.76,4.84L4.96,3.05M20.45,18.53L18.66,16.74L17.24,18.15L19.04,19.95M13,22.45V19.5H11V22.45C11.32,22.45 13,22.45 13,22.45M19.04,3.05L17.24,4.84L18.66,6.26L20.45,4.46M11,3.5H13V0.55H11M5,14.5H19V8.5H5V14.5Z" };
|
|
521
|
+
const _hoisted_4$v = { key: 0 };
|
|
522
|
+
function _sfc_render$r(_ctx, _cache, $props, $setup, $data, $options) {
|
|
523
|
+
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
524
|
+
"aria-hidden": $props.title ? null : "true",
|
|
525
|
+
"aria-label": $props.title,
|
|
526
|
+
class: "material-design-icon white-balance-iridescent-icon",
|
|
527
|
+
role: "img",
|
|
528
|
+
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
|
|
529
|
+
}), [
|
|
530
|
+
(openBlock(), createElementBlock("svg", {
|
|
531
|
+
fill: $props.fillColor,
|
|
532
|
+
class: "material-design-icon__svg",
|
|
533
|
+
width: $props.size,
|
|
534
|
+
height: $props.size,
|
|
535
|
+
viewBox: "0 0 24 24"
|
|
536
|
+
}, [
|
|
537
|
+
createElementVNode("path", _hoisted_3$w, [
|
|
538
|
+
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$v, toDisplayString($props.title), 1)) : createCommentVNode("", true)
|
|
539
|
+
])
|
|
540
|
+
], 8, _hoisted_2$z))
|
|
541
|
+
], 16, _hoisted_1$E);
|
|
542
|
+
}
|
|
543
|
+
const WhiteBalanceIridescent = /* @__PURE__ */ _export_sfc(_sfc_main$H, [["render", _sfc_render$r]]);
|
|
544
|
+
const _sfc_main$G = {
|
|
362
545
|
name: "WhiteBalanceSunnyIcon",
|
|
363
546
|
emits: ["click"],
|
|
364
547
|
props: {
|
|
@@ -375,11 +558,11 @@ const _sfc_main$F = {
|
|
|
375
558
|
}
|
|
376
559
|
}
|
|
377
560
|
};
|
|
378
|
-
const _hoisted_1$
|
|
379
|
-
const _hoisted_2$
|
|
380
|
-
const _hoisted_3$
|
|
381
|
-
const _hoisted_4$
|
|
382
|
-
function _sfc_render$
|
|
561
|
+
const _hoisted_1$D = ["aria-hidden", "aria-label"];
|
|
562
|
+
const _hoisted_2$y = ["fill", "width", "height"];
|
|
563
|
+
const _hoisted_3$v = { d: "M3.55 19.09L4.96 20.5L6.76 18.71L5.34 17.29M12 6C8.69 6 6 8.69 6 12S8.69 18 12 18 18 15.31 18 12C18 8.68 15.31 6 12 6M20 13H23V11H20M17.24 18.71L19.04 20.5L20.45 19.09L18.66 17.29M20.45 5L19.04 3.6L17.24 5.39L18.66 6.81M13 1H11V4H13M6.76 5.39L4.96 3.6L3.55 5L5.34 6.81L6.76 5.39M1 13H4V11H1M13 20H11V23H13" };
|
|
564
|
+
const _hoisted_4$u = { key: 0 };
|
|
565
|
+
function _sfc_render$q(_ctx, _cache, $props, $setup, $data, $options) {
|
|
383
566
|
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
384
567
|
"aria-hidden": $props.title ? null : "true",
|
|
385
568
|
"aria-label": $props.title,
|
|
@@ -394,16 +577,16 @@ function _sfc_render$p(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
394
577
|
height: $props.size,
|
|
395
578
|
viewBox: "0 0 24 24"
|
|
396
579
|
}, [
|
|
397
|
-
createElementVNode("path", _hoisted_3$
|
|
398
|
-
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$
|
|
580
|
+
createElementVNode("path", _hoisted_3$v, [
|
|
581
|
+
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$u, toDisplayString($props.title), 1)) : createCommentVNode("", true)
|
|
399
582
|
])
|
|
400
|
-
], 8, _hoisted_2$
|
|
401
|
-
], 16, _hoisted_1$
|
|
583
|
+
], 8, _hoisted_2$y))
|
|
584
|
+
], 16, _hoisted_1$D);
|
|
402
585
|
}
|
|
403
|
-
const WhiteBalanceSunny = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
404
|
-
const _hoisted_1$
|
|
405
|
-
const _hoisted_2$
|
|
406
|
-
const _sfc_main$
|
|
586
|
+
const WhiteBalanceSunny = /* @__PURE__ */ _export_sfc(_sfc_main$G, [["render", _sfc_render$q]]);
|
|
587
|
+
const _hoisted_1$C = { class: "editor-slider" };
|
|
588
|
+
const _hoisted_2$x = ["value", "data-test", "disabled", "aria-label", "min", "max", "step"];
|
|
589
|
+
const _sfc_main$F = /* @__PURE__ */ defineComponent({
|
|
407
590
|
__name: "EditorSlider",
|
|
408
591
|
props: {
|
|
409
592
|
value: {},
|
|
@@ -423,7 +606,7 @@ const _sfc_main$E = /* @__PURE__ */ defineComponent({
|
|
|
423
606
|
emit("input", Number(event.target.value));
|
|
424
607
|
}
|
|
425
608
|
return (_ctx, _cache) => {
|
|
426
|
-
return openBlock(), createElementBlock("div", _hoisted_1$
|
|
609
|
+
return openBlock(), createElementBlock("div", _hoisted_1$C, [
|
|
427
610
|
createElementVNode("input", {
|
|
428
611
|
value: props.value,
|
|
429
612
|
"data-test": __props.dataTest,
|
|
@@ -435,7 +618,7 @@ const _sfc_main$E = /* @__PURE__ */ defineComponent({
|
|
|
435
618
|
step: __props.step,
|
|
436
619
|
onInput,
|
|
437
620
|
onChange: _cache[0] || (_cache[0] = ($event) => emit("commit"))
|
|
438
|
-
}, null, 40, _hoisted_2$
|
|
621
|
+
}, null, 40, _hoisted_2$x),
|
|
439
622
|
createElementVNode("output", null, [
|
|
440
623
|
renderSlot(_ctx.$slots, "preview", {}, () => [
|
|
441
624
|
createTextVNode(toDisplayString(__props.display ?? props.value), 1)
|
|
@@ -445,9 +628,9 @@ const _sfc_main$E = /* @__PURE__ */ defineComponent({
|
|
|
445
628
|
};
|
|
446
629
|
}
|
|
447
630
|
});
|
|
448
|
-
const EditorSlider = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
449
|
-
const _hoisted_1$
|
|
450
|
-
const _sfc_main$
|
|
631
|
+
const EditorSlider = /* @__PURE__ */ _export_sfc(_sfc_main$F, [["__scopeId", "data-v-6562ea60"]]);
|
|
632
|
+
const _hoisted_1$B = ["disabled", "data-test", "aria-pressed"];
|
|
633
|
+
const _sfc_main$E = /* @__PURE__ */ defineComponent({
|
|
451
634
|
__name: "IconTab",
|
|
452
635
|
props: {
|
|
453
636
|
label: {},
|
|
@@ -469,11 +652,11 @@ const _sfc_main$D = /* @__PURE__ */ defineComponent({
|
|
|
469
652
|
}, [
|
|
470
653
|
renderSlot(_ctx.$slots, "default", {}, void 0, true),
|
|
471
654
|
createElementVNode("span", null, toDisplayString(__props.label), 1)
|
|
472
|
-
], 10, _hoisted_1$
|
|
655
|
+
], 10, _hoisted_1$B);
|
|
473
656
|
};
|
|
474
657
|
}
|
|
475
658
|
});
|
|
476
|
-
const IconTab = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
659
|
+
const IconTab = /* @__PURE__ */ _export_sfc(_sfc_main$E, [["__scopeId", "data-v-95889662"]]);
|
|
477
660
|
const gtBuilder = getGettextBuilder().detectLocale();
|
|
478
661
|
[].map((data) => gtBuilder.addTranslation(data.locale, data.json));
|
|
479
662
|
const gt = gtBuilder.build();
|
|
@@ -629,9 +812,9 @@ function useEditorContext() {
|
|
|
629
812
|
}
|
|
630
813
|
return context;
|
|
631
814
|
}
|
|
632
|
-
const _hoisted_1$
|
|
633
|
-
const _hoisted_2$
|
|
634
|
-
const _sfc_main$
|
|
815
|
+
const _hoisted_1$A = { class: "adjust-panel" };
|
|
816
|
+
const _hoisted_2$w = { class: "adjust-panel__tabs" };
|
|
817
|
+
const _sfc_main$D = /* @__PURE__ */ defineComponent({
|
|
635
818
|
__name: "AdjustPanel",
|
|
636
819
|
props: {
|
|
637
820
|
loaded: { type: Boolean }
|
|
@@ -639,11 +822,15 @@ const _sfc_main$C = /* @__PURE__ */ defineComponent({
|
|
|
639
822
|
setup(__props) {
|
|
640
823
|
const context = useEditorContext();
|
|
641
824
|
const adjustments = [
|
|
825
|
+
{ id: "exposure", label: t("Exposure"), icon: CameraIris },
|
|
642
826
|
{ id: "brightness", label: t("Brightness"), icon: WhiteBalanceSunny },
|
|
643
827
|
{ id: "contrast", label: t("Contrast"), icon: ContrastCircle },
|
|
644
|
-
{ id: "saturation", label: t("Saturation"), icon: InvertColors }
|
|
828
|
+
{ id: "saturation", label: t("Saturation"), icon: InvertColors },
|
|
829
|
+
{ id: "temperature", label: t("Temperature"), icon: Thermometer },
|
|
830
|
+
{ id: "tint", label: t("Tint"), icon: WhiteBalanceIridescent },
|
|
831
|
+
{ id: "sharpen", label: t("Sharpen"), icon: ImageFilterCenterFocus }
|
|
645
832
|
];
|
|
646
|
-
const activeAdjustment = shallowRef("
|
|
833
|
+
const activeAdjustment = shallowRef("exposure");
|
|
647
834
|
const display = computed(() => {
|
|
648
835
|
const value = context.state.value.adjustments[activeAdjustment.value];
|
|
649
836
|
return value > 0 ? `+${value}` : `${value}`;
|
|
@@ -659,8 +846,8 @@ const _sfc_main$C = /* @__PURE__ */ defineComponent({
|
|
|
659
846
|
context.commit(context.state.value, adjustments.find((entry) => entry.id === activeAdjustment.value).label);
|
|
660
847
|
}
|
|
661
848
|
return (_ctx, _cache) => {
|
|
662
|
-
return openBlock(), createElementBlock("div", _hoisted_1$
|
|
663
|
-
createElementVNode("div", _hoisted_2$
|
|
849
|
+
return openBlock(), createElementBlock("div", _hoisted_1$A, [
|
|
850
|
+
createElementVNode("div", _hoisted_2$w, [
|
|
664
851
|
(openBlock(), createElementBlock(Fragment, null, renderList(adjustments, (adjustment) => {
|
|
665
852
|
return createVNode(IconTab, {
|
|
666
853
|
key: adjustment.id,
|
|
@@ -693,8 +880,8 @@ const _sfc_main$C = /* @__PURE__ */ defineComponent({
|
|
|
693
880
|
};
|
|
694
881
|
}
|
|
695
882
|
});
|
|
696
|
-
const AdjustPanel = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
697
|
-
const _sfc_main$
|
|
883
|
+
const AdjustPanel = /* @__PURE__ */ _export_sfc(_sfc_main$D, [["__scopeId", "data-v-3ad63bd8"]]);
|
|
884
|
+
const _sfc_main$C = {
|
|
698
885
|
name: "ArrowTopRightIcon",
|
|
699
886
|
emits: ["click"],
|
|
700
887
|
props: {
|
|
@@ -711,15 +898,58 @@ const _sfc_main$B = {
|
|
|
711
898
|
}
|
|
712
899
|
}
|
|
713
900
|
};
|
|
901
|
+
const _hoisted_1$z = ["aria-hidden", "aria-label"];
|
|
902
|
+
const _hoisted_2$v = ["fill", "width", "height"];
|
|
903
|
+
const _hoisted_3$u = { d: "M5,17.59L15.59,7H9V5H19V15H17V8.41L6.41,19L5,17.59Z" };
|
|
904
|
+
const _hoisted_4$t = { key: 0 };
|
|
905
|
+
function _sfc_render$p(_ctx, _cache, $props, $setup, $data, $options) {
|
|
906
|
+
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
907
|
+
"aria-hidden": $props.title ? null : "true",
|
|
908
|
+
"aria-label": $props.title,
|
|
909
|
+
class: "material-design-icon arrow-top-right-icon",
|
|
910
|
+
role: "img",
|
|
911
|
+
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
|
|
912
|
+
}), [
|
|
913
|
+
(openBlock(), createElementBlock("svg", {
|
|
914
|
+
fill: $props.fillColor,
|
|
915
|
+
class: "material-design-icon__svg",
|
|
916
|
+
width: $props.size,
|
|
917
|
+
height: $props.size,
|
|
918
|
+
viewBox: "0 0 24 24"
|
|
919
|
+
}, [
|
|
920
|
+
createElementVNode("path", _hoisted_3$u, [
|
|
921
|
+
$props.title ? (openBlock(), createElementBlock("title", _hoisted_4$t, toDisplayString($props.title), 1)) : createCommentVNode("", true)
|
|
922
|
+
])
|
|
923
|
+
], 8, _hoisted_2$v))
|
|
924
|
+
], 16, _hoisted_1$z);
|
|
925
|
+
}
|
|
926
|
+
const ArrowTopRight = /* @__PURE__ */ _export_sfc(_sfc_main$C, [["render", _sfc_render$p]]);
|
|
927
|
+
const _sfc_main$B = {
|
|
928
|
+
name: "EllipseOutlineIcon",
|
|
929
|
+
emits: ["click"],
|
|
930
|
+
props: {
|
|
931
|
+
title: {
|
|
932
|
+
type: String
|
|
933
|
+
},
|
|
934
|
+
fillColor: {
|
|
935
|
+
type: String,
|
|
936
|
+
default: "currentColor"
|
|
937
|
+
},
|
|
938
|
+
size: {
|
|
939
|
+
type: Number,
|
|
940
|
+
default: 24
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
};
|
|
714
944
|
const _hoisted_1$y = ["aria-hidden", "aria-label"];
|
|
715
945
|
const _hoisted_2$u = ["fill", "width", "height"];
|
|
716
|
-
const _hoisted_3$t = { d: "
|
|
946
|
+
const _hoisted_3$t = { d: "M12,6C16.41,6 20,8.69 20,12C20,15.31 16.41,18 12,18C7.59,18 4,15.31 4,12C4,8.69 7.59,6 12,6M12,4C6.5,4 2,7.58 2,12C2,16.42 6.5,20 12,20C17.5,20 22,16.42 22,12C22,7.58 17.5,4 12,4Z" };
|
|
717
947
|
const _hoisted_4$s = { key: 0 };
|
|
718
948
|
function _sfc_render$o(_ctx, _cache, $props, $setup, $data, $options) {
|
|
719
949
|
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
720
950
|
"aria-hidden": $props.title ? null : "true",
|
|
721
951
|
"aria-label": $props.title,
|
|
722
|
-
class: "material-design-icon
|
|
952
|
+
class: "material-design-icon ellipse-outline-icon",
|
|
723
953
|
role: "img",
|
|
724
954
|
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
|
|
725
955
|
}), [
|
|
@@ -736,9 +966,9 @@ function _sfc_render$o(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
736
966
|
], 8, _hoisted_2$u))
|
|
737
967
|
], 16, _hoisted_1$y);
|
|
738
968
|
}
|
|
739
|
-
const
|
|
969
|
+
const EllipseOutline = /* @__PURE__ */ _export_sfc(_sfc_main$B, [["render", _sfc_render$o]]);
|
|
740
970
|
const _sfc_main$A = {
|
|
741
|
-
name: "
|
|
971
|
+
name: "FormatTextIcon",
|
|
742
972
|
emits: ["click"],
|
|
743
973
|
props: {
|
|
744
974
|
title: {
|
|
@@ -756,13 +986,13 @@ const _sfc_main$A = {
|
|
|
756
986
|
};
|
|
757
987
|
const _hoisted_1$x = ["aria-hidden", "aria-label"];
|
|
758
988
|
const _hoisted_2$t = ["fill", "width", "height"];
|
|
759
|
-
const _hoisted_3$s = { d: "
|
|
989
|
+
const _hoisted_3$s = { d: "M18.5,4L19.66,8.35L18.7,8.61C18.25,7.74 17.79,6.87 17.26,6.43C16.73,6 16.11,6 15.5,6H13V16.5C13,17 13,17.5 13.33,17.75C13.67,18 14.33,18 15,18V19H9V18C9.67,18 10.33,18 10.67,17.75C11,17.5 11,17 11,16.5V6H8.5C7.89,6 7.27,6 6.74,6.43C6.21,6.87 5.75,7.74 5.3,8.61L4.34,8.35L5.5,4H18.5Z" };
|
|
760
990
|
const _hoisted_4$r = { key: 0 };
|
|
761
991
|
function _sfc_render$n(_ctx, _cache, $props, $setup, $data, $options) {
|
|
762
992
|
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
763
993
|
"aria-hidden": $props.title ? null : "true",
|
|
764
994
|
"aria-label": $props.title,
|
|
765
|
-
class: "material-design-icon
|
|
995
|
+
class: "material-design-icon format-text-icon",
|
|
766
996
|
role: "img",
|
|
767
997
|
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
|
|
768
998
|
}), [
|
|
@@ -779,9 +1009,9 @@ function _sfc_render$n(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
779
1009
|
], 8, _hoisted_2$t))
|
|
780
1010
|
], 16, _hoisted_1$x);
|
|
781
1011
|
}
|
|
782
|
-
const
|
|
1012
|
+
const FormatText = /* @__PURE__ */ _export_sfc(_sfc_main$A, [["render", _sfc_render$n]]);
|
|
783
1013
|
const _sfc_main$z = {
|
|
784
|
-
name: "
|
|
1014
|
+
name: "PencilIcon",
|
|
785
1015
|
emits: ["click"],
|
|
786
1016
|
props: {
|
|
787
1017
|
title: {
|
|
@@ -799,13 +1029,13 @@ const _sfc_main$z = {
|
|
|
799
1029
|
};
|
|
800
1030
|
const _hoisted_1$w = ["aria-hidden", "aria-label"];
|
|
801
1031
|
const _hoisted_2$s = ["fill", "width", "height"];
|
|
802
|
-
const _hoisted_3$r = { d: "
|
|
1032
|
+
const _hoisted_3$r = { d: "M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z" };
|
|
803
1033
|
const _hoisted_4$q = { key: 0 };
|
|
804
1034
|
function _sfc_render$m(_ctx, _cache, $props, $setup, $data, $options) {
|
|
805
1035
|
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
806
1036
|
"aria-hidden": $props.title ? null : "true",
|
|
807
1037
|
"aria-label": $props.title,
|
|
808
|
-
class: "material-design-icon
|
|
1038
|
+
class: "material-design-icon pencil-icon",
|
|
809
1039
|
role: "img",
|
|
810
1040
|
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
|
|
811
1041
|
}), [
|
|
@@ -822,9 +1052,9 @@ function _sfc_render$m(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
822
1052
|
], 8, _hoisted_2$s))
|
|
823
1053
|
], 16, _hoisted_1$w);
|
|
824
1054
|
}
|
|
825
|
-
const
|
|
1055
|
+
const Pencil = /* @__PURE__ */ _export_sfc(_sfc_main$z, [["render", _sfc_render$m]]);
|
|
826
1056
|
const _sfc_main$y = {
|
|
827
|
-
name: "
|
|
1057
|
+
name: "RectangleOutlineIcon",
|
|
828
1058
|
emits: ["click"],
|
|
829
1059
|
props: {
|
|
830
1060
|
title: {
|
|
@@ -842,13 +1072,13 @@ const _sfc_main$y = {
|
|
|
842
1072
|
};
|
|
843
1073
|
const _hoisted_1$v = ["aria-hidden", "aria-label"];
|
|
844
1074
|
const _hoisted_2$r = ["fill", "width", "height"];
|
|
845
|
-
const _hoisted_3$q = { d: "
|
|
1075
|
+
const _hoisted_3$q = { d: "M4,6V19H20V6H4M18,17H6V8H18V17Z" };
|
|
846
1076
|
const _hoisted_4$p = { key: 0 };
|
|
847
1077
|
function _sfc_render$l(_ctx, _cache, $props, $setup, $data, $options) {
|
|
848
1078
|
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
849
1079
|
"aria-hidden": $props.title ? null : "true",
|
|
850
1080
|
"aria-label": $props.title,
|
|
851
|
-
class: "material-design-icon
|
|
1081
|
+
class: "material-design-icon rectangle-outline-icon",
|
|
852
1082
|
role: "img",
|
|
853
1083
|
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
|
|
854
1084
|
}), [
|
|
@@ -865,9 +1095,9 @@ function _sfc_render$l(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
865
1095
|
], 8, _hoisted_2$r))
|
|
866
1096
|
], 16, _hoisted_1$v);
|
|
867
1097
|
}
|
|
868
|
-
const
|
|
1098
|
+
const RectangleOutline = /* @__PURE__ */ _export_sfc(_sfc_main$y, [["render", _sfc_render$l]]);
|
|
869
1099
|
const _sfc_main$x = {
|
|
870
|
-
name: "
|
|
1100
|
+
name: "VectorLineIcon",
|
|
871
1101
|
emits: ["click"],
|
|
872
1102
|
props: {
|
|
873
1103
|
title: {
|
|
@@ -885,13 +1115,13 @@ const _sfc_main$x = {
|
|
|
885
1115
|
};
|
|
886
1116
|
const _hoisted_1$u = ["aria-hidden", "aria-label"];
|
|
887
1117
|
const _hoisted_2$q = ["fill", "width", "height"];
|
|
888
|
-
const _hoisted_3$p = { d: "
|
|
1118
|
+
const _hoisted_3$p = { d: "M15,3V7.59L7.59,15H3V21H9V16.42L16.42,9H21V3M17,5H19V7H17M5,17H7V19H5" };
|
|
889
1119
|
const _hoisted_4$o = { key: 0 };
|
|
890
1120
|
function _sfc_render$k(_ctx, _cache, $props, $setup, $data, $options) {
|
|
891
1121
|
return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
|
|
892
1122
|
"aria-hidden": $props.title ? null : "true",
|
|
893
1123
|
"aria-label": $props.title,
|
|
894
|
-
class: "material-design-icon
|
|
1124
|
+
class: "material-design-icon vector-line-icon",
|
|
895
1125
|
role: "img",
|
|
896
1126
|
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
|
|
897
1127
|
}), [
|
|
@@ -908,7 +1138,7 @@ function _sfc_render$k(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
908
1138
|
], 8, _hoisted_2$q))
|
|
909
1139
|
], 16, _hoisted_1$u);
|
|
910
1140
|
}
|
|
911
|
-
const
|
|
1141
|
+
const VectorLine = /* @__PURE__ */ _export_sfc(_sfc_main$x, [["render", _sfc_render$k]]);
|
|
912
1142
|
function useAnnotationColor(context) {
|
|
913
1143
|
function recolorable() {
|
|
914
1144
|
const annotation = context.state.value.annotations.find((entry) => entry.id === context.selectedId.value);
|
|
@@ -963,9 +1193,10 @@ const _sfc_main$w = /* @__PURE__ */ defineComponent({
|
|
|
963
1193
|
{ id: "rectangle", label: t("Rectangle"), icon: RectangleOutline },
|
|
964
1194
|
{ id: "ellipse", label: t("Ellipse"), icon: EllipseOutline },
|
|
965
1195
|
{ id: "arrow", label: t("Arrow"), icon: ArrowTopRight },
|
|
1196
|
+
{ id: "line", label: t("Line"), icon: VectorLine },
|
|
966
1197
|
{ id: "text", label: t("Text"), icon: FormatText }
|
|
967
1198
|
];
|
|
968
|
-
const showStrokeOptions = computed(() => ["draw", "rectangle", "ellipse", "arrow"].includes(context.activeTool.value));
|
|
1199
|
+
const showStrokeOptions = computed(() => ["draw", "rectangle", "ellipse", "arrow", "line"].includes(context.activeTool.value));
|
|
969
1200
|
const viewScale = computed(() => (context.viewFit.value?.scale ?? 1) * context.viewZoom.value);
|
|
970
1201
|
const strokePreview = computed(() => Math.min(PREVIEW_CAP, Math.max(2, context.strokeWidth.value * viewScale.value)));
|
|
971
1202
|
const fontPreview = computed(() => Math.min(PREVIEW_CAP, Math.max(8, context.fontSize.value * viewScale.value)));
|
|
@@ -1050,7 +1281,7 @@ const _sfc_main$w = /* @__PURE__ */ defineComponent({
|
|
|
1050
1281
|
};
|
|
1051
1282
|
}
|
|
1052
1283
|
});
|
|
1053
|
-
const AnnotatePanel = /* @__PURE__ */ _export_sfc(_sfc_main$w, [["__scopeId", "data-v-
|
|
1284
|
+
const AnnotatePanel = /* @__PURE__ */ _export_sfc(_sfc_main$w, [["__scopeId", "data-v-f7e8a194"]]);
|
|
1054
1285
|
const _sfc_main$v = {
|
|
1055
1286
|
name: "FlipHorizontalIcon",
|
|
1056
1287
|
emits: ["click"],
|
|
@@ -1450,6 +1681,43 @@ const PresetChip = /* @__PURE__ */ _export_sfc(_sfc_main$q, [["__scopeId", "data
|
|
|
1450
1681
|
function luma(r, g, b) {
|
|
1451
1682
|
return 0.299 * r + 0.587 * g + 0.114 * b;
|
|
1452
1683
|
}
|
|
1684
|
+
const EXPOSURE_RANGE = 2;
|
|
1685
|
+
const TEMPERATURE_RANGE = 0.25;
|
|
1686
|
+
const TINT_RANGE = 0.25;
|
|
1687
|
+
function tone(imageData) {
|
|
1688
|
+
const { data } = imageData;
|
|
1689
|
+
const exposure = 2 ** ((this.getAttr("exposure") ?? 0) * EXPOSURE_RANGE);
|
|
1690
|
+
const temperature = (this.getAttr("temperature") ?? 0) * TEMPERATURE_RANGE;
|
|
1691
|
+
const tint = (this.getAttr("tint") ?? 0) * TINT_RANGE;
|
|
1692
|
+
const red = exposure * (1 + temperature) * (1 + tint / 2);
|
|
1693
|
+
const green = exposure * (1 - tint);
|
|
1694
|
+
const blue = exposure * (1 - temperature) * (1 + tint / 2);
|
|
1695
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
1696
|
+
data[i] = data[i] * red;
|
|
1697
|
+
data[i + 1] = data[i + 1] * green;
|
|
1698
|
+
data[i + 2] = data[i + 2] * blue;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
const SHARPEN_RANGE = 1.2;
|
|
1702
|
+
function sharpen(imageData) {
|
|
1703
|
+
const amount = (this.getAttr("sharpen") ?? 0) * SHARPEN_RANGE;
|
|
1704
|
+
if (amount === 0) {
|
|
1705
|
+
return;
|
|
1706
|
+
}
|
|
1707
|
+
const { data, width, height } = imageData;
|
|
1708
|
+
const source = new Uint8ClampedArray(data);
|
|
1709
|
+
const stride = width * 4;
|
|
1710
|
+
for (let y = 1; y < height - 1; y++) {
|
|
1711
|
+
for (let x = 1; x < width - 1; x++) {
|
|
1712
|
+
const centre = y * stride + x * 4;
|
|
1713
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
1714
|
+
const i = centre + channel;
|
|
1715
|
+
const neighbours = source[i - 4] + source[i + 4] + source[i - stride] + source[i + stride];
|
|
1716
|
+
data[i] = source[i] * (1 + 4 * amount) - amount * neighbours;
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1453
1721
|
function saturate(imageData) {
|
|
1454
1722
|
const { data } = imageData;
|
|
1455
1723
|
const factor = this.saturation() + 1;
|
|
@@ -1612,6 +1880,14 @@ function buildAnnotationNode(annotation, oriented) {
|
|
|
1612
1880
|
lineCap: "round",
|
|
1613
1881
|
lineJoin: "round"
|
|
1614
1882
|
});
|
|
1883
|
+
case "line":
|
|
1884
|
+
return new Konva.Line({
|
|
1885
|
+
...base,
|
|
1886
|
+
points: [...annotation.points],
|
|
1887
|
+
stroke: annotation.color,
|
|
1888
|
+
strokeWidth: annotation.strokeWidth,
|
|
1889
|
+
lineCap: "round"
|
|
1890
|
+
});
|
|
1615
1891
|
case "arrow":
|
|
1616
1892
|
return new Konva.Arrow({
|
|
1617
1893
|
...base,
|
|
@@ -1670,8 +1946,11 @@ function buildAnnotationNode(annotation, oriented) {
|
|
|
1670
1946
|
}
|
|
1671
1947
|
}
|
|
1672
1948
|
function applyFilters(node, state, pixelRatio = 1) {
|
|
1673
|
-
const { brightness, contrast, saturation } = state.adjustments;
|
|
1949
|
+
const { exposure, brightness, contrast, saturation, temperature, tint } = state.adjustments;
|
|
1674
1950
|
const filters = [];
|
|
1951
|
+
if (exposure !== 0 || temperature !== 0 || tint !== 0) {
|
|
1952
|
+
filters.push(tone);
|
|
1953
|
+
}
|
|
1675
1954
|
if (brightness !== 0) {
|
|
1676
1955
|
filters.push(Konva.Filters.Brighten);
|
|
1677
1956
|
}
|
|
@@ -1703,6 +1982,9 @@ function applyFilters(node, state, pixelRatio = 1) {
|
|
|
1703
1982
|
if (presetFilters !== null) {
|
|
1704
1983
|
filters.push(presetFilters);
|
|
1705
1984
|
}
|
|
1985
|
+
if (state.adjustments.sharpen !== 0) {
|
|
1986
|
+
filters.push(sharpen);
|
|
1987
|
+
}
|
|
1706
1988
|
if (filters.length === 0) {
|
|
1707
1989
|
node.filters([]);
|
|
1708
1990
|
node.clearCache();
|
|
@@ -1712,6 +1994,10 @@ function applyFilters(node, state, pixelRatio = 1) {
|
|
|
1712
1994
|
node.brightness(brightness / 100);
|
|
1713
1995
|
node.contrast(contrast);
|
|
1714
1996
|
node.saturation(saturation / 100);
|
|
1997
|
+
node.setAttr("exposure", exposure / 100);
|
|
1998
|
+
node.setAttr("temperature", temperature / 100);
|
|
1999
|
+
node.setAttr("tint", tint / 100);
|
|
2000
|
+
node.setAttr("sharpen", state.adjustments.sharpen / 100);
|
|
1715
2001
|
if (state.preset === "posterize") {
|
|
1716
2002
|
node.levels(0.02);
|
|
1717
2003
|
}
|
|
@@ -1727,9 +2013,7 @@ function thumbnailKey(state) {
|
|
|
1727
2013
|
crop?.y,
|
|
1728
2014
|
crop?.width,
|
|
1729
2015
|
crop?.height,
|
|
1730
|
-
adjustments
|
|
1731
|
-
adjustments.contrast,
|
|
1732
|
-
adjustments.saturation
|
|
2016
|
+
...Object.values(adjustments)
|
|
1733
2017
|
].join("|");
|
|
1734
2018
|
}
|
|
1735
2019
|
function presetThumbnail(oriented, state, preset, size = 96) {
|
|
@@ -1784,8 +2068,7 @@ function createScene(stage) {
|
|
|
1784
2068
|
viewGroup.clipHeight(void 0);
|
|
1785
2069
|
}
|
|
1786
2070
|
const pixelRatio = options.fastFilters ? Math.min(1, options.scale * (globalThis.devicePixelRatio || 1)) : 1;
|
|
1787
|
-
const
|
|
1788
|
-
const nextFilterKey = `${brightness}|${contrast}|${saturation}|${state.preset}|${pixelRatio}`;
|
|
2071
|
+
const nextFilterKey = `${Object.values(state.adjustments).join("|")}|${state.preset}|${pixelRatio}`;
|
|
1789
2072
|
if (orientedChanged || nextFilterKey !== filterKey) {
|
|
1790
2073
|
applyFilters(imageNode, state, pixelRatio);
|
|
1791
2074
|
filterKey = nextFilterKey;
|
|
@@ -2759,7 +3042,8 @@ const _hoisted_4$3 = { class: "editor-topbar__actions" };
|
|
|
2759
3042
|
const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
2760
3043
|
__name: "EditorTopBar",
|
|
2761
3044
|
props: {
|
|
2762
|
-
loaded: { type: Boolean }
|
|
3045
|
+
loaded: { type: Boolean },
|
|
3046
|
+
saving: { type: Boolean }
|
|
2763
3047
|
},
|
|
2764
3048
|
emits: ["save", "cancel"],
|
|
2765
3049
|
setup(__props, { emit: __emit }) {
|
|
@@ -2942,20 +3226,31 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
|
2942
3226
|
createVNode(unref(NcButton), {
|
|
2943
3227
|
"data-test": "save",
|
|
2944
3228
|
variant: "primary",
|
|
2945
|
-
disabled: !__props.loaded,
|
|
3229
|
+
disabled: !__props.loaded || __props.saving,
|
|
2946
3230
|
onClick: _cache[6] || (_cache[6] = ($event) => emit("save"))
|
|
2947
|
-
}, {
|
|
3231
|
+
}, createSlots({
|
|
2948
3232
|
default: withCtx(() => [
|
|
2949
|
-
createTextVNode(toDisplayString(labels.save), 1)
|
|
3233
|
+
createTextVNode(" " + toDisplayString(labels.save), 1)
|
|
2950
3234
|
]),
|
|
2951
|
-
_:
|
|
2952
|
-
},
|
|
3235
|
+
_: 2
|
|
3236
|
+
}, [
|
|
3237
|
+
__props.saving ? {
|
|
3238
|
+
name: "icon",
|
|
3239
|
+
fn: withCtx(() => [
|
|
3240
|
+
createVNode(unref(NcLoadingIcon), {
|
|
3241
|
+
size: 20,
|
|
3242
|
+
"data-test": "saving"
|
|
3243
|
+
})
|
|
3244
|
+
]),
|
|
3245
|
+
key: "0"
|
|
3246
|
+
} : void 0
|
|
3247
|
+
]), 1032, ["disabled"])
|
|
2953
3248
|
])
|
|
2954
3249
|
]);
|
|
2955
3250
|
};
|
|
2956
3251
|
}
|
|
2957
3252
|
});
|
|
2958
|
-
const EditorTopBar = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-
|
|
3253
|
+
const EditorTopBar = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-50392429"]]);
|
|
2959
3254
|
const _sfc_main$4 = {
|
|
2960
3255
|
name: "ContentCopyIcon",
|
|
2961
3256
|
emits: ["click"],
|
|
@@ -3376,7 +3671,13 @@ async function canvasToBlob(canvas, type = "image/png", quality) {
|
|
|
3376
3671
|
}, type, quality);
|
|
3377
3672
|
});
|
|
3378
3673
|
}
|
|
3674
|
+
async function painted() {
|
|
3675
|
+
await new Promise((resolve) => {
|
|
3676
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve(null)));
|
|
3677
|
+
});
|
|
3678
|
+
}
|
|
3379
3679
|
function useExportImage(deps) {
|
|
3680
|
+
const exporting = ref(false);
|
|
3380
3681
|
async function exportImage(options = {}) {
|
|
3381
3682
|
const oriented = deps.oriented();
|
|
3382
3683
|
if (oriented === null) {
|
|
@@ -3386,6 +3687,15 @@ function useExportImage(deps) {
|
|
|
3386
3687
|
if (source !== null && source.type !== "" && isPristine(deps.getState()) && options.maxSize === void 0 && (options.format === void 0 || options.format === source.type)) {
|
|
3387
3688
|
return { blob: source, width: oriented.width, height: oriented.height, mimeType: source.type };
|
|
3388
3689
|
}
|
|
3690
|
+
exporting.value = true;
|
|
3691
|
+
await painted();
|
|
3692
|
+
try {
|
|
3693
|
+
return await encode(oriented, options);
|
|
3694
|
+
} finally {
|
|
3695
|
+
exporting.value = false;
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
async function encode(oriented, options) {
|
|
3389
3699
|
const canvas = renderToCanvas(oriented, deps.getState(), options.maxSize);
|
|
3390
3700
|
const mimeType = options.format ?? "image/png";
|
|
3391
3701
|
try {
|
|
@@ -3408,7 +3718,7 @@ function useExportImage(deps) {
|
|
|
3408
3718
|
deps.onError(error instanceof Error ? error : new Error(String(error)));
|
|
3409
3719
|
}
|
|
3410
3720
|
}
|
|
3411
|
-
return { exportImage, save };
|
|
3721
|
+
return { exporting, exportImage, save };
|
|
3412
3722
|
}
|
|
3413
3723
|
function useTextEditing(deps) {
|
|
3414
3724
|
const { context } = deps;
|
|
@@ -3896,7 +4206,8 @@ function transformPoints(points, node) {
|
|
|
3896
4206
|
function applyNodeTransform(annotation, node) {
|
|
3897
4207
|
switch (annotation.type) {
|
|
3898
4208
|
case "draw":
|
|
3899
|
-
case "arrow":
|
|
4209
|
+
case "arrow":
|
|
4210
|
+
case "line": {
|
|
3900
4211
|
const points = transformPoints(annotation.points, node);
|
|
3901
4212
|
const scale = (Math.abs(node.scaleX()) + Math.abs(node.scaleY())) / 2;
|
|
3902
4213
|
const strokeWidth = Math.max(1, annotation.strokeWidth * scale);
|
|
@@ -4025,11 +4336,12 @@ const TOOL_LABELS = {
|
|
|
4025
4336
|
rectangle: t("Rectangle"),
|
|
4026
4337
|
ellipse: t("Ellipse"),
|
|
4027
4338
|
arrow: t("Arrow"),
|
|
4339
|
+
line: t("Line"),
|
|
4028
4340
|
sticker: t("Sticker"),
|
|
4029
4341
|
redact: t("Redact")
|
|
4030
4342
|
};
|
|
4031
4343
|
function attachPointerTools(tool, deps) {
|
|
4032
|
-
if (!["draw", "rectangle", "ellipse", "arrow", "text", "sticker", "redact"].includes(tool)) {
|
|
4344
|
+
if (!["draw", "rectangle", "ellipse", "arrow", "line", "text", "sticker", "redact"].includes(tool)) {
|
|
4033
4345
|
return () => {
|
|
4034
4346
|
};
|
|
4035
4347
|
}
|
|
@@ -4047,7 +4359,7 @@ function attachPointerTools(tool, deps) {
|
|
|
4047
4359
|
previewNode = null;
|
|
4048
4360
|
return;
|
|
4049
4361
|
}
|
|
4050
|
-
if (previewNode !== null && (active.type === "draw" || active.type === "arrow")) {
|
|
4362
|
+
if (previewNode !== null && (active.type === "draw" || active.type === "arrow" || active.type === "line")) {
|
|
4051
4363
|
previewNode.points(active.points);
|
|
4052
4364
|
return;
|
|
4053
4365
|
}
|
|
@@ -4078,7 +4390,8 @@ function attachPointerTools(tool, deps) {
|
|
|
4078
4390
|
active = { id: newId(), type: "draw", points: [point.x, point.y], color: options.color, strokeWidth: options.strokeWidth };
|
|
4079
4391
|
break;
|
|
4080
4392
|
case "arrow":
|
|
4081
|
-
|
|
4393
|
+
case "line":
|
|
4394
|
+
active = { id: newId(), type: tool, points: [point.x, point.y, point.x, point.y], color: options.color, strokeWidth: options.strokeWidth };
|
|
4082
4395
|
break;
|
|
4083
4396
|
case "rectangle":
|
|
4084
4397
|
case "ellipse":
|
|
@@ -4125,6 +4438,7 @@ function attachPointerTools(tool, deps) {
|
|
|
4125
4438
|
active.points.push(point.x, point.y);
|
|
4126
4439
|
break;
|
|
4127
4440
|
case "arrow":
|
|
4441
|
+
case "line":
|
|
4128
4442
|
active.points = [start.x, start.y, point.x, point.y];
|
|
4129
4443
|
break;
|
|
4130
4444
|
case "rectangle":
|
|
@@ -4188,7 +4502,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
4188
4502
|
src: {},
|
|
4189
4503
|
label: {},
|
|
4190
4504
|
exportOptions: {},
|
|
4191
|
-
initialState: {}
|
|
4505
|
+
initialState: {},
|
|
4506
|
+
saving: { type: Boolean }
|
|
4192
4507
|
},
|
|
4193
4508
|
emits: ["save", "cancel", "error", "change"],
|
|
4194
4509
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
@@ -4228,7 +4543,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
4228
4543
|
return "grab";
|
|
4229
4544
|
}
|
|
4230
4545
|
const tool = context.activeTool.value;
|
|
4231
|
-
if (["draw", "rectangle", "ellipse", "arrow", "text", "sticker", "redact"].includes(tool)) {
|
|
4546
|
+
if (["draw", "rectangle", "ellipse", "arrow", "line", "text", "sticker", "redact"].includes(tool)) {
|
|
4232
4547
|
return "crosshair";
|
|
4233
4548
|
}
|
|
4234
4549
|
return "default";
|
|
@@ -4272,7 +4587,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
4272
4587
|
viewOptions: () => viewOptions.value,
|
|
4273
4588
|
oriented: () => orientedCanvas.value
|
|
4274
4589
|
});
|
|
4275
|
-
const { exportImage, save: onSave } = useExportImage({
|
|
4590
|
+
const { exporting, exportImage, save: onSave } = useExportImage({
|
|
4276
4591
|
oriented: () => orientedCanvas.value,
|
|
4277
4592
|
getState: () => context.state.value,
|
|
4278
4593
|
source: () => props.src instanceof Blob ? props.src : null,
|
|
@@ -4654,9 +4969,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
4654
4969
|
createVNode(EditorTopBar, {
|
|
4655
4970
|
class: "image-editor__topbar",
|
|
4656
4971
|
loaded: loaded.value,
|
|
4972
|
+
saving: unref(exporting) || __props.saving === true,
|
|
4657
4973
|
onSave: unref(onSave),
|
|
4658
4974
|
onCancel: _cache[2] || (_cache[2] = ($event) => emit("cancel"))
|
|
4659
|
-
}, null, 8, ["loaded", "onSave"]),
|
|
4975
|
+
}, null, 8, ["loaded", "saving", "onSave"]),
|
|
4660
4976
|
createVNode(EditorPanel, {
|
|
4661
4977
|
class: normalizeClass(unref(context).activeMode.value === "filter" ? "image-editor__strip" : "image-editor__controls"),
|
|
4662
4978
|
loaded: loaded.value,
|
|
@@ -4673,7 +4989,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
4673
4989
|
};
|
|
4674
4990
|
}
|
|
4675
4991
|
});
|
|
4676
|
-
const ImageEditor = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
4992
|
+
const ImageEditor = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-5225c517"]]);
|
|
4677
4993
|
export {
|
|
4678
4994
|
ImageEditor,
|
|
4679
4995
|
createInitialState,
|