sprintify-ui 0.0.9 → 0.0.11
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/README.md +14 -3
- package/dist/sprintify-ui.es.js +3851 -6637
- package/dist/style.css +2 -2
- package/dist/tailwindcss/index.js +283 -32
- package/dist/types/src/components/BaseAutocomplete.vue.d.ts +0 -1
- package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +0 -1
- package/dist/types/src/components/BaseBelongsTo.vue.d.ts +13 -3
- package/dist/types/src/components/BaseDataTable.vue.d.ts +95 -64
- package/dist/types/src/components/BaseDialog.vue.d.ts +8 -8
- package/dist/types/src/components/BaseFilePicker.vue.d.ts +3 -3
- package/dist/types/src/components/BaseLoadingCover.vue.d.ts +12 -12
- package/dist/types/src/components/BaseMenuItem.vue.d.ts +4 -4
- package/dist/types/src/components/BaseNavbarItemContent.vue.d.ts +4 -4
- package/dist/types/src/components/BaseTableColumn.vue.d.ts +4 -4
- package/dist/types/src/svg/BaseEmptyState.vue.d.ts +2 -0
- package/dist/types/src/{components/BaseSpinner.vue.d.ts → svg/BaseSpinnerLarge.vue.d.ts} +0 -0
- package/dist/types/src/svg/BaseSpinnerSmall.vue.d.ts +44 -0
- package/dist/types/src/types/types.d.ts +1 -1
- package/package.json +4 -2
- package/src/assets/form.css +1 -10
- package/src/assets/main.css +0 -1
- package/src/assets/tailwind.css +3 -5
- package/src/components/BaseAutocomplete.stories.js +7 -4
- package/src/components/BaseAutocomplete.vue +44 -15
- package/src/components/BaseAutocompleteFetch.stories.js +6 -3
- package/src/components/BaseAutocompleteFetch.vue +8 -3
- package/src/components/BaseBelongsTo.stories.js +9 -4
- package/src/components/BaseBelongsTo.vue +1 -0
- package/src/components/BaseButton.stories.js +11 -3
- package/src/components/BaseCard.vue +1 -1
- package/src/components/BaseDataIterator.stories.js +102 -3
- package/src/components/BaseDataIterator.vue +44 -12
- package/src/components/BaseDataTable.stories.js +149 -2
- package/src/components/BaseDataTable.vue +34 -28
- package/src/components/BaseDataTableToggleColumns.vue +1 -1
- package/src/components/BaseDateSelect.vue +6 -2
- package/src/components/BaseDescriptionListItem.vue +40 -4
- package/src/components/BaseDialog.stories.js +51 -0
- package/src/components/BaseDialog.vue +13 -7
- package/src/components/BaseFilePicker.stories.js +51 -0
- package/src/components/BaseFilePicker.vue +6 -6
- package/src/components/BaseFileUploader.stories.js +80 -0
- package/src/components/BaseFileUploader.vue +12 -3
- package/src/components/BaseLoadingCover.vue +8 -16
- package/src/components/BaseTable.vue +42 -29
- package/src/components/BaseTableColumn.vue +2 -2
- package/src/svg/BaseEmptyState.vue +34 -0
- package/src/{components/BaseSpinner.vue → svg/BaseSpinnerLarge.vue} +0 -0
- package/src/svg/BaseSpinnerSmall.vue +9 -0
- package/src/types/types.ts +1 -1
- package/src/assets/button.css +0 -80
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import BaseDataTable from './BaseDataTable.vue';
|
|
2
2
|
import BaseTableColumn from './BaseTableColumn.vue';
|
|
3
3
|
import BaseBoolean from './BaseBoolean.vue';
|
|
4
|
+
import BaseSelect from './BaseSelect.vue';
|
|
5
|
+
import BaseBadge from './BaseBadge.vue';
|
|
6
|
+
import BaseAppNotifications from './BaseAppNotifications.vue';
|
|
7
|
+
import BaseAppDialogs from './BaseAppDialogs.vue';
|
|
4
8
|
|
|
5
9
|
export default {
|
|
6
10
|
title: 'Data/BaseDataTable',
|
|
@@ -23,6 +27,7 @@ const template = `
|
|
|
23
27
|
label="Titre"
|
|
24
28
|
sortable
|
|
25
29
|
field="title->en"
|
|
30
|
+
:toggle="false"
|
|
26
31
|
>
|
|
27
32
|
<div class="max-w-sm">
|
|
28
33
|
<div class="font-medium text-slate-900">
|
|
@@ -53,11 +58,84 @@ const template = `
|
|
|
53
58
|
{{ Math.round(row.votes_avg_score) }} / 5
|
|
54
59
|
</div>
|
|
55
60
|
</BaseTableColumn>
|
|
61
|
+
|
|
62
|
+
<BaseTableColumn
|
|
63
|
+
v-slot="{ row }"
|
|
64
|
+
label="Access level"
|
|
65
|
+
field="access_level"
|
|
66
|
+
sortable
|
|
67
|
+
optional
|
|
68
|
+
>
|
|
69
|
+
<BaseBadge>
|
|
70
|
+
{{ row.access_level }}
|
|
71
|
+
</BaseBadge>
|
|
72
|
+
</BaseTableColumn>
|
|
73
|
+
|
|
74
|
+
<template #detail="{ row }">
|
|
75
|
+
<div class="p-4 text-sm">
|
|
76
|
+
<p>ID : {{ row.id }}</p>
|
|
77
|
+
<p>Created at : {{ row.created_at }}</p>
|
|
78
|
+
</div>
|
|
79
|
+
</template>
|
|
80
|
+
|
|
81
|
+
<template #filters="{ query, updateQueryValue }">
|
|
82
|
+
<div class="space-y-3">
|
|
83
|
+
<div>
|
|
84
|
+
<p class="mb-1 text-sm">
|
|
85
|
+
Type
|
|
86
|
+
</p>
|
|
87
|
+
<BaseSelect
|
|
88
|
+
:model-value="query.type ?? null"
|
|
89
|
+
class="w-full rounded border-slate-300"
|
|
90
|
+
@update:model-value="updateQueryValue('type', $event)"
|
|
91
|
+
>
|
|
92
|
+
<option value="">-</option>
|
|
93
|
+
<option value="video">
|
|
94
|
+
Video
|
|
95
|
+
</option>
|
|
96
|
+
<option value="article">
|
|
97
|
+
Article
|
|
98
|
+
</option>
|
|
99
|
+
</BaseSelect>
|
|
100
|
+
</div>
|
|
101
|
+
<div>
|
|
102
|
+
<p class="mb-1 text-sm">
|
|
103
|
+
Access Level
|
|
104
|
+
</p>
|
|
105
|
+
<BaseSelect
|
|
106
|
+
:model-value="query.access_level ?? null"
|
|
107
|
+
class="w-full rounded border-slate-300"
|
|
108
|
+
@update:model-value="updateQueryValue('access_level', $event)"
|
|
109
|
+
>
|
|
110
|
+
<option value="">-</option>
|
|
111
|
+
<option value="public">
|
|
112
|
+
Public
|
|
113
|
+
</option>
|
|
114
|
+
<option value="member">
|
|
115
|
+
Member
|
|
116
|
+
</option>
|
|
117
|
+
<option value="vip">
|
|
118
|
+
VIP
|
|
119
|
+
</option>
|
|
120
|
+
</BaseSelect>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</template>
|
|
56
124
|
</BaseDataTable>
|
|
125
|
+
<BaseAppNotifications></BaseAppNotifications>
|
|
126
|
+
<BaseAppDialogs></BaseAppDialogs>
|
|
57
127
|
`;
|
|
58
128
|
|
|
59
129
|
const Template = (args) => ({
|
|
60
|
-
components: {
|
|
130
|
+
components: {
|
|
131
|
+
BaseDataTable,
|
|
132
|
+
BaseTableColumn,
|
|
133
|
+
BaseBoolean,
|
|
134
|
+
BaseSelect,
|
|
135
|
+
BaseBadge,
|
|
136
|
+
BaseAppNotifications,
|
|
137
|
+
BaseAppDialogs,
|
|
138
|
+
},
|
|
61
139
|
setup() {
|
|
62
140
|
return { args };
|
|
63
141
|
},
|
|
@@ -86,10 +164,79 @@ Demo.args = {
|
|
|
86
164
|
color: 'danger',
|
|
87
165
|
},
|
|
88
166
|
],
|
|
167
|
+
checkable: true,
|
|
168
|
+
checkableActions: [
|
|
169
|
+
{
|
|
170
|
+
label: 'Delete all',
|
|
171
|
+
action: () => {
|
|
172
|
+
alert('delete!');
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
detailed: true,
|
|
177
|
+
maxHeight: 400,
|
|
178
|
+
editUrl() {
|
|
179
|
+
return '/';
|
|
180
|
+
},
|
|
181
|
+
deleteUrl() {
|
|
182
|
+
return '/';
|
|
183
|
+
},
|
|
89
184
|
};
|
|
90
185
|
|
|
91
|
-
|
|
186
|
+
const SimpleTemplate = (args) => ({
|
|
187
|
+
components: {
|
|
188
|
+
BaseDataTable,
|
|
189
|
+
BaseTableColumn,
|
|
190
|
+
BaseBoolean,
|
|
191
|
+
},
|
|
192
|
+
setup() {
|
|
193
|
+
return { args };
|
|
194
|
+
},
|
|
195
|
+
template: `
|
|
196
|
+
<BaseDataTable v-bind="args">
|
|
197
|
+
<BaseTableColumn
|
|
198
|
+
v-slot="{ row }"
|
|
199
|
+
label="Titre"
|
|
200
|
+
sortable
|
|
201
|
+
field="title->en"
|
|
202
|
+
:toggle="false"
|
|
203
|
+
>
|
|
204
|
+
<div class="max-w-sm">
|
|
205
|
+
<div class="font-medium text-slate-900">
|
|
206
|
+
{{ row.title }}
|
|
207
|
+
</div>
|
|
208
|
+
<p class="text-xs leading-tight text-slate-500">
|
|
209
|
+
{{ row.subtitle }}
|
|
210
|
+
</p>
|
|
211
|
+
</div>
|
|
212
|
+
</BaseTableColumn>
|
|
213
|
+
|
|
214
|
+
<BaseTableColumn
|
|
215
|
+
v-slot="{ row }"
|
|
216
|
+
label="VIP"
|
|
217
|
+
field="access_level"
|
|
218
|
+
sortable
|
|
219
|
+
>
|
|
220
|
+
<BaseBoolean :model-value="row.access_level == 'vip'" />
|
|
221
|
+
</BaseTableColumn>
|
|
222
|
+
|
|
223
|
+
<BaseTableColumn
|
|
224
|
+
v-slot="{ row }"
|
|
225
|
+
label="Vote"
|
|
226
|
+
field="votes_avg_score"
|
|
227
|
+
sortable
|
|
228
|
+
>
|
|
229
|
+
<div class="">
|
|
230
|
+
{{ Math.round(row.votes_avg_score) }} / 5
|
|
231
|
+
</div>
|
|
232
|
+
</BaseTableColumn>
|
|
233
|
+
</BaseDataTable>
|
|
234
|
+
`,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
export const Simple = SimpleTemplate.bind({});
|
|
92
238
|
Simple.args = {
|
|
93
239
|
searchable: false,
|
|
240
|
+
toggleable: false,
|
|
94
241
|
actions: [],
|
|
95
242
|
};
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
firstLoad,
|
|
21
21
|
}"
|
|
22
22
|
>
|
|
23
|
-
<BaseCard clipped class="
|
|
23
|
+
<BaseCard clipped class="w-full overflow-hidden">
|
|
24
24
|
<BaseTable
|
|
25
25
|
ref="table"
|
|
26
26
|
:data="items"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
<BaseTableColumn
|
|
49
49
|
v-slot="{ row }"
|
|
50
50
|
:visible="editButton || deleteButton || $slots.rowActions != null"
|
|
51
|
-
:
|
|
51
|
+
:toggle="false"
|
|
52
52
|
>
|
|
53
53
|
<div class="flex justify-end text-right">
|
|
54
54
|
<slot name="rowActions" :row="row" />
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
:to="editUrl(row)"
|
|
59
59
|
:disabled="!canUpdate(row)"
|
|
60
60
|
>
|
|
61
|
-
<button class="btn btn-white p-2">
|
|
61
|
+
<button class="btn btn-white bg-transparent p-2">
|
|
62
62
|
<BaseIcon
|
|
63
63
|
icon="heroicons:cog-6-tooth-solid"
|
|
64
64
|
class="text-slate-500"
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
<button
|
|
70
70
|
v-if="deleteButton && deleteUrl"
|
|
71
71
|
type="button"
|
|
72
|
-
class="btn btn-white p-2"
|
|
72
|
+
class="btn btn-white bg-transparent p-2"
|
|
73
73
|
:disabled="!canDelete(row)"
|
|
74
74
|
@click="onDeleteClick(row)"
|
|
75
75
|
>
|
|
@@ -107,11 +107,8 @@
|
|
|
107
107
|
class="flex items-center justify-center py-16"
|
|
108
108
|
>
|
|
109
109
|
<div class="flex flex-col items-center">
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
alt="No data"
|
|
113
|
-
width="100"
|
|
114
|
-
/>
|
|
110
|
+
<BaseEmptyState class="w-32"></BaseEmptyState>
|
|
111
|
+
|
|
115
112
|
<p class="mt-3 text-center text-sm text-slate-600">
|
|
116
113
|
{{ $t('sui.nothing_found') }}
|
|
117
114
|
</p>
|
|
@@ -138,7 +135,7 @@
|
|
|
138
135
|
<slot name="sidebarTop" v-bind="sidebarProps"></slot>
|
|
139
136
|
</template>
|
|
140
137
|
|
|
141
|
-
<template #sidebarBottom>
|
|
138
|
+
<template v-if="toggleable" #sidebarBottom>
|
|
142
139
|
<div class="mb-3">
|
|
143
140
|
<h3
|
|
144
141
|
class="mb-1 text-xs font-semibold uppercase tracking-wider text-slate-500"
|
|
@@ -177,6 +174,7 @@ import BaseTable from './BaseTable.vue';
|
|
|
177
174
|
import BaseTableColumn from './BaseTableColumn.vue';
|
|
178
175
|
import BaseDataTableToggleColumns from './BaseDataTableToggleColumns.vue';
|
|
179
176
|
import { config } from '@/index';
|
|
177
|
+
import BaseEmptyState from '../svg/BaseEmptyState.vue';
|
|
180
178
|
|
|
181
179
|
const i18n = useI18n();
|
|
182
180
|
|
|
@@ -196,22 +194,6 @@ const props = defineProps({
|
|
|
196
194
|
type: String,
|
|
197
195
|
},
|
|
198
196
|
|
|
199
|
-
/**
|
|
200
|
-
* Show/Hide edit button
|
|
201
|
-
*/
|
|
202
|
-
editButton: {
|
|
203
|
-
default: true,
|
|
204
|
-
type: Boolean,
|
|
205
|
-
},
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Show/Hide delete button
|
|
209
|
-
*/
|
|
210
|
-
deleteButton: {
|
|
211
|
-
default: true,
|
|
212
|
-
type: Boolean,
|
|
213
|
-
},
|
|
214
|
-
|
|
215
197
|
/**
|
|
216
198
|
* Route key name for Laravel route model binding
|
|
217
199
|
*/
|
|
@@ -237,6 +219,14 @@ const props = defineProps({
|
|
|
237
219
|
type: Object as PropType<DataTableQuery>,
|
|
238
220
|
},
|
|
239
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Show/Hide edit button
|
|
224
|
+
*/
|
|
225
|
+
editButton: {
|
|
226
|
+
default: true,
|
|
227
|
+
type: Boolean,
|
|
228
|
+
},
|
|
229
|
+
|
|
240
230
|
/**
|
|
241
231
|
* Edit url for router link
|
|
242
232
|
*/
|
|
@@ -245,6 +235,14 @@ const props = defineProps({
|
|
|
245
235
|
type: Function as PropType<(row: CollectionItem) => string>,
|
|
246
236
|
},
|
|
247
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Show/Hide delete button
|
|
240
|
+
*/
|
|
241
|
+
deleteButton: {
|
|
242
|
+
default: true,
|
|
243
|
+
type: Boolean,
|
|
244
|
+
},
|
|
245
|
+
|
|
248
246
|
/**
|
|
249
247
|
* Delete endpoint to delete an item
|
|
250
248
|
*/
|
|
@@ -262,7 +260,7 @@ const props = defineProps({
|
|
|
262
260
|
},
|
|
263
261
|
|
|
264
262
|
/**
|
|
265
|
-
*
|
|
263
|
+
* Check is a given row has details
|
|
266
264
|
*/
|
|
267
265
|
hasDetailedVisible: {
|
|
268
266
|
default() {
|
|
@@ -315,6 +313,14 @@ const props = defineProps({
|
|
|
315
313
|
type: Boolean,
|
|
316
314
|
},
|
|
317
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Shows the column toggle utility
|
|
318
|
+
*/
|
|
319
|
+
toggleable: {
|
|
320
|
+
default: true,
|
|
321
|
+
type: Boolean,
|
|
322
|
+
},
|
|
323
|
+
|
|
318
324
|
/**
|
|
319
325
|
* Actions
|
|
320
326
|
*/
|
|
@@ -388,7 +394,7 @@ function onDeleteClick(row: CollectionItem) {
|
|
|
388
394
|
title: i18n.t('sui.delete_record') + '?',
|
|
389
395
|
message: i18n.t('sui.delete_record_description'),
|
|
390
396
|
color: 'danger',
|
|
391
|
-
closeOnOutsideClick:
|
|
397
|
+
closeOnOutsideClick: true,
|
|
392
398
|
confirmText: i18n.t('sui.yes_delete'),
|
|
393
399
|
onConfirm: () => onDelete(row),
|
|
394
400
|
});
|
|
@@ -54,13 +54,13 @@
|
|
|
54
54
|
<div class="w-auto p-0.5">
|
|
55
55
|
<select
|
|
56
56
|
v-model="date.day"
|
|
57
|
-
:disabled="
|
|
57
|
+
:disabled="dayDisabled"
|
|
58
58
|
:required="required"
|
|
59
59
|
data-cy="day"
|
|
60
60
|
class="w-full rounded capitalize"
|
|
61
61
|
:class="[
|
|
62
62
|
{
|
|
63
|
-
'cursor-not-allowed bg-slate-100 text-slate-500':
|
|
63
|
+
'cursor-not-allowed bg-slate-100 text-slate-500': dayDisabled,
|
|
64
64
|
},
|
|
65
65
|
inputClass,
|
|
66
66
|
]"
|
|
@@ -189,4 +189,8 @@ function getDateTime(): DateTime | null {
|
|
|
189
189
|
padStart(date.value.day + '', 2, '0')
|
|
190
190
|
);
|
|
191
191
|
}
|
|
192
|
+
|
|
193
|
+
const dayDisabled = computed(() => {
|
|
194
|
+
return days.value.length == 0 || props.disabled;
|
|
195
|
+
});
|
|
192
196
|
</script>
|
|
@@ -1,12 +1,48 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
2
|
+
<div
|
|
3
|
+
ref="item"
|
|
4
|
+
:class="{
|
|
5
|
+
'px-4 py-4': mobile,
|
|
6
|
+
'grid grid-cols-3 gap-4 py-5 px-6': !mobile,
|
|
7
|
+
}"
|
|
8
|
+
>
|
|
9
|
+
<dt class="text-sm font-medium leading-tight text-slate-500">
|
|
4
10
|
<slot name="left" />
|
|
5
11
|
</dt>
|
|
6
|
-
<dd
|
|
12
|
+
<dd
|
|
13
|
+
class="text-sm leading-tight text-slate-900"
|
|
14
|
+
:class="{
|
|
15
|
+
'mt-1.5': mobile,
|
|
16
|
+
'col-span-2': !mobile,
|
|
17
|
+
}"
|
|
18
|
+
>
|
|
7
19
|
<slot name="right" />
|
|
8
20
|
</dd>
|
|
9
21
|
</div>
|
|
10
22
|
</template>
|
|
11
23
|
|
|
12
|
-
<script lang="ts" setup
|
|
24
|
+
<script lang="ts" setup>
|
|
25
|
+
import { useResizeObserver } from '@vueuse/core';
|
|
26
|
+
import { debounce } from 'lodash';
|
|
27
|
+
import { Ref } from 'vue';
|
|
28
|
+
import breakpoints from '../../config/breakpoints.json';
|
|
29
|
+
|
|
30
|
+
const DEFAULT_WIDTH = 800;
|
|
31
|
+
|
|
32
|
+
const item = ref(null) as Ref<HTMLElement | null>;
|
|
33
|
+
const width = ref(DEFAULT_WIDTH);
|
|
34
|
+
|
|
35
|
+
const mobile = computed(() => {
|
|
36
|
+
return width.value < breakpoints.sm;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
function setWidth() {
|
|
40
|
+
width.value = item.value?.clientWidth ?? DEFAULT_WIDTH;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onMounted(() => {
|
|
44
|
+
setWidth();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
useResizeObserver(item, debounce(setWidth, 50));
|
|
48
|
+
</script>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import BaseDialog from './BaseDialog.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Components/BaseDialog',
|
|
5
|
+
component: BaseDialog,
|
|
6
|
+
argTypes: {
|
|
7
|
+
color: {
|
|
8
|
+
control: { type: 'select' },
|
|
9
|
+
options: ['success', 'info', 'warning', 'danger'],
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
args: {
|
|
13
|
+
message:
|
|
14
|
+
'Nisi Lorem sunt amet aliqua dolor ullamco deserunt enim irure non ad. Excepteur culpa consectetur dolore culpa sunt aliquip proident quis.',
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const Template = (args) => ({
|
|
19
|
+
components: { BaseDialog },
|
|
20
|
+
setup() {
|
|
21
|
+
return { args };
|
|
22
|
+
},
|
|
23
|
+
template: `
|
|
24
|
+
<BaseDialog v-bind="args">
|
|
25
|
+
</BaseDialog>
|
|
26
|
+
`,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const Demo = Template.bind({});
|
|
30
|
+
Demo.args = {
|
|
31
|
+
title: 'Be careful',
|
|
32
|
+
color: 'warning',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const Success = Template.bind({});
|
|
36
|
+
Success.args = {
|
|
37
|
+
title: 'Success',
|
|
38
|
+
color: 'success',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const Danger = Template.bind({});
|
|
42
|
+
Danger.args = {
|
|
43
|
+
title: 'Error',
|
|
44
|
+
color: 'danger',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const Info = Template.bind({});
|
|
48
|
+
Info.args = {
|
|
49
|
+
title: 'Information',
|
|
50
|
+
color: 'info',
|
|
51
|
+
};
|
|
@@ -15,22 +15,22 @@
|
|
|
15
15
|
<BaseIcon
|
|
16
16
|
v-if="color == 'danger'"
|
|
17
17
|
class="h-6 w-6 text-red-600"
|
|
18
|
-
icon="heroicons:
|
|
18
|
+
icon="heroicons:exclamation-triangle-20-solid"
|
|
19
19
|
/>
|
|
20
20
|
<BaseIcon
|
|
21
21
|
v-else-if="color == 'warning'"
|
|
22
22
|
class="h-6 w-6 text-yellow-600"
|
|
23
|
-
icon="heroicons:
|
|
23
|
+
icon="heroicons:exclamation-triangle-20-solid"
|
|
24
24
|
/>
|
|
25
25
|
<BaseIcon
|
|
26
26
|
v-else-if="color == 'success'"
|
|
27
27
|
class="h-6 w-6 text-green-600"
|
|
28
|
-
icon="heroicons:check-circle"
|
|
28
|
+
icon="heroicons:check-circle-20-solid"
|
|
29
29
|
/>
|
|
30
30
|
<BaseIcon
|
|
31
31
|
v-else
|
|
32
32
|
class="h-6 w-6 text-primary-600"
|
|
33
|
-
icon="heroicons:information-circle"
|
|
33
|
+
icon="heroicons:information-circle-20-solid"
|
|
34
34
|
/>
|
|
35
35
|
</div>
|
|
36
36
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
{{ title }}
|
|
43
43
|
</h3>
|
|
44
44
|
<div class="mt-2">
|
|
45
|
-
<p class="text-
|
|
45
|
+
<p class="text-base font-light text-slate-600">
|
|
46
46
|
{{ message }}
|
|
47
47
|
</p>
|
|
48
48
|
</div>
|
|
@@ -92,11 +92,17 @@ defineProps({
|
|
|
92
92
|
type: String,
|
|
93
93
|
},
|
|
94
94
|
confirmText: {
|
|
95
|
-
default
|
|
95
|
+
default() {
|
|
96
|
+
const i18n = useI18n();
|
|
97
|
+
return i18n.t('sui.confirm');
|
|
98
|
+
},
|
|
96
99
|
type: String,
|
|
97
100
|
},
|
|
98
101
|
cancelText: {
|
|
99
|
-
default
|
|
102
|
+
default() {
|
|
103
|
+
const i18n = useI18n();
|
|
104
|
+
return i18n.t('sui.cancel');
|
|
105
|
+
},
|
|
100
106
|
type: String,
|
|
101
107
|
},
|
|
102
108
|
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import BaseFilePicker from './BaseFilePicker.vue';
|
|
2
|
+
import { Icon as BaseIcon } from '@iconify/vue';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Form/BaseFilePicker',
|
|
6
|
+
component: BaseFilePicker,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const Template = (args) => ({
|
|
10
|
+
components: { BaseFilePicker, BaseIcon },
|
|
11
|
+
setup() {
|
|
12
|
+
return { args };
|
|
13
|
+
},
|
|
14
|
+
template: `
|
|
15
|
+
<BaseFilePicker v-bind="args">
|
|
16
|
+
<template #default="{ dragging, disabled }">
|
|
17
|
+
<div
|
|
18
|
+
class="flex w-full items-center space-x-4 rounded-lg border-2 border-dashed border-slate-200 p-5 duration-100"
|
|
19
|
+
:class="[
|
|
20
|
+
dragging ? 'bg-slate-100' : 'bg-white',
|
|
21
|
+
disabled ? 'bg-slate-100 cursor-not-allowed' : 'hover:bg-slate-50',
|
|
22
|
+
]"
|
|
23
|
+
>
|
|
24
|
+
<div class="rounded-full bg-slate-200 p-2">
|
|
25
|
+
<BaseIcon
|
|
26
|
+
icon="heroicons:arrow-up-on-square"
|
|
27
|
+
class="h-6 w-6"
|
|
28
|
+
:class="[disabled ? 'text-slate-400' : 'text-slate-500']"
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="text-left">
|
|
32
|
+
<p
|
|
33
|
+
class="mb-0 text-sm font-medium leading-tight"
|
|
34
|
+
:class="[disabled ? 'text-slate-400' : 'text-slate-900']"
|
|
35
|
+
>
|
|
36
|
+
{{ $t("sui.drop_or_click_to_upload") }}
|
|
37
|
+
</p>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
41
|
+
</BaseFilePicker>
|
|
42
|
+
`,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const Demo = Template.bind({});
|
|
46
|
+
Demo.args = {};
|
|
47
|
+
|
|
48
|
+
export const Disabled = Template.bind({});
|
|
49
|
+
Disabled.args = {
|
|
50
|
+
disabled: true,
|
|
51
|
+
};
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
@dragenter.prevent="dragging = true"
|
|
13
13
|
@click="pickFile"
|
|
14
14
|
>
|
|
15
|
-
<slot :selecting="selecting" :dragging="dragging" />
|
|
15
|
+
<slot :selecting="selecting" :dragging="dragging" :disabled="disabled" />
|
|
16
16
|
</button>
|
|
17
17
|
<input
|
|
18
18
|
ref="input"
|
|
@@ -41,7 +41,7 @@ export default defineComponent({
|
|
|
41
41
|
type: String,
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
|
-
emits: ['
|
|
44
|
+
emits: ['select'],
|
|
45
45
|
data() {
|
|
46
46
|
return {
|
|
47
47
|
selecting: false,
|
|
@@ -63,7 +63,7 @@ export default defineComponent({
|
|
|
63
63
|
},
|
|
64
64
|
onInputChange() {
|
|
65
65
|
const files = (this.inputElement?.files ?? []) as File[];
|
|
66
|
-
this.
|
|
66
|
+
this.select(files);
|
|
67
67
|
},
|
|
68
68
|
handleDrop(e: any) {
|
|
69
69
|
if (this.disabled) {
|
|
@@ -72,9 +72,9 @@ export default defineComponent({
|
|
|
72
72
|
|
|
73
73
|
const files = e?.dataTransfer?.files ?? [];
|
|
74
74
|
|
|
75
|
-
this.
|
|
75
|
+
this.select(files);
|
|
76
76
|
},
|
|
77
|
-
async
|
|
77
|
+
async select(files: File[]) {
|
|
78
78
|
if (this.disabled) {
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
@@ -88,7 +88,7 @@ export default defineComponent({
|
|
|
88
88
|
try {
|
|
89
89
|
const file = files[0];
|
|
90
90
|
|
|
91
|
-
this.$emit('
|
|
91
|
+
this.$emit('select', file);
|
|
92
92
|
} finally {
|
|
93
93
|
if (this.inputElement) {
|
|
94
94
|
this.inputElement.value = '';
|