@planningcenter/chat-react-native 1.3.0 → 1.3.1-rc.1
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 +16 -0
- package/build/components/conversations.d.ts.map +1 -1
- package/build/components/conversations.js +32 -4
- package/build/components/conversations.js.map +1 -1
- package/build/components/display/image.d.ts +19 -0
- package/build/components/display/image.d.ts.map +1 -0
- package/build/components/display/image.js +46 -0
- package/build/components/display/image.js.map +1 -0
- package/build/components/display/index.d.ts +3 -0
- package/build/components/display/index.d.ts.map +1 -0
- package/build/components/display/index.js +3 -0
- package/build/components/display/index.js.map +1 -0
- package/build/components/display/spinner.d.ts +10 -0
- package/build/components/display/spinner.d.ts.map +1 -0
- package/build/components/display/spinner.js +94 -0
- package/build/components/display/spinner.js.map +1 -0
- package/build/hooks/index.d.ts +3 -0
- package/build/hooks/index.d.ts.map +1 -0
- package/build/hooks/index.js +3 -0
- package/build/hooks/index.js.map +1 -0
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/conversations.tsx +38 -4
- package/src/components/display/image.tsx +91 -0
- package/src/components/display/index.ts +2 -0
- package/src/components/display/spinner.tsx +120 -0
- package/src/hooks/index.ts +2 -0
- package/src/index.tsx +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.3.1-rc.1](https://github.com/planningcenter/chat-js/compare/v1.3.0...v1.3.1-rc.1) (2025-02-13)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @planningcenter/chat-react-native
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [1.3.1-rc.0](https://github.com/planningcenter/chat-js/compare/v1.3.0...v1.3.1-rc.0) (2025-02-12)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @planningcenter/chat-react-native
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
## [1.3.0](https://github.com/planningcenter/chat-js/compare/v1.2.0...v1.3.0) (2025-02-12)
|
|
7
23
|
|
|
8
24
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../src/components/conversations.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA+B,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../src/components/conversations.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA+B,MAAM,OAAO,CAAA;AAcnD,wBAAgB,aAAa,6BAgB5B"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { useNavigation } from '@react-navigation/native';
|
|
2
2
|
import { QueryErrorResetBoundary, useSuspenseQuery } from '@tanstack/react-query';
|
|
3
3
|
import React, { Suspense, useContext } from 'react';
|
|
4
|
-
import { FlatList, Pressable, StyleSheet, Text } from 'react-native';
|
|
4
|
+
import { FlatList, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
5
5
|
import { ChatContext } from '../contexts/chat_context';
|
|
6
|
-
import { useTheme } from '../hooks/use_theme';
|
|
7
6
|
import ErrorBoundary from './error_boundary';
|
|
7
|
+
import { useTheme } from '../hooks';
|
|
8
|
+
import { Spinner, Image } from './display';
|
|
8
9
|
export function Conversations() {
|
|
9
10
|
const { token } = useContext(ChatContext);
|
|
10
11
|
if (!token)
|
|
@@ -23,16 +24,43 @@ const Loaded = () => {
|
|
|
23
24
|
queryKey: ['/chat/v2/me/conversations'],
|
|
24
25
|
});
|
|
25
26
|
const navigation = useNavigation();
|
|
26
|
-
return (<FlatList data={conversations?.data} contentContainerStyle={styles.container} ListEmptyComponent={<Text>No conversations found</Text>} ListHeaderComponent={<
|
|
27
|
+
return (<FlatList data={conversations?.data} contentContainerStyle={styles.container} style={styles.scrollView} ListEmptyComponent={<Text>No conversations found</Text>} ListHeaderComponent={<View style={styles.column}>
|
|
28
|
+
<Text style={styles.foo}>Display Components</Text>
|
|
29
|
+
<View style={[styles.row, styles.spinnerContainer]}>
|
|
30
|
+
<Spinner size={24}/>
|
|
31
|
+
</View>
|
|
32
|
+
<View style={styles.row}>
|
|
33
|
+
<Image source={{ uri: 'https://broken.url' }} style={styles.image}/>
|
|
34
|
+
<Image source={{
|
|
35
|
+
uri: 'https://picsum.photos/seed/picsum/200',
|
|
36
|
+
}} style={styles.image}/>
|
|
37
|
+
</View>
|
|
38
|
+
<Text style={styles.foo}>Conversations</Text>
|
|
39
|
+
</View>} renderItem={({ item }) => (<Pressable onPress={() => navigation.navigate('Settings')}>
|
|
27
40
|
<Text style={styles.listItem}>{item.attributes.title}</Text>
|
|
28
41
|
</Pressable>)}/>);
|
|
29
42
|
};
|
|
30
43
|
const useStyles = () => {
|
|
31
44
|
const { colors } = useTheme();
|
|
32
45
|
return StyleSheet.create({
|
|
33
|
-
|
|
46
|
+
scrollView: { flex: 1, backgroundColor: colors.fillColorNeutral090 },
|
|
47
|
+
container: { gap: 8, padding: 16 },
|
|
34
48
|
foo: { fontSize: 24, color: colors.testColor },
|
|
35
49
|
listItem: { color: colors.fillColorNeutral020 },
|
|
50
|
+
row: {
|
|
51
|
+
gap: 16,
|
|
52
|
+
flexDirection: 'row',
|
|
53
|
+
alignItems: 'center',
|
|
54
|
+
justifyContent: 'center',
|
|
55
|
+
},
|
|
56
|
+
column: { gap: 16 },
|
|
57
|
+
spinnerContainer: {
|
|
58
|
+
height: 20,
|
|
59
|
+
},
|
|
60
|
+
image: {
|
|
61
|
+
width: 100,
|
|
62
|
+
height: 100,
|
|
63
|
+
},
|
|
36
64
|
});
|
|
37
65
|
};
|
|
38
66
|
//# sourceMappingURL=conversations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations.js","sourceRoot":"","sources":["../../src/components/conversations.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACjF,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"conversations.js","sourceRoot":"","sources":["../../src/components/conversations.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useNavigation } from '@react-navigation/native'\nimport { QueryErrorResetBoundary, useSuspenseQuery } from '@tanstack/react-query'\nimport React, { Suspense, useContext } from 'react'\nimport { FlatList, Pressable, StyleSheet, Text, View } from 'react-native'\nimport { ChatContext } from '../contexts/chat_context'\nimport { ConversationRecord } from '../types'\nimport ErrorBoundary from './error_boundary'\nimport { useTheme } from '../hooks'\nimport { Spinner, Image } from './display'\n\ntype ConversationsResponse = {\n data: ConversationRecord[]\n links: Record<string, string>\n meta: Record<string, string>\n}\n\nexport function Conversations() {\n const { token } = useContext(ChatContext)\n\n if (!token) return null\n\n return (\n <QueryErrorResetBoundary>\n {({ reset }) => (\n <ErrorBoundary onReset={reset}>\n <Suspense fallback={<Text>loading...</Text>}>\n <Loaded />\n </Suspense>\n </ErrorBoundary>\n )}\n </QueryErrorResetBoundary>\n )\n}\n\nconst Loaded = () => {\n const styles = useStyles()\n const { data: conversations } = useSuspenseQuery<ConversationsResponse>({\n queryKey: ['/chat/v2/me/conversations'],\n })\n const navigation = useNavigation()\n\n return (\n <FlatList\n data={conversations?.data}\n contentContainerStyle={styles.container}\n style={styles.scrollView}\n ListEmptyComponent={<Text>No conversations found</Text>}\n ListHeaderComponent={\n <View style={styles.column}>\n <Text style={styles.foo}>Display Components</Text>\n <View style={[styles.row, styles.spinnerContainer]}>\n <Spinner size={24} />\n </View>\n <View style={styles.row}>\n <Image source={{ uri: 'https://broken.url' }} style={styles.image} />\n <Image\n source={{\n uri: 'https://picsum.photos/seed/picsum/200',\n }}\n style={styles.image}\n />\n </View>\n <Text style={styles.foo}>Conversations</Text>\n </View>\n }\n renderItem={({ item }) => (\n <Pressable onPress={() => navigation.navigate('Settings')}>\n <Text style={styles.listItem}>{item.attributes.title}</Text>\n </Pressable>\n )}\n />\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n scrollView: { flex: 1, backgroundColor: colors.fillColorNeutral090 },\n container: { gap: 8, padding: 16 },\n foo: { fontSize: 24, color: colors.testColor },\n listItem: { color: colors.fillColorNeutral020 },\n row: {\n gap: 16,\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n },\n column: { gap: 16 },\n spinnerContainer: {\n height: 20,\n },\n image: {\n width: 100,\n height: 100,\n },\n })\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ImageProps as RNImageProps, ViewStyle } from 'react-native';
|
|
3
|
+
interface ImageProps extends RNImageProps {
|
|
4
|
+
/**
|
|
5
|
+
* Should the image show the loading indicator by default.
|
|
6
|
+
*/
|
|
7
|
+
defaultLoading?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Size of the loading spinner.
|
|
10
|
+
*/
|
|
11
|
+
loaderSize?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Style object for the preload background.
|
|
14
|
+
*/
|
|
15
|
+
loadingBackgroundStyles?: ViewStyle;
|
|
16
|
+
}
|
|
17
|
+
export declare function Image({ source, onLoad, defaultLoading, loaderSize, loadingBackgroundStyles, style, ...restProps }: ImageProps): React.JSX.Element;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/components/display/image.tsx"],"names":[],"mappings":"AACA,OAAO,KAAmB,MAAM,OAAO,CAAA;AACvC,OAAO,EAIL,UAAU,IAAI,YAAY,EAC1B,SAAS,EACV,MAAM,cAAc,CAAA;AAIrB,UAAU,UAAW,SAAQ,YAAY;IACvC;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;OAEG;IACH,uBAAuB,CAAC,EAAE,SAAS,CAAA;CACpC;AAED,wBAAgB,KAAK,CAAC,EACpB,MAAM,EACN,MAAa,EACb,cAAqB,EACrB,UAAe,EACf,uBAAuB,EACvB,KAAK,EACL,GAAG,SAAS,EACb,EAAE,UAAU,qBAuCZ"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { noop } from 'lodash';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import { Image as ReactNativeImage, StyleSheet, View, } from 'react-native';
|
|
4
|
+
import { useTheme } from '../../hooks';
|
|
5
|
+
import { Spinner } from './spinner';
|
|
6
|
+
export function Image({ source, onLoad = noop, defaultLoading = true, loaderSize = 24, loadingBackgroundStyles, style, ...restProps }) {
|
|
7
|
+
const [loading, setLoading] = useState(defaultLoading);
|
|
8
|
+
const styles = useStyles();
|
|
9
|
+
const imageStyles = StyleSheet.flatten(style);
|
|
10
|
+
const { width = '100%', height = '100%', borderRadius = 0 } = imageStyles || {};
|
|
11
|
+
const handleOnLoad = (event) => {
|
|
12
|
+
setLoading(false);
|
|
13
|
+
onLoad?.(event);
|
|
14
|
+
};
|
|
15
|
+
return (<View>
|
|
16
|
+
<ReactNativeImage style={[styles.image, imageStyles]} onLoad={handleOnLoad} source={source} {...restProps}/>
|
|
17
|
+
{loading && (<View style={[
|
|
18
|
+
{
|
|
19
|
+
...styles.loadingBackground,
|
|
20
|
+
...loadingBackgroundStyles,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
borderRadius: borderRadius,
|
|
24
|
+
width: width,
|
|
25
|
+
height: height,
|
|
26
|
+
},
|
|
27
|
+
]}>
|
|
28
|
+
<Spinner size={loaderSize}/>
|
|
29
|
+
</View>)}
|
|
30
|
+
</View>);
|
|
31
|
+
}
|
|
32
|
+
const useStyles = () => {
|
|
33
|
+
const { colors } = useTheme();
|
|
34
|
+
return StyleSheet.create({
|
|
35
|
+
loadingBackground: {
|
|
36
|
+
position: 'absolute',
|
|
37
|
+
top: 0,
|
|
38
|
+
left: 0,
|
|
39
|
+
backgroundColor: colors.fillColorNeutral070,
|
|
40
|
+
},
|
|
41
|
+
image: {
|
|
42
|
+
backgroundColor: 'transparent',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../../src/components/display/image.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACvC,OAAO,EACL,KAAK,IAAI,gBAAgB,EACzB,UAAU,EACV,IAAI,GAGL,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAiBnC,MAAM,UAAU,KAAK,CAAC,EACpB,MAAM,EACN,MAAM,GAAG,IAAI,EACb,cAAc,GAAG,IAAI,EACrB,UAAU,GAAG,EAAE,EACf,uBAAuB,EACvB,KAAK,EACL,GAAG,SAAS,EACD;IACX,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAA;IACtD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC7C,MAAM,EAAE,KAAK,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,YAAY,GAAG,CAAC,EAAE,GAAG,WAAW,IAAI,EAAE,CAAA;IAE/E,MAAM,YAAY,GAAG,CAAC,KAAU,EAAE,EAAE;QAClC,UAAU,CAAC,KAAK,CAAC,CAAA;QACjB,MAAM,EAAE,CAAC,KAAK,CAAC,CAAA;IACjB,CAAC,CAAA;IAED,OAAO,CACL,CAAC,IAAI,CACH;MAAA,CAAC,gBAAgB,CACf,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CACnC,MAAM,CAAC,CAAC,YAAY,CAAC,CACrB,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,IAAI,SAAS,CAAC,EAEhB;MAAA,CAAC,OAAO,IAAI,CACV,CAAC,IAAI,CACH,KAAK,CAAC,CAAC;gBACL;oBACE,GAAG,MAAM,CAAC,iBAAiB;oBAC3B,GAAG,uBAAuB;iBAC3B;gBACD;oBACE,YAAY,EAAE,YAAY;oBAC1B,KAAK,EAAE,KAAK;oBACZ,MAAM,EAAE,MAAM;iBACf;aACF,CAAC,CAEF;UAAA,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,EAC5B;QAAA,EAAE,IAAI,CAAC,CACR,CACH;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE7B,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,iBAAiB,EAAE;YACjB,QAAQ,EAAE,UAAU;YACpB,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,CAAC;YACP,eAAe,EAAE,MAAM,CAAC,mBAAmB;SAC5C;QACD,KAAK,EAAE;YACL,eAAe,EAAE,aAAa;SAC/B;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { noop } from 'lodash'\nimport React, { useState } from 'react'\nimport {\n Image as ReactNativeImage,\n StyleSheet,\n View,\n ImageProps as RNImageProps,\n ViewStyle,\n} from 'react-native'\nimport { useTheme } from '../../hooks'\nimport { Spinner } from './spinner'\n\ninterface ImageProps extends RNImageProps {\n /**\n * Should the image show the loading indicator by default.\n */\n defaultLoading?: boolean\n /**\n * Size of the loading spinner.\n */\n loaderSize?: number\n /**\n * Style object for the preload background.\n */\n loadingBackgroundStyles?: ViewStyle\n}\n\nexport function Image({\n source,\n onLoad = noop,\n defaultLoading = true,\n loaderSize = 24,\n loadingBackgroundStyles,\n style,\n ...restProps\n}: ImageProps) {\n const [loading, setLoading] = useState(defaultLoading)\n const styles = useStyles()\n\n const imageStyles = StyleSheet.flatten(style)\n const { width = '100%', height = '100%', borderRadius = 0 } = imageStyles || {}\n\n const handleOnLoad = (event: any) => {\n setLoading(false)\n onLoad?.(event)\n }\n\n return (\n <View>\n <ReactNativeImage\n style={[styles.image, imageStyles]}\n onLoad={handleOnLoad}\n source={source}\n {...restProps}\n />\n {loading && (\n <View\n style={[\n {\n ...styles.loadingBackground,\n ...loadingBackgroundStyles,\n },\n {\n borderRadius: borderRadius,\n width: width,\n height: height,\n },\n ]}\n >\n <Spinner size={loaderSize} />\n </View>\n )}\n </View>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n loadingBackground: {\n position: 'absolute',\n top: 0,\n left: 0,\n backgroundColor: colors.fillColorNeutral070,\n },\n image: {\n backgroundColor: 'transparent',\n },\n })\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/display/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/display/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA","sourcesContent":["export { Spinner } from './spinner'\nexport { Image } from './image'\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../../src/components/display/spinner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAIhD,UAAU,YAAY;IACpB;;SAEK;IACL,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,OAAO,CAAC,EAAE,IAAS,EAAE,EAAE,YAAY,qBAsElD"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { Animated, Easing, StyleSheet, View } from 'react-native';
|
|
3
|
+
import { useTheme } from '../../hooks';
|
|
4
|
+
export function Spinner({ size = 20 }) {
|
|
5
|
+
const rotation = useRef(new Animated.Value(0)).current;
|
|
6
|
+
const styles = useStyles();
|
|
7
|
+
const animation = Animated.loop(Animated.timing(rotation, {
|
|
8
|
+
toValue: 1,
|
|
9
|
+
duration: 1000,
|
|
10
|
+
easing: Easing.linear,
|
|
11
|
+
useNativeDriver: true,
|
|
12
|
+
}));
|
|
13
|
+
const rotateValue = rotation.interpolate({
|
|
14
|
+
inputRange: [0, 1],
|
|
15
|
+
outputRange: ['0deg', '360deg'],
|
|
16
|
+
});
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
animation.start();
|
|
19
|
+
return () => animation.stop();
|
|
20
|
+
}, [animation]);
|
|
21
|
+
useEffect(() => () => rotation.setValue(0), [rotation]);
|
|
22
|
+
return (<View style={styles.container}>
|
|
23
|
+
<Animated.View style={{
|
|
24
|
+
width: size,
|
|
25
|
+
height: size,
|
|
26
|
+
borderRadius: size / 2,
|
|
27
|
+
transform: [{ rotate: rotateValue }],
|
|
28
|
+
}}>
|
|
29
|
+
<View style={[
|
|
30
|
+
styles.clipping,
|
|
31
|
+
{
|
|
32
|
+
width: size / 2,
|
|
33
|
+
height: size / 2,
|
|
34
|
+
},
|
|
35
|
+
]}>
|
|
36
|
+
<View style={[
|
|
37
|
+
styles.circle,
|
|
38
|
+
styles.spinner,
|
|
39
|
+
{
|
|
40
|
+
width: size,
|
|
41
|
+
height: size,
|
|
42
|
+
borderRadius: size / 2,
|
|
43
|
+
},
|
|
44
|
+
]}/>
|
|
45
|
+
</View>
|
|
46
|
+
<View style={[
|
|
47
|
+
styles.circle,
|
|
48
|
+
styles.track,
|
|
49
|
+
{
|
|
50
|
+
width: size,
|
|
51
|
+
height: size,
|
|
52
|
+
borderRadius: size / 2,
|
|
53
|
+
},
|
|
54
|
+
]}/>
|
|
55
|
+
</Animated.View>
|
|
56
|
+
</View>);
|
|
57
|
+
}
|
|
58
|
+
const useStyles = () => {
|
|
59
|
+
const { colors } = useTheme();
|
|
60
|
+
return StyleSheet.create({
|
|
61
|
+
container: {
|
|
62
|
+
width: '100%',
|
|
63
|
+
height: '100%',
|
|
64
|
+
position: 'absolute',
|
|
65
|
+
top: 0,
|
|
66
|
+
left: 0,
|
|
67
|
+
zIndex: 200,
|
|
68
|
+
justifyContent: 'center',
|
|
69
|
+
alignItems: 'center',
|
|
70
|
+
opacity: 0.7,
|
|
71
|
+
},
|
|
72
|
+
circle: {
|
|
73
|
+
borderStyle: 'solid',
|
|
74
|
+
borderWidth: 3,
|
|
75
|
+
},
|
|
76
|
+
spinner: {
|
|
77
|
+
position: 'absolute',
|
|
78
|
+
top: 0,
|
|
79
|
+
left: 0,
|
|
80
|
+
borderColor: colors.fillColorNeutral020,
|
|
81
|
+
},
|
|
82
|
+
track: {
|
|
83
|
+
borderColor: colors.fillColorNeutral050Base,
|
|
84
|
+
},
|
|
85
|
+
clipping: {
|
|
86
|
+
position: 'absolute',
|
|
87
|
+
top: 0,
|
|
88
|
+
left: 0,
|
|
89
|
+
overflow: 'hidden',
|
|
90
|
+
zIndex: 200,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../../src/components/display/spinner.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useRef } from 'react'\nimport { Animated, Easing, StyleSheet, View } from 'react-native'\nimport { useTheme } from '../../hooks'\n\ninterface SpinnerProps {\n /**\n * Size of the spinner in px\n * */\n size?: number\n}\n\nexport function Spinner({ size = 20 }: SpinnerProps) {\n const rotation = useRef(new Animated.Value(0)).current\n const styles = useStyles()\n\n const animation = Animated.loop(\n Animated.timing(rotation, {\n toValue: 1,\n duration: 1000,\n easing: Easing.linear,\n useNativeDriver: true,\n })\n )\n\n const rotateValue = rotation.interpolate({\n inputRange: [0, 1],\n outputRange: ['0deg', '360deg'],\n })\n\n useEffect(() => {\n animation.start()\n return () => animation.stop()\n }, [animation])\n\n useEffect(() => () => rotation.setValue(0), [rotation])\n\n return (\n <View style={styles.container}>\n <Animated.View\n style={{\n width: size,\n height: size,\n borderRadius: size / 2,\n transform: [{ rotate: rotateValue }],\n }}\n >\n <View\n style={[\n styles.clipping,\n {\n width: size / 2,\n height: size / 2,\n },\n ]}\n >\n <View\n style={[\n styles.circle,\n styles.spinner,\n {\n width: size,\n height: size,\n borderRadius: size / 2,\n },\n ]}\n />\n </View>\n <View\n style={[\n styles.circle,\n styles.track,\n {\n width: size,\n height: size,\n borderRadius: size / 2,\n },\n ]}\n />\n </Animated.View>\n </View>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n container: {\n width: '100%',\n height: '100%',\n position: 'absolute',\n top: 0,\n left: 0,\n zIndex: 200,\n justifyContent: 'center',\n alignItems: 'center',\n opacity: 0.7,\n },\n circle: {\n borderStyle: 'solid',\n borderWidth: 3,\n },\n spinner: {\n position: 'absolute',\n top: 0,\n left: 0,\n borderColor: colors.fillColorNeutral020,\n },\n track: {\n borderColor: colors.fillColorNeutral050Base,\n },\n clipping: {\n position: 'absolute',\n top: 0,\n left: 0,\n overflow: 'hidden',\n zIndex: 200,\n },\n })\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA","sourcesContent":["export { useCreateChatTheme } from './use_create_chat_theme'\nexport { useTheme } from './use_theme'\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Conversations } from './components/conversations';
|
|
2
2
|
import { ChatContext, ChatProvider } from './contexts/chat_context';
|
|
3
|
-
import { useCreateChatTheme } from './hooks
|
|
3
|
+
import { useCreateChatTheme } from './hooks';
|
|
4
4
|
import { OAuthToken } from './types';
|
|
5
5
|
import { baseUrlMap, uploadUrlMap } from './utils/session';
|
|
6
6
|
import { TemporaryDefaultColorsType } from './utils/theme';
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAA;AAE1D,OAAO,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,UAAU,EACV,0BAA0B,EAC1B,YAAY,EACZ,kBAAkB,GACnB,CAAA"}
|
package/build/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Conversations } from './components/conversations';
|
|
2
2
|
import { ChatContext, ChatProvider } from './contexts/chat_context';
|
|
3
|
-
import { useCreateChatTheme } from './hooks
|
|
3
|
+
import { useCreateChatTheme } from './hooks';
|
|
4
4
|
import { baseUrlMap, uploadUrlMap } from './utils/session';
|
|
5
5
|
export { baseUrlMap, ChatContext, ChatProvider, Conversations, uploadUrlMap, useCreateChatTheme, };
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAE5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAG1D,OAAO,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EAGb,YAAY,EACZ,kBAAkB,GACnB,CAAA","sourcesContent":["import { Conversations } from './components/conversations'\nimport { ChatContext, ChatProvider } from './contexts/chat_context'\nimport { useCreateChatTheme } from './hooks'\nimport { OAuthToken } from './types'\nimport { baseUrlMap, uploadUrlMap } from './utils/session'\nimport { TemporaryDefaultColorsType } from './utils/theme'\n\nexport {\n baseUrlMap,\n ChatContext,\n ChatProvider,\n Conversations,\n OAuthToken,\n TemporaryDefaultColorsType,\n uploadUrlMap,\n useCreateChatTheme,\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1-rc.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"prettier": "^3.4.2",
|
|
34
34
|
"react-native": "0.74.5"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "a452b6b8fcd23775e30ab5ba9e98e95289594f9f"
|
|
37
37
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { useNavigation } from '@react-navigation/native'
|
|
2
2
|
import { QueryErrorResetBoundary, useSuspenseQuery } from '@tanstack/react-query'
|
|
3
3
|
import React, { Suspense, useContext } from 'react'
|
|
4
|
-
import { FlatList, Pressable, StyleSheet, Text } from 'react-native'
|
|
4
|
+
import { FlatList, Pressable, StyleSheet, Text, View } from 'react-native'
|
|
5
5
|
import { ChatContext } from '../contexts/chat_context'
|
|
6
|
-
import { useTheme } from '../hooks/use_theme'
|
|
7
6
|
import { ConversationRecord } from '../types'
|
|
8
7
|
import ErrorBoundary from './error_boundary'
|
|
8
|
+
import { useTheme } from '../hooks'
|
|
9
|
+
import { Spinner, Image } from './display'
|
|
9
10
|
|
|
10
11
|
type ConversationsResponse = {
|
|
11
12
|
data: ConversationRecord[]
|
|
@@ -42,8 +43,26 @@ const Loaded = () => {
|
|
|
42
43
|
<FlatList
|
|
43
44
|
data={conversations?.data}
|
|
44
45
|
contentContainerStyle={styles.container}
|
|
46
|
+
style={styles.scrollView}
|
|
45
47
|
ListEmptyComponent={<Text>No conversations found</Text>}
|
|
46
|
-
ListHeaderComponent={
|
|
48
|
+
ListHeaderComponent={
|
|
49
|
+
<View style={styles.column}>
|
|
50
|
+
<Text style={styles.foo}>Display Components</Text>
|
|
51
|
+
<View style={[styles.row, styles.spinnerContainer]}>
|
|
52
|
+
<Spinner size={24} />
|
|
53
|
+
</View>
|
|
54
|
+
<View style={styles.row}>
|
|
55
|
+
<Image source={{ uri: 'https://broken.url' }} style={styles.image} />
|
|
56
|
+
<Image
|
|
57
|
+
source={{
|
|
58
|
+
uri: 'https://picsum.photos/seed/picsum/200',
|
|
59
|
+
}}
|
|
60
|
+
style={styles.image}
|
|
61
|
+
/>
|
|
62
|
+
</View>
|
|
63
|
+
<Text style={styles.foo}>Conversations</Text>
|
|
64
|
+
</View>
|
|
65
|
+
}
|
|
47
66
|
renderItem={({ item }) => (
|
|
48
67
|
<Pressable onPress={() => navigation.navigate('Settings')}>
|
|
49
68
|
<Text style={styles.listItem}>{item.attributes.title}</Text>
|
|
@@ -57,8 +76,23 @@ const useStyles = () => {
|
|
|
57
76
|
const { colors } = useTheme()
|
|
58
77
|
|
|
59
78
|
return StyleSheet.create({
|
|
60
|
-
|
|
79
|
+
scrollView: { flex: 1, backgroundColor: colors.fillColorNeutral090 },
|
|
80
|
+
container: { gap: 8, padding: 16 },
|
|
61
81
|
foo: { fontSize: 24, color: colors.testColor },
|
|
62
82
|
listItem: { color: colors.fillColorNeutral020 },
|
|
83
|
+
row: {
|
|
84
|
+
gap: 16,
|
|
85
|
+
flexDirection: 'row',
|
|
86
|
+
alignItems: 'center',
|
|
87
|
+
justifyContent: 'center',
|
|
88
|
+
},
|
|
89
|
+
column: { gap: 16 },
|
|
90
|
+
spinnerContainer: {
|
|
91
|
+
height: 20,
|
|
92
|
+
},
|
|
93
|
+
image: {
|
|
94
|
+
width: 100,
|
|
95
|
+
height: 100,
|
|
96
|
+
},
|
|
63
97
|
})
|
|
64
98
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { noop } from 'lodash'
|
|
2
|
+
import React, { useState } from 'react'
|
|
3
|
+
import {
|
|
4
|
+
Image as ReactNativeImage,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
View,
|
|
7
|
+
ImageProps as RNImageProps,
|
|
8
|
+
ViewStyle,
|
|
9
|
+
} from 'react-native'
|
|
10
|
+
import { useTheme } from '../../hooks'
|
|
11
|
+
import { Spinner } from './spinner'
|
|
12
|
+
|
|
13
|
+
interface ImageProps extends RNImageProps {
|
|
14
|
+
/**
|
|
15
|
+
* Should the image show the loading indicator by default.
|
|
16
|
+
*/
|
|
17
|
+
defaultLoading?: boolean
|
|
18
|
+
/**
|
|
19
|
+
* Size of the loading spinner.
|
|
20
|
+
*/
|
|
21
|
+
loaderSize?: number
|
|
22
|
+
/**
|
|
23
|
+
* Style object for the preload background.
|
|
24
|
+
*/
|
|
25
|
+
loadingBackgroundStyles?: ViewStyle
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function Image({
|
|
29
|
+
source,
|
|
30
|
+
onLoad = noop,
|
|
31
|
+
defaultLoading = true,
|
|
32
|
+
loaderSize = 24,
|
|
33
|
+
loadingBackgroundStyles,
|
|
34
|
+
style,
|
|
35
|
+
...restProps
|
|
36
|
+
}: ImageProps) {
|
|
37
|
+
const [loading, setLoading] = useState(defaultLoading)
|
|
38
|
+
const styles = useStyles()
|
|
39
|
+
|
|
40
|
+
const imageStyles = StyleSheet.flatten(style)
|
|
41
|
+
const { width = '100%', height = '100%', borderRadius = 0 } = imageStyles || {}
|
|
42
|
+
|
|
43
|
+
const handleOnLoad = (event: any) => {
|
|
44
|
+
setLoading(false)
|
|
45
|
+
onLoad?.(event)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<View>
|
|
50
|
+
<ReactNativeImage
|
|
51
|
+
style={[styles.image, imageStyles]}
|
|
52
|
+
onLoad={handleOnLoad}
|
|
53
|
+
source={source}
|
|
54
|
+
{...restProps}
|
|
55
|
+
/>
|
|
56
|
+
{loading && (
|
|
57
|
+
<View
|
|
58
|
+
style={[
|
|
59
|
+
{
|
|
60
|
+
...styles.loadingBackground,
|
|
61
|
+
...loadingBackgroundStyles,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
borderRadius: borderRadius,
|
|
65
|
+
width: width,
|
|
66
|
+
height: height,
|
|
67
|
+
},
|
|
68
|
+
]}
|
|
69
|
+
>
|
|
70
|
+
<Spinner size={loaderSize} />
|
|
71
|
+
</View>
|
|
72
|
+
)}
|
|
73
|
+
</View>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const useStyles = () => {
|
|
78
|
+
const { colors } = useTheme()
|
|
79
|
+
|
|
80
|
+
return StyleSheet.create({
|
|
81
|
+
loadingBackground: {
|
|
82
|
+
position: 'absolute',
|
|
83
|
+
top: 0,
|
|
84
|
+
left: 0,
|
|
85
|
+
backgroundColor: colors.fillColorNeutral070,
|
|
86
|
+
},
|
|
87
|
+
image: {
|
|
88
|
+
backgroundColor: 'transparent',
|
|
89
|
+
},
|
|
90
|
+
})
|
|
91
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react'
|
|
2
|
+
import { Animated, Easing, StyleSheet, View } from 'react-native'
|
|
3
|
+
import { useTheme } from '../../hooks'
|
|
4
|
+
|
|
5
|
+
interface SpinnerProps {
|
|
6
|
+
/**
|
|
7
|
+
* Size of the spinner in px
|
|
8
|
+
* */
|
|
9
|
+
size?: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function Spinner({ size = 20 }: SpinnerProps) {
|
|
13
|
+
const rotation = useRef(new Animated.Value(0)).current
|
|
14
|
+
const styles = useStyles()
|
|
15
|
+
|
|
16
|
+
const animation = Animated.loop(
|
|
17
|
+
Animated.timing(rotation, {
|
|
18
|
+
toValue: 1,
|
|
19
|
+
duration: 1000,
|
|
20
|
+
easing: Easing.linear,
|
|
21
|
+
useNativeDriver: true,
|
|
22
|
+
})
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
const rotateValue = rotation.interpolate({
|
|
26
|
+
inputRange: [0, 1],
|
|
27
|
+
outputRange: ['0deg', '360deg'],
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
animation.start()
|
|
32
|
+
return () => animation.stop()
|
|
33
|
+
}, [animation])
|
|
34
|
+
|
|
35
|
+
useEffect(() => () => rotation.setValue(0), [rotation])
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<View style={styles.container}>
|
|
39
|
+
<Animated.View
|
|
40
|
+
style={{
|
|
41
|
+
width: size,
|
|
42
|
+
height: size,
|
|
43
|
+
borderRadius: size / 2,
|
|
44
|
+
transform: [{ rotate: rotateValue }],
|
|
45
|
+
}}
|
|
46
|
+
>
|
|
47
|
+
<View
|
|
48
|
+
style={[
|
|
49
|
+
styles.clipping,
|
|
50
|
+
{
|
|
51
|
+
width: size / 2,
|
|
52
|
+
height: size / 2,
|
|
53
|
+
},
|
|
54
|
+
]}
|
|
55
|
+
>
|
|
56
|
+
<View
|
|
57
|
+
style={[
|
|
58
|
+
styles.circle,
|
|
59
|
+
styles.spinner,
|
|
60
|
+
{
|
|
61
|
+
width: size,
|
|
62
|
+
height: size,
|
|
63
|
+
borderRadius: size / 2,
|
|
64
|
+
},
|
|
65
|
+
]}
|
|
66
|
+
/>
|
|
67
|
+
</View>
|
|
68
|
+
<View
|
|
69
|
+
style={[
|
|
70
|
+
styles.circle,
|
|
71
|
+
styles.track,
|
|
72
|
+
{
|
|
73
|
+
width: size,
|
|
74
|
+
height: size,
|
|
75
|
+
borderRadius: size / 2,
|
|
76
|
+
},
|
|
77
|
+
]}
|
|
78
|
+
/>
|
|
79
|
+
</Animated.View>
|
|
80
|
+
</View>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const useStyles = () => {
|
|
85
|
+
const { colors } = useTheme()
|
|
86
|
+
|
|
87
|
+
return StyleSheet.create({
|
|
88
|
+
container: {
|
|
89
|
+
width: '100%',
|
|
90
|
+
height: '100%',
|
|
91
|
+
position: 'absolute',
|
|
92
|
+
top: 0,
|
|
93
|
+
left: 0,
|
|
94
|
+
zIndex: 200,
|
|
95
|
+
justifyContent: 'center',
|
|
96
|
+
alignItems: 'center',
|
|
97
|
+
opacity: 0.7,
|
|
98
|
+
},
|
|
99
|
+
circle: {
|
|
100
|
+
borderStyle: 'solid',
|
|
101
|
+
borderWidth: 3,
|
|
102
|
+
},
|
|
103
|
+
spinner: {
|
|
104
|
+
position: 'absolute',
|
|
105
|
+
top: 0,
|
|
106
|
+
left: 0,
|
|
107
|
+
borderColor: colors.fillColorNeutral020,
|
|
108
|
+
},
|
|
109
|
+
track: {
|
|
110
|
+
borderColor: colors.fillColorNeutral050Base,
|
|
111
|
+
},
|
|
112
|
+
clipping: {
|
|
113
|
+
position: 'absolute',
|
|
114
|
+
top: 0,
|
|
115
|
+
left: 0,
|
|
116
|
+
overflow: 'hidden',
|
|
117
|
+
zIndex: 200,
|
|
118
|
+
},
|
|
119
|
+
})
|
|
120
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Conversations } from './components/conversations'
|
|
2
2
|
import { ChatContext, ChatProvider } from './contexts/chat_context'
|
|
3
|
-
import { useCreateChatTheme } from './hooks
|
|
3
|
+
import { useCreateChatTheme } from './hooks'
|
|
4
4
|
import { OAuthToken } from './types'
|
|
5
5
|
import { baseUrlMap, uploadUrlMap } from './utils/session'
|
|
6
6
|
import { TemporaryDefaultColorsType } from './utils/theme'
|