@codingfactory/messenger-client 0.2.37 → 0.3.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.
@@ -0,0 +1,9 @@
1
+ export interface ReportPayload {
2
+ subject_urn: string;
3
+ category: string;
4
+ notes?: string;
5
+ }
6
+ export type ReportFn = (payload: ReportPayload) => Promise<void>;
7
+ export declare function setModerationProvider(fn: ReportFn): void;
8
+ export declare function resetModerationProvider(): void;
9
+ export declare function fileReport(payload: ReportPayload): Promise<void>;
@@ -0,0 +1,10 @@
1
+ export type TermFn = (key: string, params?: Record<string, unknown>) => string;
2
+ export declare function setTermsProvider(fn: TermFn): void;
3
+ export declare function resetTermsProvider(): void;
4
+ /**
5
+ * Composable-style hook matching the blowglass `useTerms()` API.
6
+ * Returns an object with a `term()` function.
7
+ */
8
+ export declare function useTerms(): {
9
+ term: TermFn;
10
+ };
@@ -0,0 +1,5 @@
1
+ export type ToastColor = 'success' | 'error' | 'info' | 'warning';
2
+ export type ToastFn = (message: string, type?: ToastColor) => void;
3
+ export declare function setToastProvider(fn: ToastFn): void;
4
+ export declare function resetToastProvider(): void;
5
+ export declare function showToast(message: string, type?: ToastColor): void;
@@ -0,0 +1,4 @@
1
+ export type GetTokenFn = () => string | null;
2
+ export declare function setTokenProvider(fn: GetTokenFn): void;
3
+ export declare function resetTokenProvider(): void;
4
+ export declare function getToken(): string | null;
@@ -0,0 +1,62 @@
1
+ export interface ChatWindowState {
2
+ conversationId: string;
3
+ minimized: boolean;
4
+ }
5
+ interface ChatWidgetState {
6
+ /** Whether the main panel (conversation list) is open */
7
+ panelOpen: boolean;
8
+ /** Open chat windows, ordered left-to-right. Max 3 on desktop. */
9
+ openWindows: ChatWindowState[];
10
+ /** Dynamic max windows based on viewport (1-3). */
11
+ maxWindows: number;
12
+ }
13
+ export declare const useChatWidgetStore: import("pinia").StoreDefinition<"chatWidget", ChatWidgetState, {
14
+ isWindowOpen: (state: {
15
+ panelOpen: boolean;
16
+ openWindows: {
17
+ conversationId: string;
18
+ minimized: boolean;
19
+ }[];
20
+ maxWindows: number;
21
+ } & import("pinia").PiniaCustomStateProperties<ChatWidgetState>) => (conversationId: string) => boolean;
22
+ getWindow: (state: {
23
+ panelOpen: boolean;
24
+ openWindows: {
25
+ conversationId: string;
26
+ minimized: boolean;
27
+ }[];
28
+ maxWindows: number;
29
+ } & import("pinia").PiniaCustomStateProperties<ChatWidgetState>) => (conversationId: string) => ChatWindowState | undefined;
30
+ expandedWindows: (state: {
31
+ panelOpen: boolean;
32
+ openWindows: {
33
+ conversationId: string;
34
+ minimized: boolean;
35
+ }[];
36
+ maxWindows: number;
37
+ } & import("pinia").PiniaCustomStateProperties<ChatWidgetState>) => ChatWindowState[];
38
+ minimizedWindows: (state: {
39
+ panelOpen: boolean;
40
+ openWindows: {
41
+ conversationId: string;
42
+ minimized: boolean;
43
+ }[];
44
+ maxWindows: number;
45
+ } & import("pinia").PiniaCustomStateProperties<ChatWidgetState>) => ChatWindowState[];
46
+ }, {
47
+ togglePanel(): void;
48
+ openPanel(): void;
49
+ closePanel(): void;
50
+ setMaxWindows(maxWindows: number): void;
51
+ /**
52
+ * Open a conversation in its own chat window.
53
+ * If already open, bring it to focus (un-minimize).
54
+ * If max windows reached, close the oldest one.
55
+ */
56
+ openWindow(conversationId: string): void;
57
+ closeWindow(conversationId: string): void;
58
+ minimizeWindow(conversationId: string): void;
59
+ toggleMinimize(conversationId: string): void;
60
+ closeAllWindows(): void;
61
+ }>;
62
+ export {};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Format a message body for safe HTML rendering.
3
+ * Escapes HTML, converts newlines to <br>, and auto-links URLs.
4
+ */
5
+ export declare function formatMessageBody(body: string): string;
6
+ /**
7
+ * Check if text contains only emoji characters (no regular text).
8
+ */
9
+ export declare function isEmojiOnly(text: string): boolean;
@@ -0,0 +1,8 @@
1
+ import type { Attachment } from '../stores/messaging';
2
+ export type NormalizeMediaUrlFn = (url: string | undefined) => string | undefined;
3
+ export type ResolveVideoPlaybackUrlFn = (attachment: Attachment) => string | undefined;
4
+ export declare function setNormalizeMediaUrl(fn: NormalizeMediaUrlFn): void;
5
+ export declare function setResolveVideoPlaybackUrl(fn: ResolveVideoPlaybackUrlFn): void;
6
+ export declare function resetMediaUrlProviders(): void;
7
+ export declare function normalizeMediaUrl(url: string | undefined): string | undefined;
8
+ export declare function resolveMessageVideoPlaybackUrl(attachment: Attachment): string | undefined;
@@ -0,0 +1,4 @@
1
+ import type { Message } from '../stores/messaging';
2
+ export declare function isSameMessageDay(previousMessage: Message, currentMessage: Message): boolean;
3
+ export declare function shouldShowDaySeparatorForIndex(messages: Message[], index: number): boolean;
4
+ export declare function formatMessageDayLabel(message: Message): string;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Calculates the scrollTop needed to center a message inside the scroll container.
3
+ * The result is clamped to [0, maxScrollTop].
4
+ */
5
+ export declare const calculateCenteredScrollTop: (containerRect: DOMRect, messageRect: DOMRect, currentScrollTop: number, maxScrollTop: number) => number;
6
+ type ScrollableElement = {
7
+ clientHeight?: number;
8
+ scrollHeight?: number;
9
+ scrollTop: number;
10
+ scrollTo?: (options: ScrollToOptions) => void;
11
+ };
12
+ /**
13
+ * Keeps the current viewport anchored when older messages are prepended above it.
14
+ */
15
+ export declare const calculateAnchoredPrependScrollTop: (previousScrollHeight: number, previousScrollTop: number, nextScrollHeight: number) => number;
16
+ /**
17
+ * Returns the current distance between the viewport and the bottom of the scrollable area.
18
+ */
19
+ export declare const getDistanceFromBottom: (element: ScrollableElement) => number;
20
+ /**
21
+ * Reports whether the viewport is close enough to the bottom to be treated as "sticky".
22
+ */
23
+ export declare const isScrollNearBottom: (element: ScrollableElement, thresholdPx?: number) => boolean;
24
+ /**
25
+ * Scrolls a container to `top` with smooth behavior when possible.
26
+ * Falls back to setting `scrollTop` directly if smooth scrolling no-ops.
27
+ */
28
+ export declare const scrollElementTo: (element: ScrollableElement, top: number, fallbackDelayMs?: number, behavior?: ScrollBehavior) => void;
29
+ export {};
@@ -0,0 +1,4 @@
1
+ export declare const getSavedScrollTop: (key: string) => number;
2
+ export declare const hasSavedScrollTop: (key: string) => boolean;
3
+ export declare const setSavedScrollTop: (key: string, scrollTop: number) => void;
4
+ export declare const clearSavedScrollTop: (key: string) => void;
@@ -0,0 +1,2 @@
1
+ import type { Conversation, Message } from '../stores/messaging';
2
+ export declare const resolveFirstUnreadMessageId: (conversation: Conversation | undefined, messages: Message[], currentUserId?: string) => string | null;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@codingfactory/messenger-client",
3
- "version": "0.2.37",
4
- "description": "Shared messaging frontend state, API helpers, and realtime composables.",
3
+ "version": "0.3.0",
4
+ "description": "Shared messaging frontend: UI components, state management, API helpers, and realtime composables.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -25,21 +25,29 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "axios": "^1.13.6",
28
- "ionicons": "^8.0.13",
29
28
  "laravel-echo": "^2.2.0",
30
29
  "pusher-js": "^8.4.0"
31
30
  },
32
31
  "peerDependencies": {
33
32
  "pinia": "^3.0.0",
34
33
  "vue": "^3.5.0",
35
- "vue-router": "^4.5.0 || ^5.0.0"
34
+ "vue-router": "^4.5.0 || ^5.0.0",
35
+ "date-fns": "^4.0.0"
36
+ },
37
+ "peerDependenciesMeta": {
38
+ "date-fns": { "optional": true },
39
+ "@ionic/vue": { "optional": true }
36
40
  },
37
41
  "devDependencies": {
38
42
  "@eslint/js": "^10.0.1",
43
+ "@ionic/vue": "^8.8.1",
39
44
  "@types/node": "^25.3.5",
45
+ "@vitejs/plugin-vue": "^6.0.5",
40
46
  "@vue/test-utils": "^2.4.6",
47
+ "date-fns": "^4.1.0",
41
48
  "eslint": "^10.0.3",
42
49
  "globals": "^17.4.0",
50
+ "ionicons": "^8.0.13",
43
51
  "jsdom": "^28.1.0",
44
52
  "pinia": "^3.0.4",
45
53
  "typescript": "^5.9.3",