aloha-vue 2.53.0 → 2.55.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.53.0",
3
+ "version": "2.55.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",
@@ -11,6 +11,7 @@
11
11
  --a_dropdown_max_height: 31.25rem;
12
12
  --a_dropdown_padding_x: 0;
13
13
  --a_dropdown_padding_y: 0.5rem;
14
+ --a_dropdown_group_indent: 0.375rem;
14
15
  --a_dropdown_spacer: 0.125rem;
15
16
  --a_dropdown_font_size: 1rem;
16
17
  --a_dropdown_color: var(--a_color_text);
@@ -30,7 +31,7 @@
30
31
  --a_dropdown_item_padding_y: 0.25rem;
31
32
  --a_dropdown_header_color: #6c757d;
32
33
  --a_dropdown_header_padding_x: 1rem;
33
- --a_dropdown_header_padding_y: 0.5rem;
34
+ --a_dropdown_header_padding_y: 0.125rem;
34
35
  --a_select_menu_link_focus_color: var(--a_color_focus);
35
36
 
36
37
  z-index: var(--a_z_index_dropdown);
@@ -53,6 +54,15 @@
53
54
  .a_dropdown__menu_show {
54
55
  display: block;
55
56
  }
57
+ .a_dropdown__menu,
58
+ .a_dropdown__menu ul,
59
+ .a_dropdown__menu li {
60
+ list-style: none;
61
+ }
62
+ .a_dropdown__menu ul {
63
+ margin: 0;
64
+ padding: 0;
65
+ }
56
66
  .a_dropdown__item {
57
67
  display: block;
58
68
  width: 100%;
@@ -108,7 +118,68 @@
108
118
  margin-bottom: 0;
109
119
  font-size: .875rem;
110
120
  color: var(--a_dropdown_header_color);
121
+ font-weight: 600;
111
122
  white-space: nowrap;
112
123
  }
124
+ .a_dropdown__group {
125
+ margin: 0;
126
+ padding: 0;
127
+ }
128
+ .a_dropdown__group + .a_dropdown__group {
129
+ margin-top: 0;
130
+ }
131
+ .a_dropdown__group__label {
132
+ position: relative;
133
+ }
134
+ .a_dropdown__group__list {
135
+ margin-left: var(--a_dropdown_group_indent);
136
+ padding-left: var(--a_dropdown_group_indent);
137
+ }
138
+ .a_dropdown__group_level_0 > .a_dropdown__group__list {
139
+ margin-left: calc(var(--a_dropdown_group_indent) * 0.5);
140
+ padding-left: calc(var(--a_dropdown_group_indent) * 0.75);
141
+ }
142
+ .a_dropdown__group_level_1 > .a_dropdown__group__list {
143
+ margin-left: var(--a_dropdown_group_indent);
144
+ padding-left: calc(var(--a_dropdown_group_indent) * 0.875);
145
+ }
146
+ .a_dropdown__group_level_2 > .a_dropdown__group__list {
147
+ margin-left: calc(var(--a_dropdown_group_indent) * 0.875);
148
+ padding-left: var(--a_dropdown_group_indent);
149
+ }
150
+ .a_dropdown__group_level_3 > .a_dropdown__group__list,
151
+ .a_dropdown__group_level_4 > .a_dropdown__group__list,
152
+ .a_dropdown__group_level_5 > .a_dropdown__group__list {
153
+ margin-left: calc(var(--a_dropdown_group_indent) * 0.875);
154
+ padding-left: var(--a_dropdown_group_indent);
155
+ }
156
+ .a_dropdown__group__list > li,
157
+ .a_dropdown__group__list > .a_dropdown__group {
158
+ margin-top: 0;
159
+ }
160
+ .a_dropdown__group__list > li:first-child,
161
+ .a_dropdown__group__list > .a_dropdown__group:first-child {
162
+ margin-top: 0;
163
+ }
164
+ .a_dropdown__group_level_0 > .a_dropdown__group__label {
165
+ padding-top: 0.0625rem;
166
+ }
167
+ .a_dropdown__group_level_0:first-child > .a_dropdown__group__label {
168
+ padding-top: var(--a_dropdown_header_padding_y);
169
+ }
170
+ .a_dropdown__group_level_1 > .a_dropdown__group__label {
171
+ padding-left: calc(var(--a_dropdown_header_padding_x) + 0.0625rem);
172
+ }
173
+ .a_dropdown__group_level_2 > .a_dropdown__group__label {
174
+ padding-left: calc(var(--a_dropdown_header_padding_x) + 0.125rem);
175
+ }
176
+ .a_dropdown__group_level_3 > .a_dropdown__group__label,
177
+ .a_dropdown__group_level_4 > .a_dropdown__group__label,
178
+ .a_dropdown__group_level_5 > .a_dropdown__group__label {
179
+ padding-left: calc(var(--a_dropdown_header_padding_x) + 0.1875rem);
180
+ }
181
+ .a_dropdown__group__list .a_dropdown__item {
182
+ padding-left: calc(var(--a_dropdown_item_padding_x) + 0.0625rem);
183
+ }
113
184
 
114
185
 
@@ -1,198 +1,207 @@
1
- import {
2
- computed,
3
- h,
4
- } from "vue";
5
-
6
- import AAccordionItem from "./AAccordionItem/AAccordionItem";
7
-
8
- import DataAPI from "./compositionAPI/DataAPI";
9
- import IndexesForOpenAPI from "./compositionAPI/IndexesForOpenAPI";
10
- import ToggleAPI from "./compositionAPI/ToggleAPI";
11
-
12
- import {
13
- AKeyId,
14
- } from "../const/AKeys";
15
- import {
16
- uniqueId,
17
- } from "lodash-es";
18
-
19
- export default {
20
- name: "AAccordion",
21
- provide() {
22
- return {
23
- classBody: computed(() => this.classBody),
24
- classButton: computed(() => this.classButton),
25
- classHeader: computed(() => this.classHeader),
26
- disabled: computed(() => this.disabled),
27
- id: computed(() => this.id),
28
- idsForOpen: computed(() => this.idsForOpen),
29
- isCaret: computed(() => this.isCaret),
30
- keyChildren: computed(() => this.keyChildren),
31
- keyClassBody: computed(() => this.keyClassBody),
32
- keyClassButton: computed(() => this.keyClassButton),
33
- keyClassHeader: computed(() => this.keyClassHeader),
34
- keyContent: computed(() => this.keyContent),
35
- keyIsRender: computed(() => this.keyIsRender),
36
- keyIsRenderBodyByFirstOpen: computed(() => this.keyIsRenderBodyByFirstOpen),
37
- keyLabel: computed(() => this.keyLabel),
38
- readonly: computed(() => this.readonly),
39
- withGap: computed(() => this.withGap),
40
- toggle: this.toggleLocal,
41
- };
42
- },
43
- props: {
44
- alwaysOpen: {
45
- type: Boolean,
46
- required: false,
47
- },
48
- classBody: {
49
- type: [String, Object],
50
- required: false,
51
- default: "",
52
- },
53
- classButton: {
54
- type: [String, Object],
55
- required: false,
56
- default: undefined,
57
- },
58
- classHeader: {
59
- type: [String, Object],
60
- required: false,
61
- default: "",
62
- },
63
- disabled: {
64
- type: Boolean,
65
- required: false,
66
- },
67
- id: {
68
- type: String,
69
- required: false,
70
- default: uniqueId("accordion_"),
71
- },
72
- idsForOpenDefault: {
73
- type: Array,
74
- required: false,
75
- default: () => [],
76
- },
77
- isCaret: {
78
- type: Boolean,
79
- required: false,
80
- default: true,
81
- },
82
- data: {
83
- type: Array,
84
- required: true,
85
- },
86
- keyClassBody: {
87
- type: String,
88
- required: false,
89
- default: "classBody",
90
- },
91
- keyClassButton: {
92
- type: String,
93
- required: false,
94
- default: "classButton",
95
- },
96
- keyClassHeader: {
97
- type: String,
98
- required: false,
99
- default: "classHeader",
100
- },
101
- keyContent: {
102
- type: String,
103
- required: false,
104
- default: "content",
105
- },
106
- keyId: {
107
- type: String,
108
- required: false,
109
- default: undefined,
110
- },
111
- keyIsRender: {
112
- type: String,
113
- required: false,
114
- default: "isRender",
115
- },
116
- keyIsRenderBodyByFirstOpen: {
117
- type: String,
118
- required: false,
119
- default: "isRenderBodyByFirstOpen",
120
- },
121
- keyLabel: {
122
- type: String,
123
- required: false,
124
- default: "label",
125
- },
126
- keyChildren: {
127
- type: String,
128
- required: false,
129
- default: "children",
130
- },
131
- prevent: {
132
- type: Boolean,
133
- required: false,
134
- },
135
- readonly: {
136
- type: Boolean,
137
- required: false,
138
- },
139
- stop: {
140
- type: Boolean,
141
- required: false,
142
- },
143
- withGap: {
144
- type: Boolean,
145
- required: false,
146
- },
147
- indexesForOpen: {
148
- type: Array,
149
- required: false,
150
- default: () => [],
151
- },
152
- },
153
- emits: [
154
- "toggle",
155
- ],
156
- setup(props, context) {
157
- const {
158
- idsForOpen,
159
- initIdsForOpen,
160
- toggleLocal,
161
- } = ToggleAPI(props, context);
162
-
163
- const {
164
- dataWithIds,
165
- } = DataAPI(props);
166
-
167
- const {
168
- initIdsFromIndexesForOpen,
169
- } = IndexesForOpenAPI(props, {
170
- idsForOpen,
171
- dataWithIds,
172
- });
173
-
174
- initIdsForOpen();
175
- initIdsFromIndexesForOpen();
176
-
177
- return {
178
- dataWithIds,
179
- idsForOpen,
180
- toggleLocal,
181
- };
182
- },
183
- render() {
184
- return h("div", {
185
- class: ["a_accordion"],
186
- }, [
187
- this.dataWithIds.map((item, itemIndex) => {
188
- return h(AAccordionItem, {
189
- key: item[AKeyId],
190
- item,
191
- itemIndex,
192
- isParentOpen: true,
193
- keyId: this.keyId,
194
- }, this.$slots);
195
- }),
196
- ]);
197
- },
198
- };
1
+ import {
2
+ computed,
3
+ h,
4
+ watch,
5
+ } from "vue";
6
+
7
+ import AAccordionItem from "./AAccordionItem/AAccordionItem";
8
+
9
+ import DataAPI from "./compositionAPI/DataAPI";
10
+ import IndexesForOpenAPI from "./compositionAPI/IndexesForOpenAPI";
11
+ import ToggleAPI from "./compositionAPI/ToggleAPI";
12
+
13
+ import {
14
+ AKeyId,
15
+ } from "../const/AKeys";
16
+ import {
17
+ uniqueId,
18
+ } from "lodash-es";
19
+
20
+ export default {
21
+ name: "AAccordion",
22
+ provide() {
23
+ return {
24
+ alwaysOpen: computed(() => this.alwaysOpen),
25
+ classBody: computed(() => this.classBody),
26
+ classButton: computed(() => this.classButton),
27
+ classHeader: computed(() => this.classHeader),
28
+ disabled: computed(() => this.disabled),
29
+ id: computed(() => this.id),
30
+ idsForOpen: computed(() => this.idsForOpen),
31
+ isCaret: computed(() => this.isCaret),
32
+ keyChildren: computed(() => this.keyChildren),
33
+ keyClassBody: computed(() => this.keyClassBody),
34
+ keyClassButton: computed(() => this.keyClassButton),
35
+ keyClassHeader: computed(() => this.keyClassHeader),
36
+ keyContent: computed(() => this.keyContent),
37
+ keyIsRender: computed(() => this.keyIsRender),
38
+ keyIsRenderBodyByFirstOpen: computed(() => this.keyIsRenderBodyByFirstOpen),
39
+ keyLabel: computed(() => this.keyLabel),
40
+ oneItemAlwaysOpen: computed(() => this.oneItemAlwaysOpen),
41
+ readonly: computed(() => this.readonly),
42
+ withGap: computed(() => this.withGap),
43
+ toggle: this.toggleLocal,
44
+ };
45
+ },
46
+ props: {
47
+ alwaysOpen: {
48
+ type: Boolean,
49
+ required: false,
50
+ default: false,
51
+ },
52
+ classBody: {
53
+ type: [String, Object],
54
+ required: false,
55
+ default: "",
56
+ },
57
+ classButton: {
58
+ type: [String, Object],
59
+ required: false,
60
+ default: undefined,
61
+ },
62
+ classHeader: {
63
+ type: [String, Object],
64
+ required: false,
65
+ default: "",
66
+ },
67
+ disabled: {
68
+ type: Boolean,
69
+ required: false,
70
+ },
71
+ id: {
72
+ type: String,
73
+ required: false,
74
+ default: uniqueId("accordion_"),
75
+ },
76
+ idsForOpenDefault: {
77
+ type: Array,
78
+ required: false,
79
+ default: () => [],
80
+ },
81
+ isCaret: {
82
+ type: Boolean,
83
+ required: false,
84
+ default: true,
85
+ },
86
+ data: {
87
+ type: Array,
88
+ required: true,
89
+ },
90
+ keyClassBody: {
91
+ type: String,
92
+ required: false,
93
+ default: "classBody",
94
+ },
95
+ keyClassButton: {
96
+ type: String,
97
+ required: false,
98
+ default: "classButton",
99
+ },
100
+ keyClassHeader: {
101
+ type: String,
102
+ required: false,
103
+ default: "classHeader",
104
+ },
105
+ keyContent: {
106
+ type: String,
107
+ required: false,
108
+ default: "content",
109
+ },
110
+ keyId: {
111
+ type: String,
112
+ required: false,
113
+ default: undefined,
114
+ },
115
+ keyIsRender: {
116
+ type: String,
117
+ required: false,
118
+ default: "isRender",
119
+ },
120
+ keyIsRenderBodyByFirstOpen: {
121
+ type: String,
122
+ required: false,
123
+ default: "isRenderBodyByFirstOpen",
124
+ },
125
+ keyLabel: {
126
+ type: String,
127
+ required: false,
128
+ default: "label",
129
+ },
130
+ oneItemAlwaysOpen: {
131
+ type: Boolean,
132
+ required: false,
133
+ default: false,
134
+ },
135
+ keyChildren: {
136
+ type: String,
137
+ required: false,
138
+ default: "children",
139
+ },
140
+ prevent: {
141
+ type: Boolean,
142
+ required: false,
143
+ },
144
+ readonly: {
145
+ type: Boolean,
146
+ required: false,
147
+ },
148
+ stop: {
149
+ type: Boolean,
150
+ required: false,
151
+ },
152
+ withGap: {
153
+ type: Boolean,
154
+ required: false,
155
+ },
156
+ indexesForOpen: {
157
+ type: Array,
158
+ required: false,
159
+ default: () => [],
160
+ },
161
+ },
162
+ emits: [
163
+ "toggle",
164
+ ],
165
+ setup(props, context) {
166
+ const {
167
+ idsForOpen,
168
+ initIdsForOpen,
169
+ toggleLocal,
170
+ } = ToggleAPI(props, context);
171
+
172
+ const {
173
+ dataWithIds,
174
+ } = DataAPI(props);
175
+
176
+ const {
177
+ initIdsFromIndexesForOpen,
178
+ } = IndexesForOpenAPI(props, {
179
+ idsForOpen,
180
+ dataWithIds,
181
+ });
182
+
183
+ initIdsForOpen();
184
+ initIdsFromIndexesForOpen();
185
+
186
+ return {
187
+ dataWithIds,
188
+ idsForOpen,
189
+ toggleLocal,
190
+ };
191
+ },
192
+ render() {
193
+ return h("div", {
194
+ class: ["a_accordion"],
195
+ }, [
196
+ this.dataWithIds.map((item, itemIndex) => {
197
+ return h(AAccordionItem, {
198
+ key: item[AKeyId],
199
+ item,
200
+ itemIndex,
201
+ isParentOpen: true,
202
+ keyId: this.keyId,
203
+ }, this.$slots);
204
+ }),
205
+ ]);
206
+ },
207
+ };
@@ -17,12 +17,14 @@ export default function AttributesAPI(props, {
17
17
  }) {
18
18
  const item = toRef(props, "item");
19
19
 
20
+ const alwaysOpen = inject("alwaysOpen");
20
21
  const classButton = inject("classButton");
21
22
  const disabled = inject("disabled");
22
23
  const id = inject("id");
23
24
  const isCaret = inject("isCaret");
24
25
  const keyContent = inject("keyContent");
25
26
  const keyLabel = inject("keyLabel");
27
+ const oneItemAlwaysOpen = inject("oneItemAlwaysOpen");
26
28
  const readonly = inject("readonly");
27
29
  const withGap = inject("withGap");
28
30
 
@@ -41,12 +43,16 @@ export default function AttributesAPI(props, {
41
43
  return readonly.value || item.value.readonly;
42
44
  });
43
45
 
46
+ const isDisabledByOneItemAlwaysOpen = computed(() => {
47
+ return !alwaysOpen.value && oneItemAlwaysOpen.value && isOpen.value;
48
+ });
49
+
44
50
  const idForCollapse = computed(() => {
45
51
  return `${ id.value }_${ currentId.value }`;
46
52
  });
47
53
 
48
54
  const buttonTag = computed(() => {
49
- return readonlyLocal.value ? "div" : "a";
55
+ return readonlyLocal.value || isDisabledByOneItemAlwaysOpen.value ? "div" : "a";
50
56
  });
51
57
 
52
58
  const buttonAttributes = computed(() => {
@@ -61,12 +67,17 @@ export default function AttributesAPI(props, {
61
67
  };
62
68
 
63
69
  if (!readonlyLocal.value) {
64
- ATTRIBUTES.ariaExpanded = isOpen.value;
70
+ ATTRIBUTES["aria-expanded"] = isOpen.value;
65
71
  ATTRIBUTES["aria-controls"] = idForCollapse.value;
66
- ATTRIBUTES.rolw = "button";
67
- ATTRIBUTES.tabindex = 0;
68
- ATTRIBUTES.disabled = disabledLocal.value;
69
- ATTRIBUTES.onClick = toggleLocal;
72
+ ATTRIBUTES.role = "button";
73
+
74
+ if (isDisabledByOneItemAlwaysOpen.value) {
75
+ ATTRIBUTES["aria-disabled"] = true;
76
+ } else {
77
+ ATTRIBUTES.tabindex = 0;
78
+ ATTRIBUTES.disabled = disabledLocal.value;
79
+ ATTRIBUTES.onClick = toggleLocal;
80
+ }
70
81
  }
71
82
 
72
83
  return ATTRIBUTES;
@@ -9,6 +9,7 @@ import {
9
9
  } from "../../../const/AKeys";
10
10
  import {
11
11
  cloneDeep,
12
+ filter,
12
13
  } from "lodash-es";
13
14
 
14
15
  export default function ToggleAPI(props) {
@@ -68,7 +69,9 @@ export default function ToggleAPI(props) {
68
69
 
69
70
  const closeItemIfOpen = () => {
70
71
  if (isOpen.value && keyId.value) {
71
- toggleLocal();
72
+ idsForOpen.value = filter(idsForOpen.value, id => {
73
+ return id !== currentId.value;
74
+ });
72
75
  }
73
76
  };
74
77