sprintify-ui 0.0.12 → 0.0.14
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 +8 -7
- package/dist/sprintify-ui.es.js +4429 -3588
- package/dist/style.css +1 -1
- package/dist/tailwindcss/index.js +13 -4
- package/dist/types/src/components/BaseAutocomplete.vue.d.ts +8 -5
- package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +8 -5
- package/dist/types/src/components/BaseBelongsTo.vue.d.ts +8 -5
- package/dist/types/src/components/BaseCharacterCounter.vue.d.ts +4 -4
- package/dist/types/src/components/BaseDatePicker.vue.d.ts +8 -5
- package/dist/types/src/components/BaseHasMany.vue.d.ts +277 -0
- package/dist/types/src/components/BaseInput.vue.d.ts +39 -1
- package/dist/types/src/components/{BaseMediaLibraryItem.vue.d.ts → BaseMediaItem.vue.d.ts} +26 -4
- package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +23 -15
- package/dist/types/src/components/BaseMediaPreview.vue.d.ts +97 -0
- package/dist/types/src/components/BaseSelect.vue.d.ts +7 -7
- package/dist/types/src/components/BaseSideNavigationItem.vue.d.ts +20 -1
- package/dist/types/src/components/BaseTabItem.vue.d.ts +20 -1
- package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +25 -17
- package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +37 -21
- package/dist/types/src/components/BaseTextarea.vue.d.ts +8 -5
- package/dist/types/src/components/index.d.ts +10 -4
- package/package.json +1 -1
- package/src/components/BaseAppDialogs.vue +2 -2
- package/src/components/BaseAppNotifications.vue +1 -1
- package/src/components/BaseAutocomplete.vue +18 -20
- package/src/components/BaseAutocompleteFetch.vue +2 -2
- package/src/components/BaseBelongsTo.vue +3 -2
- package/src/components/BaseClipboard.vue +1 -1
- package/src/components/BaseDatePicker.vue +2 -2
- package/src/components/BaseHasMany.vue +92 -0
- package/src/components/BaseInput.stories.js +20 -1
- package/src/components/BaseInput.vue +42 -14
- package/src/components/BaseMediaItem.stories.js +41 -0
- package/src/components/BaseMediaItem.vue +71 -0
- package/src/components/BaseMediaLibrary.stories.js +80 -0
- package/src/components/BaseMediaLibrary.vue +67 -68
- package/src/components/BaseMediaPreview.stories.js +72 -0
- package/src/components/BaseMediaPreview.vue +90 -0
- package/src/components/BaseMenu.vue +1 -1
- package/src/components/BaseSelect.vue +1 -1
- package/src/components/BaseSideNavigationItem.vue +11 -3
- package/src/components/BaseSystemAlert.vue +1 -1
- package/src/components/BaseTabItem.vue +13 -3
- package/src/components/BaseTable.vue +2 -2
- package/src/components/BaseTagAutocomplete.stories.js +129 -0
- package/src/components/BaseTagAutocomplete.vue +155 -57
- package/src/components/BaseTagAutocompleteFetch.stories.js +130 -0
- package/src/components/BaseTagAutocompleteFetch.vue +36 -25
- package/src/components/BaseTextarea.vue +2 -2
- package/src/components/HasMany.stories.js +135 -0
- package/src/components/index.ts +18 -6
- package/src/lang/en.json +1 -1
- package/src/lang/fr.json +1 -1
- package/dist/types/src/components/BasePaginationSimple.vue.d.ts +0 -25
- package/src/components/BaseMediaLibraryItem.vue +0 -92
- package/src/components/BasePaginationSimple.vue +0 -60
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<BaseTagAutocomplete
|
|
3
|
-
:loading="
|
|
3
|
+
:loading="showLoading && page == 1"
|
|
4
4
|
:model-value="modelValue"
|
|
5
5
|
:disabled="disabled"
|
|
6
6
|
:placeholder="placeholder"
|
|
@@ -8,22 +8,30 @@
|
|
|
8
8
|
:value-key="valueKey"
|
|
9
9
|
:label-key="labelKey"
|
|
10
10
|
:input-class="inputClass"
|
|
11
|
-
:min="min"
|
|
12
11
|
:max="max"
|
|
12
|
+
:filter="() => true"
|
|
13
13
|
@focus="onFocus"
|
|
14
14
|
@typing="onTyping"
|
|
15
15
|
@scroll-bottom="scrollBottom"
|
|
16
16
|
@update:model-value="$emit('update:modelValue', $event)"
|
|
17
17
|
>
|
|
18
|
-
<template #
|
|
19
|
-
<
|
|
20
|
-
|
|
18
|
+
<template #option="optionProps">
|
|
19
|
+
<slot name="option" v-bind="optionProps" />
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<template #footer="footerProps">
|
|
23
|
+
<slot name="footer" v-bind="footerProps" :keywords="keywords"> </slot>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<template #empty="emptyProps">
|
|
27
|
+
<slot name="empty" v-bind="emptyProps" :first-search="firstSearch">
|
|
28
|
+
<div
|
|
29
|
+
v-if="firstSearch"
|
|
30
|
+
class="flex h-[80px] items-center justify-center px-3 text-center text-base leading-tight text-slate-600"
|
|
31
|
+
>
|
|
21
32
|
{{ $t('sui.nothing_found') }}
|
|
22
|
-
</
|
|
23
|
-
|
|
24
|
-
{{ $t('sui.autocomplete_placeholder') }}
|
|
25
|
-
</span>
|
|
26
|
-
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</slot>
|
|
27
35
|
</template>
|
|
28
36
|
</BaseTagAutocomplete>
|
|
29
37
|
</template>
|
|
@@ -33,6 +41,7 @@ import { debounce } from 'lodash';
|
|
|
33
41
|
import { config } from '@/index';
|
|
34
42
|
import { PropType, Ref } from 'vue';
|
|
35
43
|
import { Option } from '@/types/types';
|
|
44
|
+
import BaseTagAutocomplete from './BaseTagAutocomplete.vue';
|
|
36
45
|
|
|
37
46
|
const props = defineProps({
|
|
38
47
|
modelValue: {
|
|
@@ -67,21 +76,22 @@ const props = defineProps({
|
|
|
67
76
|
default: false,
|
|
68
77
|
type: Boolean,
|
|
69
78
|
},
|
|
70
|
-
min: {
|
|
71
|
-
default: undefined,
|
|
72
|
-
type: Number,
|
|
73
|
-
},
|
|
74
79
|
max: {
|
|
75
80
|
default: undefined,
|
|
76
81
|
type: Number,
|
|
77
82
|
},
|
|
83
|
+
queryKey: {
|
|
84
|
+
default: 'search',
|
|
85
|
+
type: String,
|
|
86
|
+
},
|
|
78
87
|
});
|
|
79
88
|
|
|
80
89
|
defineEmits(['update:modelValue', 'typing', 'focus', 'scrollBottom']);
|
|
81
90
|
|
|
82
91
|
const http = config.http;
|
|
83
92
|
|
|
84
|
-
const
|
|
93
|
+
const showLoading = ref(false);
|
|
94
|
+
const fetching = ref(false);
|
|
85
95
|
const firstSearch = ref(false);
|
|
86
96
|
const reachedEnd = ref(false);
|
|
87
97
|
const keywords = ref('');
|
|
@@ -94,18 +104,15 @@ const onTyping = (query: string) => {
|
|
|
94
104
|
|
|
95
105
|
if (keywords.value != query) {
|
|
96
106
|
keywords.value = query;
|
|
107
|
+
showLoading.value = true;
|
|
97
108
|
debouncedSearch();
|
|
98
109
|
}
|
|
99
110
|
};
|
|
100
111
|
|
|
101
112
|
const onFocus = () => {
|
|
102
|
-
if (firstSearch.value) {
|
|
103
|
-
|
|
113
|
+
if (!firstSearch.value) {
|
|
114
|
+
search();
|
|
104
115
|
}
|
|
105
|
-
|
|
106
|
-
search();
|
|
107
|
-
|
|
108
|
-
firstSearch.value = true;
|
|
109
116
|
};
|
|
110
117
|
|
|
111
118
|
const scrollBottom = () => {
|
|
@@ -116,17 +123,18 @@ const scrollBottom = () => {
|
|
|
116
123
|
};
|
|
117
124
|
|
|
118
125
|
const search = () => {
|
|
119
|
-
if (
|
|
126
|
+
if (fetching.value) {
|
|
120
127
|
return;
|
|
121
128
|
}
|
|
122
129
|
|
|
123
|
-
|
|
130
|
+
fetching.value = true;
|
|
131
|
+
showLoading.value = true;
|
|
124
132
|
firstSearch.value = true;
|
|
125
133
|
|
|
126
134
|
http
|
|
127
135
|
.get(props.url, {
|
|
128
136
|
params: {
|
|
129
|
-
|
|
137
|
+
[props.queryKey]: keywords.value,
|
|
130
138
|
page: page.value,
|
|
131
139
|
},
|
|
132
140
|
})
|
|
@@ -142,9 +150,12 @@ const search = () => {
|
|
|
142
150
|
} else {
|
|
143
151
|
options.value.push(...data);
|
|
144
152
|
}
|
|
153
|
+
|
|
154
|
+
firstSearch.value = true;
|
|
145
155
|
})
|
|
146
156
|
.finally(() => {
|
|
147
|
-
|
|
157
|
+
fetching.value = false;
|
|
158
|
+
showLoading.value = false;
|
|
148
159
|
});
|
|
149
160
|
};
|
|
150
161
|
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import BaseHasMany from './BaseHasMany.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Form/BaseHasMany',
|
|
5
|
+
component: BaseHasMany,
|
|
6
|
+
argTypes: {},
|
|
7
|
+
args: {
|
|
8
|
+
url: 'https://effettandem.com/api/content/articles',
|
|
9
|
+
field: 'title',
|
|
10
|
+
foreignKey: 'id',
|
|
11
|
+
},
|
|
12
|
+
decorators: [() => ({ template: '<div class="mb-36"><story/></div>' })],
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const Template = (args) => {
|
|
16
|
+
return {
|
|
17
|
+
components: { BaseHasMany },
|
|
18
|
+
setup() {
|
|
19
|
+
const value = ref([]);
|
|
20
|
+
return { args, value };
|
|
21
|
+
},
|
|
22
|
+
template: `
|
|
23
|
+
<BaseHasMany
|
|
24
|
+
v-model="value"
|
|
25
|
+
v-bind="args"
|
|
26
|
+
></BaseHasMany>
|
|
27
|
+
<p class="mt-5 text-sm">Value: <span class="bg-slate-200 font-mono px-1 py-px rounded">{{ value ?? '[]' }}</span></p>
|
|
28
|
+
`,
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const Demo = Template.bind({});
|
|
33
|
+
Demo.args = {};
|
|
34
|
+
|
|
35
|
+
export const Disabled = (args) => {
|
|
36
|
+
return {
|
|
37
|
+
components: { BaseHasMany },
|
|
38
|
+
setup() {
|
|
39
|
+
const value = ref([]);
|
|
40
|
+
return { args, value };
|
|
41
|
+
},
|
|
42
|
+
template: `<BaseHasMany
|
|
43
|
+
v-bind="args"
|
|
44
|
+
v-model="value"
|
|
45
|
+
:current-models="[{title: 'Dark Vader', id: 1}]"
|
|
46
|
+
:disabled="true"
|
|
47
|
+
></BaseHasMany>`,
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const Maximum = Template.bind({});
|
|
52
|
+
Maximum.args = {
|
|
53
|
+
max: 3,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const SlotOption = (args) => {
|
|
57
|
+
return {
|
|
58
|
+
components: { BaseHasMany },
|
|
59
|
+
setup() {
|
|
60
|
+
const value = ref([]);
|
|
61
|
+
return { args, value };
|
|
62
|
+
},
|
|
63
|
+
template: `
|
|
64
|
+
<div class="mb-20">
|
|
65
|
+
<BaseHasMany
|
|
66
|
+
v-model="value"
|
|
67
|
+
v-bind="args"
|
|
68
|
+
>
|
|
69
|
+
<template #option="{ option, active, selected }">
|
|
70
|
+
<div
|
|
71
|
+
class="rounded px-2 py-1"
|
|
72
|
+
:class="{
|
|
73
|
+
'hover:bg-slate-100': !active && !selected,
|
|
74
|
+
'bg-slate-200 hover:bg-slate-300': active && !selected,
|
|
75
|
+
'bg-blue-500 text-white hover:bg-blue-600': !active && selected,
|
|
76
|
+
'bg-blue-600 text-white hover:bg-blue-700': active && selected,
|
|
77
|
+
}"
|
|
78
|
+
>
|
|
79
|
+
<p class="text-sm font-medium">{{ option.title }}</p>
|
|
80
|
+
<p class="opacity-60 text-xs">{{ option.owner?.name }}</p>
|
|
81
|
+
</div>
|
|
82
|
+
</template>
|
|
83
|
+
</BaseHasMany>
|
|
84
|
+
</div>
|
|
85
|
+
`,
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const SlotFooter = (args) => {
|
|
90
|
+
return {
|
|
91
|
+
components: { BaseHasMany },
|
|
92
|
+
setup() {
|
|
93
|
+
const value = ref([]);
|
|
94
|
+
function onClick() {
|
|
95
|
+
alert(1);
|
|
96
|
+
}
|
|
97
|
+
return { args, value, onClick };
|
|
98
|
+
},
|
|
99
|
+
template: `
|
|
100
|
+
<BaseHasMany
|
|
101
|
+
v-model="value"
|
|
102
|
+
v-bind="args"
|
|
103
|
+
>
|
|
104
|
+
<template #footer>
|
|
105
|
+
<div class="text-center p-2 border-t">
|
|
106
|
+
<button @click=onClick class="btn btn-sm w-full btn-slate-200-outline">This is the footer 💯</button>
|
|
107
|
+
</div>
|
|
108
|
+
</template>
|
|
109
|
+
</BaseHasMany>
|
|
110
|
+
`,
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const SlotEmpty = (args) => {
|
|
115
|
+
return {
|
|
116
|
+
components: { BaseHasMany },
|
|
117
|
+
setup() {
|
|
118
|
+
const value = ref([]);
|
|
119
|
+
return { args, value };
|
|
120
|
+
},
|
|
121
|
+
template: `
|
|
122
|
+
<BaseHasMany
|
|
123
|
+
v-model="value"
|
|
124
|
+
v-bind="args"
|
|
125
|
+
>
|
|
126
|
+
<template #empty="props">
|
|
127
|
+
<div>
|
|
128
|
+
<div v-if="props.firstSearch" class="text-center py-10 p-6">🤓🤓🤓</div>
|
|
129
|
+
<div v-else class="text-center px-6 py-20">Start your search... 🔎</div>
|
|
130
|
+
</div>
|
|
131
|
+
</template>
|
|
132
|
+
</BaseHasMany>
|
|
133
|
+
`,
|
|
134
|
+
};
|
|
135
|
+
};
|
package/src/components/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import BaseBreadcrumbs from './BaseBreadcrumbs.vue';
|
|
|
12
12
|
import BaseButton from './BaseButton.vue';
|
|
13
13
|
import BaseCard from './BaseCard.vue';
|
|
14
14
|
import BaseCardRow from './BaseCardRow.vue';
|
|
15
|
+
import BaseCharacterCounter from './BaseCharacterCounter.vue';
|
|
15
16
|
import BaseClipboard from './BaseClipboard.vue';
|
|
16
17
|
import BaseContainer from './BaseContainer.vue';
|
|
17
18
|
import BaseCounter from './BaseCounter.vue';
|
|
@@ -24,10 +25,14 @@ import BaseDescriptionListItem from './BaseDescriptionListItem.vue';
|
|
|
24
25
|
import BaseDialog from './BaseDialog.vue';
|
|
25
26
|
import BaseFilePicker from './BaseFilePicker.vue';
|
|
26
27
|
import BaseFileUploader from './BaseFileUploader.vue';
|
|
28
|
+
import BaseHasMany from './BaseHasMany.vue';
|
|
27
29
|
import { Icon as BaseIcon } from '@iconify/vue';
|
|
28
30
|
import BaseInput from './BaseInput.vue';
|
|
29
31
|
import BaseInputLabel from './BaseInputLabel.vue';
|
|
30
32
|
import BaseLoadingCover from './BaseLoadingCover.vue';
|
|
33
|
+
import BaseMediaItem from './BaseMediaItem.vue';
|
|
34
|
+
import BaseMediaLibrary from './BaseMediaLibrary.vue';
|
|
35
|
+
import BaseMediaPreview from './BaseMediaPreview.vue';
|
|
31
36
|
import BaseMenu from './BaseMenu.vue';
|
|
32
37
|
import BaseMenuItem from './BaseMenuItem.vue';
|
|
33
38
|
import BaseModalCenter from './BaseModalCenter.vue';
|
|
@@ -46,13 +51,14 @@ import BaseSideNavigationItem from './BaseSideNavigationItem.vue';
|
|
|
46
51
|
import BaseSkeleton from './BaseSkeleton.vue';
|
|
47
52
|
import BaseSwitch from './BaseSwitch.vue';
|
|
48
53
|
import BaseSystemAlert from './BaseSystemAlert.vue';
|
|
49
|
-
import BaseTextarea from './BaseTextarea.vue';
|
|
50
|
-
import BaseTextareaAutoresize from './BaseTextareaAutoresize.vue';
|
|
51
|
-
import BaseCharacterCounter from './BaseCharacterCounter.vue';
|
|
52
54
|
import BaseTabs from './BaseTabs.vue';
|
|
53
55
|
import BaseTabItem from './BaseTabItem.vue';
|
|
56
|
+
import BaseTagAutocomplete from './BaseTagAutocomplete.vue';
|
|
57
|
+
import BaseTagAutocompleteFetch from './BaseTagAutocompleteFetch.vue';
|
|
54
58
|
import BaseTable from './BaseTable.vue';
|
|
55
59
|
import BaseTableColumn from './BaseTableColumn.vue';
|
|
60
|
+
import BaseTextarea from './BaseTextarea.vue';
|
|
61
|
+
import BaseTextareaAutoresize from './BaseTextareaAutoresize.vue';
|
|
56
62
|
|
|
57
63
|
export {
|
|
58
64
|
BaseAlert,
|
|
@@ -69,6 +75,7 @@ export {
|
|
|
69
75
|
BaseButton,
|
|
70
76
|
BaseCard,
|
|
71
77
|
BaseCardRow,
|
|
78
|
+
BaseCharacterCounter,
|
|
72
79
|
BaseClipboard,
|
|
73
80
|
BaseContainer,
|
|
74
81
|
BaseCounter,
|
|
@@ -81,10 +88,14 @@ export {
|
|
|
81
88
|
BaseDialog,
|
|
82
89
|
BaseFilePicker,
|
|
83
90
|
BaseFileUploader,
|
|
91
|
+
BaseHasMany,
|
|
84
92
|
BaseIcon,
|
|
85
93
|
BaseInput,
|
|
86
94
|
BaseInputLabel,
|
|
87
95
|
BaseLoadingCover,
|
|
96
|
+
BaseMediaItem,
|
|
97
|
+
BaseMediaLibrary,
|
|
98
|
+
BaseMediaPreview,
|
|
88
99
|
BaseMenu,
|
|
89
100
|
BaseMenuItem,
|
|
90
101
|
BaseModalCenter,
|
|
@@ -103,11 +114,12 @@ export {
|
|
|
103
114
|
BaseSkeleton,
|
|
104
115
|
BaseSwitch,
|
|
105
116
|
BaseSystemAlert,
|
|
106
|
-
BaseTextarea,
|
|
107
|
-
BaseTextareaAutoresize,
|
|
108
|
-
BaseCharacterCounter,
|
|
109
117
|
BaseTabs,
|
|
110
118
|
BaseTabItem,
|
|
119
|
+
BaseTagAutocomplete,
|
|
120
|
+
BaseTagAutocompleteFetch,
|
|
111
121
|
BaseTable,
|
|
112
122
|
BaseTableColumn,
|
|
123
|
+
BaseTextarea,
|
|
124
|
+
BaseTextareaAutoresize,
|
|
113
125
|
};
|
package/src/lang/en.json
CHANGED
|
@@ -53,6 +53,6 @@
|
|
|
53
53
|
"year": "Year",
|
|
54
54
|
"yes_delete": "Yes, delete",
|
|
55
55
|
"you_can_upload_up_to_n_files": "You can upload one file at most|You can upload up to {count} files",
|
|
56
|
-
"you_cannot_select_more_than_x_items": "You can't select more than one item|You can't select more than {
|
|
56
|
+
"you_cannot_select_more_than_x_items": "You can't select more than one item|You can't select more than {count} items"
|
|
57
57
|
}
|
|
58
58
|
}
|
package/src/lang/fr.json
CHANGED
|
@@ -53,6 +53,6 @@
|
|
|
53
53
|
"year": "An",
|
|
54
54
|
"yes_delete": "Oui, supprimer",
|
|
55
55
|
"you_can_upload_up_to_n_files": "Vous pouvez télécharger un fichier au maximum|Vous pouvez télécharger jusqu'à {count} fichiers",
|
|
56
|
-
"you_cannot_select_more_than_x_items": "Vous ne pouvez pas sélectionner plus de un élément|Vous ne pouvez pas sélectionner plus de {
|
|
56
|
+
"you_cannot_select_more_than_x_items": "Vous ne pouvez pas sélectionner plus de un élément|Vous ne pouvez pas sélectionner plus de {count} éléments"
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
declare const _default: import("vue").DefineComponent<{
|
|
2
|
-
modelValue: {
|
|
3
|
-
required: true;
|
|
4
|
-
type: NumberConstructor;
|
|
5
|
-
};
|
|
6
|
-
lastPage: {
|
|
7
|
-
required: true;
|
|
8
|
-
type: NumberConstructor;
|
|
9
|
-
};
|
|
10
|
-
}, unknown, unknown, {}, {
|
|
11
|
-
next(): void;
|
|
12
|
-
previous(): void;
|
|
13
|
-
}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:model-value"[], "update:model-value", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
|
14
|
-
modelValue: {
|
|
15
|
-
required: true;
|
|
16
|
-
type: NumberConstructor;
|
|
17
|
-
};
|
|
18
|
-
lastPage: {
|
|
19
|
-
required: true;
|
|
20
|
-
type: NumberConstructor;
|
|
21
|
-
};
|
|
22
|
-
}>> & {
|
|
23
|
-
"onUpdate:model-value"?: ((...args: any[]) => any) | undefined;
|
|
24
|
-
}, {}>;
|
|
25
|
-
export default _default;
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="w-full rounded-lg border border-slate-200">
|
|
3
|
-
<div class="flex space-x-5 p-4">
|
|
4
|
-
<div
|
|
5
|
-
class="h-20 w-20 shrink-0 rounded border border-slate-200 bg-slate-900"
|
|
6
|
-
>
|
|
7
|
-
<component
|
|
8
|
-
:is="url ? 'a' : 'div'"
|
|
9
|
-
:href="url"
|
|
10
|
-
target="_blank"
|
|
11
|
-
class="flex h-full w-full items-center justify-center overflow-hidden"
|
|
12
|
-
>
|
|
13
|
-
<img
|
|
14
|
-
v-if="type == 'image' && url"
|
|
15
|
-
:src="url"
|
|
16
|
-
class="h-full w-full object-contain object-center"
|
|
17
|
-
:alt="name"
|
|
18
|
-
/>
|
|
19
|
-
<img
|
|
20
|
-
v-else-if="type == 'image' && 'data_url' in media"
|
|
21
|
-
:src="media.data_url"
|
|
22
|
-
class="h-full w-full object-contain object-center"
|
|
23
|
-
:alt="name"
|
|
24
|
-
/>
|
|
25
|
-
<span v-else class="leading-tight text-slate-600">{{
|
|
26
|
-
extension
|
|
27
|
-
}}</span>
|
|
28
|
-
</component>
|
|
29
|
-
</div>
|
|
30
|
-
<div class="grow overflow-hidden">
|
|
31
|
-
<div class="leading-normal">
|
|
32
|
-
<p class="mb-1 truncate text-sm font-medium leading-tight">
|
|
33
|
-
{{ name }}
|
|
34
|
-
</p>
|
|
35
|
-
<p class="text-sm leading-tight text-slate-500">
|
|
36
|
-
{{ size }}
|
|
37
|
-
</p>
|
|
38
|
-
<button
|
|
39
|
-
type="button"
|
|
40
|
-
class="mt-2 appearance-none text-sm underline"
|
|
41
|
-
@click="$emit('delete')"
|
|
42
|
-
>
|
|
43
|
-
{{ capitalize($t('sui.remove')) }}
|
|
44
|
-
</button>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
</template>
|
|
50
|
-
|
|
51
|
-
<script lang="ts" setup>
|
|
52
|
-
import { Media } from '@/types/Media';
|
|
53
|
-
import { UploadedFile } from '@/types/UploadedFile';
|
|
54
|
-
import { PropType } from 'vue';
|
|
55
|
-
import { capitalize } from 'lodash';
|
|
56
|
-
import { fileSizeFormat } from 'src/utils';
|
|
57
|
-
|
|
58
|
-
defineEmits(['delete']);
|
|
59
|
-
|
|
60
|
-
const props = defineProps({
|
|
61
|
-
media: {
|
|
62
|
-
required: true,
|
|
63
|
-
type: Object as PropType<Media | UploadedFile>,
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const name = computed(() => {
|
|
68
|
-
return props.media.file_name;
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const size = computed(() => {
|
|
72
|
-
return fileSizeFormat(props.media.size);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const type = computed(() => {
|
|
76
|
-
const parts = props.media.mime_type.split('/');
|
|
77
|
-
return parts[0];
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const extension = computed(() => {
|
|
81
|
-
const parts = props.media.mime_type.split('/');
|
|
82
|
-
return parts[parts.length - 1];
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const url = computed(() => {
|
|
86
|
-
if ('url' in props.media) {
|
|
87
|
-
return props.media.url;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return null;
|
|
91
|
-
});
|
|
92
|
-
</script>
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<nav
|
|
3
|
-
v-if="lastPage > 1 || lastPage < modelValue"
|
|
4
|
-
class="flex items-center space-x-1 sm:px-0"
|
|
5
|
-
>
|
|
6
|
-
<button
|
|
7
|
-
type="button"
|
|
8
|
-
:disabled="modelValue == 1"
|
|
9
|
-
class="flex h-8 w-8 items-center justify-center rounded-md border border-slate-300 text-sm font-medium text-slate-400 outline-none hover:enabled:border-slate-400 hover:enabled:text-slate-700 disabled:cursor-not-allowed disabled:border-transparent disabled:opacity-60"
|
|
10
|
-
@click="previous()"
|
|
11
|
-
>
|
|
12
|
-
<BaseIcon
|
|
13
|
-
class="h-5 w-5 text-slate-400"
|
|
14
|
-
icon="heroicons-solid:chevron-left"
|
|
15
|
-
/>
|
|
16
|
-
</button>
|
|
17
|
-
<button
|
|
18
|
-
:disabled="modelValue >= lastPage"
|
|
19
|
-
class="flex h-8 w-8 items-center justify-center rounded-md border border-slate-300 text-sm font-medium text-slate-400 outline-none hover:enabled:border-slate-400 hover:enabled:text-slate-700 disabled:cursor-not-allowed disabled:border-transparent disabled:opacity-60"
|
|
20
|
-
@click="next()"
|
|
21
|
-
>
|
|
22
|
-
<BaseIcon
|
|
23
|
-
class="h-5 w-5 text-slate-400"
|
|
24
|
-
icon="heroicons-solid:chevron-right"
|
|
25
|
-
/>
|
|
26
|
-
</button>
|
|
27
|
-
</nav>
|
|
28
|
-
</template>
|
|
29
|
-
|
|
30
|
-
<script lang="ts">
|
|
31
|
-
import { defineComponent } from 'vue';
|
|
32
|
-
|
|
33
|
-
export default defineComponent({
|
|
34
|
-
props: {
|
|
35
|
-
modelValue: {
|
|
36
|
-
required: true,
|
|
37
|
-
type: Number,
|
|
38
|
-
},
|
|
39
|
-
lastPage: {
|
|
40
|
-
required: true,
|
|
41
|
-
type: Number,
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
emits: ['update:model-value'],
|
|
45
|
-
methods: {
|
|
46
|
-
next() {
|
|
47
|
-
if (this.modelValue >= this.lastPage) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
this.$emit('update:model-value', this.modelValue + 1);
|
|
51
|
-
},
|
|
52
|
-
previous() {
|
|
53
|
-
if (this.modelValue == 1) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
this.$emit('update:model-value', this.modelValue - 1);
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
</script>
|