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.
Files changed (96) hide show
  1. package/README.md +8 -7
  2. package/dist/sprintify-ui.es.js +5911 -3760
  3. package/dist/style.css +1 -1
  4. package/dist/tailwindcss/index.js +1 -2
  5. package/dist/types/src/components/BaseCharacterCounter.vue.d.ts +143 -0
  6. package/dist/types/src/components/BaseHasMany.vue.d.ts +277 -0
  7. package/dist/types/src/components/BaseInput.vue.d.ts +39 -5
  8. package/dist/types/src/components/BaseLoadingCover.vue.d.ts +72 -0
  9. package/dist/types/src/components/{BaseMediaLibraryItem.vue.d.ts → BaseMediaItem.vue.d.ts} +26 -4
  10. package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +23 -15
  11. package/dist/types/src/components/BaseMediaPreview.vue.d.ts +97 -0
  12. package/dist/types/src/components/BaseModalCenter.vue.d.ts +8 -8
  13. package/dist/types/src/components/BaseModalSide.vue.d.ts +8 -8
  14. package/dist/types/src/components/BasePagination.vue.d.ts +105 -13
  15. package/dist/types/src/components/BaseSelect.vue.d.ts +130 -26
  16. package/dist/types/src/components/BaseSideNavigationItem.vue.d.ts +20 -1
  17. package/dist/types/src/components/BaseSwitch.vue.d.ts +15 -8
  18. package/dist/types/src/components/BaseTabItem.vue.d.ts +45 -4
  19. package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +25 -17
  20. package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +37 -21
  21. package/dist/types/src/components/BaseTextareaAutoresize.vue.d.ts +175 -21
  22. package/dist/types/src/components/index.d.ts +30 -1
  23. package/dist/types/src/index.d.ts +4 -0
  24. package/package.json +1 -1
  25. package/src/components/BaseAppDialogs.vue +2 -2
  26. package/src/components/BaseAppNotifications.vue +1 -1
  27. package/src/components/BaseAutocomplete.vue +16 -18
  28. package/src/components/BaseBelongsTo.vue +1 -0
  29. package/src/components/BaseCharacterCounter.stories.js +30 -0
  30. package/src/components/BaseCharacterCounter.vue +60 -0
  31. package/src/components/BaseClipboard.vue +1 -1
  32. package/src/components/BaseDataIterator.stories.js +2 -2
  33. package/src/components/BaseDataIterator.vue +32 -38
  34. package/src/components/BaseDataTable.stories.js +2 -2
  35. package/src/components/BaseFileUploader.vue +4 -0
  36. package/src/components/BaseHasMany.vue +92 -0
  37. package/src/components/BaseInput.stories.js +46 -0
  38. package/src/components/BaseInput.vue +10 -2
  39. package/src/components/BaseInputLabel.stories.js +31 -0
  40. package/src/components/BaseInputLabel.vue +1 -1
  41. package/src/components/BaseLoadingCover.stories.js +55 -0
  42. package/src/components/BaseLoadingCover.vue +19 -1
  43. package/src/components/BaseMediaItem.stories.js +41 -0
  44. package/src/components/BaseMediaItem.vue +71 -0
  45. package/src/components/BaseMediaLibrary.stories.js +80 -0
  46. package/src/components/BaseMediaLibrary.vue +67 -68
  47. package/src/components/BaseMediaPreview.stories.js +72 -0
  48. package/src/components/BaseMediaPreview.vue +90 -0
  49. package/src/components/BaseMenu.stories.js +125 -0
  50. package/src/components/BaseMenu.vue +1 -1
  51. package/src/components/BaseModalCenter.stories.js +61 -0
  52. package/src/components/BaseModalCenter.vue +2 -2
  53. package/src/components/BaseModalSide.stories.js +55 -0
  54. package/src/components/BaseModalSide.vue +2 -2
  55. package/src/components/BaseNavbar.stories.js +150 -0
  56. package/src/components/BaseNavbar.vue +3 -0
  57. package/src/components/BaseNavbarItem.vue +1 -0
  58. package/src/components/BaseNavbarItemContent.vue +3 -0
  59. package/src/components/BasePagination.stories.js +32 -0
  60. package/src/components/BasePagination.vue +126 -40
  61. package/src/components/BasePanel.stories.js +56 -0
  62. package/src/components/BasePassword.stories.js +36 -0
  63. package/src/components/BasePassword.vue +11 -5
  64. package/src/components/BaseProcessRing.stories.js +27 -0
  65. package/src/components/BaseReadMore.stories.js +30 -0
  66. package/src/components/BaseReadMore.vue +1 -1
  67. package/src/components/BaseSelect.stories.js +67 -0
  68. package/src/components/BaseSelect.vue +144 -44
  69. package/src/components/BaseSideNavigation.stories.js +55 -0
  70. package/src/components/BaseSideNavigation.vue +7 -2
  71. package/src/components/BaseSideNavigationItem.vue +21 -5
  72. package/src/components/BaseSkeleton.stories.js +36 -0
  73. package/src/components/BaseSwitch.stories.js +101 -0
  74. package/src/components/BaseSwitch.vue +90 -12
  75. package/src/components/BaseSystemAlert.stories.js +63 -0
  76. package/src/components/BaseTabItem.vue +29 -6
  77. package/src/components/BaseTable.vue +2 -2
  78. package/src/components/BaseTabs.stories.js +54 -0
  79. package/src/components/BaseTabs.vue +3 -3
  80. package/src/components/BaseTagAutocomplete.stories.js +129 -0
  81. package/src/components/BaseTagAutocomplete.vue +155 -57
  82. package/src/components/BaseTagAutocompleteFetch.stories.js +130 -0
  83. package/src/components/BaseTagAutocompleteFetch.vue +36 -25
  84. package/src/components/BaseTextarea.stories.js +35 -0
  85. package/src/components/BaseTextarea.vue +1 -1
  86. package/src/components/BaseTextareaAutoresize.stories.js +49 -0
  87. package/src/components/BaseTextareaAutoresize.vue +83 -87
  88. package/src/components/HasMany.stories.js +135 -0
  89. package/src/components/index.ts +58 -0
  90. package/src/lang/en.json +2 -1
  91. package/src/lang/fr.json +2 -1
  92. package/dist/types/src/components/BasePaginationSimple.vue.d.ts +0 -25
  93. package/dist/types/src/components/BaseWordCount.vue.d.ts +0 -31
  94. package/src/components/BaseMediaLibraryItem.vue +0 -92
  95. package/src/components/BasePaginationSimple.vue +0 -60
  96. 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="flex w-full items-start space-x-4 rounded-lg border-2 border-dashed border-slate-200 p-5 duration-200 hover:bg-slate-50 hover:enabled:bg-slate-100"
23
+ class="rounded border border-dashed p-6 duration-150"
48
24
  :class="[
49
- baseFileUploaderProps.dragging ? 'bg-slate-100' : 'bg-white',
50
- baseFileUploaderProps.disabled ? 'opacity-25' : '',
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="rounded-full bg-slate-200 p-2">
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
- </div>
59
- <div class="text-left">
60
- <p class="mb-0 text-sm font-medium leading-tight">
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
- <p class="text-red-600">
52
+ <BaseAlert v-if="globalErrorMessage" class="mt-5" color="danger" bordered>
83
53
  {{ globalErrorMessage }}
84
- </p>
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 _, { cloneDeep, get } from 'lodash';
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 { fileSizeFormat } from 'src/utils';
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: Object as PropType<Record<string, string[]>>,
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
- _.isObject(props.modelValue) &&
163
- _.isArray(props.modelValue.to_add) &&
164
- _.isArray(props.modelValue.to_remove)
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 (errorMessage(props.name + '.to_add.0')) {
275
- return errorMessage(props.name + '.to_add.0');
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-10 mt-2 rounded-md bg-white p-1 shadow-lg ring-1 ring-black ring-opacity-10 focus:outline-none"
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="modalOverlayClasses"
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
- modalOverlayClasses: {
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="modalOverlayClasses"
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
- modalOverlayClasses: {
88
+ backdropClass: {
89
89
  default: 'bg-opacity-70 bg-slate-900',
90
90
  type: String,
91
91
  },