@kiva/kv-components 3.106.0 → 3.107.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.
- package/.eslintrc.cjs +1 -0
- package/CHANGELOG.md +22 -0
- package/dist/components/.storybook/main.js +85 -0
- package/dist/components/.storybook/package.json +3 -0
- package/dist/components/.storybook/preview.js +61 -0
- package/dist/components/.storybook/tailwind.css +5 -0
- package/dist/components/KvAccordionItem.vue +130 -0
- package/dist/components/KvActivityRow.vue +33 -0
- package/dist/components/KvBorrowerImage.vue +179 -0
- package/dist/components/KvButton.vue +287 -0
- package/dist/components/KvCarousel.vue +297 -0
- package/dist/components/KvCartModal.vue +365 -0
- package/dist/components/KvCheckbox.vue +203 -0
- package/dist/components/KvChip.vue +54 -0
- package/dist/components/KvClassicLoanCard.vue +527 -0
- package/dist/components/KvCommentsAdd.vue +135 -0
- package/dist/components/KvCommentsContainer.vue +84 -0
- package/dist/components/KvCommentsHeartButton.vue +70 -0
- package/dist/components/KvCommentsList.vue +68 -0
- package/dist/components/KvCommentsListItem.vue +241 -0
- package/dist/components/KvCommentsReplyButton.vue +52 -0
- package/dist/components/KvContentfulImg.vue +273 -0
- package/dist/components/KvCountdownTimer.vue +59 -0
- package/dist/components/KvExpandable.vue +84 -0
- package/dist/components/KvExpandableQuestion.vue +120 -0
- package/dist/components/KvFlag.vue +120 -0
- package/dist/components/KvGrid.vue +28 -0
- package/dist/components/KvImpactDashboardHeader.vue +40 -0
- package/dist/components/KvInlineActivityCard.vue +55 -0
- package/dist/components/KvInlineActivityFeed.vue +38 -0
- package/dist/components/KvIntroductionLoanCard.vue +446 -0
- package/dist/components/KvLendAmountButton.vue +65 -0
- package/dist/components/KvLendCta.vue +451 -0
- package/dist/components/KvLightbox.vue +334 -0
- package/dist/components/KvLineGraph.vue +128 -0
- package/dist/components/KvLoadingPlaceholder.vue +38 -0
- package/dist/components/KvLoadingSpinner.vue +81 -0
- package/dist/components/KvLoanActivities.vue +268 -0
- package/dist/components/KvLoanBookmark.vue +39 -0
- package/dist/components/KvLoanCallouts.vue +53 -0
- package/dist/components/KvLoanProgressGroup.vue +76 -0
- package/dist/components/KvLoanTag.vue +88 -0
- package/dist/components/KvLoanTeamPick.vue +44 -0
- package/dist/components/KvLoanUse.vue +92 -0
- package/dist/components/KvMap.vue +599 -0
- package/dist/components/KvMaterialIcon.vue +47 -0
- package/dist/components/KvPageContainer.vue +15 -0
- package/dist/components/KvPagination.vue +198 -0
- package/dist/components/KvPieChart.vue +257 -0
- package/dist/components/KvPopper.vue +178 -0
- package/dist/components/KvProgressBar.vue +149 -0
- package/dist/components/KvRadio.vue +198 -0
- package/dist/components/KvSelect.vue +114 -0
- package/dist/components/KvSideSheet.vue +134 -0
- package/dist/components/KvSwitch.vue +143 -0
- package/dist/components/KvTab.vue +90 -0
- package/dist/components/KvTabPanel.vue +64 -0
- package/dist/components/KvTabs.vue +182 -0
- package/dist/components/KvTextInput.vue +247 -0
- package/dist/components/KvTextLink.vue +138 -0
- package/dist/components/KvThemeProvider.vue +122 -0
- package/dist/components/KvToast.vue +221 -0
- package/dist/components/KvTooltip.vue +168 -0
- package/dist/components/KvTreeMapChart.vue +229 -0
- package/dist/components/KvUserAvatar.vue +132 -0
- package/dist/components/KvVerticalCarousel.vue +156 -0
- package/dist/components/KvVotingCard.vue +160 -0
- package/dist/components/KvVotingCardV2.vue +154 -0
- package/dist/components/KvWideLoanCard.vue +432 -0
- package/dist/components/stories/Forms.stories.js +62 -0
- package/dist/components/stories/KvAccordionItem.stories.js +24 -0
- package/dist/components/stories/KvActivityRow.stories.js +25 -0
- package/dist/components/stories/KvBorrowerImage.stories.js +68 -0
- package/dist/components/stories/KvButton.stories.js +144 -0
- package/dist/components/stories/KvCarousel.stories.js +426 -0
- package/dist/components/stories/KvCartModal.stories.js +54 -0
- package/dist/components/stories/KvCheckbox.stories.js +163 -0
- package/dist/components/stories/KvChip.stories.js +43 -0
- package/dist/components/stories/KvClassicLoanCard.stories.js +480 -0
- package/dist/components/stories/KvCommentsAdd.stories.js +32 -0
- package/dist/components/stories/KvCommentsContainer.stories.js +42 -0
- package/dist/components/stories/KvCommentsHeartButton.stories.js +25 -0
- package/dist/components/stories/KvCommentsList.stories.js +39 -0
- package/dist/components/stories/KvCommentsListItem.stories.js +45 -0
- package/dist/components/stories/KvCommentsReplyButton.stories.js +21 -0
- package/dist/components/stories/KvContentfulImg.stories.js +196 -0
- package/dist/components/stories/KvCountdownTimer.stories.js +30 -0
- package/dist/components/stories/KvExpandableQuestion.stories.js +129 -0
- package/dist/components/stories/KvFlag.stories.js +36 -0
- package/dist/components/stories/KvGrid.stories.js +97 -0
- package/dist/components/stories/KvImpactDashboardHeader.stories.js +22 -0
- package/dist/components/stories/KvInlineActivityCard.stories.js +69 -0
- package/dist/components/stories/KvInlineActivityFeed.stories.js +76 -0
- package/dist/components/stories/KvIntroductionLoanCard.stories.js +208 -0
- package/dist/components/stories/KvLendAmountButton.stories.js +31 -0
- package/dist/components/stories/KvLendCta.stories.js +177 -0
- package/dist/components/stories/KvLightbox.stories.js +304 -0
- package/dist/components/stories/KvLineGraph.stories.js +52 -0
- package/dist/components/stories/KvLoadingPlaceholder.stories.js +17 -0
- package/dist/components/stories/KvLoadingSpinner.stories.js +52 -0
- package/dist/components/stories/KvLoanActivities.stories.js +104 -0
- package/dist/components/stories/KvLoanBookmark.stories.js +22 -0
- package/dist/components/stories/KvLoanCallouts.stories.js +22 -0
- package/dist/components/stories/KvLoanProgressGroup.stories.js +29 -0
- package/dist/components/stories/KvLoanTag.stories.js +61 -0
- package/dist/components/stories/KvLoanTeamPick.stories.js +20 -0
- package/dist/components/stories/KvLoanUse.stories.js +60 -0
- package/dist/components/stories/KvMap.stories.js +121 -0
- package/dist/components/stories/KvMaterialIcon.stories.js +201 -0
- package/dist/components/stories/KvPageContainer.stories.js +50 -0
- package/dist/components/stories/KvPagination.stories.js +70 -0
- package/dist/components/stories/KvPieChart.stories.js +47 -0
- package/dist/components/stories/KvProgressBar.stories.js +53 -0
- package/dist/components/stories/KvRadio.stories.js +140 -0
- package/dist/components/stories/KvSelect.stories.js +125 -0
- package/dist/components/stories/KvSideSheet.stories.js +50 -0
- package/dist/components/stories/KvSwitch.stories.js +66 -0
- package/dist/components/stories/KvTabs.stories.js +106 -0
- package/dist/components/stories/KvTextInput.stories.js +194 -0
- package/dist/components/stories/KvTextLink.stories.js +55 -0
- package/dist/components/stories/KvThemeProvider.stories.js +178 -0
- package/dist/components/stories/KvToast.stories.js +117 -0
- package/dist/components/stories/KvTooltip.stories.js +26 -0
- package/dist/components/stories/KvTreeMapChart.stories.js +42 -0
- package/dist/components/stories/KvUserAvatar.stories.js +47 -0
- package/dist/components/stories/KvVerticalCarousel.stories.js +168 -0
- package/dist/components/stories/KvVotingCard.stories.js +33 -0
- package/dist/components/stories/KvVotingCardV2.stories.js +89 -0
- package/dist/components/stories/KvWideLoanCard.stories.js +292 -0
- package/dist/components/stories/StyleguidePrimitives.stories.js +499 -0
- package/dist/components/stories/StyleguideProse.stories.js +215 -0
- package/dist/data/countries-borders.json +1 -0
- package/dist/data/ne_110m_admin_0_countries.json +1 -0
- package/dist/utils/Alea.cjs +87 -0
- package/dist/utils/Alea.js +9 -0
- package/dist/utils/attrs.cjs +50 -0
- package/dist/utils/attrs.js +7 -0
- package/dist/utils/carousels.cjs +184 -0
- package/dist/utils/carousels.js +8 -0
- package/dist/utils/chunk-3HK4G4NT.js +27 -0
- package/dist/utils/chunk-55HF2ORX.js +201 -0
- package/dist/utils/chunk-AY3PR5S4.js +54 -0
- package/dist/utils/chunk-AZPWOFD5.js +148 -0
- package/dist/utils/chunk-B5J5WLAH.js +18 -0
- package/dist/utils/chunk-GPSH6OPA.js +64 -0
- package/dist/utils/chunk-HIY5IW65.js +28 -0
- package/dist/utils/chunk-HV3AUBFT.js +15 -0
- package/dist/utils/chunk-MSMZIN54.js +110 -0
- package/dist/utils/chunk-OXJCCNNW.js +30 -0
- package/dist/utils/chunk-S3MABILA.js +22 -0
- package/dist/utils/chunk-VIGEMAKO.js +249 -0
- package/dist/utils/chunk-YCNMJ4YV.js +37 -0
- package/dist/utils/chunk-YFEC5ODJ.js +129 -0
- package/dist/utils/expander.cjs +78 -0
- package/dist/utils/expander.js +9 -0
- package/dist/utils/imageUtils.cjs +54 -0
- package/dist/utils/imageUtils.js +9 -0
- package/dist/utils/index.cjs +1118 -0
- package/dist/utils/index.js +166 -0
- package/dist/utils/loanCard.cjs +222 -0
- package/dist/utils/loanCard.js +9 -0
- package/dist/utils/loanUtils.cjs +170 -0
- package/dist/utils/loanUtils.js +23 -0
- package/dist/utils/mapUtils.cjs +276 -0
- package/dist/utils/mapUtils.js +15 -0
- package/dist/utils/printing.cjs +42 -0
- package/dist/utils/printing.js +9 -0
- package/dist/utils/scrollLock.cjs +54 -0
- package/dist/utils/scrollLock.js +13 -0
- package/dist/utils/throttle.cjs +38 -0
- package/dist/utils/throttle.js +7 -0
- package/dist/utils/touchEvents.cjs +47 -0
- package/dist/utils/touchEvents.js +11 -0
- package/dist/utils/treemap.cjs +133 -0
- package/dist/utils/treemap.js +7 -0
- package/package.json +12 -4
- package/utils/index.js +14 -0
- package/vue/KvVerticalCarousel.vue +1 -1
- package/index.js +0 -3
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import {
|
|
2
|
+
throttle
|
|
3
|
+
} from "./chunk-HV3AUBFT.js";
|
|
4
|
+
|
|
5
|
+
// utils/carousels.js
|
|
6
|
+
import {
|
|
7
|
+
computed,
|
|
8
|
+
onMounted,
|
|
9
|
+
onUnmounted,
|
|
10
|
+
ref,
|
|
11
|
+
toRefs,
|
|
12
|
+
nextTick
|
|
13
|
+
} from "vue-demi";
|
|
14
|
+
import EmblaCarousel from "embla-carousel";
|
|
15
|
+
function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
16
|
+
var _a;
|
|
17
|
+
const {
|
|
18
|
+
emblaOptions,
|
|
19
|
+
slidesToScroll
|
|
20
|
+
} = toRefs(props);
|
|
21
|
+
const rootEl = ref(null);
|
|
22
|
+
const embla = ref(null);
|
|
23
|
+
const slides = ref([]);
|
|
24
|
+
const startIndex = ((_a = emblaOptions.value) == null ? void 0 : _a.startIndex) ?? 0;
|
|
25
|
+
const currentIndex = ref(startIndex);
|
|
26
|
+
const slideIndicatorCount = ref(0);
|
|
27
|
+
const componentSlotKeys = computed(() => {
|
|
28
|
+
const keys = Object.keys(slots);
|
|
29
|
+
return keys;
|
|
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
|
+
const previousIndex = computed(() => {
|
|
39
|
+
const previousSlideIndex = currentIndex.value - 1;
|
|
40
|
+
if (previousSlideIndex >= 0) {
|
|
41
|
+
return previousSlideIndex;
|
|
42
|
+
}
|
|
43
|
+
return slides.value.length - 1;
|
|
44
|
+
});
|
|
45
|
+
const goToSlide = (index) => {
|
|
46
|
+
embla.value.scrollTo(index);
|
|
47
|
+
};
|
|
48
|
+
const handleUserInteraction = async (index, interactionType) => {
|
|
49
|
+
if (index !== null && typeof index !== "undefined") {
|
|
50
|
+
await nextTick();
|
|
51
|
+
goToSlide(index);
|
|
52
|
+
}
|
|
53
|
+
emit("interact-carousel", interactionType);
|
|
54
|
+
};
|
|
55
|
+
const slideIndicatorListLength = () => {
|
|
56
|
+
const indicator = embla.value ? embla.value.scrollSnapList().length : 0;
|
|
57
|
+
slideIndicatorCount.value = indicator;
|
|
58
|
+
return indicator;
|
|
59
|
+
};
|
|
60
|
+
const reInitVisible = () => {
|
|
61
|
+
const slidesInView = embla.value.slidesInView(true).length;
|
|
62
|
+
if (slidesInView) {
|
|
63
|
+
embla.value.reInit({
|
|
64
|
+
slidesToScroll: slidesInView,
|
|
65
|
+
inViewThreshold: 0.9
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const reInit = () => {
|
|
70
|
+
embla.value.reInit();
|
|
71
|
+
if (slidesToScroll.value === "visible") {
|
|
72
|
+
reInitVisible();
|
|
73
|
+
}
|
|
74
|
+
slides.value = embla.value.slideNodes();
|
|
75
|
+
slideIndicatorListLength();
|
|
76
|
+
};
|
|
77
|
+
const onCarouselContainerClick = (e) => {
|
|
78
|
+
if (embla.value && !embla.value.clickAllowed()) {
|
|
79
|
+
e.preventDefault();
|
|
80
|
+
e.stopPropagation();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const isAriaHidden = (index) => {
|
|
84
|
+
if (embla.value) {
|
|
85
|
+
return !embla.value.slidesInView(true).includes(index);
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
};
|
|
89
|
+
onMounted(async () => {
|
|
90
|
+
var _a2;
|
|
91
|
+
embla.value = EmblaCarousel(rootEl.value, {
|
|
92
|
+
loop: true,
|
|
93
|
+
containScroll: "trimSnaps",
|
|
94
|
+
inViewThreshold: 0.9,
|
|
95
|
+
align: "start",
|
|
96
|
+
...extraEmblaOptions,
|
|
97
|
+
...emblaOptions.value
|
|
98
|
+
});
|
|
99
|
+
if (slidesToScroll.value === "visible") {
|
|
100
|
+
reInitVisible();
|
|
101
|
+
embla.value.on(
|
|
102
|
+
"resize",
|
|
103
|
+
throttle(() => {
|
|
104
|
+
embla.value.reInit({
|
|
105
|
+
slidesToScroll: embla.value.slidesInView(true).length || "auto",
|
|
106
|
+
inViewThreshold: 0.9
|
|
107
|
+
});
|
|
108
|
+
slides.value = embla.value.slideNodes();
|
|
109
|
+
slideIndicatorListLength();
|
|
110
|
+
}, 250)
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
slides.value = embla.value.slideNodes();
|
|
114
|
+
slideIndicatorListLength();
|
|
115
|
+
(_a2 = embla == null ? void 0 : embla.value) == null ? void 0 : _a2.on("select", () => {
|
|
116
|
+
currentIndex.value = embla.value.selectedScrollSnap();
|
|
117
|
+
nextTick(() => {
|
|
118
|
+
emit("change", currentIndex);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
onUnmounted(async () => {
|
|
123
|
+
var _a2, _b;
|
|
124
|
+
(_a2 = embla == null ? void 0 : embla.value) == null ? void 0 : _a2.off("select");
|
|
125
|
+
(_b = embla == null ? void 0 : embla.value) == null ? void 0 : _b.destroy();
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
rootEl,
|
|
129
|
+
embla,
|
|
130
|
+
slides,
|
|
131
|
+
currentIndex,
|
|
132
|
+
componentSlotKeys,
|
|
133
|
+
nextIndex,
|
|
134
|
+
previousIndex,
|
|
135
|
+
slideIndicatorCount,
|
|
136
|
+
handleUserInteraction,
|
|
137
|
+
goToSlide,
|
|
138
|
+
reInit,
|
|
139
|
+
reInitVisible,
|
|
140
|
+
onCarouselContainerClick,
|
|
141
|
+
isAriaHidden,
|
|
142
|
+
slideIndicatorListLength
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export {
|
|
147
|
+
carouselUtil
|
|
148
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// utils/printing.js
|
|
2
|
+
function lockPrintSingleEl(domNode) {
|
|
3
|
+
if (typeof window !== "undefined" && domNode) {
|
|
4
|
+
document.body.classList.add("print:tw-invisible", "print:tw-overflow-hidden");
|
|
5
|
+
domNode.classList.add("print:tw-visible", "print:tw-overflow-auto");
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
function unlockPrintSingleEl(domNode) {
|
|
9
|
+
if (typeof window !== "undefined" && domNode) {
|
|
10
|
+
document.body.classList.remove("print:tw-invisible", "print:tw-overflow-hidden");
|
|
11
|
+
domNode.classList.remove("print:tw-visible", "print:tw-overflow-auto");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
lockPrintSingleEl,
|
|
17
|
+
unlockPrintSingleEl
|
|
18
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// utils/Alea.js
|
|
2
|
+
function Mash() {
|
|
3
|
+
let n = 4022871197;
|
|
4
|
+
const mash = function(data) {
|
|
5
|
+
data = data.toString();
|
|
6
|
+
for (let i = 0; i < data.length; i++) {
|
|
7
|
+
n += data.charCodeAt(i);
|
|
8
|
+
let h = 0.02519603282416938 * n;
|
|
9
|
+
n = h >>> 0;
|
|
10
|
+
h -= n;
|
|
11
|
+
h *= n;
|
|
12
|
+
n = h >>> 0;
|
|
13
|
+
h -= n;
|
|
14
|
+
n += h * 4294967296;
|
|
15
|
+
}
|
|
16
|
+
return (n >>> 0) * 23283064365386963e-26;
|
|
17
|
+
};
|
|
18
|
+
mash.version = "Mash 0.9";
|
|
19
|
+
return mash;
|
|
20
|
+
}
|
|
21
|
+
function Alea() {
|
|
22
|
+
return function(args) {
|
|
23
|
+
let s0 = 0;
|
|
24
|
+
let s1 = 0;
|
|
25
|
+
let s2 = 0;
|
|
26
|
+
let c = 1;
|
|
27
|
+
if (args.length === 0) {
|
|
28
|
+
args = [+/* @__PURE__ */ new Date()];
|
|
29
|
+
}
|
|
30
|
+
let mash = Mash();
|
|
31
|
+
s0 = mash(" ");
|
|
32
|
+
s1 = mash(" ");
|
|
33
|
+
s2 = mash(" ");
|
|
34
|
+
for (let i = 0; i < args.length; i++) {
|
|
35
|
+
s0 -= mash(args[i]);
|
|
36
|
+
if (s0 < 0) {
|
|
37
|
+
s0 += 1;
|
|
38
|
+
}
|
|
39
|
+
s1 -= mash(args[i]);
|
|
40
|
+
if (s1 < 0) {
|
|
41
|
+
s1 += 1;
|
|
42
|
+
}
|
|
43
|
+
s2 -= mash(args[i]);
|
|
44
|
+
if (s2 < 0) {
|
|
45
|
+
s2 += 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
mash = null;
|
|
49
|
+
const random = function() {
|
|
50
|
+
const t = 2091639 * s0 + c * 23283064365386963e-26;
|
|
51
|
+
s0 = s1;
|
|
52
|
+
s1 = s2;
|
|
53
|
+
return s2 = t - (c = t | 0);
|
|
54
|
+
};
|
|
55
|
+
random.version = "Alea 0.9";
|
|
56
|
+
random.args = args;
|
|
57
|
+
return random;
|
|
58
|
+
}(Array.prototype.slice.call(arguments));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export {
|
|
62
|
+
Mash,
|
|
63
|
+
Alea
|
|
64
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// utils/scrollLock.js
|
|
2
|
+
function lockScroll() {
|
|
3
|
+
if (typeof window !== "undefined") {
|
|
4
|
+
document.body.style.overflow = "hidden";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
function unlockScroll() {
|
|
8
|
+
if (typeof window !== "undefined") {
|
|
9
|
+
document.body.style.overflow = null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function lockScrollSmallOnly() {
|
|
13
|
+
if (typeof window !== "undefined") {
|
|
14
|
+
document.body.classList.add("tw-overflow-hidden", "md:tw-overflow-auto");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function unlockScrollSmallOnly() {
|
|
18
|
+
if (typeof window !== "undefined") {
|
|
19
|
+
document.body.classList.remove("tw-overflow-hidden", "md:tw-overflow-auto");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
lockScroll,
|
|
25
|
+
unlockScroll,
|
|
26
|
+
lockScrollSmallOnly,
|
|
27
|
+
unlockScrollSmallOnly
|
|
28
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// utils/throttle.js
|
|
2
|
+
function throttle(func, timeFrame) {
|
|
3
|
+
let lastTime = 0;
|
|
4
|
+
return function t(...args) {
|
|
5
|
+
const now = /* @__PURE__ */ new Date();
|
|
6
|
+
if (now - lastTime >= timeFrame) {
|
|
7
|
+
func(...args);
|
|
8
|
+
lastTime = now;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
throttle
|
|
15
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
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
|
+
|
|
108
|
+
export {
|
|
109
|
+
getTreemap
|
|
110
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// utils/imageUtils.js
|
|
2
|
+
function isLegacyPlaceholderAvatar(filename) {
|
|
3
|
+
if (!filename) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
let filenameCleaned = filename.toString();
|
|
7
|
+
if (filenameCleaned.includes(".")) {
|
|
8
|
+
[filenameCleaned] = filenameCleaned.split(".");
|
|
9
|
+
}
|
|
10
|
+
const defaultProfileIds = ["726677", "315726", "4d844ac2c0b77a8a522741b908ea5c32"];
|
|
11
|
+
return defaultProfileIds.includes(filenameCleaned);
|
|
12
|
+
}
|
|
13
|
+
function randomizedUserAvatarClass() {
|
|
14
|
+
const userCardStyleOptions = [
|
|
15
|
+
{ color: "tw-text-action", bg: "tw-bg-brand-100" },
|
|
16
|
+
{ color: "tw-text-black", bg: "tw-bg-brand-100" },
|
|
17
|
+
{ color: "tw-text-white", bg: "tw-bg-action" },
|
|
18
|
+
{ color: "tw-text-brand-100", bg: "tw-bg-action" },
|
|
19
|
+
{ color: "tw-text-primary-inverse", bg: "tw-bg-action" },
|
|
20
|
+
{ color: "tw-text-white", bg: "tw-bg-black" },
|
|
21
|
+
{ color: "tw-text-action", bg: "tw-bg-black" }
|
|
22
|
+
];
|
|
23
|
+
const randomStyle = userCardStyleOptions[Math.floor(Math.random() * userCardStyleOptions.length)];
|
|
24
|
+
return `${randomStyle.color} ${randomStyle.bg}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
isLegacyPlaceholderAvatar,
|
|
29
|
+
randomizedUserAvatarClass
|
|
30
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// utils/touchEvents.js
|
|
2
|
+
function onBodyTouchstart(handler) {
|
|
3
|
+
[...document.body.children].forEach((child) => child.addEventListener("touchstart", handler));
|
|
4
|
+
}
|
|
5
|
+
function offBodyTouchstart(handler) {
|
|
6
|
+
[...document.body.children].forEach((child) => child.removeEventListener("touchstart", handler));
|
|
7
|
+
}
|
|
8
|
+
function isTargetElement(event, elements) {
|
|
9
|
+
const els = Array.isArray(elements) ? elements : [elements];
|
|
10
|
+
for (let i = 0; i < els.length; i += 1) {
|
|
11
|
+
if (els[i] === event.target || els[i].contains(event.target)) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
onBodyTouchstart,
|
|
20
|
+
offBodyTouchstart,
|
|
21
|
+
isTargetElement
|
|
22
|
+
};
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
// utils/mapUtils.js
|
|
2
|
+
function getRandomInRange(from, to, fixed) {
|
|
3
|
+
return (Math.random() * (to - from) + from).toFixed(fixed) * 1;
|
|
4
|
+
}
|
|
5
|
+
var randomCoordinates = Array.from(
|
|
6
|
+
{ length: 20 },
|
|
7
|
+
() => [getRandomInRange(-180, 180, 3), getRandomInRange(-90, 90, 3)]
|
|
8
|
+
);
|
|
9
|
+
var mapColors = [
|
|
10
|
+
100,
|
|
11
|
+
300,
|
|
12
|
+
500,
|
|
13
|
+
650,
|
|
14
|
+
800,
|
|
15
|
+
1e3
|
|
16
|
+
];
|
|
17
|
+
function getCoordinatesBetween(startCoordinates, endCoordinates, numberOfSteps) {
|
|
18
|
+
if (!startCoordinates || !endCoordinates || !numberOfSteps || numberOfSteps < 1 || !Array.isArray(startCoordinates) || !Array.isArray(endCoordinates) || startCoordinates.length !== 2 || endCoordinates.length !== 2) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
const diffX = endCoordinates[0] - startCoordinates[0];
|
|
22
|
+
const diffY = endCoordinates[1] - startCoordinates[1];
|
|
23
|
+
const sfX = diffX / numberOfSteps;
|
|
24
|
+
const sfY = diffY / numberOfSteps;
|
|
25
|
+
let i = 0;
|
|
26
|
+
let j = 0;
|
|
27
|
+
const lineCoordinates = [];
|
|
28
|
+
while (Math.abs(i) < Math.abs(diffX) || Math.abs(j) < Math.abs(diffY)) {
|
|
29
|
+
lineCoordinates.push([startCoordinates[0] + i, startCoordinates[1] + j]);
|
|
30
|
+
if (Math.abs(i) < Math.abs(diffX)) {
|
|
31
|
+
i += sfX;
|
|
32
|
+
}
|
|
33
|
+
if (Math.abs(j) < Math.abs(diffY)) {
|
|
34
|
+
j += sfY;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
lineCoordinates[lineCoordinates.length - 1] = [endCoordinates[0], endCoordinates[1]];
|
|
38
|
+
return lineCoordinates;
|
|
39
|
+
}
|
|
40
|
+
function animateLines(mapInstance, originPoints, endPoint) {
|
|
41
|
+
const speedFactor = 100;
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
mapInstance.addSource("endpoint", {
|
|
44
|
+
type: "geojson",
|
|
45
|
+
data: {
|
|
46
|
+
type: "Point",
|
|
47
|
+
coordinates: [
|
|
48
|
+
endPoint[0],
|
|
49
|
+
endPoint[1]
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const lineFlight = (startCoordinates, endCoordinates, index, lastLine = false) => {
|
|
54
|
+
const lineCoordinates = getCoordinatesBetween(startCoordinates, endCoordinates, speedFactor);
|
|
55
|
+
let animationCounter = 0;
|
|
56
|
+
const geojson = {
|
|
57
|
+
type: "FeatureCollection",
|
|
58
|
+
features: [{
|
|
59
|
+
type: "Feature",
|
|
60
|
+
geometry: {
|
|
61
|
+
type: "LineString",
|
|
62
|
+
coordinates: []
|
|
63
|
+
}
|
|
64
|
+
}]
|
|
65
|
+
};
|
|
66
|
+
mapInstance.addSource(`startPoint${index}`, {
|
|
67
|
+
type: "geojson",
|
|
68
|
+
data: {
|
|
69
|
+
type: "Point",
|
|
70
|
+
coordinates: [
|
|
71
|
+
startCoordinates[0],
|
|
72
|
+
startCoordinates[1]
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
mapInstance.addLayer({
|
|
77
|
+
id: `line-animation${index}`,
|
|
78
|
+
type: "line",
|
|
79
|
+
source: {
|
|
80
|
+
type: "geojson",
|
|
81
|
+
data: geojson
|
|
82
|
+
},
|
|
83
|
+
layout: {
|
|
84
|
+
"line-cap": "round",
|
|
85
|
+
"line-join": "round"
|
|
86
|
+
},
|
|
87
|
+
paint: {
|
|
88
|
+
"line-color": "#277056",
|
|
89
|
+
"line-width": 2
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
const animateLine = () => {
|
|
93
|
+
if (animationCounter < lineCoordinates.length) {
|
|
94
|
+
geojson.features[0].geometry.coordinates.push(lineCoordinates[animationCounter]);
|
|
95
|
+
mapInstance.getSource(`line-animation${index}`).setData(geojson);
|
|
96
|
+
requestAnimationFrame(animateLine);
|
|
97
|
+
animationCounter += 1;
|
|
98
|
+
} else {
|
|
99
|
+
const coord = geojson.features[0].geometry.coordinates;
|
|
100
|
+
coord.shift();
|
|
101
|
+
coord.shift();
|
|
102
|
+
if (coord.length > 0) {
|
|
103
|
+
geojson.features[0].geometry.coordinates = coord;
|
|
104
|
+
mapInstance.getSource(`line-animation${index}`).setData(geojson);
|
|
105
|
+
requestAnimationFrame(animateLine);
|
|
106
|
+
} else {
|
|
107
|
+
mapInstance.removeLayer(`line-animation${index}`);
|
|
108
|
+
mapInstance.removeSource(`line-animation${index}`);
|
|
109
|
+
mapInstance.removeSource(`startPoint${index}`);
|
|
110
|
+
if (lastLine) {
|
|
111
|
+
mapInstance.removeSource("endpoint");
|
|
112
|
+
resolve();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
animateLine();
|
|
118
|
+
};
|
|
119
|
+
originPoints.forEach((coordinate, index) => {
|
|
120
|
+
lineFlight(coordinate, endPoint, index, index === originPoints.length - 1);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function generateMapMarkers(mapInstance, borrowerPoints) {
|
|
125
|
+
const geojson = {
|
|
126
|
+
type: "FeatureCollection"
|
|
127
|
+
};
|
|
128
|
+
geojson.features = borrowerPoints.map((borrower) => ({
|
|
129
|
+
type: "Feature",
|
|
130
|
+
properties: {
|
|
131
|
+
message: "test",
|
|
132
|
+
image: borrower.image,
|
|
133
|
+
iconSize: [80, 80]
|
|
134
|
+
},
|
|
135
|
+
geometry: {
|
|
136
|
+
type: "Point",
|
|
137
|
+
coordinates: borrower.location
|
|
138
|
+
}
|
|
139
|
+
}));
|
|
140
|
+
geojson.features.forEach((marker) => {
|
|
141
|
+
const el = document.createElement("div");
|
|
142
|
+
el.className = "map-marker";
|
|
143
|
+
el.style.backgroundImage = `url(${marker.properties.image})`;
|
|
144
|
+
el.style.width = `${marker.properties.iconSize[0]}px`;
|
|
145
|
+
el.style.height = `${marker.properties.iconSize[1]}px`;
|
|
146
|
+
new maplibregl.Marker({ element: el }).setLngLat(marker.geometry.coordinates).addTo(mapInstance);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
function animationCoordinator(mapInstance, borrowerPoints) {
|
|
150
|
+
return new Promise((resolve) => {
|
|
151
|
+
const destinationPoints = borrowerPoints.map((borrower) => borrower.location);
|
|
152
|
+
const totalNumberOfPoints = destinationPoints.length;
|
|
153
|
+
let currentPointIndex = 0;
|
|
154
|
+
const flyToPoint = (index) => {
|
|
155
|
+
mapInstance.flyTo({
|
|
156
|
+
// These options control the ending camera position: centered at
|
|
157
|
+
// the target, at zoom level 9, and north up.
|
|
158
|
+
center: destinationPoints[index],
|
|
159
|
+
zoom: 4,
|
|
160
|
+
bearing: 0,
|
|
161
|
+
// These options control the flight curve, making it move
|
|
162
|
+
// slowly and zoom out almost completely before starting
|
|
163
|
+
// to pan.
|
|
164
|
+
speed: 0.9,
|
|
165
|
+
// make the flying slow
|
|
166
|
+
curve: 1,
|
|
167
|
+
// change the speed at which it zooms out
|
|
168
|
+
// This can be any easing function: it takes a number between
|
|
169
|
+
// 0 and 1 and returns another number between 0 and 1.
|
|
170
|
+
easing(t) {
|
|
171
|
+
return t;
|
|
172
|
+
},
|
|
173
|
+
// this animation is considered essential with respect to prefers-reduced-motion
|
|
174
|
+
essential: true
|
|
175
|
+
}, { flyEnd: true });
|
|
176
|
+
};
|
|
177
|
+
mapInstance.on("moveend", (event) => {
|
|
178
|
+
if (event.flyEnd === true) {
|
|
179
|
+
animateLines(mapInstance, randomCoordinates, destinationPoints[currentPointIndex]).then(() => {
|
|
180
|
+
if (currentPointIndex < totalNumberOfPoints - 1) {
|
|
181
|
+
currentPointIndex += 1;
|
|
182
|
+
flyToPoint(currentPointIndex);
|
|
183
|
+
} else {
|
|
184
|
+
resolve();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
flyToPoint(currentPointIndex);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
var getLoansIntervals = (min, max, nbIntervals) => {
|
|
193
|
+
const size = Math.floor((max - min) / nbIntervals);
|
|
194
|
+
const result = [];
|
|
195
|
+
if (size <= 0)
|
|
196
|
+
return [[min, max]];
|
|
197
|
+
for (let i = 0; i < nbIntervals; i += 1) {
|
|
198
|
+
let inf = min + i * size;
|
|
199
|
+
let sup = inf + size < max ? inf + size : max;
|
|
200
|
+
if (i > 0) {
|
|
201
|
+
inf += 1 * i;
|
|
202
|
+
sup += 1 * i;
|
|
203
|
+
}
|
|
204
|
+
if (i > 0 && sup > max) {
|
|
205
|
+
sup = max;
|
|
206
|
+
}
|
|
207
|
+
if (i === nbIntervals - 1) {
|
|
208
|
+
if (sup < max || sup > max)
|
|
209
|
+
sup = max;
|
|
210
|
+
}
|
|
211
|
+
result.push([inf, sup]);
|
|
212
|
+
if (sup >= max)
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
return result;
|
|
216
|
+
};
|
|
217
|
+
var getCountryColor = (lenderLoans, countriesData, kvTokensPrimitives) => {
|
|
218
|
+
const loanCountsArray = [];
|
|
219
|
+
countriesData.forEach((country) => {
|
|
220
|
+
loanCountsArray.push(country.value);
|
|
221
|
+
});
|
|
222
|
+
const maxNumLoansToOneCountry = Math.max(...loanCountsArray);
|
|
223
|
+
const intervals = getLoansIntervals(1, maxNumLoansToOneCountry, 6);
|
|
224
|
+
if (intervals.length === 1) {
|
|
225
|
+
const [inf, sup] = intervals[0];
|
|
226
|
+
for (let i = 0; i < sup; i += 1) {
|
|
227
|
+
const loansNumber = i + 1;
|
|
228
|
+
if (lenderLoans && lenderLoans >= loansNumber && lenderLoans < loansNumber + 1) {
|
|
229
|
+
return kvTokensPrimitives.colors.brand[mapColors[i]];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
for (let i = 0; i < intervals.length; i += 1) {
|
|
234
|
+
const [inf, sup] = intervals[i];
|
|
235
|
+
if (lenderLoans && lenderLoans >= inf && lenderLoans <= sup) {
|
|
236
|
+
return kvTokensPrimitives.colors.brand[mapColors[i]];
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return kvTokensPrimitives.colors.gray[300];
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export {
|
|
244
|
+
getCoordinatesBetween,
|
|
245
|
+
generateMapMarkers,
|
|
246
|
+
animationCoordinator,
|
|
247
|
+
getLoansIntervals,
|
|
248
|
+
getCountryColor
|
|
249
|
+
};
|