sprintify-ui 0.0.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 (176) hide show
  1. package/README.md +188 -0
  2. package/dist/types/src/components/BaseAlert.vue.d.ts +51 -0
  3. package/dist/types/src/components/BaseAutocomplete.vue.d.ts +268 -0
  4. package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +273 -0
  5. package/dist/types/src/components/BaseAvatar.vue.d.ts +126 -0
  6. package/dist/types/src/components/BaseBadge.vue.d.ts +94 -0
  7. package/dist/types/src/components/BaseBelongsTo.vue.d.ts +268 -0
  8. package/dist/types/src/components/BaseBoolean.vue.d.ts +64 -0
  9. package/dist/types/src/components/BaseBreadcrumbs.vue.d.ts +66 -0
  10. package/dist/types/src/components/BaseButton.vue.d.ts +23 -0
  11. package/dist/types/src/components/BaseCard.vue.d.ts +74 -0
  12. package/dist/types/src/components/BaseCardRow.vue.d.ts +16 -0
  13. package/dist/types/src/components/BaseClipboard.vue.d.ts +74 -0
  14. package/dist/types/src/components/BaseContainer.vue.d.ts +34 -0
  15. package/dist/types/src/components/BaseCounter.vue.d.ts +125 -0
  16. package/dist/types/src/components/BaseDataIterator.vue.d.ts +345 -0
  17. package/dist/types/src/components/BaseDataTable.vue.d.ts +657 -0
  18. package/dist/types/src/components/BaseDataTableToggleColumns.vue.d.ts +1281 -0
  19. package/dist/types/src/components/BaseDatePicker.vue.d.ts +190 -0
  20. package/dist/types/src/components/BaseDateSelect.vue.d.ts +171 -0
  21. package/dist/types/src/components/BaseDescriptionList.vue.d.ts +48 -0
  22. package/dist/types/src/components/BaseDescriptionListItem.vue.d.ts +49 -0
  23. package/dist/types/src/components/BaseDialog.vue.d.ts +160 -0
  24. package/dist/types/src/components/BaseFilePicker.vue.d.ts +44 -0
  25. package/dist/types/src/components/BaseFileUploader.vue.d.ts +220 -0
  26. package/dist/types/src/components/BaseInput.vue.d.ts +209 -0
  27. package/dist/types/src/components/BaseInputLabel.vue.d.ts +31 -0
  28. package/dist/types/src/components/BaseLoadingCover.vue.d.ts +166 -0
  29. package/dist/types/src/components/BaseLoadingPage.vue.d.ts +2 -0
  30. package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +269 -0
  31. package/dist/types/src/components/BaseMediaLibraryItem.vue.d.ts +75 -0
  32. package/dist/types/src/components/BaseMenu.vue.d.ts +117 -0
  33. package/dist/types/src/components/BaseMenuItem.vue.d.ts +147 -0
  34. package/dist/types/src/components/BaseModalCenter.vue.d.ts +141 -0
  35. package/dist/types/src/components/BaseModalSide.vue.d.ts +141 -0
  36. package/dist/types/src/components/BaseNavbar.vue.d.ts +79 -0
  37. package/dist/types/src/components/BaseNavbarItem.vue.d.ts +80 -0
  38. package/dist/types/src/components/BaseNavbarItemContent.vue.d.ts +127 -0
  39. package/dist/types/src/components/BasePagination.vue.d.ts +25 -0
  40. package/dist/types/src/components/BasePaginationSimple.vue.d.ts +25 -0
  41. package/dist/types/src/components/BasePanel.vue.d.ts +31 -0
  42. package/dist/types/src/components/BasePassword.vue.d.ts +66 -0
  43. package/dist/types/src/components/BaseProcessRing.vue.d.ts +36 -0
  44. package/dist/types/src/components/BaseReadMore.vue.d.ts +74 -0
  45. package/dist/types/src/components/BaseSelect.vue.d.ts +55 -0
  46. package/dist/types/src/components/BaseSideNavigation.vue.d.ts +48 -0
  47. package/dist/types/src/components/BaseSideNavigationItem.vue.d.ts +92 -0
  48. package/dist/types/src/components/BaseSkeleton.vue.d.ts +93 -0
  49. package/dist/types/src/components/BaseSpinner.vue.d.ts +2 -0
  50. package/dist/types/src/components/BaseSwitch.vue.d.ts +39 -0
  51. package/dist/types/src/components/BaseSystemAlert.vue.d.ts +141 -0
  52. package/dist/types/src/components/BaseTabItem.vue.d.ts +70 -0
  53. package/dist/types/src/components/BaseTable.vue.d.ts +467 -0
  54. package/dist/types/src/components/BaseTableColumn.vue.d.ts +164 -0
  55. package/dist/types/src/components/BaseTabs.vue.d.ts +48 -0
  56. package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +274 -0
  57. package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +251 -0
  58. package/dist/types/src/components/BaseTextarea.vue.d.ts +228 -0
  59. package/dist/types/src/components/BaseTextareaAutoresize.vue.d.ts +44 -0
  60. package/dist/types/src/components/BaseTitle.vue.d.ts +45 -0
  61. package/dist/types/src/components/BaseWordCount.vue.d.ts +31 -0
  62. package/dist/types/src/components/SlotComponent.d.ts +43 -0
  63. package/dist/types/src/components/index.d.ts +2 -0
  64. package/dist/types/src/composables/breakpoints.d.ts +12 -0
  65. package/dist/types/src/composables/modal.d.ts +6 -0
  66. package/dist/types/src/constants/MyConstants.d.ts +1 -0
  67. package/dist/types/src/constants/index.d.ts +2 -0
  68. package/dist/types/src/index.d.ts +253 -0
  69. package/dist/types/src/types/Media.d.ts +8 -0
  70. package/dist/types/src/types/UploadedFile.d.ts +9 -0
  71. package/dist/types/src/types/User.d.ts +6 -0
  72. package/dist/types/src/types/types.d.ts +88 -0
  73. package/dist/types/src/utils/fileSizeFormat.d.ts +1 -0
  74. package/dist/types/src/utils/index.d.ts +4 -0
  75. package/dist/types/src/utils/scrollPreventer.d.ts +4 -0
  76. package/dist/types/src/utils/toHumanList.d.ts +1 -0
  77. package/package.json +99 -0
  78. package/src/assets/button.css +80 -0
  79. package/src/assets/form.css +15 -0
  80. package/src/assets/main.css +3 -0
  81. package/src/assets/pikaday.css +134 -0
  82. package/src/assets/tailwind.css +5 -0
  83. package/src/components/BaseAlert.stories.js +52 -0
  84. package/src/components/BaseAlert.vue +152 -0
  85. package/src/components/BaseAutocomplete.stories.js +127 -0
  86. package/src/components/BaseAutocomplete.vue +376 -0
  87. package/src/components/BaseAutocompleteFetch.stories.js +121 -0
  88. package/src/components/BaseAutocompleteFetch.vue +185 -0
  89. package/src/components/BaseAvatar.stories.js +39 -0
  90. package/src/components/BaseAvatar.vue +92 -0
  91. package/src/components/BaseBadge.stories.js +61 -0
  92. package/src/components/BaseBadge.vue +70 -0
  93. package/src/components/BaseBelongsTo.stories.js +130 -0
  94. package/src/components/BaseBelongsTo.vue +122 -0
  95. package/src/components/BaseBoolean.stories.js +35 -0
  96. package/src/components/BaseBoolean.vue +29 -0
  97. package/src/components/BaseBreadcrumbs.stories.js +45 -0
  98. package/src/components/BaseBreadcrumbs.vue +78 -0
  99. package/src/components/BaseButton.stories.js +80 -0
  100. package/src/components/BaseButton.vue +39 -0
  101. package/src/components/BaseCard.stories.js +61 -0
  102. package/src/components/BaseCard.vue +49 -0
  103. package/src/components/BaseCardRow.vue +34 -0
  104. package/src/components/BaseClipboard.stories.js +31 -0
  105. package/src/components/BaseClipboard.vue +96 -0
  106. package/src/components/BaseContainer.stories.js +34 -0
  107. package/src/components/BaseContainer.vue +50 -0
  108. package/src/components/BaseCounter.stories.js +32 -0
  109. package/src/components/BaseCounter.vue +72 -0
  110. package/src/components/BaseDataIterator.stories.js +90 -0
  111. package/src/components/BaseDataIterator.vue +658 -0
  112. package/src/components/BaseDataTable.stories.js +95 -0
  113. package/src/components/BaseDataTable.vue +489 -0
  114. package/src/components/BaseDataTableToggleColumns.vue +69 -0
  115. package/src/components/BaseDatePicker.stories.js +53 -0
  116. package/src/components/BaseDatePicker.vue +166 -0
  117. package/src/components/BaseDateSelect.vue +192 -0
  118. package/src/components/BaseDescriptionList.vue +11 -0
  119. package/src/components/BaseDescriptionListItem.vue +12 -0
  120. package/src/components/BaseDialog.vue +104 -0
  121. package/src/components/BaseFilePicker.vue +101 -0
  122. package/src/components/BaseFileUploader.vue +166 -0
  123. package/src/components/BaseInput.vue +82 -0
  124. package/src/components/BaseInputLabel.vue +26 -0
  125. package/src/components/BaseLoadingCover.vue +84 -0
  126. package/src/components/BaseLoadingPage.vue +19 -0
  127. package/src/components/BaseMediaLibrary.vue +281 -0
  128. package/src/components/BaseMediaLibraryItem.vue +92 -0
  129. package/src/components/BaseMenu.vue +114 -0
  130. package/src/components/BaseMenuItem.vue +93 -0
  131. package/src/components/BaseModalCenter.vue +107 -0
  132. package/src/components/BaseModalSide.vue +112 -0
  133. package/src/components/BaseNavbar.vue +72 -0
  134. package/src/components/BaseNavbarItem.vue +72 -0
  135. package/src/components/BaseNavbarItemContent.vue +57 -0
  136. package/src/components/BasePagination.vue +82 -0
  137. package/src/components/BasePaginationSimple.vue +60 -0
  138. package/src/components/BasePanel.vue +39 -0
  139. package/src/components/BasePassword.vue +73 -0
  140. package/src/components/BaseProcessRing.vue +56 -0
  141. package/src/components/BaseReadMore.vue +72 -0
  142. package/src/components/BaseSelect.vue +59 -0
  143. package/src/components/BaseSideNavigation.vue +7 -0
  144. package/src/components/BaseSideNavigationItem.vue +42 -0
  145. package/src/components/BaseSkeleton.vue +24 -0
  146. package/src/components/BaseSpinner.vue +47 -0
  147. package/src/components/BaseSwitch.vue +87 -0
  148. package/src/components/BaseSystemAlert.vue +86 -0
  149. package/src/components/BaseTabItem.vue +30 -0
  150. package/src/components/BaseTable.vue +781 -0
  151. package/src/components/BaseTableColumn.vue +109 -0
  152. package/src/components/BaseTabs.vue +12 -0
  153. package/src/components/BaseTagAutocomplete.vue +385 -0
  154. package/src/components/BaseTagAutocompleteFetch.vue +154 -0
  155. package/src/components/BaseTextarea.vue +73 -0
  156. package/src/components/BaseTextareaAutoresize.vue +117 -0
  157. package/src/components/BaseTitle.vue +80 -0
  158. package/src/components/BaseWordCount.vue +36 -0
  159. package/src/components/SlotComponent.ts +37 -0
  160. package/src/components/index.ts +5 -0
  161. package/src/composables/breakpoints.ts +6 -0
  162. package/src/composables/modal.ts +77 -0
  163. package/src/constants/MyConstants.ts +1 -0
  164. package/src/constants/index.ts +5 -0
  165. package/src/env.d.ts +15 -0
  166. package/src/index.ts +70 -0
  167. package/src/lang/en.json +56 -0
  168. package/src/lang/fr.json +56 -0
  169. package/src/types/Media.ts +9 -0
  170. package/src/types/UploadedFile.ts +10 -0
  171. package/src/types/User.ts +7 -0
  172. package/src/types/types.ts +112 -0
  173. package/src/utils/fileSizeFormat.ts +15 -0
  174. package/src/utils/index.ts +5 -0
  175. package/src/utils/scrollPreventer.ts +21 -0
  176. package/src/utils/toHumanList.ts +20 -0
@@ -0,0 +1,92 @@
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>
@@ -0,0 +1,114 @@
1
+ <template>
2
+ <Menu v-slot="{ open }" as="div" class="relative text-left">
3
+ <div>
4
+ <MenuButton class="flex">
5
+ <slot name="button" :open="open" />
6
+ </MenuButton>
7
+ </div>
8
+
9
+ <transition
10
+ enter-active-class="transition duration-200 ease-out"
11
+ enter-from-class="transform scale-95 opacity-0"
12
+ enter-to-class="transform scale-100 opacity-100"
13
+ leave-active-class="transition duration-75 ease-in"
14
+ leave-from-class="transform scale-100 opacity-100"
15
+ leave-to-class="transform scale-95 opacity-0"
16
+ >
17
+ <MenuItems
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"
20
+ >
21
+ <slot name="items">
22
+ <template v-for="item in items" :key="item.label + 'link'">
23
+ <div v-if="item.line" class="my-1 -mx-1 flex h-px bg-gray-200" />
24
+
25
+ <router-link
26
+ v-else-if="item.to"
27
+ v-slot="{ href, navigate }"
28
+ custom
29
+ :to="item.to"
30
+ >
31
+ <MenuItem
32
+ v-slot="{ active }"
33
+ as="a"
34
+ :href="href"
35
+ @click="navigate"
36
+ >
37
+ <BaseMenuItem
38
+ :label="item.label"
39
+ :count="item.count"
40
+ :icon="item.icon"
41
+ :color="item.color"
42
+ :active="active"
43
+ />
44
+ </MenuItem>
45
+ </router-link>
46
+
47
+ <MenuItem
48
+ v-else-if="item.href"
49
+ v-slot="{ active }"
50
+ as="a"
51
+ :href="item.href"
52
+ >
53
+ <BaseMenuItem
54
+ :label="item.label"
55
+ :count="item.count"
56
+ :icon="item.icon"
57
+ :color="item.color"
58
+ :active="active"
59
+ />
60
+ </MenuItem>
61
+
62
+ <MenuItem
63
+ v-else-if="item.action"
64
+ v-slot="{ active }"
65
+ as="button"
66
+ type="button"
67
+ class="w-full"
68
+ @click="item.action"
69
+ >
70
+ <BaseMenuItem
71
+ :label="item.label"
72
+ :count="item.count"
73
+ :icon="item.icon"
74
+ :color="item.color"
75
+ :active="active"
76
+ />
77
+ </MenuItem>
78
+ </template>
79
+ </slot>
80
+ </MenuItems>
81
+ </transition>
82
+ </Menu>
83
+ </template>
84
+
85
+ <script lang="ts" setup>
86
+ import { PropType } from 'vue';
87
+ import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue';
88
+ import { MenuItemInterface } from '@/types/types';
89
+ import BaseMenuItem from './BaseMenuItem.vue';
90
+
91
+ const props = defineProps({
92
+ items: {
93
+ default: undefined,
94
+ type: Array as PropType<MenuItemInterface[]>,
95
+ },
96
+ menuClass: {
97
+ default: 'w-48',
98
+ type: String,
99
+ },
100
+ position: {
101
+ default: 'bottom-left',
102
+ type: String as PropType<'bottom-left' | 'bottom-right'>,
103
+ },
104
+ });
105
+
106
+ const menuPositionClass = computed(() => {
107
+ if (props.position == 'bottom-left') {
108
+ return 'origin-top-right right-0';
109
+ }
110
+ if (props.position == 'bottom-right') {
111
+ return 'origin-top-left left-0';
112
+ }
113
+ });
114
+ </script>
@@ -0,0 +1,93 @@
1
+ <template>
2
+ <div :class="buttonClasses">
3
+ <div class="flex items-center">
4
+ <Icon v-if="icon" :icon="icon" :class="iconClasses" />
5
+ {{ label }}
6
+ </div>
7
+ <div v-if="count" class="relative -top-px ml-[5px]">
8
+ <BaseCounter
9
+ :count="count"
10
+ :max-digit="2"
11
+ :color="active ? 'white' : 'primary'"
12
+ />
13
+ </div>
14
+ </div>
15
+ </template>
16
+
17
+ <script lang="ts" setup>
18
+ import { PropType } from 'vue';
19
+ import BaseCounter from './BaseCounter.vue';
20
+
21
+ const props = defineProps({
22
+ label: {
23
+ default: undefined,
24
+ type: String,
25
+ },
26
+ icon: {
27
+ default: undefined,
28
+ type: String,
29
+ },
30
+ active: {
31
+ default: false,
32
+ type: Boolean,
33
+ },
34
+ count: {
35
+ default: undefined,
36
+ type: Number,
37
+ },
38
+ color: {
39
+ default: 'dark',
40
+ type: String as PropType<
41
+ 'dark' | 'light' | 'danger' | 'success' | 'warning'
42
+ >,
43
+ },
44
+ });
45
+
46
+ const textColor = computed((): string => {
47
+ if (props.color == 'dark') {
48
+ return 'text-slate-700';
49
+ } else if (props.color == 'light') {
50
+ return 'text-slate-600';
51
+ } else if (props.color == 'danger') {
52
+ return 'text-red-600';
53
+ } else if (props.color == 'success') {
54
+ return 'text-green-600';
55
+ } else if (props.color == 'warning') {
56
+ return 'text-yellow-600';
57
+ }
58
+
59
+ return '';
60
+ });
61
+
62
+ const buttonClasses = computed((): string => {
63
+ let baseClasses =
64
+ 'flex items-center justify-between w-full leading-tight py-2 text-sm text-left rounded';
65
+
66
+ if (!props.active) {
67
+ baseClasses += ' bg-white';
68
+ baseClasses += ' ' + textColor.value;
69
+ } else {
70
+ baseClasses += ' bg-primary-600 text-white';
71
+ }
72
+
73
+ if (props.icon) {
74
+ baseClasses += ' pl-2 pr-4';
75
+ } else {
76
+ baseClasses += ' px-4';
77
+ }
78
+
79
+ return baseClasses;
80
+ });
81
+
82
+ const iconClasses = computed((): string => {
83
+ let baseClasses = ' w-5 h-5 shrink-0 mr-2';
84
+
85
+ if (!props.active) {
86
+ baseClasses += ' opacity-70 ' + textColor.value;
87
+ } else {
88
+ baseClasses += ' text-primary-100';
89
+ }
90
+
91
+ return baseClasses;
92
+ });
93
+ </script>
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <Teleport to="body">
3
+ <transition
4
+ name="modal"
5
+ enter-active-class="duration-300"
6
+ leave-active-class="duration-200"
7
+ >
8
+ <div v-show="modelValue">
9
+ <div
10
+ ref="allow"
11
+ class="fixed inset-0 z-modal w-full overflow-y-auto overflow-x-hidden"
12
+ scroll-lock-target
13
+ >
14
+ <div
15
+ class="flex min-h-full w-full items-end justify-center overflow-hidden pt-20 sm:px-6 sm:pb-6 sm:pt-20"
16
+ :class="{
17
+ 'sm:items-center': verticalAlign == 'center',
18
+ 'sm:items-start': verticalAlign == 'top',
19
+ }"
20
+ >
21
+ <div class="pt-safe grow">
22
+ <transition
23
+ appear
24
+ enter-active-class="duration-300 ease-out"
25
+ enter-from-class="opacity-0"
26
+ enter-to-class="opacity-100"
27
+ leave-active-class="duration-200 ease-in"
28
+ leave-from-class="opacity-100"
29
+ leave-to-class="opacity-0"
30
+ >
31
+ <div
32
+ v-if="modelValue"
33
+ :class="modalOverlayClasses"
34
+ class="fixed inset-0 transition-opacity"
35
+ @click="
36
+ closeOnOutsideClick
37
+ ? modal.close()
38
+ : modal.refuseAnimation()
39
+ "
40
+ />
41
+ </transition>
42
+
43
+ <transition
44
+ appear
45
+ enter-active-class="duration-300 ease-out"
46
+ enter-from-class="translate-y-20 opacity-0"
47
+ enter-to-class="translate-y-0 opacity-100"
48
+ leave-active-class="duration-200 ease-in"
49
+ leave-from-class="translate-y-0 opacity-100"
50
+ leave-to-class="translate-y-20 opacity-0"
51
+ >
52
+ <div
53
+ v-if="modelValue"
54
+ class="pb-safe relative z-[1] mx-auto block w-full rounded-t-xl bg-white sm:max-w-lg sm:rounded-xl sm:shadow-xl"
55
+ :class="[modal.animationClasses.value]"
56
+ >
57
+ <slot :close="modal.close" />
58
+ </div>
59
+ </transition>
60
+ </div>
61
+ </div>
62
+
63
+ <button
64
+ class="right absolute top-2 right-2 flex h-16 w-16 items-center justify-center rounded-full hover:bg-black hover:bg-opacity-20"
65
+ type="button"
66
+ @click="modal.close()"
67
+ >
68
+ <Icon class="h-8 w-8 text-white" icon="heroicons:x-mark"></Icon>
69
+ </button>
70
+ </div>
71
+ </div>
72
+ </transition>
73
+ </Teleport>
74
+ </template>
75
+
76
+ <script lang="ts" setup>
77
+ import { useModal } from '@/composables/modal';
78
+
79
+ const props = defineProps({
80
+ modelValue: {
81
+ default: false,
82
+ type: Boolean,
83
+ },
84
+ verticalAlign: {
85
+ default: 'center',
86
+ type: String,
87
+ },
88
+ modalOverlayClasses: {
89
+ default: 'bg-opacity-70 bg-slate-900',
90
+ type: String,
91
+ },
92
+ closeOnOutsideClick: {
93
+ default: true,
94
+ type: Boolean,
95
+ },
96
+ });
97
+
98
+ const emit = defineEmits(['update:modelValue']);
99
+
100
+ const allow = ref(null);
101
+
102
+ const modal = useModal(
103
+ computed(() => props.modelValue),
104
+ allow,
105
+ emit as any
106
+ );
107
+ </script>
@@ -0,0 +1,112 @@
1
+ <template>
2
+ <Teleport to="body">
3
+ <transition
4
+ name="modal"
5
+ enter-active-class="duration-300"
6
+ leave-active-class="duration-200"
7
+ >
8
+ <div v-show="modelValue">
9
+ <div
10
+ ref="allow"
11
+ class="fixed inset-0 z-modal w-full overflow-y-auto overflow-x-hidden"
12
+ scroll-lock-target
13
+ >
14
+ <div class="flex min-h-full w-full pt-20 sm:pt-0">
15
+ <div class="min-h-full grow">
16
+ <transition
17
+ appear
18
+ enter-active-class="duration-300 ease-out"
19
+ enter-from-class="opacity-0"
20
+ enter-to-class="opacity-100"
21
+ leave-active-class="duration-200 ease-in"
22
+ leave-from-class="opacity-100"
23
+ leave-to-class="opacity-0"
24
+ >
25
+ <div
26
+ v-show="modelValue"
27
+ :class="modalOverlayClasses"
28
+ class="fixed inset-0 transition-opacity"
29
+ @click="
30
+ closeOnOutsideClick
31
+ ? modal.close()
32
+ : modal.refuseAnimation()
33
+ "
34
+ />
35
+ </transition>
36
+
37
+ <transition
38
+ appear
39
+ enter-active-class="duration-300 ease-out"
40
+ enter-from-class="translate-x-20 opacity-0"
41
+ enter-to-class="translate-x-0 opacity-100"
42
+ leave-active-class="duration-200 ease-in"
43
+ leave-from-class="translate-x-0 opacity-100"
44
+ leave-to-class="translate-x-20 opacity-0"
45
+ >
46
+ <div
47
+ v-show="modelValue"
48
+ :style="{
49
+ maxWidth: realMaxWidth,
50
+ }"
51
+ class="pb-safe py-safe relative z-[1] ml-auto mr-0 flex h-full w-full flex-col rounded-t-lg bg-white text-left shadow-xl sm:rounded-t-none"
52
+ :class="[modal.animationClasses.value]"
53
+ >
54
+ <button
55
+ class="absolute -top-[4.5rem] right-2 flex h-16 w-16 items-center justify-center rounded-full hover:bg-black hover:bg-opacity-20 sm:-left-[4.5rem] sm:top-2"
56
+ type="button"
57
+ @click="modal.close()"
58
+ >
59
+ <Icon
60
+ class="h-8 w-8 text-white"
61
+ icon="heroicons:x-mark"
62
+ ></Icon>
63
+ </button>
64
+ <slot :close="modal.close" />
65
+ </div>
66
+ </transition>
67
+ </div>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ </transition>
72
+ </Teleport>
73
+ </template>
74
+
75
+ <script lang="ts" setup>
76
+ import { useBreakpoints } from '@/composables/breakpoints';
77
+ import { useModal } from '@/composables/modal';
78
+
79
+ const props = defineProps({
80
+ modelValue: {
81
+ default: false,
82
+ type: Boolean,
83
+ },
84
+ maxWidth: {
85
+ default: '32rem',
86
+ type: String,
87
+ },
88
+ modalOverlayClasses: {
89
+ default: 'bg-opacity-70 bg-slate-900',
90
+ type: String,
91
+ },
92
+ closeOnOutsideClick: {
93
+ default: true,
94
+ type: Boolean,
95
+ },
96
+ });
97
+
98
+ const emit = defineEmits(['update:modelValue']);
99
+
100
+ const allow = ref(null);
101
+ const modal = useModal(
102
+ computed(() => props.modelValue),
103
+ allow,
104
+ emit
105
+ );
106
+
107
+ const breakpoints = useBreakpoints();
108
+
109
+ const realMaxWidth = computed((): string => {
110
+ return breakpoints.greater('sm').value ? props.maxWidth : '100%';
111
+ });
112
+ </script>
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <nav class="bg-slate-800">
3
+ <BaseContainer :size="size">
4
+ <div class="flex h-16 justify-between">
5
+ <!-- Navbar (desktop and mobile) -->
6
+ <div class="grow">
7
+ <slot name="navbar" />
8
+ </div>
9
+
10
+ <!-- Mobile Burger menu button -->
11
+ <div class="-mr-2 flex items-center md:hidden">
12
+ <button
13
+ type="button"
14
+ class="inline-flex items-center justify-center rounded-md bg-slate-800 p-2 text-slate-400 hover:bg-slate-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 focus:ring-offset-slate-800"
15
+ @click="toggleMenu()"
16
+ >
17
+ <span class="sr-only">Open main menu</span>
18
+ <Icon
19
+ v-if="!showMobileMenu"
20
+ icon="heroicons:bars-3"
21
+ class="block h-6 w-6"
22
+ aria-hidden="true"
23
+ />
24
+ <Icon
25
+ v-else
26
+ icon="heroicons:x-mark"
27
+ class="block h-6 w-6"
28
+ aria-hidden="true"
29
+ />
30
+ </button>
31
+ </div>
32
+ </div>
33
+ </BaseContainer>
34
+
35
+ <!-- Mobile -->
36
+ <div v-if="showMobileMenu" class="absolute w-full bg-slate-800 md:hidden">
37
+ <slot
38
+ name="mobile"
39
+ :toggle-menu="toggleMenu"
40
+ :close-menu="closeMenu"
41
+ :open-menu="openMenu"
42
+ />
43
+ </div>
44
+ </nav>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ defineProps({
49
+ size: {
50
+ default: '7xl',
51
+ type: String,
52
+ },
53
+ });
54
+
55
+ const showMobileMenu = ref(false);
56
+
57
+ function toggleMenu() {
58
+ showMobileMenu.value = !showMobileMenu.value;
59
+ }
60
+
61
+ function openMenu() {
62
+ showMobileMenu.value = true;
63
+ }
64
+
65
+ function closeMenu() {
66
+ showMobileMenu.value = false;
67
+ }
68
+
69
+ provide('toggleMenu', toggleMenu);
70
+ provide('openMenu', openMenu);
71
+ provide('closeMenu', closeMenu);
72
+ </script>
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <div>
3
+ <RouterLink
4
+ v-if="item.to"
5
+ v-slot="{ isActive, href: slotHref, navigate }"
6
+ custom
7
+ :to="item.to"
8
+ >
9
+ <a
10
+ :active="isActive"
11
+ :href="slotHref"
12
+ :aria-current="isActive ? 'page' : undefined"
13
+ class="block w-full"
14
+ @click.prevent="onClick(navigate)"
15
+ >
16
+ <slot :active="isActive">
17
+ <BaseNavbarItemContent
18
+ :label="item.label"
19
+ :icon="item.icon"
20
+ :active="isActive"
21
+ :count="item.count"
22
+ />
23
+ </slot>
24
+ </a>
25
+ </RouterLink>
26
+ <button
27
+ v-else-if="item.action"
28
+ type="button"
29
+ class="block w-full"
30
+ @click="item.action"
31
+ >
32
+ <slot :active="false">
33
+ <BaseNavbarItemContent
34
+ :label="item.label"
35
+ :icon="item.icon"
36
+ :count="item.count"
37
+ />
38
+ </slot>
39
+ </button>
40
+ <a v-else-if="item.href" :href="item.href" class="block w-full">
41
+ <slot :active="false">
42
+ <BaseNavbarItemContent
43
+ :label="item.label"
44
+ :icon="item.icon"
45
+ :count="item.count"
46
+ />
47
+ </slot>
48
+ </a>
49
+ </div>
50
+ </template>
51
+
52
+ <script setup lang="ts">
53
+ import { PropType } from 'vue';
54
+ import { ActionItem } from '@/types/types';
55
+
56
+ defineProps({
57
+ item: {
58
+ required: true,
59
+ type: Object as PropType<ActionItem>,
60
+ },
61
+ });
62
+
63
+ const closeMenu = inject('closeMenu') as () => void;
64
+
65
+ const emit = defineEmits(['click']);
66
+
67
+ function onClick(navigate: () => void) {
68
+ navigate();
69
+ emit('click');
70
+ closeMenu();
71
+ }
72
+ </script>