movius-chats 1.3.0 → 1.3.2

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/src/index.tsx CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { FlatList, View } from 'react-native';
2
+ import { FlatList, KeyboardAvoidingView, Platform, View } from 'react-native';
3
3
  import tw from 'twrnc';
4
4
  import ChatBubble from './components/ChatBubble/ChatBubble';
5
5
  import ChatInput from './components/ChatInput/ChatInput';
@@ -7,6 +7,7 @@ import MediaViewer from './components/MediaViewer/MediaViewer';
7
7
  import { TypingIndicator } from './components/TypingComponent/TypingIndicator';
8
8
  import { AudioProvider } from './context/AudioContext';
9
9
  import { ChatProvider, useChatContext } from './context/ChatContext';
10
+ import { useKeyboardInset } from './hooks/useKeyboardInset';
10
11
  import { ChatScreenProps } from './types';
11
12
 
12
13
  const ChatScreenContent = () => {
@@ -34,11 +35,26 @@ const ChatScreenContent = () => {
34
35
  CustomFileIcon,
35
36
  CustomImagePreview,
36
37
  CustomVideoPreview,
38
+ keyboardVerticalOffset = 0,
39
+ disableKeyboardAvoiding = false,
37
40
  } = useChatContext();
38
41
 
39
- return (
40
- <View style={tw`flex-1 px-2 pb-4 gap-2 relative`}>
42
+ const keyboardInset = useKeyboardInset(
43
+ keyboardVerticalOffset,
44
+ !disableKeyboardAvoiding
45
+ );
46
+
47
+ const content = (
48
+ <View
49
+ style={[
50
+ tw`flex-1 px-2 pb-4 gap-2 relative`,
51
+ !disableKeyboardAvoiding && keyboardInset > 0
52
+ ? { paddingBottom: keyboardInset + 16 }
53
+ : undefined,
54
+ ]}
55
+ >
41
56
  <FlatList
57
+ style={tw`flex-1`}
42
58
  data={messages}
43
59
  keyExtractor={(item) => item.id}
44
60
  renderItem={({ item, index }) => (
@@ -60,6 +76,8 @@ const ChatScreenContent = () => {
60
76
  }
61
77
  showsVerticalScrollIndicator={false}
62
78
  inverted
79
+ keyboardShouldPersistTaps="handled"
80
+ keyboardDismissMode="interactive"
63
81
  />
64
82
 
65
83
  {renderCustomInput ? (
@@ -94,6 +112,20 @@ const ChatScreenContent = () => {
94
112
  />
95
113
  </View>
96
114
  );
115
+
116
+ if (disableKeyboardAvoiding) {
117
+ return <View style={tw`flex-1`}>{content}</View>;
118
+ }
119
+
120
+ return (
121
+ <KeyboardAvoidingView
122
+ style={tw`flex-1`}
123
+ behavior={Platform.OS === 'ios' ? 'padding' : undefined}
124
+ keyboardVerticalOffset={keyboardVerticalOffset}
125
+ >
126
+ {content}
127
+ </KeyboardAvoidingView>
128
+ );
97
129
  };
98
130
 
99
131
  const ChatScreen: React.FC<ChatScreenProps> = (props) => {
@@ -24,6 +24,11 @@ export interface ChatScreenProps {
24
24
  onAudioRecordStart?: () => void;
25
25
  onCameraPress?: () => void;
26
26
 
27
+ /** Extra space subtracted from keyboard height (header, tab bar, safe area). */
28
+ keyboardVerticalOffset?: number;
29
+ /** Set true if your screen already handles keyboard insets. */
30
+ disableKeyboardAvoiding?: boolean;
31
+
27
32
  // Typing indicators and input
28
33
  typingUsers?: Array<{ id: string; avatar: string; name: string }>;
29
34
  onTypingStart?: () => void;
@@ -37,6 +42,7 @@ export interface ChatScreenProps {
37
42
 
38
43
  // UI Customization
39
44
  theme?: {
45
+ fontFamily?: string;
40
46
  colors?: {
41
47
  sentMessageTailColor?: string;
42
48
  receivedMessageTailColor?: string;
@@ -47,6 +53,14 @@ export interface ChatScreenProps {
47
53
  audioPlayIconColor?: string;
48
54
  audioPauseIconColor?: string;
49
55
  videoPlayIconColor?: string;
56
+ inputTextColor?: string;
57
+ sentIconColor?: string;
58
+ deliveredIconColor?: string;
59
+ readIconColor?: string;
60
+ };
61
+ sizes?: {
62
+ /** Twrnc classes (e.g. `"h-8 w-8"`) or pixel size (e.g. `28`). */
63
+ inputIconSize?: string | number;
50
64
  };
51
65
  bubbleStyle?: {
52
66
  sent?: ViewStyle;
@@ -0,0 +1,37 @@
1
+ import { Platform, StyleProp, TextStyle, ViewStyle } from 'react-native';
2
+ import tw from 'twrnc';
3
+
4
+ const DEFAULT_INPUT_ICON_CLASS =
5
+ Platform.OS === 'ios' ? 'h-6 w-6' : 'w-6 h-6';
6
+
7
+ /** Resolves theme.sizes.inputIconSize (twrnc class string or pixel number). */
8
+ export function getInputIconStyle(
9
+ size?: string | number,
10
+ extraClass?: string
11
+ ): ViewStyle {
12
+ if (typeof size === 'number' && size > 0) {
13
+ return { width: size, height: size };
14
+ }
15
+
16
+ const sizeClass =
17
+ typeof size === 'string' && size.trim().length > 0
18
+ ? size.trim()
19
+ : DEFAULT_INPUT_ICON_CLASS;
20
+
21
+ return tw.style(sizeClass, extraClass);
22
+ }
23
+
24
+ /** Applies theme.fontFamily to any Text / ParsedText style array. */
25
+ export function withFontFamily(
26
+ style: StyleProp<TextStyle>,
27
+ fontFamily?: string
28
+ ): StyleProp<TextStyle> {
29
+ if (!fontFamily) {
30
+ return style;
31
+ }
32
+ return [style, { fontFamily }];
33
+ }
34
+
35
+ export function getFontFamilyStyle(fontFamily?: string): TextStyle | undefined {
36
+ return fontFamily ? { fontFamily } : undefined;
37
+ }