@medipha/chat 1.0.14

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 (119) hide show
  1. package/README.md +103 -0
  2. package/dist/api/client.d.ts +5 -0
  3. package/dist/features/composer/attachment-file-helpers.d.ts +22 -0
  4. package/dist/features/composer/attachments/attachment-buttons.d.ts +8 -0
  5. package/dist/features/composer/conversation-composer.d.ts +20 -0
  6. package/dist/features/composer/editor/font-size-extension.d.ts +18 -0
  7. package/dist/features/composer/editor/mention-suggestion-list.d.ts +15 -0
  8. package/dist/features/composer/editor/paste-text-style.d.ts +5 -0
  9. package/dist/features/composer/emoji/emoji-picker-button.d.ts +9 -0
  10. package/dist/features/composer/emoji/emoji-shortcode-extension.d.ts +9 -0
  11. package/dist/features/composer/emoji/emoji-shortcodes.d.ts +2 -0
  12. package/dist/features/composer/format-bar/format-bar.d.ts +14 -0
  13. package/dist/features/composer/more-menu/more-menu.d.ts +4 -0
  14. package/dist/features/composer/pending-attachment.d.ts +10 -0
  15. package/dist/features/composer/reply/composer-reply-banner.d.ts +11 -0
  16. package/dist/features/composer/reply/use-reply-target.d.ts +12 -0
  17. package/dist/features/composer/stickers.d.ts +6 -0
  18. package/dist/features/composer/toolbar/composer-toolbar.d.ts +19 -0
  19. package/dist/features/composer/typing/use-typing-notifier.d.ts +11 -0
  20. package/dist/features/composer/use-attachment-upload.d.ts +4 -0
  21. package/dist/features/composer/use-pending-attachments.d.ts +16 -0
  22. package/dist/features/create-conversation/create-conversation-panel.d.ts +9 -0
  23. package/dist/features/create-conversation/tabs/create-group-tab.d.ts +13 -0
  24. package/dist/features/create-conversation/tabs/direct-chat-tab.d.ts +12 -0
  25. package/dist/features/create-conversation/tabs/selected-members-modal.d.ts +11 -0
  26. package/dist/features/files/file-attachment.d.ts +24 -0
  27. package/dist/features/forward/forward-dialog.d.ts +11 -0
  28. package/dist/features/forward/use-forward-message.d.ts +21 -0
  29. package/dist/features/media-preview/media-preview-modal.d.ts +23 -0
  30. package/dist/features/media-preview/use-image-lightbox.d.ts +16 -0
  31. package/dist/features/message-list/bubble/message-actions/message-actions-menu.d.ts +27 -0
  32. package/dist/features/message-list/bubble/message-bubble.d.ts +53 -0
  33. package/dist/features/message-list/bubble/message-content-body.d.ts +12 -0
  34. package/dist/features/message-list/bubble/message-reactions.d.ts +18 -0
  35. package/dist/features/message-list/bubble/rich-message-content.d.ts +8 -0
  36. package/dist/features/message-list/overlays/message-details/message-details-modal.d.ts +16 -0
  37. package/dist/features/message-list/overlays/message-details/use-message-details-modal.d.ts +14 -0
  38. package/dist/features/message-list/overlays/message-menu/use-message-menu.d.ts +21 -0
  39. package/dist/features/message-list/overlays/reaction/reaction-modal.d.ts +22 -0
  40. package/dist/features/message-list/overlays/reaction/use-reaction-modal.d.ts +23 -0
  41. package/dist/features/message-list/overlays/reaction/use-reaction-picker.d.ts +8 -0
  42. package/dist/features/message-list/overlays/system-members/system-members-modal.d.ts +22 -0
  43. package/dist/features/message-list/overlays/system-members/use-system-members-modal.d.ts +18 -0
  44. package/dist/features/message-list/use-message-removal.d.ts +12 -0
  45. package/dist/features/message-list/use-message-timeline-scroll.d.ts +25 -0
  46. package/dist/features/message-window/use-message-window.d.ts +46 -0
  47. package/dist/features/pinned-messages/pinned-messages-bar.d.ts +18 -0
  48. package/dist/features/pinned-messages/use-pinned-messages.d.ts +21 -0
  49. package/dist/features/typing/use-typing-indicator.d.ts +12 -0
  50. package/dist/index.cjs +278 -0
  51. package/dist/index.d.ts +2 -0
  52. package/dist/index.js +66322 -0
  53. package/dist/module/chat-module.d.ts +3 -0
  54. package/dist/module/chat-module.types.d.ts +11 -0
  55. package/dist/module/chat-routes.d.ts +4 -0
  56. package/dist/module/chat-runtime-context.d.ts +5 -0
  57. package/dist/pages/Setting/archive/archive-attachment-preview.d.ts +13 -0
  58. package/dist/pages/Setting/archive/archive-file-list.d.ts +15 -0
  59. package/dist/pages/Setting/archive/archive-helpers.d.ts +37 -0
  60. package/dist/pages/Setting/archive/archive-media-grid.d.ts +14 -0
  61. package/dist/pages/Setting/archive/archive-view.d.ts +19 -0
  62. package/dist/pages/Setting/archive/hooks/use-conversation-archive.d.ts +22 -0
  63. package/dist/pages/Setting/conversation-settings-panel.d.ts +20 -0
  64. package/dist/pages/Setting/hooks/use-conversation-settings.d.ts +41 -0
  65. package/dist/pages/Setting/hooks/use-search-panel.d.ts +7 -0
  66. package/dist/pages/Setting/index.d.ts +39 -0
  67. package/dist/pages/Setting/members/add-member-modal.d.ts +11 -0
  68. package/dist/pages/Setting/members/group-members-modal.d.ts +21 -0
  69. package/dist/pages/Setting/members/hooks/use-rename-group-dialog.d.ts +15 -0
  70. package/dist/pages/Setting/members/member-selection-footer.d.ts +12 -0
  71. package/dist/pages/Setting/members/members-list-modal.d.ts +29 -0
  72. package/dist/pages/Setting/members/settings-modal.d.ts +36 -0
  73. package/dist/pages/Setting/members/use-member-selection.d.ts +18 -0
  74. package/dist/pages/Setting/search-panel.d.ts +13 -0
  75. package/dist/pages/conversation/conversation-detail/conversation-detail.d.ts +92 -0
  76. package/dist/pages/conversation/conversation-footer/conversation-footer.d.ts +42 -0
  77. package/dist/pages/conversation/conversation-header/conversation-header.d.ts +27 -0
  78. package/dist/pages/conversation/hooks/use-current-membership.d.ts +14 -0
  79. package/dist/pages/conversation/index.d.ts +28 -0
  80. package/dist/pages/conversations/empty-state/conversation-empty-state.d.ts +3 -0
  81. package/dist/pages/conversations/index.d.ts +4 -0
  82. package/dist/pages/sidebar/hooks/use-conversations.d.ts +17 -0
  83. package/dist/pages/sidebar/index.d.ts +4 -0
  84. package/dist/pages/sidebar/sidbar-conversation-list/sidbar-conversation-list.d.ts +13 -0
  85. package/dist/pages/sidebar/sidebar-filter/sidebar-filter.d.ts +13 -0
  86. package/dist/pages/sidebar/sidebar-header-infor/sidebar-header-infor.d.ts +4 -0
  87. package/dist/shared/components/banner-carousel.d.ts +9 -0
  88. package/dist/shared/components/conversation-avatar.d.ts +19 -0
  89. package/dist/shared/components/date-range-filter-pill.d.ts +17 -0
  90. package/dist/shared/components/download-action.d.ts +11 -0
  91. package/dist/shared/components/filter-pill.d.ts +15 -0
  92. package/dist/shared/components/image-not-available.d.ts +12 -0
  93. package/dist/shared/components/image-with-fallback.d.ts +13 -0
  94. package/dist/shared/components/load-more-sentinel.d.ts +15 -0
  95. package/dist/shared/components/quote-icon.d.ts +5 -0
  96. package/dist/shared/components/search-empty-state.d.ts +8 -0
  97. package/dist/shared/components/shared-icon.d.ts +5 -0
  98. package/dist/shared/components/user-avatar.d.ts +12 -0
  99. package/dist/shared/components/user-profile-modal.d.ts +13 -0
  100. package/dist/shared/components/verified-badge.d.ts +5 -0
  101. package/dist/shared/helper/dayjs-date-picker.d.ts +14 -0
  102. package/dist/shared/hooks/use-directory-filter.d.ts +13 -0
  103. package/dist/shared/hooks/use-user-profile-modal.d.ts +9 -0
  104. package/dist/socket/chatSocket.d.ts +6 -0
  105. package/dist/store/authStore.d.ts +34 -0
  106. package/dist/store/connectionStore.d.ts +8 -0
  107. package/dist/store/conversationsStore.d.ts +38 -0
  108. package/dist/store/forwardStore.d.ts +14 -0
  109. package/dist/store/pinnedMessagesStore.d.ts +16 -0
  110. package/dist/store/presenceStore.d.ts +11 -0
  111. package/dist/store/verifiedPermissionsStore.d.ts +20 -0
  112. package/dist/styles.css +2 -0
  113. package/dist/utils/chat-display.d.ts +44 -0
  114. package/dist/utils/chat-member-resolvers.d.ts +9 -0
  115. package/dist/utils/chat-toast.d.ts +18 -0
  116. package/dist/utils/chat.d.ts +282 -0
  117. package/dist/utils/token.d.ts +0 -0
  118. package/dist/utils/work-status.d.ts +15 -0
  119. package/package.json +96 -0
@@ -0,0 +1,28 @@
1
+ import { ChatUser, Conversation } from '../../utils/chat';
2
+ export interface ConversationGroupHandle {
3
+ /** Jumps the message timeline to the given message — used by the page-level SearchPanel,
4
+ * which lives outside this group but needs to drive its message window. */
5
+ loadAround: (messageId: string) => Promise<boolean> | boolean;
6
+ }
7
+ interface ConversationGroupProps {
8
+ conversationId: string | undefined;
9
+ conversation: Conversation | null;
10
+ isLoadingConversation: boolean;
11
+ currentUserId: string | null;
12
+ authUser: ChatUser | null;
13
+ accessToken: string | undefined;
14
+ isSettingsOpen: boolean;
15
+ onToggleSettings: () => void;
16
+ onOpenSearch: () => void;
17
+ onEditTitle: () => void;
18
+ onOpenMembers: () => void;
19
+ onOpenUserProfile: (userId: string) => void;
20
+ onNavigateBack: () => void;
21
+ }
22
+ /** Header + detail + footer for the currently open conversation. Owns only what's
23
+ * genuinely shared across those three (message window, membership, reply target,
24
+ * pending attachments, typing, the shared image lightbox) — the nearest common ancestor
25
+ * for exactly the state they need. Everything exclusive to one of them (pin, reaction,
26
+ * message menu/details — all detail-only) lives inside that component instead. */
27
+ export declare const ConversationGroup: import('react').ForwardRefExoticComponent<ConversationGroupProps & import('react').RefAttributes<ConversationGroupHandle>>;
28
+ export {};
@@ -0,0 +1,3 @@
1
+ /** Welcome/placeholder screen shown in the conversation pane before any conversation
2
+ * has been picked from the sidebar. */
3
+ export declare function ConversationEmptyState(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,4 @@
1
+ /** Full-viewport chat workspace: sidebar plus the active conversation. Owns the
2
+ * conversation object itself (shared by both the conversation group and the Setting
3
+ * group) and the handful of dialogs/state that outlive either (forward, user profile). */
4
+ export declare function ConversationScreen(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { Conversation } from '../../../utils/chat';
2
+ interface UseConversationsResult {
3
+ conversations: Conversation[];
4
+ isLoading: boolean;
5
+ error: string;
6
+ togglePin: (conversationId: string, pinned: boolean) => Promise<void>;
7
+ reload: () => Promise<void>;
8
+ }
9
+ /**
10
+ * Loads the current user's conversations and keeps the list live via socket events.
11
+ * Backed by the shared `conversationsStore` (not local state) — the page-level "currently
12
+ * open conversation" reads and gets patched through the same store, so the two never
13
+ * drift out of sync on the same realtime events.
14
+ * `activeConversationId` is accepted for call-site compatibility (currently unused here).
15
+ */
16
+ export declare function useConversations(activeConversationId?: string): UseConversationsResult;
17
+ export {};
@@ -0,0 +1,4 @@
1
+ /** Left rail listing conversations with search, unread filter, and creation entry. Owns the
2
+ * search/filter state shared by its filter row and list, and the conversation feed itself —
3
+ * its 3 sub-parts (header-infor, filter, conversation-list) are otherwise independent. */
4
+ export declare function ConversationSidebar(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { Conversation } from '../../../utils/chat';
2
+ interface SidbarConversationListProps {
3
+ conversations: Conversation[];
4
+ isLoading: boolean;
5
+ error: string;
6
+ currentUserId: string | null;
7
+ activeConversationId: string | undefined;
8
+ buildConversationPath: (targetId: string) => string;
9
+ onTogglePin: (conversationId: string, nextPinned: boolean) => void;
10
+ }
11
+ /** The scrollable list of conversation rows — already-filtered input in, Link rows out. */
12
+ export declare function SidbarConversationList({ conversations, isLoading, error, currentUserId, activeConversationId, buildConversationPath, onTogglePin, }: SidbarConversationListProps): import("react/jsx-runtime").JSX.Element;
13
+ export {};
@@ -0,0 +1,13 @@
1
+ export type SidebarConversationFilter = 'all' | 'unread' | 'verified';
2
+ interface SidebarFilterProps {
3
+ searchTerm: string;
4
+ onSearchTermChange: (value: string) => void;
5
+ activeFilter: SidebarConversationFilter;
6
+ onActiveFilterChange: (filter: SidebarConversationFilter) => void;
7
+ onOpenCreate: () => void;
8
+ }
9
+ /** Sidebar search input, "Tạo cuộc trò chuyện" entry point, and the Tất cả/Chưa đọc/Tích
10
+ * xanh filter row. Controlled — the actual conversation list it filters lives in the
11
+ * sibling sidbar-conversation-list component, driven from the same state one level up. */
12
+ export declare function SidebarFilter({ searchTerm, onSearchTermChange, activeFilter, onActiveFilterChange, onOpenCreate, }: SidebarFilterProps): import("react/jsx-runtime").JSX.Element;
13
+ export {};
@@ -0,0 +1,4 @@
1
+ /** Current-user identity block at the top of the sidebar: avatar, name, work info, and
2
+ * the entry point into the user's own profile modal. Fully self-contained — reads the
3
+ * authenticated user straight from the auth store, no props needed. */
4
+ export declare function SidebarHeaderInfor(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ interface BannerCarouselProps {
2
+ images: string[];
3
+ className?: string;
4
+ }
5
+ /** Zalo-style auto-sliding banner carousel — fixed interval, prev/next arrows, and dot
6
+ * indicators (click a dot to jump directly) — used on the "no conversation selected"
7
+ * default screen. */
8
+ export declare function BannerCarousel({ images, className }: BannerCarouselProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1,19 @@
1
+ import { ConversationMember } from '../../utils/chat';
2
+ interface ConversationAvatarProps {
3
+ /** Resolved avatar photo URL (absolute); when absent the initials fallback is shown. */
4
+ avatarUrl?: string | null;
5
+ /** Name used for the initials fallback when there is no photo. */
6
+ name: string;
7
+ isGroup: boolean;
8
+ /** Group members used to build the composite avatar; empty for direct chats. */
9
+ members?: ConversationMember[];
10
+ /** Total member count for the group composite; falls back to members.length. */
11
+ memberCount?: number;
12
+ currentUserId?: string | null;
13
+ className?: string;
14
+ }
15
+ /** Conversation avatar: photo (group or direct) → direct-chat partner photo → initials.
16
+ * Groups without their own photo render a 2×2 composite of 3 member avatars (excluding
17
+ * self) plus a circle with the total member count, once there are 4+ members. */
18
+ export declare function ConversationAvatar({ avatarUrl, name, isGroup, members, memberCount, currentUserId, className, }: ConversationAvatarProps): import("react/jsx-runtime").JSX.Element;
19
+ export {};
@@ -0,0 +1,17 @@
1
+ import { Dayjs } from 'dayjs';
2
+ export interface DateFilterValue {
3
+ from: Dayjs | null;
4
+ to: Dayjs | null;
5
+ }
6
+ export declare const DEFAULT_DATE_FILTER: DateFilterValue;
7
+ /** Matches when `dateInput` falls within [from, to] — either bound may be unset. */
8
+ export declare function matchesDateFilter(filter: DateFilterValue, dateInput: string): boolean;
9
+ interface DateRangeFilterPillProps {
10
+ value: DateFilterValue;
11
+ onChange: (value: DateFilterValue) => void;
12
+ }
13
+ /** "Ngày gửi ⌄" filter pill: two independent single-month date pickers ("Từ ngày" /
14
+ * "Đến ngày", neither ever a future date) — not antd's combined two-month RangePicker.
15
+ * Confirmed with Hủy/Xác nhận. */
16
+ export declare function DateRangeFilterPill({ value, onChange }: DateRangeFilterPillProps): import("react/jsx-runtime").JSX.Element;
17
+ export {};
@@ -0,0 +1,11 @@
1
+ import { MouseEvent } from 'react';
2
+ interface DownloadActionProps {
3
+ url: string;
4
+ name?: string | null;
5
+ className?: string;
6
+ onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
7
+ }
8
+ /** Shared "Tải xuống" action — same download button/behavior everywhere a file or image
9
+ * can be downloaded (chat bubble, kho lưu trữ, settings media preview). */
10
+ export declare function DownloadAction({ url, name, className, onClick, }: DownloadActionProps): import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1,15 @@
1
+ export interface FilterPillOption<T extends string> {
2
+ value: T;
3
+ label: string;
4
+ }
5
+ export interface FilterPillProps<T extends string> {
6
+ label: string;
7
+ value: T;
8
+ options: Array<FilterPillOption<T>>;
9
+ onChange: (value: T) => void;
10
+ disabled?: boolean;
11
+ }
12
+ /** Small dropdown pill ("Loại ⌄", "Người gửi ⌄", "Ngày gửi ⌄", ...) — shows `label` while
13
+ * the first (default) option is selected, otherwise turns into an active chip showing the
14
+ * picked option with a clear ("x") button in place of the chevron. */
15
+ export declare function FilterPill<T extends string>({ label, value, options, onChange, disabled, }: FilterPillProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ interface ImageNotAvailableProps {
2
+ className?: string;
3
+ /** Icon only, no label — for boxes too small to fit "Không tìm thấy ảnh" (e.g. a 64px
4
+ * thumbnail rail). */
5
+ compact?: boolean;
6
+ }
7
+ /** Placeholder shown in place of an image that failed to load (e.g. a 404'd attachment) —
8
+ * icon + "Không tìm thấy ảnh" instead of the browser's bare broken-image glyph. Sized to
9
+ * fill whatever box it's given (see .image-not-available), so it drops into the same
10
+ * fixed-size frame the real `<img>` would have used. */
11
+ export declare function ImageNotAvailable({ className, compact }: ImageNotAvailableProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,13 @@
1
+ import { ImgHTMLAttributes } from 'react';
2
+ interface ImageWithFallbackProps extends ImgHTMLAttributes<HTMLImageElement> {
3
+ /** Applied to the ImageNotAvailable placeholder instead of the <img> once it fails —
4
+ * pass the same sizing class the <img> would have gotten so the placeholder fills the
5
+ * same box. */
6
+ fallbackClassName?: string;
7
+ /** Forwarded to ImageNotAvailable — icon only, no label, for boxes too small to fit it. */
8
+ fallbackCompact?: boolean;
9
+ }
10
+ /** Drop-in `<img>` replacement that swaps to the ImageNotAvailable placeholder on error
11
+ * (a 404'd attachment, most often) instead of the browser's bare broken-image glyph. */
12
+ export declare function ImageWithFallback({ fallbackClassName, fallbackCompact, onError, ...imgProps }: ImageWithFallbackProps): import("react/jsx-runtime").JSX.Element;
13
+ export {};
@@ -0,0 +1,15 @@
1
+ interface LoadMoreSentinelProps {
2
+ /** Whether a next page exists to load. */
3
+ enabled: boolean;
4
+ /** True while the next page is being fetched (shows "Đang tải..." and gates refires). */
5
+ isLoading: boolean;
6
+ onLoadMore: () => void;
7
+ }
8
+ /**
9
+ * Invisible marker at the bottom of a paginated list that triggers `onLoadMore` as soon
10
+ * as it scrolls into view. Because it uses IntersectionObserver (rooted at the scrollable
11
+ * list), it also fires immediately when a fresh page doesn't fill the list — the case a
12
+ * plain onScroll handler misses, since there is no scrollbar to produce scroll events.
13
+ */
14
+ export declare function LoadMoreSentinel({ enabled, isLoading, onLoadMore }: LoadMoreSentinelProps): import("react/jsx-runtime").JSX.Element | null;
15
+ export {};
@@ -0,0 +1,5 @@
1
+ /** Custom "reply" icon (assets/icons/quote.svg), replacing antd's RollbackOutlined
2
+ * everywhere the reply action appears. Colored like an antd icon (currentColor) and sized
3
+ * relative to it (0.8em — the source artwork reads visually heavier/bigger than antd's
4
+ * icons at a literal 1em) so it drops into the same buttons without CSS changes. */
5
+ export declare function QuoteIcon(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ interface SearchEmptyStateProps {
2
+ message: string;
3
+ className?: string;
4
+ }
5
+ /** Illustration + message shown whenever a search or filter yields zero results — shared
6
+ * across the message search panel, conversation list, member/user pickers, and archive. */
7
+ export declare function SearchEmptyState({ message, className }: SearchEmptyStateProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,5 @@
1
+ /** Custom "share/forward" icon (assets/icons/sheared.svg), replacing antd's ShareAltOutlined
2
+ * everywhere the forward/share action appears. Colored like an antd icon (currentColor) and
3
+ * sized relative to it (0.8em — the source artwork reads visually heavier/bigger than
4
+ * antd's icons at a literal 1em) so it drops into the same buttons without CSS changes. */
5
+ export declare function SharedIcon(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ interface UserAvatarProps {
2
+ /** Resolved avatar photo URL (absolute); when absent the initials fallback is shown. */
3
+ avatarUrl?: string | null;
4
+ /** Name used for the initials fallback when there is no photo. */
5
+ name: string;
6
+ className?: string;
7
+ }
8
+ /** Circular avatar: shows the user's photo when available, otherwise their initials —
9
+ * also the fallback when the photo URL 404s (e.g. a deleted file) instead of the
10
+ * browser's broken-image icon. */
11
+ export declare function UserAvatar({ avatarUrl, name, className }: UserAvatarProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,13 @@
1
+ interface UserProfileModalProps {
2
+ userId: string;
3
+ fallbackName?: string;
4
+ onClose: () => void;
5
+ /** Opens (or reuses) a direct conversation with this user. */
6
+ onStartChat?: (userId: string) => void;
7
+ }
8
+ /** Zalo-style "Thông tin tài khoản" dialog, opened from a user avatar click: avatar on
9
+ * top, then contact details (họ tên, ngày sinh, email, số điện thoại) and a second
10
+ * group with the directory info (chi nhánh, phòng ban, chức vụ). Portals to body with
11
+ * the layered mask so it stacks above the member-list modal it may be opened from. */
12
+ export declare function UserProfileModal({ userId, fallbackName, onClose, onStartChat }: UserProfileModalProps): import('react').ReactPortal;
13
+ export {};
@@ -0,0 +1,5 @@
1
+ /** Themed "verified" check (--chat-primary) with a scalloped (sawtooth) badge outline, shown next to a
2
+ * verified group's name or in the sidebar row's top-right corner. */
3
+ export declare function VerifiedBadge({ className }: {
4
+ className?: string;
5
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { Dayjs } from 'dayjs';
2
+ declare const DayjsDatePicker: import('antd/es/date-picker/generatePicker/interface').PickerComponentClass<import('antd/es/date-picker/generatePicker').PickerProps<Dayjs> & {
3
+ status?: "" | "warning" | "error" | undefined;
4
+ dropdownClassName?: string | undefined;
5
+ popupClassName?: string | undefined;
6
+ }, unknown> & {
7
+ WeekPicker: import('antd/es/date-picker/generatePicker/interface').PickerComponentClass<Omit<import('antd/es/date-picker/generatePicker').PickerDateProps<Dayjs>, "picker">, unknown>;
8
+ MonthPicker: import('antd/es/date-picker/generatePicker/interface').PickerComponentClass<Omit<import('antd/es/date-picker/generatePicker').PickerDateProps<Dayjs>, "picker">, unknown>;
9
+ YearPicker: import('antd/es/date-picker/generatePicker/interface').PickerComponentClass<Omit<import('antd/es/date-picker/generatePicker').PickerDateProps<Dayjs>, "picker">, unknown>;
10
+ RangePicker: import('antd/es/date-picker/generatePicker/interface').PickerComponentClass<import('antd/es/date-picker/generatePicker').RangePickerProps<Dayjs>, unknown>;
11
+ TimePicker: import('antd/es/date-picker/generatePicker/interface').PickerComponentClass<Omit<import('antd/es/date-picker/generatePicker').PickerTimeProps<Dayjs>, "picker">, unknown>;
12
+ QuarterPicker: import('antd/es/date-picker/generatePicker/interface').PickerComponentClass<Omit<import('antd/es/date-picker/generatePicker').PickerTimeProps<Dayjs>, "picker">, unknown>;
13
+ };
14
+ export default DayjsDatePicker;
@@ -0,0 +1,13 @@
1
+ import { FilterPillOption } from '../components/filter-pill';
2
+ export interface DirectoryFilter {
3
+ branchId: string;
4
+ departmentId: string;
5
+ branchOptions: Array<FilterPillOption<string>>;
6
+ departmentOptions: Array<FilterPillOption<string>>;
7
+ handleBranchChange: (branchId: string) => void;
8
+ setDepartmentId: (departmentId: string) => void;
9
+ }
10
+ /** Branch/department pickers shared by the user-directory surfaces (create conversation,
11
+ * add members): branch options come from the org-tree's branch-level departments (via
12
+ * the zero-UUID branch), and department options follow the selected branch. */
13
+ export declare function useDirectoryFilter(): DirectoryFilter;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Tracks which user's profile modal is open. A shared trigger point — opened from
3
+ * mention clicks, avatar clicks, member/reaction list rows, and direct-chat entry.
4
+ */
5
+ export declare function useUserProfileModal(): {
6
+ profileUserId: string | null;
7
+ openProfile: (userId: string | null) => void;
8
+ closeProfile: () => void;
9
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @deprecated Import realtime functions from `@medipha/chat-core` in new code.
3
+ * This compatibility re-export keeps the web UI's existing imports unchanged.
4
+ */
5
+ export { configureSocket, connectSocket, subscribeSocketHandlers, getSocket, emitCreateConversation, subscribeConversation, unsubscribeConversation, emitMessageSend, emitMessageReactionApply, emitMessageReactionRemove, emitMessagePin, emitMessageForward, emitConversationRead, emitTypingStart, emitTypingStop, disconnectSocket, } from '@medipha/chat-core';
6
+ export type { GetMessageReactionsQuery, MessageReactionUpdatedEvent, ReactionSummaryPayload, ReactionType, ReactionUserItem, ReactionUsersPage, SocketEmitResult, SocketHandlers, } from '@medipha/chat-core';
@@ -0,0 +1,34 @@
1
+ /** Minimal authenticated user shape; extra ERP-provided fields are preserved. */
2
+ export interface AuthUser {
3
+ userId?: string;
4
+ [key: string]: unknown;
5
+ }
6
+ interface AuthState {
7
+ user: AuthUser | null;
8
+ userId: string | null;
9
+ hasHydrated: boolean;
10
+ setUser: (user: AuthUser | null) => void;
11
+ setUserId: (userId: string | null) => void;
12
+ setHasHydrated: (hasHydrated: boolean) => void;
13
+ logout: () => void;
14
+ }
15
+ export declare const useAuthStore: import('zustand').UseBoundStore<Omit<import('zustand').StoreApi<AuthState>, "setState" | "persist"> & {
16
+ setState(partial: AuthState | Partial<AuthState> | ((state: AuthState) => AuthState | Partial<AuthState>), replace?: false | undefined): unknown;
17
+ setState(state: AuthState | ((state: AuthState) => AuthState), replace: true): unknown;
18
+ persist: {
19
+ setOptions: (options: Partial<import('zustand/middleware').PersistOptions<AuthState, {
20
+ user: AuthUser | null;
21
+ userId: string | null;
22
+ }, unknown>>) => void;
23
+ clearStorage: () => void;
24
+ rehydrate: () => Promise<void> | void;
25
+ hasHydrated: () => boolean;
26
+ onHydrate: (fn: (state: AuthState) => void) => () => void;
27
+ onFinishHydration: (fn: (state: AuthState) => void) => () => void;
28
+ getOptions: () => Partial<import('zustand/middleware').PersistOptions<AuthState, {
29
+ user: AuthUser | null;
30
+ userId: string | null;
31
+ }, unknown>>;
32
+ };
33
+ }>;
34
+ export {};
@@ -0,0 +1,8 @@
1
+ interface ConnectionState {
2
+ /** Whether the realtime socket is currently connected. Starts true (optimistic) so the
3
+ * banner doesn't flash before the socket has had a chance to connect. */
4
+ isConnected: boolean;
5
+ setConnected: (isConnected: boolean) => void;
6
+ }
7
+ export declare const useConnectionStore: import('zustand').UseBoundStore<import('zustand').StoreApi<ConnectionState>>;
8
+ export {};
@@ -0,0 +1,38 @@
1
+ import { Conversation } from '../utils/chat';
2
+ interface ConversationsState {
3
+ conversations: Conversation[];
4
+ isLoading: boolean;
5
+ error: string;
6
+ setConversations: (conversations: Conversation[]) => void;
7
+ setLoading: (isLoading: boolean) => void;
8
+ setError: (error: string) => void;
9
+ /** Adds (or repositions) a conversation that just appeared for this user — a brand-new
10
+ * chat, or one they were just added back into. Repositions by pin/recency, same as any
11
+ * other realtime list event. */
12
+ upsertConversation: (incoming: unknown, currentUserId: string | null) => void;
13
+ /** Merges a partial update into one entry in place (no repositioning) — used for
14
+ * page-driven edits (rename, avatar change) that only carry the changed fields. */
15
+ patchConversation: (conversationId: string, update: Partial<Conversation>) => void;
16
+ /** Replaces one entry with a freshly REST-fetched full detail (richer member roster than
17
+ * the list's own summary shape) — merged in place if already present (the page opening
18
+ * a conversation shouldn't bump its position in the list), appended if this is the
19
+ * first the store has heard of it (e.g. a deep link opened before the list loaded). */
20
+ setFullConversation: (conversation: Conversation) => void;
21
+ removeConversation: (conversationId: string) => void;
22
+ applyIncomingMessage: (incoming: unknown, currentUserId: string | null) => void;
23
+ applyReadMarker: (payload: unknown) => void;
24
+ applyUnreadCount: (payload: unknown) => void;
25
+ applyMessageRemoved: (payload: unknown) => void;
26
+ applyConversationUpdated: (payload: unknown) => void;
27
+ applyPinnedAt: (conversationId: string, userId: string, pinnedAt: string | null) => void;
28
+ applyConversationPinned: (payload: unknown) => void;
29
+ }
30
+ /**
31
+ * Shared conversation-summary list — the single source sidebar rows AND the page-level
32
+ * "currently open conversation" both read, instead of each independently patching its own
33
+ * copy on the same realtime events (title/avatar/verified changes, read markers, unread
34
+ * counts...). Pin ordering and per-conversation patch rules are ported unchanged from the
35
+ * sidebar's own hook, which now just wraps this store.
36
+ */
37
+ export declare const useConversationsStore: import('zustand').UseBoundStore<import('zustand').StoreApi<ConversationsState>>;
38
+ export {};
@@ -0,0 +1,14 @@
1
+ import { ChatMessage } from '../utils/chat';
2
+ interface ForwardState {
3
+ /** The message currently staged to forward — drives whether ForwardDialog is open. */
4
+ forwardSource: ChatMessage | null;
5
+ openForward: (message: ChatMessage) => void;
6
+ closeForward: () => void;
7
+ clearIfTarget: (messageId: string) => void;
8
+ }
9
+ /** Shared "Chuyển tiếp" (forward) state — triggered from message bubbles inside
10
+ * conversation-detail and from the archive's share button inside Setting, two
11
+ * independent branches with no other common ground. Either can call `openForward`
12
+ * directly; no ref/handle needed to reach across. */
13
+ export declare const useForwardStore: import('zustand').UseBoundStore<import('zustand').StoreApi<ForwardState>>;
14
+ export {};
@@ -0,0 +1,16 @@
1
+ import { ChatMessage } from '../utils/chat';
2
+ interface PinnedMessagesState {
3
+ /** Only the currently open conversation's pinned list is ever held — a stray update for
4
+ * a conversation the user has since navigated away from is dropped, not applied. */
5
+ conversationId: string | undefined;
6
+ pinnedMessages: ChatMessage[];
7
+ setForConversation: (conversationId: string | undefined, messages: ChatMessage[]) => void;
8
+ applyPinnedUpdate: (conversationId: string | undefined, message: ChatMessage) => void;
9
+ clearIfTarget: (conversationId: string | undefined, messageId: string) => void;
10
+ reset: () => void;
11
+ }
12
+ /** Shared pinned-messages state for the open conversation — read by both the pinned-bar
13
+ * (the list itself) and every message bubble (per-message pin icon), so a pin/unpin from
14
+ * either place is reflected in the other immediately, with no prop drilling between them. */
15
+ export declare const usePinnedMessagesStore: import('zustand').UseBoundStore<import('zustand').StoreApi<PinnedMessagesState>>;
16
+ export {};
@@ -0,0 +1,11 @@
1
+ interface PresenceState {
2
+ /** userId -> online, for every user presence has been reported for since connecting. */
3
+ onlineByUserId: Record<string, boolean>;
4
+ setOnline: (userId: string, isOnline: boolean) => void;
5
+ }
6
+ /** Global presence map fed by a single `presence:changed` socket subscription (wired up
7
+ * once in ChatBootstrap) — every place that needs a user's online dot (sidebar rows,
8
+ * the conversation header) reads it straight from here instead of each patching its own
9
+ * local copy of the same data. */
10
+ export declare const usePresenceStore: import('zustand').UseBoundStore<import('zustand').StoreApi<PresenceState>>;
11
+ export {};
@@ -0,0 +1,20 @@
1
+ /** The three ERP-granted permissions gating actions on a verified (tích xanh) group —
2
+ * decided by the host app's own RBAC, passed in once as ChatModule props. Stored here
3
+ * (not just in ChatRuntimeContext) so code outside the component tree — socket handlers,
4
+ * plain utility functions — can read the current value via `.getState()`, the same
5
+ * reason useAuthStore/usePresenceStore exist alongside the context. */
6
+ interface VerifiedPermissionsState {
7
+ /** Permission to add a new verified group. */
8
+ hasAddGroupVerified: boolean;
9
+ /** Permission to update a verified group: avatar, name, add members, remove members. */
10
+ hasUpdateGroupVerified: boolean;
11
+ /** Permission to delete a verified group. */
12
+ hasDeleteGroupVerified: boolean;
13
+ setVerifiedPermissions: (permissions: {
14
+ hasAddGroupVerified: boolean;
15
+ hasUpdateGroupVerified: boolean;
16
+ hasDeleteGroupVerified: boolean;
17
+ }) => void;
18
+ }
19
+ export declare const useVerifiedPermissionsStore: import('zustand').UseBoundStore<import('zustand').StoreApi<VerifiedPermissionsState>>;
20
+ export {};