@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 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;AAanD,wBAAgB,aAAa,6BAgB5B"}
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={<Text style={styles.foo}>Conversations</Text>} renderItem={({ item }) => (<Pressable onPress={() => navigation.navigate('Settings')}>
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
- container: { columnGap: 16, backgroundColor: colors.fillColorNeutral080 },
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;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAE7C,OAAO,aAAa,MAAM,kBAAkB,CAAA;AAQ5C,MAAM,UAAU,aAAa;IAC3B,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IAEzC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IAEvB,OAAO,CACL,CAAC,uBAAuB,CACtB;MAAA,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CACd,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAC5B;UAAA,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAC1C;YAAA,CAAC,MAAM,CAAC,AAAD,EACT;UAAA,EAAE,QAAQ,CACZ;QAAA,EAAE,aAAa,CAAC,CACjB,CACH;IAAA,EAAE,uBAAuB,CAAC,CAC3B,CAAA;AACH,CAAC;AAED,MAAM,MAAM,GAAG,GAAG,EAAE;IAClB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,gBAAgB,CAAwB;QACtE,QAAQ,EAAE,CAAC,2BAA2B,CAAC;KACxC,CAAC,CAAA;IACF,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAElC,OAAO,CACL,CAAC,QAAQ,CACP,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAC1B,qBAAqB,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CACxC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC,CACxD,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CACnE,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CACxB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CACxD;UAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,CAC7D;QAAA,EAAE,SAAS,CAAC,CACb,CAAC,EACF,CACH,CAAA;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE7B,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,eAAe,EAAE,MAAM,CAAC,mBAAmB,EAAE;QACzE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE;QAC9C,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,mBAAmB,EAAE;KAChD,CAAC,CAAA;AACJ,CAAC,CAAA","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 } from 'react-native'\nimport { ChatContext } from '../contexts/chat_context'\nimport { useTheme } from '../hooks/use_theme'\nimport { ConversationRecord } from '../types'\nimport ErrorBoundary from './error_boundary'\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 ListEmptyComponent={<Text>No conversations found</Text>}\n ListHeaderComponent={<Text style={styles.foo}>Conversations</Text>}\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 container: { columnGap: 16, backgroundColor: colors.fillColorNeutral080 },\n foo: { fontSize: 24, color: colors.testColor },\n listItem: { color: colors.fillColorNeutral020 },\n })\n}\n"]}
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,3 @@
1
+ export { Spinner } from './spinner';
2
+ export { Image } from './image';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,3 @@
1
+ export { Spinner } from './spinner';
2
+ export { Image } from './image';
3
+ //# sourceMappingURL=index.js.map
@@ -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,10 @@
1
+ import React from 'react';
2
+ interface SpinnerProps {
3
+ /**
4
+ * Size of the spinner in px
5
+ * */
6
+ size?: number;
7
+ }
8
+ export declare function Spinner({ size }: SpinnerProps): React.JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=spinner.d.ts.map
@@ -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,3 @@
1
+ export { useCreateChatTheme } from './use_create_chat_theme';
2
+ export { useTheme } from './use_theme';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,3 @@
1
+ export { useCreateChatTheme } from './use_create_chat_theme';
2
+ export { useTheme } from './use_theme';
3
+ //# sourceMappingURL=index.js.map
@@ -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/use_create_chat_theme';
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';
@@ -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,+BAA+B,CAAA;AAClE,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"}
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/use_create_chat_theme';
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
@@ -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,+BAA+B,CAAA;AAElE,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/use_create_chat_theme'\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"]}
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.0",
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": "fccff0f8691ba483d7f504423a1bd649c94a5af8"
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={<Text style={styles.foo}>Conversations</Text>}
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
- container: { columnGap: 16, backgroundColor: colors.fillColorNeutral080 },
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,2 @@
1
+ export { Spinner } from './spinner'
2
+ export { Image } from './image'
@@ -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
+ }
@@ -0,0 +1,2 @@
1
+ export { useCreateChatTheme } from './use_create_chat_theme'
2
+ export { useTheme } from './use_theme'
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/use_create_chat_theme'
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'