@kiva/kv-components 3.84.0 → 3.86.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/CHANGELOG.md CHANGED
@@ -3,6 +3,37 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [3.86.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.85.0...@kiva/kv-components@3.86.0) (2024-07-12)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * adding tracking info ([a666513](https://github.com/kiva/kv-ui-elements/commit/a6665130d65f350d119c5e5669b6dd45a7e0ddef))
12
+ * lint ([a197c47](https://github.com/kiva/kv-ui-elements/commit/a197c47ea65c2927d4b60bb9f2533622dbae6f85))
13
+ * missing js docs ([1370e81](https://github.com/kiva/kv-ui-elements/commit/1370e81d8baecf49e6b40b84cad527ea68779763))
14
+ * remove unnecesary important in loan img ([014b48d](https://github.com/kiva/kv-ui-elements/commit/014b48d5506782fdcb6aa102ec3fc4d68f042012))
15
+
16
+
17
+ ### Features
18
+
19
+ * add secondary btn ([579c61a](https://github.com/kiva/kv-ui-elements/commit/579c61ad6d7c0b25cb0a6f7e01fb2da5c58c9c86))
20
+ * create new cart modal component ([3719d2b](https://github.com/kiva/kv-ui-elements/commit/3719d2b3aaa47cb2f9b856c577aa1230619aab11))
21
+
22
+
23
+
24
+
25
+
26
+ # [3.85.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.84.0...@kiva/kv-components@3.85.0) (2024-07-10)
27
+
28
+
29
+ ### Features
30
+
31
+ * carousel controls arrow added for aside version ([#423](https://github.com/kiva/kv-ui-elements/issues/423)) ([f1f8fb3](https://github.com/kiva/kv-ui-elements/commit/f1f8fb337b4a8ffb343e8341ce7a8d932805df1f))
32
+
33
+
34
+
35
+
36
+
6
37
  # [3.84.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.83.2...@kiva/kv-components@3.84.0) (2024-07-08)
7
38
 
8
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kiva/kv-components",
3
- "version": "3.84.0",
3
+ "version": "3.86.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -75,5 +75,5 @@
75
75
  "optional": true
76
76
  }
77
77
  },
78
- "gitHead": "5e75a9b1c10233bd13cd5b897dcbbb2990d03647"
78
+ "gitHead": "f5afa172fdace504add5543a4a312742cfddda61"
79
79
  }
@@ -48,7 +48,7 @@
48
48
  >
49
49
  <kv-material-icon
50
50
  class="tw-w-4"
51
- :icon="mdiChevronLeft"
51
+ :icon="asideControls? mdiArrowLeft : mdiChevronLeft"
52
52
  />
53
53
  <span class="tw-sr-only">Show previous slide</span>
54
54
  </button>
@@ -70,7 +70,7 @@
70
70
  >
71
71
  <kv-material-icon
72
72
  class="tw-w-4"
73
- :icon="mdiChevronRight"
73
+ :icon="asideControls ? mdiArrowRight : mdiChevronRight"
74
74
  />
75
75
  <span class="tw-sr-only">Show next slide</span>
76
76
  </button>
@@ -0,0 +1,357 @@
1
+ <template>
2
+ <transition
3
+ enter-active-class="tw-transition-opacity tw-duration-300"
4
+ leave-active-class="tw-transition-opacity tw-duration-300"
5
+ enter-class="tw-opacity-0"
6
+ enter-to-class="tw-opacity-full"
7
+ leave-class="tw-opacity-full"
8
+ leave-to-class="tw-opacity-0"
9
+ >
10
+ <!-- the screen -->
11
+ <div
12
+ v-show="visible"
13
+ class="screen"
14
+ @click.stop.prevent="onScreenClick"
15
+ >
16
+ <div>
17
+ <div
18
+ class="
19
+ tw-absolute
20
+ tw-inset-0
21
+ md:tw-px-2
22
+ "
23
+ >
24
+ <div
25
+ ref="kvCartModal"
26
+ tabindex="-1"
27
+ data-test="kv-cart-modal"
28
+ class="modal"
29
+ aria-modal="true"
30
+ aria-label="Added to basket"
31
+ @click.stop
32
+ >
33
+ <!-- header -->
34
+ <div
35
+ class="
36
+ tw-flex
37
+ tw-p-2.5 md:tw-px-4 md:tw-pt-4 md:tw-pb-3.5
38
+ "
39
+ >
40
+ <div class="tw-flex tw-flex-grow tw-gap-1 tw-items-center">
41
+ <!-- header -->
42
+ <slot name="header">
43
+ <kv-material-icon
44
+ class="tw-w-4 tw-h-4 tw-text-brand"
45
+ :icon="mdiCheckCircle"
46
+ />
47
+ <h3 class="tw-text-h3 tw-flex-1">
48
+ Added to Basket
49
+ </h3>
50
+ </slot>
51
+ <button
52
+ v-if="!preventClose"
53
+ class="
54
+ tw-grid tw-content-center tw-justify-center
55
+ tw-ml-auto
56
+ tw-w-6 tw-h-6 tw--m-2
57
+ hover:tw-text-action-highlight
58
+ "
59
+ @click.stop="hide('x-button')"
60
+ >
61
+ <kv-material-icon
62
+ class="tw-w-3 tw-h-3"
63
+ :icon="mdiClose"
64
+ />
65
+ <span class="tw-sr-only">Close</span>
66
+ </button>
67
+ </div>
68
+ </div>
69
+
70
+ <!-- body -->
71
+ <div
72
+ id="kvCartModalBody"
73
+ ref="kvCartModalBody"
74
+ class="modal__body"
75
+ >
76
+ <div>
77
+ <kv-borrower-image
78
+ class="tw-rounded loan-image"
79
+ :alt="borrowerImage.alt"
80
+ :aspect-ratio="borrowerImage.aspectRatio"
81
+ :default-image="borrowerImage.defaultImage"
82
+ :hash="borrowerImage.hash"
83
+ :images="borrowerImage.images"
84
+ :photo-path="photoPath"
85
+ />
86
+ </div>
87
+ <div class="tw-flex tw-items-center tw-justify-between tw-w-full">
88
+ <div class="tw-flex tw-flex-col tw-h-full tw-justify-between">
89
+ <p>{{ borrowerName }}</p>
90
+ <p class="tw-p-1 tw-text-center tw-rounded tw-bg-secondary tw-text-h5">
91
+ {{ borrowerCountry }}
92
+ </p>
93
+ </div>
94
+ <p> ${{ amount }}</p>
95
+ </div>
96
+ </div>
97
+
98
+ <!-- controls -->
99
+ <div
100
+ ref="controlsRef"
101
+ class="
102
+ tw-flex-shrink-0 tw-flex tw-justify-end tw-gap-x-2.5
103
+ tw-p-2.5 md:tw-px-4 md:tw-pb-4 tw-flex-col tw-gap-1
104
+ "
105
+ >
106
+ <kv-button
107
+ class="tw-w-full"
108
+ @click="handleClick('view-basket')"
109
+ >
110
+ View basket ({{ basketCount }})
111
+ </kv-button>
112
+ <kv-button
113
+ class="tw-w-full"
114
+ variant="secondary"
115
+ @click="handleClick('help-another-person')"
116
+ >
117
+ Help another person
118
+ </kv-button>
119
+ </div>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ </transition>
125
+ </template>
126
+
127
+ <script>
128
+ import {
129
+ ref,
130
+ toRefs,
131
+ computed,
132
+ nextTick,
133
+ watch,
134
+ onBeforeUnmount,
135
+ onMounted,
136
+ } from 'vue-demi';
137
+ import { mdiClose, mdiCheckCircle } from '@mdi/js';
138
+ import { useFocusTrap } from '@vueuse/integrations/useFocusTrap';
139
+ import { hideOthers as makePageInert } from 'aria-hidden';
140
+ import { lockScroll, unlockScroll } from '../utils/scrollLock';
141
+ import { lockPrintSingleEl, unlockPrintSingleEl } from '../utils/printing';
142
+ import KvButton from './KvButton.vue';
143
+ import KvMaterialIcon from './KvMaterialIcon.vue';
144
+ import KvBorrowerImage from './KvBorrowerImage.vue';
145
+
146
+ /**
147
+ * Based on KvLightbox functionality
148
+ * */
149
+
150
+ export default {
151
+ components: {
152
+ KvMaterialIcon,
153
+ KvButton,
154
+ KvBorrowerImage,
155
+ },
156
+ props: {
157
+ /**
158
+ * Whether the dialog is open or not
159
+ * */
160
+ visible: {
161
+ type: Boolean,
162
+ default: false,
163
+ },
164
+ /**
165
+ * The dialog has no close X button, clicking the screen does not close,
166
+ * pressing ESC does not close.
167
+ * */
168
+ preventClose: {
169
+ type: Boolean,
170
+ default: false,
171
+ },
172
+ /**
173
+ * The number of loans in the basket
174
+ * */
175
+ basketCount: {
176
+ type: Number,
177
+ default: 0,
178
+ },
179
+ /**
180
+ * The loan added to the basket
181
+ * */
182
+ addedLoan: {
183
+ type: Object,
184
+ default: () => ({}),
185
+ },
186
+ /**
187
+ * The photo path for the borrower image
188
+ * */
189
+ photoPath: {
190
+ type: String,
191
+ default: '',
192
+ },
193
+ },
194
+ emits: [
195
+ 'cart-modal-closed',
196
+ ],
197
+ setup(props, { emit }) {
198
+ const {
199
+ visible,
200
+ preventClose,
201
+ addedLoan,
202
+ } = toRefs(props);
203
+
204
+ const kvCartModal = ref(null);
205
+ const kvCartModalBody = ref(null);
206
+ const controlsRef = ref(null);
207
+
208
+ const trapElements = computed(() => [
209
+ kvCartModal.value, // This cart modal
210
+ ]);
211
+ const {
212
+ activate: activateFocusTrap,
213
+ deactivate: deactivateFocusTrap,
214
+ } = useFocusTrap(trapElements, {
215
+ allowOutsideClick: true, // allow clicking outside the cart modal to close it
216
+ });
217
+
218
+ let makePageInertCallback = null;
219
+ let onKeyUp = null;
220
+
221
+ const hide = (closedBy = '') => {
222
+ // scroll any content inside the cart modal back to top
223
+ if (kvCartModal.value && kvCartModalBody.value) {
224
+ deactivateFocusTrap();
225
+ kvCartModalBody.value.scrollTop = 0;
226
+ unlockPrintSingleEl(kvCartModalBody.value);
227
+ }
228
+ unlockScroll();
229
+ if (makePageInertCallback) {
230
+ makePageInertCallback();
231
+ makePageInertCallback = null;
232
+ }
233
+ document.removeEventListener('keyup', onKeyUp);
234
+
235
+ /**
236
+ * Triggered when the cart modal is closed
237
+ * @event cart-modal-closed
238
+ * @type {Event}
239
+ */
240
+ emit('cart-modal-closed', { type: closedBy });
241
+ };
242
+
243
+ onKeyUp = (e) => {
244
+ if (!!e && e.key === 'Escape' && !preventClose.value) {
245
+ hide();
246
+ }
247
+ };
248
+
249
+ const onScreenClick = () => {
250
+ if (!preventClose.value) {
251
+ hide('background');
252
+ }
253
+ };
254
+
255
+ const show = () => {
256
+ if (visible.value) {
257
+ document.addEventListener('keyup', onKeyUp);
258
+
259
+ nextTick(() => {
260
+ if (kvCartModal.value && kvCartModalBody.value) {
261
+ activateFocusTrap();
262
+ makePageInertCallback = makePageInert(kvCartModal.value);
263
+ lockPrintSingleEl(kvCartModalBody.value);
264
+ }
265
+ lockScroll();
266
+ });
267
+ }
268
+ };
269
+
270
+ const borrowerName = computed(() => {
271
+ return addedLoan.value?.name ?? '';
272
+ });
273
+ const borrowerImage = computed(() => {
274
+ return {
275
+ alt: `Photo of ${borrowerName.value}`,
276
+ aspectRatio: 1,
277
+ defaultImage: { width: 300 },
278
+ hash: addedLoan.value.imageHash,
279
+ images: [
280
+ {
281
+ width: 300,
282
+ },
283
+ ],
284
+ };
285
+ });
286
+ const borrowerCountry = computed(() => {
287
+ return addedLoan.value.country ?? '';
288
+ });
289
+
290
+ const amount = computed(() => {
291
+ return addedLoan.value.amount ?? '';
292
+ });
293
+
294
+ const handleClick = (cta) => {
295
+ hide(cta);
296
+ };
297
+
298
+ watch(visible, () => {
299
+ if (visible.value) {
300
+ show();
301
+ } else {
302
+ hide();
303
+ }
304
+ });
305
+
306
+ onMounted(() => {
307
+ if (visible.value) {
308
+ show();
309
+ setTimeout(() => {
310
+ // Automatically close the cart modal after 10 seconds
311
+ emit('cart-modal-closed', { type: 'time' });
312
+ }, 10000);
313
+ }
314
+ });
315
+
316
+ onBeforeUnmount(() => hide());
317
+
318
+ return {
319
+ mdiClose,
320
+ mdiCheckCircle,
321
+ onKeyUp,
322
+ onScreenClick,
323
+ hide,
324
+ show,
325
+ controlsRef,
326
+
327
+ handleClick,
328
+ borrowerName,
329
+ borrowerImage,
330
+ borrowerCountry,
331
+ amount,
332
+ };
333
+ },
334
+ };
335
+ </script>
336
+
337
+ <style lang="postcss" scoped>
338
+ .screen {
339
+ @apply tw-z-modal tw-absolute tw-inset-0;
340
+ background-color: rgb(0, 0, 0, 0.2);
341
+ }
342
+
343
+ .modal {
344
+ @apply tw-bg-primary md:tw-absolute md:tw-right-0 tw-w-full md:tw-w-auto tw-rounded-b;
345
+ max-width: 30rem;
346
+ max-height: 90%;
347
+ }
348
+
349
+ .modal__body {
350
+ @apply tw-flex tw-gap-2 tw-px-2.5 md:tw-px-4;
351
+ height: 3.75rem;
352
+ }
353
+
354
+ .loan-image {
355
+ width: 3.75rem;
356
+ }
357
+ </style>
@@ -0,0 +1,52 @@
1
+ import KvCartModal from '../KvCartModal.vue';
2
+ import KvButton from '../KvButton.vue';
3
+
4
+ export default {
5
+ title: 'KvCartModal',
6
+ component: KvCartModal,
7
+ parameters: {
8
+ layout: 'fullscreen',
9
+ },
10
+ args: {
11
+ visible: true,
12
+ title: '',
13
+ preventClose: false,
14
+ addedLoan: {
15
+ name: 'Test Loan',
16
+ amount: 100,
17
+ country: 'Kenya',
18
+ imageHash: '9673d0722a7675b9b8d11f90849d9b44',
19
+ },
20
+ photoPath: 'https://www-kiva-org.freetls.fastly.net/img/',
21
+ },
22
+ };
23
+
24
+ const DefaultTemplate = (args, { argTypes }) => ({
25
+ props: Object.keys(argTypes),
26
+ components: { KvCartModal, KvButton },
27
+ template: `
28
+ <div>
29
+ <kv-button @click="isVisible = true;">Show cart modal</kv-button>
30
+ <p>The lightbox is visible: {{isVisible}}</p>
31
+
32
+ <kv-cart-modal
33
+ :visible="isVisible"
34
+ :prevent-close="preventClose"
35
+ :added-loan="addedLoan"
36
+ :photo-path="photoPath"
37
+ @cart-modal-closed="isVisible = false"
38
+ >
39
+ </kv-cart-modal>
40
+ </div>
41
+ `,
42
+ data() {
43
+ return {
44
+ isVisible: args.visible,
45
+ };
46
+ },
47
+ });
48
+
49
+ export const Lightbox = DefaultTemplate.bind({});
50
+ Lightbox.args = {
51
+ title: 'Added to Basket',
52
+ };