sprintify-ui 0.0.204 → 0.1.0

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.
Files changed (30) hide show
  1. package/dist/sprintify-ui.es.js +19691 -14695
  2. package/dist/types/src/components/BaseAddressForm.vue.d.ts +24 -3
  3. package/dist/types/src/components/BaseMediaGallery.vue.d.ts +64 -0
  4. package/dist/types/src/components/BaseMediaGalleryItem.vue.d.ts +45 -0
  5. package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +37 -3
  6. package/dist/types/src/components/BaseMediaList.vue.d.ts +47 -0
  7. package/dist/types/src/components/BaseMediaListItem.vue.d.ts +47 -0
  8. package/dist/types/src/components/BaseMediaPictures.vue.d.ts +55 -0
  9. package/dist/types/src/components/BaseMediaPicturesItem.vue.d.ts +54 -0
  10. package/dist/types/src/index.d.ts +8 -0
  11. package/dist/types/src/types/Media.d.ts +1 -0
  12. package/dist/types/src/types/UploadedFile.d.ts +1 -0
  13. package/dist/types/src/types/index.d.ts +2 -4
  14. package/package.json +3 -2
  15. package/src/components/BaseAddressForm.vue +27 -6
  16. package/src/components/BaseMediaGallery.vue +95 -0
  17. package/src/components/BaseMediaGalleryItem.vue +92 -0
  18. package/src/components/BaseMediaItem.vue +1 -1
  19. package/src/components/BaseMediaLibrary.stories.js +181 -19
  20. package/src/components/BaseMediaLibrary.vue +94 -102
  21. package/src/components/BaseMediaList.vue +70 -0
  22. package/src/components/BaseMediaListItem.vue +171 -0
  23. package/src/components/BaseMediaPictures.vue +66 -0
  24. package/src/components/BaseMediaPicturesItem.vue +93 -0
  25. package/src/components/BaseMediaPreview.vue +16 -4
  26. package/src/lang/en.json +2 -0
  27. package/src/lang/fr.json +2 -0
  28. package/src/types/Media.ts +1 -0
  29. package/src/types/UploadedFile.ts +1 -0
  30. 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>
@@ -10,7 +10,7 @@
10
10
  target="_blank"
11
11
  class="flex grow items-center overflow-hidden px-3"
12
12
  >
13
- <div class="text-left leading-tight">
13
+ <div class="overflow-hidden text-left leading-tight">
14
14
  <p class="mb-px grow truncate text-[13px] font-medium">
15
15
  {{ name }}
16
16
  </p>
@@ -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
- currentMedia: [
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
- export const Demo = Template.bind({});
71
- Demo.args = {};
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 = {};