@kiva/kv-components 3.107.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.
Files changed (177) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/components/.storybook/main.js +85 -0
  3. package/dist/components/.storybook/package.json +3 -0
  4. package/dist/components/.storybook/preview.js +61 -0
  5. package/dist/components/.storybook/tailwind.css +5 -0
  6. package/dist/components/KvAccordionItem.vue +130 -0
  7. package/dist/components/KvActivityRow.vue +33 -0
  8. package/dist/components/KvBorrowerImage.vue +179 -0
  9. package/dist/components/KvButton.vue +287 -0
  10. package/dist/components/KvCarousel.vue +297 -0
  11. package/dist/components/KvCartModal.vue +365 -0
  12. package/dist/components/KvCheckbox.vue +203 -0
  13. package/dist/components/KvChip.vue +54 -0
  14. package/dist/components/KvClassicLoanCard.vue +527 -0
  15. package/dist/components/KvCommentsAdd.vue +135 -0
  16. package/dist/components/KvCommentsContainer.vue +84 -0
  17. package/dist/components/KvCommentsHeartButton.vue +70 -0
  18. package/dist/components/KvCommentsList.vue +68 -0
  19. package/dist/components/KvCommentsListItem.vue +241 -0
  20. package/dist/components/KvCommentsReplyButton.vue +52 -0
  21. package/dist/components/KvContentfulImg.vue +273 -0
  22. package/dist/components/KvCountdownTimer.vue +59 -0
  23. package/dist/components/KvExpandable.vue +84 -0
  24. package/dist/components/KvExpandableQuestion.vue +120 -0
  25. package/dist/components/KvFlag.vue +120 -0
  26. package/dist/components/KvGrid.vue +28 -0
  27. package/dist/components/KvImpactDashboardHeader.vue +40 -0
  28. package/dist/components/KvInlineActivityCard.vue +55 -0
  29. package/dist/components/KvInlineActivityFeed.vue +38 -0
  30. package/dist/components/KvIntroductionLoanCard.vue +446 -0
  31. package/dist/components/KvLendAmountButton.vue +65 -0
  32. package/dist/components/KvLendCta.vue +451 -0
  33. package/dist/components/KvLightbox.vue +334 -0
  34. package/dist/components/KvLineGraph.vue +128 -0
  35. package/dist/components/KvLoadingPlaceholder.vue +38 -0
  36. package/dist/components/KvLoadingSpinner.vue +81 -0
  37. package/dist/components/KvLoanActivities.vue +268 -0
  38. package/dist/components/KvLoanBookmark.vue +39 -0
  39. package/dist/components/KvLoanCallouts.vue +53 -0
  40. package/dist/components/KvLoanProgressGroup.vue +76 -0
  41. package/dist/components/KvLoanTag.vue +88 -0
  42. package/dist/components/KvLoanTeamPick.vue +44 -0
  43. package/dist/components/KvLoanUse.vue +92 -0
  44. package/dist/components/KvMap.vue +599 -0
  45. package/dist/components/KvMaterialIcon.vue +47 -0
  46. package/dist/components/KvPageContainer.vue +15 -0
  47. package/dist/components/KvPagination.vue +198 -0
  48. package/dist/components/KvPieChart.vue +257 -0
  49. package/dist/components/KvPopper.vue +178 -0
  50. package/dist/components/KvProgressBar.vue +149 -0
  51. package/dist/components/KvRadio.vue +198 -0
  52. package/dist/components/KvSelect.vue +114 -0
  53. package/dist/components/KvSideSheet.vue +134 -0
  54. package/dist/components/KvSwitch.vue +143 -0
  55. package/dist/components/KvTab.vue +90 -0
  56. package/dist/components/KvTabPanel.vue +64 -0
  57. package/dist/components/KvTabs.vue +182 -0
  58. package/dist/components/KvTextInput.vue +247 -0
  59. package/dist/components/KvTextLink.vue +138 -0
  60. package/dist/components/KvThemeProvider.vue +122 -0
  61. package/dist/components/KvToast.vue +221 -0
  62. package/dist/components/KvTooltip.vue +168 -0
  63. package/dist/components/KvTreeMapChart.vue +229 -0
  64. package/dist/components/KvUserAvatar.vue +132 -0
  65. package/dist/components/KvVerticalCarousel.vue +156 -0
  66. package/dist/components/KvVotingCard.vue +160 -0
  67. package/dist/components/KvVotingCardV2.vue +154 -0
  68. package/dist/components/KvWideLoanCard.vue +432 -0
  69. package/dist/components/stories/Forms.stories.js +62 -0
  70. package/dist/components/stories/KvAccordionItem.stories.js +24 -0
  71. package/dist/components/stories/KvActivityRow.stories.js +25 -0
  72. package/dist/components/stories/KvBorrowerImage.stories.js +68 -0
  73. package/dist/components/stories/KvButton.stories.js +144 -0
  74. package/dist/components/stories/KvCarousel.stories.js +426 -0
  75. package/dist/components/stories/KvCartModal.stories.js +54 -0
  76. package/dist/components/stories/KvCheckbox.stories.js +163 -0
  77. package/dist/components/stories/KvChip.stories.js +43 -0
  78. package/dist/components/stories/KvClassicLoanCard.stories.js +480 -0
  79. package/dist/components/stories/KvCommentsAdd.stories.js +32 -0
  80. package/dist/components/stories/KvCommentsContainer.stories.js +42 -0
  81. package/dist/components/stories/KvCommentsHeartButton.stories.js +25 -0
  82. package/dist/components/stories/KvCommentsList.stories.js +39 -0
  83. package/dist/components/stories/KvCommentsListItem.stories.js +45 -0
  84. package/dist/components/stories/KvCommentsReplyButton.stories.js +21 -0
  85. package/dist/components/stories/KvContentfulImg.stories.js +196 -0
  86. package/dist/components/stories/KvCountdownTimer.stories.js +30 -0
  87. package/dist/components/stories/KvExpandableQuestion.stories.js +129 -0
  88. package/dist/components/stories/KvFlag.stories.js +36 -0
  89. package/dist/components/stories/KvGrid.stories.js +97 -0
  90. package/dist/components/stories/KvImpactDashboardHeader.stories.js +22 -0
  91. package/dist/components/stories/KvInlineActivityCard.stories.js +69 -0
  92. package/dist/components/stories/KvInlineActivityFeed.stories.js +76 -0
  93. package/dist/components/stories/KvIntroductionLoanCard.stories.js +208 -0
  94. package/dist/components/stories/KvLendAmountButton.stories.js +31 -0
  95. package/dist/components/stories/KvLendCta.stories.js +177 -0
  96. package/dist/components/stories/KvLightbox.stories.js +304 -0
  97. package/dist/components/stories/KvLineGraph.stories.js +52 -0
  98. package/dist/components/stories/KvLoadingPlaceholder.stories.js +17 -0
  99. package/dist/components/stories/KvLoadingSpinner.stories.js +52 -0
  100. package/dist/components/stories/KvLoanActivities.stories.js +104 -0
  101. package/dist/components/stories/KvLoanBookmark.stories.js +22 -0
  102. package/dist/components/stories/KvLoanCallouts.stories.js +22 -0
  103. package/dist/components/stories/KvLoanProgressGroup.stories.js +29 -0
  104. package/dist/components/stories/KvLoanTag.stories.js +61 -0
  105. package/dist/components/stories/KvLoanTeamPick.stories.js +20 -0
  106. package/dist/components/stories/KvLoanUse.stories.js +60 -0
  107. package/dist/components/stories/KvMap.stories.js +121 -0
  108. package/dist/components/stories/KvMaterialIcon.stories.js +201 -0
  109. package/dist/components/stories/KvPageContainer.stories.js +50 -0
  110. package/dist/components/stories/KvPagination.stories.js +70 -0
  111. package/dist/components/stories/KvPieChart.stories.js +47 -0
  112. package/dist/components/stories/KvProgressBar.stories.js +53 -0
  113. package/dist/components/stories/KvRadio.stories.js +140 -0
  114. package/dist/components/stories/KvSelect.stories.js +125 -0
  115. package/dist/components/stories/KvSideSheet.stories.js +50 -0
  116. package/dist/components/stories/KvSwitch.stories.js +66 -0
  117. package/dist/components/stories/KvTabs.stories.js +106 -0
  118. package/dist/components/stories/KvTextInput.stories.js +194 -0
  119. package/dist/components/stories/KvTextLink.stories.js +55 -0
  120. package/dist/components/stories/KvThemeProvider.stories.js +178 -0
  121. package/dist/components/stories/KvToast.stories.js +117 -0
  122. package/dist/components/stories/KvTooltip.stories.js +26 -0
  123. package/dist/components/stories/KvTreeMapChart.stories.js +42 -0
  124. package/dist/components/stories/KvUserAvatar.stories.js +47 -0
  125. package/dist/components/stories/KvVerticalCarousel.stories.js +168 -0
  126. package/dist/components/stories/KvVotingCard.stories.js +33 -0
  127. package/dist/components/stories/KvVotingCardV2.stories.js +89 -0
  128. package/dist/components/stories/KvWideLoanCard.stories.js +292 -0
  129. package/dist/components/stories/StyleguidePrimitives.stories.js +499 -0
  130. package/dist/components/stories/StyleguideProse.stories.js +215 -0
  131. package/dist/data/countries-borders.json +1 -0
  132. package/dist/data/ne_110m_admin_0_countries.json +1 -0
  133. package/dist/utils/Alea.js +9 -0
  134. package/dist/utils/attrs.js +7 -0
  135. package/dist/utils/carousels.js +8 -0
  136. package/dist/{attrs.js → utils/chunk-3HK4G4NT.js} +1 -0
  137. package/dist/{loanCard.js → utils/chunk-55HF2ORX.js} +1 -0
  138. package/dist/{expander.js → utils/chunk-AY3PR5S4.js} +3 -2
  139. package/dist/{carousels.js → utils/chunk-AZPWOFD5.js} +1 -0
  140. package/dist/{printing.js → utils/chunk-B5J5WLAH.js} +1 -0
  141. package/dist/{Alea.js → utils/chunk-GPSH6OPA.js} +2 -1
  142. package/dist/{scrollLock.js → utils/chunk-HIY5IW65.js} +2 -1
  143. package/dist/{treemap.js → utils/chunk-MSMZIN54.js} +1 -0
  144. package/dist/{imageUtils.js → utils/chunk-OXJCCNNW.js} +1 -0
  145. package/dist/{touchEvents.js → utils/chunk-S3MABILA.js} +3 -2
  146. package/dist/{mapUtils.js → utils/chunk-VIGEMAKO.js} +5 -4
  147. package/dist/utils/chunk-YCNMJ4YV.js +37 -0
  148. package/dist/{loanUtils.js → utils/chunk-YFEC5ODJ.js} +7 -6
  149. package/dist/utils/expander.js +9 -0
  150. package/dist/utils/imageUtils.js +9 -0
  151. package/dist/utils/index.cjs +1118 -0
  152. package/dist/utils/index.js +166 -0
  153. package/dist/utils/loanCard.js +9 -0
  154. package/dist/utils/loanUtils.js +23 -0
  155. package/dist/utils/mapUtils.js +15 -0
  156. package/dist/utils/printing.js +9 -0
  157. package/dist/utils/scrollLock.js +13 -0
  158. package/dist/{throttle.js → utils/throttle.js} +1 -0
  159. package/dist/utils/touchEvents.js +11 -0
  160. package/dist/utils/treemap.js +7 -0
  161. package/package.json +7 -7
  162. package/utils/index.js +14 -0
  163. package/index.js +0 -3
  164. /package/dist/{Alea.cjs → utils/Alea.cjs} +0 -0
  165. /package/dist/{attrs.cjs → utils/attrs.cjs} +0 -0
  166. /package/dist/{carousels.cjs → utils/carousels.cjs} +0 -0
  167. /package/dist/{chunk-HV3AUBFT.js → utils/chunk-HV3AUBFT.js} +0 -0
  168. /package/dist/{expander.cjs → utils/expander.cjs} +0 -0
  169. /package/dist/{imageUtils.cjs → utils/imageUtils.cjs} +0 -0
  170. /package/dist/{loanCard.cjs → utils/loanCard.cjs} +0 -0
  171. /package/dist/{loanUtils.cjs → utils/loanUtils.cjs} +0 -0
  172. /package/dist/{mapUtils.cjs → utils/mapUtils.cjs} +0 -0
  173. /package/dist/{printing.cjs → utils/printing.cjs} +0 -0
  174. /package/dist/{scrollLock.cjs → utils/scrollLock.cjs} +0 -0
  175. /package/dist/{throttle.cjs → utils/throttle.cjs} +0 -0
  176. /package/dist/{touchEvents.cjs → utils/touchEvents.cjs} +0 -0
  177. /package/dist/{treemap.cjs → utils/treemap.cjs} +0 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
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.107.1](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.107.0...@kiva/kv-components@3.107.1) (2024-11-05)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * add components to dist folder as well ([0b20c69](https://github.com/kiva/kv-ui-elements/commit/0b20c69ed132a9a46da040523c559a6d900143d1))
12
+
13
+
14
+
15
+
16
+
6
17
  # [3.107.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.106.0...@kiva/kv-components@3.107.0) (2024-11-05)
7
18
 
8
19
 
@@ -0,0 +1,85 @@
1
+ const path = require('path');
2
+
3
+ const config = {
4
+ stories: [
5
+ '../stories/Styleguide.stories.js', // show the base styleguide first
6
+ '../stories/**/*.stories.mdx',
7
+ '../stories/**/*.stories.@(js|jsx|ts|tsx)'
8
+ ],
9
+
10
+ addons: [
11
+ "@storybook/addon-links",
12
+ "@storybook/addon-essentials",
13
+ "@storybook/addon-a11y",
14
+ "@storybook/addon-storysource",
15
+ {
16
+ name: '@storybook/addon-styling-webpack',
17
+ options: {
18
+ rules: [
19
+ // Replaces existing CSS rules to support PostCSS
20
+ {
21
+ test: /\.css$/,
22
+ use: [
23
+ 'style-loader',
24
+ {
25
+ loader: 'css-loader',
26
+ options: { importLoaders: 1 }
27
+ },
28
+ {
29
+ // Gets options from `postcss.config.js` in your project root
30
+ loader: 'postcss-loader',
31
+ options: { implementation: require.resolve('postcss') }
32
+ }
33
+ ],
34
+ }
35
+ ]
36
+ }
37
+ }
38
+ ],
39
+
40
+ webpackFinal: async (config) => {
41
+ config.module.rules.push({
42
+ test: /\.mjs$/,
43
+ include: /node_modules/,
44
+ type: 'javascript/auto'
45
+ });
46
+ config.module.rules.push({
47
+ test: /\.postcss$/,
48
+ use: [
49
+ 'style-loader',
50
+ {
51
+ loader: 'css-loader',
52
+ options: { importLoaders: 1, sourceMap: false },
53
+ },
54
+ {
55
+ loader: 'postcss-loader',
56
+ options: {
57
+ postcssOptions: {
58
+ plugins: [
59
+ require('tailwindcss'),
60
+ require('autoprefixer'),
61
+ ]
62
+ }
63
+ },
64
+ }
65
+ ]
66
+ });
67
+ config.resolve.alias = {
68
+ ...config.resolve.alias,
69
+ '~/node_modules': path.resolve(__dirname, '../../../../node_modules/'),
70
+ };
71
+ return config;
72
+ },
73
+
74
+ framework: {
75
+ name: "@storybook/vue-webpack5",
76
+ options: {}
77
+ },
78
+
79
+ docs: {
80
+ autodocs: true,
81
+ defaultName: 'Kv Components',
82
+ }
83
+ }
84
+
85
+ export default config;
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,61 @@
1
+ import './tailwind.css';
2
+ import { addons } from '@storybook/preview-api';
3
+ import KvThemeProvider from '../KvThemeProvider.vue';
4
+ import { defaultTheme, darkTheme } from '@kiva/kv-tokens/configs/kivaColors.cjs';
5
+ import Vue from 'vue';
6
+ import VueCompositionApi from '@vue/composition-api';
7
+ import VueRouter from 'vue-router';
8
+
9
+ // Add vue composition api
10
+ Vue.use(VueCompositionApi);
11
+
12
+ Vue.use(VueRouter);
13
+
14
+ const parameters = {
15
+ actions: { argTypesRegex: "^on[A-Z].*" },
16
+ controls: {
17
+ matchers: {
18
+ color: /(background|color)$/i,
19
+ date: /Date$/,
20
+ },
21
+ },
22
+ options: {
23
+ storySort: {
24
+ order: ['Base Styling', '*'],
25
+ },
26
+ },
27
+ }
28
+
29
+ // Listen for events from the dark mode plugin
30
+ // https://github.com/hipstersmoothie/storybook-dark-mode#events
31
+ const channel = addons.getChannel();
32
+
33
+ // Wrap all stories with the kv-theme-provider component
34
+ const decorators = [(story) => ({
35
+ components: { story, KvThemeProvider },
36
+ template: '<kv-theme-provider :theme="theme"><story /></kv-theme-provider>',
37
+ data() {
38
+ return {
39
+ theme: {}
40
+ }
41
+ },
42
+ methods: {
43
+ setTheme(darkMode) {
44
+ darkMode ? this.theme = darkTheme : this.theme = defaultTheme
45
+ }
46
+ },
47
+ mounted() {
48
+ channel.on('DARK_MODE', this.setTheme);
49
+ },
50
+ destroyed() {
51
+ channel.off('DARK_MODE', this.setTheme);
52
+ },
53
+ router: new VueRouter(),
54
+ })];
55
+
56
+ const preview = {
57
+ parameters,
58
+ decorators,
59
+ };
60
+
61
+ export default preview;
@@ -0,0 +1,5 @@
1
+ @import url('https://use.typekit.net/pmj7shs.css');
2
+
3
+ @tailwind base;
4
+ @tailwind components;
5
+ @tailwind utilities;
@@ -0,0 +1,130 @@
1
+ <template>
2
+ <div
3
+ class="tw-border-b tw-border-tertiary tw-relative last:tw-border-b-0"
4
+ >
5
+ <button
6
+ class="tw-w-full tw-flex tw-justify-between tw-items-center tw-py-1.5 tw-px-0
7
+ tw-text-left disabled:tw-cursor-not-allowed disabled:tw-opacity-low
8
+ hover:tw-text-action-highlight focus:tw-text-action-highlight"
9
+ :disabled="disabled"
10
+ :aria-controls="`kv-accordion-${id}`"
11
+ :aria-expanded="isOpen ? 'true' : 'false'"
12
+ @click.prevent="toggle"
13
+ >
14
+ <span class="tw-flex-1">
15
+ <slot name="header"></slot>
16
+ </span>
17
+ <kv-material-icon
18
+ class="tw-h-3 tw-w-3 tw-transition tw-transform tw-duration-500 tw-ease"
19
+ :class="{ 'tw-rotate-180' : isOpen }"
20
+ :icon="mdiChevronDown"
21
+ />
22
+ </button>
23
+ <kv-expandable>
24
+ <div
25
+ v-show="isOpen"
26
+ :id="`kv-accordion-${id}`"
27
+ :aria-hidden="isOpen ? 'false' : 'true'"
28
+ >
29
+ <slot></slot>
30
+ </div>
31
+ </kv-expandable>
32
+ </div>
33
+ </template>
34
+
35
+ <script>
36
+ // Accordion a11y resources
37
+ // https://www.w3.org/TR/wai-aria-practices-1.1/examples/accordion/accordion.html
38
+ // https://www.aditus.io/patterns/accordion/
39
+ // Future improvement
40
+ // Currently the slot content is inside the button, which means h2, h3 etc. won't be
41
+ // navigatable via headings. See https://daverupert.com/2019/12/why-details-is-not-an-accordion/
42
+ // h2 + button // ✅ H1 will show up when navigating by headings
43
+ // button + h2 // ❌ H1 will not show up when navigating by headings
44
+ // Perhaps we could do some magic DOM reordering via this.$slots.header or
45
+ // pass a prop like 'tag' that sets the parent node of the button. <accordion tag="h3">...
46
+
47
+ import {
48
+ ref,
49
+ toRefs,
50
+ } from 'vue-demi';
51
+ import { mdiChevronDown } from '@mdi/js';
52
+ import KvExpandable from './KvExpandable.vue';
53
+ import KvMaterialIcon from './KvMaterialIcon.vue';
54
+
55
+ export default {
56
+ components: {
57
+ KvMaterialIcon,
58
+ KvExpandable,
59
+ },
60
+ props: {
61
+ /**
62
+ * Unique id. used for a11y
63
+ * */
64
+ id: {
65
+ type: String,
66
+ required: true,
67
+ validator: (v) => v.length > 0 && !/\s/g.test(v), // must be a valid html5 id
68
+ },
69
+ /**
70
+ * Whether the body is shown initially
71
+ * */
72
+ open: {
73
+ type: Boolean,
74
+ default: false,
75
+ },
76
+ /**
77
+ * Whether the accordion can be toggled
78
+ * */
79
+ disabled: {
80
+ type: Boolean,
81
+ default: false,
82
+ },
83
+ },
84
+ emits: [
85
+ 'toggle',
86
+ ],
87
+ setup(props, { emit }) {
88
+ const {
89
+ open,
90
+ disabled,
91
+ } = toRefs(props);
92
+
93
+ const isOpen = ref(open.value);
94
+
95
+ const toggle = () => {
96
+ if (!disabled.value) {
97
+ isOpen.value = !isOpen.value;
98
+ /**
99
+ * Fires when the accordion has been toggled.
100
+ * Contains an object with a boolean 'open' property of the current open
101
+ * state of the accordion
102
+ * @event toggle
103
+ * @type {Event}
104
+ */
105
+ emit('toggle', { open: isOpen.value });
106
+ }
107
+ };
108
+
109
+ const expand = () => {
110
+ if (!disabled.value) {
111
+ isOpen.value = true;
112
+ }
113
+ };
114
+
115
+ const collapse = () => {
116
+ if (!disabled.value) {
117
+ isOpen.value = false;
118
+ }
119
+ };
120
+
121
+ return {
122
+ collapse,
123
+ expand,
124
+ isOpen,
125
+ mdiChevronDown,
126
+ toggle,
127
+ };
128
+ },
129
+ };
130
+ </script>
@@ -0,0 +1,33 @@
1
+ <template>
2
+ <div class="tw-flex tw-gap-x-1 tw-items-center">
3
+ <div>
4
+ <KvUserAvatar
5
+ :lender-name="activity.lenderName"
6
+ :lender-image-url="activity.lenderImage"
7
+ :is-small="true"
8
+ />
9
+ </div>
10
+ <div>
11
+ <!-- eslint-disable vue/no-v-html -->
12
+ <p v-html="activity.text"></p>
13
+ <!-- eslint-enable -->
14
+ </div>
15
+ </div>
16
+ </template>
17
+
18
+ <script>
19
+ import KvUserAvatar from './KvUserAvatar.vue';
20
+
21
+ export default {
22
+ name: 'KvActivityRow',
23
+ components: {
24
+ KvUserAvatar,
25
+ },
26
+ props: {
27
+ activity: {
28
+ type: Object,
29
+ required: true,
30
+ },
31
+ },
32
+ };
33
+ </script>
@@ -0,0 +1,179 @@
1
+ <template>
2
+ <picture
3
+ class="
4
+ tw-inline-block
5
+ tw-relative
6
+ tw-overflow-hidden
7
+ tw-w-full
8
+ tw-bg-black
9
+ "
10
+ :style="`padding-bottom: ${aspectRatio * 100}%;`"
11
+ >
12
+ <source
13
+ :srcset="srcset"
14
+ :sizes="sizes"
15
+ >
16
+ <img
17
+ v-if="hash"
18
+ class="
19
+ tw-absolute
20
+ tw-w-full
21
+ tw-h-full
22
+ tw-object-contain
23
+ "
24
+ :src="defaultUrl"
25
+ :alt="alt"
26
+ loading="lazy"
27
+ >
28
+ </picture>
29
+ </template>
30
+
31
+ <script>
32
+ export default {
33
+ name: 'KvBorrowerImage',
34
+ props: {
35
+ /**
36
+ * String to use as the alternative of this image for screen readers.
37
+ */
38
+ alt: {
39
+ type: String,
40
+ required: true,
41
+ },
42
+ /**
43
+ * Number to use as the aspect ratio for this image. Defined as height / width.
44
+ */
45
+ aspectRatio: {
46
+ type: Number,
47
+ default: 1,
48
+ },
49
+ /**
50
+ * Size properties of the default image to use as a fallback.
51
+ * Sample object:
52
+ * {
53
+ width: 320,
54
+ faceZoom: 50, // optional
55
+ }
56
+ */
57
+ defaultImage: {
58
+ type: Object,
59
+ required: true,
60
+ },
61
+ /**
62
+ * String of the hash of the image, used to build the image urls.
63
+ */
64
+ hash: {
65
+ type: String,
66
+ required: true,
67
+ },
68
+ /**
69
+ * Array of image objects containing their size and their intended viewport display width.
70
+ * Sample image object:
71
+ * {
72
+ width: 280, // width of the image at 1x
73
+ viewSize: 320, // viewport width at which this size should be displayed
74
+ faceZoom: 50, // optional
75
+ }
76
+ */
77
+ images: {
78
+ type: Array,
79
+ default: () => [],
80
+ },
81
+ /**
82
+ * The base path to source the image
83
+ */
84
+ photoPath: {
85
+ type: String,
86
+ required: true,
87
+ },
88
+ },
89
+ computed: {
90
+ // Get the full url for the fallback image
91
+ defaultUrl() {
92
+ if (!this.hash) {
93
+ return '';
94
+ }
95
+ return this.getImgUrl({
96
+ ...this.defaultImage,
97
+ height: this.defaultImage.width * this.aspectRatio,
98
+ });
99
+ },
100
+ // Get the 'sizes' string for the source element
101
+ sizes() {
102
+ if (!this.hash) {
103
+ return '';
104
+ }
105
+ return this.images.map(({ width, viewSize }) => {
106
+ if (viewSize) {
107
+ return `(min-width: ${viewSize}px) ${width}px`;
108
+ }
109
+ return `${width}px`;
110
+ }).join(', ');
111
+ },
112
+ // Get the 'srcset' string for the source element
113
+ srcset() {
114
+ if (!this.hash) {
115
+ return '';
116
+ }
117
+ return this.images.map(({ width, faceZoom }) => {
118
+ const height = width * this.aspectRatio;
119
+ const size = {
120
+ width,
121
+ height,
122
+ faceZoom,
123
+ };
124
+ const retinaSize = {
125
+ width: width * 2,
126
+ height: height * 2,
127
+ faceZoom,
128
+ };
129
+ return `${this.getSrcsetDef(size)}, ${this.getSrcsetDef(retinaSize)}`;
130
+ }).join(', ');
131
+ },
132
+ },
133
+ methods: {
134
+ getKivaImageUrl({
135
+ base = '/',
136
+ width,
137
+ height,
138
+ square,
139
+ faceZoom,
140
+ hash,
141
+ format = 'jpg',
142
+ } = {}) {
143
+ if (!hash) {
144
+ return '';
145
+ }
146
+ if (!width && !height && !square && !faceZoom) {
147
+ return '';
148
+ }
149
+ let w = '';
150
+ let h = '';
151
+ // If width and height are different, use w and h
152
+ if (width === height) {
153
+ // if height and width are the same, use square param
154
+ // eslint-disable-next-line no-param-reassign
155
+ square = width;
156
+ } else {
157
+ w = width ? `w${Math.ceil(width)}` : '';
158
+ h = height ? `h${Math.ceil(height)}` : '';
159
+ }
160
+ const s = square ? `s${Math.ceil(square)}` : '';
161
+ const fz = faceZoom ? `fz${Math.ceil(faceZoom)}` : '';
162
+
163
+ return `${base}${w}${h}${s}${fz}/${hash}.${format}`;
164
+ },
165
+ // Get the url for the loan image sized width by height
166
+ getImgUrl(size) {
167
+ return this.getKivaImageUrl({
168
+ ...size,
169
+ base: this.photoPath,
170
+ hash: this.hash,
171
+ });
172
+ },
173
+ // Get a string to use in the srcset attribute as the definition for a single image size
174
+ getSrcsetDef(size) {
175
+ return `${this.getImgUrl(size)} ${size.width}w`;
176
+ },
177
+ },
178
+ };
179
+ </script>