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