@codewithvincent/react-native-love-chat 0.1.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/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/README.md +152 -0
- package/dist/Chat.d.ts +3 -0
- package/dist/Chat.js +78 -0
- package/dist/components/Bubble.d.ts +21 -0
- package/dist/components/Bubble.js +55 -0
- package/dist/components/Composer.d.ts +14 -0
- package/dist/components/Composer.js +44 -0
- package/dist/components/FooterReplyPreview.d.ts +7 -0
- package/dist/components/FooterReplyPreview.js +130 -0
- package/dist/components/Icons.d.ts +21 -0
- package/dist/components/Icons.js +71 -0
- package/dist/components/InputToolbar.d.ts +17 -0
- package/dist/components/InputToolbar.js +110 -0
- package/dist/components/Message.d.ts +21 -0
- package/dist/components/Message.js +131 -0
- package/dist/components/MessageList.d.ts +6 -0
- package/dist/components/MessageList.js +111 -0
- package/dist/components/MessageStatus.d.ts +6 -0
- package/dist/components/MessageStatus.js +59 -0
- package/dist/components/ReactionBubble.d.ts +55 -0
- package/dist/components/ReactionBubble.js +262 -0
- package/dist/components/ReplyPreview.d.ts +7 -0
- package/dist/components/ReplyPreview.js +102 -0
- package/dist/components/UploadFooter.d.ts +4 -0
- package/dist/components/UploadFooter.js +33 -0
- package/dist/components/adapters/UniversalAudio.d.ts +8 -0
- package/dist/components/adapters/UniversalAudio.js +23 -0
- package/dist/components/adapters/UniversalBlurView.d.ts +3 -0
- package/dist/components/adapters/UniversalBlurView.js +26 -0
- package/dist/components/adapters/UniversalVideo.d.ts +8 -0
- package/dist/components/adapters/UniversalVideo.js +20 -0
- package/dist/components/media/AudioCard.d.ts +7 -0
- package/dist/components/media/AudioCard.js +187 -0
- package/dist/components/media/FileCard.d.ts +8 -0
- package/dist/components/media/FileCard.js +68 -0
- package/dist/components/media/ImageCard.d.ts +9 -0
- package/dist/components/media/ImageCard.js +76 -0
- package/dist/components/media/VideoCard.d.ts +10 -0
- package/dist/components/media/VideoCard.js +232 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +36 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.js +2 -0
- package/dist/utils/index.d.ts +14 -0
- package/dist/utils/index.js +44 -0
- package/dist/utils/theme.d.ts +77 -0
- package/dist/utils/theme.js +55 -0
- package/package.json +67 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { PartialTheme } from './utils/theme';
|
|
2
|
+
export interface IUser {
|
|
3
|
+
_id: string | number;
|
|
4
|
+
name?: string;
|
|
5
|
+
avatar?: string | number;
|
|
6
|
+
}
|
|
7
|
+
export interface IMessage {
|
|
8
|
+
_id: string | number;
|
|
9
|
+
text: string;
|
|
10
|
+
createdAt: Date | number;
|
|
11
|
+
user: IUser;
|
|
12
|
+
image?: string;
|
|
13
|
+
video?: string;
|
|
14
|
+
audio?: string;
|
|
15
|
+
system?: boolean;
|
|
16
|
+
sent?: boolean;
|
|
17
|
+
received?: boolean;
|
|
18
|
+
pending?: boolean;
|
|
19
|
+
quickReplies?: any;
|
|
20
|
+
caption?: string;
|
|
21
|
+
fileName?: string;
|
|
22
|
+
fileType?: string;
|
|
23
|
+
fileUrl?: string;
|
|
24
|
+
replyTo?: IMessage;
|
|
25
|
+
reactions?: any[];
|
|
26
|
+
status?: 'pending' | 'sent' | 'delivered' | 'read';
|
|
27
|
+
isMine?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface ChatProps {
|
|
30
|
+
messages: IMessage[];
|
|
31
|
+
user: IUser;
|
|
32
|
+
onSend: (messages: IMessage[]) => void;
|
|
33
|
+
placeholder?: string;
|
|
34
|
+
text?: string;
|
|
35
|
+
onInputTextChanged?: (text: string) => void;
|
|
36
|
+
dateFormat?: string;
|
|
37
|
+
timeFormat?: string;
|
|
38
|
+
renderBubble?: (props: any) => React.ReactNode;
|
|
39
|
+
renderInputToolbar?: (props: any) => React.ReactNode;
|
|
40
|
+
renderComposer?: (props: any) => React.ReactNode;
|
|
41
|
+
renderSend?: (props: any) => React.ReactNode;
|
|
42
|
+
renderAvatar?: (props: any) => React.ReactNode;
|
|
43
|
+
renderMessage?: (props: any) => React.ReactNode;
|
|
44
|
+
renderMessageText?: (props: any) => React.ReactNode;
|
|
45
|
+
renderMessageImage?: (props: any) => React.ReactNode;
|
|
46
|
+
renderMessageVideo?: (props: any) => React.ReactNode;
|
|
47
|
+
renderMessageAudio?: (props: any) => React.ReactNode;
|
|
48
|
+
renderFooter?: () => React.ReactNode;
|
|
49
|
+
renderChatFooter?: () => React.ReactNode;
|
|
50
|
+
renderUploadFooter?: (props: any) => React.ReactNode;
|
|
51
|
+
loadEarlier?: boolean;
|
|
52
|
+
onLoadEarlier?: () => void;
|
|
53
|
+
isLoadingEarlier?: boolean;
|
|
54
|
+
inverted?: boolean;
|
|
55
|
+
listViewProps?: any;
|
|
56
|
+
onPressActionButton?: () => void;
|
|
57
|
+
renderActions?: (props: any) => React.ReactNode;
|
|
58
|
+
textInputProps?: any;
|
|
59
|
+
minInputToolbarHeight?: number;
|
|
60
|
+
onPressAttachment?: (type: string) => void;
|
|
61
|
+
onReply?: (message: IMessage) => void;
|
|
62
|
+
onClearReply?: () => void;
|
|
63
|
+
onReaction?: (message: IMessage, reaction: string) => void;
|
|
64
|
+
onDeleteMessage?: (message: IMessage) => void;
|
|
65
|
+
onDownloadFile?: (message: IMessage) => void;
|
|
66
|
+
keyboardShouldPersistTaps?: 'always' | 'never' | 'handled';
|
|
67
|
+
isTyping?: boolean;
|
|
68
|
+
theme?: PartialTheme;
|
|
69
|
+
containerStyle?: any;
|
|
70
|
+
messagesContainerStyle?: any;
|
|
71
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const appSize: {
|
|
2
|
+
width: (percent: number) => number;
|
|
3
|
+
height: (percent: number) => number;
|
|
4
|
+
font: (size: number) => number;
|
|
5
|
+
SCREEN_WIDTH: number;
|
|
6
|
+
SCREEN_HEIGHT: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const Logger: {
|
|
9
|
+
info: (...args: any[]) => void;
|
|
10
|
+
error: (...args: any[]) => void;
|
|
11
|
+
debug: (...args: any[]) => void;
|
|
12
|
+
};
|
|
13
|
+
export declare const isSameUser: (currentMessage: any, diffMessage: any) => boolean;
|
|
14
|
+
export declare const isSameDay: (currentMessage: any, diffMessage: any) => boolean;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isSameDay = exports.isSameUser = exports.Logger = exports.appSize = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = react_native_1.Dimensions.get('window');
|
|
6
|
+
const widthPercentageToDP = (widthPercent) => {
|
|
7
|
+
const elemWidth = typeof widthPercent === "number" ? widthPercent : parseFloat(widthPercent);
|
|
8
|
+
return react_native_1.PixelRatio.roundToNearestPixel((SCREEN_WIDTH * elemWidth) / 100);
|
|
9
|
+
};
|
|
10
|
+
const heightPercentageToDP = (heightPercent) => {
|
|
11
|
+
const elemHeight = typeof heightPercent === "number" ? heightPercent : parseFloat(heightPercent);
|
|
12
|
+
return react_native_1.PixelRatio.roundToNearestPixel((SCREEN_HEIGHT * elemHeight) / 100);
|
|
13
|
+
};
|
|
14
|
+
// Layout utility similar to the original appSize
|
|
15
|
+
exports.appSize = {
|
|
16
|
+
width: (percent) => widthPercentageToDP(percent),
|
|
17
|
+
height: (percent) => heightPercentageToDP(percent),
|
|
18
|
+
font: (size) => size * (SCREEN_WIDTH / 375), // approximate scaling
|
|
19
|
+
SCREEN_WIDTH,
|
|
20
|
+
SCREEN_HEIGHT,
|
|
21
|
+
};
|
|
22
|
+
exports.Logger = {
|
|
23
|
+
info: (...args) => console.log('[Chat]', ...args),
|
|
24
|
+
error: (...args) => console.error('[Chat Error]', ...args),
|
|
25
|
+
debug: (...args) => console.debug('[Chat Debug]', ...args),
|
|
26
|
+
};
|
|
27
|
+
const isSameUser = (currentMessage, diffMessage) => {
|
|
28
|
+
return !!(diffMessage &&
|
|
29
|
+
diffMessage.user &&
|
|
30
|
+
currentMessage.user &&
|
|
31
|
+
diffMessage.user._id === currentMessage.user._id);
|
|
32
|
+
};
|
|
33
|
+
exports.isSameUser = isSameUser;
|
|
34
|
+
const isSameDay = (currentMessage, diffMessage) => {
|
|
35
|
+
if (!diffMessage || !diffMessage.createdAt) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const currentCreatedAt = new Date(currentMessage.createdAt);
|
|
39
|
+
const diffCreatedAt = new Date(diffMessage.createdAt);
|
|
40
|
+
return (currentCreatedAt.getDate() === diffCreatedAt.getDate() &&
|
|
41
|
+
currentCreatedAt.getMonth() === diffCreatedAt.getMonth() &&
|
|
42
|
+
currentCreatedAt.getFullYear() === diffCreatedAt.getFullYear());
|
|
43
|
+
};
|
|
44
|
+
exports.isSameDay = isSameDay;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const defaultTheme: {
|
|
3
|
+
colors: {
|
|
4
|
+
primary: string;
|
|
5
|
+
darkPrimary: string;
|
|
6
|
+
lightRed: string;
|
|
7
|
+
darkRed: string;
|
|
8
|
+
black: string;
|
|
9
|
+
lightBlack: string;
|
|
10
|
+
gray: string;
|
|
11
|
+
white: string;
|
|
12
|
+
darkBrown: string;
|
|
13
|
+
lightGrey: string;
|
|
14
|
+
softGray: string;
|
|
15
|
+
borderGray: string;
|
|
16
|
+
textGray: string;
|
|
17
|
+
softRed: string;
|
|
18
|
+
verySoftGray: string;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
ownMessageBubble: string;
|
|
21
|
+
otherMessageBubble: string;
|
|
22
|
+
ownMessageText: string;
|
|
23
|
+
otherMessageText: string;
|
|
24
|
+
ownFileBg: string;
|
|
25
|
+
otherFileBg: string;
|
|
26
|
+
};
|
|
27
|
+
fonts: {
|
|
28
|
+
light: string;
|
|
29
|
+
regular: string;
|
|
30
|
+
medium: string;
|
|
31
|
+
semiBold: string;
|
|
32
|
+
bold: string;
|
|
33
|
+
extraBold: string;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export type Theme = typeof defaultTheme;
|
|
37
|
+
export type PartialTheme = {
|
|
38
|
+
[K in keyof Theme]?: Partial<Theme[K]>;
|
|
39
|
+
};
|
|
40
|
+
export declare const useTheme: () => {
|
|
41
|
+
colors: {
|
|
42
|
+
primary: string;
|
|
43
|
+
darkPrimary: string;
|
|
44
|
+
lightRed: string;
|
|
45
|
+
darkRed: string;
|
|
46
|
+
black: string;
|
|
47
|
+
lightBlack: string;
|
|
48
|
+
gray: string;
|
|
49
|
+
white: string;
|
|
50
|
+
darkBrown: string;
|
|
51
|
+
lightGrey: string;
|
|
52
|
+
softGray: string;
|
|
53
|
+
borderGray: string;
|
|
54
|
+
textGray: string;
|
|
55
|
+
softRed: string;
|
|
56
|
+
verySoftGray: string;
|
|
57
|
+
timestamp: string;
|
|
58
|
+
ownMessageBubble: string;
|
|
59
|
+
otherMessageBubble: string;
|
|
60
|
+
ownMessageText: string;
|
|
61
|
+
otherMessageText: string;
|
|
62
|
+
ownFileBg: string;
|
|
63
|
+
otherFileBg: string;
|
|
64
|
+
};
|
|
65
|
+
fonts: {
|
|
66
|
+
light: string;
|
|
67
|
+
regular: string;
|
|
68
|
+
medium: string;
|
|
69
|
+
semiBold: string;
|
|
70
|
+
bold: string;
|
|
71
|
+
extraBold: string;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
export declare const ThemeProvider: ({ theme, children, }: {
|
|
75
|
+
theme?: PartialTheme;
|
|
76
|
+
children: React.ReactNode;
|
|
77
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ThemeProvider = exports.useTheme = exports.defaultTheme = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
exports.defaultTheme = {
|
|
7
|
+
colors: {
|
|
8
|
+
primary: '#e6e1e1',
|
|
9
|
+
darkPrimary: '#e3e3e4ff',
|
|
10
|
+
lightRed: '#EB5757',
|
|
11
|
+
darkRed: '#ef4136',
|
|
12
|
+
black: '#000',
|
|
13
|
+
lightBlack: '#605e5eff',
|
|
14
|
+
gray: '#999',
|
|
15
|
+
white: '#fff',
|
|
16
|
+
darkBrown: '#54392A',
|
|
17
|
+
lightGrey: '#f8f8f8',
|
|
18
|
+
softGray: '#fafafa',
|
|
19
|
+
borderGray: '#eee',
|
|
20
|
+
textGray: '#eee',
|
|
21
|
+
softRed: '#fff7f7',
|
|
22
|
+
verySoftGray: '#f9f9f9',
|
|
23
|
+
timestamp: '#8b8b8b',
|
|
24
|
+
ownMessageBubble: '#EB5757',
|
|
25
|
+
otherMessageBubble: '#f9f9f9',
|
|
26
|
+
ownMessageText: '#fff',
|
|
27
|
+
otherMessageText: '#000',
|
|
28
|
+
ownFileBg: 'rgba(0, 0, 0, 0.1)',
|
|
29
|
+
otherFileBg: 'rgba(0, 0, 0, 0.05)',
|
|
30
|
+
},
|
|
31
|
+
fonts: {
|
|
32
|
+
light: 'System',
|
|
33
|
+
regular: 'System',
|
|
34
|
+
medium: 'System',
|
|
35
|
+
semiBold: 'System',
|
|
36
|
+
bold: 'System',
|
|
37
|
+
extraBold: 'System',
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
const ThemeContext = (0, react_1.createContext)(exports.defaultTheme);
|
|
41
|
+
const useTheme = () => (0, react_1.useContext)(ThemeContext);
|
|
42
|
+
exports.useTheme = useTheme;
|
|
43
|
+
const ThemeProvider = ({ theme, children, }) => {
|
|
44
|
+
const mergedTheme = (0, react_1.useMemo)(() => {
|
|
45
|
+
if (!theme)
|
|
46
|
+
return exports.defaultTheme;
|
|
47
|
+
return {
|
|
48
|
+
...exports.defaultTheme,
|
|
49
|
+
colors: { ...exports.defaultTheme.colors, ...theme.colors },
|
|
50
|
+
fonts: { ...exports.defaultTheme.fonts, ...theme.fonts },
|
|
51
|
+
};
|
|
52
|
+
}, [theme]);
|
|
53
|
+
return ((0, jsx_runtime_1.jsx)(ThemeContext.Provider, { value: mergedTheme, children: children }));
|
|
54
|
+
};
|
|
55
|
+
exports.ThemeProvider = ThemeProvider;
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codewithvincent/react-native-love-chat",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A fully featured React Native chat UI component with replies, reactions, media, and theming.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"private": false,
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE",
|
|
13
|
+
"CHANGELOG.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc -p tsconfig.json",
|
|
17
|
+
"prepare": "npm run build",
|
|
18
|
+
"test": "jest",
|
|
19
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
20
|
+
"lint": "echo \"No lint configured\""
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"react": ">=18.0.0",
|
|
24
|
+
"react-native": ">=0.73.0",
|
|
25
|
+
"react-native-gesture-handler": ">=2.12.0",
|
|
26
|
+
"react-native-reanimated": ">=3.6.0",
|
|
27
|
+
"react-native-safe-area-context": ">=4.10.0",
|
|
28
|
+
"react-native-root-siblings": ">=4.2.1",
|
|
29
|
+
"@shopify/flash-list": ">=1.6.3",
|
|
30
|
+
"react-native-svg": ">=15.0.0"
|
|
31
|
+
},
|
|
32
|
+
"peerDependenciesMeta": {
|
|
33
|
+
"@react-native-community/blur": {
|
|
34
|
+
"optional": true
|
|
35
|
+
},
|
|
36
|
+
"expo-blur": {
|
|
37
|
+
"optional": true
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"typescript": "^5.3.3",
|
|
42
|
+
"jest": "^29.7.0",
|
|
43
|
+
"@types/jest": "^29.5.11",
|
|
44
|
+
"ts-jest": "^29.2.4",
|
|
45
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
46
|
+
"babel-jest": "^29.7.0",
|
|
47
|
+
"@babel/core": "^7.23.9",
|
|
48
|
+
"metro-react-native-babel-preset": "^0.76.8",
|
|
49
|
+
"@testing-library/react-native": "^12.4.3",
|
|
50
|
+
"react-test-renderer": "18.2.0",
|
|
51
|
+
"react-native": "0.73.6",
|
|
52
|
+
"react": "18.2.0"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "https://github.com/your-org/react-native-standalone-chat.git"
|
|
57
|
+
},
|
|
58
|
+
"keywords": [
|
|
59
|
+
"react-native",
|
|
60
|
+
"chat",
|
|
61
|
+
"ui",
|
|
62
|
+
"messages",
|
|
63
|
+
"reactions",
|
|
64
|
+
"reply",
|
|
65
|
+
"components"
|
|
66
|
+
]
|
|
67
|
+
}
|