@eturnity/eturnity_reusable_components 7.4.4-EPDM-9606 → 7.4.4-EPDM-7260.3

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.
@@ -0,0 +1,541 @@
1
+ <template>
2
+ <div
3
+ :style="style"
4
+ :class="className"
5
+ @mousedown="elementMouseDown"
6
+ @touchstart="elementTouchDown"
7
+ >
8
+ <div
9
+ v-for="handle in actualHandles"
10
+ :key="handle"
11
+ :style="{ display: enabled ? 'block' : 'none' }"
12
+ @mousedown.stop.prevent="handleDown(handle, $event)"
13
+ @touchstart.stop.prevent="handleTouchDown(handle, $event)"
14
+ >
15
+ <slot :name="handle"></slot>
16
+ </div>
17
+ <slot></slot>
18
+ </div>
19
+ </template>
20
+
21
+ <script>
22
+ import {
23
+ matchesSelectorToParentElements,
24
+ addEvent,
25
+ removeEvent
26
+ } from './utils/dom'
27
+ import { computeWidth, restrictToBounds, snapToGrid } from './utils/fns'
28
+
29
+ const events = {
30
+ mouse: {
31
+ start: 'mousedown',
32
+ move: 'mousemove',
33
+ stop: 'mouseup'
34
+ },
35
+ touch: {
36
+ start: 'touchstart',
37
+ move: 'touchmove',
38
+ stop: 'touchend'
39
+ }
40
+ }
41
+
42
+ const userSelectNone = {
43
+ userSelect: 'none',
44
+ MozUserSelect: 'none',
45
+ WebkitUserSelect: 'none',
46
+ MsUserSelect: 'none'
47
+ }
48
+
49
+ const userSelectAuto = {
50
+ userSelect: 'auto',
51
+ MozUserSelect: 'auto',
52
+ WebkitUserSelect: 'auto',
53
+ MsUserSelect: 'auto'
54
+ }
55
+
56
+ let eventsFor = events.mouse
57
+
58
+ export default {
59
+ replace: true,
60
+ name: 'slider',
61
+ props: {
62
+ className: {
63
+ type: String,
64
+ default: 'vdr'
65
+ },
66
+ disableUserSelect: {
67
+ type: Boolean,
68
+ default: true
69
+ },
70
+ preventDeactivation: {
71
+ type: Boolean,
72
+ default: false
73
+ },
74
+ active: {
75
+ type: Boolean,
76
+ default: false
77
+ },
78
+ draggable: {
79
+ type: Boolean,
80
+ default: true
81
+ },
82
+ resizable: {
83
+ type: Boolean,
84
+ default: true
85
+ },
86
+ minWidth: {
87
+ type: Number,
88
+ default: 1,
89
+ validator: (val) => val >= 0
90
+ },
91
+ step: {
92
+ type: Number,
93
+ default: 1,
94
+ validator: (val) => val > 0
95
+ },
96
+ stepCount: {
97
+ type: Number,
98
+ default: 0,
99
+ validator: (val) => val > 0
100
+ },
101
+ subStepCount: {
102
+ type: Number,
103
+ default: 0,
104
+ validator: (val) => val >= 0
105
+ },
106
+ h: {
107
+ type: [Number, String],
108
+ default: 'auto',
109
+ validator: (val) => {
110
+ if (typeof val === 'number') {
111
+ return val > 0
112
+ }
113
+
114
+ return val === 'auto'
115
+ }
116
+ },
117
+ z: {
118
+ type: [String, Number],
119
+ default: 'auto',
120
+ validator: (val) => (typeof val === 'string' ? val === 'auto' : val >= 0)
121
+ },
122
+ min: {
123
+ type: Number,
124
+ default: 0,
125
+ validator: (val) => val >= 0
126
+ },
127
+ max: {
128
+ type: Number,
129
+ default: 0,
130
+ validator: (val) => val >= 0
131
+ },
132
+ dragHandle: {
133
+ type: String,
134
+ default: null
135
+ },
136
+ dragCancel: {
137
+ type: String,
138
+ default: null
139
+ },
140
+ onDrag: {
141
+ type: Function,
142
+ default: () => true
143
+ },
144
+ onResize: {
145
+ type: Function,
146
+ default: () => true
147
+ }
148
+ },
149
+
150
+ data: function () {
151
+ return {
152
+ left: null,
153
+ right: null,
154
+ width: null,
155
+ height: null,
156
+ parentWidth: null,
157
+ parentHeight: null,
158
+ widthTouched: false,
159
+ heightTouched: false,
160
+
161
+ handle: null,
162
+ resizing: false,
163
+ dragging: false,
164
+ dragEnable: false,
165
+ resizeEnable: false,
166
+ enabled: this.active,
167
+
168
+ zIndex: this.z,
169
+ handles: ['ml', 'mr']
170
+ }
171
+ },
172
+
173
+ created: function () {
174
+ this.resetBoundsAndMouseState()
175
+ },
176
+ mounted: function () {
177
+ const [parentWidth, parentHeight] = this.getParentSize()
178
+
179
+ this.parentWidth = parentWidth
180
+ this.parentHeight = parentHeight
181
+
182
+ this.left = this.min * this.stepCount
183
+ this.right = this.max * this.stepCount
184
+ this.width = computeWidth(this.left, this.right)
185
+ this.height = this.h !== 'auto' ? this.h : parentHeight
186
+
187
+ if (this.active) {
188
+ this.$emit('activated')
189
+ }
190
+
191
+ addEvent(document.documentElement, 'mousedown', this.deselect)
192
+ addEvent(document.documentElement, 'touchend touchcancel', this.deselect)
193
+
194
+ addEvent(window, 'resize', this.checkParentSize)
195
+ },
196
+ beforeUnmount: function () {
197
+ removeEvent(document.documentElement, 'mousedown', this.deselect)
198
+ removeEvent(document.documentElement, 'touchstart', this.handleUp)
199
+ removeEvent(document.documentElement, 'mousemove', this.move)
200
+ removeEvent(document.documentElement, 'touchmove', this.move)
201
+ removeEvent(document.documentElement, 'mouseup', this.handleUp)
202
+ removeEvent(document.documentElement, 'touchend touchcancel', this.deselect)
203
+
204
+ removeEvent(window, 'resize', this.checkParentSize)
205
+ },
206
+
207
+ methods: {
208
+ resetBoundsAndMouseState() {
209
+ this.mouseClickPosition = { mouseX: 0, mouseY: 0, x: 0, y: 0, w: 0, h: 0 }
210
+
211
+ this.bounds = {
212
+ minLeft: null,
213
+ maxLeft: null,
214
+ minRight: null,
215
+ maxRight: null
216
+ }
217
+ },
218
+ checkParentSize() {
219
+ const [newParentWidth, newParentHeight] = this.getParentSize()
220
+
221
+ this.parentWidth = newParentWidth
222
+ this.parentHeight = newParentHeight
223
+ },
224
+ getParentSize() {
225
+ const style = window.getComputedStyle(this.$el.parentNode, null)
226
+
227
+ return [
228
+ parseInt(style.getPropertyValue('width'), 10),
229
+ parseInt(style.getPropertyValue('height'), 10)
230
+ ]
231
+ },
232
+ elementTouchDown(e) {
233
+ eventsFor = events.touch
234
+
235
+ this.elementDown(e)
236
+ },
237
+ elementMouseDown(e) {
238
+ eventsFor = events.mouse
239
+
240
+ this.elementDown(e)
241
+ },
242
+ elementDown(e) {
243
+ if (e instanceof MouseEvent && e.button !== 0) {
244
+ return
245
+ }
246
+
247
+ const target = e.target || e.srcElement
248
+
249
+ if (this.$el.contains(target)) {
250
+ if (
251
+ (this.dragHandle &&
252
+ !matchesSelectorToParentElements(
253
+ target,
254
+ this.dragHandle,
255
+ this.$el
256
+ )) ||
257
+ (this.dragCancel &&
258
+ matchesSelectorToParentElements(target, this.dragCancel, this.$el))
259
+ ) {
260
+ this.dragging = false
261
+
262
+ return
263
+ }
264
+
265
+ if (!this.enabled) {
266
+ this.enabled = true
267
+
268
+ this.$emit('activated')
269
+ this.$emit('update:active', true)
270
+ }
271
+
272
+ if (this.draggable) {
273
+ this.dragEnable = true
274
+ }
275
+
276
+ const newPosition = {
277
+ ...this.mouseClickPosition,
278
+ mouseX: e.touches ? e.touches[0].pageX : e.pageX,
279
+ left: this.left,
280
+ right: this.right
281
+ }
282
+
283
+ this.mouseClickPosition = newPosition
284
+ this.bounds = this.calcDragLimits()
285
+
286
+ addEvent(document.documentElement, eventsFor.move, this.move)
287
+ addEvent(document.documentElement, eventsFor.stop, this.handleUp)
288
+ }
289
+ },
290
+ calcDragLimits() {
291
+ const limits = {
292
+ minLeft: null,
293
+ maxLeft: null,
294
+ minRight: null,
295
+ maxRight: null
296
+ }
297
+
298
+ limits.minLeft = 0
299
+ limits.maxLeft = this.parentWidth - this.width
300
+ limits.minRight = this.width
301
+ limits.maxRight = this.parentWidth
302
+
303
+ return limits
304
+ },
305
+ deselect(e) {
306
+ const target = e.target || e.srcElement
307
+ const regex = new RegExp(this.className + '-([trmbl]{2})', '')
308
+
309
+ if (!this.$el.contains(target) && !regex.test(target.className)) {
310
+ if (this.enabled && !this.preventDeactivation) {
311
+ this.enabled = false
312
+
313
+ this.$emit('deactivated')
314
+ this.$emit('update:active', false)
315
+ }
316
+
317
+ removeEvent(document.documentElement, eventsFor.move, this.handleResize)
318
+ }
319
+
320
+ this.resetBoundsAndMouseState()
321
+ },
322
+ handleTouchDown(handle, e) {
323
+ eventsFor = events.touch
324
+
325
+ this.handleDown(handle, e)
326
+ },
327
+ handleDown(handle, e) {
328
+ if (e instanceof MouseEvent && e.which !== 1) {
329
+ return
330
+ }
331
+
332
+ if (e.stopPropagation) e.stopPropagation()
333
+
334
+ this.handle = handle
335
+ this.resizeEnable = true
336
+
337
+ const newPosition = {
338
+ ...this.mouseClickPosition,
339
+ mouseX: e.touches ? e.touches[0].pageX : e.pageX,
340
+ left: this.left,
341
+ right: this.right
342
+ }
343
+
344
+ this.mouseClickPosition = newPosition
345
+ this.bounds = this.calcResizeLimits()
346
+
347
+ addEvent(document.documentElement, eventsFor.move, this.handleResize)
348
+ addEvent(document.documentElement, eventsFor.stop, this.handleUp)
349
+ },
350
+ calcResizeLimits() {
351
+ const limits = {
352
+ minLeft: null,
353
+ maxLeft: null,
354
+ minRight: null,
355
+ maxRight: null
356
+ }
357
+
358
+ limits.minLeft = 0
359
+ limits.maxLeft = this.right - this.minWidthByPx
360
+ limits.minRight = this.left + this.minWidthByPx
361
+ limits.maxRight = this.parentWidth
362
+
363
+ return limits
364
+ },
365
+ move(e) {
366
+ if (this.resizing) {
367
+ this.handleResize(e)
368
+ } else if (this.dragEnable) {
369
+ this.handleDrag(e)
370
+ }
371
+ },
372
+ handleDrag(e) {
373
+ let left = this.left
374
+ let right = this.right
375
+ const bounds = this.bounds
376
+ const mouseClickPosition = this.mouseClickPosition
377
+
378
+ const tmpDeltaX =
379
+ mouseClickPosition.mouseX - (e.touches ? e.touches[0].pageX : e.pageX)
380
+
381
+ const deltaX = snapToGrid(this.parentWidth / this.subStepCount, tmpDeltaX)
382
+
383
+ left = restrictToBounds(
384
+ mouseClickPosition.left - deltaX,
385
+ bounds.minLeft,
386
+ bounds.maxLeft
387
+ )
388
+
389
+ right = restrictToBounds(
390
+ mouseClickPosition.right - deltaX,
391
+ bounds.minRight,
392
+ bounds.maxRight
393
+ )
394
+
395
+ this.left = left
396
+ this.right = right
397
+
398
+ this.$emit('dragging', this.left, this.right)
399
+ this.dragging = true
400
+ },
401
+ handleResize(e) {
402
+ let left = this.left
403
+ let right = this.right
404
+ const bounds = this.bounds
405
+ const mouseClickPosition = this.mouseClickPosition
406
+
407
+ const tmpDeltaX =
408
+ mouseClickPosition.mouseX - (e.touches ? e.touches[0].pageX : e.pageX)
409
+
410
+ if (!this.widthTouched && tmpDeltaX) {
411
+ this.widthTouched = true
412
+ }
413
+
414
+ const deltaX = snapToGrid(this.parentWidth / this.subStepCount, tmpDeltaX)
415
+
416
+ if (this.handle.includes('r')) {
417
+ right = restrictToBounds(
418
+ mouseClickPosition.right - deltaX,
419
+ bounds.minRight,
420
+ bounds.maxRight
421
+ )
422
+ } else if (this.handle.includes('l')) {
423
+ left = restrictToBounds(
424
+ mouseClickPosition.left - deltaX,
425
+ bounds.minLeft,
426
+ bounds.maxLeft
427
+ )
428
+ }
429
+
430
+ const width = computeWidth(left, right)
431
+
432
+ if (this.onResize(this.handle, left, width, this.height) === false) {
433
+ return
434
+ }
435
+
436
+ this.left = left
437
+ this.right = right
438
+ this.width = width
439
+
440
+ this.$emit('resizing', this.left, this.right)
441
+ this.resizing = true
442
+ },
443
+ handleUp() {
444
+ this.handle = null
445
+
446
+ this.resetBoundsAndMouseState()
447
+
448
+ this.dragEnable = false
449
+ this.resizeEnable = false
450
+
451
+ if (this.resizing) {
452
+ this.resizing = false
453
+ this.$emit('resizeStop', {
454
+ min: this.roundToNearestStep(this.left),
455
+ max: this.roundToNearestStep(this.right)
456
+ })
457
+ }
458
+
459
+ if (this.dragging) {
460
+ this.dragging = false
461
+ this.$emit('dragStop', {
462
+ min: this.roundToNearestStep(this.left),
463
+ max: this.roundToNearestStep(this.right)
464
+ })
465
+ }
466
+
467
+ removeEvent(document.documentElement, eventsFor.move, this.handleResize)
468
+ },
469
+ roundToNearestStep(value) {
470
+ const val = value / this.stepCount
471
+
472
+ const int = 1.0 / this.step
473
+ return (Math.floor(val * int) / int).toFixed(2)
474
+ }
475
+ },
476
+ computed: {
477
+ style() {
478
+ return {
479
+ transform: `translate(${this.left}px, 0px)`,
480
+ width: this.computedWidth,
481
+ height: this.computedHeight,
482
+ zIndex: this.zIndex,
483
+ ...(this.dragging && this.disableUserSelect
484
+ ? userSelectNone
485
+ : userSelectAuto)
486
+ }
487
+ },
488
+ actualHandles() {
489
+ if (!this.resizable) return []
490
+
491
+ return this.handles
492
+ },
493
+ minWidthByPx() {
494
+ return this.minWidth * this.stepCount
495
+ },
496
+ computedWidth() {
497
+ if (this.width === 'auto') {
498
+ if (!this.widthTouched) {
499
+ return 'auto'
500
+ }
501
+ }
502
+
503
+ return this.width + 'px'
504
+ },
505
+ computedHeight() {
506
+ if (this.height === 'auto') {
507
+ if (!this.heightTouched) {
508
+ return 'auto'
509
+ }
510
+ }
511
+
512
+ return this.height + 'px'
513
+ }
514
+ },
515
+
516
+ watch: {
517
+ active(val) {
518
+ this.enabled = val
519
+
520
+ if (val) {
521
+ this.$emit('activated')
522
+ } else {
523
+ this.$emit('deactivated')
524
+ }
525
+ },
526
+ z(val) {
527
+ if (val >= 0 || val === 'auto') {
528
+ this.zIndex = val
529
+ }
530
+ }
531
+ }
532
+ }
533
+ </script>
534
+ <style scoped>
535
+ .vdr {
536
+ touch-action: none;
537
+ position: absolute;
538
+ box-sizing: border-box;
539
+ border: 1px dashed black;
540
+ }
541
+ </style>