aloha-vue 1.0.235 → 1.0.237

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 (27) hide show
  1. package/docs/src/components/TheMenu/TheMenu.js +8 -0
  2. package/docs/src/main.js +12 -4
  3. package/docs/src/router/index.js +5 -0
  4. package/docs/src/views/PageDropdown/PageDropdown.pug +2 -4
  5. package/docs/src/views/PageGroupButtonDropdown/PageGroupButtonDropdown.js +52 -0
  6. package/docs/src/views/PageGroupButtonDropdown/PageGroupButtonDropdown.pug +8 -0
  7. package/docs/src/views/PageGroupButtonDropdown/PageGroupButtonDropdown.vue +2 -0
  8. package/docs/src/views/PageModal/PageModal.js +2 -0
  9. package/docs/src/views/PageModal/PageModal.pug +5 -2
  10. package/package.json +1 -1
  11. package/src/AButton/AButton.js +1 -0
  12. package/src/ADropdown/ADropdown.js +158 -32
  13. package/src/ADropdown/compositionAPI/ActionsAPI.js +4 -21
  14. package/src/ADropdown/compositionAPI/AttributesAPI.js +10 -13
  15. package/src/ADropdown/compositionAPI/PopoverAPI.js +1 -1
  16. package/src/AGroupButtonDropdown/AGroupButtonDropdown.js +85 -0
  17. package/src/AGroupButtonDropdown/AGroupButtonDropdownItem/AGroupButtonDropdownItem.js +91 -0
  18. package/src/AGroupButtonDropdown/AGroupButtonDropdownItem/compositionAPI/DropdownAPI.js +27 -0
  19. package/src/AGroupButtonDropdown/compositionAPI/ActionsAPI.js +106 -0
  20. package/src/compositionAPI/AMobileAPI.js +16 -0
  21. package/src/plugins/AGroupButtonDropdownPlugin.js +24 -0
  22. package/src/plugins/AMobilePlugin.js +25 -0
  23. package/src/styles/components/AButton.scss +3 -8
  24. package/src/styles/components/AGroupButtonDropdown.scss +5 -0
  25. package/src/styles/components/ALink.scss +3 -8
  26. package/src/styles/styles.scss +8 -0
  27. package/src/utils/actions.js +43 -0
@@ -212,6 +212,14 @@ export default {
212
212
  },
213
213
  icon: "Cog",
214
214
  },
215
+ {
216
+ id: "GroupButtonDropdown",
217
+ label: "GroupButtonDropdown",
218
+ to: {
219
+ name: "PageGroupButtonDropdown",
220
+ },
221
+ icon: "Cog",
222
+ },
215
223
  {
216
224
  id: "tabs",
217
225
  label: "Tabs",
package/docs/src/main.js CHANGED
@@ -3,7 +3,8 @@ import { createApp } from "vue";
3
3
  import store from "./store/index";
4
4
  import router from "./router/index";
5
5
  import AI18nPlugin from "../../src/plugins/AI18nPlugin";
6
- // import alohaPlugin from "../src/plugins/alohaPlugin";
6
+ import AMobilePlugin from "../../src/plugins/AMobilePlugin";
7
+ import AGroupButtonDropdownPlugin from "../../src/plugins/AGroupButtonDropdownPlugin";
7
8
  import AIconPlugin from "../../src/plugins/AIconPlugin";
8
9
  import AModalPlugin from "../../src/plugins/AModalPlugin";
9
10
  import mainIcons from "./mainIcons";
@@ -28,14 +29,21 @@ const TRANSLATIONS = {
28
29
  };
29
30
  APP.use(AI18nPlugin, TRANSLATIONS, "de");
30
31
  APP.use(AIconPlugin, mainIcons);
32
+ APP.use(AMobilePlugin, {
33
+ breakpoint: 991,
34
+ });
31
35
  APP.use(AModalPlugin, {
32
36
  propsDefault: {
33
37
  closeButtonClass: "a_btn a_btn_link",
34
38
  },
35
39
  });
36
- // APP.use(alohaPlugin, {
37
- // framework: "bootstrap",
38
- // });
40
+ APP.use(AGroupButtonDropdownPlugin, {
41
+ propsDefault: {
42
+ dropdownAttributes: {
43
+ buttonText: "Weitere Aktionen",
44
+ },
45
+ },
46
+ });
39
47
  APP.config.unwrapInjectedRef = true;
40
48
  APP.directive("SafeHtml", ASafeHtml);
41
49
  APP.use(store).use(router).mount("#app");
@@ -149,6 +149,11 @@ const ROUTES = [
149
149
  name: "PageWizard",
150
150
  component: () => import(/* webpackChunkName: "PageWizard" */ "../views/PageWizard/PageWizard.vue"),
151
151
  },
152
+ {
153
+ path: "/group-button-dropdown",
154
+ name: "PageGroupButtonDropdown",
155
+ component: () => import(/* webpackChunkName: "PageGroupButtonDropdown" */ "../views/PageGroupButtonDropdown/PageGroupButtonDropdown.vue"),
156
+ },
152
157
  {
153
158
  // If the routing configuration '*' reports an error, replace it with '/: catchAll(. *)'
154
159
  // caught Error: Catch all routes ("*") must now be defined using a param with a custom regexp
@@ -31,15 +31,13 @@ div
31
31
  button-class="a_btn a_btn_primary"
32
32
  :is-render-default="true"
33
33
  :actions="dropdownActions"
34
+ button-text="Weitere Aktionen"
34
35
  )
35
- template(
36
- v-slot:button
37
- )
38
- span Weitere Aktionen
39
36
 
40
37
  a-dropdown.ml_3(
41
38
  button-class="a_btn a_btn_primary"
42
39
  :is-render-default="true"
40
+
43
41
  )
44
42
  template(
45
43
  v-slot:button
@@ -0,0 +1,52 @@
1
+ import AGroupButtonDropdown from "../../../../src/AGroupButtonDropdown/AGroupButtonDropdown";
2
+
3
+ export default {
4
+ name: "PageGroupButtonDropdown",
5
+ components: {
6
+ AGroupButtonDropdown,
7
+ },
8
+ setup() {
9
+ const actions = [
10
+ {
11
+ text: "Actions 0",
12
+ type: "button",
13
+ callback: () => {},
14
+ isHidden: true,
15
+ },
16
+ {
17
+ text: "Actions 1",
18
+ type: "button",
19
+ callback: () => {},
20
+ disabled: false,
21
+ },
22
+ {
23
+ type: "divider",
24
+ },
25
+ {
26
+ type: "divider",
27
+ },
28
+ {
29
+ text: "Actions 2",
30
+ type: "button",
31
+ callback: () => {},
32
+ },
33
+ {
34
+ type: "link",
35
+ text: "Link 1",
36
+ href: "#",
37
+ },
38
+ {
39
+ type: "divider",
40
+ },
41
+ {
42
+ type: "link",
43
+ text: "Link 2",
44
+ href: "#",
45
+ },
46
+ ];
47
+
48
+ return {
49
+ actions,
50
+ };
51
+ },
52
+ };
@@ -0,0 +1,8 @@
1
+ div
2
+ h1 AGroupButtonDropdown
3
+
4
+ a-group-button-dropdown(
5
+ :actions="actions"
6
+ :index-first-dropdown-action="2"
7
+ )
8
+
@@ -0,0 +1,2 @@
1
+ <template lang="pug" src="./PageGroupButtonDropdown.pug"></template>
2
+ <script src="./PageGroupButtonDropdown.js"></script>
@@ -1,3 +1,4 @@
1
+ import AButton from "../../../../src/AButton/AButton";
1
2
  import AModal from "../../../../src/AModal/AModal";
2
3
 
3
4
  import AConfirmAPI from "../../../../src/compositionAPI/AConfirmAPI";
@@ -5,6 +6,7 @@ import AConfirmAPI from "../../../../src/compositionAPI/AConfirmAPI";
5
6
  export default {
6
7
  name: "PageModal",
7
8
  components: {
9
+ AButton,
8
10
  AModal,
9
11
  },
10
12
  setup() {
@@ -1,10 +1,13 @@
1
1
  div
2
2
  h1 AModal
3
- button.a_btn.a_btn_primary(
3
+ a-button.a_btn.a_btn_primary(
4
4
  id="btn_modal"
5
5
  type="button"
6
+ text="Open Modal"
7
+ icon="Cog"
8
+ :loading="true"
6
9
  @click="openModal"
7
- ) Open Modal
10
+ )
8
11
 
9
12
  a-modal(
10
13
  v-if="isModalOpen"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aloha-vue",
3
3
  "description": "Project aloha",
4
- "version": "1.0.235",
4
+ "version": "1.0.237",
5
5
  "author": "Ilia Brykin",
6
6
  "scripts": {
7
7
  "build-icons": "node scriptsNode/iconsSvgToJs.js bootstrap3 && node scriptsNode/iconsSvgToJs.js bootstrap-1-9-1"
@@ -250,6 +250,7 @@ export default {
250
250
  this.loadingClass,
251
251
  ],
252
252
  }),
253
+ this.$slots.buttonAppend && this.$slots.buttonAppend(),
253
254
  ]);
254
255
  },
255
256
  };
@@ -1,8 +1,10 @@
1
1
  import {
2
- h, onBeforeUnmount,
2
+ h,
3
+ onBeforeUnmount,
3
4
  Teleport,
4
5
  } from "vue";
5
6
 
7
+ import AButton from "../AButton/AButton";
6
8
  import ADropdownAction from "./ADropdownAction/ADropdownAction";
7
9
  import AIcon from "../AIcon/AIcon";
8
10
  import ATranslation from "../ATranslation/ATranslation";
@@ -22,6 +24,7 @@ import {
22
24
 
23
25
  export default {
24
26
  name: "ADropdown",
27
+ inheritAttrs: false,
25
28
  components: {
26
29
  ATranslation,
27
30
  },
@@ -41,6 +44,26 @@ export default {
41
44
  required: false,
42
45
  default: () => ({}),
43
46
  },
47
+ buttonText: {
48
+ type: [String, Number],
49
+ required: false,
50
+ default: undefined,
51
+ },
52
+ buttonTextScreenReader: {
53
+ type: String,
54
+ required: false,
55
+ default: undefined,
56
+ },
57
+ buttonTextAriaHidden: {
58
+ type: Boolean,
59
+ required: false,
60
+ default: false,
61
+ },
62
+ buttonTextClass: {
63
+ type: String,
64
+ required: false,
65
+ default: undefined,
66
+ },
44
67
  buttonClass: {
45
68
  type: [String, Object],
46
69
  required: false,
@@ -51,6 +74,76 @@ export default {
51
74
  required: false,
52
75
  default: "button",
53
76
  },
77
+ buttonTitle: {
78
+ type: String,
79
+ required: false,
80
+ default: undefined,
81
+ },
82
+ buttonIsTitleHtml: {
83
+ type: Boolean,
84
+ required: false,
85
+ },
86
+ buttonTitlePlacement: {
87
+ type: String,
88
+ required: false,
89
+ default: "top",
90
+ validator: value => ["top", "left", "bottom", "right"].indexOf(value) !== -1,
91
+ },
92
+ buttonLoading: {
93
+ type: Boolean,
94
+ required: false,
95
+ default: false,
96
+ },
97
+ buttonLoadingClass: {
98
+ type: [String, Object],
99
+ required: false,
100
+ default: "a_spinner_small",
101
+ },
102
+ buttonLoadingAlign: {
103
+ type: String,
104
+ required: false,
105
+ default: "right",
106
+ validator: value => ["right", "left"].indexOf(value) !== -1,
107
+ },
108
+ buttonIcon: {
109
+ type: String,
110
+ required: false,
111
+ default: undefined,
112
+ },
113
+ buttonIconAlign: {
114
+ type: String,
115
+ required: false,
116
+ default: "left",
117
+ validator: value => ["right", "left"].indexOf(value) !== -1,
118
+ },
119
+ buttonIconClass: {
120
+ type: String,
121
+ required: false,
122
+ default: undefined,
123
+ },
124
+ buttonIconAttributes: {
125
+ type: Object,
126
+ required: false,
127
+ default: () => ({}),
128
+ },
129
+ buttonIconTag: {
130
+ type: String,
131
+ required: false,
132
+ default: undefined,
133
+ },
134
+ buttonPrevent: {
135
+ type: Boolean,
136
+ required: false,
137
+ },
138
+ buttonStop: {
139
+ type: Boolean,
140
+ required: false,
141
+ },
142
+ extraTranslate: {
143
+ type: Object,
144
+ required: false,
145
+ default: undefined,
146
+ },
54
147
  classForTooltipInner: {
55
148
  type: [String, Object],
56
149
  required: false,
@@ -161,6 +254,8 @@ export default {
161
254
  });
162
255
 
163
256
  const {
257
+ idLocal,
258
+ buttonAttributesDisabled,
164
259
  buttonAttributesLocal,
165
260
  dropdownAttributesLocal,
166
261
  isMenuRendered,
@@ -183,13 +278,18 @@ export default {
183
278
 
184
279
  return {
185
280
  actionsFiltered,
281
+ buttonAttributesDisabled,
186
282
  buttonAttributesLocal,
187
283
  buttonWidth,
188
284
  dropdownAttributesLocal,
189
285
  dropdownButtonRef,
190
286
  dropdownRef,
191
287
  hasActions,
288
+ idLocal,
192
289
  isMenuRendered,
290
+ onToggle,
291
+ onKeydown,
292
+ statusExpanded,
193
293
  };
194
294
  },
195
295
  render() {
@@ -198,39 +298,65 @@ export default {
198
298
  !this.$slots.dropdown) {
199
299
  return "";
200
300
  }
201
- return h(
202
- this.tag,
203
- {
204
- class: "a_dropdown",
205
- },
206
- [
207
- h(this.buttonTag, this.buttonAttributesLocal, [
208
- this.$slots.button && this.$slots.button(),
209
- this.isCaret && h(AIcon, {
301
+ return [
302
+ h(AButton, {
303
+ ref: "dropdownButtonRef",
304
+ ...this.$attrs,
305
+ id: this.idLocal,
306
+ tag: this.buttonTag,
307
+ class: this.buttonClass,
308
+ text: this.buttonText,
309
+ textScreenReader: this.buttonTextScreenReader,
310
+ textAriaHidden: this.buttonTextAriaHidden,
311
+ textClass: this.buttonTextClass,
312
+ title: this.buttonTitle,
313
+ isTitleHtml: this.buttonIsTitleHtml,
314
+ titlePlacement: this.buttonTitlePlacement,
315
+ loading: this.buttonLoading,
316
+ loadingClass: this.buttonLoadingClass,
317
+ loadingAlign: this.buttonLoadingAlign,
318
+ icon: this.buttonIcon,
319
+ iconAlign: this.buttonIconAlign,
320
+ iconClass: this.buttonIconClass,
321
+ iconAttributes: this.buttonIconAttributes,
322
+ iconTag: this.buttonIconTag,
323
+ prevent: this.buttonPrevent,
324
+ stop: this.buttonStop,
325
+ extraTranslate: this.extraTranslate,
326
+ attributes: this.buttonAttributesLocal,
327
+ ...this.buttonAttributesDisabled,
328
+ onClick: this.onToggle,
329
+ onKeydown: this.onKeydown,
330
+ }, {
331
+ default: () => {
332
+ return this.$slots.button && this.$slots.button();
333
+ },
334
+ buttonAppend: () => {
335
+ return this.isCaret && h(AIcon, {
210
336
  class: "a_dropdown__caret",
211
337
  icon: "ChevronDown",
212
- }),
213
- ]),
214
- h(Teleport, {
215
- to: "body",
216
- }, [
217
- this.isMenuRendered && h("div", null, [
218
- h(
219
- this.dropdownTag,
220
- this.dropdownAttributesLocal,
221
- [
222
- this.$slots.dropdown && this.$slots.dropdown(),
223
- this.hasActions && this.actionsFiltered.map((action, actionIndex) => {
224
- return h(ADropdownAction, {
225
- key: actionIndex,
226
- action,
227
- }, this.$slots);
228
- }),
229
- ],
230
- ),
231
- ]),
338
+ });
339
+ },
340
+ }),
341
+ h(Teleport, {
342
+ to: "body",
343
+ }, [
344
+ this.isMenuRendered && h("div", null, [
345
+ h(
346
+ this.dropdownTag,
347
+ this.dropdownAttributesLocal,
348
+ [
349
+ this.$slots.dropdown && this.$slots.dropdown(),
350
+ this.hasActions && this.actionsFiltered.map((action, actionIndex) => {
351
+ return h(ADropdownAction, {
352
+ key: actionIndex,
353
+ action,
354
+ }, this.$slots);
355
+ }),
356
+ ],
357
+ ),
232
358
  ]),
233
- ],
234
- );
359
+ ]),
360
+ ];
235
361
  },
236
362
  };
@@ -4,33 +4,16 @@ import {
4
4
  } from "vue";
5
5
 
6
6
  import {
7
- filter,
8
- forEach,
9
- last,
10
- } from "lodash-es";
7
+ filterActionsHiddenAndDivider,
8
+ } from "../../utils/actions";
11
9
 
12
10
  export default function ActionsAPI(props) {
13
11
  const actions = toRef(props, "actions");
14
12
 
15
13
  const actionsFiltered = computed(() => {
16
- const ACTIONS_FILTERED = filter(actions.value, action => {
17
- return !action.isHidden;
14
+ return filterActionsHiddenAndDivider({
15
+ actions: actions.value,
18
16
  });
19
-
20
- const ACTIONS_DIVIDER_FILTERED = [];
21
- forEach(ACTIONS_FILTERED, action => {
22
- if (action.type !== "divider" ||
23
- (ACTIONS_DIVIDER_FILTERED.length > 0 &&
24
- last(ACTIONS_DIVIDER_FILTERED).type !== "divider")) {
25
- ACTIONS_DIVIDER_FILTERED.push(action);
26
- }
27
- });
28
- const LAST_ACTION = last(ACTIONS_DIVIDER_FILTERED);
29
- if (LAST_ACTION && LAST_ACTION.type === "divider") {
30
- ACTIONS_DIVIDER_FILTERED.pop();
31
- }
32
-
33
- return ACTIONS_DIVIDER_FILTERED;
34
17
  });
35
18
 
36
19
  const hasActions = computed(() => {
@@ -10,11 +10,8 @@ import {
10
10
 
11
11
  export default function AttributesAPI(props, {
12
12
  statusExpanded = ref(false),
13
- onToggle = () => {},
14
- onKeydown = () => {},
15
13
  }) {
16
14
  const buttonAttributes = toRef(props, "buttonAttributes");
17
- const buttonClass = toRef(props, "buttonClass");
18
15
  const buttonTag = toRef(props, "buttonTag");
19
16
  const disabled = toRef(props, "disabled");
20
17
  const dropdownAttributes = toRef(props, "dropdownAttributes");
@@ -29,27 +26,25 @@ export default function AttributesAPI(props, {
29
26
 
30
27
  const buttonAttributesLocal = computed(() => {
31
28
  const BUTTON_ATTRIBUTES = cloneDeep(buttonAttributes.value);
32
- BUTTON_ATTRIBUTES.id = idLocal.value;
33
- BUTTON_ATTRIBUTES.ref = "dropdownButtonRef";
34
29
  BUTTON_ATTRIBUTES["aria-haspopup"] = "true";
35
30
  BUTTON_ATTRIBUTES["aria-expanded"] = statusExpanded.value;
36
- if (buttonClass.value) {
37
- BUTTON_ATTRIBUTES.class = buttonClass.value;
38
- }
39
- BUTTON_ATTRIBUTES.onClick = onToggle;
40
- BUTTON_ATTRIBUTES.onKeydown = onKeydown;
41
31
 
42
32
  if (buttonTag.value === "button") {
43
33
  BUTTON_ATTRIBUTES.type = BUTTON_ATTRIBUTES.type || "button";
44
34
  }
35
+ return BUTTON_ATTRIBUTES;
36
+ });
37
+
38
+ const buttonAttributesDisabled = computed(() => {
39
+ const ATTRIBUTES = {};
45
40
  if (disabled.value) {
46
41
  if (buttonTag.value === "button") {
47
- BUTTON_ATTRIBUTES.disabled = true;
42
+ ATTRIBUTES.disabled = true;
48
43
  } else if (buttonTag.value === "a") {
49
- BUTTON_ATTRIBUTES["aria-disabled"] = "true";
44
+ ATTRIBUTES.ariaDisabled = true;
50
45
  }
51
46
  }
52
- return BUTTON_ATTRIBUTES;
47
+ return ATTRIBUTES;
53
48
  });
54
49
 
55
50
  const dropdownAttributesLocal = computed(() => {
@@ -70,6 +65,8 @@ export default function AttributesAPI(props, {
70
65
  });
71
66
 
72
67
  return {
68
+ idLocal,
69
+ buttonAttributesDisabled,
73
70
  buttonAttributesLocal,
74
71
  dropdownAttributesLocal,
75
72
  isMenuRendered,
@@ -17,7 +17,7 @@ export default function PopoverAPI(props, {
17
17
  const openPopoverWithPopperjs = () => {
18
18
  if (!popper.value) {
19
19
  popper.value = createPopper(
20
- dropdownButtonRef.value,
20
+ dropdownButtonRef.value.$el,
21
21
  dropdownRef.value,
22
22
  {
23
23
  placement: placement.value,
@@ -0,0 +1,85 @@
1
+ import {
2
+ h,
3
+ } from "vue";
4
+
5
+ import AGroupButtonDropdownItem from "./AGroupButtonDropdownItem/AGroupButtonDropdownItem";
6
+
7
+ import ActionsAPI from "./compositionAPI/ActionsAPI";
8
+ import {
9
+ groupButtonDropdownPluginOptions,
10
+ } from "../plugins/AGroupButtonDropdownPlugin";
11
+
12
+ export default {
13
+ name: "AGroupButtonDropdown",
14
+ props: {
15
+ actions: {
16
+ type: Array,
17
+ required: false,
18
+ default: () => [],
19
+ },
20
+ actionsClasses: {
21
+ type: Array,
22
+ required: false,
23
+ default: () => groupButtonDropdownPluginOptions.value.propsDefault.actionsClasses,
24
+ },
25
+ dropdownAttributes: {
26
+ type: Object,
27
+ required: false,
28
+ default: () => groupButtonDropdownPluginOptions.value.propsDefault.dropdownAttributes,
29
+ },
30
+ hasDividerBeforeDropdown: {
31
+ type: Boolean,
32
+ required: false,
33
+ default: () => groupButtonDropdownPluginOptions.value.propsDefault.hasDividerBeforeDropdown,
34
+ },
35
+ indexFirstDropdownAction: {
36
+ type: Number,
37
+ required: false,
38
+ default: () => groupButtonDropdownPluginOptions.value.propsDefault.indexFirstDropdownAction,
39
+ validator: value => value > -1,
40
+ },
41
+ indexFirstDropdownActionMobile: {
42
+ type: Number,
43
+ required: false,
44
+ default: () => groupButtonDropdownPluginOptions.value.propsDefault.indexFirstDropdownActionMobile,
45
+ validator: value => value > -1,
46
+ },
47
+ minDropdownActions: {
48
+ type: Number,
49
+ required: false,
50
+ default: () => groupButtonDropdownPluginOptions.value.propsDefault.minDropdownActions,
51
+ },
52
+ },
53
+ setup(props) {
54
+ const {
55
+ actionsAllFiltered,
56
+ actionsGrouped,
57
+ hasDropdownActions,
58
+ } = ActionsAPI(props);
59
+
60
+ return {
61
+ actionsAllFiltered,
62
+ actionsGrouped,
63
+ hasDropdownActions,
64
+ };
65
+ },
66
+ render() {
67
+ if (this.actionsAllFiltered.length) {
68
+ return h("div", {
69
+ class: "aloha_group_btn_dropdown",
70
+ }, [
71
+ ...this.actionsGrouped.buttons.map((item, itemIndex) => {
72
+ return h(AGroupButtonDropdownItem, {
73
+ data: item,
74
+ actionsDropdown: this.actionsGrouped.dropdown,
75
+ hasDropdownActions: this.hasDropdownActions,
76
+ dropdownAttributes: this.dropdownAttributes,
77
+ actionsClasses: this.actionsClasses,
78
+ isLast: itemIndex === this.actionsGrouped.buttons.length - 1,
79
+ hasDividerBeforeDropdown: this.hasDividerBeforeDropdown,
80
+ }, this.$slots);
81
+ }),
82
+ ]);
83
+ }
84
+ },
85
+ };
@@ -0,0 +1,91 @@
1
+ import {
2
+ h,
3
+ } from "vue";
4
+
5
+ import AButton from "../../AButton/AButton";
6
+ import ADropdown from "../../ADropdown/ADropdown";
7
+ import ALink from "../../ALink/ALink";
8
+
9
+ import DropdownAPI from "./compositionAPI/DropdownAPI";
10
+
11
+ export default {
12
+ name: "AGroupButtonDropdownItem",
13
+ props: {
14
+ data: {
15
+ type: Object,
16
+ required: true,
17
+ },
18
+ actionsDropdown: {
19
+ type: Array,
20
+ required: true,
21
+ },
22
+ hasDropdownActions: {
23
+ type: Boolean,
24
+ required: true,
25
+ },
26
+ dropdownAttributes: {
27
+ type: Object,
28
+ required: true,
29
+ },
30
+ isLast: {
31
+ type: Boolean,
32
+ required: true,
33
+ },
34
+ actionsClasses: {
35
+ type: Array,
36
+ required: true,
37
+ },
38
+ hasDividerBeforeDropdown: {
39
+ type: Boolean,
40
+ required: true,
41
+ },
42
+ },
43
+ setup(props) {
44
+ const {
45
+ isDropdownActionsAfterGroup,
46
+ isDropdownActionsInGroup,
47
+ } = DropdownAPI(props);
48
+
49
+ return {
50
+ isDropdownActionsAfterGroup,
51
+ isDropdownActionsInGroup,
52
+ };
53
+ },
54
+ render() {
55
+ return [
56
+ h("div", {
57
+ class: "a_btn_group",
58
+ }, [
59
+ ...this.data.children.map(action => {
60
+ if (action.type === "button") {
61
+ return h(AButton, {
62
+ class: this.actionsClasses[action.actionNotDividerIndex],
63
+ ...action,
64
+ onClick: action.callback,
65
+ });
66
+ }
67
+ if (action.type === "link") {
68
+ return h(ALink, action);
69
+ }
70
+ if (action.type === "template" &&
71
+ action.slotName &&
72
+ this.$slots[action.slotName]) {
73
+ return this.$slots[action.slotName]({
74
+ action: action,
75
+ });
76
+ }
77
+ }),
78
+ this.isDropdownActionsInGroup && h(ADropdown, {
79
+ isHideWithoutActionAndSlot: true,
80
+ actions: this.actionsDropdown,
81
+ ...this.dropdownAttributes,
82
+ }, this.$slots),
83
+ ]),
84
+ this.isDropdownActionsAfterGroup && h(ADropdown, {
85
+ isHideWithoutActionAndSlot: true,
86
+ actions: this.actionsDropdown,
87
+ ...this.dropdownAttributes,
88
+ }, this.$slots),
89
+ ];
90
+ },
91
+ };
@@ -0,0 +1,27 @@
1
+ import {
2
+ computed,
3
+ toRef,
4
+ } from "vue";
5
+
6
+ export default function DropdownAPI(props) {
7
+ const isLast = toRef(props, "isLast");
8
+ const hasDropdownActions = toRef(props, "hasDropdownActions");
9
+ const hasDividerBeforeDropdown = toRef(props, "hasDividerBeforeDropdown");
10
+
11
+ const isDropdownActionsVisible = computed(() => {
12
+ return isLast.value && hasDropdownActions.value;
13
+ });
14
+
15
+ const isDropdownActionsInGroup = computed(() => {
16
+ return isDropdownActionsVisible.value && !hasDividerBeforeDropdown.value;
17
+ });
18
+
19
+ const isDropdownActionsAfterGroup = computed(() => {
20
+ return isDropdownActionsVisible.value && hasDividerBeforeDropdown.value;
21
+ });
22
+
23
+ return {
24
+ isDropdownActionsAfterGroup,
25
+ isDropdownActionsInGroup,
26
+ };
27
+ }
@@ -0,0 +1,106 @@
1
+ import {
2
+ computed,
3
+ toRef,
4
+ } from "vue";
5
+
6
+ import AMobileAPI from "../../compositionAPI/AMobileAPI";
7
+
8
+ import {
9
+ filterActionsHiddenAndDivider,
10
+ } from "../../utils/actions";
11
+ import {
12
+ cloneDeep,
13
+ forEach, last,
14
+ } from "lodash-es";
15
+
16
+ export default function ActionsAPI(props) {
17
+ const actions = toRef(props, "actions");
18
+ const indexFirstDropdownAction = toRef(props, "indexFirstDropdownAction");
19
+ const indexFirstDropdownActionMobile = toRef(props, "indexFirstDropdownActionMobile");
20
+ const minDropdownActions = toRef(props, "minDropdownActions");
21
+
22
+ const {
23
+ isMobile,
24
+ } = AMobileAPI();
25
+
26
+ const actionsAllFiltered = computed(() => {
27
+ return filterActionsHiddenAndDivider({
28
+ actions: actions.value,
29
+ });
30
+ });
31
+
32
+ const currentIndexFirstDropdownAction = computed(() => {
33
+ return isMobile.value ? indexFirstDropdownActionMobile.value : indexFirstDropdownAction.value;
34
+ });
35
+
36
+ const hasMoreEqualActionsThenParameter = ({ actions = [], minCountActions = 0 }) => {
37
+ let countActions = 0;
38
+ forEach(actions, action => {
39
+ if (countActions >= minCountActions) {
40
+ return false;
41
+ }
42
+ if (action.type !== "divider") {
43
+ countActions++;
44
+ }
45
+ });
46
+
47
+ return countActions >= minCountActions;
48
+ };
49
+
50
+ const actionsGrouped = computed(() => {
51
+ const ACTIONS_ALL = cloneDeep(actionsAllFiltered.value);
52
+
53
+ const ACTIONS_GROUPED = {
54
+ buttons: [],
55
+ dropdown: [],
56
+ };
57
+ let actionNotDividerIndex = 0;
58
+ let isPreviousActionDivider = true;
59
+ forEach(ACTIONS_ALL, (action, actionIndex) => {
60
+ if (actionNotDividerIndex === currentIndexFirstDropdownAction.value) {
61
+ const ACTION_DROPDOWN = ACTIONS_ALL.slice(actionIndex, ACTIONS_ALL.length);
62
+
63
+ if (hasMoreEqualActionsThenParameter({
64
+ actions: ACTION_DROPDOWN,
65
+ minCountActions: minDropdownActions.value,
66
+ })) {
67
+ ACTIONS_GROUPED.dropdown = ACTIONS_ALL.splice(actionIndex, ACTIONS_ALL.length);
68
+ if (currentIndexFirstDropdownAction.value === 0) {
69
+ ACTIONS_GROUPED.buttons.push({
70
+ type: "group",
71
+ children: [],
72
+ });
73
+ }
74
+ return false;
75
+ }
76
+ }
77
+
78
+ if (action.type !== "divider") {
79
+ action.actionNotDividerIndex = actionNotDividerIndex;
80
+ actionNotDividerIndex++;
81
+ if (isPreviousActionDivider) {
82
+ ACTIONS_GROUPED.buttons.push({
83
+ type: "group",
84
+ children: [action],
85
+ });
86
+ } else {
87
+ last(ACTIONS_GROUPED.buttons).children.push(action);
88
+ }
89
+ } else {
90
+ isPreviousActionDivider = true;
91
+ }
92
+ });
93
+
94
+ return ACTIONS_GROUPED;
95
+ });
96
+
97
+ const hasDropdownActions = computed(() => {
98
+ return actionsGrouped.value.dropdown.length > 0;
99
+ });
100
+
101
+ return {
102
+ actionsAllFiltered,
103
+ actionsGrouped,
104
+ hasDropdownActions,
105
+ };
106
+ }
@@ -0,0 +1,16 @@
1
+ import {
2
+ ref,
3
+ } from "vue";
4
+
5
+ export const isMobile = ref(undefined);
6
+
7
+ export function setIsMobile(isMobileLocal) {
8
+ isMobile.value = isMobileLocal;
9
+ }
10
+
11
+ export default function AMobileAPI() {
12
+ return {
13
+ isMobile,
14
+ setIsMobile,
15
+ };
16
+ }
@@ -0,0 +1,24 @@
1
+ import {
2
+ ref,
3
+ } from "vue";
4
+
5
+ export const groupButtonDropdownPluginOptions = ref({
6
+ propsDefault: {
7
+ actionsClasses: ["a_btn a_btn_primary", "a_btn a_btn_secondary"],
8
+ dropdownAttributes: {},
9
+ hasDividerBeforeDropdown: true,
10
+ indexFirstDropdownAction: 1,
11
+ indexFirstDropdownActionMobile: 0,
12
+ minDropdownActions: 2,
13
+ },
14
+ });
15
+ export default {
16
+ install: (app, {
17
+ propsDefault = {},
18
+ } = {}) => {
19
+ groupButtonDropdownPluginOptions.value.propsDefault = {
20
+ ...groupButtonDropdownPluginOptions.value.propsDefault,
21
+ ...propsDefault,
22
+ };
23
+ },
24
+ };
@@ -0,0 +1,25 @@
1
+ import {
2
+ isMobile,
3
+ setIsMobile,
4
+ } from "../compositionAPI/AMobileAPI";
5
+
6
+ export default {
7
+ install: (app, {
8
+ breakpoint,
9
+ } = {}) => {
10
+ setIsMobile(window.innerWidth <= breakpoint);
11
+ const resizeWindow = () => {
12
+ if (window.innerWidth > breakpoint) {
13
+ if (isMobile.value) {
14
+ setIsMobile(false);
15
+ }
16
+ } else {
17
+ if (!isMobile.value) {
18
+ setIsMobile(true);
19
+ }
20
+ }
21
+ };
22
+
23
+ window.addEventListener("resize", resizeWindow);
24
+ },
25
+ };
@@ -1,11 +1,6 @@
1
1
  .aloha_btn {
2
2
  position: relative;
3
- }
4
- .aloha_btn__spinner_left,
5
- .aloha_btn__icon_left {
6
- margin-right: .5rem;
7
- }
8
- .aloha_btn__spinner_right,
9
- .aloha_btn__icon_right {
10
- margin-left: .5rem;
3
+ & > * + * {
4
+ margin-left: .5rem;
5
+ }
11
6
  }
@@ -0,0 +1,5 @@
1
+ .aloha_group_btn_dropdown {
2
+ & > * + * {
3
+ margin-left: .5rem;
4
+ }
5
+ }
@@ -1,11 +1,6 @@
1
1
  .aloha_link {
2
2
  position: relative;
3
- }
4
- .aloha_link__spinner_left,
5
- .aloha_link__icon_left {
6
- margin-right: .5rem;
7
- }
8
- .aloha_link__spinner_right,
9
- .aloha_link__icon_right {
10
- margin-left: .5rem;
3
+ & > * + * {
4
+ margin-left: .5rem;
5
+ }
11
6
  }
@@ -19,3 +19,11 @@
19
19
  @import "components/AButton";
20
20
  @import "components/ALink";
21
21
  @import "components/AWizard";
22
+ @import "components/AGroupButtonDropdown";
23
+
24
+ .a_dropdown__caret {
25
+ margin: 0;
26
+ }
27
+ * + .a_dropdown__caret {
28
+ margin-left: 0.5rem;
29
+ }
@@ -0,0 +1,43 @@
1
+ import {
2
+ filter,
3
+ forEach,
4
+ last,
5
+ } from "lodash-es";
6
+
7
+ export function filterActionsHiddenAndDivider({ actions }) {
8
+ const ACTIONS_FILTERED = filter(actions, action => {
9
+ return !action.isHidden;
10
+ });
11
+
12
+ const ACTIONS_DIVIDER_FILTERED = [];
13
+ forEach(ACTIONS_FILTERED, action => {
14
+ if (action.type !== "divider" ||
15
+ (ACTIONS_DIVIDER_FILTERED.length > 0 &&
16
+ last(ACTIONS_DIVIDER_FILTERED).type !== "divider")) {
17
+ ACTIONS_DIVIDER_FILTERED.push(action);
18
+ }
19
+ });
20
+ const LAST_ACTION = last(ACTIONS_DIVIDER_FILTERED);
21
+ if (LAST_ACTION && LAST_ACTION.type === "divider") {
22
+ ACTIONS_DIVIDER_FILTERED.pop();
23
+ }
24
+
25
+ return ACTIONS_DIVIDER_FILTERED;
26
+ }
27
+
28
+ export function filterActionsDivider({ actions }) {
29
+ const ACTIONS_DIVIDER_FILTERED = [];
30
+ forEach(actions, action => {
31
+ if (action.type !== "divider" ||
32
+ (ACTIONS_DIVIDER_FILTERED.length > 0 &&
33
+ last(ACTIONS_DIVIDER_FILTERED).type !== "divider")) {
34
+ ACTIONS_DIVIDER_FILTERED.push(action);
35
+ }
36
+ });
37
+ const LAST_ACTION = last(ACTIONS_DIVIDER_FILTERED);
38
+ if (LAST_ACTION && LAST_ACTION.type === "divider") {
39
+ ACTIONS_DIVIDER_FILTERED.pop();
40
+ }
41
+
42
+ return ACTIONS_DIVIDER_FILTERED;
43
+ }