sprintify-ui 0.0.11 → 0.0.13
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 +5911 -3760
- package/dist/style.css +1 -1
- package/dist/tailwindcss/index.js +1 -2
- package/dist/types/src/components/BaseCharacterCounter.vue.d.ts +143 -0
- package/dist/types/src/components/BaseHasMany.vue.d.ts +277 -0
- package/dist/types/src/components/BaseInput.vue.d.ts +39 -5
- package/dist/types/src/components/BaseLoadingCover.vue.d.ts +72 -0
- 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/BaseModalCenter.vue.d.ts +8 -8
- package/dist/types/src/components/BaseModalSide.vue.d.ts +8 -8
- package/dist/types/src/components/BasePagination.vue.d.ts +105 -13
- package/dist/types/src/components/BaseSelect.vue.d.ts +130 -26
- package/dist/types/src/components/BaseSideNavigationItem.vue.d.ts +20 -1
- package/dist/types/src/components/BaseSwitch.vue.d.ts +15 -8
- package/dist/types/src/components/BaseTabItem.vue.d.ts +45 -4
- 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/BaseTextareaAutoresize.vue.d.ts +175 -21
- package/dist/types/src/components/index.d.ts +30 -1
- package/dist/types/src/index.d.ts +4 -0
- package/package.json +1 -1
- package/src/components/BaseAppDialogs.vue +2 -2
- package/src/components/BaseAppNotifications.vue +1 -1
- package/src/components/BaseAutocomplete.vue +16 -18
- package/src/components/BaseBelongsTo.vue +1 -0
- package/src/components/BaseCharacterCounter.stories.js +30 -0
- package/src/components/BaseCharacterCounter.vue +60 -0
- package/src/components/BaseClipboard.vue +1 -1
- package/src/components/BaseDataIterator.stories.js +2 -2
- package/src/components/BaseDataIterator.vue +32 -38
- package/src/components/BaseDataTable.stories.js +2 -2
- package/src/components/BaseFileUploader.vue +4 -0
- package/src/components/BaseHasMany.vue +92 -0
- package/src/components/BaseInput.stories.js +46 -0
- package/src/components/BaseInput.vue +10 -2
- package/src/components/BaseInputLabel.stories.js +31 -0
- package/src/components/BaseInputLabel.vue +1 -1
- package/src/components/BaseLoadingCover.stories.js +55 -0
- package/src/components/BaseLoadingCover.vue +19 -1
- 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.stories.js +125 -0
- package/src/components/BaseMenu.vue +1 -1
- package/src/components/BaseModalCenter.stories.js +61 -0
- package/src/components/BaseModalCenter.vue +2 -2
- package/src/components/BaseModalSide.stories.js +55 -0
- package/src/components/BaseModalSide.vue +2 -2
- package/src/components/BaseNavbar.stories.js +150 -0
- package/src/components/BaseNavbar.vue +3 -0
- package/src/components/BaseNavbarItem.vue +1 -0
- package/src/components/BaseNavbarItemContent.vue +3 -0
- package/src/components/BasePagination.stories.js +32 -0
- package/src/components/BasePagination.vue +126 -40
- package/src/components/BasePanel.stories.js +56 -0
- package/src/components/BasePassword.stories.js +36 -0
- package/src/components/BasePassword.vue +11 -5
- package/src/components/BaseProcessRing.stories.js +27 -0
- package/src/components/BaseReadMore.stories.js +30 -0
- package/src/components/BaseReadMore.vue +1 -1
- package/src/components/BaseSelect.stories.js +67 -0
- package/src/components/BaseSelect.vue +144 -44
- package/src/components/BaseSideNavigation.stories.js +55 -0
- package/src/components/BaseSideNavigation.vue +7 -2
- package/src/components/BaseSideNavigationItem.vue +21 -5
- package/src/components/BaseSkeleton.stories.js +36 -0
- package/src/components/BaseSwitch.stories.js +101 -0
- package/src/components/BaseSwitch.vue +90 -12
- package/src/components/BaseSystemAlert.stories.js +63 -0
- package/src/components/BaseTabItem.vue +29 -6
- package/src/components/BaseTable.vue +2 -2
- package/src/components/BaseTabs.stories.js +54 -0
- package/src/components/BaseTabs.vue +3 -3
- 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.stories.js +35 -0
- package/src/components/BaseTextarea.vue +1 -1
- package/src/components/BaseTextareaAutoresize.stories.js +49 -0
- package/src/components/BaseTextareaAutoresize.vue +83 -87
- package/src/components/HasMany.stories.js +135 -0
- package/src/components/index.ts +58 -0
- package/src/lang/en.json +2 -1
- package/src/lang/fr.json +2 -1
- package/dist/types/src/components/BasePaginationSimple.vue.d.ts +0 -25
- package/dist/types/src/components/BaseWordCount.vue.d.ts +0 -31
- package/src/components/BaseMediaLibraryItem.vue +0 -92
- package/src/components/BasePaginationSimple.vue +0 -60
- package/src/components/BaseWordCount.vue +0 -36
|
@@ -1,29 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div
|
|
4
|
-
v-if="currentMediaInternal.length + normalizedModelValue.to_add.length"
|
|
5
|
-
class="mb-5"
|
|
6
|
-
>
|
|
7
|
-
<div class="flex flex-wrap">
|
|
8
|
-
<BaseMediaLibraryItem
|
|
9
|
-
v-for="(media, index) in currentMediaInternal"
|
|
10
|
-
:key="media.id"
|
|
11
|
-
:media="media"
|
|
12
|
-
@delete="promptRemoveMedia(index)"
|
|
13
|
-
>
|
|
14
|
-
{{ media.file_name }}
|
|
15
|
-
</BaseMediaLibraryItem>
|
|
16
|
-
<BaseMediaLibraryItem
|
|
17
|
-
v-for="(file, index) in normalizedModelValue.to_add"
|
|
18
|
-
:key="file.id"
|
|
19
|
-
:media="file"
|
|
20
|
-
@delete="promptRemoveUploadedFile(index)"
|
|
21
|
-
>
|
|
22
|
-
{{ file.file_name }}
|
|
23
|
-
</BaseMediaLibraryItem>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
3
|
<BaseFileUploader
|
|
28
4
|
:max-size="maxSize"
|
|
29
5
|
:disabled="disabled"
|
|
@@ -44,34 +20,28 @@
|
|
|
44
20
|
:max="max"
|
|
45
21
|
>
|
|
46
22
|
<div
|
|
47
|
-
class="
|
|
23
|
+
class="rounded border border-dashed p-6 duration-150"
|
|
48
24
|
:class="[
|
|
49
|
-
baseFileUploaderProps.dragging ? 'bg-
|
|
50
|
-
baseFileUploaderProps.disabled
|
|
25
|
+
baseFileUploaderProps.dragging ? 'bg-blue-100' : 'bg-slate-100',
|
|
26
|
+
baseFileUploaderProps.disabled
|
|
27
|
+
? 'cursor-not-allowed border-slate-300'
|
|
28
|
+
: 'border-slate-400 hover:bg-slate-50',
|
|
51
29
|
]"
|
|
52
30
|
>
|
|
53
|
-
<div class="
|
|
31
|
+
<div :class="[baseFileUploaderProps.disabled ? 'opacity-30' : '']">
|
|
54
32
|
<BaseIcon
|
|
55
33
|
icon="heroicons:arrow-up-on-square"
|
|
56
|
-
class="h-6 w-6 text-slate-500"
|
|
34
|
+
class="mx-auto mb-3 h-6 w-6 text-slate-500"
|
|
57
35
|
/>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
{{ $t('sui.drop_or_click_to_upload') }}
|
|
62
|
-
</p>
|
|
63
|
-
|
|
64
|
-
<div class="mt-1 text-sm leading-tight text-slate-500">
|
|
65
|
-
<p v-if="max > 1">
|
|
66
|
-
{{ $t('sui.you_can_upload_up_to_n_files', { count: max }) }}
|
|
67
|
-
</p>
|
|
68
|
-
<p>
|
|
69
|
-
{{
|
|
70
|
-
capitalize(
|
|
71
|
-
$t('sui.up_to_x', { x: fileSizeFormat(maxSize) })
|
|
72
|
-
)
|
|
73
|
-
}}
|
|
36
|
+
<div class="text-center">
|
|
37
|
+
<p class="mb-0 text-sm font-medium leading-tight">
|
|
38
|
+
{{ $t('sui.drop_or_click_to_upload') }}
|
|
74
39
|
</p>
|
|
40
|
+
|
|
41
|
+
<div class="mt-1 text-xs leading-tight text-slate-500">
|
|
42
|
+
<p v-if="maxFileText">{{ maxFileText }}</p>
|
|
43
|
+
<p>{{ maxFileSize }}</p>
|
|
44
|
+
</div>
|
|
75
45
|
</div>
|
|
76
46
|
</div>
|
|
77
47
|
</div>
|
|
@@ -79,22 +49,54 @@
|
|
|
79
49
|
</template>
|
|
80
50
|
</BaseFileUploader>
|
|
81
51
|
|
|
82
|
-
<
|
|
52
|
+
<BaseAlert v-if="globalErrorMessage" class="mt-5" color="danger" bordered>
|
|
83
53
|
{{ globalErrorMessage }}
|
|
84
|
-
</
|
|
54
|
+
</BaseAlert>
|
|
55
|
+
|
|
56
|
+
<div
|
|
57
|
+
v-if="currentMediaInternal.length + normalizedModelValue.to_add.length"
|
|
58
|
+
class="mt-5"
|
|
59
|
+
>
|
|
60
|
+
<div class="grid gap-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
|
|
61
|
+
<div v-for="(media, index) in currentMediaInternal" :key="media.id">
|
|
62
|
+
<BaseMediaItem
|
|
63
|
+
:media="media"
|
|
64
|
+
:show-remove="!disabled"
|
|
65
|
+
@delete="promptRemoveMedia(index)"
|
|
66
|
+
>
|
|
67
|
+
{{ media.file_name }}
|
|
68
|
+
</BaseMediaItem>
|
|
69
|
+
</div>
|
|
70
|
+
<div
|
|
71
|
+
v-for="(file, index) in normalizedModelValue.to_add"
|
|
72
|
+
:key="file.id"
|
|
73
|
+
>
|
|
74
|
+
<BaseMediaItem
|
|
75
|
+
:media="file"
|
|
76
|
+
:show-remove="!disabled"
|
|
77
|
+
@delete="promptRemoveUploadedFile(index)"
|
|
78
|
+
>
|
|
79
|
+
{{ file.file_name }}
|
|
80
|
+
</BaseMediaItem>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
85
84
|
</div>
|
|
86
85
|
</template>
|
|
87
86
|
|
|
88
87
|
<script lang="ts" setup>
|
|
89
88
|
import { UploadedFile } from '@/types/UploadedFile';
|
|
90
89
|
import { Media } from '@/types/Media';
|
|
91
|
-
import
|
|
90
|
+
import { cloneDeep, isArray, isObject } from 'lodash';
|
|
92
91
|
import { PropType } from 'vue';
|
|
93
92
|
import { MediaLibraryPayload } from '@/types/types';
|
|
94
93
|
import { useDialogsStore } from '../stores/dialogs';
|
|
95
94
|
import { useNotificationsStore } from '../stores/notifications';
|
|
96
95
|
import { capitalize } from 'lodash';
|
|
97
|
-
import
|
|
96
|
+
import BaseFileUploader from './BaseFileUploader.vue';
|
|
97
|
+
import BaseMediaItem from './BaseMediaItem.vue';
|
|
98
|
+
import { fileSizeFormat } from '@/utils';
|
|
99
|
+
import BaseAlert from './BaseAlert.vue';
|
|
98
100
|
|
|
99
101
|
const i18n = useI18n();
|
|
100
102
|
|
|
@@ -146,7 +148,7 @@ const props = defineProps({
|
|
|
146
148
|
},
|
|
147
149
|
errors: {
|
|
148
150
|
default: undefined,
|
|
149
|
-
type:
|
|
151
|
+
type: [Array] as PropType<string[]>,
|
|
150
152
|
},
|
|
151
153
|
disabled: {
|
|
152
154
|
default: false,
|
|
@@ -159,9 +161,9 @@ const currentMediaInternal = ref(cloneDeep(props.currentMedia));
|
|
|
159
161
|
const normalizedModelValue = computed(() => {
|
|
160
162
|
if (
|
|
161
163
|
props.modelValue &&
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
isObject(props.modelValue) &&
|
|
165
|
+
isArray(props.modelValue.to_add) &&
|
|
166
|
+
isArray(props.modelValue.to_remove)
|
|
165
167
|
) {
|
|
166
168
|
return props.modelValue;
|
|
167
169
|
}
|
|
@@ -260,23 +262,20 @@ function sync(modelValue: MediaLibraryPayload) {
|
|
|
260
262
|
emit('update', modelValue);
|
|
261
263
|
}
|
|
262
264
|
|
|
263
|
-
function errorMessage(name: string): string {
|
|
264
|
-
const errors = get(props.errors, name, []);
|
|
265
|
-
|
|
266
|
-
if (errors.length == 0) {
|
|
267
|
-
return '';
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return errors[0];
|
|
271
|
-
}
|
|
272
|
-
|
|
273
265
|
const globalErrorMessage = computed(() => {
|
|
274
|
-
if (
|
|
275
|
-
return
|
|
276
|
-
}
|
|
277
|
-
if (errorMessage(props.name + '.to_remove')) {
|
|
278
|
-
return errorMessage(props.name + '.to_remove');
|
|
266
|
+
if (props.errors && props.errors.length) {
|
|
267
|
+
return props.errors[0];
|
|
279
268
|
}
|
|
280
269
|
return '';
|
|
281
270
|
});
|
|
271
|
+
|
|
272
|
+
const maxFileText = computed(() => {
|
|
273
|
+
return i18n.t('sui.you_can_upload_up_to_n_files', { count: props.max });
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const maxFileSize = computed(() => {
|
|
277
|
+
return capitalize(
|
|
278
|
+
i18n.t('sui.up_to_x', { x: fileSizeFormat(props.maxSize) })
|
|
279
|
+
);
|
|
280
|
+
});
|
|
282
281
|
</script>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import BaseMediaPreview from './BaseMediaPreview.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Components/BaseMediaPreview',
|
|
5
|
+
component: BaseMediaPreview,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const Template = (args) => ({
|
|
9
|
+
components: {
|
|
10
|
+
BaseMediaPreview,
|
|
11
|
+
},
|
|
12
|
+
setup() {
|
|
13
|
+
return { args };
|
|
14
|
+
},
|
|
15
|
+
template: `
|
|
16
|
+
<BaseMediaPreview v-bind="args" class="w-20 h-20" />
|
|
17
|
+
`,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const Image = Template.bind({});
|
|
21
|
+
Image.args = {
|
|
22
|
+
media: {
|
|
23
|
+
id: 'xxxxxxxxxxx',
|
|
24
|
+
file_name: 'picture.jpg',
|
|
25
|
+
mime_type: 'image/jpg',
|
|
26
|
+
size: 430 * 1024,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const ImageUrl = Template.bind({});
|
|
31
|
+
ImageUrl.args = {
|
|
32
|
+
media: {
|
|
33
|
+
id: 'xxxxxxxxxxx',
|
|
34
|
+
file_name: 'picture.jpg',
|
|
35
|
+
mime_type: 'image/jpg',
|
|
36
|
+
url: 'https://images.unsplash.com/photo-1670139018938-af8bf748a1bc?auto=format&fit=crop&w=800&h=800&q=80',
|
|
37
|
+
size: 430 * 1024,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const PDF = Template.bind({});
|
|
42
|
+
PDF.args = {
|
|
43
|
+
media: {
|
|
44
|
+
id: 'xxxxxxxxxxx',
|
|
45
|
+
file_name: 'picture.pdf',
|
|
46
|
+
mime_type: 'application/pdf',
|
|
47
|
+
url: 'https://images.unsplash.com/photo-1670139018938-af8bf748a1bc?auto=format&fit=crop&w=800&h=800&q=80',
|
|
48
|
+
size: 430 * 1024,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const Music = Template.bind({});
|
|
53
|
+
Music.args = {
|
|
54
|
+
media: {
|
|
55
|
+
id: 'xxxxxxxxxxx',
|
|
56
|
+
file_name: 'picture.mp3',
|
|
57
|
+
mime_type: 'audio/mpeg',
|
|
58
|
+
url: 'https://images.unsplash.com/photo-1670139018938-af8bf748a1bc?auto=format&fit=crop&w=800&h=800&q=80',
|
|
59
|
+
size: 430 * 1024,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const Other = Template.bind({});
|
|
64
|
+
Other.args = {
|
|
65
|
+
media: {
|
|
66
|
+
id: 'xxxxxxxxxxx',
|
|
67
|
+
file_name: 'picture.mp3',
|
|
68
|
+
mime_type: 'application/excel',
|
|
69
|
+
url: 'https://images.unsplash.com/photo-1670139018938-af8bf748a1bc?auto=format&fit=crop&w=800&h=800&q=80',
|
|
70
|
+
size: 430 * 1024,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
:is="url ? 'a' : 'div'"
|
|
4
|
+
:href="url"
|
|
5
|
+
target="_blank"
|
|
6
|
+
class="relative flex items-center justify-center overflow-hidden"
|
|
7
|
+
:class="[url ? 'duration-100 hover:bg-slate-100' : 'bg-white']"
|
|
8
|
+
>
|
|
9
|
+
<img
|
|
10
|
+
v-if="type == 'image' && url"
|
|
11
|
+
:src="url"
|
|
12
|
+
class="h-full w-full bg-black object-contain object-center"
|
|
13
|
+
:alt="name"
|
|
14
|
+
/>
|
|
15
|
+
<img
|
|
16
|
+
v-else-if="type == 'image' && 'data_url' in media"
|
|
17
|
+
:src="media.data_url"
|
|
18
|
+
class="h-full w-full bg-black object-contain object-center"
|
|
19
|
+
:alt="name"
|
|
20
|
+
/>
|
|
21
|
+
<div
|
|
22
|
+
v-else
|
|
23
|
+
class="flex h-full w-full items-center justify-center bg-slate-200"
|
|
24
|
+
>
|
|
25
|
+
<BaseIcon
|
|
26
|
+
v-if="extension == 'pdf'"
|
|
27
|
+
class="max-w-8 h-1/2 max-h-8 w-1/2 text-slate-600"
|
|
28
|
+
icon="mdi:file-pdf-box"
|
|
29
|
+
/>
|
|
30
|
+
<BaseIcon
|
|
31
|
+
v-else-if="type == 'image'"
|
|
32
|
+
class="max-w-8 h-1/2 max-h-8 w-1/2 text-slate-600"
|
|
33
|
+
icon="mdi:camera"
|
|
34
|
+
/>
|
|
35
|
+
<BaseIcon
|
|
36
|
+
v-else-if="type == 'audio'"
|
|
37
|
+
class="max-w-8 h-1/2 max-h-8 w-1/2 text-slate-600"
|
|
38
|
+
icon="mdi:music"
|
|
39
|
+
/>
|
|
40
|
+
<span
|
|
41
|
+
v-else
|
|
42
|
+
class="text-xs font-semibold uppercase leading-tight text-slate-600"
|
|
43
|
+
>
|
|
44
|
+
{{ extension }}
|
|
45
|
+
</span>
|
|
46
|
+
</div>
|
|
47
|
+
</component>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<script lang="ts" setup>
|
|
51
|
+
import { Media } from '@/types/Media';
|
|
52
|
+
import { UploadedFile } from '@/types/UploadedFile';
|
|
53
|
+
import { PropType } from 'vue';
|
|
54
|
+
import { BaseIcon } from './index';
|
|
55
|
+
|
|
56
|
+
defineEmits(['delete']);
|
|
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
|
+
});
|
|
68
|
+
|
|
69
|
+
const name = computed(() => {
|
|
70
|
+
return props.media.file_name;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const type = computed(() => {
|
|
74
|
+
const parts = props.media.mime_type.split('/');
|
|
75
|
+
return parts[0];
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const extension = computed(() => {
|
|
79
|
+
const parts = props.media.mime_type.split('/');
|
|
80
|
+
return parts[parts.length - 1];
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const url = computed(() => {
|
|
84
|
+
if ('url' in props.media) {
|
|
85
|
+
return props.media.url;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return null;
|
|
89
|
+
});
|
|
90
|
+
</script>
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import BaseMenu from './BaseMenu.vue';
|
|
2
|
+
import { Icon as BaseIcon } from '@iconify/vue';
|
|
3
|
+
import BaseAvatar from './BaseAvatar.vue';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'Components/BaseMenu',
|
|
7
|
+
component: BaseMenu,
|
|
8
|
+
args: {
|
|
9
|
+
position: 'bottom-right',
|
|
10
|
+
},
|
|
11
|
+
argTypes: {
|
|
12
|
+
position: {
|
|
13
|
+
control: { type: 'select' },
|
|
14
|
+
options: ['bottom-left', 'bottom-right'],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const Template = (args) => ({
|
|
20
|
+
components: {
|
|
21
|
+
BaseMenu,
|
|
22
|
+
BaseIcon,
|
|
23
|
+
BaseAvatar,
|
|
24
|
+
},
|
|
25
|
+
setup() {
|
|
26
|
+
const items = [
|
|
27
|
+
{
|
|
28
|
+
label: 'Export file',
|
|
29
|
+
icon: 'mdi-export',
|
|
30
|
+
action() {
|
|
31
|
+
alert('Export!');
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'Google',
|
|
36
|
+
icon: 'mdi-google',
|
|
37
|
+
href: 'https://google.com',
|
|
38
|
+
count: 1000,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
icon: 'mdi-access-point',
|
|
42
|
+
label: 'Reconnect',
|
|
43
|
+
to: 'home',
|
|
44
|
+
color: 'success',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
icon: 'mdi-archive',
|
|
48
|
+
label: 'Archive',
|
|
49
|
+
href: 'https://google.com',
|
|
50
|
+
color: 'warning',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
icon: 'mdi-trash-can',
|
|
54
|
+
label: 'Delete',
|
|
55
|
+
href: 'https://google.com',
|
|
56
|
+
color: 'danger',
|
|
57
|
+
count: 1,
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const user = {
|
|
62
|
+
email: 'jane@witify.io',
|
|
63
|
+
first_name: 'Jane',
|
|
64
|
+
last_name: 'Doe',
|
|
65
|
+
full_name: 'Jane Doe',
|
|
66
|
+
avatar_url:
|
|
67
|
+
'https://images.unsplash.com/photo-1494790108377-be9c29b29330??auto=format&fit=crop&w=200&h=200&q=80&g=face',
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
args.items = items;
|
|
71
|
+
|
|
72
|
+
return { args, user };
|
|
73
|
+
},
|
|
74
|
+
template: `
|
|
75
|
+
<div class="pb-52">
|
|
76
|
+
|
|
77
|
+
<h2 class="mb-5 font-semibold">Various examples</h2>
|
|
78
|
+
|
|
79
|
+
<p class="text-sm mb-1 text-slate-600">Simple button</p>
|
|
80
|
+
|
|
81
|
+
<BaseMenu v-bind="args" class="inline-block">
|
|
82
|
+
<template #button="{ open }">
|
|
83
|
+
<div
|
|
84
|
+
class="btn"
|
|
85
|
+
:class="[open ? 'ring-2 ring-primary-500 ring-offset-2': '']"
|
|
86
|
+
>
|
|
87
|
+
Click me
|
|
88
|
+
</div>
|
|
89
|
+
</template>
|
|
90
|
+
</BaseMenu>
|
|
91
|
+
|
|
92
|
+
<br>
|
|
93
|
+
<br>
|
|
94
|
+
|
|
95
|
+
<p class="text-sm mb-1 text-slate-600">Contextual action button</p>
|
|
96
|
+
|
|
97
|
+
<BaseMenu v-bind="args" class="inline-block">
|
|
98
|
+
<template #button="{ open }">
|
|
99
|
+
<div
|
|
100
|
+
class="flex h-10 w-10 items-center justify-center rounded-full border border-slate-300 bg-white duration-150 hover:bg-slate-50"
|
|
101
|
+
:class="[open ? 'ring-2 ring-primary-500 ring-offset-2': '']"
|
|
102
|
+
>
|
|
103
|
+
<BaseIcon icon="heroicons-solid:dots-vertical" />
|
|
104
|
+
</div>
|
|
105
|
+
</template>
|
|
106
|
+
</BaseMenu>
|
|
107
|
+
|
|
108
|
+
<br>
|
|
109
|
+
<br>
|
|
110
|
+
|
|
111
|
+
<p class="text-sm mb-1 text-slate-600">With BaseAvatar</p>
|
|
112
|
+
|
|
113
|
+
<BaseMenu v-bind="args" class="inline-block">
|
|
114
|
+
<template #button="{ open }">
|
|
115
|
+
<div class="bg-white">
|
|
116
|
+
<BaseAvatar show-details :user="user" />
|
|
117
|
+
</div>
|
|
118
|
+
</template>
|
|
119
|
+
</BaseMenu>
|
|
120
|
+
</div>
|
|
121
|
+
`,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
export const Demo = Template.bind({});
|
|
125
|
+
Demo.args = {};
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
>
|
|
17
17
|
<MenuItems
|
|
18
18
|
:class="[menuClass, menuPositionClass]"
|
|
19
|
-
class="absolute z-
|
|
19
|
+
class="absolute z-menu mt-2 rounded-md bg-white p-1 shadow-lg ring-1 ring-black ring-opacity-10 focus:outline-none"
|
|
20
20
|
>
|
|
21
21
|
<slot name="items">
|
|
22
22
|
<template v-for="item in items" :key="item.label + 'link'">
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import BaseModalCenter from './BaseModalCenter.vue';
|
|
2
|
+
import { Icon as BaseIcon } from '@iconify/vue';
|
|
3
|
+
import BaseAvatar from './BaseAvatar.vue';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'Components/BaseModalCenter',
|
|
7
|
+
component: BaseModalCenter,
|
|
8
|
+
args: {
|
|
9
|
+
position: 'bottom-right',
|
|
10
|
+
},
|
|
11
|
+
argTypes: {
|
|
12
|
+
verticalAlign: {
|
|
13
|
+
control: { type: 'select' },
|
|
14
|
+
options: ['center', 'top'],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const Template = (args) => ({
|
|
20
|
+
components: {
|
|
21
|
+
BaseModalCenter,
|
|
22
|
+
BaseIcon,
|
|
23
|
+
BaseAvatar,
|
|
24
|
+
},
|
|
25
|
+
setup() {
|
|
26
|
+
const show = ref(false);
|
|
27
|
+
return { args, show };
|
|
28
|
+
},
|
|
29
|
+
template: `
|
|
30
|
+
<div class="">
|
|
31
|
+
<button @click="show = true" class="btn">Show modal</button>
|
|
32
|
+
<BaseModalCenter v-model="show" v-bind="args">
|
|
33
|
+
<template #default="{close}">
|
|
34
|
+
<div class="p-8">
|
|
35
|
+
<p class="mb-6">Hello!</p>
|
|
36
|
+
|
|
37
|
+
<button @click="close" class="btn btn-sm">Close</button>
|
|
38
|
+
</div>
|
|
39
|
+
</template>
|
|
40
|
+
</BaseModalCenter>
|
|
41
|
+
</div>
|
|
42
|
+
`,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const Demo = Template.bind({});
|
|
46
|
+
Demo.args = {};
|
|
47
|
+
|
|
48
|
+
export const VerticalAlignTop = Template.bind({});
|
|
49
|
+
VerticalAlignTop.args = {
|
|
50
|
+
verticalAlign: 'top',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const CustomBackdropClass = Template.bind({});
|
|
54
|
+
CustomBackdropClass.args = {
|
|
55
|
+
backdropClass: 'bg-red-500 bg-opacity-70',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const PreventLeave = Template.bind({});
|
|
59
|
+
PreventLeave.args = {
|
|
60
|
+
closeOnOutsideClick: false,
|
|
61
|
+
};
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
>
|
|
31
31
|
<div
|
|
32
32
|
v-if="modelValue"
|
|
33
|
-
:class="
|
|
33
|
+
:class="backdropClass"
|
|
34
34
|
class="fixed inset-0 transition-opacity"
|
|
35
35
|
@click="
|
|
36
36
|
closeOnOutsideClick
|
|
@@ -85,7 +85,7 @@ const props = defineProps({
|
|
|
85
85
|
default: 'center',
|
|
86
86
|
type: String,
|
|
87
87
|
},
|
|
88
|
-
|
|
88
|
+
backdropClass: {
|
|
89
89
|
default: 'bg-opacity-70 bg-slate-900',
|
|
90
90
|
type: String,
|
|
91
91
|
},
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import BaseModalSide from './BaseModalSide.vue';
|
|
2
|
+
import { Icon as BaseIcon } from '@iconify/vue';
|
|
3
|
+
import BaseAvatar from './BaseAvatar.vue';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'Components/BaseModalSide',
|
|
7
|
+
component: BaseModalSide,
|
|
8
|
+
args: {
|
|
9
|
+
position: 'bottom-right',
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const Template = (args) => ({
|
|
14
|
+
components: {
|
|
15
|
+
BaseModalSide,
|
|
16
|
+
BaseIcon,
|
|
17
|
+
BaseAvatar,
|
|
18
|
+
},
|
|
19
|
+
setup() {
|
|
20
|
+
const show = ref(false);
|
|
21
|
+
return { args, show };
|
|
22
|
+
},
|
|
23
|
+
template: `
|
|
24
|
+
<div class="">
|
|
25
|
+
<button @click="show = true" class="btn">Show modal</button>
|
|
26
|
+
<BaseModalSide v-model="show" v-bind="args">
|
|
27
|
+
<template #default="{close}">
|
|
28
|
+
<div class="p-8">
|
|
29
|
+
<p class="mb-6">Hello!</p>
|
|
30
|
+
|
|
31
|
+
<button @click="close" class="btn btn-sm">Close</button>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
</BaseModalSide>
|
|
35
|
+
</div>
|
|
36
|
+
`,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export const Demo = Template.bind({});
|
|
40
|
+
Demo.args = {};
|
|
41
|
+
|
|
42
|
+
export const CustomMaxWidth = Template.bind({});
|
|
43
|
+
CustomMaxWidth.args = {
|
|
44
|
+
maxWidth: '16rem',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const CustomBackdropClass = Template.bind({});
|
|
48
|
+
CustomBackdropClass.args = {
|
|
49
|
+
backdropClass: 'bg-red-500 bg-opacity-70',
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const PreventLeave = Template.bind({});
|
|
53
|
+
PreventLeave.args = {
|
|
54
|
+
closeOnOutsideClick: false,
|
|
55
|
+
};
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
>
|
|
25
25
|
<div
|
|
26
26
|
v-show="modelValue"
|
|
27
|
-
:class="
|
|
27
|
+
:class="backdropClass"
|
|
28
28
|
class="fixed inset-0 transition-opacity"
|
|
29
29
|
@click="
|
|
30
30
|
closeOnOutsideClick
|
|
@@ -85,7 +85,7 @@ const props = defineProps({
|
|
|
85
85
|
default: '32rem',
|
|
86
86
|
type: String,
|
|
87
87
|
},
|
|
88
|
-
|
|
88
|
+
backdropClass: {
|
|
89
89
|
default: 'bg-opacity-70 bg-slate-900',
|
|
90
90
|
type: String,
|
|
91
91
|
},
|