@thinkpixellab-public/px-vue 3.0.25 → 3.0.27
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/components/PxCardGrid.vue +26 -1
- package/components/PxFloat.vue +21 -1
- package/components/PxNineGrid.vue +0 -2
- package/components/PxSpinner.vue +130 -0
- package/package.json +1 -1
- package/plugins/filters/striphtml.js +9 -2
- package/utils/cardGrid.js +0 -1
- package/utils/textWidth.js +36 -0
|
@@ -109,9 +109,10 @@ You can define a template using space notation like this:
|
|
|
109
109
|
:key="spaceIndex"
|
|
110
110
|
>
|
|
111
111
|
<div
|
|
112
|
-
:class="bem('card')"
|
|
113
112
|
v-for="(item, cardIndex) in space.cards"
|
|
114
113
|
:key="cardIndex"
|
|
114
|
+
:class="bem('card')"
|
|
115
|
+
:ref="cardRefFromItem(item)"
|
|
115
116
|
>
|
|
116
117
|
<slot
|
|
117
118
|
name="default"
|
|
@@ -382,6 +383,7 @@ export default {
|
|
|
382
383
|
|
|
383
384
|
this.rowTemplates = rowTemplates;
|
|
384
385
|
},
|
|
386
|
+
|
|
385
387
|
resize() {
|
|
386
388
|
let count = 1;
|
|
387
389
|
let availableWidth = this.$el.offsetWidth;
|
|
@@ -401,6 +403,29 @@ export default {
|
|
|
401
403
|
}
|
|
402
404
|
this.columnCount = count;
|
|
403
405
|
},
|
|
406
|
+
|
|
407
|
+
cardRefFromItem(item) {
|
|
408
|
+
if (!item) {
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const key = this.getItemKey(item);
|
|
413
|
+
|
|
414
|
+
if (key && key.toString) {
|
|
415
|
+
const ref = `card-${key.toString()}`;
|
|
416
|
+
return ref;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return null;
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
cardElementFromItem(item) {
|
|
423
|
+
const ref = this.cardRefFromItem(item);
|
|
424
|
+
if (ref && this.$refs[ref] && this.$refs[ref].length) {
|
|
425
|
+
return this.$refs[ref][0];
|
|
426
|
+
}
|
|
427
|
+
return null;
|
|
428
|
+
},
|
|
404
429
|
},
|
|
405
430
|
};
|
|
406
431
|
</script>
|
package/components/PxFloat.vue
CHANGED
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
import PxBaseVariants from './PxBaseVariants.vue';
|
|
67
67
|
import PxPortal from './PxPortal.vue';
|
|
68
68
|
|
|
69
|
-
import { computePosition, autoUpdate, flip, shift, offset } from '@floating-ui/dom';
|
|
69
|
+
import { computePosition, autoUpdate, flip, shift, offset, size } from '@floating-ui/dom';
|
|
70
70
|
import { disableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock';
|
|
71
71
|
|
|
72
72
|
const FOCUS_ELEMENTS = [
|
|
@@ -171,6 +171,10 @@ export default {
|
|
|
171
171
|
// like flip but for the start/end direction
|
|
172
172
|
shift: { default: true },
|
|
173
173
|
|
|
174
|
+
// uses the size middleware to keep the float on screen, resizing when necessary
|
|
175
|
+
sizeToView: { default: false },
|
|
176
|
+
sizeToViewPadding: { type: Number, default: 10 },
|
|
177
|
+
|
|
174
178
|
// NOT IMPLEMENTED
|
|
175
179
|
// hiddenClass: { type: String, default: null },
|
|
176
180
|
|
|
@@ -461,6 +465,18 @@ export default {
|
|
|
461
465
|
middleware.push(flip(this.flip));
|
|
462
466
|
}
|
|
463
467
|
|
|
468
|
+
let maxHeight = null;
|
|
469
|
+
if (this.sizeToView) {
|
|
470
|
+
let padding = this.sizeToViewPadding || 0;
|
|
471
|
+
middleware.push(
|
|
472
|
+
size({
|
|
473
|
+
apply({ availableHeight }) {
|
|
474
|
+
maxHeight = availableHeight - padding;
|
|
475
|
+
},
|
|
476
|
+
})
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
|
|
464
480
|
if (this.placement && this.$refs.popup && reference) {
|
|
465
481
|
computePosition(reference, this.$refs.popup, {
|
|
466
482
|
placement: this.placement,
|
|
@@ -470,11 +486,13 @@ export default {
|
|
|
470
486
|
if (this.useTranslate) {
|
|
471
487
|
this.positionCss = {
|
|
472
488
|
transform: `translate(${this.cssPx(x)},${this.cssPx(y)})`,
|
|
489
|
+
maxHeight: this.cssPx(maxHeight),
|
|
473
490
|
};
|
|
474
491
|
} else {
|
|
475
492
|
this.positionCss = {
|
|
476
493
|
left: this.cssPx(x),
|
|
477
494
|
top: this.cssPx(y),
|
|
495
|
+
maxHeight: this.cssPx(maxHeight),
|
|
478
496
|
};
|
|
479
497
|
}
|
|
480
498
|
});
|
|
@@ -503,6 +521,8 @@ export default {
|
|
|
503
521
|
}
|
|
504
522
|
}
|
|
505
523
|
|
|
524
|
+
console.log(`reference: ${reference}`);
|
|
525
|
+
|
|
506
526
|
return reference;
|
|
507
527
|
},
|
|
508
528
|
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Shows a simple CSS based spinner. Future implementations can pull from here:
|
|
3
|
+
https://cssloaders.github.io/
|
|
4
|
+
|
|
5
|
+
Supported variants:
|
|
6
|
+
|
|
7
|
+
* classic - rotating semi-circle
|
|
8
|
+
* dots - three dots that fade in and out in turn
|
|
9
|
+
|
|
10
|
+
Size is derived from the current font size and color is derived from currentColor. These
|
|
11
|
+
properties (as well as a transform) can be set on the component itself without side effects.
|
|
12
|
+
|
|
13
|
+
Future enhancements could include additional properties for controlling things like timing,
|
|
14
|
+
additional colors, stroke thickness, etc.
|
|
15
|
+
-->
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<span :class="bem(variantsMap)" v-if="visible">
|
|
19
|
+
<span :class="bem('spinner')"></span>
|
|
20
|
+
</span>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script>
|
|
24
|
+
import PxBaseVariants from './PxBaseVariants.vue';
|
|
25
|
+
import PxBaseVisible from './PxBaseVisible.vue';
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
name: 'px-spinner',
|
|
29
|
+
mixins: [PxBaseVariants, PxBaseVisible],
|
|
30
|
+
props: { variant: { type: String, default: 'classic' } },
|
|
31
|
+
};
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<style lang="scss">
|
|
35
|
+
@use '../styles/px.scss' as *;
|
|
36
|
+
|
|
37
|
+
.px-spinner {
|
|
38
|
+
display: inline-block;
|
|
39
|
+
position: relative;
|
|
40
|
+
pointer-events: none;
|
|
41
|
+
|
|
42
|
+
&__spinner {
|
|
43
|
+
display: block;
|
|
44
|
+
position: relative;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// classic
|
|
48
|
+
|
|
49
|
+
&--classic & {
|
|
50
|
+
&__spinner {
|
|
51
|
+
width: 1.33em;
|
|
52
|
+
height: 1.33em;
|
|
53
|
+
border: 0.15em solid currentColor;
|
|
54
|
+
border-bottom-color: transparent;
|
|
55
|
+
border-radius: 50%;
|
|
56
|
+
display: inline-block;
|
|
57
|
+
box-sizing: border-box;
|
|
58
|
+
animation: px-spinner-classic 1s linear infinite;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@keyframes px-spinner-classic {
|
|
63
|
+
0% {
|
|
64
|
+
transform: rotate(0deg);
|
|
65
|
+
}
|
|
66
|
+
100% {
|
|
67
|
+
transform: rotate(360deg);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// dots
|
|
72
|
+
|
|
73
|
+
&--dots {
|
|
74
|
+
width: 12.5em * 0.2;
|
|
75
|
+
height: 2.5em * 0.2;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
&--dots & {
|
|
79
|
+
$dur: 1.8s;
|
|
80
|
+
|
|
81
|
+
&__spinner {
|
|
82
|
+
font-size: 0.2em;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
&__spinner,
|
|
86
|
+
&__spinner:before,
|
|
87
|
+
&__spinner:after {
|
|
88
|
+
position: absolute;
|
|
89
|
+
top: -2.5em;
|
|
90
|
+
width: 2.5em;
|
|
91
|
+
height: 2.5em;
|
|
92
|
+
border-radius: 50%;
|
|
93
|
+
animation-fill-mode: both;
|
|
94
|
+
animation: px-spinner-dots $dur infinite $ease-in-out-quart;
|
|
95
|
+
}
|
|
96
|
+
&__spinner {
|
|
97
|
+
left: 5em;
|
|
98
|
+
color: currentColor;
|
|
99
|
+
position: relative;
|
|
100
|
+
text-indent: -9999em;
|
|
101
|
+
transform: translateZ(0);
|
|
102
|
+
animation-delay: ($dur * -0.088888888);
|
|
103
|
+
}
|
|
104
|
+
&__spinner:before,
|
|
105
|
+
&__spinner:after {
|
|
106
|
+
content: '';
|
|
107
|
+
position: absolute;
|
|
108
|
+
top: 0;
|
|
109
|
+
}
|
|
110
|
+
&__spinner:before {
|
|
111
|
+
left: -5em;
|
|
112
|
+
animation-delay: ($dur * -0.088888888 * 2);
|
|
113
|
+
}
|
|
114
|
+
&__spinner:after {
|
|
115
|
+
left: 5em;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@keyframes px-spinner-dots {
|
|
119
|
+
0%,
|
|
120
|
+
80%,
|
|
121
|
+
100% {
|
|
122
|
+
box-shadow: 0 2.5em 0 -1.3em;
|
|
123
|
+
}
|
|
124
|
+
40% {
|
|
125
|
+
box-shadow: 0 2.5em 0 0;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
</style>
|
package/package.json
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
export default val => {
|
|
2
2
|
if (!process.server) {
|
|
3
|
-
|
|
3
|
+
val = val.replace(/<\/p>/g, '</p> ');
|
|
4
|
+
val = val.replace(/<\/li>/g, '</li> ');
|
|
5
|
+
val = val.replace(/<\/div>/g, '</div> ');
|
|
6
|
+
|
|
7
|
+
let div = document.createElement('div');
|
|
4
8
|
div.innerHTML = val;
|
|
5
|
-
|
|
9
|
+
|
|
10
|
+
let text = div.innerText || '';
|
|
11
|
+
text = text.replace(/(\n)+/g, ' ');
|
|
12
|
+
|
|
6
13
|
return text;
|
|
7
14
|
} else {
|
|
8
15
|
return '';
|
package/utils/cardGrid.js
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uses canvas.measureText to compute the width of a string in px.
|
|
3
|
+
*
|
|
4
|
+
* @param str The text to be measured.
|
|
5
|
+
* @param fontOrElement The css font descriptor (e.g bold 15px arial) or an element from which to extract the font.
|
|
6
|
+
*/
|
|
7
|
+
const textWidth = (str, fontOrElement, roundUp = true) => {
|
|
8
|
+
// get font metrics from an element
|
|
9
|
+
let font = fontOrElement;
|
|
10
|
+
if (typeof font !== 'string') {
|
|
11
|
+
const element = fontOrElement || document.body;
|
|
12
|
+
font = getFontFromElement(element);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// re-use canvas object for better performance
|
|
16
|
+
const canvas = textWidth.canvas || (textWidth.canvas = document.createElement('canvas'));
|
|
17
|
+
const context = canvas.getContext('2d');
|
|
18
|
+
|
|
19
|
+
context.font = font;
|
|
20
|
+
const metrics = context.measureText(str);
|
|
21
|
+
return roundUp ? Math.ceil(metrics.width) : metrics.width;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const getCssProp = (element, prop) => {
|
|
25
|
+
return window.getComputedStyle(element, null).getPropertyValue(prop);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const getFontFromElement = element => {
|
|
29
|
+
const fontWeight = getCssProp(element, 'font-weight') || 'normal';
|
|
30
|
+
const fontSize = getCssProp(element, 'font-size') || '16px';
|
|
31
|
+
const fontFamily = getCssProp(element, 'font-family') || 'sans-serif';
|
|
32
|
+
|
|
33
|
+
return `${fontWeight} ${fontSize} ${fontFamily}`;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default textWidth;
|