@thinkpixellab-public/px-vue 4.0.0 → 4.0.1

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.
@@ -26,24 +26,43 @@
26
26
  </div>
27
27
  </px-slide-transition>
28
28
  </div>
29
+
30
+ <slot name="scrollpreview" :direction="scrollPreview">
31
+ <div :class="bem('scroll-preview', { prev: true, visible: scrollPreview == -1 })">
32
+ <px-icon :src="require('../assets/feather/arrow-left.svg')" :size="2" />
33
+ </div>
34
+
35
+ <div :class="bem('scroll-preview', { next: true, visible: scrollPreview == 1 })">
36
+ <px-icon :src="require('../assets/feather/arrow-right.svg')" :size="2" />
37
+ </div>
38
+ </slot>
29
39
  </div>
30
40
  </template>
31
41
 
32
42
  <script>
33
43
  import PxBaseItemsSelect from './PxBaseItemsSelect.vue';
34
44
  import PxSlideTransition from './PxSlideTransition.vue';
45
+ import PxIcon from './PxIcon.vue';
46
+
35
47
  import gsap from 'gsap';
36
48
  import Drag from '../utils/drag.js';
49
+ import Lethargy from '../utils/lethargy.js';
37
50
 
38
51
  export default {
39
52
  name: 'px-slides',
40
53
  mixins: [PxBaseItemsSelect],
41
- components: { PxSlideTransition },
54
+ components: { PxSlideTransition, PxIcon },
42
55
 
43
56
  props: {
44
57
  // whether drag interaction is enabled
45
58
  dragEnabled: { type: Boolean, default: true },
46
59
 
60
+ // whether scroll interaction is enabled
61
+ scrollEnabled: { type: Boolean, default: false },
62
+
63
+ // whether to show an icon or other indicator that scrolling has started
64
+ scrollPreviewEnabled: { type: Boolean, default: false },
65
+
47
66
  // if true, slides loop to the first slide once last slide is reached
48
67
  loop: { type: Boolean, default: true },
49
68
 
@@ -61,6 +80,7 @@ export default {
61
80
  return {
62
81
  direction: 1,
63
82
  activeTransitions: 0,
83
+ scrollPreview: 0,
64
84
  };
65
85
  },
66
86
  computed: {},
@@ -101,11 +121,17 @@ export default {
101
121
  excludeSelector: this.dragExcludeSelector,
102
122
  disabled: !this.dragEnabled,
103
123
  });
124
+
125
+ if (this.scrollEnabled) {
126
+ this.$el.addEventListener('wheel', this.onWheel);
127
+ }
104
128
  },
105
129
  beforeDestroy() {
106
130
  if (this.drag) {
107
131
  this.drag.destroy();
108
132
  }
133
+
134
+ this.$el.removeEventListener('wheel', this.onWheel);
109
135
  },
110
136
  methods: {
111
137
  transitionStart() {
@@ -154,6 +180,39 @@ export default {
154
180
  }
155
181
  },
156
182
 
183
+ onWheel(e) {
184
+ if (typeof this.lethargy == 'undefined') {
185
+ this.lethargy = new Lethargy();
186
+ this.lethargyPrevCheck = false;
187
+ }
188
+
189
+ if (this.scrollPreviewEnabled) {
190
+ const delta = (e.deltaY + e.deltaX) / 2;
191
+ if (Math.abs(delta) > 5) {
192
+ this.scrollPreview = Math.max(Math.min(delta, 1), -1);
193
+ }
194
+
195
+ clearTimeout(this.scrollPreviewTimeout);
196
+ this.scrollPreviewTimeout = setTimeout(() => {
197
+ this.scrollPreview = 0;
198
+ }, 200);
199
+ }
200
+
201
+ const check = this.lethargy.check(e);
202
+
203
+ if (check !== this.lethargyPrevCheck) {
204
+ if (check) {
205
+ if (check > 0) {
206
+ this.previous();
207
+ } else {
208
+ this.next();
209
+ }
210
+ }
211
+ }
212
+
213
+ this.lethargyPrevCheck = check;
214
+ },
215
+
157
216
  next() {
158
217
  this.selectOffsetSafe(1, this.loop);
159
218
  },
@@ -214,5 +273,40 @@ export default {
214
273
  width: 100%;
215
274
  height: 100%;
216
275
  }
276
+
277
+ &__scroll-preview {
278
+ position: absolute;
279
+ top: 50%;
280
+ width: 5em;
281
+ height: 5em;
282
+ border-radius: 50%;
283
+ background-color: rgba(black, 0.07);
284
+ background-color: #f2f2f2;
285
+ backdrop-filter: blur(6px);
286
+ z-index: 100;
287
+ pointer-events: none;
288
+ opacity: 0;
289
+ transform: translate(0, -50%);
290
+
291
+ @include transition(opacity transform, $dur: 500ms);
292
+ @include depth-shadow(55, 0.05);
293
+
294
+ svg {
295
+ @include center();
296
+ color: currentColor;
297
+ }
298
+
299
+ &--prev {
300
+ left: 2.5em;
301
+ }
302
+
303
+ &--next {
304
+ right: 2.5em;
305
+ }
306
+
307
+ &--visible {
308
+ opacity: 1;
309
+ }
310
+ }
217
311
  }
218
312
  </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkpixellab-public/px-vue",
3
- "version": "4.0.0",
3
+ "version": "4.0.1",
4
4
  "description": "General purpose Vue components and helpers that can be used across projects.",
5
5
  "author": "Pixel Lab",
6
6
  "license": "MIT",
@@ -0,0 +1,111 @@
1
+ // Adapted from here: https://github.com/d4nyll/lethargy
2
+ // MIT License
3
+
4
+ function Lethargy(stability, sensitivity, tolerance, delay) {
5
+ this.stability = stability != null ? Math.abs(stability) : 8;
6
+ this.sensitivity = sensitivity != null ? 1 + Math.abs(sensitivity) : 100;
7
+ this.tolerance = tolerance != null ? 1 + Math.abs(tolerance) : 1.1;
8
+ this.delay = delay != null ? delay : 150;
9
+ this.lastUpDeltas = function () {
10
+ var i, ref, results;
11
+ results = [];
12
+ for (
13
+ i = 1, ref = this.stability * 2;
14
+ 1 <= ref ? i <= ref : i >= ref;
15
+ 1 <= ref ? i++ : i--
16
+ ) {
17
+ results.push(null);
18
+ }
19
+ return results;
20
+ }.call(this);
21
+ this.lastDownDeltas = function () {
22
+ var i, ref, results;
23
+ results = [];
24
+ for (
25
+ i = 1, ref = this.stability * 2;
26
+ 1 <= ref ? i <= ref : i >= ref;
27
+ 1 <= ref ? i++ : i--
28
+ ) {
29
+ results.push(null);
30
+ }
31
+ return results;
32
+ }.call(this);
33
+ this.deltasTimestamp = function () {
34
+ var i, ref, results;
35
+ results = [];
36
+ for (
37
+ i = 1, ref = this.stability * 2;
38
+ 1 <= ref ? i <= ref : i >= ref;
39
+ 1 <= ref ? i++ : i--
40
+ ) {
41
+ results.push(null);
42
+ }
43
+ return results;
44
+ }.call(this);
45
+ }
46
+
47
+ Lethargy.prototype.check = function (e) {
48
+ var lastDelta;
49
+ e = e.originalEvent || e;
50
+ if (e.wheelDelta != null) {
51
+ lastDelta = e.wheelDelta;
52
+ } else if (e.deltaY != null) {
53
+ lastDelta = e.deltaY * -40;
54
+ } else if (e.detail != null || e.detail === 0) {
55
+ lastDelta = e.detail * -40;
56
+ }
57
+ this.deltasTimestamp.push(Date.now());
58
+ this.deltasTimestamp.shift();
59
+ if (lastDelta > 0) {
60
+ this.lastUpDeltas.push(lastDelta);
61
+ this.lastUpDeltas.shift();
62
+ return this.isInertia(1);
63
+ } else {
64
+ this.lastDownDeltas.push(lastDelta);
65
+ this.lastDownDeltas.shift();
66
+ return this.isInertia(-1);
67
+ }
68
+ return false;
69
+ };
70
+
71
+ Lethargy.prototype.isInertia = function (direction) {
72
+ var lastDeltas, lastDeltasNew, lastDeltasOld, newAverage, newSum, oldAverage, oldSum;
73
+ lastDeltas = direction === -1 ? this.lastDownDeltas : this.lastUpDeltas;
74
+ if (lastDeltas[0] === null) {
75
+ return direction;
76
+ }
77
+ if (
78
+ this.deltasTimestamp[this.stability * 2 - 2] + this.delay > Date.now() &&
79
+ lastDeltas[0] === lastDeltas[this.stability * 2 - 1]
80
+ ) {
81
+ return false;
82
+ }
83
+ lastDeltasOld = lastDeltas.slice(0, this.stability);
84
+ lastDeltasNew = lastDeltas.slice(this.stability, this.stability * 2);
85
+ oldSum = lastDeltasOld.reduce(function (t, s) {
86
+ return t + s;
87
+ });
88
+ newSum = lastDeltasNew.reduce(function (t, s) {
89
+ return t + s;
90
+ });
91
+ oldAverage = oldSum / lastDeltasOld.length;
92
+ newAverage = newSum / lastDeltasNew.length;
93
+ if (
94
+ Math.abs(oldAverage) < Math.abs(newAverage * this.tolerance) &&
95
+ this.sensitivity < Math.abs(newAverage)
96
+ ) {
97
+ return direction;
98
+ } else {
99
+ return false;
100
+ }
101
+ };
102
+
103
+ Lethargy.prototype.showLastUpDeltas = function () {
104
+ return this.lastUpDeltas;
105
+ };
106
+
107
+ Lethargy.prototype.showLastDownDeltas = function () {
108
+ return this.lastDownDeltas;
109
+ };
110
+
111
+ export default Lethargy;