@thinkpixellab-public/px-vue 3.0.6 → 3.0.8

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,72 @@
1
+ <!--
2
+ Use for global mobile awareness in javascript. This doesn't actually handle mobile detection
3
+ but provides a consistent interface for communicating between a single component that does
4
+ the detection and other components that subscribe to an eventbus and update a property called
5
+ isMobile.
6
+
7
+ Sample usage using a css variable for detecting mobile (this keeps css and js in sync):
8
+
9
+ ### MyLayout.vue (or other global component)
10
+
11
+ // add PxBaseMobileAware as a mixin
12
+ import PxBaseMobileAware from '@thinkpixellab-public/px-vue/components/PxBaseMobileAware.vue';
13
+ mixins: [PxBaseMobileAware],
14
+
15
+ // add a resize handler and call setGlobalIsMobile
16
+ resize() {
17
+ if (this.$el) {
18
+ const cssMobile = getComputedStyle(this.$el).getPropertyValue('--is-mobile');
19
+ this.setGlobalIsMobile(cssMobile.toLowerCase().trim() == 'true');
20
+ }
21
+ },
22
+
23
+ // add a css variable that changes with the viewport
24
+
25
+ .my-layout {
26
+ --is-mobile: false;
27
+ @include media-until-mobile() {
28
+ --is-mobile: true;
29
+ }
30
+ }
31
+
32
+ ### MyComponent.vue
33
+
34
+ // use PxBaseMobileAware as a mixin
35
+ import PxBaseMobileAware from '@thinkpixellab-public/px-vue/components/PxBaseMobileAware.vue';
36
+ mixins: [PxBaseMobileAware]
37
+
38
+ // use the isMobile property as needed in a template
39
+ <div> This is mobile: {{isMobile ? 'yup' : 'nope' }} </div>
40
+
41
+ // or in code
42
+ watch: {
43
+ isMobile(nv) {
44
+ // do something when isMobile changes
45
+ }
46
+ }
47
+
48
+
49
+ -->
50
+
51
+ <script>
52
+ export default {
53
+ data() {
54
+ return { isMobile: null };
55
+ },
56
+ mounted() {
57
+ if (this.$globalOn) {
58
+ this.$globalOn('mobile-changed', isMobile => {
59
+ this.isMobile = isMobile;
60
+ });
61
+ }
62
+ },
63
+ methods: {
64
+ setGlobalIsMobile(isMobile) {
65
+ if (this.$globalEmit) {
66
+ this.$globalEmit('mobile-changed', isMobile);
67
+ this.isMobile = isMobile;
68
+ }
69
+ },
70
+ },
71
+ };
72
+ </script>
@@ -53,6 +53,10 @@ export default {
53
53
  padding: { default: null },
54
54
  border: { default: null },
55
55
 
56
+ // max limits fo width/height of the contain rectangle
57
+ maxWidth: { type: Number, default: null },
58
+ maxHeight: { type: Number, default: null },
59
+
56
60
  // the horizontal positioning when there is leftover space
57
61
  alignX: { default: 0.5 }, // number | 'start' | 'center' | 'end'
58
62
 
@@ -67,6 +71,9 @@ export default {
67
71
  },
68
72
  data() {
69
73
  return {
74
+ // use setContainer to use a container source other than this.$el
75
+ container: null,
76
+
70
77
  contain: {
71
78
  current: false,
72
79
  width: 0,
@@ -123,6 +130,9 @@ export default {
123
130
  // no width or height or aspect
124
131
  return null;
125
132
  },
133
+ containerValue() {
134
+ return this.container || this.$el;
135
+ },
126
136
  },
127
137
 
128
138
  watch: {
@@ -131,11 +141,19 @@ export default {
131
141
  },
132
142
  },
133
143
  methods: {
144
+ // Use a source for the outer container size other than this.$el. The container argument can
145
+ // be an element or any object that implements getBoundingClientRect; setting a custom
146
+ // container may also require a direct call to resize when the container size updates (since
147
+ // the default resize observer behavior only observes this.$el)
148
+ setContainer(container) {
149
+ this.container = container;
150
+ this.resize();
151
+ },
134
152
  resize() {
135
153
  let p = this.toBoxModelObject(this.padding);
136
-
137
154
  let b = this.toBoxModelObject(this.border);
138
- let outer = this.$el.getBoundingClientRect();
155
+
156
+ let outer = this.containerValue.getBoundingClientRect();
139
157
  let inner = this.aspectRect || outer;
140
158
 
141
159
  outer = {
@@ -143,6 +161,20 @@ export default {
143
161
  height: outer.height - (b.h + p.h),
144
162
  };
145
163
 
164
+ // max width/height
165
+
166
+ if (this.maxHeight && outer.height > this.maxHeight) {
167
+ outer.y = (outer.height - this.maxHeight) * this.alignToDecimal(this.alignY);
168
+ outer.height = this.maxHeight;
169
+ }
170
+
171
+ if (this.maxWidth && outer.width > this.maxWidth) {
172
+ outer.x = (outer.width - this.maxWidth) * this.alignToDecimal(this.alignX);
173
+ outer.width = this.maxWidth;
174
+ }
175
+
176
+ // get contain
177
+
146
178
  let r;
147
179
 
148
180
  if (this.aspect) {
@@ -24,8 +24,8 @@
24
24
  @after-leave="transitionVisible = false"
25
25
  >
26
26
  <div
27
- :class="bem({ ...variantsMap, absolute: strategy == 'absolute' })"
28
- :style="{ zIndex: zStart + currentLayerIndex }"
27
+ :class="[rootClass, bem({ ...variantsMap, absolute: strategy == 'absolute' })]"
28
+ :style="{ ...(rootStyle || {}), zIndex: zStart + currentLayerIndex }"
29
29
  v-show="visibleValueNext"
30
30
  >
31
31
  <!-- overlay element -->
@@ -34,6 +34,7 @@
34
34
  :class="[bem('overlay'), overlayClass]"
35
35
  @click="overlayClick"
36
36
  v-bind="overlayAttributes"
37
+ ref="overlay"
37
38
  :style="{
38
39
  pointerEvents: visibleValue ? null : 'none',
39
40
  userSelect: visibleValue ? null : 'none',
@@ -113,11 +114,17 @@ export default {
113
114
  // to ensure that the last opened from the same starting z will be on top of each other)
114
115
  zStart: { type: Number, default: 999999 },
115
116
 
117
+ // class set on the root element (equivalent of setting class if not using a portal)
118
+ rootClass: { type: String, default: null },
119
+
120
+ // style set on the root element (equivalent of setting style if not using a portal)
121
+ rootStyle: { default: null },
122
+
116
123
  // An additional class set on the popup element
117
124
  popupClass: { type: String, default: '' },
118
125
 
119
126
  // Style object that gets merged onto the popup
120
- popupStyle: { type: Object, default: null },
127
+ popupStyle: { default: null },
121
128
 
122
129
  // Whether to render an overlay element
123
130
  overlayEnabled: { type: Boolean, default: true },
@@ -222,6 +229,13 @@ export default {
222
229
  // emit update when visibleValue changes (enables .sync on parent)
223
230
  this.$emit('update:visible', nv);
224
231
 
232
+ if (nv) {
233
+ this.$emit('beforeshow');
234
+ }
235
+ if (!nv) {
236
+ this.$emit('beforehide');
237
+ }
238
+
225
239
  if (this.isServer) {
226
240
  return;
227
241
  }
@@ -311,6 +325,15 @@ export default {
311
325
  globalClearLayerIndex = 0;
312
326
  }
313
327
  }
328
+
329
+ // show and hide events (also see beforeshow/beforehide in visibleValue watcher)
330
+
331
+ if (nv) {
332
+ this.$emit('show');
333
+ }
334
+ if (!nv) {
335
+ this.$emit('hide');
336
+ }
314
337
  });
315
338
  },
316
339
  },
@@ -480,6 +503,15 @@ export default {
480
503
 
481
504
  return reference;
482
505
  },
506
+
507
+ // returns the default overlay element (will be null if the overlay slot has been overriden)
508
+ getOverlayElement() {
509
+ return this.$refs.overlay;
510
+ },
511
+
512
+ getPopupElement() {
513
+ return this.$refs.popup;
514
+ },
483
515
  },
484
516
  };
485
517
  </script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkpixellab-public/px-vue",
3
- "version": "3.0.6",
3
+ "version": "3.0.8",
4
4
  "description": "General purpose Vue components and helpers that can be used across projects.",
5
5
  "author": "Pixel Lab",
6
6
  "license": "MIT",
package/utils/fit.js CHANGED
@@ -50,14 +50,14 @@ export function contain(inner, outer, posX = 0.5, posY = 0.5) {
50
50
  if (aspectInner > aspectOuter) {
51
51
  width = outer.width;
52
52
  height = outer.width / aspectInner;
53
- x = 0;
53
+ x = outer.x;
54
54
  y = outer.height * posY - height * posY;
55
55
  scale = height / inner.height;
56
56
  } else {
57
57
  width = outer.height * aspectInner;
58
58
  height = outer.height;
59
59
  x = outer.width * posX - width * posX;
60
- y = 0;
60
+ y = outer.y;
61
61
  scale = width / inner.width;
62
62
  }
63
63