sprintify-ui 0.0.204 → 0.1.2
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 +19690 -14694
- package/dist/types/src/components/BaseAddressForm.vue.d.ts +24 -3
- package/dist/types/src/components/BaseMediaGallery.vue.d.ts +64 -0
- package/dist/types/src/components/BaseMediaGalleryItem.vue.d.ts +45 -0
- package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +37 -3
- package/dist/types/src/components/BaseMediaList.vue.d.ts +47 -0
- package/dist/types/src/components/BaseMediaListItem.vue.d.ts +47 -0
- package/dist/types/src/components/BaseMediaPictures.vue.d.ts +55 -0
- package/dist/types/src/components/BaseMediaPicturesItem.vue.d.ts +54 -0
- package/dist/types/src/index.d.ts +8 -0
- package/dist/types/src/types/Media.d.ts +1 -0
- package/dist/types/src/types/UploadedFile.d.ts +1 -0
- package/dist/types/src/types/index.d.ts +2 -4
- package/package.json +3 -2
- package/src/components/BaseAddressForm.vue +27 -6
- package/src/components/BaseBelongsTo.vue +4 -4
- package/src/components/BaseMediaGallery.vue +95 -0
- package/src/components/BaseMediaGalleryItem.vue +92 -0
- package/src/components/BaseMediaItem.vue +1 -1
- package/src/components/BaseMediaLibrary.stories.js +181 -19
- package/src/components/BaseMediaLibrary.vue +92 -102
- package/src/components/BaseMediaList.vue +70 -0
- package/src/components/BaseMediaListItem.vue +171 -0
- package/src/components/BaseMediaPictures.vue +66 -0
- package/src/components/BaseMediaPicturesItem.vue +93 -0
- package/src/components/BaseMediaPreview.vue +16 -4
- package/src/lang/en.json +2 -0
- package/src/lang/fr.json +2 -0
- package/src/types/Media.ts +1 -0
- package/src/types/UploadedFile.ts +1 -0
- package/src/types/index.ts +2 -4
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div ref="itemsRef">
|
|
3
|
+
<vuedraggable
|
|
4
|
+
:model-value="modelValue"
|
|
5
|
+
group="media"
|
|
6
|
+
item-key="id"
|
|
7
|
+
tag="div"
|
|
8
|
+
:disabled="disabled"
|
|
9
|
+
class="-m-1 flex flex-wrap"
|
|
10
|
+
handle=".handle"
|
|
11
|
+
@update:model-value="onDragUpdate"
|
|
12
|
+
>
|
|
13
|
+
<template #item="{ element, index }">
|
|
14
|
+
<div :style="{ width: itemWidth }" class="p-1">
|
|
15
|
+
<BaseMediaGalleryItem
|
|
16
|
+
:media="element"
|
|
17
|
+
:show-remove="!disabled"
|
|
18
|
+
:disabled="disabled"
|
|
19
|
+
:draggable="draggable"
|
|
20
|
+
@remove="$emit('remove', index)"
|
|
21
|
+
>
|
|
22
|
+
{{ element.file_name }}
|
|
23
|
+
</BaseMediaGalleryItem>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
</vuedraggable>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script lang="ts" setup>
|
|
31
|
+
import { Media } from '@/types/Media';
|
|
32
|
+
import { UploadedFile } from '@/types/UploadedFile';
|
|
33
|
+
import { useElementSize } from '@vueuse/core';
|
|
34
|
+
import { PropType } from 'vue';
|
|
35
|
+
import vuedraggable from 'vuedraggable';
|
|
36
|
+
import BaseMediaGalleryItem from './BaseMediaGalleryItem.vue';
|
|
37
|
+
|
|
38
|
+
const props = defineProps({
|
|
39
|
+
modelValue: {
|
|
40
|
+
required: true,
|
|
41
|
+
type: Object as PropType<(Media | UploadedFile)[]>,
|
|
42
|
+
},
|
|
43
|
+
showRemove: {
|
|
44
|
+
default: true,
|
|
45
|
+
type: Boolean,
|
|
46
|
+
},
|
|
47
|
+
draggable: {
|
|
48
|
+
default: false,
|
|
49
|
+
type: Boolean,
|
|
50
|
+
},
|
|
51
|
+
size: {
|
|
52
|
+
default: 140,
|
|
53
|
+
type: Number,
|
|
54
|
+
},
|
|
55
|
+
disabled: {
|
|
56
|
+
default: false,
|
|
57
|
+
type: Boolean,
|
|
58
|
+
},
|
|
59
|
+
itemMaxWidth: {
|
|
60
|
+
default: 220,
|
|
61
|
+
type: Number,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const emit = defineEmits(['update:modelValue', 'remove']);
|
|
66
|
+
|
|
67
|
+
// Item width
|
|
68
|
+
|
|
69
|
+
const itemsRef = ref<HTMLElement | null>(null);
|
|
70
|
+
const itemWidth = ref('220px');
|
|
71
|
+
|
|
72
|
+
const itemsRefSize = useElementSize(itemsRef);
|
|
73
|
+
|
|
74
|
+
watch(
|
|
75
|
+
() => itemsRefSize.width.value,
|
|
76
|
+
(width) => {
|
|
77
|
+
if (width <= 300) {
|
|
78
|
+
itemWidth.value = '100%';
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const numberOfItems = Math.floor(width / props.itemMaxWidth);
|
|
83
|
+
|
|
84
|
+
itemWidth.value = `${100 / numberOfItems}%`;
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
function onDragUpdate(value: (Media | UploadedFile)[]) {
|
|
89
|
+
if (props.disabled) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
emit('update:modelValue', value);
|
|
94
|
+
}
|
|
95
|
+
</script>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="relative overflow-hidden rounded bg-white shadow ring-1 ring-black ring-opacity-10"
|
|
4
|
+
>
|
|
5
|
+
<div
|
|
6
|
+
class="flex"
|
|
7
|
+
:class="{
|
|
8
|
+
'pr-4': draggable,
|
|
9
|
+
}"
|
|
10
|
+
>
|
|
11
|
+
<div
|
|
12
|
+
v-if="draggable && !disabled"
|
|
13
|
+
class="handle flex shrink-0 cursor-move items-center justify-center border-r border-slate-300 bg-slate-200 px-1"
|
|
14
|
+
>
|
|
15
|
+
<BaseIcon icon="mdi:drag"></BaseIcon>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="shrink-0">
|
|
18
|
+
<BaseMediaPreview class="h-12 w-12" :media="media" />
|
|
19
|
+
</div>
|
|
20
|
+
<component
|
|
21
|
+
:is="url ? 'a' : 'p'"
|
|
22
|
+
:href="url"
|
|
23
|
+
target="_blank"
|
|
24
|
+
class="flex grow items-center overflow-hidden px-3"
|
|
25
|
+
>
|
|
26
|
+
<div class="overflow-hidden text-left leading-tight">
|
|
27
|
+
<p class="mb-px grow truncate text-[13px] font-medium">
|
|
28
|
+
{{ name }}
|
|
29
|
+
</p>
|
|
30
|
+
<p class="shrink-0 text-[10px] text-slate-400">
|
|
31
|
+
{{ fileSize }}
|
|
32
|
+
</p>
|
|
33
|
+
</div>
|
|
34
|
+
</component>
|
|
35
|
+
</div>
|
|
36
|
+
<div v-if="showRemove" class="absolute top-px right-px">
|
|
37
|
+
<button
|
|
38
|
+
type="button"
|
|
39
|
+
class="rounded-full bg-white p-1 text-slate-500 hover:bg-slate-100"
|
|
40
|
+
@click="$emit('remove')"
|
|
41
|
+
>
|
|
42
|
+
<BaseIcon icon="heroicons:x-mark-20-solid" class="h-5 w-5"></BaseIcon>
|
|
43
|
+
</button>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</template>
|
|
47
|
+
|
|
48
|
+
<script lang="ts" setup>
|
|
49
|
+
import { Media } from '@/types/Media';
|
|
50
|
+
import { UploadedFile } from '@/types/UploadedFile';
|
|
51
|
+
import { PropType } from 'vue';
|
|
52
|
+
import { fileSizeFormat } from '@/utils';
|
|
53
|
+
import BaseMediaPreview from './BaseMediaPreview.vue';
|
|
54
|
+
import { Icon as BaseIcon } from '@iconify/vue';
|
|
55
|
+
|
|
56
|
+
defineEmits(['remove']);
|
|
57
|
+
|
|
58
|
+
const props = defineProps({
|
|
59
|
+
media: {
|
|
60
|
+
required: true,
|
|
61
|
+
type: Object as PropType<Media | UploadedFile>,
|
|
62
|
+
},
|
|
63
|
+
showRemove: {
|
|
64
|
+
default: true,
|
|
65
|
+
type: Boolean,
|
|
66
|
+
},
|
|
67
|
+
draggable: {
|
|
68
|
+
default: false,
|
|
69
|
+
type: Boolean,
|
|
70
|
+
},
|
|
71
|
+
disabled: {
|
|
72
|
+
default: false,
|
|
73
|
+
type: Boolean,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const name = computed(() => {
|
|
78
|
+
return props.media.file_name;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const fileSize = computed(() => {
|
|
82
|
+
return fileSizeFormat(props.media.size);
|
|
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,15 +1,27 @@
|
|
|
1
1
|
import BaseApp from './BaseApp.vue';
|
|
2
2
|
import BaseMediaLibrary from './BaseMediaLibrary.vue';
|
|
3
|
+
import { BaseIcon } from '../components';
|
|
4
|
+
import ShowValue from '../../.storybook/components/ShowValue.vue';
|
|
3
5
|
import { createFieldStory } from '@/../.storybook/utils';
|
|
4
6
|
|
|
5
7
|
const mediaModel = {
|
|
6
8
|
id: 'xxxxx',
|
|
9
|
+
name: 'picture0-1-2dfjjje-23refg-45t',
|
|
7
10
|
file_name: 'picture0-1-2dfjjje-23refg-45t.jpg',
|
|
8
11
|
mime_type: 'image/jpg',
|
|
9
12
|
url: 'https://images.unsplash.com/photo-1670139018938-af8bf748a1bc?auto=format&fit=crop&w=1200&h=800&q=80',
|
|
10
13
|
size: 430 * 1024,
|
|
11
14
|
};
|
|
12
15
|
|
|
16
|
+
const mediaModel2 = {
|
|
17
|
+
id: 'yyyyy',
|
|
18
|
+
name: 'photo-1678729465418-ee8127e8c5cd',
|
|
19
|
+
file_name: 'photo-1678729465418-ee8127e8c5cd.jpg',
|
|
20
|
+
mime_type: 'image/jpg',
|
|
21
|
+
url: 'https://images.unsplash.com/photo-1678729465418-ee8127e8c5cd?auto=format&fit=crop&w=800&q=80',
|
|
22
|
+
size: 430 * 1024,
|
|
23
|
+
};
|
|
24
|
+
|
|
13
25
|
export default {
|
|
14
26
|
title: 'Form/BaseMediaLibrary',
|
|
15
27
|
component: BaseMediaLibrary,
|
|
@@ -18,12 +30,24 @@ export default {
|
|
|
18
30
|
min: 2,
|
|
19
31
|
acceptedExtensions: ['jpg', 'jpeg', 'png', 'webp'],
|
|
20
32
|
uploadUrl: 'https://faker.witify.io/api/todos/upload',
|
|
21
|
-
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const Template = (args) => ({
|
|
37
|
+
components: {
|
|
38
|
+
BaseApp,
|
|
39
|
+
BaseMediaLibrary,
|
|
40
|
+
ShowValue,
|
|
41
|
+
},
|
|
42
|
+
setup() {
|
|
43
|
+
const value = ref([
|
|
22
44
|
mediaModel,
|
|
45
|
+
mediaModel2,
|
|
23
46
|
{
|
|
24
47
|
id: '1',
|
|
25
48
|
url: '',
|
|
26
49
|
mime_type: 'application/pdf',
|
|
50
|
+
name: 'document',
|
|
27
51
|
file_name: 'document.pdf',
|
|
28
52
|
size: 40012,
|
|
29
53
|
},
|
|
@@ -31,6 +55,7 @@ export default {
|
|
|
31
55
|
id: '2',
|
|
32
56
|
url: '',
|
|
33
57
|
mime_type: 'application/excel',
|
|
58
|
+
name: 'finance-2022',
|
|
34
59
|
file_name: 'finance-2022.xlsx',
|
|
35
60
|
size: 5461,
|
|
36
61
|
},
|
|
@@ -38,6 +63,7 @@ export default {
|
|
|
38
63
|
id: '3',
|
|
39
64
|
url: '',
|
|
40
65
|
mime_type: 'image/png',
|
|
66
|
+
name: '34345-1',
|
|
41
67
|
file_name: '34345-1.png',
|
|
42
68
|
size: 40012,
|
|
43
69
|
},
|
|
@@ -45,30 +71,101 @@ export default {
|
|
|
45
71
|
id: '4',
|
|
46
72
|
url: '',
|
|
47
73
|
mime_type: 'audio/mp3',
|
|
74
|
+
name: 'test',
|
|
48
75
|
file_name: 'test.mp3',
|
|
49
76
|
size: 792834,
|
|
50
77
|
},
|
|
51
|
-
]
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const Template = (args) => ({
|
|
56
|
-
components: {
|
|
57
|
-
BaseApp,
|
|
58
|
-
BaseMediaLibrary,
|
|
59
|
-
},
|
|
60
|
-
setup() {
|
|
61
|
-
const value = ref(null);
|
|
78
|
+
]);
|
|
62
79
|
return { args, value };
|
|
63
80
|
},
|
|
64
81
|
template: `
|
|
65
82
|
<BaseMediaLibrary v-model="value" v-bind="args" />
|
|
83
|
+
<ShowValue :value="value" />
|
|
66
84
|
<BaseApp></BaseApp>
|
|
67
85
|
`,
|
|
68
86
|
});
|
|
69
87
|
|
|
70
|
-
|
|
71
|
-
|
|
88
|
+
// Layout - Gallery
|
|
89
|
+
|
|
90
|
+
export const LayoutGallery = Template.bind({});
|
|
91
|
+
LayoutGallery.args = {
|
|
92
|
+
layout: 'gallery',
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const LayoutGalleryDisabled = Template.bind({});
|
|
96
|
+
LayoutGalleryDisabled.args = {
|
|
97
|
+
layout: 'gallery',
|
|
98
|
+
disabled: true,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const LayoutGalleryDraggable = Template.bind({});
|
|
102
|
+
LayoutGalleryDraggable.args = {
|
|
103
|
+
layout: 'gallery',
|
|
104
|
+
draggable: true,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const LayoutGalleryDraggableDisabled = Template.bind({});
|
|
108
|
+
LayoutGalleryDraggableDisabled.args = {
|
|
109
|
+
layout: 'gallery',
|
|
110
|
+
disabled: true,
|
|
111
|
+
draggable: true,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Layout - List
|
|
115
|
+
|
|
116
|
+
export const LayoutList = Template.bind({});
|
|
117
|
+
LayoutList.args = {
|
|
118
|
+
layout: 'list',
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export const LayoutListDisabled = Template.bind({});
|
|
122
|
+
LayoutListDisabled.args = {
|
|
123
|
+
layout: 'list',
|
|
124
|
+
disabled: true,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const LayoutListDraggable = Template.bind({});
|
|
128
|
+
LayoutListDraggable.args = {
|
|
129
|
+
layout: 'list',
|
|
130
|
+
draggable: true,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export const LayoutListDraggableDisabled = Template.bind({});
|
|
134
|
+
LayoutListDraggableDisabled.args = {
|
|
135
|
+
layout: 'list',
|
|
136
|
+
disabled: true,
|
|
137
|
+
draggable: true,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Layout - Images
|
|
141
|
+
|
|
142
|
+
export const LayoutImages = Template.bind({});
|
|
143
|
+
LayoutImages.args = {
|
|
144
|
+
pickerComponent: 'BaseFilePickerCrop',
|
|
145
|
+
layout: 'images',
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export const LayoutImagesDisabled = Template.bind({});
|
|
149
|
+
LayoutImagesDisabled.args = {
|
|
150
|
+
pickerComponent: 'BaseFilePickerCrop',
|
|
151
|
+
layout: 'images',
|
|
152
|
+
disabled: true,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export const LayoutImagesDraggable = Template.bind({});
|
|
156
|
+
LayoutImagesDraggable.args = {
|
|
157
|
+
pickerComponent: 'BaseFilePickerCrop',
|
|
158
|
+
layout: 'images',
|
|
159
|
+
draggable: true,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export const LayoutImagesDraggableDisabled = Template.bind({});
|
|
163
|
+
LayoutImagesDraggableDisabled.args = {
|
|
164
|
+
pickerComponent: 'BaseFilePickerCrop',
|
|
165
|
+
layout: 'images',
|
|
166
|
+
disabled: true,
|
|
167
|
+
draggable: true,
|
|
168
|
+
};
|
|
72
169
|
|
|
73
170
|
export const Crop = Template.bind({});
|
|
74
171
|
Crop.args = {
|
|
@@ -89,12 +186,77 @@ MaxSize.args = {
|
|
|
89
186
|
maxSize: 10 * 1024,
|
|
90
187
|
};
|
|
91
188
|
|
|
92
|
-
export const Disabled = Template.bind({});
|
|
93
|
-
Disabled.args = {
|
|
94
|
-
disabled: true,
|
|
95
|
-
};
|
|
96
|
-
|
|
97
189
|
export const Field = createFieldStory({
|
|
98
190
|
component: BaseMediaLibrary,
|
|
99
191
|
componentName: 'BaseMediaLibrary',
|
|
100
192
|
});
|
|
193
|
+
|
|
194
|
+
// Slots
|
|
195
|
+
|
|
196
|
+
const SlotDefaultTemplate = (args) => ({
|
|
197
|
+
components: {
|
|
198
|
+
BaseApp,
|
|
199
|
+
BaseMediaLibrary,
|
|
200
|
+
ShowValue,
|
|
201
|
+
},
|
|
202
|
+
setup() {
|
|
203
|
+
const value = ref([mediaModel, mediaModel2]);
|
|
204
|
+
return { args, value };
|
|
205
|
+
},
|
|
206
|
+
template: `
|
|
207
|
+
<BaseMediaLibrary v-model="value" v-bind="args">
|
|
208
|
+
<template #default>
|
|
209
|
+
<div class="btn btn-lg w-full">
|
|
210
|
+
Upload!
|
|
211
|
+
</div>
|
|
212
|
+
</template>
|
|
213
|
+
</BaseMediaLibrary>
|
|
214
|
+
|
|
215
|
+
<ShowValue :value="value" />
|
|
216
|
+
<BaseApp></BaseApp>
|
|
217
|
+
`,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
export const SlotDefault = SlotDefaultTemplate.bind({});
|
|
221
|
+
SlotDefault.args = {};
|
|
222
|
+
|
|
223
|
+
const SlotListTemplate = (args) => ({
|
|
224
|
+
components: {
|
|
225
|
+
BaseApp,
|
|
226
|
+
BaseMediaLibrary,
|
|
227
|
+
ShowValue,
|
|
228
|
+
},
|
|
229
|
+
setup() {
|
|
230
|
+
const value = ref([mediaModel, mediaModel2]);
|
|
231
|
+
return { args, value };
|
|
232
|
+
},
|
|
233
|
+
template: `
|
|
234
|
+
<BaseMediaLibrary v-model="value" v-bind="args">
|
|
235
|
+
<template #list="{ modelValue, remove }">
|
|
236
|
+
<div v-for="(item, i) in modelValue" :key="item.id" class="mb-3">
|
|
237
|
+
<div class="flex items-center">
|
|
238
|
+
<div class="w-12 h-12 mr-4">
|
|
239
|
+
<img :src="item.url" class="w-full h-full object-cover" />
|
|
240
|
+
</div>
|
|
241
|
+
<div class="flex-1">
|
|
242
|
+
<div class="text-sm font-semibold">{{ item.name }}</div>
|
|
243
|
+
<div class="text-xs text-gray-500">{{ item.file_name }}</div>
|
|
244
|
+
</div>
|
|
245
|
+
<div class="flex items-center">
|
|
246
|
+
<div class="text-xs text-gray-500 mr-2">{{ item.size }}</div>
|
|
247
|
+
<div class="text-xs text-gray-500 mr-2">{{ item.mime_type }}</div>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
|
|
251
|
+
<button type="button" @click="remove(i)" class="text-xs text-red-500">Remove</button>
|
|
252
|
+
</div>
|
|
253
|
+
</template>
|
|
254
|
+
</BaseMediaLibrary>
|
|
255
|
+
|
|
256
|
+
<ShowValue :value="value" />
|
|
257
|
+
<BaseApp></BaseApp>
|
|
258
|
+
`,
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
export const SlotList = SlotListTemplate.bind({});
|
|
262
|
+
SlotList.args = {};
|