@@ -17,103 +17,116 @@ Dialog button component used by NcDialog in the actions slot to display the butt
17
17
<template #icon>
18
18
<!-- @slot Allow to set a custom icon for the button -->
19
19
<slot name="icon">
20
- <NcIconSvgWrapper v-if="icon !== undefined" :svg="icon" />
20
+ <!-- The loading state is an information that must be accessible -->
21
+ <NcLoadingIcon v-if="isLoading" :name="t('Loading …') /* TRANSLATORS: The button is in a loading state*/" />
22
+ <NcIconSvgWrapper v-else-if="icon !== undefined" :svg="icon" />
21
23
</slot>
22
24
</template>
23
25
</NcButton>
24
26
</template>
25
27
26
- <script lang="ts">
27
- import { defineComponent, type PropType } from 'vue'
28
+ <script setup lang="ts">
29
+ import type { PropType } from 'vue'
30
+ import { ref } from 'vue'
31
+
28
32
import NcButton, { ButtonNativeType, ButtonType } from '../NcButton/index'
29
33
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.js'
34
+ import NcLoadingIcon from '../NcLoadingIcon/index.js'
35
+ import { t } from '../../l10n.js'
30
36
31
- export default defineComponent({
32
- name: 'NcDialogButton',
37
+ const props = defineProps({
38
+ /**
39
+ * The function that will be called when the button is pressed.
40
+ * If the function returns `false` the click is ignored and the dialog will not be closed.
41
+ * @type {() => unknown|false|Promise<unknown|false>}
42
+ */
43
+ callback: {
44
+ type: Function,
45
+ required: false,
46
+ default: () => {},
47
+ },
33
48
34
- components: {
35
- NcButton,
36
- NcIconSvgWrapper,
49
+ /**
50
+ * The label of the button
51
+ */
52
+ label: {
53
+ type: String,
54
+ required: true,
37
55
},
38
56
39
- props: {
40
- /**
41
- * The function that will be called when the button is pressed
42
- * @type {() => void}
43
- */
44
- callback: {
45
- type: Function,
46
- required: false,
47
- default: () => {},
48
- },
57
+ /**
58
+ * Optional inline SVG icon for the button
59
+ */
60
+ icon: {
61
+ type: String,
62
+ required: false,
63
+ default: undefined,
64
+ },
49
65
50
- /**
51
- * The label of the button
52
- */
53
- label: {
54
- type: String,
55
- required: true,
66
+ /**
67
+ * The button type, see NcButton
68
+ * @type {'primary'|'secondary'|'error'|'warning'|'success'}
69
+ */
70
+ type: {
71
+ type: String as PropType<ButtonType>,
72
+ default: ButtonType.Secondary,
73
+ required: false,
74
+ validator(value: string) {
75
+ return typeof value === 'string'
76
+ && Object.values(ButtonType).includes(value as ButtonType)
56
77
},
78
+ },
57
79
58
- /**
59
- * Optional inline SVG icon for the button
60
- */
61
- icon: {
62
- type: String,
63
- required: false,
64
- default: undefined,
80
+ /**
81
+ * The native type of the button, see `NcButton`
82
+ * @type {'button'|'submit'|'reset'}
83
+ */
84
+ nativeType: {
85
+ type: String as PropType<ButtonNativeType>,
86
+ required: false,
87
+ default: 'button',
88
+ validator(value) {
89
+ return typeof value === 'string'
90
+ && Object.values(ButtonNativeType).includes(value as ButtonNativeType)
65
91
},
92
+ },
66
93
67
- /**
68
- * The button type, see NcButton
69
- * @type {'primary'|'secondary'|'error'|'warning'|'success'}
70
- */
71
- type: {
72
- type: String as PropType<ButtonType>,
73
- default: ButtonType.Secondary,
74
- required: false,
75
- validator(value: string) {
76
- return typeof value === 'string'
77
- && Object.values(ButtonType).includes(value as ButtonType)
78
- },
79
- },
94
+ /**
95
+ * If the button should be shown as disabled
96
+ */
97
+ disabled: {
98
+ type: Boolean,
99
+ default: false,
100
+ },
101
+ })
80
102
81
- /**
82
- * The native type of the button, see `NcButton`
83
- * @type {'button'|'submit'|'reset'}
84
- */
85
- nativeType: {
86
- type: String as PropType<ButtonNativeType>,
87
- required: false,
88
- default: 'button',
89
- validator(value) {
90
- return typeof value === 'string'
91
- && Object.values(ButtonNativeType).includes(value as ButtonNativeType)
92
- },
93
- },
103
+ const emit = defineEmits<{
104
+ (name: 'click', event: MouseEvent, payload: unknown): void
105
+ }>()
94
106
95
- /**
96
- * If the button should be shown as disabled
97
- */
98
- disabled: {
99
- type: Boolean,
100
- default: false,
101
- },
102
- },
107
+ const isLoading = ref(false)
103
108
104
- emits: ['click'],
109
+ /**
110
+ * Handle clicking the button
111
+ * @param {MouseEvent} e The click event
112
+ */
113
+ const handleClick = async (e) => {
114
+ // Do not re-emit while loading
115
+ if (isLoading.value) {
116
+ return
117
+ }
105
118
106
- setup(props, { emit }) {
107
- /**
108
- * Handle clicking the button
109
- * @param {MouseEvent} e The click event
110
- */
111
- const handleClick = (e) => {
112
- props.callback?.()
113
- emit('click', e)
119
+ isLoading.value = true
120
+ try {
121
+ const result = await props.callback?.()
122
+ if (result !== false) {
123
+ /**
124
+ * The click event (`MouseEvent`) and the value returned by the callback
125
+ */
126
+ emit('click', e, result )
114
127
}
115
-
116
- return { handleClick }
117
- },
118
- })
128
+ } finally {
129
+ isLoading.value = false
130
+ }
131
+ }
119
132
</script>
0 commit comments