@sigmaott/base-library-next 2.2.5 → 2.2.7

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 (63) hide show
  1. package/.npmrc +3 -0
  2. package/locales/en.yaml +289 -289
  3. package/locales/vi.yaml +294 -294
  4. package/nuxt.config.ts +18 -18
  5. package/package.json +32 -33
  6. package/public/routes.json +33 -33
  7. package/src/api/axios.ts +3 -3
  8. package/src/api/index.ts +86 -86
  9. package/src/api-client-library/.openapi-generator/FILES +20 -20
  10. package/src/api-client-library/.openapi-generator-ignore +23 -23
  11. package/src/api-client-library/api/health-api.ts +119 -119
  12. package/src/api-client-library/api/presets-api.ts +599 -599
  13. package/src/api-client-library/api/profiles-api.ts +676 -676
  14. package/src/api-client-library/api.ts +20 -20
  15. package/src/api-client-library/base.ts +72 -72
  16. package/src/api-client-library/common.ts +150 -150
  17. package/src/api-client-library/configuration.ts +101 -101
  18. package/src/api-client-library/git_push.sh +57 -57
  19. package/src/api-client-library/index.ts +18 -18
  20. package/src/api-client-library/models/create-preset-dto.ts +223 -223
  21. package/src/api-client-library/models/create-profile-dto.ts +45 -45
  22. package/src/api-client-library/models/health-controller-get-health200-response-info-value.ts +32 -32
  23. package/src/api-client-library/models/health-controller-get-health200-response.ts +51 -51
  24. package/src/api-client-library/models/health-controller-get-health503-response.ts +51 -51
  25. package/src/api-client-library/models/index.ts +7 -7
  26. package/src/api-client-library/models/update-preset-dto.ts +223 -223
  27. package/src/api-client-library/models/update-profile-dto.ts +45 -45
  28. package/src/components/MediaSelection.vue +40 -40
  29. package/src/components/PresetModify.vue +154 -154
  30. package/src/components/PresetTable.vue +114 -114
  31. package/src/components/ProfileAllList.vue +137 -137
  32. package/src/components/ProfileFormModal.vue +79 -79
  33. package/src/components/ProfileModify.vue +152 -152
  34. package/src/components/ProfileTable.vue +68 -68
  35. package/src/components/WatermarkDraggableItem.vue +88 -88
  36. package/src/components/channel/ConfigWatermarkItem.vue +239 -239
  37. package/src/components/channel/WatermarkPreview.vue +19 -19
  38. package/src/components/common/Vue3DraggableResizable/Container.vue +71 -71
  39. package/src/components/common/Vue3DraggableResizable/index.vue +1327 -1327
  40. package/src/components/common/Vue3DraggableResizable/utils/dom.js +63 -63
  41. package/src/components/common/Vue3DraggableResizable/utils/fns.js +37 -37
  42. package/src/components/common/VueDraggableResizable/dom.js +63 -63
  43. package/src/components/common/VueDraggableResizable/fns.js +37 -37
  44. package/src/components/common/VueDraggableResizable/index.vue +958 -958
  45. package/src/components/preset/ConfigItem.vue +956 -956
  46. package/src/components/profile/ConfigItem.vue +765 -765
  47. package/src/components/profile/TableColumns.vue +137 -137
  48. package/src/components/shared/AudioInfoViewer.vue +101 -101
  49. package/src/components/shared/MediaInfoViewer.vue +249 -249
  50. package/src/components/shared/MediaInfoViewerSmall.vue +111 -105
  51. package/src/components/shared/PopoverProfile.vue +17 -17
  52. package/src/components/shared/VideoInfoViewer.vue +136 -136
  53. package/src/components/shared/fileSizeFilter.ts +26 -26
  54. package/src/composables/preset.ts +141 -141
  55. package/src/public/build-time.json +1 -1
  56. package/src/public/favicon.svg +15 -15
  57. package/src/public/logo.svg +9 -9
  58. package/src/public/routes.json +86 -86
  59. package/src/utils/common.ts +175 -175
  60. package/src/utils/config.ts +19 -19
  61. package/src/utils/preset.ts +353 -353
  62. package/src/utils/profile.ts +30 -30
  63. package/tsconfig.json +3 -3
@@ -1,958 +1,958 @@
1
- <script>
2
- import modulo from 'math.modulo'
3
-
4
- import { addEvent, getComputedSize, matchesSelectorToParentElements, removeEvent } from './dom'
5
- import { computeHeight, computeWidth, restrictToBounds, snapToGrid } from './fns'
6
-
7
- const events = {
8
- mouse: {
9
- start: 'mousedown',
10
- move: 'mousemove',
11
- stop: 'mouseup',
12
- },
13
- touch: {
14
- start: 'touchstart',
15
- move: 'touchmove',
16
- stop: 'touchend',
17
- },
18
- }
19
-
20
- const userSelectNone = {
21
- userSelect: 'none',
22
- MozUserSelect: 'none',
23
- WebkitUserSelect: 'none',
24
- MsUserSelect: 'none',
25
- }
26
-
27
- const userSelectAuto = {
28
- userSelect: 'auto',
29
- MozUserSelect: 'auto',
30
- WebkitUserSelect: 'auto',
31
- MsUserSelect: 'auto',
32
- }
33
-
34
- let eventsFor = events.mouse
35
-
36
- export default {
37
- replace: true,
38
- name: 'CommonVueDraggableResizable',
39
- props: {
40
- className: {
41
- type: String,
42
- default: 'vdr',
43
- },
44
- classNameDraggable: {
45
- type: String,
46
- default: 'draggable',
47
- },
48
- classNameResizable: {
49
- type: String,
50
- default: 'resizable',
51
- },
52
- classNameDragging: {
53
- type: String,
54
- default: 'dragging',
55
- },
56
- classNameResizing: {
57
- type: String,
58
- default: 'resizing',
59
- },
60
- classNameActive: {
61
- type: String,
62
- default: 'active',
63
- },
64
- classNameHandle: {
65
- type: String,
66
- default: 'handle',
67
- },
68
- disableUserSelect: {
69
- type: Boolean,
70
- default: true,
71
- },
72
- enableNativeDrag: {
73
- type: Boolean,
74
- default: false,
75
- },
76
- preventDeactivation: {
77
- type: Boolean,
78
- default: false,
79
- },
80
- active: {
81
- type: Boolean,
82
- default: false,
83
- },
84
- draggable: {
85
- type: Boolean,
86
- default: true,
87
- },
88
- resizable: {
89
- type: Boolean,
90
- default: true,
91
- },
92
- lockAspectRatio: {
93
- type: Boolean,
94
- default: false,
95
- },
96
- w: {
97
- type: [Number, String],
98
- default: 200,
99
- validator: (val) => {
100
- if (typeof val === 'number')
101
- return val > 0
102
-
103
- return val === 'auto'
104
- },
105
- },
106
- h: {
107
- type: [Number, String],
108
- default: 200,
109
- validator: (val) => {
110
- if (typeof val === 'number')
111
- return val > 0
112
-
113
- return val === 'auto'
114
- },
115
- },
116
- minWidth: {
117
- type: Number,
118
- default: 0,
119
- validator: val => val >= 0,
120
- },
121
- minHeight: {
122
- type: Number,
123
- default: 0,
124
- validator: val => val >= 0,
125
- },
126
- maxWidth: {
127
- type: Number,
128
- default: null,
129
- validator: val => val >= 0,
130
- },
131
- maxHeight: {
132
- type: Number,
133
- default: null,
134
- validator: val => val >= 0,
135
- },
136
- x: {
137
- type: Number,
138
- default: 0,
139
- },
140
- y: {
141
- type: Number,
142
- default: 0,
143
- },
144
- z: {
145
- type: [String, Number],
146
- default: 'auto',
147
- validator: val => (typeof val === 'string' ? val === 'auto' : val >= 0),
148
- },
149
- handles: {
150
- type: Array,
151
- default: () => ['tl', 'tm', 'tr', 'mr', 'br', 'bm', 'bl', 'ml'],
152
- validator: (val) => {
153
- const s = new Set(['tl', 'tm', 'tr', 'mr', 'br', 'bm', 'bl', 'ml'])
154
-
155
- return new Set(val.filter(h => s.has(h))).size === val.length
156
- },
157
- },
158
- dragHandle: {
159
- type: String,
160
- default: null,
161
- },
162
- dragCancel: {
163
- type: String,
164
- default: null,
165
- },
166
- axis: {
167
- type: String,
168
- default: 'both',
169
- validator: val => ['x', 'y', 'both'].includes(val),
170
- },
171
- grid: {
172
- type: Array,
173
- default: () => [1, 1],
174
- },
175
- parent: {
176
- type: Boolean,
177
- default: false,
178
- },
179
- scale: {
180
- type: [Number, Array],
181
- default: 1,
182
- validator: (val) => {
183
- if (typeof val === 'number')
184
- return val > 0
185
-
186
- return val.length === 2 && val[0] > 0 && val[1] > 0
187
- },
188
- },
189
- onDragStart: {
190
- type: Function,
191
- default: () => true,
192
- },
193
- onDrag: {
194
- type: Function,
195
- default: () => true,
196
- },
197
- onResizeStart: {
198
- type: Function,
199
- default: () => true,
200
- },
201
- onResize: {
202
- type: Function,
203
- default: () => true,
204
- },
205
- },
206
-
207
- data() {
208
- return {
209
- left: this.x,
210
- top: this.y,
211
- right: null,
212
- bottom: null,
213
-
214
- width: null,
215
- height: null,
216
-
217
- widthTouched: false,
218
- heightTouched: false,
219
-
220
- aspectFactor: null,
221
-
222
- parentWidth: null,
223
- parentHeight: null,
224
-
225
- minW: this.minWidth,
226
- minH: this.minHeight,
227
-
228
- maxW: this.maxWidth,
229
- maxH: this.maxHeight,
230
-
231
- handle: null,
232
- enabled: this.active,
233
- resizing: false,
234
- dragging: false,
235
- dragEnable: false,
236
- resizeEnable: false,
237
- zIndex: this.z,
238
- }
239
- },
240
- computed: {
241
- style() {
242
- return {
243
- transform: `translate(${this.left}px, ${this.top}px)`,
244
- width: this.computedWidth,
245
- height: this.computedHeight,
246
- zIndex: this.zIndex,
247
- ...(this.dragging && this.disableUserSelect ? userSelectNone : userSelectAuto),
248
- }
249
- },
250
- actualHandles() {
251
- if (!this.resizable)
252
- return []
253
-
254
- return this.handles
255
- },
256
- computedWidth() {
257
- if (this.w === 'auto') {
258
- if (!this.widthTouched)
259
- return 'auto'
260
- }
261
-
262
- return `${this.width}px`
263
- },
264
- computedHeight() {
265
- if (this.h === 'auto') {
266
- if (!this.heightTouched)
267
- return 'auto'
268
- }
269
-
270
- return `${this.height}px`
271
- },
272
- resizingOnX() {
273
- return Boolean(this.handle) && (this.handle.includes('l') || this.handle.includes('r'))
274
- },
275
- resizingOnY() {
276
- return Boolean(this.handle) && (this.handle.includes('t') || this.handle.includes('b'))
277
- },
278
- isCornerHandle() {
279
- return Boolean(this.handle) && ['tl', 'tr', 'br', 'bl'].includes(this.handle)
280
- },
281
- },
282
-
283
- watch: {
284
- active(val) {
285
- this.enabled = val
286
-
287
- if (val)
288
- this.$emit('activated')
289
-
290
- else
291
- this.$emit('deactivated')
292
- },
293
- z(val) {
294
- if (val >= 0 || val === 'auto')
295
- this.zIndex = val
296
- },
297
- x(val) {
298
- if (this.resizing || this.dragging)
299
- return
300
-
301
- if (this.parent)
302
- this.bounds = this.calcDragLimits()
303
-
304
- this.moveHorizontally(val)
305
- },
306
- y(val) {
307
- if (this.resizing || this.dragging)
308
- return
309
-
310
- if (this.parent)
311
- this.bounds = this.calcDragLimits()
312
-
313
- this.moveVertically(val)
314
- },
315
- lockAspectRatio(val) {
316
- if (val)
317
- this.aspectFactor = this.width / this.height
318
-
319
- else
320
- this.aspectFactor = undefined
321
- },
322
- minWidth(val) {
323
- if (val > 0 && val <= this.width)
324
- this.minW = val
325
- },
326
- minHeight(val) {
327
- if (val > 0 && val <= this.height)
328
- this.minH = val
329
- },
330
- maxWidth(val) {
331
- this.maxW = val
332
- },
333
- maxHeight(val) {
334
- this.maxH = val
335
- },
336
- w(val) {
337
- if (this.resizing || this.dragging)
338
- return
339
-
340
- if (this.parent)
341
- this.bounds = this.calcResizeLimits()
342
-
343
- this.changeWidth(val)
344
- },
345
- h(val) {
346
- if (this.resizing || this.dragging)
347
- return
348
-
349
- if (this.parent)
350
- this.bounds = this.calcResizeLimits()
351
-
352
- this.changeHeight(val)
353
- },
354
-
355
- // Code by Joenix
356
- grid(value) {
357
- // this.draggableAndResizableInit();
358
- },
359
- },
360
-
361
- created() {
362
- if (this.maxWidth && this.minWidth > this.maxWidth)
363
- console.warn('[Vdr warn]: Invalid prop: minWidth cannot be greater than maxWidth')
364
- if (this.maxWidth && this.minHeight > this.maxHeight)
365
- console.warn('[Vdr warn]: Invalid prop: minHeight cannot be greater than maxHeight')
366
-
367
- this.resetBoundsAndMouseState()
368
- },
369
- mounted() {
370
- this.draggableAndResizableInit()
371
-
372
- // addEvent(document.documentElement, 'mousedown', this.deselect)
373
- addEvent(document.documentElement, 'touchend touchcancel', this.deselect)
374
- this.$nextTick(() => {
375
- this.checkParentSize()
376
- })
377
- addEvent(window, 'resize', this.checkParentSize)
378
- },
379
- beforeUnmount() {
380
- removeEvent(document.documentElement, 'mousedown', this.deselect)
381
- removeEvent(document.documentElement, 'touchstart', this.handleUp)
382
- removeEvent(document.documentElement, 'mousemove', this.move)
383
- removeEvent(document.documentElement, 'touchmove', this.move)
384
- removeEvent(document.documentElement, 'mouseup', this.handleUp)
385
- removeEvent(document.documentElement, 'touchend touchcancel', this.deselect)
386
-
387
- removeEvent(window, 'resize', this.checkParentSize)
388
- },
389
-
390
- methods: {
391
- // Code by Joenix
392
- draggableAndResizableInit() {
393
- this.resetBoundsAndMouseState()
394
-
395
- if (!this.enableNativeDrag)
396
- this.$el.ondragstart = () => false
397
-
398
- const [parentWidth, parentHeight] = this.getParentSize()
399
-
400
- this.parentWidth = parentWidth
401
- this.parentHeight = parentHeight
402
-
403
- const [width, height] = getComputedSize(this.$el)
404
-
405
- this.aspectFactor = (this.w !== 'auto' ? this.w : width) / (this.h !== 'auto' ? this.h : height)
406
-
407
- this.width = this.w !== 'auto' ? this.w : width
408
- this.height = this.h !== 'auto' ? this.h : height
409
-
410
- // Code by Joenix
411
- this.$emit('init', this)
412
-
413
- this.right = this.parentWidth - this.width - this.left
414
- this.bottom = this.parentHeight - this.height - this.top
415
-
416
- if (this.active)
417
- this.$emit('activated')
418
- },
419
-
420
- resetBoundsAndMouseState() {
421
- this.mouseClickPosition = { mouseX: 0, mouseY: 0, x: 0, y: 0, w: 0, h: 0 }
422
-
423
- this.bounds = {
424
- minLeft: null,
425
- maxLeft: null,
426
- minRight: null,
427
- maxRight: null,
428
- minTop: null,
429
- maxTop: null,
430
- minBottom: null,
431
- maxBottom: null,
432
- }
433
- },
434
- checkParentSize() {
435
- if (this.parent) {
436
- const [newParentWidth, newParentHeight] = this.getParentSize()
437
-
438
- this.parentWidth = newParentWidth
439
- this.parentHeight = newParentHeight
440
- this.right = this.parentWidth - this.width - this.left
441
- this.bottom = this.parentHeight - this.height - this.top
442
- }
443
- },
444
- getParentSize() {
445
- if (this.parent) {
446
- const style = window.getComputedStyle(this.$el.parentNode, null)
447
-
448
- return [parseInt(style.getPropertyValue('width'), 10), parseInt(style.getPropertyValue('height'), 10)]
449
- }
450
-
451
- return [null, null]
452
- },
453
- elementTouchDown(e) {
454
- eventsFor = events.touch
455
-
456
- this.elementDown(e)
457
- },
458
- elementMouseDown(e) {
459
- eventsFor = events.mouse
460
-
461
- this.elementDown(e)
462
- },
463
- elementDown(e) {
464
- if (e instanceof MouseEvent && e.which !== 1)
465
- return
466
-
467
- const target = e.target || e.srcElement
468
-
469
- if (this.$el.contains(target)) {
470
- if (this.onDragStart(e) === false)
471
- return
472
-
473
- if ((this.dragHandle && !matchesSelectorToParentElements(target, this.dragHandle, this.$el)) || (this.dragCancel && matchesSelectorToParentElements(target, this.dragCancel, this.$el))) {
474
- this.dragging = false
475
-
476
- return
477
- }
478
-
479
- if (!this.enabled) {
480
- this.enabled = true
481
-
482
- this.$emit('activated')
483
- this.$emit('update:active', true)
484
- }
485
-
486
- if (this.draggable)
487
- this.dragEnable = true
488
-
489
- this.mouseClickPosition.mouseX = e.touches ? e.touches[0].pageX : e.pageX
490
- this.mouseClickPosition.mouseY = e.touches ? e.touches[0].pageY : e.pageY
491
-
492
- this.mouseClickPosition.left = this.left
493
- this.mouseClickPosition.right = this.right
494
- this.mouseClickPosition.top = this.top
495
- this.mouseClickPosition.bottom = this.bottom
496
-
497
- if (this.parent)
498
- this.bounds = this.calcDragLimits()
499
-
500
- addEvent(document.documentElement, eventsFor.move, this.move)
501
- addEvent(document.documentElement, eventsFor.stop, this.handleUp)
502
- }
503
- },
504
- calcDragLimits() {
505
- return {
506
- minLeft: modulo(this.left, this.grid[0]),
507
- maxLeft: Math.floor((this.parentWidth - this.width - this.left) / this.grid[0]) * this.grid[0] + this.left,
508
- minRight: modulo(this.right, this.grid[0]),
509
- maxRight: Math.floor((this.parentWidth - this.width - this.right) / this.grid[0]) * this.grid[0] + this.right,
510
- minTop: modulo(this.top, this.grid[1]),
511
- maxTop: Math.floor((this.parentHeight - this.height - this.top) / this.grid[1]) * this.grid[1] + this.top,
512
- minBottom: modulo(this.bottom, this.grid[1]),
513
- maxBottom: Math.floor((this.parentHeight - this.height - this.bottom) / this.grid[1]) * this.grid[1] + this.bottom,
514
- }
515
- },
516
- deselect(e) {
517
- const target = e.target || e.srcElement
518
- const regex = new RegExp(`${this.className}-([trmbl]{2})`, '')
519
-
520
- if (!this.$el.contains(target) && !regex.test(target.className)) {
521
- if (this.enabled && !this.preventDeactivation) {
522
- this.enabled = false
523
-
524
- this.$emit('deactivated')
525
- this.$emit('update:active', false)
526
- }
527
-
528
- removeEvent(document.documentElement, eventsFor.move, this.handleResize)
529
- }
530
-
531
- this.resetBoundsAndMouseState()
532
- },
533
- handleTouchDown(handle, e) {
534
- eventsFor = events.touch
535
-
536
- this.handleDown(handle, e)
537
- },
538
- handleDown(handle, e) {
539
- if (e instanceof MouseEvent && e.which !== 1)
540
- return
541
-
542
- if (this.onResizeStart(handle, e) === false)
543
- return
544
-
545
- if (e.stopPropagation)
546
- e.stopPropagation()
547
-
548
- // Here we avoid a dangerous recursion by faking
549
- // corner handles as middle handles
550
- if (this.lockAspectRatio && !handle.includes('m'))
551
- this.handle = `m${handle.substring(1)}`
552
- else
553
- this.handle = handle
554
-
555
- this.resizeEnable = true
556
-
557
- this.mouseClickPosition.mouseX = e.touches ? e.touches[0].pageX : e.pageX
558
- this.mouseClickPosition.mouseY = e.touches ? e.touches[0].pageY : e.pageY
559
- this.mouseClickPosition.left = this.left
560
- this.mouseClickPosition.right = this.right
561
- this.mouseClickPosition.top = this.top
562
- this.mouseClickPosition.bottom = this.bottom
563
-
564
- this.bounds = this.calcResizeLimits()
565
-
566
- addEvent(document.documentElement, eventsFor.move, this.handleResize)
567
- addEvent(document.documentElement, eventsFor.stop, this.handleUp)
568
- },
569
- calcResizeLimits() {
570
- let minW = this.minW
571
- let minH = this.minH
572
- let maxW = this.maxW
573
- let maxH = this.maxH
574
-
575
- const aspectFactor = this.aspectFactor
576
- const [gridX, gridY] = this.grid
577
- const width = this.width
578
- const height = this.height
579
- const left = this.left
580
- const top = this.top
581
- const right = this.right
582
- const bottom = this.bottom
583
-
584
- if (this.lockAspectRatio) {
585
- if (minW / minH > aspectFactor)
586
- minH = minW / aspectFactor
587
- else
588
- minW = aspectFactor * minH
589
-
590
- if (maxW && maxH) {
591
- maxW = Math.min(maxW, aspectFactor * maxH)
592
- maxH = Math.min(maxH, maxW / aspectFactor)
593
- }
594
- else if (maxW) {
595
- maxH = maxW / aspectFactor
596
- }
597
- else if (maxH) {
598
- maxW = aspectFactor * maxH
599
- }
600
- }
601
-
602
- maxW = maxW - modulo(maxW, gridX)
603
- maxH = maxH - modulo(maxH, gridY)
604
-
605
- const limits = {
606
- minLeft: null,
607
- maxLeft: null,
608
- minTop: null,
609
- maxTop: null,
610
- minRight: null,
611
- maxRight: null,
612
- minBottom: null,
613
- maxBottom: null,
614
- }
615
-
616
- if (this.parent) {
617
- limits.minLeft = modulo(left, gridX)
618
- limits.maxLeft = left + Math.floor((width - minW) / gridX) * gridX
619
- limits.minTop = modulo(top, gridY)
620
- limits.maxTop = top + Math.floor((height - minH) / gridY) * gridY
621
- limits.minRight = modulo(right, gridX)
622
- limits.maxRight = right + Math.floor((width - minW) / gridX) * gridX
623
- limits.minBottom = modulo(bottom, gridY)
624
- limits.maxBottom = bottom + Math.floor((height - minH) / gridY) * gridY
625
-
626
- if (maxW) {
627
- limits.minLeft = Math.max(limits.minLeft, this.parentWidth - right - maxW)
628
- limits.minRight = Math.max(limits.minRight, this.parentWidth - left - maxW)
629
- }
630
-
631
- if (maxH) {
632
- limits.minTop = Math.max(limits.minTop, this.parentHeight - bottom - maxH)
633
- limits.minBottom = Math.max(limits.minBottom, this.parentHeight - top - maxH)
634
- }
635
-
636
- if (this.lockAspectRatio) {
637
- limits.minLeft = Math.max(limits.minLeft, left - top * aspectFactor)
638
- limits.minTop = Math.max(limits.minTop, top - left / aspectFactor)
639
- limits.minRight = Math.max(limits.minRight, right - bottom * aspectFactor)
640
- limits.minBottom = Math.max(limits.minBottom, bottom - right / aspectFactor)
641
- }
642
- }
643
- else {
644
- limits.minLeft = null
645
- limits.maxLeft = left + Math.floor((width - minW) / gridX) * gridX
646
- limits.minTop = null
647
- limits.maxTop = top + Math.floor((height - minH) / gridY) * gridY
648
- limits.minRight = null
649
- limits.maxRight = right + Math.floor((width - minW) / gridX) * gridX
650
- limits.minBottom = null
651
- limits.maxBottom = bottom + Math.floor((height - minH) / gridY) * gridY
652
-
653
- if (maxW) {
654
- limits.minLeft = -(right + maxW)
655
- limits.minRight = -(left + maxW)
656
- }
657
-
658
- if (maxH) {
659
- limits.minTop = -(bottom + maxH)
660
- limits.minBottom = -(top + maxH)
661
- }
662
-
663
- if (this.lockAspectRatio && maxW && maxH) {
664
- limits.minLeft = Math.min(limits.minLeft, -(right + maxW))
665
- limits.minTop = Math.min(limits.minTop, -(maxH + bottom))
666
- limits.minRight = Math.min(limits.minRight, -left - maxW)
667
- limits.minBottom = Math.min(limits.minBottom, -top - maxH)
668
- }
669
- }
670
-
671
- return limits
672
- },
673
- move(e) {
674
- if (this.resizing)
675
- this.handleResize(e)
676
- else if (this.dragEnable)
677
- this.handleDrag(e)
678
- },
679
- handleDrag(e) {
680
- const axis = this.axis
681
- const grid = this.grid
682
- const bounds = this.bounds
683
- const mouseClickPosition = this.mouseClickPosition
684
-
685
- const tmpDeltaX = axis && axis !== 'y' ? mouseClickPosition.mouseX - (e.touches ? e.touches[0].pageX : e.pageX) : 0
686
- const tmpDeltaY = axis && axis !== 'x' ? mouseClickPosition.mouseY - (e.touches ? e.touches[0].pageY : e.pageY) : 0
687
-
688
- const [deltaX, deltaY] = snapToGrid(grid, tmpDeltaX, tmpDeltaY, this.scale)
689
-
690
- const left = restrictToBounds(mouseClickPosition.left - deltaX, bounds.minLeft, bounds.maxLeft)
691
- const top = restrictToBounds(mouseClickPosition.top - deltaY, bounds.minTop, bounds.maxTop)
692
-
693
- if (this.onDrag(left, top) === false)
694
- return
695
-
696
- const right = restrictToBounds(mouseClickPosition.right + deltaX, bounds.minRight, bounds.maxRight)
697
- const bottom = restrictToBounds(mouseClickPosition.bottom + deltaY, bounds.minBottom, bounds.maxBottom)
698
-
699
- this.left = left
700
- this.top = top
701
- this.right = right
702
- this.bottom = bottom
703
-
704
- // this.$emit("dragging", this.left, this.top);
705
-
706
- // Code by Joenix
707
- this.$emit('dragging', this)
708
-
709
- this.dragging = true
710
- },
711
- moveHorizontally(val) {
712
- // should calculate with scale 1.
713
- const [deltaX, _] = snapToGrid(this.grid, val, this.top, 1)
714
-
715
- const left = restrictToBounds(deltaX, this.bounds.minLeft, this.bounds.maxLeft)
716
-
717
- this.left = left
718
- this.right = this.parentWidth - this.width - left
719
- },
720
- moveVertically(val) {
721
- // should calculate with scale 1.
722
- const [_, deltaY] = snapToGrid(this.grid, this.left, val, 1)
723
-
724
- const top = restrictToBounds(deltaY, this.bounds.minTop, this.bounds.maxTop)
725
-
726
- this.top = top
727
- this.bottom = this.parentHeight - this.height - top
728
- },
729
- handleResize(e) {
730
- let left = this.left
731
- let top = this.top
732
- let right = this.right
733
- let bottom = this.bottom
734
-
735
- const mouseClickPosition = this.mouseClickPosition
736
- const lockAspectRatio = this.lockAspectRatio
737
- const aspectFactor = this.aspectFactor
738
-
739
- const tmpDeltaX = mouseClickPosition.mouseX - (e.touches ? e.touches[0].pageX : e.pageX)
740
- const tmpDeltaY = mouseClickPosition.mouseY - (e.touches ? e.touches[0].pageY : e.pageY)
741
-
742
- if (!this.widthTouched && tmpDeltaX)
743
- this.widthTouched = true
744
-
745
- if (!this.heightTouched && tmpDeltaY)
746
- this.heightTouched = true
747
-
748
- const [deltaX, deltaY] = snapToGrid(this.grid, tmpDeltaX, tmpDeltaY, this.scale)
749
-
750
- if (this.handle.includes('b')) {
751
- bottom = restrictToBounds(mouseClickPosition.bottom + deltaY, this.bounds.minBottom, this.bounds.maxBottom)
752
-
753
- if (this.lockAspectRatio && this.resizingOnY)
754
- right = this.right - (this.bottom - bottom) * aspectFactor
755
- }
756
- else if (this.handle.includes('t')) {
757
- top = restrictToBounds(mouseClickPosition.top - deltaY, this.bounds.minTop, this.bounds.maxTop)
758
-
759
- if (this.lockAspectRatio && this.resizingOnY)
760
- left = this.left - (this.top - top) * aspectFactor
761
- }
762
-
763
- if (this.handle.includes('r')) {
764
- right = restrictToBounds(mouseClickPosition.right + deltaX, this.bounds.minRight, this.bounds.maxRight)
765
-
766
- if (this.lockAspectRatio && this.resizingOnX)
767
- bottom = this.bottom - (this.right - right) / aspectFactor
768
- }
769
- else if (this.handle.includes('l')) {
770
- left = restrictToBounds(mouseClickPosition.left - deltaX, this.bounds.minLeft, this.bounds.maxLeft)
771
-
772
- if (this.lockAspectRatio && this.resizingOnX)
773
- top = this.top - (this.left - left) / aspectFactor
774
- }
775
-
776
- const width = computeWidth(this.parentWidth, left, right)
777
- const height = computeHeight(this.parentHeight, top, bottom)
778
-
779
- if (this.onResize(this.handle, left, top, width, height) === false)
780
- return
781
-
782
- this.left = left
783
- this.top = top
784
- this.right = right
785
- this.bottom = bottom
786
- this.width = width
787
- this.height = height
788
-
789
- // this.$emit("resizing", this.left, this.top, this.width, this.height);
790
-
791
- // Code by Joenix
792
- this.$emit('resizing', this)
793
-
794
- this.resizing = true
795
- },
796
- changeWidth(val) {
797
- // should calculate with scale 1.
798
- const [newWidth, _] = snapToGrid(this.grid, val, 0, 1)
799
-
800
- const right = restrictToBounds(this.parentWidth - newWidth - this.left, this.bounds.minRight, this.bounds.maxRight)
801
- let bottom = this.bottom
802
-
803
- if (this.lockAspectRatio)
804
- bottom = this.bottom - (this.right - right) / this.aspectFactor
805
-
806
- const width = computeWidth(this.parentWidth, this.left, right)
807
- const height = computeHeight(this.parentHeight, this.top, bottom)
808
-
809
- this.right = right
810
- this.bottom = bottom
811
- this.width = width
812
- this.height = height
813
- },
814
- changeHeight(val) {
815
- // should calculate with scale 1.
816
- const [_, newHeight] = snapToGrid(this.grid, 0, val, 1)
817
-
818
- const bottom = restrictToBounds(this.parentHeight - newHeight - this.top, this.bounds.minBottom, this.bounds.maxBottom)
819
- let right = this.right
820
-
821
- if (this.lockAspectRatio)
822
- right = this.right - (this.bottom - bottom) * this.aspectFactor
823
-
824
- const width = computeWidth(this.parentWidth, this.left, right)
825
- const height = computeHeight(this.parentHeight, this.top, bottom)
826
-
827
- this.right = right
828
- this.bottom = bottom
829
- this.width = width
830
- this.height = height
831
- },
832
- handleUp(e) {
833
- this.handle = null
834
-
835
- this.resetBoundsAndMouseState()
836
-
837
- this.dragEnable = false
838
- this.resizeEnable = false
839
-
840
- if (this.resizing) {
841
- this.resizing = false
842
- this.$emit('resizestop', this.left, this.top, this.width, this.height)
843
- }
844
-
845
- if (this.dragging) {
846
- this.dragging = false
847
- this.$emit('dragstop', this.left, this.top)
848
- }
849
-
850
- // Code by Joenix
851
- this.$emit('stoping', this)
852
-
853
- removeEvent(document.documentElement, eventsFor.move, this.handleResize)
854
- },
855
- },
856
- }
857
- </script>
858
-
859
- <template>
860
- <div
861
- :style="style"
862
- :class="[
863
- {
864
- [classNameActive]: enabled,
865
- [classNameDragging]: dragging,
866
- [classNameResizing]: resizing,
867
- [classNameDraggable]: draggable,
868
- [classNameResizable]: resizable,
869
- },
870
- className,
871
- ]"
872
- @mousedown="elementMouseDown"
873
- @touchstart="elementTouchDown"
874
- >
875
- <div
876
- v-for="handle in actualHandles"
877
- :key="handle"
878
- :class="[classNameHandle, `${classNameHandle}-${handle}`]"
879
- :style="{ display: enabled ? 'block' : 'none' }"
880
- @mousedown.stop.prevent="handleDown(handle, $event)"
881
- @touchstart.stop.prevent="handleTouchDown(handle, $event)"
882
- >
883
- <slot :name="handle" />
884
- </div>
885
- <slot />
886
- </div>
887
- </template>
888
-
889
- <style>
890
- .vdr {
891
- touch-action: none;
892
- position: absolute;
893
- box-sizing: border-box;
894
- border: 1px dashed white;
895
- }
896
- .handle {
897
- box-sizing: border-box;
898
- position: absolute;
899
- width: 10px;
900
- height: 10px;
901
- background: #EEE;
902
- border: 1px solid #333;
903
- }
904
- .handle-tl {
905
- top: -10px;
906
- left: -10px;
907
- cursor: nw-resize;
908
- }
909
- .handle-tm {
910
- top: -10px;
911
- left: 50%;
912
- margin-left: -5px;
913
- cursor: n-resize;
914
- }
915
- .handle-tr {
916
- top: -10px;
917
- right: -10px;
918
- cursor: ne-resize;
919
- }
920
- .handle-ml {
921
- top: 50%;
922
- margin-top: -5px;
923
- left: -10px;
924
- cursor: w-resize;
925
- }
926
- .handle-mr {
927
- top: 50%;
928
- margin-top: -5px;
929
- right: -10px;
930
- cursor: e-resize;
931
- }
932
- .handle-bl {
933
- bottom: -10px;
934
- left: -10px;
935
- cursor: sw-resize;
936
- }
937
- .handle-bm {
938
- bottom: -10px;
939
- left: 50%;
940
- margin-left: -5px;
941
- cursor: s-resize;
942
- }
943
- .handle-br {
944
- bottom: -10px;
945
- right: -10px;
946
- cursor: se-resize;
947
- }
948
- @media only screen and (max-width: 768px) {
949
- [class*="handle-"]:before {
950
- content: '';
951
- left: -10px;
952
- right: -10px;
953
- bottom: -10px;
954
- top: -10px;
955
- position: absolute;
956
- }
957
- }
958
- </style>
1
+ <script>
2
+ import modulo from 'math.modulo'
3
+
4
+ import { addEvent, getComputedSize, matchesSelectorToParentElements, removeEvent } from './dom'
5
+ import { computeHeight, computeWidth, restrictToBounds, snapToGrid } from './fns'
6
+
7
+ const events = {
8
+ mouse: {
9
+ start: 'mousedown',
10
+ move: 'mousemove',
11
+ stop: 'mouseup',
12
+ },
13
+ touch: {
14
+ start: 'touchstart',
15
+ move: 'touchmove',
16
+ stop: 'touchend',
17
+ },
18
+ }
19
+
20
+ const userSelectNone = {
21
+ userSelect: 'none',
22
+ MozUserSelect: 'none',
23
+ WebkitUserSelect: 'none',
24
+ MsUserSelect: 'none',
25
+ }
26
+
27
+ const userSelectAuto = {
28
+ userSelect: 'auto',
29
+ MozUserSelect: 'auto',
30
+ WebkitUserSelect: 'auto',
31
+ MsUserSelect: 'auto',
32
+ }
33
+
34
+ let eventsFor = events.mouse
35
+
36
+ export default {
37
+ replace: true,
38
+ name: 'CommonVueDraggableResizable',
39
+ props: {
40
+ className: {
41
+ type: String,
42
+ default: 'vdr',
43
+ },
44
+ classNameDraggable: {
45
+ type: String,
46
+ default: 'draggable',
47
+ },
48
+ classNameResizable: {
49
+ type: String,
50
+ default: 'resizable',
51
+ },
52
+ classNameDragging: {
53
+ type: String,
54
+ default: 'dragging',
55
+ },
56
+ classNameResizing: {
57
+ type: String,
58
+ default: 'resizing',
59
+ },
60
+ classNameActive: {
61
+ type: String,
62
+ default: 'active',
63
+ },
64
+ classNameHandle: {
65
+ type: String,
66
+ default: 'handle',
67
+ },
68
+ disableUserSelect: {
69
+ type: Boolean,
70
+ default: true,
71
+ },
72
+ enableNativeDrag: {
73
+ type: Boolean,
74
+ default: false,
75
+ },
76
+ preventDeactivation: {
77
+ type: Boolean,
78
+ default: false,
79
+ },
80
+ active: {
81
+ type: Boolean,
82
+ default: false,
83
+ },
84
+ draggable: {
85
+ type: Boolean,
86
+ default: true,
87
+ },
88
+ resizable: {
89
+ type: Boolean,
90
+ default: true,
91
+ },
92
+ lockAspectRatio: {
93
+ type: Boolean,
94
+ default: false,
95
+ },
96
+ w: {
97
+ type: [Number, String],
98
+ default: 200,
99
+ validator: (val) => {
100
+ if (typeof val === 'number')
101
+ return val > 0
102
+
103
+ return val === 'auto'
104
+ },
105
+ },
106
+ h: {
107
+ type: [Number, String],
108
+ default: 200,
109
+ validator: (val) => {
110
+ if (typeof val === 'number')
111
+ return val > 0
112
+
113
+ return val === 'auto'
114
+ },
115
+ },
116
+ minWidth: {
117
+ type: Number,
118
+ default: 0,
119
+ validator: val => val >= 0,
120
+ },
121
+ minHeight: {
122
+ type: Number,
123
+ default: 0,
124
+ validator: val => val >= 0,
125
+ },
126
+ maxWidth: {
127
+ type: Number,
128
+ default: null,
129
+ validator: val => val >= 0,
130
+ },
131
+ maxHeight: {
132
+ type: Number,
133
+ default: null,
134
+ validator: val => val >= 0,
135
+ },
136
+ x: {
137
+ type: Number,
138
+ default: 0,
139
+ },
140
+ y: {
141
+ type: Number,
142
+ default: 0,
143
+ },
144
+ z: {
145
+ type: [String, Number],
146
+ default: 'auto',
147
+ validator: val => (typeof val === 'string' ? val === 'auto' : val >= 0),
148
+ },
149
+ handles: {
150
+ type: Array,
151
+ default: () => ['tl', 'tm', 'tr', 'mr', 'br', 'bm', 'bl', 'ml'],
152
+ validator: (val) => {
153
+ const s = new Set(['tl', 'tm', 'tr', 'mr', 'br', 'bm', 'bl', 'ml'])
154
+
155
+ return new Set(val.filter(h => s.has(h))).size === val.length
156
+ },
157
+ },
158
+ dragHandle: {
159
+ type: String,
160
+ default: null,
161
+ },
162
+ dragCancel: {
163
+ type: String,
164
+ default: null,
165
+ },
166
+ axis: {
167
+ type: String,
168
+ default: 'both',
169
+ validator: val => ['x', 'y', 'both'].includes(val),
170
+ },
171
+ grid: {
172
+ type: Array,
173
+ default: () => [1, 1],
174
+ },
175
+ parent: {
176
+ type: Boolean,
177
+ default: false,
178
+ },
179
+ scale: {
180
+ type: [Number, Array],
181
+ default: 1,
182
+ validator: (val) => {
183
+ if (typeof val === 'number')
184
+ return val > 0
185
+
186
+ return val.length === 2 && val[0] > 0 && val[1] > 0
187
+ },
188
+ },
189
+ onDragStart: {
190
+ type: Function,
191
+ default: () => true,
192
+ },
193
+ onDrag: {
194
+ type: Function,
195
+ default: () => true,
196
+ },
197
+ onResizeStart: {
198
+ type: Function,
199
+ default: () => true,
200
+ },
201
+ onResize: {
202
+ type: Function,
203
+ default: () => true,
204
+ },
205
+ },
206
+
207
+ data() {
208
+ return {
209
+ left: this.x,
210
+ top: this.y,
211
+ right: null,
212
+ bottom: null,
213
+
214
+ width: null,
215
+ height: null,
216
+
217
+ widthTouched: false,
218
+ heightTouched: false,
219
+
220
+ aspectFactor: null,
221
+
222
+ parentWidth: null,
223
+ parentHeight: null,
224
+
225
+ minW: this.minWidth,
226
+ minH: this.minHeight,
227
+
228
+ maxW: this.maxWidth,
229
+ maxH: this.maxHeight,
230
+
231
+ handle: null,
232
+ enabled: this.active,
233
+ resizing: false,
234
+ dragging: false,
235
+ dragEnable: false,
236
+ resizeEnable: false,
237
+ zIndex: this.z,
238
+ }
239
+ },
240
+ computed: {
241
+ style() {
242
+ return {
243
+ transform: `translate(${this.left}px, ${this.top}px)`,
244
+ width: this.computedWidth,
245
+ height: this.computedHeight,
246
+ zIndex: this.zIndex,
247
+ ...(this.dragging && this.disableUserSelect ? userSelectNone : userSelectAuto),
248
+ }
249
+ },
250
+ actualHandles() {
251
+ if (!this.resizable)
252
+ return []
253
+
254
+ return this.handles
255
+ },
256
+ computedWidth() {
257
+ if (this.w === 'auto') {
258
+ if (!this.widthTouched)
259
+ return 'auto'
260
+ }
261
+
262
+ return `${this.width}px`
263
+ },
264
+ computedHeight() {
265
+ if (this.h === 'auto') {
266
+ if (!this.heightTouched)
267
+ return 'auto'
268
+ }
269
+
270
+ return `${this.height}px`
271
+ },
272
+ resizingOnX() {
273
+ return Boolean(this.handle) && (this.handle.includes('l') || this.handle.includes('r'))
274
+ },
275
+ resizingOnY() {
276
+ return Boolean(this.handle) && (this.handle.includes('t') || this.handle.includes('b'))
277
+ },
278
+ isCornerHandle() {
279
+ return Boolean(this.handle) && ['tl', 'tr', 'br', 'bl'].includes(this.handle)
280
+ },
281
+ },
282
+
283
+ watch: {
284
+ active(val) {
285
+ this.enabled = val
286
+
287
+ if (val)
288
+ this.$emit('activated')
289
+
290
+ else
291
+ this.$emit('deactivated')
292
+ },
293
+ z(val) {
294
+ if (val >= 0 || val === 'auto')
295
+ this.zIndex = val
296
+ },
297
+ x(val) {
298
+ if (this.resizing || this.dragging)
299
+ return
300
+
301
+ if (this.parent)
302
+ this.bounds = this.calcDragLimits()
303
+
304
+ this.moveHorizontally(val)
305
+ },
306
+ y(val) {
307
+ if (this.resizing || this.dragging)
308
+ return
309
+
310
+ if (this.parent)
311
+ this.bounds = this.calcDragLimits()
312
+
313
+ this.moveVertically(val)
314
+ },
315
+ lockAspectRatio(val) {
316
+ if (val)
317
+ this.aspectFactor = this.width / this.height
318
+
319
+ else
320
+ this.aspectFactor = undefined
321
+ },
322
+ minWidth(val) {
323
+ if (val > 0 && val <= this.width)
324
+ this.minW = val
325
+ },
326
+ minHeight(val) {
327
+ if (val > 0 && val <= this.height)
328
+ this.minH = val
329
+ },
330
+ maxWidth(val) {
331
+ this.maxW = val
332
+ },
333
+ maxHeight(val) {
334
+ this.maxH = val
335
+ },
336
+ w(val) {
337
+ if (this.resizing || this.dragging)
338
+ return
339
+
340
+ if (this.parent)
341
+ this.bounds = this.calcResizeLimits()
342
+
343
+ this.changeWidth(val)
344
+ },
345
+ h(val) {
346
+ if (this.resizing || this.dragging)
347
+ return
348
+
349
+ if (this.parent)
350
+ this.bounds = this.calcResizeLimits()
351
+
352
+ this.changeHeight(val)
353
+ },
354
+
355
+ // Code by Joenix
356
+ grid(value) {
357
+ // this.draggableAndResizableInit();
358
+ },
359
+ },
360
+
361
+ created() {
362
+ if (this.maxWidth && this.minWidth > this.maxWidth)
363
+ console.warn('[Vdr warn]: Invalid prop: minWidth cannot be greater than maxWidth')
364
+ if (this.maxWidth && this.minHeight > this.maxHeight)
365
+ console.warn('[Vdr warn]: Invalid prop: minHeight cannot be greater than maxHeight')
366
+
367
+ this.resetBoundsAndMouseState()
368
+ },
369
+ mounted() {
370
+ this.draggableAndResizableInit()
371
+
372
+ // addEvent(document.documentElement, 'mousedown', this.deselect)
373
+ addEvent(document.documentElement, 'touchend touchcancel', this.deselect)
374
+ this.$nextTick(() => {
375
+ this.checkParentSize()
376
+ })
377
+ addEvent(window, 'resize', this.checkParentSize)
378
+ },
379
+ beforeUnmount() {
380
+ removeEvent(document.documentElement, 'mousedown', this.deselect)
381
+ removeEvent(document.documentElement, 'touchstart', this.handleUp)
382
+ removeEvent(document.documentElement, 'mousemove', this.move)
383
+ removeEvent(document.documentElement, 'touchmove', this.move)
384
+ removeEvent(document.documentElement, 'mouseup', this.handleUp)
385
+ removeEvent(document.documentElement, 'touchend touchcancel', this.deselect)
386
+
387
+ removeEvent(window, 'resize', this.checkParentSize)
388
+ },
389
+
390
+ methods: {
391
+ // Code by Joenix
392
+ draggableAndResizableInit() {
393
+ this.resetBoundsAndMouseState()
394
+
395
+ if (!this.enableNativeDrag)
396
+ this.$el.ondragstart = () => false
397
+
398
+ const [parentWidth, parentHeight] = this.getParentSize()
399
+
400
+ this.parentWidth = parentWidth
401
+ this.parentHeight = parentHeight
402
+
403
+ const [width, height] = getComputedSize(this.$el)
404
+
405
+ this.aspectFactor = (this.w !== 'auto' ? this.w : width) / (this.h !== 'auto' ? this.h : height)
406
+
407
+ this.width = this.w !== 'auto' ? this.w : width
408
+ this.height = this.h !== 'auto' ? this.h : height
409
+
410
+ // Code by Joenix
411
+ this.$emit('init', this)
412
+
413
+ this.right = this.parentWidth - this.width - this.left
414
+ this.bottom = this.parentHeight - this.height - this.top
415
+
416
+ if (this.active)
417
+ this.$emit('activated')
418
+ },
419
+
420
+ resetBoundsAndMouseState() {
421
+ this.mouseClickPosition = { mouseX: 0, mouseY: 0, x: 0, y: 0, w: 0, h: 0 }
422
+
423
+ this.bounds = {
424
+ minLeft: null,
425
+ maxLeft: null,
426
+ minRight: null,
427
+ maxRight: null,
428
+ minTop: null,
429
+ maxTop: null,
430
+ minBottom: null,
431
+ maxBottom: null,
432
+ }
433
+ },
434
+ checkParentSize() {
435
+ if (this.parent) {
436
+ const [newParentWidth, newParentHeight] = this.getParentSize()
437
+
438
+ this.parentWidth = newParentWidth
439
+ this.parentHeight = newParentHeight
440
+ this.right = this.parentWidth - this.width - this.left
441
+ this.bottom = this.parentHeight - this.height - this.top
442
+ }
443
+ },
444
+ getParentSize() {
445
+ if (this.parent) {
446
+ const style = window.getComputedStyle(this.$el.parentNode, null)
447
+
448
+ return [parseInt(style.getPropertyValue('width'), 10), parseInt(style.getPropertyValue('height'), 10)]
449
+ }
450
+
451
+ return [null, null]
452
+ },
453
+ elementTouchDown(e) {
454
+ eventsFor = events.touch
455
+
456
+ this.elementDown(e)
457
+ },
458
+ elementMouseDown(e) {
459
+ eventsFor = events.mouse
460
+
461
+ this.elementDown(e)
462
+ },
463
+ elementDown(e) {
464
+ if (e instanceof MouseEvent && e.which !== 1)
465
+ return
466
+
467
+ const target = e.target || e.srcElement
468
+
469
+ if (this.$el.contains(target)) {
470
+ if (this.onDragStart(e) === false)
471
+ return
472
+
473
+ if ((this.dragHandle && !matchesSelectorToParentElements(target, this.dragHandle, this.$el)) || (this.dragCancel && matchesSelectorToParentElements(target, this.dragCancel, this.$el))) {
474
+ this.dragging = false
475
+
476
+ return
477
+ }
478
+
479
+ if (!this.enabled) {
480
+ this.enabled = true
481
+
482
+ this.$emit('activated')
483
+ this.$emit('update:active', true)
484
+ }
485
+
486
+ if (this.draggable)
487
+ this.dragEnable = true
488
+
489
+ this.mouseClickPosition.mouseX = e.touches ? e.touches[0].pageX : e.pageX
490
+ this.mouseClickPosition.mouseY = e.touches ? e.touches[0].pageY : e.pageY
491
+
492
+ this.mouseClickPosition.left = this.left
493
+ this.mouseClickPosition.right = this.right
494
+ this.mouseClickPosition.top = this.top
495
+ this.mouseClickPosition.bottom = this.bottom
496
+
497
+ if (this.parent)
498
+ this.bounds = this.calcDragLimits()
499
+
500
+ addEvent(document.documentElement, eventsFor.move, this.move)
501
+ addEvent(document.documentElement, eventsFor.stop, this.handleUp)
502
+ }
503
+ },
504
+ calcDragLimits() {
505
+ return {
506
+ minLeft: modulo(this.left, this.grid[0]),
507
+ maxLeft: Math.floor((this.parentWidth - this.width - this.left) / this.grid[0]) * this.grid[0] + this.left,
508
+ minRight: modulo(this.right, this.grid[0]),
509
+ maxRight: Math.floor((this.parentWidth - this.width - this.right) / this.grid[0]) * this.grid[0] + this.right,
510
+ minTop: modulo(this.top, this.grid[1]),
511
+ maxTop: Math.floor((this.parentHeight - this.height - this.top) / this.grid[1]) * this.grid[1] + this.top,
512
+ minBottom: modulo(this.bottom, this.grid[1]),
513
+ maxBottom: Math.floor((this.parentHeight - this.height - this.bottom) / this.grid[1]) * this.grid[1] + this.bottom,
514
+ }
515
+ },
516
+ deselect(e) {
517
+ const target = e.target || e.srcElement
518
+ const regex = new RegExp(`${this.className}-([trmbl]{2})`, '')
519
+
520
+ if (!this.$el.contains(target) && !regex.test(target.className)) {
521
+ if (this.enabled && !this.preventDeactivation) {
522
+ this.enabled = false
523
+
524
+ this.$emit('deactivated')
525
+ this.$emit('update:active', false)
526
+ }
527
+
528
+ removeEvent(document.documentElement, eventsFor.move, this.handleResize)
529
+ }
530
+
531
+ this.resetBoundsAndMouseState()
532
+ },
533
+ handleTouchDown(handle, e) {
534
+ eventsFor = events.touch
535
+
536
+ this.handleDown(handle, e)
537
+ },
538
+ handleDown(handle, e) {
539
+ if (e instanceof MouseEvent && e.which !== 1)
540
+ return
541
+
542
+ if (this.onResizeStart(handle, e) === false)
543
+ return
544
+
545
+ if (e.stopPropagation)
546
+ e.stopPropagation()
547
+
548
+ // Here we avoid a dangerous recursion by faking
549
+ // corner handles as middle handles
550
+ if (this.lockAspectRatio && !handle.includes('m'))
551
+ this.handle = `m${handle.substring(1)}`
552
+ else
553
+ this.handle = handle
554
+
555
+ this.resizeEnable = true
556
+
557
+ this.mouseClickPosition.mouseX = e.touches ? e.touches[0].pageX : e.pageX
558
+ this.mouseClickPosition.mouseY = e.touches ? e.touches[0].pageY : e.pageY
559
+ this.mouseClickPosition.left = this.left
560
+ this.mouseClickPosition.right = this.right
561
+ this.mouseClickPosition.top = this.top
562
+ this.mouseClickPosition.bottom = this.bottom
563
+
564
+ this.bounds = this.calcResizeLimits()
565
+
566
+ addEvent(document.documentElement, eventsFor.move, this.handleResize)
567
+ addEvent(document.documentElement, eventsFor.stop, this.handleUp)
568
+ },
569
+ calcResizeLimits() {
570
+ let minW = this.minW
571
+ let minH = this.minH
572
+ let maxW = this.maxW
573
+ let maxH = this.maxH
574
+
575
+ const aspectFactor = this.aspectFactor
576
+ const [gridX, gridY] = this.grid
577
+ const width = this.width
578
+ const height = this.height
579
+ const left = this.left
580
+ const top = this.top
581
+ const right = this.right
582
+ const bottom = this.bottom
583
+
584
+ if (this.lockAspectRatio) {
585
+ if (minW / minH > aspectFactor)
586
+ minH = minW / aspectFactor
587
+ else
588
+ minW = aspectFactor * minH
589
+
590
+ if (maxW && maxH) {
591
+ maxW = Math.min(maxW, aspectFactor * maxH)
592
+ maxH = Math.min(maxH, maxW / aspectFactor)
593
+ }
594
+ else if (maxW) {
595
+ maxH = maxW / aspectFactor
596
+ }
597
+ else if (maxH) {
598
+ maxW = aspectFactor * maxH
599
+ }
600
+ }
601
+
602
+ maxW = maxW - modulo(maxW, gridX)
603
+ maxH = maxH - modulo(maxH, gridY)
604
+
605
+ const limits = {
606
+ minLeft: null,
607
+ maxLeft: null,
608
+ minTop: null,
609
+ maxTop: null,
610
+ minRight: null,
611
+ maxRight: null,
612
+ minBottom: null,
613
+ maxBottom: null,
614
+ }
615
+
616
+ if (this.parent) {
617
+ limits.minLeft = modulo(left, gridX)
618
+ limits.maxLeft = left + Math.floor((width - minW) / gridX) * gridX
619
+ limits.minTop = modulo(top, gridY)
620
+ limits.maxTop = top + Math.floor((height - minH) / gridY) * gridY
621
+ limits.minRight = modulo(right, gridX)
622
+ limits.maxRight = right + Math.floor((width - minW) / gridX) * gridX
623
+ limits.minBottom = modulo(bottom, gridY)
624
+ limits.maxBottom = bottom + Math.floor((height - minH) / gridY) * gridY
625
+
626
+ if (maxW) {
627
+ limits.minLeft = Math.max(limits.minLeft, this.parentWidth - right - maxW)
628
+ limits.minRight = Math.max(limits.minRight, this.parentWidth - left - maxW)
629
+ }
630
+
631
+ if (maxH) {
632
+ limits.minTop = Math.max(limits.minTop, this.parentHeight - bottom - maxH)
633
+ limits.minBottom = Math.max(limits.minBottom, this.parentHeight - top - maxH)
634
+ }
635
+
636
+ if (this.lockAspectRatio) {
637
+ limits.minLeft = Math.max(limits.minLeft, left - top * aspectFactor)
638
+ limits.minTop = Math.max(limits.minTop, top - left / aspectFactor)
639
+ limits.minRight = Math.max(limits.minRight, right - bottom * aspectFactor)
640
+ limits.minBottom = Math.max(limits.minBottom, bottom - right / aspectFactor)
641
+ }
642
+ }
643
+ else {
644
+ limits.minLeft = null
645
+ limits.maxLeft = left + Math.floor((width - minW) / gridX) * gridX
646
+ limits.minTop = null
647
+ limits.maxTop = top + Math.floor((height - minH) / gridY) * gridY
648
+ limits.minRight = null
649
+ limits.maxRight = right + Math.floor((width - minW) / gridX) * gridX
650
+ limits.minBottom = null
651
+ limits.maxBottom = bottom + Math.floor((height - minH) / gridY) * gridY
652
+
653
+ if (maxW) {
654
+ limits.minLeft = -(right + maxW)
655
+ limits.minRight = -(left + maxW)
656
+ }
657
+
658
+ if (maxH) {
659
+ limits.minTop = -(bottom + maxH)
660
+ limits.minBottom = -(top + maxH)
661
+ }
662
+
663
+ if (this.lockAspectRatio && maxW && maxH) {
664
+ limits.minLeft = Math.min(limits.minLeft, -(right + maxW))
665
+ limits.minTop = Math.min(limits.minTop, -(maxH + bottom))
666
+ limits.minRight = Math.min(limits.minRight, -left - maxW)
667
+ limits.minBottom = Math.min(limits.minBottom, -top - maxH)
668
+ }
669
+ }
670
+
671
+ return limits
672
+ },
673
+ move(e) {
674
+ if (this.resizing)
675
+ this.handleResize(e)
676
+ else if (this.dragEnable)
677
+ this.handleDrag(e)
678
+ },
679
+ handleDrag(e) {
680
+ const axis = this.axis
681
+ const grid = this.grid
682
+ const bounds = this.bounds
683
+ const mouseClickPosition = this.mouseClickPosition
684
+
685
+ const tmpDeltaX = axis && axis !== 'y' ? mouseClickPosition.mouseX - (e.touches ? e.touches[0].pageX : e.pageX) : 0
686
+ const tmpDeltaY = axis && axis !== 'x' ? mouseClickPosition.mouseY - (e.touches ? e.touches[0].pageY : e.pageY) : 0
687
+
688
+ const [deltaX, deltaY] = snapToGrid(grid, tmpDeltaX, tmpDeltaY, this.scale)
689
+
690
+ const left = restrictToBounds(mouseClickPosition.left - deltaX, bounds.minLeft, bounds.maxLeft)
691
+ const top = restrictToBounds(mouseClickPosition.top - deltaY, bounds.minTop, bounds.maxTop)
692
+
693
+ if (this.onDrag(left, top) === false)
694
+ return
695
+
696
+ const right = restrictToBounds(mouseClickPosition.right + deltaX, bounds.minRight, bounds.maxRight)
697
+ const bottom = restrictToBounds(mouseClickPosition.bottom + deltaY, bounds.minBottom, bounds.maxBottom)
698
+
699
+ this.left = left
700
+ this.top = top
701
+ this.right = right
702
+ this.bottom = bottom
703
+
704
+ // this.$emit("dragging", this.left, this.top);
705
+
706
+ // Code by Joenix
707
+ this.$emit('dragging', this)
708
+
709
+ this.dragging = true
710
+ },
711
+ moveHorizontally(val) {
712
+ // should calculate with scale 1.
713
+ const [deltaX, _] = snapToGrid(this.grid, val, this.top, 1)
714
+
715
+ const left = restrictToBounds(deltaX, this.bounds.minLeft, this.bounds.maxLeft)
716
+
717
+ this.left = left
718
+ this.right = this.parentWidth - this.width - left
719
+ },
720
+ moveVertically(val) {
721
+ // should calculate with scale 1.
722
+ const [_, deltaY] = snapToGrid(this.grid, this.left, val, 1)
723
+
724
+ const top = restrictToBounds(deltaY, this.bounds.minTop, this.bounds.maxTop)
725
+
726
+ this.top = top
727
+ this.bottom = this.parentHeight - this.height - top
728
+ },
729
+ handleResize(e) {
730
+ let left = this.left
731
+ let top = this.top
732
+ let right = this.right
733
+ let bottom = this.bottom
734
+
735
+ const mouseClickPosition = this.mouseClickPosition
736
+ const lockAspectRatio = this.lockAspectRatio
737
+ const aspectFactor = this.aspectFactor
738
+
739
+ const tmpDeltaX = mouseClickPosition.mouseX - (e.touches ? e.touches[0].pageX : e.pageX)
740
+ const tmpDeltaY = mouseClickPosition.mouseY - (e.touches ? e.touches[0].pageY : e.pageY)
741
+
742
+ if (!this.widthTouched && tmpDeltaX)
743
+ this.widthTouched = true
744
+
745
+ if (!this.heightTouched && tmpDeltaY)
746
+ this.heightTouched = true
747
+
748
+ const [deltaX, deltaY] = snapToGrid(this.grid, tmpDeltaX, tmpDeltaY, this.scale)
749
+
750
+ if (this.handle.includes('b')) {
751
+ bottom = restrictToBounds(mouseClickPosition.bottom + deltaY, this.bounds.minBottom, this.bounds.maxBottom)
752
+
753
+ if (this.lockAspectRatio && this.resizingOnY)
754
+ right = this.right - (this.bottom - bottom) * aspectFactor
755
+ }
756
+ else if (this.handle.includes('t')) {
757
+ top = restrictToBounds(mouseClickPosition.top - deltaY, this.bounds.minTop, this.bounds.maxTop)
758
+
759
+ if (this.lockAspectRatio && this.resizingOnY)
760
+ left = this.left - (this.top - top) * aspectFactor
761
+ }
762
+
763
+ if (this.handle.includes('r')) {
764
+ right = restrictToBounds(mouseClickPosition.right + deltaX, this.bounds.minRight, this.bounds.maxRight)
765
+
766
+ if (this.lockAspectRatio && this.resizingOnX)
767
+ bottom = this.bottom - (this.right - right) / aspectFactor
768
+ }
769
+ else if (this.handle.includes('l')) {
770
+ left = restrictToBounds(mouseClickPosition.left - deltaX, this.bounds.minLeft, this.bounds.maxLeft)
771
+
772
+ if (this.lockAspectRatio && this.resizingOnX)
773
+ top = this.top - (this.left - left) / aspectFactor
774
+ }
775
+
776
+ const width = computeWidth(this.parentWidth, left, right)
777
+ const height = computeHeight(this.parentHeight, top, bottom)
778
+
779
+ if (this.onResize(this.handle, left, top, width, height) === false)
780
+ return
781
+
782
+ this.left = left
783
+ this.top = top
784
+ this.right = right
785
+ this.bottom = bottom
786
+ this.width = width
787
+ this.height = height
788
+
789
+ // this.$emit("resizing", this.left, this.top, this.width, this.height);
790
+
791
+ // Code by Joenix
792
+ this.$emit('resizing', this)
793
+
794
+ this.resizing = true
795
+ },
796
+ changeWidth(val) {
797
+ // should calculate with scale 1.
798
+ const [newWidth, _] = snapToGrid(this.grid, val, 0, 1)
799
+
800
+ const right = restrictToBounds(this.parentWidth - newWidth - this.left, this.bounds.minRight, this.bounds.maxRight)
801
+ let bottom = this.bottom
802
+
803
+ if (this.lockAspectRatio)
804
+ bottom = this.bottom - (this.right - right) / this.aspectFactor
805
+
806
+ const width = computeWidth(this.parentWidth, this.left, right)
807
+ const height = computeHeight(this.parentHeight, this.top, bottom)
808
+
809
+ this.right = right
810
+ this.bottom = bottom
811
+ this.width = width
812
+ this.height = height
813
+ },
814
+ changeHeight(val) {
815
+ // should calculate with scale 1.
816
+ const [_, newHeight] = snapToGrid(this.grid, 0, val, 1)
817
+
818
+ const bottom = restrictToBounds(this.parentHeight - newHeight - this.top, this.bounds.minBottom, this.bounds.maxBottom)
819
+ let right = this.right
820
+
821
+ if (this.lockAspectRatio)
822
+ right = this.right - (this.bottom - bottom) * this.aspectFactor
823
+
824
+ const width = computeWidth(this.parentWidth, this.left, right)
825
+ const height = computeHeight(this.parentHeight, this.top, bottom)
826
+
827
+ this.right = right
828
+ this.bottom = bottom
829
+ this.width = width
830
+ this.height = height
831
+ },
832
+ handleUp(e) {
833
+ this.handle = null
834
+
835
+ this.resetBoundsAndMouseState()
836
+
837
+ this.dragEnable = false
838
+ this.resizeEnable = false
839
+
840
+ if (this.resizing) {
841
+ this.resizing = false
842
+ this.$emit('resizestop', this.left, this.top, this.width, this.height)
843
+ }
844
+
845
+ if (this.dragging) {
846
+ this.dragging = false
847
+ this.$emit('dragstop', this.left, this.top)
848
+ }
849
+
850
+ // Code by Joenix
851
+ this.$emit('stoping', this)
852
+
853
+ removeEvent(document.documentElement, eventsFor.move, this.handleResize)
854
+ },
855
+ },
856
+ }
857
+ </script>
858
+
859
+ <template>
860
+ <div
861
+ :style="style"
862
+ :class="[
863
+ {
864
+ [classNameActive]: enabled,
865
+ [classNameDragging]: dragging,
866
+ [classNameResizing]: resizing,
867
+ [classNameDraggable]: draggable,
868
+ [classNameResizable]: resizable,
869
+ },
870
+ className,
871
+ ]"
872
+ @mousedown="elementMouseDown"
873
+ @touchstart="elementTouchDown"
874
+ >
875
+ <div
876
+ v-for="handle in actualHandles"
877
+ :key="handle"
878
+ :class="[classNameHandle, `${classNameHandle}-${handle}`]"
879
+ :style="{ display: enabled ? 'block' : 'none' }"
880
+ @mousedown.stop.prevent="handleDown(handle, $event)"
881
+ @touchstart.stop.prevent="handleTouchDown(handle, $event)"
882
+ >
883
+ <slot :name="handle" />
884
+ </div>
885
+ <slot />
886
+ </div>
887
+ </template>
888
+
889
+ <style>
890
+ .vdr {
891
+ touch-action: none;
892
+ position: absolute;
893
+ box-sizing: border-box;
894
+ border: 1px dashed white;
895
+ }
896
+ .handle {
897
+ box-sizing: border-box;
898
+ position: absolute;
899
+ width: 10px;
900
+ height: 10px;
901
+ background: #EEE;
902
+ border: 1px solid #333;
903
+ }
904
+ .handle-tl {
905
+ top: -10px;
906
+ left: -10px;
907
+ cursor: nw-resize;
908
+ }
909
+ .handle-tm {
910
+ top: -10px;
911
+ left: 50%;
912
+ margin-left: -5px;
913
+ cursor: n-resize;
914
+ }
915
+ .handle-tr {
916
+ top: -10px;
917
+ right: -10px;
918
+ cursor: ne-resize;
919
+ }
920
+ .handle-ml {
921
+ top: 50%;
922
+ margin-top: -5px;
923
+ left: -10px;
924
+ cursor: w-resize;
925
+ }
926
+ .handle-mr {
927
+ top: 50%;
928
+ margin-top: -5px;
929
+ right: -10px;
930
+ cursor: e-resize;
931
+ }
932
+ .handle-bl {
933
+ bottom: -10px;
934
+ left: -10px;
935
+ cursor: sw-resize;
936
+ }
937
+ .handle-bm {
938
+ bottom: -10px;
939
+ left: 50%;
940
+ margin-left: -5px;
941
+ cursor: s-resize;
942
+ }
943
+ .handle-br {
944
+ bottom: -10px;
945
+ right: -10px;
946
+ cursor: se-resize;
947
+ }
948
+ @media only screen and (max-width: 768px) {
949
+ [class*="handle-"]:before {
950
+ content: '';
951
+ left: -10px;
952
+ right: -10px;
953
+ bottom: -10px;
954
+ top: -10px;
955
+ position: absolute;
956
+ }
957
+ }
958
+ </style>