@kiva/kv-components 3.0.1 → 3.0.4

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,42 @@
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.0.4](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.0.3...@kiva/kv-components@3.0.4) (2022-05-23)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * remove usage of currentInstance, re-implement indicator count update mechanism ([21dae02](https://github.com/kiva/kv-ui-elements/commit/21dae029094bdeecd4d352eea70a116c08af504c))
12
+
13
+
14
+
15
+
16
+
17
+ ## [3.0.3](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.0.2...@kiva/kv-components@3.0.3) (2022-05-16)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * added back initial uuid value. ([aa4a88c](https://github.com/kiva/kv-ui-elements/commit/aa4a88c5a65846e9103ce25985bd7d1cc7bfd025))
23
+ * label and input uuids didn't match ([742452a](https://github.com/kiva/kv-ui-elements/commit/742452a9ffe03980f10f444a99f253429d028170))
24
+
25
+
26
+
27
+
28
+
29
+ ## [3.0.2](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.0.1...@kiva/kv-components@3.0.2) (2022-03-18)
30
+
31
+
32
+ ### Bug Fixes
33
+
34
+ * clean up tests console errors and props ([37a6da9](https://github.com/kiva/kv-ui-elements/commit/37a6da9b4439463e777ae503b7ccff6562b9c81f))
35
+ * ensure reactive ref state without timeout ([eda1553](https://github.com/kiva/kv-ui-elements/commit/eda1553304e6ed4199e35dbd73cb821b87bf3175))
36
+ * return additional items for access as refs in vue2 ([b34ee52](https://github.com/kiva/kv-ui-elements/commit/b34ee52c39357bb7469418717d99c08a937c5cb8))
37
+
38
+
39
+
40
+
41
+
6
42
  ## [3.0.1](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.0.0...@kiva/kv-components@3.0.1) (2022-02-16)
7
43
 
8
44
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kiva/kv-components",
3
- "version": "3.0.1",
3
+ "version": "3.0.4",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -68,5 +68,5 @@
68
68
  "optional": true
69
69
  }
70
70
  },
71
- "gitHead": "2a8ff1a1fb9a3ad59f371d1e938a858e52372c62"
71
+ "gitHead": "2bf5d2277e1537b150e396320d72ece46f746840"
72
72
  }
@@ -3,7 +3,7 @@ import KvProgressBar from '../../../../vue/KvProgressBar.vue';
3
3
 
4
4
  describe('KvProgressBar', () => {
5
5
  it('renders with a role of "progressbar"', () => {
6
- const { getByRole } = render(KvProgressBar);
6
+ const { getByRole } = render(KvProgressBar, { props: { ariaLabel: 'progress-bar', value: 100 } });
7
7
  const progressbarEl = getByRole('progressbar');
8
8
 
9
9
  expect(progressbarEl).toBeDefined();
@@ -1,10 +1,31 @@
1
1
  import { render } from '@testing-library/vue';
2
2
  import { axe } from 'jest-axe';
3
+ import '../../../../__mocks__/ResizeObserver';
4
+ import KvTab from '../../../../vue/KvTab.vue';
3
5
  import KvTabPanel from '../../../../vue/KvTabPanel.vue';
6
+ import KvTabs from '../../../../vue/KvTabs.vue';
4
7
 
5
8
  describe('KvTabPanel', () => {
6
9
  it('has no automated accessibility violations', async () => {
7
- const { container } = render(KvTabPanel);
10
+ const { container } = render({
11
+ components: { KvTabs, KvTab, KvTabPanel },
12
+ template: `
13
+ <kv-tabs>
14
+ <template #tabNav>
15
+ <kv-tab forPanel="demo-1-first">First</kv-tab>
16
+ <kv-tab forPanel="demo-1-second">Second</kv-tab>
17
+ <kv-tab forPanel="demo-1-third">Third</kv-tab>
18
+ <kv-tab forPanel="demo-1-forth">Fourth is longer</kv-tab>
19
+ </template>
20
+ <template #tabPanels>
21
+ <kv-tab-panel id="demo-1-first"><p>First Panel</p></kv-tab-panel>
22
+ <kv-tab-panel id="demo-1-second"><p>Second Panel has <br>longer<br>content</p></kv-tab-panel>
23
+ <kv-tab-panel id="demo-1-third"><p>Third Panel</p></kv-tab-panel>
24
+ <kv-tab-panel id="demo-1-forth"><p>Fourth Panel</p></kv-tab-panel>
25
+ </template>
26
+ </kv-tabs>
27
+ `,
28
+ });
8
29
  const results = await axe(container);
9
30
  expect(results).toHaveNoViolations();
10
31
  });
@@ -5,6 +5,8 @@ import '../../../../__mocks__/ResizeObserver';
5
5
  import KvTab from '../../../../vue/KvTab.vue';
6
6
  import KvTabPanel from '../../../../vue/KvTabPanel.vue';
7
7
  import KvTabs from '../../../../vue/KvTabs.vue';
8
+ import KvButton from '../../../../vue/KvButton.vue';
9
+ import addVueRouter from '../../utils/addVueRouter';
8
10
 
9
11
  // jsdom does not include scrollIntoView, so define it to avoid errors when switching tabs
10
12
  window.HTMLElement.prototype.scrollIntoView = () => {};
@@ -30,7 +32,6 @@ function renderOneTabSet() {
30
32
  `,
31
33
  });
32
34
  }
33
-
34
35
  describe('KvTabs', () => {
35
36
  it('has no automated accessibility violations', async () => {
36
37
  const { container } = renderOneTabSet();
@@ -96,4 +97,71 @@ describe('KvTabs', () => {
96
97
  userEvent.keyboard('{Home}');
97
98
  expect(await findByText('First Panel')).toBeVisible();
98
99
  });
100
+
101
+ it('verifies setTab method when called by a ref', async () => {
102
+ const {
103
+ getByRole,
104
+ getAllByRole,
105
+ getByText,
106
+ } = render({
107
+ components: {
108
+ KvTabs,
109
+ KvTab,
110
+ KvTabPanel,
111
+ KvButton,
112
+ },
113
+ data() {
114
+ return { selectedIndexCheck: null };
115
+ },
116
+ template: `
117
+ <div data-testid="tabContainer">
118
+ <kv-tabs @tab-changed="handleTabChanged" data-testid="tabInstance" ref="tabsRef">
119
+ <template #tabNav>
120
+ <kv-tab forPanel="demo-1-first">First</kv-tab>
121
+ <kv-tab forPanel="demo-1-second">Second</kv-tab>
122
+ <kv-tab forPanel="demo-1-third">Third</kv-tab>
123
+ <kv-tab forPanel="demo-1-forth">Fourth is longer</kv-tab>
124
+ </template>
125
+ <template #tabPanels>
126
+ <kv-tab-panel id="demo-1-first"><p>First Panel</p></kv-tab-panel>
127
+ <kv-tab-panel id="demo-1-second"><p>Second Panel has <br>longer<br>content</p></kv-tab-panel>
128
+ <kv-tab-panel id="demo-1-third"><p>Third Panel</p></kv-tab-panel>
129
+ <kv-tab-panel id="demo-1-forth"><p>Fourth Panel</p></kv-tab-panel>
130
+ </template>
131
+ </kv-tabs>
132
+ <kv-button @click.native.prevent="setTabButtonClick(1)" role="tabSetButton">Set Tab</kv-button>
133
+ <p>Tab index is {{ selectedIndexCheck }}</p>
134
+ </div>
135
+ `,
136
+ methods: {
137
+ handleTabChanged() {
138
+ this.selectedIndexCheck = this?.$refs?.tabsRef?.tabContext?.selectedIndex;
139
+ },
140
+ setTabButtonClick() {
141
+ this?.$refs?.tabsRef?.tabContext?.setTab(0);
142
+ },
143
+ },
144
+ }, addVueRouter());
145
+
146
+ // check for our elements
147
+ expect(getByRole('tabSetButton')).toBeDefined();
148
+ expect(getByRole('tablist')).toBeDefined();
149
+ expect(getAllByRole('tab').length).toBe(4);
150
+
151
+ // Click third tab and expect the third panel to be visible
152
+ await fireEvent.click(getByText('Third'));
153
+ expect(getByText('First Panel')).not.toBeVisible();
154
+ expect(getByText('Third Panel')).toBeVisible();
155
+ // Test access and updating of property ref
156
+ // expect the selected index value to be set to our new tab index
157
+ expect(getByText('Tab index is 2')).toBeVisible();
158
+
159
+ // click the button to test our ref method
160
+ await userEvent.click(getByText('Set Tab'));
161
+ expect(getByText('Third Panel')).not.toBeVisible();
162
+ expect(getByText('First Panel')).toBeVisible();
163
+ // Test access and updating of property ref
164
+ // expect the selected index value to be set to our new tab index
165
+ expect(getByText('Tab index is 0')).toBeVisible();
166
+ });
99
167
  });
@@ -14,7 +14,7 @@
14
14
  :key="index"
15
15
  class="tw-flex-none tw-relative"
16
16
  role="group"
17
- :aria-label="`slide ${index} of ${componentSlotKeys.length}`"
17
+ :aria-label="`slide ${index + 1} of ${componentSlotKeys.length}`"
18
18
  :aria-current="true ? currentIndex + 1 === index : false"
19
19
  :aria-hidden="isAriaHidden(index)"
20
20
  :tab-index="isAriaHidden(index) ? '-1' : false"
@@ -48,8 +48,11 @@
48
48
  />
49
49
  <span class="tw-sr-only">Show previous slide</span>
50
50
  </button>
51
- <div class="tw-mx-2 md:tw-mx-3 lg:tw-mx-4 tw-invisible md:tw-visible">
52
- {{ currentIndex + 1 }}/{{ slideIndicatorListLength() }}
51
+ <div
52
+ :aria-label="`screen ${currentIndex + 1} of ${slideIndicatorCount}`"
53
+ class="tw-mx-2 md:tw-mx-3 lg:tw-mx-4 tw-invisible md:tw-visible"
54
+ >
55
+ {{ currentIndex + 1 }}/{{ slideIndicatorCount }}
53
56
  </div>
54
57
  <button
55
58
  class="tw-text-primary
@@ -79,7 +82,6 @@ import {
79
82
  ref,
80
83
  toRefs,
81
84
  nextTick,
82
- getCurrentInstance,
83
85
  } from 'vue-demi';
84
86
  import EmblaCarousel from 'embla-carousel';
85
87
  import { mdiChevronLeft, mdiChevronRight } from '@mdi/js';
@@ -144,11 +146,8 @@ export default {
144
146
  const embla = ref(null);
145
147
  const slides = ref([]);
146
148
  const currentIndex = ref(0);
147
-
148
- const forceUpdate = () => {
149
- const instance = getCurrentInstance();
150
- instance.proxy.$forceUpdate();
151
- };
149
+ // The indicator count may differ from the slide count when multiple slides are in view
150
+ const slideIndicatorCount = ref(0);
152
151
 
153
152
  const componentSlotKeys = computed(() => {
154
153
  const keys = Object.keys(slots);
@@ -193,6 +192,18 @@ export default {
193
192
  */
194
193
  emit('interact-carousel', interactionType);
195
194
  };
195
+
196
+ /**
197
+ * Returns number of slides in the carousel
198
+ *
199
+ * @returns {Number}
200
+ */
201
+ const slideIndicatorListLength = () => {
202
+ const indicator = embla.value ? embla.value.scrollSnapList().length : 0;
203
+ slideIndicatorCount.value = indicator;
204
+ return indicator;
205
+ };
206
+
196
207
  /**
197
208
  * Reinitialize the carousel.
198
209
  * Used after adding slides dynamically.
@@ -214,7 +225,7 @@ export default {
214
225
  reInitVisible();
215
226
  }
216
227
  slides.value = embla.value.slideNodes();
217
- forceUpdate(); // force a re-render so embla.canScrollNext() gets called in the template
228
+ slideIndicatorListLength();
218
229
  };
219
230
  const onCarouselContainerClick = (e) => {
220
231
  // If we're dragging, block click handlers within slides
@@ -238,18 +249,8 @@ export default {
238
249
  }
239
250
  return false;
240
251
  };
241
- /**
242
- * Returns number of slides in the carousel
243
- *
244
- * @returns {Number}
245
- */
246
- const slideIndicatorListLength = () => {
247
- const indicator = embla.value ? embla.value.scrollSnapList().length : 0;
248
- return indicator;
249
- };
250
252
 
251
253
  onMounted(async () => {
252
- getCurrentInstance();
253
254
  embla.value = EmblaCarousel(rootEl.value, {
254
255
  loop: true,
255
256
  containScroll: 'trimSnaps',
@@ -268,23 +269,26 @@ export default {
268
269
  slidesToScroll: embla.value.slidesInView(true).length,
269
270
  inViewThreshold: 0.9,
270
271
  });
271
- forceUpdate();
272
+ slides.value = embla.value.slideNodes();
273
+ slideIndicatorListLength();
272
274
  }, 250),
273
275
  );
274
276
  }
275
277
 
276
278
  // get slide components
277
279
  slides.value = embla.value.slideNodes();
280
+ slideIndicatorListLength();
278
281
 
279
282
  embla.value.on('select', () => {
280
283
  currentIndex.value = embla.value.selectedScrollSnap();
281
-
282
284
  /**
283
285
  * The index of the slide that the carousel has changed to
284
286
  * @event change
285
287
  * @type {Event}
286
288
  */
287
- emit('change', currentIndex);
289
+ nextTick(() => {
290
+ emit('change', currentIndex);
291
+ });
288
292
  });
289
293
  });
290
294
 
@@ -303,6 +307,7 @@ export default {
303
307
  componentSlotKeys,
304
308
  nextIndex,
305
309
  previousIndex,
310
+ slideIndicatorCount,
306
311
  handleUserInteraction,
307
312
  goToSlide,
308
313
  reInit,
package/vue/KvRadio.vue CHANGED
@@ -151,7 +151,7 @@ export default {
151
151
  modelValue,
152
152
  } = toRefs(props);
153
153
 
154
- let uuid = ref(`kvr-${nanoid(10)}`);
154
+ const uuid = ref(`kvr-${nanoid(10)}`);
155
155
  const radioRef = ref(null);
156
156
 
157
157
  const {
@@ -169,7 +169,7 @@ export default {
169
169
  });
170
170
 
171
171
  onMounted(() => {
172
- uuid = `kvr-${nanoid(10)}`;
172
+ uuid.value = `kvr-${nanoid(10)}`;
173
173
  });
174
174
 
175
175
  const onChange = (event) => {
package/vue/KvTabs.vue CHANGED
@@ -44,8 +44,8 @@
44
44
  * ```
45
45
  * <kv-tabs>
46
46
  * <template #tabNav>
47
- * <kv-tab for="foo">Foo</kv-tab>
48
- * <kv-tab for="bar">Bar</kv-tab>
47
+ * <kv-tab for-panel="foo">Foo</kv-tab>
48
+ * <kv-tab for-panel="bar">Bar</kv-tab>
49
49
  * </template>
50
50
  * <template #tabPanels>
51
51
  * <kv-tab-panel id="foo">Foo content</kv-tab-panel>
@@ -163,6 +163,7 @@ export default {
163
163
  return {
164
164
  handleKeyDown,
165
165
  selectedTabEl,
166
+ tabContext,
166
167
  };
167
168
  },
168
169
  };
@@ -164,6 +164,78 @@ export const MultipleLoanCards2 = () => ({
164
164
  `,
165
165
  });
166
166
 
167
+ export const MultipleLoanCardsReInit = () => ({
168
+ components: {
169
+ KvCarousel,
170
+ KvButton,
171
+ },
172
+ template: `
173
+ <div data-testid="carousel-container">
174
+ <kv-carousel
175
+ ref="myCarouselRef"
176
+ :multiple-slides-visible="true"
177
+ slides-to-scroll="visible"
178
+ style="max-width: 800px;"
179
+ >
180
+ <template #slide1>
181
+ ${generateLoanCardTemplate(1)}
182
+ </template>
183
+ <template #slide2>
184
+ ${generateLoanCardTemplate(2)}
185
+ </template>
186
+ <template #slide3>
187
+ ${generateLoanCardTemplate(3)}
188
+ </template>
189
+ <template #slide4>
190
+ ${generateLoanCardTemplate(4)}
191
+ </template>
192
+ <template #slide5>
193
+ ${generateLoanCardTemplate(5)}
194
+ </template>
195
+ <template #slide6>
196
+ ${generateLoanCardTemplate(6)}
197
+ </template>
198
+ <template #slide7>
199
+ ${generateLoanCardTemplate(7)}
200
+ </template>
201
+ <template #slide8>
202
+ ${generateLoanCardTemplate(8)}
203
+ </template>
204
+ </kv-carousel>
205
+ <kv-button @click.native.prevent="removeSlide()" role="removeSlideButton">Remove Slide</kv-button>
206
+ <p>Slide Count: {{ slideCount }} | Indicator Count: {{ slideIndicatorCount }} | Removed Slides: {{ removedSlides.length }}</p>
207
+ </div>
208
+ `,
209
+ data() {
210
+ return {
211
+ removedSlides: [],
212
+ slideCount: null,
213
+ slideIndicatorCount: null,
214
+ };
215
+ },
216
+ mounted() {
217
+ this.$nextTick(() => {
218
+ this.slideCount = this.$refs?.myCarouselRef?.slides?.length;
219
+ this.slideIndicatorCount = this.$refs?.myCarouselRef?.slideIndicatorCount;
220
+ });
221
+ },
222
+ methods: {
223
+ removeSlide() {
224
+ // Fetch slides + remove one
225
+ const slides = this.$refs?.myCarouselRef?.embla?.slideNodes();
226
+ const slideToRemove = slides.pop();
227
+ this.removedSlides.push(slideToRemove);
228
+ this.$refs?.myCarouselRef?.embla?.containerNode()?.removeChild(slideToRemove);
229
+ // Call our component reInit method
230
+ this.$refs?.myCarouselRef?.reInit();
231
+ // Update values for reflection in story
232
+ this.slideCount = this.$refs?.myCarouselRef?.slides?.length;
233
+ this.selectedIndexCheck = this.$refs?.myCarouselRef?.currentIndex;
234
+ this.slideIndicatorCount = this.$refs?.myCarouselRef?.slideIndicatorCount;
235
+ },
236
+ },
237
+ });
238
+
167
239
  export const loadingLoanCardExample = () => ({
168
240
  components: {
169
241
  KvCarousel,