@apptegy/nuxt-navigation 0.1.111 → 1.0.0-alpha.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 (28) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +3 -2
  3. package/dist/runtime/components/Nav/Header.vue +108 -321
  4. package/dist/runtime/components/Nav/Header.vue.d.ts +12 -39
  5. package/dist/runtime/components/Nav/OrgSelect.vue +8 -8
  6. package/dist/runtime/components/Nav/Sidebar.vue +118 -207
  7. package/dist/runtime/components/Nav/Sidebar.vue.d.ts +7 -15
  8. package/dist/runtime/components/Nav/SidebarItem.vue +19 -22
  9. package/dist/runtime/components/Nav/SidebarSection.vue +28 -35
  10. package/dist/runtime/components/Nav/SidebarSection.vue.d.ts +2 -2
  11. package/dist/runtime/components/Nav/SubMenuItem.vue +1 -1
  12. package/dist/runtime/types/index.d.ts +0 -1
  13. package/locale/en.json +1 -22
  14. package/package.json +6 -9
  15. package/dist/runtime/components/Nav/NotificationItem.vue +0 -337
  16. package/dist/runtime/components/Nav/NotificationItem.vue.d.ts +0 -12
  17. package/dist/runtime/components/Nav/NotificationsPanel.vue +0 -513
  18. package/dist/runtime/components/Nav/NotificationsPanel.vue.d.ts +0 -53
  19. package/dist/runtime/constants/notification-types.d.ts +0 -19
  20. package/dist/runtime/constants/notification-types.js +0 -48
  21. package/dist/runtime/types/notifications.d.ts +0 -79
  22. package/dist/runtime/types/notifications.js +0 -0
  23. package/dist/runtime/utils/notification-api.d.ts +0 -26
  24. package/dist/runtime/utils/notification-api.js +0 -84
  25. package/dist/runtime/utils/notification-dates.d.ts +0 -15
  26. package/dist/runtime/utils/notification-dates.js +0 -81
  27. package/dist/runtime/utils/notifications.d.ts +0 -21
  28. package/dist/runtime/utils/notifications.js +0 -117
@@ -1,26 +0,0 @@
1
- import type { INotificationApiActor, INotificationApiRecord, INotificationGroup, INotificationItem, INotificationsApiResponse, INotificationsPanelData, INotificationTab, NotificationType } from '../types/index.js';
2
- import { type INotificationDateLabels } from './notification-dates.js';
3
- export declare const DEFAULT_NOTIFICATION_TABS: INotificationTab[];
4
- export declare function mapSourceRecordType(sourceRecordType: string): NotificationType;
5
- export declare function mapNotificationApiActor(actor: INotificationApiActor): {
6
- name: string;
7
- avatarUrl: string | undefined;
8
- };
9
- export declare function mapNotificationApiRecord(record: INotificationApiRecord, options: {
10
- locale?: string;
11
- dateLabels: INotificationDateLabels;
12
- now?: Date;
13
- }): INotificationItem;
14
- export declare function groupNotificationItems(items: INotificationItem[], options: {
15
- locale?: string;
16
- dateLabels: INotificationDateLabels;
17
- now?: Date;
18
- }): INotificationGroup[];
19
- export declare function mapNotificationsApiResponse(response: INotificationsApiResponse, options: {
20
- locale?: string;
21
- dateLabels: INotificationDateLabels;
22
- retentionLabel?: string;
23
- tabs?: INotificationTab[];
24
- now?: Date;
25
- }): INotificationsPanelData;
26
- export declare function getNotificationsTotalCount(response: INotificationsApiResponse | null | undefined): number;
@@ -1,84 +0,0 @@
1
- import {
2
- compareNotificationDateGroups,
3
- formatNotificationGroupLabel,
4
- formatNotificationTimeAgo,
5
- getNotificationDateGroupKey
6
- } from "./notification-dates.js";
7
- const SOURCE_RECORD_TYPE_MAP = {
8
- announcement: "announcement",
9
- message: "message",
10
- comment: "comment",
11
- mention: "mention",
12
- reply: "reply",
13
- reaction: "reaction",
14
- school_post: "school-post",
15
- "school-post": "school-post",
16
- system: "system"
17
- };
18
- export const DEFAULT_NOTIFICATION_TABS = [
19
- { id: "new", label: "New", unreadOnly: true },
20
- { id: "all", label: "All" }
21
- ];
22
- export function mapSourceRecordType(sourceRecordType) {
23
- const normalizedSourceRecordType = sourceRecordType.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
24
- return SOURCE_RECORD_TYPE_MAP[normalizedSourceRecordType] ?? "unknown";
25
- }
26
- export function mapNotificationApiActor(actor) {
27
- const name = [actor.first_name, actor.last_name].filter(Boolean).join(" ").trim();
28
- return {
29
- name: name || "Unknown",
30
- avatarUrl: actor.avatar_url
31
- };
32
- }
33
- export function mapNotificationApiRecord(record, options) {
34
- const state = record.notification_state;
35
- return {
36
- id: String(record.id),
37
- type: mapSourceRecordType(record.source_record_type),
38
- actors: (record.actors ?? []).map(mapNotificationApiActor),
39
- actionText: record.title,
40
- timestampLabel: formatNotificationTimeAgo(record.created_at, {
41
- locale: options.locale,
42
- now: options.now,
43
- labels: {
44
- justNow: options.dateLabels.justNow,
45
- yesterdayTimeAgo: options.dateLabels.yesterdayTimeAgo
46
- }
47
- }),
48
- createdAt: record.created_at,
49
- contextLabel: record.summary,
50
- dismissed: state === "dismissed",
51
- read: state === "read",
52
- unread: state === "unread",
53
- href: record.detail_link ?? void 0
54
- };
55
- }
56
- export function groupNotificationItems(items, options) {
57
- const groups = /* @__PURE__ */ new Map();
58
- for (const item of items) {
59
- const createdAt = item.createdAt;
60
- if (!createdAt) {
61
- continue;
62
- }
63
- const groupKey = getNotificationDateGroupKey(createdAt, options.now);
64
- const bucket = groups.get(groupKey) ?? [];
65
- bucket.push(item);
66
- groups.set(groupKey, bucket);
67
- }
68
- return [...groups.entries()].sort(([a], [b]) => compareNotificationDateGroups(a, b)).map(([groupKey, notifications]) => ({
69
- id: groupKey,
70
- label: formatNotificationGroupLabel(groupKey, options.dateLabels, options.locale),
71
- notifications
72
- }));
73
- }
74
- export function mapNotificationsApiResponse(response, options) {
75
- const items = response.data.map((record) => mapNotificationApiRecord(record, options));
76
- return {
77
- retentionLabel: options.retentionLabel,
78
- tabs: options.tabs ?? DEFAULT_NOTIFICATION_TABS,
79
- groups: groupNotificationItems(items, options)
80
- };
81
- }
82
- export function getNotificationsTotalCount(response) {
83
- return response?.pagination?.total_count ?? 0;
84
- }
@@ -1,15 +0,0 @@
1
- export interface INotificationDateLabels {
2
- today: string;
3
- yesterday: string;
4
- yesterdayTimeAgo: string;
5
- justNow: string;
6
- }
7
- /** Calendar bucket id used to group notifications (today, yesterday, or YYYY-MM-DD). */
8
- export declare function getNotificationDateGroupKey(createdAt: string, now?: Date): string;
9
- export declare function compareNotificationDateGroups(a: string, b: string): number;
10
- export declare function formatNotificationGroupLabel(groupKey: string, labels: INotificationDateLabels, locale?: string): string;
11
- export declare function formatNotificationTimeAgo(createdAt: string, options?: {
12
- locale?: string;
13
- now?: Date;
14
- labels?: Pick<INotificationDateLabels, 'justNow' | 'yesterdayTimeAgo'>;
15
- }): string;
@@ -1,81 +0,0 @@
1
- function startOfDay(date) {
2
- const value = new Date(date);
3
- value.setHours(0, 0, 0, 0);
4
- return value;
5
- }
6
- export function getNotificationDateGroupKey(createdAt, now = /* @__PURE__ */ new Date()) {
7
- const created = new Date(createdAt);
8
- const today = startOfDay(now);
9
- const yesterday = new Date(today);
10
- yesterday.setDate(yesterday.getDate() - 1);
11
- const createdDay = startOfDay(created);
12
- if (createdDay.getTime() === today.getTime()) {
13
- return "today";
14
- }
15
- if (createdDay.getTime() === yesterday.getTime()) {
16
- return "yesterday";
17
- }
18
- const year = createdDay.getFullYear();
19
- const month = String(createdDay.getMonth() + 1).padStart(2, "0");
20
- const day = String(createdDay.getDate()).padStart(2, "0");
21
- return `${year}-${month}-${day}`;
22
- }
23
- const GROUP_SORT_ORDER = {
24
- today: 0,
25
- yesterday: 1
26
- };
27
- export function compareNotificationDateGroups(a, b) {
28
- const orderA = GROUP_SORT_ORDER[a] ?? 2;
29
- const orderB = GROUP_SORT_ORDER[b] ?? 2;
30
- if (orderA !== orderB) {
31
- return orderA - orderB;
32
- }
33
- if (orderA === 2 && orderB === 2) {
34
- return b.localeCompare(a);
35
- }
36
- return 0;
37
- }
38
- export function formatNotificationGroupLabel(groupKey, labels, locale = "en") {
39
- if (groupKey === "today") {
40
- return labels.today;
41
- }
42
- if (groupKey === "yesterday") {
43
- return labels.yesterday;
44
- }
45
- const date = /* @__PURE__ */ new Date(`${groupKey}T12:00:00`);
46
- return date.toLocaleDateString(locale, { month: "long", day: "numeric" }).toUpperCase();
47
- }
48
- export function formatNotificationTimeAgo(createdAt, options = {}) {
49
- const now = options.now ?? /* @__PURE__ */ new Date();
50
- const created = new Date(createdAt);
51
- const locale = options.locale ?? "en";
52
- const labels = {
53
- justNow: options.labels?.justNow ?? "just now",
54
- yesterday: options.labels?.yesterdayTimeAgo ?? "Yesterday"
55
- };
56
- const diffMs = now.getTime() - created.getTime();
57
- const diffMinutes = Math.floor(diffMs / 6e4);
58
- const diffHours = Math.floor(diffMs / 36e5);
59
- const today = startOfDay(now);
60
- const createdDay = startOfDay(created);
61
- const yesterday = new Date(today);
62
- yesterday.setDate(yesterday.getDate() - 1);
63
- if (diffMinutes < 1) {
64
- return labels.justNow;
65
- }
66
- const relativeTime = new Intl.RelativeTimeFormat(locale, { numeric: "always" });
67
- if (createdDay.getTime() === today.getTime()) {
68
- if (diffMinutes < 60) {
69
- return relativeTime.format(-diffMinutes, "minute");
70
- }
71
- return relativeTime.format(-diffHours, "hour");
72
- }
73
- if (createdDay.getTime() === yesterday.getTime()) {
74
- return labels.yesterday;
75
- }
76
- const diffDays = Math.floor((today.getTime() - createdDay.getTime()) / 864e5);
77
- if (diffDays < 7) {
78
- return relativeTime.format(-diffDays, "day");
79
- }
80
- return created.toLocaleDateString(locale, { month: "short", day: "numeric" });
81
- }
@@ -1,21 +0,0 @@
1
- import type { INotificationFilter, INotificationGroup, INotificationItem, INotificationTab, NotificationType } from '../types/index.js';
2
- export declare function flattenNotifications(groups: INotificationGroup[]): INotificationItem[];
3
- /** In-badge notifications (New tab scope): unread only. */
4
- export declare function isInBadge(notification: INotificationItem): boolean;
5
- export declare function getInBadgeNotifications(notifications: INotificationItem[]): INotificationItem[];
6
- export declare function getInBadgeCount(notifications: INotificationItem[]): number;
7
- export declare function notificationMatchesFilter(notification: INotificationItem, filter: INotificationFilter): boolean;
8
- export declare function getTabBadgeCount(notifications: INotificationItem[], tab: INotificationTab): number;
9
- export declare function getFilterBadgeCount(notifications: INotificationItem[], filter: INotificationFilter): number;
10
- export declare function getScopedNotifications(notifications: INotificationItem[], tab: INotificationTab | undefined): INotificationItem[];
11
- /**
12
- * Builds filter pills from notification results.
13
- * Returns an empty array when fewer than 2 categories have content (per NC v2 spec).
14
- */
15
- export declare function buildFiltersFromNotifications(notifications: INotificationItem[], tab: INotificationTab | undefined): INotificationFilter[];
16
- export declare function resolveNotificationFilters(notifications: INotificationItem[], tab: INotificationTab | undefined, filters?: INotificationFilter[]): INotificationFilter[];
17
- export declare function filterHasContent(notifications: INotificationItem[], filter: INotificationFilter, tab: INotificationTab | undefined): boolean;
18
- export declare function getVisibleFilters(notifications: INotificationItem[], filters: INotificationFilter[], tab: INotificationTab | undefined): INotificationFilter[];
19
- export declare function shouldShowFilterChips(notifications: INotificationItem[], filters: INotificationFilter[], tab: INotificationTab | undefined, usesDynamicFilters?: boolean): boolean;
20
- export declare function formatNotificationCount(count: number): string;
21
- export declare function getTypeAccent(type: NotificationType): string;
@@ -1,117 +0,0 @@
1
- import { NOTIFICATION_FILTER_CATEGORIES } from "../constants/notification-types.js";
2
- export function flattenNotifications(groups) {
3
- return groups.flatMap((group) => group.notifications);
4
- }
5
- export function isInBadge(notification) {
6
- if (notification.dismissed === true) {
7
- return false;
8
- }
9
- if (notification.unread === true) {
10
- return true;
11
- }
12
- if (notification.read === true) {
13
- return false;
14
- }
15
- if (notification.dismissed !== void 0) {
16
- return !notification.dismissed;
17
- }
18
- return notification.unread === true;
19
- }
20
- export function getInBadgeNotifications(notifications) {
21
- return notifications.filter(isInBadge);
22
- }
23
- export function getInBadgeCount(notifications) {
24
- return getInBadgeNotifications(notifications).length;
25
- }
26
- export function notificationMatchesFilter(notification, filter) {
27
- if (!filter.types?.length) {
28
- return true;
29
- }
30
- return filter.types.includes(notification.type);
31
- }
32
- export function getTabBadgeCount(notifications, tab) {
33
- if (tab.unreadOnly || tab.id === "new") {
34
- return getInBadgeCount(notifications);
35
- }
36
- return 0;
37
- }
38
- export function getFilterBadgeCount(notifications, filter) {
39
- if (!filter.types?.length || filter.id === "all-types") {
40
- return 0;
41
- }
42
- return getInBadgeNotifications(notifications).filter(
43
- (notification) => notificationMatchesFilter(notification, filter)
44
- ).length;
45
- }
46
- export function getScopedNotifications(notifications, tab) {
47
- if (tab?.unreadOnly || tab?.id === "new") {
48
- return getInBadgeNotifications(notifications);
49
- }
50
- return notifications;
51
- }
52
- export function buildFiltersFromNotifications(notifications, tab) {
53
- const scoped = getScopedNotifications(notifications, tab);
54
- const typesPresent = new Set(scoped.map((notification) => notification.type));
55
- const categories = NOTIFICATION_FILTER_CATEGORIES.filter(
56
- (category) => category.types.some((type) => typesPresent.has(type))
57
- );
58
- if (categories.length < 2) {
59
- return [];
60
- }
61
- return [
62
- { id: "all-types", label: "All types" },
63
- ...categories
64
- ];
65
- }
66
- export function resolveNotificationFilters(notifications, tab, filters) {
67
- if (filters?.length) {
68
- return filters;
69
- }
70
- return buildFiltersFromNotifications(notifications, tab);
71
- }
72
- export function filterHasContent(notifications, filter, tab) {
73
- const scoped = getScopedNotifications(notifications, tab);
74
- return scoped.some((notification) => notificationMatchesFilter(notification, filter));
75
- }
76
- export function getVisibleFilters(notifications, filters, tab) {
77
- return filters.filter((filter) => {
78
- if (filter.id === "other") {
79
- return notifications.some((notification) => notification.type === "unknown");
80
- }
81
- return true;
82
- }).filter((filter) => {
83
- if (filter.id === "all-types") {
84
- return true;
85
- }
86
- return filterHasContent(notifications, filter, tab);
87
- });
88
- }
89
- export function shouldShowFilterChips(notifications, filters, tab, usesDynamicFilters = false) {
90
- if (usesDynamicFilters) {
91
- return filters.length > 0;
92
- }
93
- const categoriesWithContent = filters.filter(
94
- (filter) => filter.id !== "all-types" && filter.id !== "other" && filterHasContent(notifications, filter, tab)
95
- );
96
- return categoriesWithContent.length >= 2;
97
- }
98
- export function formatNotificationCount(count) {
99
- if (count > 99) {
100
- return "99+";
101
- }
102
- return String(count);
103
- }
104
- export function getTypeAccent(type) {
105
- const accents = {
106
- announcement: "#D67A11",
107
- message: "#1372B3",
108
- comment: "#139A4F",
109
- mention: "#5A2496",
110
- reply: "#1372B3",
111
- reaction: "#62626E",
112
- "school-post": "#1E3FBA",
113
- system: "#62626E",
114
- unknown: "#62626E"
115
- };
116
- return accents[type];
117
- }