@kiva/kv-components 3.105.3 → 3.107.0
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/.eslintrc.cjs +1 -0
- package/CHANGELOG.md +22 -0
- package/dist/Alea.cjs +87 -0
- package/dist/Alea.js +63 -0
- package/dist/attrs.cjs +50 -0
- package/dist/attrs.js +26 -0
- package/dist/carousels.cjs +184 -0
- package/dist/carousels.js +147 -0
- package/dist/chunk-HV3AUBFT.js +15 -0
- package/dist/expander.cjs +78 -0
- package/dist/expander.js +53 -0
- package/dist/imageUtils.cjs +54 -0
- package/dist/imageUtils.js +29 -0
- package/dist/loanCard.cjs +222 -0
- package/dist/loanCard.js +200 -0
- package/dist/loanUtils.cjs +170 -0
- package/dist/loanUtils.js +128 -0
- package/dist/mapUtils.cjs +276 -0
- package/dist/mapUtils.js +248 -0
- package/dist/printing.cjs +42 -0
- package/dist/printing.js +17 -0
- package/dist/scrollLock.cjs +54 -0
- package/dist/scrollLock.js +27 -0
- package/dist/throttle.cjs +38 -0
- package/dist/throttle.js +6 -0
- package/dist/touchEvents.cjs +47 -0
- package/dist/touchEvents.js +21 -0
- package/dist/treemap.cjs +133 -0
- package/dist/treemap.js +109 -0
- package/package.json +12 -4
- package/utils/carousels.js +190 -0
- package/vue/KvCarousel.vue +33 -182
- package/vue/KvVerticalCarousel.vue +156 -0
- package/vue/stories/KvVerticalCarousel.stories.js +168 -0
package/dist/treemap.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// utils/treemap.js
|
|
2
|
+
var getMaximum = (array) => Math.max(...array);
|
|
3
|
+
var getMinimum = (array) => Math.min(...array);
|
|
4
|
+
var sumReducer = (acc, cur) => acc + cur;
|
|
5
|
+
var roundValue = (number) => Math.max(Math.round(number * 100) / 100, 0);
|
|
6
|
+
var validateArguments = ({ data, width, height }) => {
|
|
7
|
+
if (!width || typeof width !== "number" || width < 0) {
|
|
8
|
+
throw new Error("You need to specify the width of your treemap");
|
|
9
|
+
}
|
|
10
|
+
if (!height || typeof height !== "number" || height < 0) {
|
|
11
|
+
throw new Error("You need to specify the height of your treemap");
|
|
12
|
+
}
|
|
13
|
+
if (!data || !Array.isArray(data) || data.length === 0 || !data.every((dataPoint) => Object.prototype.hasOwnProperty.call(dataPoint, "value") && typeof dataPoint.value === "number" && dataPoint.value >= 0 && !Number.isNaN(dataPoint.value))) {
|
|
14
|
+
throw new Error("You data must be in this format [{ value: 1 }, { value: 2 }], 'value' being a positive number");
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
function getTreemap({ data, width, height }) {
|
|
18
|
+
let Rectangle = {};
|
|
19
|
+
let initialData = [];
|
|
20
|
+
function worstRatio(row, width2) {
|
|
21
|
+
const sum = row.reduce(sumReducer, 0);
|
|
22
|
+
const rowMax = getMaximum(row);
|
|
23
|
+
const rowMin = getMinimum(row);
|
|
24
|
+
return Math.max(width2 ** 2 * rowMax / sum ** 2, sum ** 2 / (width2 ** 2 * rowMin));
|
|
25
|
+
}
|
|
26
|
+
const getMinWidth = () => {
|
|
27
|
+
if (Rectangle.totalHeight ** 2 > Rectangle.totalWidth ** 2) {
|
|
28
|
+
return { value: Rectangle.totalWidth, vertical: false };
|
|
29
|
+
}
|
|
30
|
+
return { value: Rectangle.totalHeight, vertical: true };
|
|
31
|
+
};
|
|
32
|
+
const layoutRow = (row, width2, vertical) => {
|
|
33
|
+
const rowHeight = row.reduce(sumReducer, 0) / width2;
|
|
34
|
+
row.forEach((rowItem) => {
|
|
35
|
+
const rowWidth = rowItem / rowHeight;
|
|
36
|
+
const { xBeginning } = Rectangle;
|
|
37
|
+
const { yBeginning } = Rectangle;
|
|
38
|
+
let data2;
|
|
39
|
+
if (vertical) {
|
|
40
|
+
data2 = {
|
|
41
|
+
x: xBeginning,
|
|
42
|
+
y: yBeginning,
|
|
43
|
+
width: rowHeight,
|
|
44
|
+
height: rowWidth,
|
|
45
|
+
data: initialData[Rectangle.data.length]
|
|
46
|
+
};
|
|
47
|
+
Rectangle.yBeginning += rowWidth;
|
|
48
|
+
} else {
|
|
49
|
+
data2 = {
|
|
50
|
+
x: xBeginning,
|
|
51
|
+
y: yBeginning,
|
|
52
|
+
width: rowWidth,
|
|
53
|
+
height: rowHeight,
|
|
54
|
+
data: initialData[Rectangle.data.length]
|
|
55
|
+
};
|
|
56
|
+
Rectangle.xBeginning += rowWidth;
|
|
57
|
+
}
|
|
58
|
+
Rectangle.data.push(data2);
|
|
59
|
+
});
|
|
60
|
+
if (vertical) {
|
|
61
|
+
Rectangle.xBeginning += rowHeight;
|
|
62
|
+
Rectangle.yBeginning -= width2;
|
|
63
|
+
Rectangle.totalWidth -= rowHeight;
|
|
64
|
+
} else {
|
|
65
|
+
Rectangle.xBeginning -= width2;
|
|
66
|
+
Rectangle.yBeginning += rowHeight;
|
|
67
|
+
Rectangle.totalHeight -= rowHeight;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const layoutLastRow = (rows, children, width2) => {
|
|
71
|
+
const { vertical } = getMinWidth();
|
|
72
|
+
layoutRow(rows, width2, vertical);
|
|
73
|
+
layoutRow(children, width2, vertical);
|
|
74
|
+
};
|
|
75
|
+
const squarify = (children, row, width2) => {
|
|
76
|
+
if (children.length === 1) {
|
|
77
|
+
return layoutLastRow(row, children, width2);
|
|
78
|
+
}
|
|
79
|
+
const rowWithChild = [...row, children[0]];
|
|
80
|
+
if (row.length === 0 || worstRatio(row, width2) >= worstRatio(rowWithChild, width2)) {
|
|
81
|
+
children.shift();
|
|
82
|
+
return squarify(children, rowWithChild, width2);
|
|
83
|
+
}
|
|
84
|
+
layoutRow(row, width2, getMinWidth().vertical);
|
|
85
|
+
return squarify(children, [], getMinWidth().value);
|
|
86
|
+
};
|
|
87
|
+
validateArguments({ data, width, height });
|
|
88
|
+
Rectangle = {
|
|
89
|
+
data: [],
|
|
90
|
+
xBeginning: 0,
|
|
91
|
+
yBeginning: 0,
|
|
92
|
+
totalWidth: width,
|
|
93
|
+
totalHeight: height
|
|
94
|
+
};
|
|
95
|
+
initialData = data;
|
|
96
|
+
const totalValue = data.map((dataPoint) => dataPoint.value).reduce(sumReducer, 0);
|
|
97
|
+
const dataScaled = data.map((dataPoint) => dataPoint.value * height * width / totalValue);
|
|
98
|
+
squarify(dataScaled, [], getMinWidth().value);
|
|
99
|
+
return Rectangle.data.map((dataPoint) => ({
|
|
100
|
+
...dataPoint,
|
|
101
|
+
x: roundValue(dataPoint.x),
|
|
102
|
+
y: roundValue(dataPoint.y),
|
|
103
|
+
width: roundValue(dataPoint.width),
|
|
104
|
+
height: roundValue(dataPoint.height)
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
getTreemap
|
|
109
|
+
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kiva/kv-components",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.107.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
|
-
"main": "index.
|
|
8
|
+
"main": "dist/index.cjs",
|
|
9
|
+
"module": "dist/index.js",
|
|
9
10
|
"devDependencies": {
|
|
10
11
|
"@babel/core": "^7.14.8",
|
|
11
12
|
"@babel/eslint-parser": "^7.13.14",
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
"storybook": "7.6.20",
|
|
47
48
|
"style-loader": "^3.3.4",
|
|
48
49
|
"tailwindcss": "^3.4.3",
|
|
50
|
+
"tsup": "^6.7.0",
|
|
49
51
|
"vue": "2.6.14",
|
|
50
52
|
"vue-loader": "^15.9.6",
|
|
51
53
|
"vue-router": "^3.5.2",
|
|
@@ -56,7 +58,7 @@
|
|
|
56
58
|
"build-storybook": "vue-demi-switch 2 && storybook build -c vue/.storybook",
|
|
57
59
|
"lint": "eslint --ext .js,.vue ./",
|
|
58
60
|
"test": "npm run lint",
|
|
59
|
-
"build": "
|
|
61
|
+
"build": "tsup utils/*.js --format cjs,esm --clean"
|
|
60
62
|
},
|
|
61
63
|
"dependencies": {
|
|
62
64
|
"@kiva/kv-tokens": "^2.13.0",
|
|
@@ -74,6 +76,12 @@
|
|
|
74
76
|
"popper.js": "^1.16.1",
|
|
75
77
|
"vue-demi": "^0.14.7"
|
|
76
78
|
},
|
|
79
|
+
"exports": {
|
|
80
|
+
".": {
|
|
81
|
+
"require": "./dist/index.cjs",
|
|
82
|
+
"import": "./dist/index.js"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
77
85
|
"peerDependencies": {
|
|
78
86
|
"@vue/composition-api": "^1.0.0-rc.1",
|
|
79
87
|
"vue": "^2.6.0 || >=3.0.0"
|
|
@@ -83,5 +91,5 @@
|
|
|
83
91
|
"optional": true
|
|
84
92
|
}
|
|
85
93
|
},
|
|
86
|
-
"gitHead": "
|
|
94
|
+
"gitHead": "6efc99e83efc05ac8d3ee259bc24a22012dc22ef"
|
|
87
95
|
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/* eslint-disable import/prefer-default-export */
|
|
2
|
+
import {
|
|
3
|
+
computed,
|
|
4
|
+
onMounted,
|
|
5
|
+
onUnmounted,
|
|
6
|
+
ref,
|
|
7
|
+
toRefs,
|
|
8
|
+
nextTick,
|
|
9
|
+
} from 'vue-demi';
|
|
10
|
+
import EmblaCarousel from 'embla-carousel';
|
|
11
|
+
import { throttle } from './throttle';
|
|
12
|
+
|
|
13
|
+
export function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
14
|
+
const {
|
|
15
|
+
emblaOptions,
|
|
16
|
+
slidesToScroll,
|
|
17
|
+
} = toRefs(props);
|
|
18
|
+
const rootEl = ref(null);
|
|
19
|
+
const embla = ref(null);
|
|
20
|
+
const slides = ref([]);
|
|
21
|
+
const startIndex = emblaOptions.value?.startIndex ?? 0;
|
|
22
|
+
const currentIndex = ref(startIndex);
|
|
23
|
+
// The indicator count may differ from the slide count when multiple slides are in view
|
|
24
|
+
const slideIndicatorCount = ref(0);
|
|
25
|
+
|
|
26
|
+
const componentSlotKeys = computed(() => {
|
|
27
|
+
const keys = Object.keys(slots);
|
|
28
|
+
return keys;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const nextIndex = computed(() => {
|
|
32
|
+
const nextSlideIndex = currentIndex.value + 1;
|
|
33
|
+
if (nextSlideIndex < slides.value.length) {
|
|
34
|
+
return nextSlideIndex;
|
|
35
|
+
}
|
|
36
|
+
return 0;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const previousIndex = computed(() => {
|
|
40
|
+
const previousSlideIndex = currentIndex.value - 1;
|
|
41
|
+
if (previousSlideIndex >= 0) {
|
|
42
|
+
return previousSlideIndex;
|
|
43
|
+
}
|
|
44
|
+
return slides.value.length - 1;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Jump to a specific slide index
|
|
49
|
+
*
|
|
50
|
+
* @param {Number} num Index of slide to show
|
|
51
|
+
* @public This is a public method
|
|
52
|
+
*/
|
|
53
|
+
const goToSlide = (index) => {
|
|
54
|
+
embla.value.scrollTo(index);
|
|
55
|
+
};
|
|
56
|
+
const handleUserInteraction = async (index, interactionType) => {
|
|
57
|
+
if (index !== null && typeof index !== 'undefined') {
|
|
58
|
+
await nextTick(); // wait for embla.
|
|
59
|
+
goToSlide(index);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Fires when the user interacts with the carousel.
|
|
63
|
+
* Contains the interaction type (swipe-left, click-left-arrow, etc.)
|
|
64
|
+
* @event interact-carousel
|
|
65
|
+
* @type {Event}
|
|
66
|
+
*/
|
|
67
|
+
emit('interact-carousel', interactionType);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Returns number of slides in the carousel
|
|
72
|
+
*
|
|
73
|
+
* @returns {Number}
|
|
74
|
+
*/
|
|
75
|
+
const slideIndicatorListLength = () => {
|
|
76
|
+
const indicator = embla.value ? embla.value.scrollSnapList().length : 0;
|
|
77
|
+
slideIndicatorCount.value = indicator;
|
|
78
|
+
return indicator;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Reinitialize the carousel.
|
|
83
|
+
* Used after adding slides dynamically.
|
|
84
|
+
*
|
|
85
|
+
* @public This is a public method
|
|
86
|
+
*/
|
|
87
|
+
const reInitVisible = () => {
|
|
88
|
+
const slidesInView = embla.value.slidesInView(true).length;
|
|
89
|
+
if (slidesInView) {
|
|
90
|
+
embla.value.reInit({
|
|
91
|
+
slidesToScroll: slidesInView,
|
|
92
|
+
inViewThreshold: 0.9,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const reInit = () => {
|
|
97
|
+
embla.value.reInit();
|
|
98
|
+
if (slidesToScroll.value === 'visible') {
|
|
99
|
+
reInitVisible();
|
|
100
|
+
}
|
|
101
|
+
slides.value = embla.value.slideNodes();
|
|
102
|
+
slideIndicatorListLength();
|
|
103
|
+
};
|
|
104
|
+
const onCarouselContainerClick = (e) => {
|
|
105
|
+
// If we're dragging, block click handlers within slides
|
|
106
|
+
if (embla.value && !embla.value.clickAllowed()) {
|
|
107
|
+
e.preventDefault();
|
|
108
|
+
e.stopPropagation();
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* If the slide is not completely in view in the carousel
|
|
113
|
+
* it should be aria-hidden
|
|
114
|
+
*
|
|
115
|
+
* @param {Number} index The current index of the slide
|
|
116
|
+
* @returns {Boolean}
|
|
117
|
+
*/
|
|
118
|
+
const isAriaHidden = (index) => {
|
|
119
|
+
if (embla.value) {
|
|
120
|
+
return !embla.value.slidesInView(true).includes(index);
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
onMounted(async () => {
|
|
126
|
+
embla.value = EmblaCarousel(rootEl.value, {
|
|
127
|
+
loop: true,
|
|
128
|
+
containScroll: 'trimSnaps',
|
|
129
|
+
inViewThreshold: 0.9,
|
|
130
|
+
align: 'start',
|
|
131
|
+
...extraEmblaOptions,
|
|
132
|
+
...emblaOptions.value,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
if (slidesToScroll.value === 'visible') {
|
|
136
|
+
reInitVisible();
|
|
137
|
+
|
|
138
|
+
embla.value.on(
|
|
139
|
+
'resize',
|
|
140
|
+
throttle(() => {
|
|
141
|
+
embla.value.reInit({
|
|
142
|
+
slidesToScroll: embla.value.slidesInView(true).length || 'auto',
|
|
143
|
+
inViewThreshold: 0.9,
|
|
144
|
+
});
|
|
145
|
+
slides.value = embla.value.slideNodes();
|
|
146
|
+
slideIndicatorListLength();
|
|
147
|
+
}, 250),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// get slide components
|
|
152
|
+
slides.value = embla.value.slideNodes();
|
|
153
|
+
slideIndicatorListLength();
|
|
154
|
+
|
|
155
|
+
embla?.value?.on('select', () => {
|
|
156
|
+
currentIndex.value = embla.value.selectedScrollSnap();
|
|
157
|
+
/**
|
|
158
|
+
* The index of the slide that the carousel has changed to
|
|
159
|
+
* @event change
|
|
160
|
+
* @type {Event}
|
|
161
|
+
*/
|
|
162
|
+
nextTick(() => {
|
|
163
|
+
emit('change', currentIndex);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
onUnmounted(async () => {
|
|
169
|
+
embla?.value?.off('select');
|
|
170
|
+
embla?.value?.destroy();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
rootEl,
|
|
175
|
+
embla,
|
|
176
|
+
slides,
|
|
177
|
+
currentIndex,
|
|
178
|
+
componentSlotKeys,
|
|
179
|
+
nextIndex,
|
|
180
|
+
previousIndex,
|
|
181
|
+
slideIndicatorCount,
|
|
182
|
+
handleUserInteraction,
|
|
183
|
+
goToSlide,
|
|
184
|
+
reInit,
|
|
185
|
+
reInitVisible,
|
|
186
|
+
onCarouselContainerClick,
|
|
187
|
+
isAriaHidden,
|
|
188
|
+
slideIndicatorListLength,
|
|
189
|
+
};
|
|
190
|
+
}
|
package/vue/KvCarousel.vue
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
:aria-current="currentIndex === index ? 'true' : 'false'"
|
|
24
24
|
:aria-hidden="isAriaHidden(index)? 'true' : 'false'"
|
|
25
25
|
:tab-index="isAriaHidden(index) ? '-1' : false"
|
|
26
|
-
:class="{ 'tw-w-full': !multipleSlidesVisible || slideMaxWidth, '
|
|
26
|
+
:class="{ 'tw-w-full': !multipleSlidesVisible || slideMaxWidth, 'circle-slide': inCircle }"
|
|
27
27
|
:style="slideMaxWidth ? `max-width:${slideMaxWidth}` :''"
|
|
28
28
|
>
|
|
29
29
|
<slot
|
|
@@ -146,22 +146,13 @@
|
|
|
146
146
|
</template>
|
|
147
147
|
|
|
148
148
|
<script>
|
|
149
|
-
import {
|
|
150
|
-
computed,
|
|
151
|
-
onMounted,
|
|
152
|
-
onUnmounted,
|
|
153
|
-
ref,
|
|
154
|
-
toRefs,
|
|
155
|
-
nextTick,
|
|
156
|
-
} from 'vue-demi';
|
|
157
|
-
import EmblaCarousel from 'embla-carousel';
|
|
158
149
|
import {
|
|
159
150
|
mdiChevronLeft,
|
|
160
151
|
mdiChevronRight,
|
|
161
152
|
mdiArrowLeft,
|
|
162
153
|
mdiArrowRight,
|
|
163
154
|
} from '@mdi/js';
|
|
164
|
-
import {
|
|
155
|
+
import { carouselUtil } from '../utils/carousels';
|
|
165
156
|
|
|
166
157
|
import KvMaterialIcon from './KvMaterialIcon.vue';
|
|
167
158
|
|
|
@@ -236,183 +227,43 @@ export default {
|
|
|
236
227
|
],
|
|
237
228
|
setup(props, { emit, slots }) {
|
|
238
229
|
const {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const nextIndex = computed(() => {
|
|
256
|
-
const nextSlideIndex = currentIndex.value + 1;
|
|
257
|
-
if (nextSlideIndex < slides.value.length) {
|
|
258
|
-
return nextSlideIndex;
|
|
259
|
-
}
|
|
260
|
-
return 0;
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
const previousIndex = computed(() => {
|
|
264
|
-
const previousSlideIndex = currentIndex.value - 1;
|
|
265
|
-
if (previousSlideIndex >= 0) {
|
|
266
|
-
return previousSlideIndex;
|
|
267
|
-
}
|
|
268
|
-
return slides.value.length - 1;
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Jump to a specific slide index
|
|
273
|
-
*
|
|
274
|
-
* @param {Number} num Index of slide to show
|
|
275
|
-
* @public This is a public method
|
|
276
|
-
*/
|
|
277
|
-
const goToSlide = (index) => {
|
|
278
|
-
embla.value.scrollTo(index);
|
|
279
|
-
};
|
|
280
|
-
const handleUserInteraction = async (index, interactionType) => {
|
|
281
|
-
if (index !== null && typeof index !== 'undefined') {
|
|
282
|
-
await nextTick(); // wait for embla.
|
|
283
|
-
goToSlide(index);
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Fires when the user interacts with the carousel.
|
|
287
|
-
* Contains the interaction type (swipe-left, click-left-arrow, etc.)
|
|
288
|
-
* @event interact-carousel
|
|
289
|
-
* @type {Event}
|
|
290
|
-
*/
|
|
291
|
-
emit('interact-carousel', interactionType);
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Returns number of slides in the carousel
|
|
296
|
-
*
|
|
297
|
-
* @returns {Number}
|
|
298
|
-
*/
|
|
299
|
-
const slideIndicatorListLength = () => {
|
|
300
|
-
const indicator = embla.value ? embla.value.scrollSnapList().length : 0;
|
|
301
|
-
slideIndicatorCount.value = indicator;
|
|
302
|
-
return indicator;
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Reinitialize the carousel.
|
|
307
|
-
* Used after adding slides dynamically.
|
|
308
|
-
*
|
|
309
|
-
* @public This is a public method
|
|
310
|
-
*/
|
|
311
|
-
const reInitVisible = () => {
|
|
312
|
-
const slidesInView = embla.value.slidesInView(true).length;
|
|
313
|
-
if (slidesInView) {
|
|
314
|
-
embla.value.reInit({
|
|
315
|
-
slidesToScroll: slidesInView,
|
|
316
|
-
inViewThreshold: 0.9,
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
const reInit = () => {
|
|
321
|
-
embla.value.reInit();
|
|
322
|
-
if (slidesToScroll.value === 'visible') {
|
|
323
|
-
reInitVisible();
|
|
324
|
-
}
|
|
325
|
-
slides.value = embla.value.slideNodes();
|
|
326
|
-
slideIndicatorListLength();
|
|
327
|
-
};
|
|
328
|
-
const onCarouselContainerClick = (e) => {
|
|
329
|
-
// If we're dragging, block click handlers within slides
|
|
330
|
-
if (embla.value && !embla.value.clickAllowed()) {
|
|
331
|
-
e.preventDefault();
|
|
332
|
-
e.stopPropagation();
|
|
333
|
-
}
|
|
334
|
-
};
|
|
335
|
-
/**
|
|
336
|
-
* If the slide is not completely in view in the carousel
|
|
337
|
-
* it should be aria-hidden
|
|
338
|
-
*
|
|
339
|
-
* @param {Number} index The current index of the slide
|
|
340
|
-
* @returns {Boolean}
|
|
341
|
-
*/
|
|
342
|
-
const isAriaHidden = (index) => {
|
|
343
|
-
if (embla.value) {
|
|
344
|
-
return !embla.value.slidesInView(true).includes(index);
|
|
345
|
-
}
|
|
346
|
-
return false;
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
onMounted(async () => {
|
|
350
|
-
embla.value = EmblaCarousel(rootEl.value, {
|
|
351
|
-
loop: true,
|
|
352
|
-
containScroll: 'trimSnaps',
|
|
353
|
-
inViewThreshold: 0.9,
|
|
354
|
-
align: 'start',
|
|
355
|
-
...emblaOptions.value,
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
if (slidesToScroll.value === 'visible') {
|
|
359
|
-
reInitVisible();
|
|
360
|
-
|
|
361
|
-
embla.value.on(
|
|
362
|
-
'resize',
|
|
363
|
-
throttle(() => {
|
|
364
|
-
embla.value.reInit({
|
|
365
|
-
slidesToScroll: embla.value.slidesInView(true).length || 'auto',
|
|
366
|
-
inViewThreshold: 0.9,
|
|
367
|
-
});
|
|
368
|
-
slides.value = embla.value.slideNodes();
|
|
369
|
-
slideIndicatorListLength();
|
|
370
|
-
}, 250),
|
|
371
|
-
);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// get slide components
|
|
375
|
-
slides.value = embla.value.slideNodes();
|
|
376
|
-
slideIndicatorListLength();
|
|
377
|
-
|
|
378
|
-
embla?.value?.on('select', () => {
|
|
379
|
-
currentIndex.value = embla.value.selectedScrollSnap();
|
|
380
|
-
/**
|
|
381
|
-
* The index of the slide that the carousel has changed to
|
|
382
|
-
* @event change
|
|
383
|
-
* @type {Event}
|
|
384
|
-
*/
|
|
385
|
-
nextTick(() => {
|
|
386
|
-
emit('change', currentIndex);
|
|
387
|
-
});
|
|
388
|
-
});
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
onUnmounted(async () => {
|
|
392
|
-
embla?.value?.off('select');
|
|
393
|
-
embla?.value?.destroy();
|
|
394
|
-
});
|
|
230
|
+
componentSlotKeys,
|
|
231
|
+
currentIndex,
|
|
232
|
+
embla,
|
|
233
|
+
goToSlide,
|
|
234
|
+
handleUserInteraction,
|
|
235
|
+
isAriaHidden,
|
|
236
|
+
nextIndex,
|
|
237
|
+
onCarouselContainerClick,
|
|
238
|
+
previousIndex,
|
|
239
|
+
reInit,
|
|
240
|
+
reInitVisible,
|
|
241
|
+
rootEl,
|
|
242
|
+
slideIndicatorCount,
|
|
243
|
+
slideIndicatorListLength,
|
|
244
|
+
slides,
|
|
245
|
+
} = carouselUtil(props, { emit, slots });
|
|
395
246
|
|
|
396
247
|
return {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
248
|
+
componentSlotKeys,
|
|
249
|
+
currentIndex,
|
|
250
|
+
embla,
|
|
251
|
+
goToSlide,
|
|
252
|
+
handleUserInteraction,
|
|
253
|
+
isAriaHidden,
|
|
400
254
|
mdiArrowLeft,
|
|
401
255
|
mdiArrowRight,
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
currentIndex,
|
|
405
|
-
componentSlotKeys,
|
|
256
|
+
mdiChevronLeft,
|
|
257
|
+
mdiChevronRight,
|
|
406
258
|
nextIndex,
|
|
259
|
+
onCarouselContainerClick,
|
|
407
260
|
previousIndex,
|
|
408
|
-
slideIndicatorCount,
|
|
409
|
-
handleUserInteraction,
|
|
410
|
-
goToSlide,
|
|
411
261
|
reInit,
|
|
412
262
|
reInitVisible,
|
|
413
|
-
|
|
414
|
-
|
|
263
|
+
rootEl,
|
|
264
|
+
slideIndicatorCount,
|
|
415
265
|
slideIndicatorListLength,
|
|
266
|
+
slides,
|
|
416
267
|
};
|
|
417
268
|
},
|
|
418
269
|
};
|
|
@@ -425,17 +276,17 @@ export default {
|
|
|
425
276
|
}
|
|
426
277
|
}
|
|
427
278
|
|
|
428
|
-
.
|
|
279
|
+
.circle-slide {
|
|
429
280
|
width: auto;
|
|
430
281
|
}
|
|
431
282
|
|
|
432
|
-
.
|
|
283
|
+
.circle-slide.is-selected {
|
|
433
284
|
opacity: 1;
|
|
434
285
|
transform: scale(1.2);
|
|
435
286
|
max-width: 300px;
|
|
436
287
|
}
|
|
437
288
|
|
|
438
|
-
.
|
|
289
|
+
.circle-slide:not(.is-selected) {
|
|
439
290
|
opacity: 0.5;
|
|
440
291
|
transform: scale(0.7);
|
|
441
292
|
}
|