@devalok/shilp-sutra 0.57.0 → 0.59.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.
- package/MIGRATION.md +91 -0
- package/dist/_chunks/badge-group.js +75 -188
- package/dist/_chunks/badge-group.js.map +1 -1
- package/dist/_chunks/chat.js +244 -243
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/image-preview.js +71 -70
- package/dist/_chunks/image-preview.js.map +1 -1
- package/dist/_chunks/motion-preference.js +15 -0
- package/dist/_chunks/motion-preference.js.map +1 -0
- package/dist/_chunks/motion-provider.js +1 -1
- package/dist/_chunks/motion-provider.js.map +1 -1
- package/dist/_chunks/popover.js +50 -49
- package/dist/_chunks/popover.js.map +1 -1
- package/dist/_chunks/primitives-internal.js +29 -29
- package/dist/_chunks/primitives-internal.js.map +1 -1
- package/dist/_chunks/shared.js +48 -47
- package/dist/_chunks/shared.js.map +1 -1
- package/dist/_chunks/success.js +34 -34
- package/dist/_chunks/tree-view.js +1 -1
- package/dist/_chunks/tree-view.js.map +1 -1
- package/dist/ai/block-renderer.js +8 -8
- package/dist/ai/command-bar.js +65 -65
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/ai/conversation.js +35 -35
- package/dist/ai/conversation.js.map +1 -1
- package/dist/ai/index.js +4 -4
- package/dist/composed/activity-feed.d.ts.map +1 -1
- package/dist/composed/activity-feed.js +108 -107
- package/dist/composed/activity-feed.js.map +1 -1
- package/dist/composed/command-palette.js +137 -137
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/content-card.js +1 -1
- package/dist/composed/content-card.js.map +1 -1
- package/dist/composed/date-picker/index.js +5 -5
- package/dist/composed/date-picker/index.js.map +1 -1
- package/dist/composed/empty-state.js +4 -4
- package/dist/composed/file-preview/image-preview.d.ts.map +1 -1
- package/dist/composed/file-preview/shared.d.ts.map +1 -1
- package/dist/composed/file-preview/video-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.js +151 -150
- package/dist/composed/file-preview.js.map +1 -1
- package/dist/composed/filter-bar.d.ts.map +1 -1
- package/dist/composed/filter-bar.js +53 -52
- package/dist/composed/filter-bar.js.map +1 -1
- package/dist/composed/form-section.d.ts.map +1 -1
- package/dist/composed/form-section.js +38 -37
- package/dist/composed/form-section.js.map +1 -1
- package/dist/composed/master-detail.d.ts.map +1 -1
- package/dist/composed/master-detail.js +1 -1
- package/dist/composed/master-detail.js.map +1 -1
- package/dist/composed/multi-select-popover.d.ts.map +1 -1
- package/dist/composed/multi-select-popover.js +109 -108
- package/dist/composed/multi-select-popover.js.map +1 -1
- package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/reply-banner.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.js +467 -466
- package/dist/composed/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.js +3 -3
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/composed/schedule-view.js +2 -2
- package/dist/composed/schedule-view.js.map +1 -1
- package/dist/composed/status-badge.d.ts.map +1 -1
- package/dist/composed/status-badge.js +29 -28
- package/dist/composed/status-badge.js.map +1 -1
- package/dist/motion/index.d.ts +1 -0
- package/dist/motion/index.d.ts.map +1 -1
- package/dist/motion/index.js +2 -15
- package/dist/motion/motion-preference.d.ts +36 -0
- package/dist/motion/motion-preference.d.ts.map +1 -0
- package/dist/motion/motion-provider.d.ts +2 -1
- package/dist/motion/motion-provider.d.ts.map +1 -1
- package/dist/motion/primitives-index.js +103 -102
- package/dist/motion/primitives-index.js.map +1 -1
- package/dist/motion/primitives.d.ts.map +1 -1
- package/dist/shell/bottom-navbar.js +19 -19
- package/dist/shell/bottom-navbar.js.map +1 -1
- package/dist/shell/index.d.ts +1 -1
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/notification-center.d.ts +17 -0
- package/dist/shell/notification-center.d.ts.map +1 -1
- package/dist/shell/notification-center.js +109 -104
- package/dist/shell/notification-center.js.map +1 -1
- package/dist/shell/notification-preferences.js +1 -1
- package/dist/shell/notification-preferences.js.map +1 -1
- package/dist/shell/top-bar.js +1 -1
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/tokens/index.css +1 -0
- package/dist/tokens/palettes.css +292 -0
- package/dist/tokens/semantic.css +72 -8
- package/dist/tokens/shilp-sutra.css +1 -0
- package/dist/tokens/utilities.css +10 -7
- package/dist/ui/accordion.d.ts.map +1 -1
- package/dist/ui/accordion.js +27 -26
- package/dist/ui/accordion.js.map +1 -1
- package/dist/ui/alert-dialog.d.ts.map +1 -1
- package/dist/ui/alert-dialog.js +60 -59
- package/dist/ui/alert-dialog.js.map +1 -1
- package/dist/ui/alert.d.ts.map +1 -1
- package/dist/ui/alert.js +55 -113
- package/dist/ui/alert.js.map +1 -1
- package/dist/ui/autocomplete.js +80 -80
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/avatar.d.ts.map +1 -1
- package/dist/ui/avatar.js +69 -68
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/badge-indicator.d.ts +4 -8
- package/dist/ui/badge-indicator.d.ts.map +1 -1
- package/dist/ui/badge-indicator.js +3 -8
- package/dist/ui/badge-indicator.js.map +1 -1
- package/dist/ui/badge.d.ts +8 -1
- package/dist/ui/badge.d.ts.map +1 -1
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +42 -40
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/button-group.d.ts.map +1 -1
- package/dist/ui/button-group.js +3 -23
- package/dist/ui/button-group.js.map +1 -1
- package/dist/ui/button.d.ts +10 -1
- package/dist/ui/button.d.ts.map +1 -1
- package/dist/ui/button.js +79 -212
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.d.ts.map +1 -1
- package/dist/ui/card.js +75 -72
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/charts/radar-chart.d.ts.map +1 -1
- package/dist/ui/charts/radar-chart.js +1 -1
- package/dist/ui/charts/radar-chart.js.map +1 -1
- package/dist/ui/chat/message-list.d.ts.map +1 -1
- package/dist/ui/chat/message.d.ts.map +1 -1
- package/dist/ui/chat/typing-indicator.d.ts.map +1 -1
- package/dist/ui/code.js +1 -1
- package/dist/ui/code.js.map +1 -1
- package/dist/ui/color-input.d.ts.map +1 -1
- package/dist/ui/color-input.js +151 -150
- package/dist/ui/color-input.js.map +1 -1
- package/dist/ui/combobox.d.ts +14 -0
- package/dist/ui/combobox.d.ts.map +1 -1
- package/dist/ui/combobox.js +152 -148
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/context-menu.d.ts.map +1 -1
- package/dist/ui/context-menu.js +70 -69
- package/dist/ui/context-menu.js.map +1 -1
- package/dist/ui/data-table-body.js +2 -2
- package/dist/ui/data-table-body.js.map +1 -1
- package/dist/ui/data-table-context.js +2 -2
- package/dist/ui/data-table-context.js.map +1 -1
- package/dist/ui/data-table-header.d.ts.map +1 -1
- package/dist/ui/data-table-header.js +41 -40
- package/dist/ui/data-table-header.js.map +1 -1
- package/dist/ui/data-table-pagination.js +2 -2
- package/dist/ui/data-table-pagination.js.map +1 -1
- package/dist/ui/dialog.d.ts.map +1 -1
- package/dist/ui/dialog.js +61 -60
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dot.d.ts.map +1 -1
- package/dist/ui/dot.js +10 -41
- package/dist/ui/dot.js.map +1 -1
- package/dist/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/ui/dropdown-menu.js +79 -78
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/file-upload.d.ts.map +1 -1
- package/dist/ui/file-upload.js +116 -115
- package/dist/ui/file-upload.js.map +1 -1
- package/dist/ui/form.d.ts.map +1 -1
- package/dist/ui/form.js +27 -26
- package/dist/ui/form.js.map +1 -1
- package/dist/ui/hover-card.d.ts.map +1 -1
- package/dist/ui/hover-card.js +26 -25
- package/dist/ui/hover-card.js.map +1 -1
- package/dist/ui/icon.js +7 -7
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +3 -3
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/input.js +1 -1
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/menubar.d.ts.map +1 -1
- package/dist/ui/menubar.js +73 -72
- package/dist/ui/menubar.js.map +1 -1
- package/dist/ui/navigation-menu.d.ts.map +1 -1
- package/dist/ui/navigation-menu.js +80 -79
- package/dist/ui/navigation-menu.js.map +1 -1
- package/dist/ui/popover.d.ts.map +1 -1
- package/dist/ui/progress.d.ts.map +1 -1
- package/dist/ui/progress.js +72 -68
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/radio.d.ts.map +1 -1
- package/dist/ui/radio.js +32 -31
- package/dist/ui/radio.js.map +1 -1
- package/dist/ui/search-input.d.ts.map +1 -1
- package/dist/ui/search-input.js +28 -27
- package/dist/ui/search-input.js.map +1 -1
- package/dist/ui/select.d.ts.map +1 -1
- package/dist/ui/select.js +64 -63
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/sidebar.d.ts.map +1 -1
- package/dist/ui/sidebar.js +4 -4
- package/dist/ui/sidebar.js.map +1 -1
- package/dist/ui/slider.d.ts +63 -9
- package/dist/ui/slider.d.ts.map +1 -1
- package/dist/ui/slider.js +74 -32
- package/dist/ui/slider.js.map +1 -1
- package/dist/ui/split-button.d.ts +8 -2
- package/dist/ui/split-button.d.ts.map +1 -1
- package/dist/ui/split-button.js +49 -95
- package/dist/ui/split-button.js.map +1 -1
- package/dist/ui/stat-card.d.ts.map +1 -1
- package/dist/ui/stat-card.js +89 -88
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/stat-flash.js +16 -16
- package/dist/ui/stepper.d.ts.map +1 -1
- package/dist/ui/stepper.js +63 -62
- package/dist/ui/stepper.js.map +1 -1
- package/dist/ui/table.js +3 -3
- package/dist/ui/table.js.map +1 -1
- package/dist/ui/tabs.d.ts.map +1 -1
- package/dist/ui/tabs.js +67 -66
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/textarea.js +1 -1
- package/dist/ui/textarea.js.map +1 -1
- package/dist/ui/toast.d.ts.map +1 -1
- package/dist/ui/toast.js +195 -194
- package/dist/ui/toast.js.map +1 -1
- package/dist/ui/toggle.d.ts.map +1 -1
- package/dist/ui/toggle.js +24 -22
- package/dist/ui/toggle.js.map +1 -1
- package/dist/ui/tooltip.d.ts.map +1 -1
- package/dist/ui/tooltip.js +37 -36
- package/dist/ui/tooltip.js.map +1 -1
- package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
- package/docs/recipes/customize-brand.md +58 -0
- package/docs/recipes/install-astro.md +1 -1
- package/docs/recipes/install-next-app-router.md +1 -1
- package/docs/recipes/install-next-pages.md +22 -1
- package/docs/recipes/install-remix.md +1 -1
- package/docs/recipes/install-tanstack-start.md +1 -1
- package/docs/recipes/install-vite.md +2 -1
- package/docs/recipes/server-components.md +7 -4
- package/docs/recipes/troubleshoot.md +1 -0
- package/llms.txt +1 -1
- package/mcp-manifest.json +9 -4
- package/package.json +3 -2
- package/skill/SKILL.md +1 -1
- package/skill/references/components.md +1 -1
- package/skill/references/customize-brand.md +58 -0
- package/skill/references/server-components.md +7 -4
- package/skill/references/setup-astro.md +1 -1
- package/skill/references/setup-next-app-router.md +1 -1
- package/skill/references/setup-next-pages.md +22 -1
- package/skill/references/setup-remix.md +1 -1
- package/skill/references/setup-tanstack-start.md +1 -1
- package/skill/references/setup-vite.md +2 -1
- package/skill/references/troubleshoot.md +1 -0
- package/dist/motion/check-motion-provider.d.ts +0 -2
- package/dist/motion/check-motion-provider.d.ts.map +0 -1
- package/dist/motion/index.js.map +0 -1
package/dist/shell/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export { BottomNavbar, type BottomNavbarProps, type BottomNavbarUser, type Botto
|
|
|
16
16
|
export { type CommandPageItem, type CommandRegistry, CommandRegistryProvider, type CommandRegistryProviderProps, useCommandRegistry, } from './command-registry.js';
|
|
17
17
|
export { AppShell, AppShellBar, type AppShellBarProps, AppShellBody, AppShellCanvas, type AppShellProps, AppShellSidebar, type AppShellSidebarProps, } from './app-shell.js';
|
|
18
18
|
export { LinkProvider, type LinkProviderProps, useLink } from './link-context.js';
|
|
19
|
-
export { type Notification, NotificationCenter, type NotificationCenterProps, } from './notification-center.js';
|
|
19
|
+
export { type Notification, NotificationCenter, type NotificationCenterProps, type NotificationUnreadStyle, } from './notification-center.js';
|
|
20
20
|
export { type NotificationPreference, NotificationPreferences, type NotificationPreferencesProps, type NotificationProject, } from './notification-preferences.js';
|
|
21
21
|
export { TopBar, type TopBarProps, type TopBarUser, type UserMenuItem, } from './top-bar.js';
|
|
22
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shell/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,uBAAuB,EACvB,KAAK,4BAA4B,EACjC,kBAAkB,GACnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,KAAK,gBAAgB,EACrB,YAAY,EACZ,cAAc,EACd,KAAK,aAAa,EAClB,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAC,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAC7E,OAAO,EACL,KAAK,YAAY,EACjB,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,KAAK,sBAAsB,EAC3B,uBAAuB,EACvB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACL,MAAM,EACN,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shell/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,uBAAuB,EACvB,KAAK,4BAA4B,EACjC,kBAAkB,GACnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,KAAK,gBAAgB,EACrB,YAAY,EACZ,cAAc,EACd,KAAK,aAAa,EAClB,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAC,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAC7E,OAAO,EACL,KAAK,YAAY,EACjB,kBAAkB,EAClB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,KAAK,sBAAsB,EAC3B,uBAAuB,EACvB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACL,MAAM,EACN,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,WAAW,CAAA"}
|
|
@@ -23,6 +23,8 @@ export interface Notification {
|
|
|
23
23
|
/** Inline action buttons (e.g. Approve / Deny). Max 2–3 recommended. */
|
|
24
24
|
actions?: NotificationAction[];
|
|
25
25
|
}
|
|
26
|
+
/** Visual weight of an unread row. See `NotificationCenterProps.unreadStyle`. */
|
|
27
|
+
export type NotificationUnreadStyle = 'tint' | 'strong' | 'none';
|
|
26
28
|
export interface NotificationCenterProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
27
29
|
/** List of notifications to display */
|
|
28
30
|
notifications?: Notification[];
|
|
@@ -54,6 +56,21 @@ export interface NotificationCenterProps extends React.ButtonHTMLAttributes<HTML
|
|
|
54
56
|
footerSlot?: React.ReactNode;
|
|
55
57
|
/** Called when the user dismisses a notification. Renders an X button per row when provided. */
|
|
56
58
|
onDismiss?: (id: string) => void;
|
|
59
|
+
/**
|
|
60
|
+
* How an unread row announces itself.
|
|
61
|
+
*
|
|
62
|
+
* - `tint` (default) — an accent wash plus a bold title. The conventional
|
|
63
|
+
* look, and the quietest fill that still reads louder than a hovered
|
|
64
|
+
* already-read row in both themes.
|
|
65
|
+
* - `strong` — a heavier wash, for inboxes where unread has to carry across
|
|
66
|
+
* a long list at a glance.
|
|
67
|
+
* - `none` — no wash at all. The tier dot (which already fades to 20% once
|
|
68
|
+
* read) and the bold title carry the state on their own. The calmest
|
|
69
|
+
* option, and the one that scales best down a long list.
|
|
70
|
+
*
|
|
71
|
+
* @default 'tint'
|
|
72
|
+
*/
|
|
73
|
+
unreadStyle?: NotificationUnreadStyle;
|
|
57
74
|
/** Additional className for the popover content container */
|
|
58
75
|
popoverClassName?: string;
|
|
59
76
|
/** Additional className */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification-center.d.ts","sourceRoot":"","sources":["../../src/shell/notification-center.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAgC9B,MAAM,WAAW,kBAAkB;IACjC,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;IAC1C,8EAA8E;IAC9E,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;IACvC,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAClC,wEAAwE;IACxE,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAC/B;AAED,MAAM,WAAW,uBACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IACrD,uCAAuC;IACvC,aAAa,CAAC,EAAE,YAAY,EAAE,CAAA;IAC9B,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oDAAoD;IACpD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,iDAAiD;IACjD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,mDAAmD;IACnD,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,4EAA4E;IAC5E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,MAAM,GAAG,IAAI,CAAA;IACpE,wEAAwE;IACxE,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,+DAA+D;IAC/D,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,gGAAgG;IAChG,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;
|
|
1
|
+
{"version":3,"file":"notification-center.d.ts","sourceRoot":"","sources":["../../src/shell/notification-center.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAgC9B,MAAM,WAAW,kBAAkB;IACjC,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;IAC1C,8EAA8E;IAC9E,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;IACvC,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAClC,wEAAwE;IACxE,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAC/B;AAED,iFAAiF;AACjF,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEhE,MAAM,WAAW,uBACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IACrD,uCAAuC;IACvC,aAAa,CAAC,EAAE,YAAY,EAAE,CAAA;IAC9B,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oDAAoD;IACpD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,iDAAiD;IACjD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,mDAAmD;IACnD,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,4EAA4E;IAC5E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,MAAM,GAAG,IAAI,CAAA;IACpE,wEAAwE;IACxE,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,+DAA+D;IAC/D,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,gGAAgG;IAChG,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,uBAAuB,CAAA;IACrC,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA4LD,QAAA,MAAM,kBAAkB,mGAuPvB,CAAA;AAGD,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
|
|
@@ -8,12 +8,12 @@ import { Button as a } from "../ui/button.js";
|
|
|
8
8
|
import { Popover as o, PopoverContent as s, PopoverTrigger as c } from "../_chunks/popover.js";
|
|
9
9
|
import { Tooltip as l, TooltipContent as u, TooltipTrigger as d } from "../ui/tooltip.js";
|
|
10
10
|
import { TruncatedText as f } from "../ui/truncated-text.js";
|
|
11
|
-
import { Sheet as p, SheetContent as
|
|
12
|
-
import { formatRelativeTime as
|
|
13
|
-
import * as
|
|
14
|
-
import { useCallback as
|
|
15
|
-
import { Fragment as
|
|
16
|
-
import { IconBell as
|
|
11
|
+
import { Sheet as p, SheetContent as m, SheetTitle as h, SheetTrigger as g } from "../ui/sheet.js";
|
|
12
|
+
import { formatRelativeTime as _ } from "../ui/lib/date-utils.js";
|
|
13
|
+
import * as v from "react";
|
|
14
|
+
import { useCallback as y, useRef as b } from "react";
|
|
15
|
+
import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
|
|
16
|
+
import { IconBell as ee, IconChecks as w, IconInbox as T, IconX as E } from "@tabler/icons-react";
|
|
17
17
|
import { motion as D, useReducedMotion as O } from "framer-motion";
|
|
18
18
|
//#region src/shell/notification-center.tsx
|
|
19
19
|
function k(e, t) {
|
|
@@ -24,55 +24,59 @@ function A(e) {
|
|
|
24
24
|
return r.setDate(n.getDate() - 1), k(t, n) ? "Today" : k(t, r) ? "Yesterday" : "Earlier";
|
|
25
25
|
}
|
|
26
26
|
var j = {
|
|
27
|
+
tint: "bg-accent-4",
|
|
28
|
+
strong: "bg-accent-5",
|
|
29
|
+
none: ""
|
|
30
|
+
}, M = {
|
|
27
31
|
INFO: "bg-info-9",
|
|
28
32
|
IMPORTANT: "bg-warning-9",
|
|
29
33
|
CRITICAL: "bg-error-9"
|
|
30
34
|
};
|
|
31
|
-
function te({ notification: e, onRead: n, onNavigate: i, getRoute: o, onDismiss: s }) {
|
|
32
|
-
let
|
|
33
|
-
e.isRead || n(e.id),
|
|
35
|
+
function te({ notification: e, onRead: n, onNavigate: i, getRoute: o, onDismiss: s, unreadStyle: c }) {
|
|
36
|
+
let l = o(e), u = () => {
|
|
37
|
+
e.isRead || n(e.id), l && i(l);
|
|
34
38
|
};
|
|
35
|
-
return /* @__PURE__ */
|
|
39
|
+
return /* @__PURE__ */ C("div", {
|
|
36
40
|
role: "button",
|
|
37
41
|
tabIndex: 0,
|
|
38
|
-
onClick:
|
|
42
|
+
onClick: u,
|
|
39
43
|
onKeyDown: (e) => {
|
|
40
|
-
(e.key === "Enter" || e.key === " ") && (e.preventDefault(),
|
|
44
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), u());
|
|
41
45
|
},
|
|
42
|
-
className: t("group relative flex w-full cursor-pointer items-start gap-ds-04 px-ds-05 py-ds-04 text-left transition-colors duration-fast-02 ease-productive-standard", "hover:bg-surface-panel-hover", !e.isRead &&
|
|
46
|
+
className: t("group relative flex w-full cursor-pointer items-start gap-ds-04 px-ds-05 py-ds-04 text-left transition-colors duration-fast-02 ease-productive-standard", "hover:bg-surface-panel-hover", !e.isRead && j[c]),
|
|
43
47
|
children: [
|
|
44
|
-
/* @__PURE__ */
|
|
48
|
+
/* @__PURE__ */ S("div", {
|
|
45
49
|
className: "mt-ds-02b flex shrink-0",
|
|
46
|
-
children: /* @__PURE__ */
|
|
50
|
+
children: /* @__PURE__ */ S("span", { className: t("h-[8px] w-[8px] rounded-pill transition-opacity duration-fast-02 ease-productive-standard", M[e.tier] || M.INFO, e.isRead ? "opacity-20" : "opacity-100") })
|
|
47
51
|
}),
|
|
48
|
-
/* @__PURE__ */
|
|
52
|
+
/* @__PURE__ */ C("div", {
|
|
49
53
|
className: "min-w-0 flex-1",
|
|
50
54
|
children: [
|
|
51
|
-
/* @__PURE__ */
|
|
55
|
+
/* @__PURE__ */ S(f, {
|
|
52
56
|
as: "p",
|
|
53
57
|
className: t("text-body-md text-surface-fg", !e.isRead && "font-semibold"),
|
|
54
58
|
children: e.title
|
|
55
59
|
}),
|
|
56
|
-
e.body && /* @__PURE__ */
|
|
60
|
+
e.body && /* @__PURE__ */ S("p", {
|
|
57
61
|
className: "mt-ds-01 line-clamp-2 text-body-sm text-surface-fg-subtle",
|
|
58
62
|
children: e.body
|
|
59
63
|
}),
|
|
60
|
-
/* @__PURE__ */
|
|
64
|
+
/* @__PURE__ */ C("div", {
|
|
61
65
|
className: "mt-ds-02 flex items-center gap-ds-03",
|
|
62
|
-
children: [/* @__PURE__ */
|
|
66
|
+
children: [/* @__PURE__ */ S("span", {
|
|
63
67
|
className: "text-body-sm text-surface-fg-subtle",
|
|
64
|
-
children:
|
|
65
|
-
}), e.project && /* @__PURE__ */
|
|
68
|
+
children: _(e.createdAt)
|
|
69
|
+
}), e.project && /* @__PURE__ */ C(x, { children: [/* @__PURE__ */ S("span", {
|
|
66
70
|
className: "text-surface-fg-subtle",
|
|
67
71
|
children: "·"
|
|
68
|
-
}), /* @__PURE__ */
|
|
72
|
+
}), /* @__PURE__ */ S(f, {
|
|
69
73
|
className: "text-body-sm text-surface-fg-subtle",
|
|
70
74
|
children: e.project.title
|
|
71
75
|
})] })]
|
|
72
76
|
}),
|
|
73
|
-
e.actions && e.actions.length > 0 && /* @__PURE__ */
|
|
77
|
+
e.actions && e.actions.length > 0 && /* @__PURE__ */ S("div", {
|
|
74
78
|
className: "mt-ds-03 flex items-center gap-ds-02",
|
|
75
|
-
children: e.actions.map((t) => /* @__PURE__ */
|
|
79
|
+
children: e.actions.map((t) => /* @__PURE__ */ S(a, {
|
|
76
80
|
size: "sm",
|
|
77
81
|
variant: t.variant === "primary" ? "solid" : "ghost",
|
|
78
82
|
color: t.variant === "danger" ? "error" : "accent",
|
|
@@ -85,7 +89,7 @@ function te({ notification: e, onRead: n, onNavigate: i, getRoute: o, onDismiss:
|
|
|
85
89
|
})
|
|
86
90
|
]
|
|
87
91
|
}),
|
|
88
|
-
s && /* @__PURE__ */
|
|
92
|
+
s && /* @__PURE__ */ S("button", {
|
|
89
93
|
type: "button",
|
|
90
94
|
"aria-label": `Dismiss notification: ${e.title}`,
|
|
91
95
|
onClick: (t) => {
|
|
@@ -93,7 +97,7 @@ function te({ notification: e, onRead: n, onNavigate: i, getRoute: o, onDismiss:
|
|
|
93
97
|
},
|
|
94
98
|
onKeyDown: (e) => e.stopPropagation(),
|
|
95
99
|
className: "absolute right-ds-03 top-ds-03 hidden rounded-control-inner p-ds-01 text-surface-fg-subtle transition-[color,background-color,opacity] duration-fast-01 ease-productive-standard hover:bg-surface-panel-hover hover:text-surface-fg-muted group-hover:flex group-focus-within:flex",
|
|
96
|
-
children: /* @__PURE__ */
|
|
100
|
+
children: /* @__PURE__ */ S(r, {
|
|
97
101
|
icon: E,
|
|
98
102
|
size: "sm"
|
|
99
103
|
})
|
|
@@ -101,66 +105,66 @@ function te({ notification: e, onRead: n, onNavigate: i, getRoute: o, onDismiss:
|
|
|
101
105
|
]
|
|
102
106
|
});
|
|
103
107
|
}
|
|
104
|
-
var
|
|
105
|
-
let
|
|
106
|
-
|
|
107
|
-
}, [
|
|
108
|
-
|
|
109
|
-
}, [
|
|
110
|
-
let e =
|
|
111
|
-
!e ||
|
|
108
|
+
var N = v.forwardRef(({ notifications: a = [], unreadCount: f, unreadStyle: _ = "tint", open: v, onOpenChange: E, isLoading: k = !1, hasMore: j = !1, onFetchMore: M, onMarkRead: N, onMarkAllRead: P, onNavigate: F, getNotificationRoute: I, onDismiss: L, headerActions: R, emptyState: z, footerSlot: B, popoverClassName: V, className: H, ...U }, W) => {
|
|
109
|
+
let G = b(null), K = O(), q = i(), J = f ?? a.filter((e) => !e.isRead).length, Y = I ?? (() => null), X = y((e) => {
|
|
110
|
+
E?.(!1), F?.(e);
|
|
111
|
+
}, [F, E]), Z = y((e) => {
|
|
112
|
+
N?.(e);
|
|
113
|
+
}, [N]), ne = y(() => {
|
|
114
|
+
let e = G.current;
|
|
115
|
+
!e || k || !j || e.scrollTop + e.clientHeight >= e.scrollHeight - 50 && M?.();
|
|
112
116
|
}, [
|
|
113
|
-
E,
|
|
114
117
|
k,
|
|
115
|
-
j
|
|
116
|
-
|
|
118
|
+
j,
|
|
119
|
+
M
|
|
120
|
+
]), re = a.reduce((e, t) => {
|
|
117
121
|
let n = A(t.createdAt);
|
|
118
122
|
return e[n] || (e[n] = []), e[n].push(t), e;
|
|
119
|
-
}, {}), Q = /* @__PURE__ */
|
|
120
|
-
/* @__PURE__ */
|
|
123
|
+
}, {}), Q = /* @__PURE__ */ C(x, { children: [
|
|
124
|
+
/* @__PURE__ */ C("div", {
|
|
121
125
|
className: "flex items-center justify-between border-b border-surface-border-strong px-ds-05 py-ds-04",
|
|
122
|
-
children: [/* @__PURE__ */
|
|
126
|
+
children: [/* @__PURE__ */ C("div", {
|
|
123
127
|
className: "flex items-center gap-ds-03",
|
|
124
|
-
children: [!
|
|
128
|
+
children: [!q && /* @__PURE__ */ S("h3", {
|
|
125
129
|
className: "text-body-md font-semibold text-surface-fg",
|
|
126
130
|
children: "Notifications"
|
|
127
|
-
}),
|
|
131
|
+
}), J > 0 && /* @__PURE__ */ S("span", {
|
|
128
132
|
className: "flex h-5 min-w-5 items-center justify-center rounded-pill bg-accent-2 px-ds-02b text-body-sm font-semibold text-accent-11",
|
|
129
|
-
children:
|
|
133
|
+
children: J
|
|
130
134
|
})]
|
|
131
|
-
}), /* @__PURE__ */
|
|
135
|
+
}), /* @__PURE__ */ C("div", {
|
|
132
136
|
className: "flex items-center gap-ds-03",
|
|
133
|
-
children: [
|
|
137
|
+
children: [J > 0 && P && /* @__PURE__ */ C("button", {
|
|
134
138
|
type: "button",
|
|
135
|
-
onClick:
|
|
139
|
+
onClick: P,
|
|
136
140
|
className: "flex items-center gap-ds-02 text-body-sm text-surface-fg-subtle transition-colors hover:text-accent-11",
|
|
137
|
-
children: [/* @__PURE__ */
|
|
141
|
+
children: [/* @__PURE__ */ S(r, {
|
|
138
142
|
icon: w,
|
|
139
143
|
size: "sm"
|
|
140
144
|
}), "Mark all read"]
|
|
141
|
-
}),
|
|
145
|
+
}), R]
|
|
142
146
|
})]
|
|
143
147
|
}),
|
|
144
|
-
/* @__PURE__ */
|
|
145
|
-
ref:
|
|
146
|
-
onScroll:
|
|
147
|
-
className: t("overflow-y-auto",
|
|
148
|
-
children: [a.length === 0 ?
|
|
148
|
+
/* @__PURE__ */ C("div", {
|
|
149
|
+
ref: G,
|
|
150
|
+
onScroll: ne,
|
|
151
|
+
className: t("overflow-y-auto", q ? "max-h-[60vh]" : "max-h-[420px]"),
|
|
152
|
+
children: [a.length === 0 ? z || /* @__PURE__ */ C("div", {
|
|
149
153
|
className: "flex flex-col items-center justify-center px-ds-05 py-ds-09",
|
|
150
154
|
children: [
|
|
151
|
-
/* @__PURE__ */
|
|
152
|
-
className: "flex h-ds-lg w-ds-lg items-center justify-center rounded-pill bg-surface-panel",
|
|
153
|
-
children: /* @__PURE__ */
|
|
155
|
+
/* @__PURE__ */ S("div", {
|
|
156
|
+
className: "flex h-ds-lg w-ds-lg items-center justify-center rounded-pill bg-surface-panel-hover",
|
|
157
|
+
children: /* @__PURE__ */ S(r, {
|
|
154
158
|
icon: T,
|
|
155
159
|
size: "lg",
|
|
156
160
|
className: "text-surface-fg-subtle"
|
|
157
161
|
})
|
|
158
162
|
}),
|
|
159
|
-
/* @__PURE__ */
|
|
163
|
+
/* @__PURE__ */ S("p", {
|
|
160
164
|
className: "mt-ds-04 text-body-md text-surface-fg-subtle",
|
|
161
165
|
children: "No notifications yet"
|
|
162
166
|
}),
|
|
163
|
-
/* @__PURE__ */
|
|
167
|
+
/* @__PURE__ */ S("p", {
|
|
164
168
|
className: "mt-ds-02 text-body-sm text-surface-fg-subtle",
|
|
165
169
|
children: "You're all caught up!"
|
|
166
170
|
})
|
|
@@ -170,45 +174,46 @@ var M = _.forwardRef(({ notifications: a = [], unreadCount: f, open: g, onOpenCh
|
|
|
170
174
|
"Yesterday",
|
|
171
175
|
"Earlier"
|
|
172
176
|
].map((e) => {
|
|
173
|
-
let t =
|
|
174
|
-
return !t || t.length === 0 ? null : /* @__PURE__ */
|
|
177
|
+
let t = re[e];
|
|
178
|
+
return !t || t.length === 0 ? null : /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("div", {
|
|
175
179
|
className: "sticky top-0 z-raised bg-surface-overlay px-ds-05 py-ds-02b",
|
|
176
|
-
children: /* @__PURE__ */
|
|
180
|
+
children: /* @__PURE__ */ S("span", {
|
|
177
181
|
className: "text-body-sm font-medium text-surface-fg-subtle",
|
|
178
182
|
children: e
|
|
179
183
|
})
|
|
180
|
-
}), t.map((e, t) => /* @__PURE__ */
|
|
181
|
-
initial:
|
|
184
|
+
}), t.map((e, t) => /* @__PURE__ */ S(D.div, {
|
|
185
|
+
initial: K ? void 0 : { opacity: 0 },
|
|
182
186
|
animate: { opacity: 1 },
|
|
183
|
-
transition:
|
|
184
|
-
children: /* @__PURE__ */
|
|
187
|
+
transition: K ? { duration: 0 } : { delay: t * .03 },
|
|
188
|
+
children: /* @__PURE__ */ S(te, {
|
|
185
189
|
notification: e,
|
|
186
|
-
onRead:
|
|
187
|
-
onNavigate:
|
|
188
|
-
getRoute:
|
|
189
|
-
onDismiss:
|
|
190
|
+
onRead: Z,
|
|
191
|
+
onNavigate: X,
|
|
192
|
+
getRoute: Y,
|
|
193
|
+
onDismiss: L,
|
|
194
|
+
unreadStyle: _
|
|
190
195
|
})
|
|
191
196
|
}, e.id))] }, e);
|
|
192
|
-
}),
|
|
197
|
+
}), k && /* @__PURE__ */ S("div", {
|
|
193
198
|
className: "flex items-center justify-center py-ds-05",
|
|
194
|
-
children: /* @__PURE__ */
|
|
199
|
+
children: /* @__PURE__ */ S(n, {})
|
|
195
200
|
})]
|
|
196
201
|
}),
|
|
197
|
-
|
|
202
|
+
B && /* @__PURE__ */ S("div", {
|
|
198
203
|
className: "border-t border-surface-border-strong px-ds-05 py-ds-03",
|
|
199
|
-
children:
|
|
204
|
+
children: B
|
|
200
205
|
})
|
|
201
|
-
] }), $ = /* @__PURE__ */
|
|
202
|
-
...
|
|
203
|
-
ref:
|
|
204
|
-
"aria-label":
|
|
205
|
-
className: t("relative flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-card-strong bg-surface-panel text-surface-fg-muted transition-colors ease-productive-standard hover:bg-surface-panel-hover",
|
|
206
|
-
children: [/* @__PURE__ */
|
|
207
|
-
icon:
|
|
206
|
+
] }), $ = /* @__PURE__ */ C("button", {
|
|
207
|
+
...U,
|
|
208
|
+
ref: W,
|
|
209
|
+
"aria-label": J > 0 ? `Notifications, ${J} unread` : "Notifications",
|
|
210
|
+
className: t("relative flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-card-strong bg-surface-panel text-surface-fg-muted transition-colors ease-productive-standard hover:bg-surface-panel-hover", H),
|
|
211
|
+
children: [/* @__PURE__ */ S(r, {
|
|
212
|
+
icon: ee,
|
|
208
213
|
size: "sm"
|
|
209
|
-
}),
|
|
214
|
+
}), J > 0 && /* @__PURE__ */ S(D.span, {
|
|
210
215
|
initial: { rotate: 0 },
|
|
211
|
-
animate:
|
|
216
|
+
animate: K ? void 0 : { rotate: [
|
|
212
217
|
0,
|
|
213
218
|
-3,
|
|
214
219
|
3,
|
|
@@ -216,57 +221,57 @@ var M = _.forwardRef(({ notifications: a = [], unreadCount: f, open: g, onOpenCh
|
|
|
216
221
|
1,
|
|
217
222
|
0
|
|
218
223
|
] },
|
|
219
|
-
transition:
|
|
224
|
+
transition: K ? { duration: 0 } : {
|
|
220
225
|
duration: e.slow01,
|
|
221
226
|
ease: "easeInOut"
|
|
222
227
|
},
|
|
223
228
|
className: "absolute -right-ds-01 -top-ds-01 flex h-4 min-w-4 items-center justify-center rounded-pill bg-accent-9 px-ds-02 text-body-xs font-semibold text-accent-fg",
|
|
224
|
-
children:
|
|
229
|
+
children: J > 99 ? "99+" : J
|
|
225
230
|
})]
|
|
226
231
|
});
|
|
227
|
-
return
|
|
228
|
-
open:
|
|
229
|
-
onOpenChange:
|
|
230
|
-
children: [/* @__PURE__ */
|
|
232
|
+
return q ? /* @__PURE__ */ C(p, {
|
|
233
|
+
open: v,
|
|
234
|
+
onOpenChange: E,
|
|
235
|
+
children: [/* @__PURE__ */ C(l, { children: [/* @__PURE__ */ S(d, {
|
|
231
236
|
asChild: !0,
|
|
232
|
-
children: /* @__PURE__ */
|
|
237
|
+
children: /* @__PURE__ */ S(g, {
|
|
233
238
|
asChild: !0,
|
|
234
239
|
children: $
|
|
235
240
|
})
|
|
236
|
-
}), /* @__PURE__ */
|
|
241
|
+
}), /* @__PURE__ */ S(u, {
|
|
237
242
|
side: "bottom",
|
|
238
243
|
align: "center",
|
|
239
244
|
children: "Notifications"
|
|
240
|
-
})] }), /* @__PURE__ */
|
|
245
|
+
})] }), /* @__PURE__ */ C(m, {
|
|
241
246
|
side: "bottom",
|
|
242
|
-
className: t("p-0",
|
|
247
|
+
className: t("p-0", V),
|
|
243
248
|
responsive: !1,
|
|
244
|
-
children: [/* @__PURE__ */
|
|
249
|
+
children: [/* @__PURE__ */ S(h, {
|
|
245
250
|
className: "px-ds-05 pt-ds-04 text-body-md font-semibold text-surface-fg",
|
|
246
251
|
children: "Notifications"
|
|
247
252
|
}), Q]
|
|
248
253
|
})]
|
|
249
|
-
}) : /* @__PURE__ */
|
|
250
|
-
open:
|
|
251
|
-
onOpenChange:
|
|
252
|
-
children: [/* @__PURE__ */
|
|
254
|
+
}) : /* @__PURE__ */ C(o, {
|
|
255
|
+
open: v,
|
|
256
|
+
onOpenChange: E,
|
|
257
|
+
children: [/* @__PURE__ */ C(l, { children: [/* @__PURE__ */ S(d, {
|
|
253
258
|
asChild: !0,
|
|
254
|
-
children: /* @__PURE__ */
|
|
259
|
+
children: /* @__PURE__ */ S(c, {
|
|
255
260
|
asChild: !0,
|
|
256
261
|
children: $
|
|
257
262
|
})
|
|
258
|
-
}), /* @__PURE__ */
|
|
263
|
+
}), /* @__PURE__ */ S(u, {
|
|
259
264
|
side: "bottom",
|
|
260
265
|
align: "center",
|
|
261
266
|
children: "Notifications"
|
|
262
|
-
})] }), /* @__PURE__ */
|
|
263
|
-
className: t("w-[380px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating",
|
|
267
|
+
})] }), /* @__PURE__ */ S(s, {
|
|
268
|
+
className: t("w-[380px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating", V),
|
|
264
269
|
sideOffset: 8,
|
|
265
270
|
align: "end",
|
|
266
271
|
children: Q
|
|
267
272
|
})]
|
|
268
273
|
});
|
|
269
274
|
});
|
|
270
|
-
|
|
275
|
+
N.displayName = "NotificationCenter";
|
|
271
276
|
//#endregion
|
|
272
|
-
export {
|
|
277
|
+
export { N as NotificationCenter };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification-center.js","names":[],"sources":["../../src/shell/notification-center.tsx"],"sourcesContent":["'use client'\n\n/**\n * NotificationCenter -- Popover-based notification panel.\n *\n * Props-driven: accepts notifications array and callbacks instead of\n * reading from Zustand stores or using Remix useNavigate.\n */\nimport { IconBell, IconChecks, IconInbox, IconX } from '@tabler/icons-react'\nimport { motion, useReducedMotion } from 'framer-motion'\nimport * as React from 'react'\nimport { useCallback,useRef } from 'react'\n\nimport { useIsMobile } from '../hooks/use-mobile'\nimport { Button } from '../ui/button'\nimport { Icon } from '../ui/icon'\nimport { formatRelativeTime } from '../ui/lib/date-utils'\nimport { durations } from '../ui/lib/motion'\nimport { cn } from '../ui/lib/utils'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '../ui/popover'\nimport {\n Sheet,\n SheetContent,\n SheetTitle,\n SheetTrigger,\n} from '../ui/sheet'\nimport { Spinner } from '../ui/spinner'\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '../ui/tooltip'\nimport { TruncatedText } from '../ui/truncated-text'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface NotificationAction {\n /** Button label */\n label: string\n /** Visual style — 'primary' is filled, 'default' is ghost, 'danger' is red ghost */\n variant?: 'primary' | 'default' | 'danger'\n /** Called when the action button is clicked. Receives the notification id. */\n onClick: (id: string) => void\n}\n\nexport interface Notification {\n id: string\n title: string\n body?: string | null\n tier: 'INFO' | 'IMPORTANT' | 'CRITICAL'\n isRead: boolean\n createdAt: string\n entityType?: string | null\n entityId?: string | null\n projectId?: string | null\n project?: { title: string } | null\n /** Inline action buttons (e.g. Approve / Deny). Max 2–3 recommended. */\n actions?: NotificationAction[]\n}\n\nexport interface NotificationCenterProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** List of notifications to display */\n notifications?: Notification[]\n /** Count of unread notifications (derived from notifications if not provided) */\n unreadCount?: number\n /** Whether the popover is open (controlled mode) */\n open?: boolean\n /** Called when the popover open state changes */\n onOpenChange?: (open: boolean) => void\n /** Whether more notifications are loading */\n isLoading?: boolean\n /** Whether there are more notifications to fetch */\n hasMore?: boolean\n /** Called when the user scrolls near the bottom to load more */\n onFetchMore?: () => void\n /** Called to mark a single notification as read */\n onMarkRead?: (id: string) => void\n /** Called to mark all notifications as read */\n onMarkAllRead?: () => void\n /** Called when the user clicks a notification (e.g., navigate to entity) */\n onNavigate?: (path: string) => void\n /** Resolve a notification to a navigation path. Return null if no navigation. */\n getNotificationRoute?: (notification: Notification) => string | null\n /** Additional actions rendered in the header (e.g., settings button) */\n headerActions?: React.ReactNode\n /** Custom empty state to display when there are no notifications */\n emptyState?: React.ReactNode\n /** Content rendered below the notification list as a footer */\n footerSlot?: React.ReactNode\n /** Called when the user dismisses a notification. Renders an X button per row when provided. */\n onDismiss?: (id: string) => void\n /** Additional className for the popover content container */\n popoverClassName?: string\n /** Additional className */\n className?: string\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\n\nfunction isSameDay(a: Date, b: Date): boolean {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n )\n}\n\nfunction getDateGroup(dateStr: string): string {\n const date = new Date(dateStr)\n const today = new Date()\n const yesterday = new Date()\n yesterday.setDate(today.getDate() - 1)\n\n if (isSameDay(date, today)) return 'Today'\n if (isSameDay(date, yesterday)) return 'Yesterday'\n return 'Earlier'\n}\n\nconst TIER_COLORS: Record<string, string> = {\n INFO: 'bg-info-9',\n IMPORTANT: 'bg-warning-9',\n CRITICAL: 'bg-error-9',\n}\n\n// -----------------------------------------------------------------------\n// NotificationItem (internal)\n// -----------------------------------------------------------------------\n\nfunction NotificationItem({\n notification,\n onRead,\n onNavigate,\n getRoute,\n onDismiss,\n}: {\n notification: Notification\n onRead: (id: string) => void\n onNavigate: (path: string) => void\n getRoute: (notification: Notification) => string | null\n onDismiss?: (id: string) => void\n}) {\n const route = getRoute(notification)\n\n const handleClick = () => {\n if (!notification.isRead) {\n onRead(notification.id)\n }\n if (route) {\n onNavigate(route)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick()\n }\n }\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n className={cn(\n 'group relative flex w-full cursor-pointer items-start gap-ds-04 px-ds-05 py-ds-04 text-left transition-colors duration-fast-02 ease-productive-standard',\n 'hover:bg-surface-panel-hover',\n !notification.isRead && 'bg-accent-1',\n )}\n >\n {/* Tier dot — doubles as read/unread marker */}\n <div className=\"mt-ds-02b flex shrink-0\">\n <span\n className={cn(\n 'h-[8px] w-[8px] rounded-pill transition-opacity duration-fast-02 ease-productive-standard',\n TIER_COLORS[notification.tier] || TIER_COLORS.INFO,\n notification.isRead ? 'opacity-20' : 'opacity-100',\n )}\n />\n </div>\n\n {/* Content */}\n <div className=\"min-w-0 flex-1\">\n <TruncatedText\n as=\"p\"\n className={cn(\n 'text-body-md text-surface-fg',\n !notification.isRead && 'font-semibold',\n )}\n >\n {notification.title}\n </TruncatedText>\n {notification.body && (\n <p className=\"mt-ds-01 line-clamp-2 text-body-sm text-surface-fg-subtle\">\n {notification.body}\n </p>\n )}\n <div className=\"mt-ds-02 flex items-center gap-ds-03\">\n <span className=\"text-body-sm text-surface-fg-subtle\">\n {formatRelativeTime(notification.createdAt)}\n </span>\n {notification.project && (\n <>\n <span className=\"text-surface-fg-subtle\">\n ·\n </span>\n <TruncatedText className=\"text-body-sm text-surface-fg-subtle\">\n {notification.project.title}\n </TruncatedText>\n </>\n )}\n </div>\n\n {/* Inline actions */}\n {notification.actions && notification.actions.length > 0 && (\n <div className=\"mt-ds-03 flex items-center gap-ds-02\">\n {notification.actions.map((action) => (\n <Button\n key={action.label}\n size=\"sm\"\n variant={action.variant === 'primary' ? 'solid' : 'ghost'}\n color={action.variant === 'danger' ? 'error' : 'accent'}\n onClick={(e) => {\n e.stopPropagation()\n action.onClick(notification.id)\n }}\n onKeyDown={(e) => e.stopPropagation()}\n >\n {action.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n\n {/* Dismiss button */}\n {onDismiss && (\n <button\n type=\"button\"\n aria-label={`Dismiss notification: ${notification.title}`}\n onClick={(e) => {\n e.stopPropagation()\n onDismiss(notification.id)\n }}\n onKeyDown={(e) => e.stopPropagation()}\n className=\"absolute right-ds-03 top-ds-03 hidden rounded-control-inner p-ds-01 text-surface-fg-subtle transition-[color,background-color,opacity] duration-fast-01 ease-productive-standard hover:bg-surface-panel-hover hover:text-surface-fg-muted group-hover:flex group-focus-within:flex\"\n >\n <Icon icon={IconX} size=\"sm\" />\n </button>\n )}\n </div>\n )\n}\n\n// -----------------------------------------------------------------------\n// NotificationCenter\n// -----------------------------------------------------------------------\n\nconst NotificationCenter = React.forwardRef<HTMLButtonElement, NotificationCenterProps>(\n (\n {\n notifications = [],\n unreadCount: unreadCountProp,\n open,\n onOpenChange,\n isLoading = false,\n hasMore = false,\n onFetchMore,\n onMarkRead,\n onMarkAllRead,\n onNavigate,\n getNotificationRoute,\n onDismiss,\n headerActions,\n emptyState,\n footerSlot,\n popoverClassName,\n className,\n ...props\n },\n ref,\n ) => {\n const scrollRef = useRef<HTMLDivElement>(null)\n const prefersReducedMotion = useReducedMotion()\n const isMobile = useIsMobile()\n\n const unreadCount =\n unreadCountProp ?? notifications.filter((n) => !n.isRead).length\n\n const getRoute = getNotificationRoute ?? (() => null)\n\n const handleNavigate = useCallback(\n (path: string) => {\n onOpenChange?.(false)\n onNavigate?.(path)\n },\n [onNavigate, onOpenChange],\n )\n\n const handleMarkRead = useCallback(\n (id: string) => {\n onMarkRead?.(id)\n },\n [onMarkRead],\n )\n\n const handleScroll = useCallback(() => {\n const el = scrollRef.current\n if (!el || isLoading || !hasMore) return\n if (el.scrollTop + el.clientHeight >= el.scrollHeight - 50) {\n onFetchMore?.()\n }\n }, [isLoading, hasMore, onFetchMore])\n\n // Group notifications by date\n const grouped = notifications.reduce<Record<string, Notification[]>>(\n (acc, n) => {\n const group = getDateGroup(n.createdAt)\n if (!acc[group]) acc[group] = []\n acc[group].push(n)\n return acc\n },\n {},\n )\n\n const groupOrder = ['Today', 'Yesterday', 'Earlier']\n\n // -- Shared panel content (used in both Popover and Sheet) --\n const panelContent = (\n <>\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <div className=\"flex items-center gap-ds-03\">\n {/* On mobile the SheetTitle provides the accessible heading; on desktop use h3 */}\n {!isMobile && (\n <h3 className=\"text-body-md font-semibold text-surface-fg\">\n Notifications\n </h3>\n )}\n {unreadCount > 0 && (\n <span className=\"flex h-5 min-w-5 items-center justify-center rounded-pill bg-accent-2 px-ds-02b text-body-sm font-semibold text-accent-11\">\n {unreadCount}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-ds-03\">\n {unreadCount > 0 && onMarkAllRead && (\n <button\n type=\"button\"\n onClick={onMarkAllRead}\n className=\"flex items-center gap-ds-02 text-body-sm text-surface-fg-subtle transition-colors hover:text-accent-11\"\n >\n <Icon icon={IconChecks} size=\"sm\" />\n Mark all read\n </button>\n )}\n {headerActions}\n </div>\n </div>\n\n {/* Notification list */}\n <div\n ref={scrollRef}\n onScroll={handleScroll}\n className={cn('overflow-y-auto', isMobile ? 'max-h-[60vh]' : 'max-h-[420px]')}\n >\n {notifications.length === 0 ? (\n emptyState || (\n <div className=\"flex flex-col items-center justify-center px-ds-05 py-ds-09\">\n <div className=\"flex h-ds-lg w-ds-lg items-center justify-center rounded-pill bg-surface-panel\">\n <Icon icon={IconInbox} size=\"lg\" className=\"text-surface-fg-subtle\" />\n </div>\n <p className=\"mt-ds-04 text-body-md text-surface-fg-subtle\">\n No notifications yet\n </p>\n <p className=\"mt-ds-02 text-body-sm text-surface-fg-subtle\">\n You're all caught up!\n </p>\n </div>\n )\n ) : (\n groupOrder.map((group) => {\n const items = grouped[group]\n if (!items || items.length === 0) return null\n return (\n <div key={group}>\n <div className=\"sticky top-0 z-raised bg-surface-overlay px-ds-05 py-ds-02b\">\n <span className=\"text-body-sm font-medium text-surface-fg-subtle\">\n {group}\n </span>\n </div>\n {items.map((notification, index) => (\n <motion.div\n key={notification.id}\n initial={prefersReducedMotion ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={prefersReducedMotion ? { duration: 0 } : { delay: index * 0.03 }}\n >\n <NotificationItem\n notification={notification}\n onRead={handleMarkRead}\n onNavigate={handleNavigate}\n getRoute={getRoute}\n onDismiss={onDismiss}\n />\n </motion.div>\n ))}\n </div>\n )\n })\n )}\n\n {isLoading && (\n <div className=\"flex items-center justify-center py-ds-05\">\n <Spinner />\n </div>\n )}\n </div>\n {footerSlot && (\n <div className=\"border-t border-surface-border-strong px-ds-05 py-ds-03\">\n {footerSlot}\n </div>\n )}\n </>\n )\n\n // -- Trigger button (shared between both modes) --\n const triggerButton = (\n <button\n {...props}\n ref={ref}\n aria-label={unreadCount > 0 ? `Notifications, ${unreadCount} unread` : 'Notifications'}\n className={cn(\n 'relative flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-card-strong bg-surface-panel text-surface-fg-muted transition-colors ease-productive-standard hover:bg-surface-panel-hover',\n className,\n )}\n >\n <Icon icon={IconBell} size=\"sm\" />\n {unreadCount > 0 && (\n <motion.span\n initial={{ rotate: 0 }}\n animate={prefersReducedMotion ? undefined : { rotate: [0, -3, 3, -1, 1, 0] }}\n transition={prefersReducedMotion ? { duration: 0 } : { duration: durations.slow01, ease: 'easeInOut' }}\n className=\"absolute -right-ds-01 -top-ds-01 flex h-4 min-w-4 items-center justify-center rounded-pill bg-accent-9 px-ds-02 text-body-xs font-semibold text-accent-fg\"\n >\n {unreadCount > 99 ? '99+' : unreadCount}\n </motion.span>\n )}\n </button>\n )\n\n // -- Mobile: render in a bottom Sheet --\n if (isMobile) {\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <Tooltip>\n <TooltipTrigger asChild>\n <SheetTrigger asChild>\n {triggerButton}\n </SheetTrigger>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n Notifications\n </TooltipContent>\n </Tooltip>\n\n <SheetContent side=\"bottom\" className={cn('p-0', popoverClassName)} responsive={false}>\n <SheetTitle className=\"px-ds-05 pt-ds-04 text-body-md font-semibold text-surface-fg\">\n Notifications\n </SheetTitle>\n {panelContent}\n </SheetContent>\n </Sheet>\n )\n }\n\n // -- Desktop: render in a Popover --\n return (\n <Popover open={open} onOpenChange={onOpenChange}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n {triggerButton}\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n Notifications\n </TooltipContent>\n </Tooltip>\n\n <PopoverContent\n className={cn(\n 'w-[380px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating',\n popoverClassName,\n )}\n sideOffset={8}\n align=\"end\"\n >\n {panelContent}\n </PopoverContent>\n </Popover>\n )\n },\n)\nNotificationCenter.displayName = 'NotificationCenter'\n\nexport { NotificationCenter }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"notification-center.js","names":[],"sources":["../../src/shell/notification-center.tsx"],"sourcesContent":["'use client'\n\n/**\n * NotificationCenter -- Popover-based notification panel.\n *\n * Props-driven: accepts notifications array and callbacks instead of\n * reading from Zustand stores or using Remix useNavigate.\n */\nimport { IconBell, IconChecks, IconInbox, IconX } from '@tabler/icons-react'\nimport { motion, useReducedMotion } from 'framer-motion'\nimport * as React from 'react'\nimport { useCallback,useRef } from 'react'\n\nimport { useIsMobile } from '../hooks/use-mobile'\nimport { Button } from '../ui/button'\nimport { Icon } from '../ui/icon'\nimport { formatRelativeTime } from '../ui/lib/date-utils'\nimport { durations } from '../ui/lib/motion'\nimport { cn } from '../ui/lib/utils'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '../ui/popover'\nimport {\n Sheet,\n SheetContent,\n SheetTitle,\n SheetTrigger,\n} from '../ui/sheet'\nimport { Spinner } from '../ui/spinner'\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '../ui/tooltip'\nimport { TruncatedText } from '../ui/truncated-text'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface NotificationAction {\n /** Button label */\n label: string\n /** Visual style — 'primary' is filled, 'default' is ghost, 'danger' is red ghost */\n variant?: 'primary' | 'default' | 'danger'\n /** Called when the action button is clicked. Receives the notification id. */\n onClick: (id: string) => void\n}\n\nexport interface Notification {\n id: string\n title: string\n body?: string | null\n tier: 'INFO' | 'IMPORTANT' | 'CRITICAL'\n isRead: boolean\n createdAt: string\n entityType?: string | null\n entityId?: string | null\n projectId?: string | null\n project?: { title: string } | null\n /** Inline action buttons (e.g. Approve / Deny). Max 2–3 recommended. */\n actions?: NotificationAction[]\n}\n\n/** Visual weight of an unread row. See `NotificationCenterProps.unreadStyle`. */\nexport type NotificationUnreadStyle = 'tint' | 'strong' | 'none'\n\nexport interface NotificationCenterProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** List of notifications to display */\n notifications?: Notification[]\n /** Count of unread notifications (derived from notifications if not provided) */\n unreadCount?: number\n /** Whether the popover is open (controlled mode) */\n open?: boolean\n /** Called when the popover open state changes */\n onOpenChange?: (open: boolean) => void\n /** Whether more notifications are loading */\n isLoading?: boolean\n /** Whether there are more notifications to fetch */\n hasMore?: boolean\n /** Called when the user scrolls near the bottom to load more */\n onFetchMore?: () => void\n /** Called to mark a single notification as read */\n onMarkRead?: (id: string) => void\n /** Called to mark all notifications as read */\n onMarkAllRead?: () => void\n /** Called when the user clicks a notification (e.g., navigate to entity) */\n onNavigate?: (path: string) => void\n /** Resolve a notification to a navigation path. Return null if no navigation. */\n getNotificationRoute?: (notification: Notification) => string | null\n /** Additional actions rendered in the header (e.g., settings button) */\n headerActions?: React.ReactNode\n /** Custom empty state to display when there are no notifications */\n emptyState?: React.ReactNode\n /** Content rendered below the notification list as a footer */\n footerSlot?: React.ReactNode\n /** Called when the user dismisses a notification. Renders an X button per row when provided. */\n onDismiss?: (id: string) => void\n /**\n * How an unread row announces itself.\n *\n * - `tint` (default) — an accent wash plus a bold title. The conventional\n * look, and the quietest fill that still reads louder than a hovered\n * already-read row in both themes.\n * - `strong` — a heavier wash, for inboxes where unread has to carry across\n * a long list at a glance.\n * - `none` — no wash at all. The tier dot (which already fades to 20% once\n * read) and the bold title carry the state on their own. The calmest\n * option, and the one that scales best down a long list.\n *\n * @default 'tint'\n */\n unreadStyle?: NotificationUnreadStyle\n /** Additional className for the popover content container */\n popoverClassName?: string\n /** Additional className */\n className?: string\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\n\nfunction isSameDay(a: Date, b: Date): boolean {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n )\n}\n\nfunction getDateGroup(dateStr: string): string {\n const date = new Date(dateStr)\n const today = new Date()\n const yesterday = new Date()\n yesterday.setDate(today.getDate() - 1)\n\n if (isSameDay(date, today)) return 'Today'\n if (isSameDay(date, yesterday)) return 'Yesterday'\n return 'Earlier'\n}\n\n// The comparison that matters is against a HOVERED READ row, not against the\n// panel. Rows hover to `surface-panel-hover`, so an unread wash has to beat that\n// or a row you have already read looks more urgent than one you have not.\n//\n// Measured on a panel, unread vs hovered-read (1.091:1 light / 1.173:1 dark):\n//\n// accent-3 1.246 light / 1.042 dark <- LOSES in dark\n// accent-4 1.422 light / 1.231 dark\n// accent-5 1.690 light / 1.458 dark\n//\n// So step 4 is the floor, not step 3. An earlier revision of this file used\n// step 3 for `tint` on the grounds that it clears `surface-panel` — true, but\n// the panel is not what an unread row competes with.\nconst UNREAD_STYLES: Record<NotificationUnreadStyle, string> = {\n tint: 'bg-accent-4',\n strong: 'bg-accent-5',\n none: '',\n}\n\nconst TIER_COLORS: Record<string, string> = {\n INFO: 'bg-info-9',\n IMPORTANT: 'bg-warning-9',\n CRITICAL: 'bg-error-9',\n}\n\n// -----------------------------------------------------------------------\n// NotificationItem (internal)\n// -----------------------------------------------------------------------\n\nfunction NotificationItem({\n notification,\n onRead,\n onNavigate,\n getRoute,\n onDismiss,\n unreadStyle,\n}: {\n notification: Notification\n onRead: (id: string) => void\n onNavigate: (path: string) => void\n getRoute: (notification: Notification) => string | null\n onDismiss?: (id: string) => void\n unreadStyle: NotificationUnreadStyle\n}) {\n const route = getRoute(notification)\n\n const handleClick = () => {\n if (!notification.isRead) {\n onRead(notification.id)\n }\n if (route) {\n onNavigate(route)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick()\n }\n }\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n className={cn(\n 'group relative flex w-full cursor-pointer items-start gap-ds-04 px-ds-05 py-ds-04 text-left transition-colors duration-fast-02 ease-productive-standard',\n 'hover:bg-surface-panel-hover',\n !notification.isRead && UNREAD_STYLES[unreadStyle],\n )}\n >\n {/* Tier dot — doubles as read/unread marker */}\n <div className=\"mt-ds-02b flex shrink-0\">\n <span\n className={cn(\n 'h-[8px] w-[8px] rounded-pill transition-opacity duration-fast-02 ease-productive-standard',\n TIER_COLORS[notification.tier] || TIER_COLORS.INFO,\n notification.isRead ? 'opacity-20' : 'opacity-100',\n )}\n />\n </div>\n\n {/* Content */}\n <div className=\"min-w-0 flex-1\">\n <TruncatedText\n as=\"p\"\n className={cn(\n 'text-body-md text-surface-fg',\n !notification.isRead && 'font-semibold',\n )}\n >\n {notification.title}\n </TruncatedText>\n {notification.body && (\n <p className=\"mt-ds-01 line-clamp-2 text-body-sm text-surface-fg-subtle\">\n {notification.body}\n </p>\n )}\n <div className=\"mt-ds-02 flex items-center gap-ds-03\">\n <span className=\"text-body-sm text-surface-fg-subtle\">\n {formatRelativeTime(notification.createdAt)}\n </span>\n {notification.project && (\n <>\n <span className=\"text-surface-fg-subtle\">\n ·\n </span>\n <TruncatedText className=\"text-body-sm text-surface-fg-subtle\">\n {notification.project.title}\n </TruncatedText>\n </>\n )}\n </div>\n\n {/* Inline actions */}\n {notification.actions && notification.actions.length > 0 && (\n <div className=\"mt-ds-03 flex items-center gap-ds-02\">\n {notification.actions.map((action) => (\n <Button\n key={action.label}\n size=\"sm\"\n variant={action.variant === 'primary' ? 'solid' : 'ghost'}\n color={action.variant === 'danger' ? 'error' : 'accent'}\n onClick={(e) => {\n e.stopPropagation()\n action.onClick(notification.id)\n }}\n onKeyDown={(e) => e.stopPropagation()}\n >\n {action.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n\n {/* Dismiss button */}\n {onDismiss && (\n <button\n type=\"button\"\n aria-label={`Dismiss notification: ${notification.title}`}\n onClick={(e) => {\n e.stopPropagation()\n onDismiss(notification.id)\n }}\n onKeyDown={(e) => e.stopPropagation()}\n className=\"absolute right-ds-03 top-ds-03 hidden rounded-control-inner p-ds-01 text-surface-fg-subtle transition-[color,background-color,opacity] duration-fast-01 ease-productive-standard hover:bg-surface-panel-hover hover:text-surface-fg-muted group-hover:flex group-focus-within:flex\"\n >\n <Icon icon={IconX} size=\"sm\" />\n </button>\n )}\n </div>\n )\n}\n\n// -----------------------------------------------------------------------\n// NotificationCenter\n// -----------------------------------------------------------------------\n\nconst NotificationCenter = React.forwardRef<HTMLButtonElement, NotificationCenterProps>(\n (\n {\n notifications = [],\n unreadCount: unreadCountProp,\n unreadStyle = 'tint',\n open,\n onOpenChange,\n isLoading = false,\n hasMore = false,\n onFetchMore,\n onMarkRead,\n onMarkAllRead,\n onNavigate,\n getNotificationRoute,\n onDismiss,\n headerActions,\n emptyState,\n footerSlot,\n popoverClassName,\n className,\n ...props\n },\n ref,\n ) => {\n const scrollRef = useRef<HTMLDivElement>(null)\n const prefersReducedMotion = useReducedMotion()\n const isMobile = useIsMobile()\n\n const unreadCount =\n unreadCountProp ?? notifications.filter((n) => !n.isRead).length\n\n const getRoute = getNotificationRoute ?? (() => null)\n\n const handleNavigate = useCallback(\n (path: string) => {\n onOpenChange?.(false)\n onNavigate?.(path)\n },\n [onNavigate, onOpenChange],\n )\n\n const handleMarkRead = useCallback(\n (id: string) => {\n onMarkRead?.(id)\n },\n [onMarkRead],\n )\n\n const handleScroll = useCallback(() => {\n const el = scrollRef.current\n if (!el || isLoading || !hasMore) return\n if (el.scrollTop + el.clientHeight >= el.scrollHeight - 50) {\n onFetchMore?.()\n }\n }, [isLoading, hasMore, onFetchMore])\n\n // Group notifications by date\n const grouped = notifications.reduce<Record<string, Notification[]>>(\n (acc, n) => {\n const group = getDateGroup(n.createdAt)\n if (!acc[group]) acc[group] = []\n acc[group].push(n)\n return acc\n },\n {},\n )\n\n const groupOrder = ['Today', 'Yesterday', 'Earlier']\n\n // -- Shared panel content (used in both Popover and Sheet) --\n const panelContent = (\n <>\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <div className=\"flex items-center gap-ds-03\">\n {/* On mobile the SheetTitle provides the accessible heading; on desktop use h3 */}\n {!isMobile && (\n <h3 className=\"text-body-md font-semibold text-surface-fg\">\n Notifications\n </h3>\n )}\n {unreadCount > 0 && (\n <span className=\"flex h-5 min-w-5 items-center justify-center rounded-pill bg-accent-2 px-ds-02b text-body-sm font-semibold text-accent-11\">\n {unreadCount}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-ds-03\">\n {unreadCount > 0 && onMarkAllRead && (\n <button\n type=\"button\"\n onClick={onMarkAllRead}\n className=\"flex items-center gap-ds-02 text-body-sm text-surface-fg-subtle transition-colors hover:text-accent-11\"\n >\n <Icon icon={IconChecks} size=\"sm\" />\n Mark all read\n </button>\n )}\n {headerActions}\n </div>\n </div>\n\n {/* Notification list */}\n <div\n ref={scrollRef}\n onScroll={handleScroll}\n className={cn('overflow-y-auto', isMobile ? 'max-h-[60vh]' : 'max-h-[420px]')}\n >\n {notifications.length === 0 ? (\n emptyState || (\n <div className=\"flex flex-col items-center justify-center px-ds-05 py-ds-09\">\n <div className=\"flex h-ds-lg w-ds-lg items-center justify-center rounded-pill bg-surface-panel-hover\">\n <Icon icon={IconInbox} size=\"lg\" className=\"text-surface-fg-subtle\" />\n </div>\n <p className=\"mt-ds-04 text-body-md text-surface-fg-subtle\">\n No notifications yet\n </p>\n <p className=\"mt-ds-02 text-body-sm text-surface-fg-subtle\">\n You're all caught up!\n </p>\n </div>\n )\n ) : (\n groupOrder.map((group) => {\n const items = grouped[group]\n if (!items || items.length === 0) return null\n return (\n <div key={group}>\n <div className=\"sticky top-0 z-raised bg-surface-overlay px-ds-05 py-ds-02b\">\n <span className=\"text-body-sm font-medium text-surface-fg-subtle\">\n {group}\n </span>\n </div>\n {items.map((notification, index) => (\n <motion.div\n key={notification.id}\n initial={prefersReducedMotion ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={prefersReducedMotion ? { duration: 0 } : { delay: index * 0.03 }}\n >\n <NotificationItem\n notification={notification}\n onRead={handleMarkRead}\n onNavigate={handleNavigate}\n getRoute={getRoute}\n onDismiss={onDismiss}\n unreadStyle={unreadStyle}\n />\n </motion.div>\n ))}\n </div>\n )\n })\n )}\n\n {isLoading && (\n <div className=\"flex items-center justify-center py-ds-05\">\n <Spinner />\n </div>\n )}\n </div>\n {footerSlot && (\n <div className=\"border-t border-surface-border-strong px-ds-05 py-ds-03\">\n {footerSlot}\n </div>\n )}\n </>\n )\n\n // -- Trigger button (shared between both modes) --\n const triggerButton = (\n <button\n {...props}\n ref={ref}\n aria-label={unreadCount > 0 ? `Notifications, ${unreadCount} unread` : 'Notifications'}\n className={cn(\n 'relative flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-card-strong bg-surface-panel text-surface-fg-muted transition-colors ease-productive-standard hover:bg-surface-panel-hover',\n className,\n )}\n >\n <Icon icon={IconBell} size=\"sm\" />\n {unreadCount > 0 && (\n <motion.span\n initial={{ rotate: 0 }}\n animate={prefersReducedMotion ? undefined : { rotate: [0, -3, 3, -1, 1, 0] }}\n transition={prefersReducedMotion ? { duration: 0 } : { duration: durations.slow01, ease: 'easeInOut' }}\n className=\"absolute -right-ds-01 -top-ds-01 flex h-4 min-w-4 items-center justify-center rounded-pill bg-accent-9 px-ds-02 text-body-xs font-semibold text-accent-fg\"\n >\n {unreadCount > 99 ? '99+' : unreadCount}\n </motion.span>\n )}\n </button>\n )\n\n // -- Mobile: render in a bottom Sheet --\n if (isMobile) {\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <Tooltip>\n <TooltipTrigger asChild>\n <SheetTrigger asChild>\n {triggerButton}\n </SheetTrigger>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n Notifications\n </TooltipContent>\n </Tooltip>\n\n <SheetContent side=\"bottom\" className={cn('p-0', popoverClassName)} responsive={false}>\n <SheetTitle className=\"px-ds-05 pt-ds-04 text-body-md font-semibold text-surface-fg\">\n Notifications\n </SheetTitle>\n {panelContent}\n </SheetContent>\n </Sheet>\n )\n }\n\n // -- Desktop: render in a Popover --\n return (\n <Popover open={open} onOpenChange={onOpenChange}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n {triggerButton}\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n Notifications\n </TooltipContent>\n </Tooltip>\n\n <PopoverContent\n className={cn(\n 'w-[380px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating',\n popoverClassName,\n )}\n sideOffset={8}\n align=\"end\"\n >\n {panelContent}\n </PopoverContent>\n </Popover>\n )\n },\n)\nNotificationCenter.displayName = 'NotificationCenter'\n\nexport { NotificationCenter }\n"],"mappings":"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"}
|
|
@@ -88,7 +88,7 @@ var k = {
|
|
|
88
88
|
className: e("flex items-center gap-ds-05 py-ds-04", r < b.length - 1 && "border-b border-surface-border-strong"),
|
|
89
89
|
children: [
|
|
90
90
|
/* @__PURE__ */ C("div", {
|
|
91
|
-
className: "flex h-ds-sm w-ds-sm shrink-0 items-center justify-center rounded-surface bg-surface-panel",
|
|
91
|
+
className: "flex h-ds-sm w-ds-sm shrink-0 items-center justify-center rounded-surface bg-surface-panel-hover",
|
|
92
92
|
children: /* @__PURE__ */ C("span", {
|
|
93
93
|
className: "[&>svg]:h-ico-sm [&>svg]:w-ico-sm text-surface-fg-muted",
|
|
94
94
|
"aria-hidden": "true",
|