aloha-vue 2.66.2 → 2.67.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aloha-vue",
3
- "version": "2.66.2",
3
+ "version": "2.67.0",
4
4
  "description": "Aloha-vue is a JavaScript library that provides a wide range of accessible components and directives for Vue.js. Accessibility is of paramount importance to us, and we have designed all our components to meet accessibility compliance criteria. This library is a valuable tool for frontend developers and has already been used in three projects, including two large-scale ones",
5
5
  "keywords": [
6
6
  "accessibility compliance criteria",
@@ -5,9 +5,10 @@ import {
5
5
  import AModal from "../AModal/AModal";
6
6
  import AWizard from "../AWizard/AWizard";
7
7
 
8
- import EmitsAPI from "./compositionAPI/EmitsAPI";
9
- import IdsAPI from "./compositionAPI/IdsAPI";
10
- import VisibleAPI from "./compositionAPI/VisibleAPI";
8
+ import EmitsAPI from "./compositionAPI/EmitsAPI";
9
+ import IdsAPI from "./compositionAPI/IdsAPI";
10
+ import ScrollAPI from "./compositionAPI/ScrollAPI";
11
+ import VisibleAPI from "./compositionAPI/VisibleAPI";
11
12
 
12
13
  import ExclamationCircleFill from "aloha-svg/dist/js/bootstrap/ExclamationCircleFill";
13
14
  import XCircleFill from "aloha-svg/dist/js/bootstrap/XCircleFill";
@@ -350,12 +351,16 @@ export default {
350
351
  required: false,
351
352
  default: true,
352
353
  },
353
- keyId: {
354
- type: String,
355
- required: false,
356
- default: undefined,
357
- },
358
- showOnlyActiveStepMobile: {
354
+ keyId: {
355
+ type: String,
356
+ required: false,
357
+ default: undefined,
358
+ },
359
+ scrollToTopOnStepChange: {
360
+ type: Boolean,
361
+ default: true,
362
+ },
363
+ showOnlyActiveStepMobile: {
359
364
  type: Boolean,
360
365
  required: false,
361
366
  default: true,
@@ -427,39 +432,51 @@ export default {
427
432
  validator: value => ["arrows", "line", "round", "basic"].indexOf(value) !== -1,
428
433
  },
429
434
  },
430
- emits: [
431
- "goStepBack",
435
+ emits: [
436
+ "changeStep",
437
+ "goStepBack",
432
438
  "goStepForward",
433
439
  ],
434
440
  setup(props, context) {
435
- const {
436
- goStepBackLocal,
437
- goStepForwardLocal,
438
- } = EmitsAPI(context);
439
-
440
- const {
441
- footerId,
441
+ const {
442
+ footerId,
442
443
  wizardId,
443
444
  } = IdsAPI(props);
444
445
 
445
- const {
446
- initWizard,
447
- isWizardVisible,
448
- } = VisibleAPI();
446
+ const {
447
+ initWizard,
448
+ isWizardVisible,
449
+ } = VisibleAPI();
450
+
451
+ const {
452
+ modalBodyRef,
453
+ scrollToTop,
454
+ } = ScrollAPI(props);
455
+
456
+ const {
457
+ changeStepLocal,
458
+ goStepBackLocal,
459
+ goStepForwardLocal,
460
+ } = EmitsAPI(context, {
461
+ scrollToTop,
462
+ });
449
463
 
450
464
  initWizard();
451
465
 
452
466
  return {
453
- footerId,
454
- goStepBackLocal,
455
- goStepForwardLocal,
456
- isWizardVisible,
457
- wizardId,
467
+ footerId,
468
+ changeStepLocal,
469
+ goStepBackLocal,
470
+ goStepForwardLocal,
471
+ isWizardVisible,
472
+ modalBodyRef,
473
+ wizardId,
458
474
  };
459
475
  },
460
476
  render() {
461
- return h(AModal, {
462
- alwaysTranslate: this.alwaysTranslate,
477
+ return h(AModal, {
478
+ ref: "modalBodyRef",
479
+ alwaysTranslate: this.alwaysTranslate,
463
480
  backdropZIndex: this.backdropZIndex,
464
481
  classExtra: this.classExtra,
465
482
  close: this.close,
@@ -500,8 +517,8 @@ export default {
500
517
  }, {
501
518
  ...this.$slots || {},
502
519
  modalBody: () => [
503
- this.isWizardVisible && h(AWizard, {
504
- id: this.wizardId,
520
+ this.isWizardVisible && h(AWizard, {
521
+ id: this.wizardId,
505
522
  ariaLabel: this.ariaLabel,
506
523
  ariaLabelSteps: this.ariaLabelSteps,
507
524
  backButtonAttributes: this.backButtonAttributes,
@@ -546,8 +563,9 @@ export default {
546
563
  stepsVisited: this.stepsVisited,
547
564
  subType: this.subType,
548
565
  toolbarBottomTeleportId: this.footerId,
549
- type: this.type,
550
- onGoStepBack: this.goStepBackLocal,
566
+ type: this.type,
567
+ onChangeStep: this.changeStepLocal,
568
+ onGoStepBack: this.goStepBackLocal,
551
569
  onGoStepForward: this.goStepForwardLocal,
552
570
  }, this.$slots),
553
571
  ],
@@ -1,4 +1,11 @@
1
- export default function EmitsAPI({ emit }) {
1
+ export default function EmitsAPI({ emit }, {
2
+ scrollToTop = () => {},
3
+ } = {}) {
4
+ const changeStepLocal = arg => {
5
+ scrollToTop();
6
+ emit("changeStep", arg);
7
+ };
8
+
2
9
  const goStepBackLocal = arg => {
3
10
  emit("goStepBack", arg);
4
11
  };
@@ -7,6 +14,7 @@ export default function EmitsAPI({ emit }) {
7
14
  };
8
15
 
9
16
  return {
17
+ changeStepLocal,
10
18
  goStepBackLocal,
11
19
  goStepForwardLocal,
12
20
  };
@@ -0,0 +1,26 @@
1
+ import {
2
+ ref,
3
+ toRef,
4
+ } from "vue";
5
+
6
+ export default function ScrollAPI(props) {
7
+ const scrollToTopOnStepChange = toRef(props, "scrollToTopOnStepChange");
8
+
9
+ const modalBodyRef = ref(undefined);
10
+
11
+ const scrollToTop = () => {
12
+ if (!scrollToTopOnStepChange.value) {
13
+ return;
14
+ }
15
+
16
+ modalBodyRef.value?.modalRef?.querySelector(".a_modal_body")?.scrollTo({
17
+ top: 0,
18
+ behavior: "auto",
19
+ });
20
+ };
21
+
22
+ return {
23
+ modalBodyRef,
24
+ scrollToTop,
25
+ };
26
+ }
@@ -0,0 +1,46 @@
1
+ import {
2
+ reactive,
3
+ } from "vue";
4
+ import {
5
+ describe,
6
+ expect,
7
+ it,
8
+ jest,
9
+ } from "@jest/globals";
10
+
11
+ import ScrollAPI from "../ScrollAPI";
12
+
13
+ describe("AModalWizard ScrollAPI", () => {
14
+ it("scrolls the modal body when the active step changes", () => {
15
+ const props = reactive({
16
+ scrollToTopOnStepChange: true,
17
+ });
18
+ const scrollTo = jest.fn();
19
+ const modalBody = {
20
+ scrollTo,
21
+ };
22
+
23
+ const {
24
+ modalBodyRef,
25
+ scrollToTop,
26
+ } = ScrollAPI(props);
27
+
28
+ modalBodyRef.value = {
29
+ modalRef: {
30
+ querySelector: jest.fn(() => modalBody),
31
+ },
32
+ };
33
+
34
+ scrollToTop();
35
+
36
+ expect(scrollTo).toHaveBeenCalledWith({
37
+ top: 0,
38
+ behavior: "auto",
39
+ });
40
+
41
+ props.scrollToTopOnStepChange = false;
42
+ scrollToTop();
43
+
44
+ expect(scrollTo).toHaveBeenCalledTimes(1);
45
+ });
46
+ });
@@ -8,8 +8,9 @@ import AWizardStep from "./AWizardStep/AWizardStep";
8
8
  import AWizardTab from "./AWizardTab/AWizardTab";
9
9
  import AWizardToolbar from "./AWizardToolbar/AWizardToolbar";
10
10
 
11
- import AttributesAPI from "./compositionAPI/AttributesAPI";
12
- import ClassAPI from "./compositionAPI/ClassAPI";
11
+ import AttributesAPI from "./compositionAPI/AttributesAPI";
12
+ import ChangeStepAPI from "./compositionAPI/ChangeStepAPI";
13
+ import ClassAPI from "./compositionAPI/ClassAPI";
13
14
  import EventsAPI from "./compositionAPI/EventsAPI";
14
15
  import FocusAPI from "./compositionAPI/FocusAPI";
15
16
  import LocalAPI from "./compositionAPI/LocalAPI";
@@ -273,8 +274,9 @@ export default {
273
274
  validator: value => ["arrows", "line", "round", "basic"].indexOf(value) !== -1,
274
275
  },
275
276
  },
276
- emits: [
277
- "goStepBack",
277
+ emits: [
278
+ "changeStep",
279
+ "goStepBack",
278
280
  "goStepForward",
279
281
  ],
280
282
  setup(props, context) {
@@ -288,19 +290,24 @@ export default {
288
290
  subTypeLocal,
289
291
  });
290
292
 
291
- const {
292
- setFocusToActiveStep,
293
- wizardTabsRef,
294
- } = FocusAPI(props);
295
-
296
- const {
293
+ const {
294
+ setFocusToActiveStep,
295
+ wizardTabsRef,
296
+ } = FocusAPI(props);
297
+
298
+ const {
299
+ changeStep,
300
+ } = ChangeStepAPI(props, context);
301
+
302
+ const {
297
303
  initStepActive,
298
304
  stepActiveComputed,
299
305
  stepActiveLocal,
300
306
  stepsVisitedComputed,
301
307
  stepsVisitedLocal,
302
- } = LocalAPI(props, {
303
- setFocusToActiveStep,
308
+ } = LocalAPI(props, {
309
+ changeStep,
310
+ setFocusToActiveStep,
304
311
  });
305
312
 
306
313
  const {
@@ -0,0 +1,19 @@
1
+ import {
2
+ toRef,
3
+ } from "vue";
4
+
5
+ export default function ChangeStepAPI(props, { emit }) {
6
+ const steps = toRef(props, "steps");
7
+
8
+ const changeStep = ({ stepIndex, previousStepIndex }) => {
9
+ emit("changeStep", {
10
+ step: steps.value[stepIndex],
11
+ stepIndex,
12
+ previousStepIndex,
13
+ });
14
+ };
15
+
16
+ return {
17
+ changeStep,
18
+ };
19
+ }
@@ -10,6 +10,7 @@ import {
10
10
  } from "lodash-es";
11
11
 
12
12
  export default function LocalAPI(props, {
13
+ changeStep = () => {},
13
14
  setFocusToActiveStep = () => {},
14
15
  }) {
15
16
  const stepActive = toRef(props, "stepActive");
@@ -44,9 +45,13 @@ export default function LocalAPI(props, {
44
45
  });
45
46
  };
46
47
 
47
- watch(stepActiveComputed, newValue => {
48
+ watch(stepActiveComputed, (newValue, oldValue) => {
48
49
  if (isWatchActive.value) {
49
50
  setFocusToActiveStep({ stepActive: newValue });
51
+ changeStep({
52
+ stepIndex: newValue,
53
+ previousStepIndex: oldValue,
54
+ });
50
55
  }
51
56
  });
52
57
 
@@ -0,0 +1,32 @@
1
+ import {
2
+ describe,
3
+ expect,
4
+ it,
5
+ jest,
6
+ } from "@jest/globals";
7
+
8
+ import ChangeStepAPI from "../ChangeStepAPI";
9
+
10
+ describe("AWizard ChangeStepAPI", () => {
11
+ it("emits details about the changed step", () => {
12
+ const emit = jest.fn();
13
+ const steps = [
14
+ { label: "Step 1" },
15
+ { label: "Step 2" },
16
+ ];
17
+ const {
18
+ changeStep,
19
+ } = ChangeStepAPI({ steps }, { emit });
20
+
21
+ changeStep({
22
+ stepIndex: 1,
23
+ previousStepIndex: 0,
24
+ });
25
+
26
+ expect(emit).toHaveBeenCalledWith("changeStep", {
27
+ step: steps[1],
28
+ stepIndex: 1,
29
+ previousStepIndex: 0,
30
+ });
31
+ });
32
+ });
@@ -0,0 +1,55 @@
1
+ import {
2
+ nextTick,
3
+ reactive,
4
+ } from "vue";
5
+ import {
6
+ afterEach,
7
+ describe,
8
+ expect,
9
+ it,
10
+ jest,
11
+ } from "@jest/globals";
12
+
13
+ import LocalAPI from "../LocalAPI";
14
+
15
+ describe("AWizard LocalAPI", () => {
16
+ afterEach(() => {
17
+ jest.useRealTimers();
18
+ });
19
+
20
+ it("reports internal and external active-step changes", async() => {
21
+ jest.useFakeTimers();
22
+
23
+ const props = reactive({
24
+ isControlOutside: false,
25
+ stepActive: undefined,
26
+ stepsVisited: undefined,
27
+ });
28
+ const changeStep = jest.fn();
29
+ const {
30
+ initStepActive,
31
+ stepActiveLocal,
32
+ } = LocalAPI(props, { changeStep });
33
+
34
+ initStepActive();
35
+ jest.runOnlyPendingTimers();
36
+
37
+ stepActiveLocal.value = 1;
38
+ await nextTick();
39
+
40
+ expect(changeStep).toHaveBeenLastCalledWith({
41
+ stepIndex: 1,
42
+ previousStepIndex: 0,
43
+ });
44
+
45
+ props.stepActive = 2;
46
+ props.isControlOutside = true;
47
+ await nextTick();
48
+
49
+ expect(changeStep).toHaveBeenLastCalledWith({
50
+ stepIndex: 2,
51
+ previousStepIndex: 1,
52
+ });
53
+ expect(changeStep).toHaveBeenCalledTimes(2);
54
+ });
55
+ });