sprintify-ui 0.2.30 → 0.4.1
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/dist/sprintify-ui.es.js +4535 -4509
- package/dist/types/src/components/BaseFileUploader.vue.d.ts +5 -7
- package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +5 -5
- package/dist/types/src/stores/systemAlerts.d.ts +2 -2
- package/package.json +3 -2
- package/src/components/BaseFilePicker.vue +1 -4
- package/src/components/BaseFileUploader.stories.js +14 -2
- package/src/components/BaseFileUploader.vue +40 -29
- package/src/components/BaseLayoutSidebar.vue +18 -18
- package/src/components/BaseLayoutStacked.vue +1 -1
- package/src/components/BaseMediaLibrary.vue +62 -43
- package/src/components/BaseMediaListItem.vue +51 -15
- package/src/stores/systemAlerts.ts +5 -6
|
@@ -14,7 +14,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
14
14
|
};
|
|
15
15
|
multiple: {
|
|
16
16
|
type: import("vue").PropType<boolean>;
|
|
17
|
-
required: true;
|
|
18
17
|
default: boolean;
|
|
19
18
|
};
|
|
20
19
|
cropper: {
|
|
@@ -45,7 +44,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
45
44
|
type: import("vue").PropType<() => boolean>;
|
|
46
45
|
default: () => boolean;
|
|
47
46
|
};
|
|
48
|
-
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("
|
|
47
|
+
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("success" | "end" | "start" | "fail")[], "success" | "end" | "start" | "fail", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
|
49
48
|
component: {
|
|
50
49
|
type: import("vue").PropType<"BaseFilePicker" | "BaseFilePickerCrop">;
|
|
51
50
|
default: string;
|
|
@@ -60,7 +59,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
60
59
|
};
|
|
61
60
|
multiple: {
|
|
62
61
|
type: import("vue").PropType<boolean>;
|
|
63
|
-
required: true;
|
|
64
62
|
default: boolean;
|
|
65
63
|
};
|
|
66
64
|
cropper: {
|
|
@@ -92,10 +90,10 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
92
90
|
default: () => boolean;
|
|
93
91
|
};
|
|
94
92
|
}>> & {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
onSuccess?: ((...args: any[]) => any) | undefined;
|
|
94
|
+
onEnd?: ((...args: any[]) => any) | undefined;
|
|
95
|
+
onStart?: ((...args: any[]) => any) | undefined;
|
|
96
|
+
onFail?: ((...args: any[]) => any) | undefined;
|
|
99
97
|
}, {
|
|
100
98
|
component: "BaseFilePicker" | "BaseFilePickerCrop";
|
|
101
99
|
disabled: boolean;
|
|
@@ -72,7 +72,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
72
72
|
default: string;
|
|
73
73
|
type: PropType<"list" | "gallery" | "images">;
|
|
74
74
|
};
|
|
75
|
-
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("
|
|
75
|
+
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("success" | "update:modelValue" | "end" | "start" | "fail")[], "success" | "update:modelValue" | "end" | "start" | "fail", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
|
76
76
|
modelValue: {
|
|
77
77
|
default: undefined;
|
|
78
78
|
type: PropType<MediaLibraryPayload>;
|
|
@@ -143,10 +143,10 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
143
143
|
};
|
|
144
144
|
}>> & {
|
|
145
145
|
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
onSuccess?: ((...args: any[]) => any) | undefined;
|
|
147
|
+
onEnd?: ((...args: any[]) => any) | undefined;
|
|
148
|
+
onStart?: ((...args: any[]) => any) | undefined;
|
|
149
|
+
onFail?: ((...args: any[]) => any) | undefined;
|
|
150
150
|
}, {
|
|
151
151
|
draggable: boolean;
|
|
152
152
|
name: string;
|
|
@@ -3,7 +3,7 @@ export declare const useSystemAlertStore: import("pinia").StoreDefinition<"syste
|
|
|
3
3
|
count: number;
|
|
4
4
|
systemAlerts: SystemAlert[];
|
|
5
5
|
}, {}, {
|
|
6
|
-
push(systemAlert: SystemAlertOptions):
|
|
7
|
-
remove(
|
|
6
|
+
push(systemAlert: SystemAlertOptions): string | number;
|
|
7
|
+
remove(alertId: number | string): void;
|
|
8
8
|
clear(): void;
|
|
9
9
|
}>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sprintify-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"build": "rimraf dist && vue-tsc && vite build",
|
|
6
6
|
"build-fast": "rimraf dist && vite build",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"prepack": "npm run build",
|
|
14
14
|
"prepare": "husky install && relative-deps",
|
|
15
15
|
"release": "standard-version",
|
|
16
|
-
"commit": "cz"
|
|
16
|
+
"commit": "cz",
|
|
17
|
+
"vue-tsc": "vue-tsc"
|
|
17
18
|
},
|
|
18
19
|
"peerDependencies": {
|
|
19
20
|
"@tailwindcss/aspect-ratio": "^0.4.2",
|
|
@@ -3,10 +3,7 @@
|
|
|
3
3
|
type="button"
|
|
4
4
|
:class="twButton"
|
|
5
5
|
:disabled="disabled"
|
|
6
|
-
@drop.prevent="
|
|
7
|
-
dragging = false;
|
|
8
|
-
handleDrop($event);
|
|
9
|
-
"
|
|
6
|
+
@drop.prevent="dragging = false; handleDrop($event);"
|
|
10
7
|
@dragleave.prevent="dragging = false"
|
|
11
8
|
@dragover.prevent="dragging = true"
|
|
12
9
|
@dragenter.prevent="dragging = true"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import BaseFileUploader from '@/components/BaseFileUploader.vue';
|
|
2
2
|
import BaseLoadingCover from '@/components/BaseLoadingCover.vue';
|
|
3
3
|
import BaseAppNotifications from '@/components/BaseAppNotifications.vue';
|
|
4
|
+
import ShowValue from '../../.storybook/components/ShowValue.vue';
|
|
4
5
|
import { Icon as BaseIcon } from '@iconify/vue';
|
|
5
6
|
import { t } from '@/i18n';
|
|
6
7
|
|
|
@@ -21,12 +22,20 @@ const Template = (args) => ({
|
|
|
21
22
|
BaseIcon,
|
|
22
23
|
BaseLoadingCover,
|
|
23
24
|
BaseAppNotifications,
|
|
25
|
+
ShowValue,
|
|
24
26
|
},
|
|
25
27
|
setup() {
|
|
26
|
-
|
|
28
|
+
|
|
29
|
+
const files = ref([]);
|
|
30
|
+
|
|
31
|
+
function onSuccess(payload) {
|
|
32
|
+
files.value = payload;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return { args, t, files, onSuccess };
|
|
27
36
|
},
|
|
28
37
|
template: `
|
|
29
|
-
<BaseFileUploader v-bind="args">
|
|
38
|
+
<BaseFileUploader v-bind="args" @success="onSuccess">
|
|
30
39
|
<template #default="{ dragging, disabled, uploading, selecting }">
|
|
31
40
|
<div
|
|
32
41
|
class="flex w-full items-center space-x-4 rounded-lg border-2 border-dashed border-slate-200 p-5 duration-100"
|
|
@@ -59,6 +68,9 @@ const Template = (args) => ({
|
|
|
59
68
|
/>
|
|
60
69
|
</template>
|
|
61
70
|
</BaseFileUploader>
|
|
71
|
+
|
|
72
|
+
<ShowValue :value="files" />
|
|
73
|
+
|
|
62
74
|
<BaseAppNotifications></BaseAppNotifications>
|
|
63
75
|
`,
|
|
64
76
|
});
|
|
@@ -54,7 +54,7 @@ const props = withDefaults(
|
|
|
54
54
|
accept?: string;
|
|
55
55
|
acceptedExtensions?: string[];
|
|
56
56
|
cropper?: BaseCropperConfig | Record<string, any> | boolean | null;
|
|
57
|
-
multiple
|
|
57
|
+
multiple?: boolean;
|
|
58
58
|
}>(),
|
|
59
59
|
{
|
|
60
60
|
component: 'BaseFilePicker',
|
|
@@ -74,10 +74,10 @@ const props = withDefaults(
|
|
|
74
74
|
);
|
|
75
75
|
|
|
76
76
|
const emit = defineEmits([
|
|
77
|
-
'
|
|
78
|
-
'
|
|
79
|
-
'
|
|
80
|
-
'
|
|
77
|
+
'start',
|
|
78
|
+
'success',
|
|
79
|
+
'fail',
|
|
80
|
+
'end',
|
|
81
81
|
]);
|
|
82
82
|
|
|
83
83
|
const componentInternal = computed(() => {
|
|
@@ -118,57 +118,68 @@ async function onFileSelect(files: File | File[]) {
|
|
|
118
118
|
return;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
emit('start');
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
let payloads = [] as UploadedFile[];
|
|
125
|
+
|
|
121
126
|
try {
|
|
122
|
-
const formData = new FormData();
|
|
123
127
|
|
|
124
128
|
if (Array.isArray(files)) {
|
|
125
|
-
await Promise.all(files.map(f => processFileUpload(
|
|
129
|
+
payloads = await Promise.all(files.map(f => processFileUpload(f)));
|
|
126
130
|
} else {
|
|
127
|
-
await processFileUpload(
|
|
131
|
+
const payload = await processFileUpload(files);
|
|
132
|
+
payloads.push(payload);
|
|
128
133
|
}
|
|
134
|
+
|
|
135
|
+
emit('success', payloads)
|
|
136
|
+
|
|
129
137
|
} catch (e: unknown) {
|
|
130
138
|
console.error(e);
|
|
131
|
-
emit('
|
|
139
|
+
emit('fail');
|
|
132
140
|
notifications.push({
|
|
133
141
|
color: 'danger',
|
|
134
142
|
title: t('sui.error'),
|
|
135
143
|
text: t('sui.upload_failed'),
|
|
136
144
|
});
|
|
137
145
|
} finally {
|
|
138
|
-
emit('
|
|
146
|
+
emit('end');
|
|
139
147
|
uploading.value = false;
|
|
140
148
|
}
|
|
141
149
|
}
|
|
142
150
|
|
|
143
|
-
async function processFileUpload(
|
|
144
|
-
|
|
151
|
+
async function processFileUpload(file: File): Promise<UploadedFile> {
|
|
152
|
+
|
|
153
|
+
const formData = new FormData();
|
|
145
154
|
|
|
146
|
-
|
|
155
|
+
formData.append('file', file);
|
|
147
156
|
|
|
148
157
|
const response = await http.post(props.url ?? config.upload_url, formData);
|
|
149
158
|
|
|
150
159
|
const payload = response.data as UploadedFile;
|
|
151
160
|
payload.original_file = file;
|
|
152
161
|
|
|
153
|
-
|
|
162
|
+
// Read file if image, add add data_url to payload
|
|
154
163
|
|
|
155
|
-
|
|
156
|
-
payload.data_url = e.target.result;
|
|
157
|
-
onSuccess(payload);
|
|
158
|
-
};
|
|
164
|
+
return new Promise(resolve => {
|
|
159
165
|
|
|
160
|
-
|
|
161
|
-
onSuccess(payload);
|
|
162
|
-
};
|
|
166
|
+
const reader = new FileReader();
|
|
163
167
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
168
|
+
reader.onload = (e: any) => {
|
|
169
|
+
payload.data_url = e.target.result;
|
|
170
|
+
resolve(payload);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
reader.onerror = () => {
|
|
174
|
+
resolve(payload);
|
|
175
|
+
};
|
|
170
176
|
|
|
171
|
-
|
|
172
|
-
|
|
177
|
+
if (payload.mime_type.includes('image')) {
|
|
178
|
+
reader.readAsDataURL(file);
|
|
179
|
+
} else {
|
|
180
|
+
resolve(payload);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
173
183
|
}
|
|
184
|
+
|
|
174
185
|
</script>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
leave-from="opacity-100"
|
|
19
19
|
leave-to="opacity-0"
|
|
20
20
|
>
|
|
21
|
-
<div class="fixed inset-0 bg-
|
|
21
|
+
<div class="fixed inset-0 bg-opacity-75 bg-slate-600" />
|
|
22
22
|
</TransitionChild>
|
|
23
23
|
|
|
24
24
|
<div class="fixed inset-0 z-40 flex">
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
leave-to="-translate-x-full"
|
|
33
33
|
>
|
|
34
34
|
<DialogPanel
|
|
35
|
-
class="relative flex w-full max-w-xs
|
|
35
|
+
class="relative flex flex-col flex-1 w-full max-w-xs pt-5 pb-4"
|
|
36
36
|
:class="[dark ? 'bg-slate-800' : 'bg-white']"
|
|
37
37
|
>
|
|
38
38
|
<TransitionChild
|
|
@@ -44,31 +44,31 @@
|
|
|
44
44
|
leave-from="opacity-100"
|
|
45
45
|
leave-to="opacity-0"
|
|
46
46
|
>
|
|
47
|
-
<div class="absolute top-0 right-0 -mr-12
|
|
47
|
+
<div class="absolute top-0 right-0 pt-2 -mr-12">
|
|
48
48
|
<button
|
|
49
49
|
type="button"
|
|
50
|
-
class="
|
|
50
|
+
class="flex items-center justify-center w-10 h-10 ml-1 rounded-full"
|
|
51
51
|
@click="showMobileMenu = false"
|
|
52
52
|
>
|
|
53
53
|
<span class="sr-only">Close sidebar</span>
|
|
54
54
|
<BaseIcon
|
|
55
55
|
icon="heroicons:x-mark"
|
|
56
|
-
class="
|
|
56
|
+
class="w-6 h-6 text-white"
|
|
57
57
|
aria-hidden="true"
|
|
58
58
|
/>
|
|
59
59
|
</button>
|
|
60
60
|
</div>
|
|
61
61
|
</TransitionChild>
|
|
62
|
-
<div class="flex flex-shrink-0
|
|
62
|
+
<div class="flex items-center flex-shrink-0 px-4">
|
|
63
63
|
<img
|
|
64
|
-
class="block h-8
|
|
64
|
+
class="block w-auto h-8"
|
|
65
65
|
:src="logoUrl"
|
|
66
66
|
:alt="appName"
|
|
67
67
|
>
|
|
68
68
|
</div>
|
|
69
69
|
<div
|
|
70
70
|
data-scroll-lock-scrollable
|
|
71
|
-
class="
|
|
71
|
+
class="flex-1 h-0 mt-5 overflow-y-auto"
|
|
72
72
|
>
|
|
73
73
|
<nav>
|
|
74
74
|
<slot name="menu" />
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
</DialogPanel>
|
|
78
78
|
</TransitionChild>
|
|
79
79
|
<div
|
|
80
|
-
class="
|
|
80
|
+
class="flex-shrink-0 w-14"
|
|
81
81
|
aria-hidden="true"
|
|
82
82
|
>
|
|
83
83
|
<!-- Dummy element to force sidebar to shrink to fit close icon -->
|
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
</Dialog>
|
|
87
87
|
</TransitionRoot>
|
|
88
88
|
|
|
89
|
-
<div class="flex min-h-full
|
|
90
|
-
<div class="sticky top-0 left-0 z-10 shrink-0
|
|
89
|
+
<div class="flex flex-col min-h-full xl:pl-64">
|
|
90
|
+
<div class="sticky top-0 left-0 z-10 shadow shrink-0">
|
|
91
91
|
<BaseSystemAlert
|
|
92
92
|
v-for="systemAlert in systemAlerts"
|
|
93
93
|
:key="systemAlert.id"
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
:to="systemAlert.to"
|
|
96
96
|
:action="systemAlert.action"
|
|
97
97
|
:closable="systemAlert.closable"
|
|
98
|
-
@close="systemAlertStore.remove(systemAlert)"
|
|
98
|
+
@close="systemAlertStore.remove(systemAlert.id)"
|
|
99
99
|
>
|
|
100
100
|
{{ systemAlert.message }}
|
|
101
101
|
</BaseSystemAlert>
|
|
@@ -106,13 +106,13 @@
|
|
|
106
106
|
>
|
|
107
107
|
<button
|
|
108
108
|
type="button"
|
|
109
|
-
class="border-r border-slate-200
|
|
109
|
+
class="px-4 border-r border-slate-200 text-slate-500 xl:hidden"
|
|
110
110
|
@click="showMobileMenu = true"
|
|
111
111
|
>
|
|
112
112
|
<span class="sr-only">Open sidebar</span>
|
|
113
113
|
<BaseIcon
|
|
114
114
|
icon="heroicons:bars-3-bottom-left"
|
|
115
|
-
class="
|
|
115
|
+
class="w-6 h-6"
|
|
116
116
|
aria-hidden="true"
|
|
117
117
|
/>
|
|
118
118
|
</button>
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
</div>
|
|
126
126
|
|
|
127
127
|
<!-- Position: relative to contain Loading Covers -->
|
|
128
|
-
<main class="relative min-h-full
|
|
128
|
+
<main class="relative flex-1 min-h-full">
|
|
129
129
|
<slot />
|
|
130
130
|
</main>
|
|
131
131
|
</div>
|
|
@@ -135,16 +135,16 @@
|
|
|
135
135
|
<!-- Sidebar component, swap this element with another sidebar if you like -->
|
|
136
136
|
<div
|
|
137
137
|
data-scroll-lock-scrollable
|
|
138
|
-
class="flex
|
|
138
|
+
class="flex flex-col flex-1 min-h-0 overflow-y-auto"
|
|
139
139
|
:class="[dark ? 'bg-slate-800' : 'bg-white shadow']"
|
|
140
140
|
>
|
|
141
141
|
<div
|
|
142
|
-
class="flex flex-shrink-0
|
|
142
|
+
class="flex items-center flex-shrink-0 px-4"
|
|
143
143
|
:style="{ height: navbarHeight + 'px' }"
|
|
144
144
|
:class="[dark ? 'bg-slate-900' : 'bg-white']"
|
|
145
145
|
>
|
|
146
146
|
<img
|
|
147
|
-
class="block h-8
|
|
147
|
+
class="block w-auto h-8"
|
|
148
148
|
:src="logoUrl"
|
|
149
149
|
:alt="appName"
|
|
150
150
|
>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<BaseFileUploader
|
|
4
4
|
:component="pickerComponent"
|
|
5
5
|
:max-size="maxSize"
|
|
6
|
-
:disabled="
|
|
6
|
+
:disabled="disabledInternal"
|
|
7
7
|
class="w-full"
|
|
8
8
|
tw-button="w-full"
|
|
9
9
|
:accept="accept"
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
:url="uploadUrl"
|
|
12
12
|
:multiple="multiple"
|
|
13
13
|
:cropper="pickerComponent == 'BaseFilePickerCrop' ? cropper : undefined"
|
|
14
|
-
@
|
|
15
|
-
@
|
|
16
|
-
@
|
|
17
|
-
@
|
|
14
|
+
@start="onStart"
|
|
15
|
+
@success="onSuccess"
|
|
16
|
+
@fail="onFail"
|
|
17
|
+
@end="onEnd"
|
|
18
18
|
>
|
|
19
19
|
<template #default="baseFileUploaderProps">
|
|
20
20
|
<slot
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
<slot
|
|
63
63
|
:model-value="normalizedModelValue"
|
|
64
64
|
name="list"
|
|
65
|
-
:disabled="
|
|
65
|
+
:disabled="disabledInternal"
|
|
66
66
|
:draggable="draggable"
|
|
67
67
|
:remove="promptRemove"
|
|
68
68
|
@update:model-value="sync"
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
v-if="layout == 'images'"
|
|
72
72
|
v-bind="listProps"
|
|
73
73
|
:model-value="normalizedModelValue"
|
|
74
|
-
:disabled="
|
|
74
|
+
:disabled="disabledInternal"
|
|
75
75
|
:draggable="draggable"
|
|
76
76
|
@update:model-value="sync"
|
|
77
77
|
@remove="promptRemove($event)"
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
v-else-if="layout == 'list'"
|
|
82
82
|
v-bind="listProps"
|
|
83
83
|
:model-value="normalizedModelValue"
|
|
84
|
-
:disabled="
|
|
84
|
+
:disabled="disabledInternal"
|
|
85
85
|
:draggable="draggable"
|
|
86
86
|
@update:model-value="sync"
|
|
87
87
|
@remove="promptRemove($event)"
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
v-else-if="layout == 'gallery'"
|
|
92
92
|
v-bind="listProps"
|
|
93
93
|
:model-value="normalizedModelValue"
|
|
94
|
-
:disabled="
|
|
94
|
+
:disabled="disabledInternal"
|
|
95
95
|
:draggable="draggable"
|
|
96
96
|
@update:model-value="sync"
|
|
97
97
|
@remove="promptRemove($event)"
|
|
@@ -196,10 +196,10 @@ const props = defineProps({
|
|
|
196
196
|
|
|
197
197
|
const emit = defineEmits([
|
|
198
198
|
'update:modelValue',
|
|
199
|
-
'
|
|
200
|
-
'
|
|
201
|
-
'
|
|
202
|
-
'
|
|
199
|
+
'start',
|
|
200
|
+
'success',
|
|
201
|
+
'fail',
|
|
202
|
+
'end',
|
|
203
203
|
]);
|
|
204
204
|
|
|
205
205
|
const { emitUpdate, enableForm, disableForm } = useField({
|
|
@@ -222,10 +222,6 @@ const normalizedModelValue = computed(() => {
|
|
|
222
222
|
|
|
223
223
|
sync(normalizedModelValue.value);
|
|
224
224
|
|
|
225
|
-
const numberOfFiles = computed((): number => {
|
|
226
|
-
return normalizedModelValue.value.length;
|
|
227
|
-
});
|
|
228
|
-
|
|
229
225
|
// Validations
|
|
230
226
|
|
|
231
227
|
const normalizedMax = computed(() => {
|
|
@@ -248,40 +244,59 @@ const maxFileSize = computed(() => {
|
|
|
248
244
|
|
|
249
245
|
// Upload
|
|
250
246
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
247
|
+
const syncingFiles = ref(false);
|
|
248
|
+
|
|
249
|
+
function onSuccess(files: UploadedFile[]) {
|
|
255
250
|
|
|
256
|
-
if (
|
|
257
|
-
normalizedMax.value &&
|
|
258
|
-
numberOfFiles.value >= normalizedMax.value &&
|
|
259
|
-
normalizedMax.value > 1
|
|
260
|
-
) {
|
|
261
|
-
notifications.push({
|
|
262
|
-
title: t('sui.whoops'),
|
|
263
|
-
text: t('sui.you_can_upload_up_to_n_files', {
|
|
264
|
-
count: normalizedMax.value,
|
|
265
|
-
}),
|
|
266
|
-
color: 'danger',
|
|
267
|
-
});
|
|
251
|
+
if (files.length == 0) {
|
|
268
252
|
return;
|
|
269
253
|
}
|
|
270
254
|
|
|
255
|
+
syncingFiles.value = true;
|
|
256
|
+
|
|
271
257
|
let modelValue = cloneDeep(normalizedModelValue.value);
|
|
272
258
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
259
|
+
for (const file of files) {
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
if (
|
|
263
|
+
normalizedMax.value &&
|
|
264
|
+
modelValue.length >= normalizedMax.value &&
|
|
265
|
+
normalizedMax.value > 1
|
|
266
|
+
) {
|
|
267
|
+
notifications.push({
|
|
268
|
+
title: t('sui.whoops'),
|
|
269
|
+
text: t('sui.you_can_upload_up_to_n_files', {
|
|
270
|
+
count: normalizedMax.value,
|
|
271
|
+
}),
|
|
272
|
+
color: 'danger',
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
277
|
|
|
278
|
-
|
|
278
|
+
if (normalizedMax.value == 1) {
|
|
279
|
+
// Remove everything...
|
|
280
|
+
modelValue = [];
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
modelValue.push(file);
|
|
284
|
+
}
|
|
279
285
|
|
|
280
286
|
sync(modelValue);
|
|
281
287
|
|
|
282
|
-
|
|
288
|
+
syncingFiles.value = false;
|
|
289
|
+
|
|
290
|
+
emit('success', files);
|
|
283
291
|
}
|
|
284
292
|
|
|
293
|
+
// Disabled
|
|
294
|
+
|
|
295
|
+
const disabledInternal = computed(() => {
|
|
296
|
+
return props.disabled || syncingFiles.value;
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
|
|
285
300
|
// Remove
|
|
286
301
|
|
|
287
302
|
function promptRemove(index: number, length = 1) {
|
|
@@ -311,13 +326,17 @@ function sync(modelValue: MediaLibraryPayload) {
|
|
|
311
326
|
|
|
312
327
|
// Events
|
|
313
328
|
|
|
314
|
-
function
|
|
315
|
-
emit('
|
|
329
|
+
function onStart(event: unknown) {
|
|
330
|
+
emit('start', event);
|
|
316
331
|
disableForm();
|
|
317
332
|
}
|
|
318
333
|
|
|
319
|
-
function
|
|
320
|
-
emit('
|
|
334
|
+
function onFail(event: unknown) {
|
|
335
|
+
emit('fail', event);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function onEnd(event: unknown) {
|
|
339
|
+
emit('end', event);
|
|
321
340
|
enableForm();
|
|
322
341
|
}
|
|
323
342
|
</script>
|