aloha-vue 2.72.0 → 2.74.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.72.0",
3
+ "version": "2.74.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",
@@ -567,9 +567,10 @@ export default {
567
567
  const {
568
568
  columnsOrderedFromSimpleTable,
569
569
  renderedGroupedColumns,
570
- } = ColumnsGroupedAPI(props, {
571
- modelSort: modelSortLocal,
572
- });
570
+ } = ColumnsGroupedAPI(props, {
571
+ modelSort: modelSortLocal,
572
+ slots: context.slots,
573
+ });
573
574
 
574
575
  const {
575
576
  columnIdsGroupByLocked,
@@ -995,7 +996,7 @@ export default {
995
996
  onSetSelectedRowsIndexes: this.setSelectedRowsIndexes,
996
997
  columnsForRender: this.renderedGroupedColumns,
997
998
  }) :
998
- h(ATableHeader, {
999
+ h(ATableHeader, {
999
1000
  areAllRowsSelected: this.areAllRowsSelected,
1000
1001
  areAllVisibleRowsSelected: this.areAllVisibleRowsSelected,
1001
1002
  areSomeRowsSelected: this.areSomeRowsSelected,
@@ -1008,8 +1009,8 @@ export default {
1008
1009
  rowsLocalLength: this.rowsLocalLength,
1009
1010
  showFirstSortingSequenceNumber: this.showFirstSortingSequenceNumber,
1010
1011
  sortingSequenceNumberClass: this.sortingSequenceNumberClass,
1011
- onSetSelectedRowsIndexes: this.setSelectedRowsIndexes,
1012
- }),
1012
+ onSetSelectedRowsIndexes: this.setSelectedRowsIndexes,
1013
+ }, this.$slots),
1013
1014
  h("div", {
1014
1015
  class: "a_table__loading",
1015
1016
  }, [
@@ -165,7 +165,7 @@ export default {
165
165
  onDragenterParent: this.dragenter,
166
166
  onDragleaveParent: this.dragleave,
167
167
  onDragendParent: this.dragend,
168
- });
168
+ }, this.$slots);
169
169
  }),
170
170
  this.isActionColumnVisible && h(ATableHeaderThAction, {
171
171
  disabledOptions: this.disabledOptions,
@@ -154,13 +154,18 @@ export default {
154
154
  textScreenReader: this.column.textScreenReader || undefined,
155
155
  ...this.attributesForButtonSort,
156
156
  }, () => [
157
- this.column.label && h(ATranslation, {
158
- html: this.column.label,
159
- tag: "span",
160
- extra: this.column.extra,
161
- class: "a_table__th__text aloha_element__ml_0",
162
- ariaHidden: !!this.column.textScreenReader,
163
- }),
157
+ (this.column.headerSlot && this.$slots[this.column.headerSlot]) ?
158
+ this.$slots[this.column.headerSlot]({
159
+ column: this.column,
160
+ columnIndex: this.columnIndex,
161
+ }) :
162
+ this.column.label && h(ATranslation, {
163
+ html: this.column.label,
164
+ tag: "span",
165
+ extra: this.column.extra,
166
+ class: "a_table__th__text aloha_element__ml_0",
167
+ ariaHidden: !!this.column.textScreenReader,
168
+ }),
164
169
  this.isSortable && h("span", {
165
170
  class: "a_table__th__sort__box aloha_element__ml_0",
166
171
  }, [
@@ -0,0 +1,97 @@
1
+ import {
2
+ h,
3
+ ref,
4
+ } from "vue";
5
+ import {
6
+ describe,
7
+ expect,
8
+ it,
9
+ jest,
10
+ } from "@jest/globals";
11
+ import {
12
+ mount,
13
+ } from "@vue/test-utils";
14
+
15
+ import ATableHeaderTh from "../ATableHeaderTh/ATableHeaderTh";
16
+
17
+ jest.mock("../../AButton/AButton", () => ({
18
+ name: "AButton",
19
+ render() {
20
+ return jest.requireActual("vue").h("span", this.$slots.default?.());
21
+ },
22
+ }));
23
+ jest.mock("aloha-svg/dist/js/bootstrap/CaretDownFill", () => "");
24
+ jest.mock("aloha-svg/dist/js/bootstrap/CaretUpFill", () => "");
25
+
26
+ const ATranslationStub = {
27
+ name: "ATranslation",
28
+ props: {
29
+ html: {
30
+ type: [String, Number, Object, Array],
31
+ default: undefined,
32
+ },
33
+ text: {
34
+ type: [String, Number, Object, Array],
35
+ default: undefined,
36
+ },
37
+ },
38
+ render() {
39
+ return h("span", this.html || this.text);
40
+ },
41
+ };
42
+
43
+ const mountHeader = ({ column, slots }) => mount(ATableHeaderTh, {
44
+ props: {
45
+ column,
46
+ columnIndex: 2,
47
+ hasMultipleActions: false,
48
+ },
49
+ slots,
50
+ global: {
51
+ provide: {
52
+ changeModelSort: () => {},
53
+ columnWidthDefault: ref(250),
54
+ isColumnsDnd: ref(false),
55
+ isLoadingOptions: ref(false),
56
+ isLoadingTable: ref(false),
57
+ tableId: ref("table"),
58
+ useRem: ref(false),
59
+ },
60
+ stubs: {
61
+ ATranslation: ATranslationStub,
62
+ },
63
+ },
64
+ });
65
+
66
+ describe("ATable header slot", () => {
67
+ it("renders the configured header slot instead of the label", () => {
68
+ const wrapper = mountHeader({
69
+ column: {
70
+ id: "name",
71
+ label: "Name label",
72
+ headerSlot: "nameHeader",
73
+ },
74
+ slots: {
75
+ nameHeader: ({ column, columnIndex }) => h(
76
+ "strong",
77
+ { class: "custom-header" },
78
+ `${ column.id }-${ columnIndex }`,
79
+ ),
80
+ },
81
+ });
82
+
83
+ expect(wrapper.find(".custom-header").text()).toBe("name-2");
84
+ expect(wrapper.text()).not.toContain("Name label");
85
+ });
86
+
87
+ it("renders the label when the configured header slot is not provided", () => {
88
+ const wrapper = mountHeader({
89
+ column: {
90
+ label: "Name label",
91
+ headerSlot: "nameHeader",
92
+ },
93
+ });
94
+
95
+ expect(wrapper.text()).toContain("Name label");
96
+ });
97
+ });
@@ -24,9 +24,10 @@ import {
24
24
  uniqBy,
25
25
  } from "lodash-es";
26
26
 
27
- export default function ColumnsGroupedAPI(props, {
28
- modelSort = ref([]),
29
- }) {
27
+ export default function ColumnsGroupedAPI(props, {
28
+ modelSort = ref([]),
29
+ slots = {},
30
+ }) {
30
31
  const columns = toRef(props, "columns");
31
32
  const showFirstSortingSequenceNumber = toRef(props, "showFirstSortingSequenceNumber");
32
33
  const sortingSequenceNumberClass = toRef(props, "sortingSequenceNumberClass");
@@ -133,7 +134,7 @@ export default function ColumnsGroupedAPI(props, {
133
134
  });
134
135
 
135
136
  const getColumnsForRender = col => {
136
- return h(ATableHeaderTh, {
137
+ return h(ATableHeaderTh, {
137
138
  ref: "th",
138
139
  class: "a_table__cell__child_group",
139
140
  column: col,
@@ -142,8 +143,8 @@ export default function ColumnsGroupedAPI(props, {
142
143
  hasMultipleActions: false,
143
144
  modelSort: modelSort.value,
144
145
  showFirstSortingSequenceNumber: showFirstSortingSequenceNumber.value,
145
- sortingSequenceNumberClass: sortingSequenceNumberClass.value,
146
- });
146
+ sortingSequenceNumberClass: sortingSequenceNumberClass.value,
147
+ }, slots);
147
148
  };
148
149
  const getRecursiveGroupForRender = group => {
149
150
  return h("div", {
@@ -1,4 +1,5 @@
1
1
  import {
2
+ Fragment,
2
3
  h,
3
4
  resolveComponent,
4
5
  } from "vue";
@@ -363,10 +364,6 @@ export default {
363
364
  } else if (item.classColumn) {
364
365
  classColumn = item.classColumn;
365
366
  }
366
- let style;
367
- if (item.isHide) {
368
- style = "display: none;";
369
- }
370
367
  const COMPONENT = this.componentTypesMapping()[item.type];
371
368
  const ERRORS = this.useFlatErrors ?
372
369
  get(this.errorsAll, item.id) :
@@ -394,21 +391,20 @@ export default {
394
391
  });
395
392
  }
396
393
 
397
- return h("div", {
394
+ return h(Fragment, {
398
395
  key,
399
- class: classColumn,
400
- style,
401
396
  }, [
402
397
  h(COMPONENT, {
403
398
  alwaysTranslate: this.alwaysTranslate,
404
399
  modelValue: MODEL_VALUE,
405
400
  modelAll: IS_CONTAINER ? this.modelAll : undefined,
406
- modelDependencies: IS_CONTAINER ? this.modelValue : undefined,
401
+ modelDependencies: this.modelValue,
407
402
  errors: ERRORS,
408
403
  errorsAll: IS_CONTAINER ? this.errorsAll : undefined,
409
404
  parentId,
410
405
  idPrefix: this.idPrefix,
411
406
  onUpdateData: ({ dataKeyByKeyId }) => this.onUpdateDataLocal({ item, dataKeyByKeyId }),
407
+ class: classColumn,
412
408
  ...item,
413
409
  change: ({ currentModel, id, item: _item, model, props, fullModel }) => this.onUpdateModelLocal({
414
410
  currentModel, id, item: _item, model, props, component: item, fullModel,
@@ -0,0 +1,114 @@
1
+ import {
2
+ h,
3
+ } from "vue";
4
+ import {
5
+ afterEach,
6
+ describe,
7
+ expect,
8
+ it,
9
+ jest,
10
+ } from "@jest/globals";
11
+ import {
12
+ mount,
13
+ } from "@vue/test-utils";
14
+
15
+ import AFieldset from "../AFieldset";
16
+ import {
17
+ AFormPluginOptions,
18
+ } from "../../../plugins/AFormPlugin";
19
+
20
+ jest.mock("../../../index", () => {
21
+ const {
22
+ computed,
23
+ h: hLocal,
24
+ ref,
25
+ } = require("vue");
26
+ const {
27
+ AFormPluginOptions: pluginOptions,
28
+ } = require("../../../plugins/AFormPlugin");
29
+
30
+ const componentStub = {
31
+ render() {
32
+ return hLocal("div");
33
+ },
34
+ };
35
+
36
+ return {
37
+ AElement: componentStub,
38
+ AErrorsText: componentStub,
39
+ AFormHelpText: componentStub,
40
+ AFormLabelDescription: componentStub,
41
+ AFormPluginOptions: pluginOptions,
42
+ AFormReadonly: componentStub,
43
+ AGroup: componentStub,
44
+ AUiTypes_typesContainer: ref({}),
45
+ UiAPI: props => ({
46
+ ariaDescribedbyLocal: computed(() => undefined),
47
+ errorsId: computed(() => `${ props.id }_errors`),
48
+ helpTextId: computed(() => `${ props.id }_help`),
49
+ htmlIdLocal: computed(() => props.htmlId || props.id),
50
+ isErrors: computed(() => false),
51
+ labelDescriptionId: computed(() => `${ props.id }_description`),
52
+ }),
53
+ UiCollapseAPI: () => ({
54
+ iconCollapse: computed(() => undefined),
55
+ initIsCollapsedLocal: () => {},
56
+ isCollapsedLocal: ref(false),
57
+ titleCollapse: computed(() => undefined),
58
+ toggleCollapse: () => {},
59
+ }),
60
+ UIExcludeRenderAttributesAPI: () => ({
61
+ attributesToExcludeFromRender: computed(() => ({})),
62
+ }),
63
+ UiStyleHideAPI: () => ({
64
+ componentStyleHide: computed(() => ""),
65
+ }),
66
+ UiTextAfterLabelAPI: () => ({
67
+ textAfterLabel: computed(() => ""),
68
+ }),
69
+ };
70
+ });
71
+
72
+ jest.mock("../../AUiComponents", () => ({
73
+ __esModule: true,
74
+ default: {},
75
+ }));
76
+
77
+ const COMPONENTS_ORIGINAL = AFormPluginOptions.components;
78
+
79
+ afterEach(() => {
80
+ AFormPluginOptions.components = COMPONENTS_ORIGINAL;
81
+ });
82
+
83
+ describe("AFieldset classColumn", () => {
84
+ it("applies classColumn to the child component without a wrapper element", () => {
85
+ AFormPluginOptions.components = {
86
+ testColumn: {
87
+ inheritAttrs: false,
88
+ render() {
89
+ return h("section", {
90
+ ...this.$attrs,
91
+ "data-testid": "child",
92
+ });
93
+ },
94
+ },
95
+ };
96
+
97
+ const wrapper = mount(AFieldset, {
98
+ props: {
99
+ children: [{
100
+ classColumn: "test_column",
101
+ id: "child",
102
+ type: "testColumn",
103
+ }],
104
+ modelValue: {},
105
+ },
106
+ });
107
+
108
+ const content = wrapper.get(".a_fieldset__content");
109
+ const child = content.get("[data-testid='child']");
110
+
111
+ expect(child.classes()).toContain("test_column");
112
+ expect(child.element.parentElement).toBe(content.element);
113
+ });
114
+ });
@@ -90,16 +90,16 @@ export default {
90
90
  required: false,
91
91
  default: "",
92
92
  },
93
- showErrors: {
94
- type: Boolean,
95
- required: false,
96
- default: true,
97
- },
98
- showRequiredText: {
99
- type: Boolean,
100
- required: false,
101
- default: true,
102
- },
93
+ showErrors: {
94
+ type: Boolean,
95
+ required: false,
96
+ default: true,
97
+ },
98
+ showRequiredText: {
99
+ type: Boolean,
100
+ required: false,
101
+ default: true,
102
+ },
103
103
  tag: {
104
104
  type: String,
105
105
  required: false,
@@ -182,10 +182,10 @@ export default {
182
182
  this.$slots.formPrepend() :
183
183
  "",
184
184
 
185
- this.showRequiredText && this.isRequiredLocal ?
186
- h(ARequired, {
187
- text: this.textRequired,
188
- }) :
185
+ this.showRequiredText && this.isRequiredLocal ?
186
+ h(ARequired, {
187
+ text: this.textRequired,
188
+ }) :
189
189
  "",
190
190
  this.$slots.formPrependAfterRequired ?
191
191
  this.$slots.formPrependAfterRequired() :
@@ -235,7 +235,7 @@ export default {
235
235
  alwaysTranslate: this.alwaysTranslate,
236
236
  modelValue: MODEL_VALUE,
237
237
  modelAll: IS_CONTAINER ? this.modelValueLocal : undefined,
238
- modelDependencies: IS_CONTAINER ? this.modelValueLocal : undefined,
238
+ modelDependencies: this.modelValueLocal,
239
239
  class: classColumn,
240
240
  errors: this.errors[item.id],
241
241
  errorsAll: IS_CONTAINER ? this.errors : undefined,
@@ -385,7 +385,7 @@ export default {
385
385
  alwaysTranslate: this.alwaysTranslate,
386
386
  modelAll: IS_CONTAINER ? this.modelAll : undefined,
387
387
  modelValue: MODEL_VALUE,
388
- modelDependencies: IS_CONTAINER ? this.modelValue : undefined,
388
+ modelDependencies: this.modelValue,
389
389
  errors: ERRORS,
390
390
  errorsAll: IS_CONTAINER ? this.errorsAll : undefined,
391
391
  parentId,