@apptegy/nuxt-navigation 0.1.114 → 0.1.115
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/dist/module.json +1 -1
- package/dist/module.mjs +2 -2
- package/dist/runtime/components/Nav/Header.vue.d.ts +21 -1
- package/dist/runtime/components/Nav/NotificationItem.vue +1 -18
- package/dist/runtime/components/Nav/NotificationItem.vue.d.ts +2 -2
- package/dist/runtime/components/Nav/NotificationsPanel.vue.d.ts +9 -9
- package/dist/runtime/composables/useSidebar.d.ts +1 -1
- package/dist/runtime/constants/notification-types.d.ts +2 -2
- package/dist/runtime/constants/notification-types.js +8 -8
- package/dist/runtime/types/notifications.d.ts +20 -1
- package/dist/runtime/utils/notification-api.d.ts +3 -0
- package/dist/runtime/utils/notification-api.js +12 -1
- package/dist/runtime/utils/notifications.js +22 -6
- package/package.json +15 -16
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineNuxtModule, createResolver, addComponentsDir, addImportsDir } from '@nuxt/kit';
|
|
2
2
|
|
|
3
|
-
const module
|
|
3
|
+
const module = defineNuxtModule({
|
|
4
4
|
meta: {
|
|
5
5
|
name: "@apptegy/nuxt-navigation",
|
|
6
6
|
compatibility: {
|
|
@@ -22,4 +22,4 @@ const module$1 = defineNuxtModule({
|
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
export { module
|
|
25
|
+
export { module as default };
|
|
@@ -29,7 +29,27 @@ type __VLS_Slots = {} & {
|
|
|
29
29
|
} & {
|
|
30
30
|
notifications?: (props: typeof __VLS_15) => any;
|
|
31
31
|
};
|
|
32
|
-
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin,
|
|
32
|
+
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
33
|
+
"selected-option": (...args: any[]) => void;
|
|
34
|
+
"user-logout": (...args: any[]) => void;
|
|
35
|
+
"update:notificationPanelOpen": (...args: any[]) => void;
|
|
36
|
+
"update:activeTabId": (...args: any[]) => void;
|
|
37
|
+
"update:activeFilterId": (...args: any[]) => void;
|
|
38
|
+
"notifications-clear-all": (...args: any[]) => void;
|
|
39
|
+
"notifications-dismiss": (...args: any[]) => void;
|
|
40
|
+
"notifications-select": (...args: any[]) => void;
|
|
41
|
+
"notification-click": (...args: any[]) => void;
|
|
42
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
43
|
+
"onSelected-option"?: ((...args: any[]) => any) | undefined;
|
|
44
|
+
"onUser-logout"?: ((...args: any[]) => any) | undefined;
|
|
45
|
+
"onUpdate:notificationPanelOpen"?: ((...args: any[]) => any) | undefined;
|
|
46
|
+
"onUpdate:activeTabId"?: ((...args: any[]) => any) | undefined;
|
|
47
|
+
"onUpdate:activeFilterId"?: ((...args: any[]) => any) | undefined;
|
|
48
|
+
"onNotifications-clear-all"?: ((...args: any[]) => any) | undefined;
|
|
49
|
+
"onNotifications-dismiss"?: ((...args: any[]) => any) | undefined;
|
|
50
|
+
"onNotifications-select"?: ((...args: any[]) => any) | undefined;
|
|
51
|
+
"onNotification-click"?: ((...args: any[]) => any) | undefined;
|
|
52
|
+
}>, {
|
|
33
53
|
showNotifications: boolean;
|
|
34
54
|
notificationsResponse: INotificationsApiResponse | null;
|
|
35
55
|
notificationsLoading: boolean;
|
|
@@ -38,10 +38,6 @@
|
|
|
38
38
|
|
|
39
39
|
<div class="notification-item__content">
|
|
40
40
|
<p class="notification-item__message">
|
|
41
|
-
<strong>{{ primaryActor.name }}</strong>
|
|
42
|
-
<template v-if="additionalActorsLabel">
|
|
43
|
-
{{ additionalActorsLabel }}
|
|
44
|
-
</template>
|
|
45
41
|
{{ item.actionText }}
|
|
46
42
|
</p>
|
|
47
43
|
<p class="notification-item__meta">
|
|
@@ -106,16 +102,6 @@ const groupBadgeLabel = computed(() => {
|
|
|
106
102
|
const count = props.item.groupCount ?? Math.max(props.item.actors.length - 1, 0);
|
|
107
103
|
return count > 0 ? `+${count}` : "";
|
|
108
104
|
});
|
|
109
|
-
const additionalActorsLabel = computed(() => {
|
|
110
|
-
if (props.item.groupCount && props.item.groupCount > 0) {
|
|
111
|
-
return ` and ${props.item.groupCount} others`;
|
|
112
|
-
}
|
|
113
|
-
if (props.item.actors.length <= 1) {
|
|
114
|
-
return "";
|
|
115
|
-
}
|
|
116
|
-
const names = props.item.actors.slice(1).map((actor) => actor.name);
|
|
117
|
-
return `, ${names.join(", ")}`;
|
|
118
|
-
});
|
|
119
105
|
function svgIcon(paths) {
|
|
120
106
|
return h(
|
|
121
107
|
"svg",
|
|
@@ -220,7 +206,7 @@ function handleDismiss(event) {
|
|
|
220
206
|
text-align: left;
|
|
221
207
|
color: inherit;
|
|
222
208
|
}
|
|
223
|
-
.notification-item__main:hover .notification-item__message
|
|
209
|
+
.notification-item__main:hover .notification-item__message {
|
|
224
210
|
color: var(--purple-60, #662e80);
|
|
225
211
|
}
|
|
226
212
|
.notification-item__main:focus-visible {
|
|
@@ -297,9 +283,6 @@ function handleDismiss(event) {
|
|
|
297
283
|
line-height: 20px;
|
|
298
284
|
color: var(--grey-90, #111827);
|
|
299
285
|
}
|
|
300
|
-
.notification-item__message strong {
|
|
301
|
-
font-weight: 600;
|
|
302
|
-
}
|
|
303
286
|
.notification-item__meta {
|
|
304
287
|
display: flex;
|
|
305
288
|
flex-wrap: wrap;
|
|
@@ -3,10 +3,10 @@ type __VLS_Props = {
|
|
|
3
3
|
item: INotificationItem;
|
|
4
4
|
};
|
|
5
5
|
declare const _default: import("vue").DefineComponent<__VLS_Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
-
dismiss: (id: string) => any;
|
|
7
6
|
select: (item: INotificationItem) => any;
|
|
7
|
+
dismiss: (id: string) => any;
|
|
8
8
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
9
|
-
onDismiss?: ((id: string) => any) | undefined;
|
|
10
9
|
onSelect?: ((item: INotificationItem) => any) | undefined;
|
|
10
|
+
onDismiss?: ((id: string) => any) | undefined;
|
|
11
11
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
12
|
export default _default;
|
|
@@ -8,6 +8,11 @@ type __VLS_Props = {
|
|
|
8
8
|
mobile?: boolean;
|
|
9
9
|
};
|
|
10
10
|
declare const _default: import("vue").DefineComponent<__VLS_Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
|
+
select: (payload: {
|
|
12
|
+
item: INotificationsPanelData["groups"][number]["notifications"][number];
|
|
13
|
+
tabId: string;
|
|
14
|
+
filterId: string;
|
|
15
|
+
}) => any;
|
|
11
16
|
"update:activeTabId": (id: string) => any;
|
|
12
17
|
"update:activeFilterId": (id: string) => any;
|
|
13
18
|
"clear-all": (payload: {
|
|
@@ -20,13 +25,13 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, void, {}, {},
|
|
|
20
25
|
tabId: string;
|
|
21
26
|
filterId: string;
|
|
22
27
|
}) => any;
|
|
23
|
-
|
|
28
|
+
close: () => any;
|
|
29
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
30
|
+
onSelect?: ((payload: {
|
|
24
31
|
item: INotificationsPanelData["groups"][number]["notifications"][number];
|
|
25
32
|
tabId: string;
|
|
26
33
|
filterId: string;
|
|
27
|
-
}) => any;
|
|
28
|
-
close: () => any;
|
|
29
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
34
|
+
}) => any) | undefined;
|
|
30
35
|
"onUpdate:activeTabId"?: ((id: string) => any) | undefined;
|
|
31
36
|
"onUpdate:activeFilterId"?: ((id: string) => any) | undefined;
|
|
32
37
|
"onClear-all"?: ((payload: {
|
|
@@ -39,11 +44,6 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, void, {}, {},
|
|
|
39
44
|
tabId: string;
|
|
40
45
|
filterId: string;
|
|
41
46
|
}) => any) | undefined;
|
|
42
|
-
onSelect?: ((payload: {
|
|
43
|
-
item: INotificationsPanelData["groups"][number]["notifications"][number];
|
|
44
|
-
tabId: string;
|
|
45
|
-
filterId: string;
|
|
46
|
-
}) => any) | undefined;
|
|
47
47
|
onClose?: (() => any) | undefined;
|
|
48
48
|
}>, {
|
|
49
49
|
loading: boolean;
|
|
@@ -6,13 +6,13 @@ export declare const NOTIFICATION_BADGE_COLOR = "#C84B31";
|
|
|
6
6
|
export declare const NOTIFICATION_FILTER_CATEGORIES: Array<{
|
|
7
7
|
id: string;
|
|
8
8
|
label: string;
|
|
9
|
-
|
|
9
|
+
kinds: string[];
|
|
10
10
|
}>;
|
|
11
11
|
/** @deprecated Use NOTIFICATION_FILTER_CATEGORIES */
|
|
12
12
|
export declare const DEFAULT_NOTIFICATION_FILTERS: ({
|
|
13
13
|
id: string;
|
|
14
14
|
label: string;
|
|
15
|
-
|
|
15
|
+
kinds: string[];
|
|
16
16
|
} | {
|
|
17
17
|
id: string;
|
|
18
18
|
label: string;
|
|
@@ -14,32 +14,32 @@ export const NOTIFICATION_FILTER_CATEGORIES = [
|
|
|
14
14
|
{
|
|
15
15
|
id: "announcements",
|
|
16
16
|
label: "Announcements",
|
|
17
|
-
|
|
17
|
+
kinds: ["announcement"]
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
id: "messages",
|
|
21
21
|
label: "Messages",
|
|
22
|
-
|
|
22
|
+
kinds: ["message"]
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
|
-
id: "comments-
|
|
26
|
-
label: "Comments &
|
|
27
|
-
|
|
25
|
+
id: "comments-reactions",
|
|
26
|
+
label: "Comments & Reactions",
|
|
27
|
+
kinds: ["comment", "reaction"]
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
id: "school-posts",
|
|
31
31
|
label: "School Posts",
|
|
32
|
-
|
|
32
|
+
kinds: ["school_post"]
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
id: "system",
|
|
36
36
|
label: "System",
|
|
37
|
-
|
|
37
|
+
kinds: ["system"]
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
id: "other",
|
|
41
41
|
label: "Other",
|
|
42
|
-
|
|
42
|
+
kinds: ["unknown"]
|
|
43
43
|
}
|
|
44
44
|
];
|
|
45
45
|
export const DEFAULT_NOTIFICATION_FILTERS = [
|
|
@@ -7,6 +7,11 @@ export interface INotificationApiActor {
|
|
|
7
7
|
}
|
|
8
8
|
export interface INotificationApiRecord {
|
|
9
9
|
id: number | string;
|
|
10
|
+
/**
|
|
11
|
+
* Category used for filter pills / `filter[kind][]` (e.g. announcement, comment, reaction).
|
|
12
|
+
* Distinct from `source_record_type`, which describes the underlying record.
|
|
13
|
+
*/
|
|
14
|
+
kind?: string | null;
|
|
10
15
|
source_record_type: string;
|
|
11
16
|
title: string;
|
|
12
17
|
summary?: string;
|
|
@@ -33,7 +38,13 @@ export interface INotificationActor {
|
|
|
33
38
|
}
|
|
34
39
|
export interface INotificationItem {
|
|
35
40
|
id: string;
|
|
41
|
+
/** Visual/icon type — derived from `source_record_type`. */
|
|
36
42
|
type: NotificationType;
|
|
43
|
+
/**
|
|
44
|
+
* Filter category — derived from API `kind` (falls back to `type` when kind is absent).
|
|
45
|
+
* Used by filter pills and `filter[kind][]`.
|
|
46
|
+
*/
|
|
47
|
+
kind: string;
|
|
37
48
|
actors: INotificationActor[];
|
|
38
49
|
actionText: string;
|
|
39
50
|
timestampLabel: string;
|
|
@@ -67,7 +78,15 @@ export interface INotificationFilter {
|
|
|
67
78
|
id: string;
|
|
68
79
|
label: string;
|
|
69
80
|
count?: number;
|
|
70
|
-
/**
|
|
81
|
+
/**
|
|
82
|
+
* Notification kinds included in this filter (`filter[kind][]`).
|
|
83
|
+
* Omit or leave empty to include all kinds.
|
|
84
|
+
*/
|
|
85
|
+
kinds?: string[];
|
|
86
|
+
/**
|
|
87
|
+
* @deprecated Prefer `kinds`. Kept for callers that still filter by
|
|
88
|
+
* `source_record_type`-derived `type`.
|
|
89
|
+
*/
|
|
71
90
|
types?: NotificationType[];
|
|
72
91
|
}
|
|
73
92
|
export interface INotificationsPanelData {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { INotificationApiActor, INotificationApiRecord, INotificationGroup, INotificationItem, INotificationsApiResponse, INotificationsPanelData, INotificationTab, NotificationType } from '../types/index.js';
|
|
2
2
|
import { type INotificationDateLabels } from './notification-dates.js';
|
|
3
3
|
export declare const DEFAULT_NOTIFICATION_TABS: INotificationTab[];
|
|
4
|
+
/** Normalize kind values for filter matching and `filter[kind][]` query params. */
|
|
5
|
+
export declare function normalizeNotificationKind(value: string): string;
|
|
4
6
|
export declare function mapSourceRecordType(sourceRecordType: string): NotificationType;
|
|
7
|
+
export declare function mapNotificationKind(kind: string | null | undefined, fallbackType: NotificationType): string;
|
|
5
8
|
export declare function mapNotificationApiActor(actor: INotificationApiActor): {
|
|
6
9
|
name: string;
|
|
7
10
|
avatarUrl: string | undefined;
|
|
@@ -19,10 +19,19 @@ export const DEFAULT_NOTIFICATION_TABS = [
|
|
|
19
19
|
{ id: "new", label: "New", unreadOnly: true },
|
|
20
20
|
{ id: "all", label: "All" }
|
|
21
21
|
];
|
|
22
|
+
export function normalizeNotificationKind(value) {
|
|
23
|
+
return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().replace(/-/g, "_");
|
|
24
|
+
}
|
|
22
25
|
export function mapSourceRecordType(sourceRecordType) {
|
|
23
26
|
const normalizedSourceRecordType = sourceRecordType.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
24
27
|
return SOURCE_RECORD_TYPE_MAP[normalizedSourceRecordType] ?? "unknown";
|
|
25
28
|
}
|
|
29
|
+
export function mapNotificationKind(kind, fallbackType) {
|
|
30
|
+
if (!kind) {
|
|
31
|
+
return normalizeNotificationKind(fallbackType);
|
|
32
|
+
}
|
|
33
|
+
return normalizeNotificationKind(kind) || normalizeNotificationKind(fallbackType);
|
|
34
|
+
}
|
|
26
35
|
export function mapNotificationApiActor(actor) {
|
|
27
36
|
const name = [actor.first_name, actor.last_name].filter(Boolean).join(" ").trim();
|
|
28
37
|
return {
|
|
@@ -32,9 +41,11 @@ export function mapNotificationApiActor(actor) {
|
|
|
32
41
|
}
|
|
33
42
|
export function mapNotificationApiRecord(record, options) {
|
|
34
43
|
const state = record.notification_state;
|
|
44
|
+
const type = mapSourceRecordType(record.source_record_type);
|
|
35
45
|
return {
|
|
36
46
|
id: String(record.id),
|
|
37
|
-
type
|
|
47
|
+
type,
|
|
48
|
+
kind: mapNotificationKind(record.kind, type),
|
|
38
49
|
actors: (record.actors ?? []).map(mapNotificationApiActor),
|
|
39
50
|
actionText: record.title,
|
|
40
51
|
timestampLabel: formatNotificationTimeAgo(record.created_at, {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NOTIFICATION_FILTER_CATEGORIES } from "../constants/notification-types.js";
|
|
2
|
+
import { normalizeNotificationKind } from "./notification-api.js";
|
|
2
3
|
export function flattenNotifications(groups) {
|
|
3
4
|
return groups.flatMap((group) => group.notifications);
|
|
4
5
|
}
|
|
@@ -23,11 +24,19 @@ export function getInBadgeNotifications(notifications) {
|
|
|
23
24
|
export function getInBadgeCount(notifications) {
|
|
24
25
|
return getInBadgeNotifications(notifications).length;
|
|
25
26
|
}
|
|
27
|
+
function filterKinds(filter) {
|
|
28
|
+
if (filter.kinds?.length) {
|
|
29
|
+
return filter.kinds.map(normalizeNotificationKind);
|
|
30
|
+
}
|
|
31
|
+
return (filter.types ?? []).map((type) => normalizeNotificationKind(type));
|
|
32
|
+
}
|
|
26
33
|
export function notificationMatchesFilter(notification, filter) {
|
|
27
|
-
|
|
34
|
+
const kinds = filterKinds(filter);
|
|
35
|
+
if (!kinds.length) {
|
|
28
36
|
return true;
|
|
29
37
|
}
|
|
30
|
-
|
|
38
|
+
const notificationKind = normalizeNotificationKind(notification.kind || notification.type);
|
|
39
|
+
return kinds.includes(notificationKind);
|
|
31
40
|
}
|
|
32
41
|
export function getTabBadgeCount(notifications, tab) {
|
|
33
42
|
if (tab.unreadOnly || tab.id === "new") {
|
|
@@ -36,7 +45,7 @@ export function getTabBadgeCount(notifications, tab) {
|
|
|
36
45
|
return 0;
|
|
37
46
|
}
|
|
38
47
|
export function getFilterBadgeCount(notifications, filter) {
|
|
39
|
-
if (
|
|
48
|
+
if (filter.id === "all-types" || !filterKinds(filter).length) {
|
|
40
49
|
return 0;
|
|
41
50
|
}
|
|
42
51
|
return getInBadgeNotifications(notifications).filter(
|
|
@@ -51,9 +60,13 @@ export function getScopedNotifications(notifications, tab) {
|
|
|
51
60
|
}
|
|
52
61
|
export function buildFiltersFromNotifications(notifications, tab) {
|
|
53
62
|
const scoped = getScopedNotifications(notifications, tab);
|
|
54
|
-
const
|
|
63
|
+
const kindsPresent = new Set(
|
|
64
|
+
scoped.map(
|
|
65
|
+
(notification) => normalizeNotificationKind(notification.kind || notification.type)
|
|
66
|
+
)
|
|
67
|
+
);
|
|
55
68
|
const categories = NOTIFICATION_FILTER_CATEGORIES.filter(
|
|
56
|
-
(category) => category.
|
|
69
|
+
(category) => category.kinds.some((kind) => kindsPresent.has(normalizeNotificationKind(kind)))
|
|
57
70
|
);
|
|
58
71
|
if (categories.length < 2) {
|
|
59
72
|
return [];
|
|
@@ -76,7 +89,10 @@ export function filterHasContent(notifications, filter, tab) {
|
|
|
76
89
|
export function getVisibleFilters(notifications, filters, tab) {
|
|
77
90
|
return filters.filter((filter) => {
|
|
78
91
|
if (filter.id === "other") {
|
|
79
|
-
return notifications.some((notification) =>
|
|
92
|
+
return notifications.some((notification) => {
|
|
93
|
+
const kind = normalizeNotificationKind(notification.kind || notification.type);
|
|
94
|
+
return kind === "unknown" || notification.type === "unknown";
|
|
95
|
+
});
|
|
80
96
|
}
|
|
81
97
|
return true;
|
|
82
98
|
}).filter((filter) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apptegy/nuxt-navigation",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.115",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -36,20 +36,19 @@
|
|
|
36
36
|
"primevue": "^4.2.5"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@nuxt/devtools": "
|
|
40
|
-
"@nuxt/eslint-config": "
|
|
41
|
-
"@nuxt/module-builder": "
|
|
42
|
-
"@nuxt/schema": "
|
|
43
|
-
"@nuxt/test-utils": "
|
|
44
|
-
"@types/node": "
|
|
45
|
-
"eslint": "
|
|
46
|
-
"nuxt": "
|
|
39
|
+
"@nuxt/devtools": "catalog:",
|
|
40
|
+
"@nuxt/eslint-config": "catalog:",
|
|
41
|
+
"@nuxt/module-builder": "catalog:",
|
|
42
|
+
"@nuxt/schema": "catalog:",
|
|
43
|
+
"@nuxt/test-utils": "catalog:",
|
|
44
|
+
"@types/node": "catalog:",
|
|
45
|
+
"eslint": "catalog:",
|
|
46
|
+
"nuxt": "catalog:",
|
|
47
47
|
"primevue": "^4.5.4",
|
|
48
|
-
"sass": "
|
|
49
|
-
"typescript": "
|
|
50
|
-
"vitest": "
|
|
51
|
-
"vue": "
|
|
52
|
-
"vue-tsc": "
|
|
53
|
-
}
|
|
54
|
-
"gitHead": "d57420f3128d73ad4ee181b2c437040434c0023c"
|
|
48
|
+
"sass": "catalog:",
|
|
49
|
+
"typescript": "catalog:",
|
|
50
|
+
"vitest": "catalog:",
|
|
51
|
+
"vue": "catalog:",
|
|
52
|
+
"vue-tsc": "catalog:"
|
|
53
|
+
}
|
|
55
54
|
}
|