@thinkpixellab-public/px-vue 4.0.19 → 4.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bases/PxBaseMobileAware.vue +60 -1
- package/bases/PxBaseMobileProvide.vue +6 -0
- package/components/PxColorPicker.vue +1 -0
- package/components/PxSlideTransition.vue +73 -29
- package/components/PxSlides.vue +14 -7
- package/components/PxTextbox.vue +4 -4
- package/components/PxVueTest.vue +4 -4
- package/package.json +1 -1
- package/utils/SharedHeightManager.js +3 -0
- package/utils/drag.js +2 -1
- package/utils/utils.js +24 -0
|
@@ -18,8 +18,67 @@ export default {
|
|
|
18
18
|
return this.mediaQuery.currentBreakpoint;
|
|
19
19
|
},
|
|
20
20
|
},
|
|
21
|
-
|
|
22
21
|
methods: {
|
|
22
|
+
/**
|
|
23
|
+
* Returns a value from a map that matches the current breakpoint or the nearest breakpoint.
|
|
24
|
+
* Nearest is determined by the searchDirection parameter.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
*
|
|
28
|
+
* // returns 240 if mobile or smaller, 320 otherwise
|
|
29
|
+
* <Card :width="responsiveValue({mobile: 240}, 320)" />
|
|
30
|
+
*
|
|
31
|
+
* // returns 240 if mobile or smaller, 300 until lg, 320 otherwise
|
|
32
|
+
* <Card :width="responsiveValue({mobile: 240, lg: 300}, 320)" />
|
|
33
|
+
*
|
|
34
|
+
* // returns 200 if smaller than mobile, 240 if smaller than lg and 300 if bigger than lg
|
|
35
|
+
* <Card :width="responsiveValue({mobile: 240, lg: 300}, 200, 'down')" />
|
|
36
|
+
*
|
|
37
|
+
* // could also be used in a computed property....
|
|
38
|
+
* responsiveColor() {
|
|
39
|
+
* return this.responsiveValue({mobile: 'red', lg: 'blue'}, 'green');
|
|
40
|
+
* }
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
responsiveValue(lookup, fallback, searchDirection = 'up') {
|
|
44
|
+
const breakpoints = this.mediaQuery.breakpoints || {};
|
|
45
|
+
const current = this.currentBreakpoint;
|
|
46
|
+
|
|
47
|
+
if (!lookup || !Object.keys(lookup).length || current == null) {
|
|
48
|
+
return fallback;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// if the current breakpoint is in the lookup, just return the value
|
|
52
|
+
if (current in lookup) {
|
|
53
|
+
return lookup[current];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// convert keys to numbers so we can sort and find the nearest
|
|
57
|
+
lookup = Object.keys(lookup).reduce((acc, key) => {
|
|
58
|
+
if (key in breakpoints) {
|
|
59
|
+
acc[breakpoints[key]] = lookup[key];
|
|
60
|
+
}
|
|
61
|
+
return acc;
|
|
62
|
+
}, {});
|
|
63
|
+
|
|
64
|
+
const currentNum = breakpoints[current];
|
|
65
|
+
|
|
66
|
+
const keys = Object.keys(lookup)
|
|
67
|
+
.map(Number)
|
|
68
|
+
.sort((a, b) => (searchDirection == 'up' ? a - b : b - a));
|
|
69
|
+
|
|
70
|
+
// find the first key that is smaller than current
|
|
71
|
+
const match = keys.find(key => {
|
|
72
|
+
return searchDirection == 'up' ? key >= currentNum : key <= currentNum;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (match) {
|
|
76
|
+
return lookup[match];
|
|
77
|
+
} else {
|
|
78
|
+
return fallback;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
|
|
23
82
|
isBreakpointOrSmaller(breakpoint) {
|
|
24
83
|
if (this.currentBreakpoint === null) {
|
|
25
84
|
return false;
|
|
@@ -35,6 +35,7 @@ const PxColorPicker = {
|
|
|
35
35
|
name: 'px-color-picker',
|
|
36
36
|
components: { PxFloat, PxColorPanel, PxColorPaletteButton, PxIcon },
|
|
37
37
|
mixins: [PxBaseColor],
|
|
38
|
+
emits: ['click'],
|
|
38
39
|
props: {
|
|
39
40
|
/**
|
|
40
41
|
* An icon to display inside the button. If a string is provided, it will be interpreted as
|
|
@@ -1,27 +1,23 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Handle transitions between slides in PxSlide. Uses a hybrid css/javascript transition where
|
|
5
|
-
fades are in css and the drag movement is done with gsap.
|
|
2
|
+
Describe this component...
|
|
6
3
|
-->
|
|
7
4
|
<template>
|
|
8
|
-
<
|
|
9
|
-
@before-enter="beforeEnter"
|
|
10
|
-
@enter="enter"
|
|
11
|
-
@leave="leave"
|
|
12
|
-
v-bind="$attrs"
|
|
13
|
-
name="px-slide-transition-fade"
|
|
14
|
-
>
|
|
5
|
+
<div :class="bem({ active: active })">
|
|
15
6
|
<slot />
|
|
16
|
-
</
|
|
7
|
+
</div>
|
|
17
8
|
</template>
|
|
18
9
|
|
|
19
10
|
<script>
|
|
20
11
|
import gsap from 'gsap';
|
|
21
12
|
|
|
22
13
|
export default {
|
|
23
|
-
name: 'px-
|
|
14
|
+
name: 'px-slides-transition',
|
|
15
|
+
// components: { Component },
|
|
16
|
+
// mixins: [ Mixin ],
|
|
17
|
+
|
|
24
18
|
props: {
|
|
19
|
+
active: { type: Boolean, default: true },
|
|
20
|
+
|
|
25
21
|
// selector used to find children of the element that should slide during the transition
|
|
26
22
|
dragSelector: { type: String, default: '[data-drag]' },
|
|
27
23
|
|
|
@@ -37,28 +33,53 @@ export default {
|
|
|
37
33
|
// vertical or horizontal
|
|
38
34
|
orientation: { type: String, default: 'horizontal' },
|
|
39
35
|
|
|
36
|
+
disableAnimations: { type: Boolean, default: false },
|
|
37
|
+
|
|
40
38
|
// TODO rtlAdjust: {type: Boolean, default: false }
|
|
41
39
|
|
|
42
40
|
duration: { type: Number, default: 1 },
|
|
43
41
|
ease: { type: String, default: 'power3.out' },
|
|
44
42
|
slideAmount: { default: '40vw' },
|
|
43
|
+
},
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
data() {
|
|
46
|
+
return { initialized: false };
|
|
47
47
|
},
|
|
48
48
|
computed: {
|
|
49
|
+
currentDuration() {
|
|
50
|
+
if (this.disableAnimations || !this.initialized) {
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
return this.duration;
|
|
54
|
+
},
|
|
49
55
|
tweenShared() {
|
|
50
56
|
return {
|
|
51
|
-
duration: this.
|
|
57
|
+
duration: this.currentDuration,
|
|
52
58
|
ease: this.ease,
|
|
53
59
|
};
|
|
54
60
|
},
|
|
55
61
|
},
|
|
62
|
+
watch: {
|
|
63
|
+
active(isActive, wasActive) {
|
|
64
|
+
this.updateActive(isActive, wasActive);
|
|
65
|
+
},
|
|
66
|
+
},
|
|
56
67
|
mounted() {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
this.updateActive(this.active, false);
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
this.initialized = true;
|
|
71
|
+
}, 0);
|
|
60
72
|
},
|
|
61
73
|
methods: {
|
|
74
|
+
updateActive(isActive, wasActive) {
|
|
75
|
+
if (isActive && !wasActive) {
|
|
76
|
+
this.enter(this.$el);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!isActive && wasActive) {
|
|
80
|
+
this.leave(this.$el);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
62
83
|
directionAmount(direction, addEquals = false) {
|
|
63
84
|
let dir;
|
|
64
85
|
if (addEquals) {
|
|
@@ -83,14 +104,14 @@ export default {
|
|
|
83
104
|
return element.querySelectorAll(this.dragReverseSelector);
|
|
84
105
|
},
|
|
85
106
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
enter(element, done) {
|
|
107
|
+
enter(element) {
|
|
89
108
|
const slideElements = this.slideElements(element);
|
|
90
109
|
|
|
91
110
|
if (slideElements?.length) {
|
|
92
111
|
const from = {};
|
|
93
|
-
const to = {
|
|
112
|
+
const to = {
|
|
113
|
+
...this.tweenShared,
|
|
114
|
+
};
|
|
94
115
|
|
|
95
116
|
if (this.orientation === 'vertical') {
|
|
96
117
|
from.y = this.directionAmount(this.direction * -1);
|
|
@@ -113,13 +134,25 @@ export default {
|
|
|
113
134
|
);
|
|
114
135
|
}
|
|
115
136
|
}
|
|
137
|
+
|
|
138
|
+
// fade
|
|
139
|
+
gsap.to(element, {
|
|
140
|
+
opacity: 1,
|
|
141
|
+
duration: this.currentDuration,
|
|
142
|
+
ease: this.ease,
|
|
143
|
+
onStart: () => {
|
|
144
|
+
this.$emit('before-enter');
|
|
145
|
+
},
|
|
146
|
+
onComplete: () => {
|
|
147
|
+
this.$emit('after-enter');
|
|
148
|
+
},
|
|
149
|
+
});
|
|
116
150
|
},
|
|
117
|
-
leave(element
|
|
151
|
+
leave(element) {
|
|
118
152
|
const slideElements = this.slideElements(element);
|
|
119
153
|
|
|
120
154
|
const to = {
|
|
121
155
|
...this.tweenShared,
|
|
122
|
-
onComplete: done,
|
|
123
156
|
};
|
|
124
157
|
|
|
125
158
|
if (this.orientation === 'vertical') {
|
|
@@ -146,6 +179,18 @@ export default {
|
|
|
146
179
|
gsap.to(slideElementsReverse, toReverse);
|
|
147
180
|
}
|
|
148
181
|
}
|
|
182
|
+
|
|
183
|
+
gsap.to(element, {
|
|
184
|
+
opacity: 0,
|
|
185
|
+
duration: this.currentDuration,
|
|
186
|
+
ease: this.ease,
|
|
187
|
+
onStart: () => {
|
|
188
|
+
this.$emit('before-leave');
|
|
189
|
+
},
|
|
190
|
+
onComplete: () => {
|
|
191
|
+
this.$emit('after-leave');
|
|
192
|
+
},
|
|
193
|
+
});
|
|
149
194
|
},
|
|
150
195
|
},
|
|
151
196
|
};
|
|
@@ -153,10 +198,9 @@ export default {
|
|
|
153
198
|
|
|
154
199
|
<style lang="scss">
|
|
155
200
|
@use '../styles/px.scss' as *;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
// add styles here
|
|
201
|
+
.px-slides-transition {
|
|
202
|
+
opacity: 0;
|
|
203
|
+
width: 100%;
|
|
204
|
+
height: 100%;
|
|
161
205
|
}
|
|
162
206
|
</style>
|
package/components/PxSlides.vue
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
-->
|
|
4
4
|
|
|
5
5
|
<template>
|
|
6
|
-
<div :class="bem(variantsMap)">
|
|
6
|
+
<div :class="bem({ hasOffset, orientation, ...variantsMap })">
|
|
7
7
|
<div
|
|
8
8
|
v-for="(item, index) in items"
|
|
9
9
|
:key="getItemKey(item)"
|
|
@@ -11,14 +11,15 @@
|
|
|
11
11
|
:class="bem('slide-wrapper', { selected: isItemSelected(item) })"
|
|
12
12
|
>
|
|
13
13
|
<px-slide-transition
|
|
14
|
+
:class="bem('transitioner')"
|
|
14
15
|
:disable-animations="disableAnimations"
|
|
15
16
|
:direction="direction"
|
|
16
17
|
:orientation="orientation"
|
|
18
|
+
:active="isItemSelected(item)"
|
|
17
19
|
@before-leave="transitionStart"
|
|
18
20
|
@after-leave="transitionEnd"
|
|
19
|
-
@leave-cancelled="transitionEnd"
|
|
20
21
|
>
|
|
21
|
-
<div :class="bem('slide')"
|
|
22
|
+
<div :class="bem('slide')">
|
|
22
23
|
<slot
|
|
23
24
|
name="slide"
|
|
24
25
|
:selected="isItemSelected(item)"
|
|
@@ -148,7 +149,6 @@ export default {
|
|
|
148
149
|
navigator.userAgent.indexOf('Win') != -1 ||
|
|
149
150
|
this.$route.query?.scroll == 'windows'
|
|
150
151
|
) {
|
|
151
|
-
//console.log('[Windows scroll values enabled.]');
|
|
152
152
|
return {
|
|
153
153
|
stability: stability || 8,
|
|
154
154
|
sensitivity: sensitivity || 20,
|
|
@@ -198,6 +198,11 @@ export default {
|
|
|
198
198
|
this.drag.enable();
|
|
199
199
|
}
|
|
200
200
|
},
|
|
201
|
+
orientation(nv) {
|
|
202
|
+
if (this.drag) {
|
|
203
|
+
this.drag.updateOptions({ lock: nv === 'horizontal' ? 'x' : 'y' });
|
|
204
|
+
}
|
|
205
|
+
},
|
|
201
206
|
},
|
|
202
207
|
mounted() {
|
|
203
208
|
if (this.scrollEnabled) {
|
|
@@ -276,8 +281,10 @@ export default {
|
|
|
276
281
|
}
|
|
277
282
|
|
|
278
283
|
if (this.orientation === 'vertical') {
|
|
279
|
-
gsap.set(this.dragElements, { y: ev.startDelta.y });
|
|
280
|
-
|
|
284
|
+
gsap.set(this.dragElements || [], { y: ev.startDelta.y });
|
|
285
|
+
if (this.dragElementsReverse?.length) {
|
|
286
|
+
gsap.set(this.dragElementsReverse, { y: -1 * ev.startDelta.y });
|
|
287
|
+
}
|
|
281
288
|
} else {
|
|
282
289
|
gsap.set(this.dragElements, { x: ev.startDelta.x });
|
|
283
290
|
}
|
|
@@ -331,6 +338,7 @@ export default {
|
|
|
331
338
|
|
|
332
339
|
if (this.scrollExcludeSelector) {
|
|
333
340
|
const excludeElements = this.$el.querySelectorAll(this.scrollExcludeSelector);
|
|
341
|
+
|
|
334
342
|
for (let i = 0; i < excludeElements.length; i++) {
|
|
335
343
|
if (excludeElements[i].contains(e.target)) return;
|
|
336
344
|
}
|
|
@@ -350,7 +358,6 @@ export default {
|
|
|
350
358
|
}
|
|
351
359
|
|
|
352
360
|
e.stopPropagation();
|
|
353
|
-
e.preventDefault();
|
|
354
361
|
}
|
|
355
362
|
}
|
|
356
363
|
|
package/components/PxTextbox.vue
CHANGED
|
@@ -30,7 +30,7 @@ export default {
|
|
|
30
30
|
multiline: { type: Boolean, default: false },
|
|
31
31
|
|
|
32
32
|
// the value of the textbox
|
|
33
|
-
|
|
33
|
+
text: { type: String, default: null },
|
|
34
34
|
|
|
35
35
|
// whether to fire an update / v-model event on every character change ('input') or when the textbox loses focus ('change')
|
|
36
36
|
updateMode: {
|
|
@@ -58,12 +58,12 @@ export default {
|
|
|
58
58
|
},
|
|
59
59
|
|
|
60
60
|
watch: {
|
|
61
|
-
|
|
61
|
+
text(nv) {
|
|
62
62
|
this.setValue(nv);
|
|
63
63
|
},
|
|
64
64
|
},
|
|
65
65
|
mounted() {
|
|
66
|
-
this.setValue(this.
|
|
66
|
+
this.setValue(this.text);
|
|
67
67
|
},
|
|
68
68
|
|
|
69
69
|
methods: {
|
|
@@ -99,7 +99,7 @@ export default {
|
|
|
99
99
|
this.$refs.input.textContent = val;
|
|
100
100
|
|
|
101
101
|
// raise an update event
|
|
102
|
-
this.$emit('update:
|
|
102
|
+
this.$emit('update:text', val);
|
|
103
103
|
|
|
104
104
|
// update the caret position
|
|
105
105
|
const newPos = startPos + (val.length - prevValue.length);
|
package/components/PxVueTest.vue
CHANGED
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
>
|
|
130
130
|
<template #default="v">
|
|
131
131
|
<px-textbox
|
|
132
|
-
v-model="validateOne"
|
|
132
|
+
v-model:text="validateOne"
|
|
133
133
|
:class="[v.class, v.requiredClass, v.violationClasses]"
|
|
134
134
|
/>
|
|
135
135
|
</template>
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
>
|
|
143
143
|
<template #default="v">
|
|
144
144
|
<px-textbox
|
|
145
|
-
v-model="validateTwo"
|
|
145
|
+
v-model:text="validateTwo"
|
|
146
146
|
:class="[v.class, v.requiredClass, v.violationClasses]"
|
|
147
147
|
/>
|
|
148
148
|
</template>
|
|
@@ -253,7 +253,7 @@
|
|
|
253
253
|
<px-flex :vertical="true" :gap="1">
|
|
254
254
|
<div>currentText: {{ currentText }}</div>
|
|
255
255
|
|
|
256
|
-
<px-textbox v-model="currentText" placeholder="Say what you want..." />
|
|
256
|
+
<px-textbox v-model:text="currentText" placeholder="Say what you want..." />
|
|
257
257
|
|
|
258
258
|
<px-textbox
|
|
259
259
|
multiline
|
|
@@ -263,7 +263,7 @@
|
|
|
263
263
|
/>
|
|
264
264
|
|
|
265
265
|
<px-textbox type="password" />
|
|
266
|
-
<px-textbox :
|
|
266
|
+
<px-textbox :text="'hello@thinkpixellab.com'" type="email" />
|
|
267
267
|
</px-flex>
|
|
268
268
|
</px-test>
|
|
269
269
|
|
package/package.json
CHANGED
|
@@ -74,6 +74,9 @@ class HeightGroup {
|
|
|
74
74
|
|
|
75
75
|
if (this.ops.varsParent) {
|
|
76
76
|
this.ops.varsParent.style.setProperty(this.getVariableName(), max + 'px');
|
|
77
|
+
if (this.ops.debug) {
|
|
78
|
+
console.log(` ${this.getVariableName()}: ${max}px`);
|
|
79
|
+
}
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
if (this.ops.changeCallback) {
|
package/utils/drag.js
CHANGED
package/utils/utils.js
CHANGED
|
@@ -423,3 +423,27 @@ export function uniqueId() {
|
|
|
423
423
|
('000' + ((Math.random() * 46656) | 0).toString(36)).slice(-3)
|
|
424
424
|
);
|
|
425
425
|
}
|
|
426
|
+
|
|
427
|
+
export function findScrollParent(node) {
|
|
428
|
+
const isScrolling = node => {
|
|
429
|
+
let overflow = getComputedStyle(node, null).getPropertyValue('overflow');
|
|
430
|
+
|
|
431
|
+
return overflow.indexOf('scroll') > -1 || overflow.indexOf('auto') > -1;
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
if (!(node instanceof HTMLElement || node instanceof SVGElement)) {
|
|
435
|
+
return undefined;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
let current = node.parentNode;
|
|
439
|
+
|
|
440
|
+
while (current?.parentNode) {
|
|
441
|
+
if (isScrolling(current)) {
|
|
442
|
+
return current;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
current = current.parentNode;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return document.scrollingElement || document.documentElement;
|
|
449
|
+
}
|