sprintify-ui 0.0.20 → 0.0.21

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.
@@ -0,0 +1,24 @@
1
+ import { PropType } from 'vue';
2
+ import { NotificationsConfig } from '../types/types';
3
+ declare const _default: import("vue").DefineComponent<{
4
+ notificationsConfig: {
5
+ required: true;
6
+ type: PropType<NotificationsConfig>;
7
+ };
8
+ dark: {
9
+ default: boolean;
10
+ type: BooleanConstructor;
11
+ };
12
+ }, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
13
+ notificationsConfig: {
14
+ required: true;
15
+ type: PropType<NotificationsConfig>;
16
+ };
17
+ dark: {
18
+ default: boolean;
19
+ type: BooleanConstructor;
20
+ };
21
+ }>>, {
22
+ dark: boolean;
23
+ }>;
24
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import { Notification } from '@/types/Notification';
2
+ import { PropType } from 'vue';
3
+ declare const _default: import("vue").DefineComponent<{
4
+ notification: {
5
+ required: true;
6
+ type: PropType<Notification>;
7
+ };
8
+ }, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
9
+ notification: {
10
+ required: true;
11
+ type: PropType<Notification>;
12
+ };
13
+ }>>, {}>;
14
+ export default _default;
@@ -1,12 +1,13 @@
1
1
  import { User } from '@/types/User';
2
2
  import { PropType } from 'vue';
3
- import { ActionItem, ActionSection } from '../types/types';
3
+ import { ActionItem, ActionSection, NotificationsConfig } from '../types/types';
4
4
  declare const _default: {
5
5
  new (...args: any[]): {
6
6
  $: import("vue").ComponentInternalInstance;
7
7
  $data: {};
8
8
  $props: Partial<{
9
9
  dark: boolean;
10
+ notifications: NotificationsConfig;
10
11
  appName: string;
11
12
  logoUrl: string;
12
13
  }> & Omit<Readonly<import("vue").ExtractPropTypes<{
@@ -30,11 +31,15 @@ declare const _default: {
30
31
  required: true;
31
32
  type: PropType<User>;
32
33
  };
34
+ notifications: {
35
+ default: undefined;
36
+ type: PropType<NotificationsConfig>;
37
+ };
33
38
  dark: {
34
39
  default: boolean;
35
40
  type: BooleanConstructor;
36
41
  };
37
- }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "dark" | "appName" | "logoUrl">;
42
+ }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "dark" | "notifications" | "appName" | "logoUrl">;
38
43
  $attrs: {
39
44
  [x: string]: unknown;
40
45
  };
@@ -69,12 +74,17 @@ declare const _default: {
69
74
  required: true;
70
75
  type: PropType<User>;
71
76
  };
77
+ notifications: {
78
+ default: undefined;
79
+ type: PropType<NotificationsConfig>;
80
+ };
72
81
  dark: {
73
82
  default: boolean;
74
83
  type: BooleanConstructor;
75
84
  };
76
85
  }>>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
77
86
  dark: boolean;
87
+ notifications: NotificationsConfig;
78
88
  appName: string;
79
89
  logoUrl: string;
80
90
  }, {}, string> & {
@@ -118,6 +128,10 @@ declare const _default: {
118
128
  required: true;
119
129
  type: PropType<User>;
120
130
  };
131
+ notifications: {
132
+ default: undefined;
133
+ type: PropType<NotificationsConfig>;
134
+ };
121
135
  dark: {
122
136
  default: boolean;
123
137
  type: BooleanConstructor;
@@ -147,12 +161,17 @@ declare const _default: {
147
161
  required: true;
148
162
  type: PropType<User>;
149
163
  };
164
+ notifications: {
165
+ default: undefined;
166
+ type: PropType<NotificationsConfig>;
167
+ };
150
168
  dark: {
151
169
  default: boolean;
152
170
  type: BooleanConstructor;
153
171
  };
154
172
  }>>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
155
173
  dark: boolean;
174
+ notifications: NotificationsConfig;
156
175
  appName: string;
157
176
  logoUrl: string;
158
177
  }, {}, string> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & (new () => {
@@ -1,12 +1,13 @@
1
1
  import { User } from '@/types/User';
2
2
  import { PropType } from 'vue';
3
- import { ActionItem } from '../types/types';
3
+ import { ActionItem, NotificationsConfig } from '../types/types';
4
4
  declare const _default: {
5
5
  new (...args: any[]): {
6
6
  $: import("vue").ComponentInternalInstance;
7
7
  $data: {};
8
8
  $props: Partial<{
9
9
  dark: boolean;
10
+ notifications: NotificationsConfig;
10
11
  appName: string;
11
12
  logoUrl: string;
12
13
  }> & Omit<Readonly<import("vue").ExtractPropTypes<{
@@ -30,11 +31,15 @@ declare const _default: {
30
31
  required: true;
31
32
  type: PropType<User>;
32
33
  };
34
+ notifications: {
35
+ default: undefined;
36
+ type: PropType<NotificationsConfig>;
37
+ };
33
38
  dark: {
34
39
  default: boolean;
35
40
  type: BooleanConstructor;
36
41
  };
37
- }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "dark" | "appName" | "logoUrl">;
42
+ }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "dark" | "notifications" | "appName" | "logoUrl">;
38
43
  $attrs: {
39
44
  [x: string]: unknown;
40
45
  };
@@ -69,12 +74,17 @@ declare const _default: {
69
74
  required: true;
70
75
  type: PropType<User>;
71
76
  };
77
+ notifications: {
78
+ default: undefined;
79
+ type: PropType<NotificationsConfig>;
80
+ };
72
81
  dark: {
73
82
  default: boolean;
74
83
  type: BooleanConstructor;
75
84
  };
76
85
  }>>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
77
86
  dark: boolean;
87
+ notifications: NotificationsConfig;
78
88
  appName: string;
79
89
  logoUrl: string;
80
90
  }, {}, string> & {
@@ -118,6 +128,10 @@ declare const _default: {
118
128
  required: true;
119
129
  type: PropType<User>;
120
130
  };
131
+ notifications: {
132
+ default: undefined;
133
+ type: PropType<NotificationsConfig>;
134
+ };
121
135
  dark: {
122
136
  default: boolean;
123
137
  type: BooleanConstructor;
@@ -147,12 +161,17 @@ declare const _default: {
147
161
  required: true;
148
162
  type: PropType<User>;
149
163
  };
164
+ notifications: {
165
+ default: undefined;
166
+ type: PropType<NotificationsConfig>;
167
+ };
150
168
  dark: {
151
169
  default: boolean;
152
170
  type: BooleanConstructor;
153
171
  };
154
172
  }>>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
155
173
  dark: boolean;
174
+ notifications: NotificationsConfig;
156
175
  appName: string;
157
176
  logoUrl: string;
158
177
  }, {}, string> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & (new () => {
@@ -6,8 +6,8 @@ declare const _default: {
6
6
  $data: {};
7
7
  $props: Partial<{
8
8
  items: MenuItemInterface[];
9
- menuClass: string;
10
- position: "bottom-left" | "bottom-right";
9
+ menuClass: string | Record<string, any> | unknown[];
10
+ position: "custom" | "bottom-left" | "bottom-right";
11
11
  }> & Omit<Readonly<import("vue").ExtractPropTypes<{
12
12
  items: {
13
13
  default: undefined;
@@ -15,11 +15,11 @@ declare const _default: {
15
15
  };
16
16
  menuClass: {
17
17
  default: string;
18
- type: StringConstructor;
18
+ type: (ObjectConstructor | StringConstructor | ArrayConstructor)[];
19
19
  };
20
20
  position: {
21
21
  default: string;
22
- type: PropType<"bottom-left" | "bottom-right">;
22
+ type: PropType<"custom" | "bottom-left" | "bottom-right">;
23
23
  };
24
24
  }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "items" | "menuClass" | "position">;
25
25
  $attrs: {
@@ -42,16 +42,16 @@ declare const _default: {
42
42
  };
43
43
  menuClass: {
44
44
  default: string;
45
- type: StringConstructor;
45
+ type: (ObjectConstructor | StringConstructor | ArrayConstructor)[];
46
46
  };
47
47
  position: {
48
48
  default: string;
49
- type: PropType<"bottom-left" | "bottom-right">;
49
+ type: PropType<"custom" | "bottom-left" | "bottom-right">;
50
50
  };
51
51
  }>>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
52
52
  items: MenuItemInterface[];
53
- menuClass: string;
54
- position: "bottom-left" | "bottom-right";
53
+ menuClass: string | Record<string, any> | unknown[];
54
+ position: "custom" | "bottom-left" | "bottom-right";
55
55
  }, {}, string> & {
56
56
  beforeCreate?: ((() => void) | (() => void)[]) | undefined;
57
57
  created?: ((() => void) | (() => void)[]) | undefined;
@@ -79,11 +79,11 @@ declare const _default: {
79
79
  };
80
80
  menuClass: {
81
81
  default: string;
82
- type: StringConstructor;
82
+ type: (ObjectConstructor | StringConstructor | ArrayConstructor)[];
83
83
  };
84
84
  position: {
85
85
  default: string;
86
- type: PropType<"bottom-left" | "bottom-right">;
86
+ type: PropType<"custom" | "bottom-left" | "bottom-right">;
87
87
  };
88
88
  }>> & import("vue").ShallowUnwrapRef<{}> & {} & import("vue").ComponentCustomProperties & {};
89
89
  __isFragment?: undefined;
@@ -96,22 +96,24 @@ declare const _default: {
96
96
  };
97
97
  menuClass: {
98
98
  default: string;
99
- type: StringConstructor;
99
+ type: (ObjectConstructor | StringConstructor | ArrayConstructor)[];
100
100
  };
101
101
  position: {
102
102
  default: string;
103
- type: PropType<"bottom-left" | "bottom-right">;
103
+ type: PropType<"custom" | "bottom-left" | "bottom-right">;
104
104
  };
105
105
  }>>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
106
106
  items: MenuItemInterface[];
107
- menuClass: string;
108
- position: "bottom-left" | "bottom-right";
107
+ menuClass: string | Record<string, any> | unknown[];
108
+ position: "custom" | "bottom-left" | "bottom-right";
109
109
  }, {}, string> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & (new () => {
110
110
  $slots: {
111
111
  button: (_: {
112
112
  open: any;
113
113
  }) => any;
114
- items: (_: {}) => any;
114
+ items: (_: {
115
+ items: MenuItemInterface[] | undefined;
116
+ }) => any;
115
117
  };
116
118
  });
117
119
  export default _default;
@@ -1,3 +1,4 @@
1
+ import BaseActionItem from './BaseActionItem.vue';
1
2
  import BaseAlert from './BaseAlert.vue';
2
3
  import BaseApp from './BaseApp.vue';
3
4
  import BaseAppDialogs from './BaseAppDialogs.vue';
@@ -63,4 +64,4 @@ import BaseLayoutStacked from './BaseLayoutStacked.vue';
63
64
  import BaseLayoutStackedConfigurable from './BaseLayoutStackedConfigurable.vue';
64
65
  import BaseLayoutSidebar from './BaseLayoutSidebar.vue';
65
66
  import BaseLayoutSidebarConfigurable from './BaseLayoutSidebarConfigurable.vue';
66
- export { BaseAlert, BaseApp, BaseAppDialogs, BaseAppNotifications, BaseAutocomplete, BaseAutocompleteFetch, BaseAvatar, BaseBadge, BaseBelongsTo, BaseBoolean, BaseBreadcrumbs, BaseButton, BaseCard, BaseCardRow, BaseCharacterCounter, BaseClipboard, BaseContainer, BaseCounter, BaseDataIterator, BaseDataTable, BaseDatePicker, BaseDateSelect, BaseDescriptionList, BaseDescriptionListItem, BaseDialog, BaseFilePicker, BaseFileUploader, BaseHasMany, BaseIcon, BaseInput, BaseInputLabel, BaseLoadingCover, BaseMediaItem, BaseMediaLibrary, BaseMediaPreview, BaseMenu, BaseMenuItem, BaseModalCenter, BaseModalSide, BaseNavbar, BaseNavbarItem, BaseNavbarItemContent, BasePagination, BasePanel, BasePassword, BaseProcessRing, BaseReadMore, BaseSelect, BaseSideNavigation, BaseSideNavigationItem, BaseSkeleton, BaseSwitch, BaseSystemAlert, BaseTabs, BaseTabItem, BaseTagAutocomplete, BaseTagAutocompleteFetch, BaseTable, BaseTableColumn, BaseTextarea, BaseTextareaAutoresize, BaseLayoutStacked, BaseLayoutStackedConfigurable, BaseLayoutSidebar, BaseLayoutSidebarConfigurable, };
67
+ export { BaseActionItem, BaseAlert, BaseApp, BaseAppDialogs, BaseAppNotifications, BaseAutocomplete, BaseAutocompleteFetch, BaseAvatar, BaseBadge, BaseBelongsTo, BaseBoolean, BaseBreadcrumbs, BaseButton, BaseCard, BaseCardRow, BaseCharacterCounter, BaseClipboard, BaseContainer, BaseCounter, BaseDataIterator, BaseDataTable, BaseDatePicker, BaseDateSelect, BaseDescriptionList, BaseDescriptionListItem, BaseDialog, BaseFilePicker, BaseFileUploader, BaseHasMany, BaseIcon, BaseInput, BaseInputLabel, BaseLoadingCover, BaseMediaItem, BaseMediaLibrary, BaseMediaPreview, BaseMenu, BaseMenuItem, BaseModalCenter, BaseModalSide, BaseNavbar, BaseNavbarItem, BaseNavbarItemContent, BasePagination, BasePanel, BasePassword, BaseProcessRing, BaseReadMore, BaseSelect, BaseSideNavigation, BaseSideNavigationItem, BaseSkeleton, BaseSwitch, BaseSystemAlert, BaseTabs, BaseTabItem, BaseTagAutocomplete, BaseTagAutocompleteFetch, BaseTable, BaseTableColumn, BaseTextarea, BaseTextareaAutoresize, BaseLayoutStacked, BaseLayoutStackedConfigurable, BaseLayoutSidebar, BaseLayoutSidebarConfigurable, };
@@ -32,6 +32,7 @@ declare const messages: {
32
32
  next_month: string;
33
33
  none: string;
34
34
  nothing_found: string;
35
+ notifications_empty: string;
35
36
  or: string;
36
37
  pagination_detail: string;
37
38
  previous: string;
@@ -40,6 +41,7 @@ declare const messages: {
40
41
  remove: string;
41
42
  remove_file: string;
42
43
  remove_file_description: string;
44
+ see_all_notifications: string;
43
45
  select_an_item: string;
44
46
  select_an_option: string;
45
47
  success: string;
@@ -56,6 +58,7 @@ declare const messages: {
56
58
  up_to_x: string;
57
59
  upload_failed: string;
58
60
  whoops: string;
61
+ x_ago: string;
59
62
  x_rows_selected: string;
60
63
  year: string;
61
64
  yes_delete: string;
@@ -90,6 +93,7 @@ declare const messages: {
90
93
  next_month: string;
91
94
  none: string;
92
95
  nothing_found: string;
96
+ notifications_empty: string;
93
97
  or: string;
94
98
  pagination_detail: string;
95
99
  previous: string;
@@ -98,6 +102,7 @@ declare const messages: {
98
102
  remove: string;
99
103
  remove_file: string;
100
104
  remove_file_description: string;
105
+ see_all_notifications: string;
101
106
  select_an_item: string;
102
107
  select_an_option: string;
103
108
  success: string;
@@ -114,6 +119,7 @@ declare const messages: {
114
119
  up_to_x: string;
115
120
  upload_failed: string;
116
121
  whoops: string;
122
+ x_ago: string;
117
123
  x_rows_selected: string;
118
124
  year: string;
119
125
  yes_delete: string;
@@ -159,6 +165,7 @@ declare const config: {
159
165
  next_month: string;
160
166
  none: string;
161
167
  nothing_found: string;
168
+ notifications_empty: string;
162
169
  or: string;
163
170
  pagination_detail: string;
164
171
  previous: string;
@@ -167,6 +174,7 @@ declare const config: {
167
174
  remove: string;
168
175
  remove_file: string;
169
176
  remove_file_description: string;
177
+ see_all_notifications: string;
170
178
  select_an_item: string;
171
179
  select_an_option: string;
172
180
  success: string;
@@ -183,6 +191,7 @@ declare const config: {
183
191
  up_to_x: string;
184
192
  upload_failed: string;
185
193
  whoops: string;
194
+ x_ago: string;
186
195
  x_rows_selected: string;
187
196
  year: string;
188
197
  yes_delete: string;
@@ -217,6 +226,7 @@ declare const config: {
217
226
  next_month: string;
218
227
  none: string;
219
228
  nothing_found: string;
229
+ notifications_empty: string;
220
230
  or: string;
221
231
  pagination_detail: string;
222
232
  previous: string;
@@ -225,6 +235,7 @@ declare const config: {
225
235
  remove: string;
226
236
  remove_file: string;
227
237
  remove_file_description: string;
238
+ see_all_notifications: string;
228
239
  select_an_item: string;
229
240
  select_an_option: string;
230
241
  success: string;
@@ -241,6 +252,7 @@ declare const config: {
241
252
  up_to_x: string;
242
253
  upload_failed: string;
243
254
  whoops: string;
255
+ x_ago: string;
244
256
  x_rows_selected: string;
245
257
  year: string;
246
258
  yes_delete: string;
@@ -0,0 +1,8 @@
1
+ import { RouteLocationRaw } from 'vue-router';
2
+ interface Notification {
3
+ id: string;
4
+ text: string;
5
+ to: RouteLocationRaw;
6
+ created_at?: string;
7
+ }
8
+ export { Notification };
@@ -1,5 +1,6 @@
1
1
  import { RouteLocationRaw } from 'vue-router';
2
2
  import { UploadedFile } from './UploadedFile';
3
+ import { Notification as AppNotification } from './Notification';
3
4
  export interface Breadcrumb {
4
5
  icon?: string;
5
6
  to: RouteLocationRaw;
@@ -144,3 +145,11 @@ export interface Notification {
144
145
  color: 'info' | 'success' | 'danger' | 'warning';
145
146
  duration: number;
146
147
  }
148
+ /**
149
+ * App Notification
150
+ */
151
+ export interface NotificationsConfig {
152
+ items: AppNotification[];
153
+ footerLabel?: string;
154
+ footerTo?: RouteLocationRaw;
155
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprintify-ui",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "scripts": {
5
5
  "build": "rimraf dist && vue-tsc && vite build",
6
6
  "build-fast": "rimraf dist && vite build",
@@ -17,15 +17,16 @@
17
17
  "@tailwindcss/typography": "^0.5.8",
18
18
  "@vueuse/core": "^9.0.0",
19
19
  "axios": "^0.26.1",
20
+ "humanize-duration": "^3.0.0",
20
21
  "lodash": "^4.17.21",
21
22
  "luxon": "^3.0.0",
23
+ "pikaday": "^1.8.2",
22
24
  "pinia": "^2.0.0",
23
25
  "qs": "^6.0.0",
24
26
  "tailwindcss": "^3.0.0",
25
27
  "vue": "^3.0.0",
26
28
  "vue-i18n": "^9.0.0",
27
- "vue-router": "^4.0.0",
28
- "pikaday": "^1.8.2"
29
+ "vue-router": "^4.0.0"
29
30
  },
30
31
  "dependencies": {
31
32
  "@headlessui/vue": "^1.7.4"
@@ -44,6 +45,7 @@
44
45
  "@tailwindcss/forms": "^0.5.3",
45
46
  "@tailwindcss/line-clamp": "^0.4.2",
46
47
  "@tailwindcss/typography": "^0.5.8",
48
+ "@types/humanize-duration": "^3.27.1",
47
49
  "@types/luxon": "^3.1.0",
48
50
  "@types/object-hash": "^2.2.1",
49
51
  "@types/pikaday": "^1.7.6",
@@ -63,6 +65,7 @@
63
65
  "eslint-plugin-storybook": "^0.6.7",
64
66
  "eslint-plugin-vue": "^9.7.0",
65
67
  "eslint-plugin-vue-scoped-css": "^2.2.0",
68
+ "humanize-duration": "^3.27.3",
66
69
  "lodash": "^4.17.21",
67
70
  "luxon": "^3.1.0",
68
71
  "object-hash": "^3.0.0",
@@ -0,0 +1,101 @@
1
+ <template>
2
+ <BaseMenu
3
+ class="inline-block"
4
+ :position="mobile ? 'custom' : 'bottom-left'"
5
+ :menu-class="['sm:w-[320px] w-[280px]', mobile ? 'right-4' : '']"
6
+ >
7
+ <template #button="{ open }">
8
+ <div
9
+ class="relative flex items-center rounded-full p-1.5"
10
+ :class="[open ? '' : '']"
11
+ >
12
+ <BaseIcon
13
+ icon="heroicons:bell"
14
+ class="h-6 w-6"
15
+ :class="[dark ? 'text-slate-300' : 'text-slate-600']"
16
+ ></BaseIcon>
17
+ <BaseCounter
18
+ v-if="notificationsConfig.items.length"
19
+ class="absolute top-0 right-0"
20
+ :count="notificationsConfig.items.length"
21
+ ></BaseCounter>
22
+ </div>
23
+ </template>
24
+
25
+ <template #items>
26
+ <template
27
+ v-for="notification in notificationsConfig.items"
28
+ :key="notification.id + 'link'"
29
+ >
30
+ <BaseLayoutNotificationItem
31
+ :notification="notification"
32
+ ></BaseLayoutNotificationItem>
33
+ </template>
34
+ <div
35
+ v-if="notificationsConfig.items.length == 0"
36
+ class="flex items-center justify-center p-6"
37
+ >
38
+ <div class="">
39
+ <BaseIcon
40
+ icon="heroicons:inbox-stack"
41
+ class="mx-auto mb-2 h-8 w-8 text-slate-400"
42
+ ></BaseIcon>
43
+ <p class="text-center text-sm text-slate-700">
44
+ {{ $t('sui.notifications_empty') }}
45
+ </p>
46
+ </div>
47
+ </div>
48
+
49
+ <div
50
+ v-if="notificationsConfig.footerTo"
51
+ class="mt-1 border-t border-slate-200 pt-1"
52
+ >
53
+ <RouterLink
54
+ v-slot="{ href, navigate }"
55
+ custom
56
+ :to="notificationsConfig.footerTo"
57
+ >
58
+ <MenuItem as="a" :href="href" @click="navigate">
59
+ <div
60
+ class="hover block px-3 py-2 text-center text-sm font-medium text-primary-600 hover:bg-slate-100"
61
+ >
62
+ {{
63
+ notificationsConfig.footerLabel
64
+ ? notificationsConfig.footerLabel
65
+ : $t('sui.see_all_notifications')
66
+ }}
67
+ </div>
68
+ </MenuItem>
69
+ </RouterLink>
70
+ </div>
71
+ </template>
72
+ </BaseMenu>
73
+ </template>
74
+
75
+ <script lang="ts" setup>
76
+ import { PropType } from 'vue';
77
+ import { BaseIcon } from '.';
78
+ import BaseCounter from './BaseCounter.vue';
79
+ import BaseLayoutNotificationItem from './BaseLayoutNotificationItem.vue';
80
+ import BaseMenu from './BaseMenu.vue';
81
+ import { useBreakpoints } from '@/composables/breakpoints';
82
+ import { NotificationsConfig } from '../types/types';
83
+ import { MenuItem } from '@headlessui/vue';
84
+
85
+ defineProps({
86
+ notificationsConfig: {
87
+ required: true,
88
+ type: Object as PropType<NotificationsConfig>,
89
+ },
90
+ dark: {
91
+ default: false,
92
+ type: Boolean,
93
+ },
94
+ });
95
+
96
+ const breakpoints = useBreakpoints();
97
+
98
+ const mobile = computed((): boolean => {
99
+ return breakpoints.smaller('sm').value;
100
+ });
101
+ </script>
@@ -0,0 +1,58 @@
1
+ <template>
2
+ <router-link v-slot="{ href, navigate }" custom :to="notification.to">
3
+ <MenuItem v-slot="{ active }" as="a" :href="href" @click="navigate">
4
+ <div class="px-3 py-2" :class="[active ? 'bg-slate-100' : '']">
5
+ <div
6
+ class="text-sm leading-tight text-slate-800"
7
+ v-html="notification.text"
8
+ ></div>
9
+ <p v-if="createdAt" class="mt-1 text-xs text-slate-400">
10
+ {{ createdAt }}
11
+ </p>
12
+ </div>
13
+ </MenuItem>
14
+ </router-link>
15
+ </template>
16
+
17
+ <script lang="ts" setup>
18
+ import { Notification } from '@/types/Notification';
19
+ import { MenuItem } from '@headlessui/vue';
20
+ import { DateTime } from 'luxon';
21
+ import { PropType } from 'vue';
22
+ import humanizeDuration from 'humanize-duration';
23
+
24
+ const i18n = useI18n();
25
+
26
+ const props = defineProps({
27
+ notification: {
28
+ required: true,
29
+ type: Object as PropType<Notification>,
30
+ },
31
+ });
32
+
33
+ const now = ref(DateTime.now());
34
+
35
+ const intervalId = setInterval(() => {
36
+ now.value.plus({ second: 1 });
37
+ }, 1000);
38
+
39
+ const createdAt = computed(() => {
40
+ if (props.notification.created_at) {
41
+ const duration = DateTime.fromISO(props.notification.created_at).diff(
42
+ now.value
43
+ ).milliseconds;
44
+
45
+ const durationHuman = humanizeDuration(duration, {
46
+ language: i18n.locale.value,
47
+ round: true,
48
+ largest: 1,
49
+ });
50
+
51
+ return i18n.t('sui.x_ago', { duration: durationHuman });
52
+ }
53
+ });
54
+
55
+ onBeforeUnmount(() => {
56
+ clearInterval(intervalId);
57
+ });
58
+ </script>
@@ -70,6 +70,24 @@ export default {
70
70
  icon: 'heroicons:arrow-left-on-rectangle',
71
71
  },
72
72
  ],
73
+ notifications: {
74
+ footerTo: '/',
75
+ footerLabel: 'See all notifications',
76
+ items: [
77
+ {
78
+ id: '1',
79
+ text: 'You have a new message',
80
+ to: '/',
81
+ created_at: '2022-01-01T00:00:00',
82
+ },
83
+ {
84
+ id: '2',
85
+ text: 'Your inbox is now full. Please empty your inbox before it goes bang.',
86
+ to: '/',
87
+ created_at: '2022-01-01T00:00:00',
88
+ },
89
+ ],
90
+ },
73
91
  },
74
92
  };
75
93