stream-chat-react-native-core 4.0.0-beta.3 → 4.0.0-beta.4
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/lib/commonjs/components/Attachment/Giphy.js +109 -145
- package/lib/commonjs/components/Attachment/Giphy.js.map +1 -1
- package/lib/commonjs/components/Message/MessageSimple/MessageFooter.js +9 -5
- package/lib/commonjs/components/Message/MessageSimple/MessageFooter.js.map +1 -1
- package/lib/commonjs/components/Message/MessageSimple/utils/renderText.js +144 -64
- package/lib/commonjs/components/Message/MessageSimple/utils/renderText.js.map +1 -1
- package/lib/commonjs/components/Message/MessageSimple/utils/renderText.test.js +240 -0
- package/lib/commonjs/components/Message/MessageSimple/utils/renderText.test.js.map +1 -0
- package/lib/commonjs/contexts/themeContext/utils/theme.js +7 -6
- package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/commonjs/icons/index.js +0 -26
- package/lib/commonjs/icons/index.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/Attachment/Giphy.js +109 -145
- package/lib/module/components/Attachment/Giphy.js.map +1 -1
- package/lib/module/components/Message/MessageSimple/MessageFooter.js +9 -5
- package/lib/module/components/Message/MessageSimple/MessageFooter.js.map +1 -1
- package/lib/module/components/Message/MessageSimple/utils/renderText.js +144 -64
- package/lib/module/components/Message/MessageSimple/utils/renderText.js.map +1 -1
- package/lib/module/components/Message/MessageSimple/utils/renderText.test.js +240 -0
- package/lib/module/components/Message/MessageSimple/utils/renderText.test.js.map +1 -0
- package/lib/module/contexts/themeContext/utils/theme.js +7 -6
- package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/module/icons/index.js +0 -26
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/Message/MessageSimple/utils/renderText.d.ts +15 -1
- package/lib/typescript/components/Message/MessageSimple/utils/renderText.test.d.ts +1 -0
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts +6 -5
- package/lib/typescript/icons/index.d.ts +0 -2
- package/package.json +1 -1
- package/src/components/Attachment/Giphy.tsx +64 -66
- package/src/components/Message/MessageSimple/MessageFooter.tsx +5 -5
- package/src/components/Message/MessageSimple/utils/renderText.test.tsx +70 -0
- package/src/components/Message/MessageSimple/utils/renderText.tsx +77 -47
- package/src/contexts/themeContext/utils/theme.ts +13 -11
- package/src/icons/index.ts +0 -2
- package/src/version.json +1 -1
- package/lib/commonjs/icons/Left.js +0 -38
- package/lib/commonjs/icons/Left.js.map +0 -1
- package/lib/commonjs/icons/Right.js +0 -38
- package/lib/commonjs/icons/Right.js.map +0 -1
- package/lib/module/icons/Left.js +0 -38
- package/lib/module/icons/Left.js.map +0 -1
- package/lib/module/icons/Right.js +0 -38
- package/lib/module/icons/Right.js.map +0 -1
- package/lib/typescript/icons/Left.d.ts +0 -3
- package/lib/typescript/icons/Right.d.ts +0 -3
- package/src/icons/Left.tsx +0 -12
- package/src/icons/Right.tsx +0 -12
|
@@ -29,7 +29,6 @@ export * from './Grid';
|
|
|
29
29
|
export * from './Group';
|
|
30
30
|
export * from './HTML';
|
|
31
31
|
export * from './Imgur';
|
|
32
|
-
export * from './Left';
|
|
33
32
|
export * from './Lightning';
|
|
34
33
|
export * from './Link';
|
|
35
34
|
export * from './Loading';
|
|
@@ -53,7 +52,6 @@ export * from './PPT';
|
|
|
53
52
|
export * from './PPTX';
|
|
54
53
|
export * from './RAR';
|
|
55
54
|
export * from './Refresh';
|
|
56
|
-
export * from './Right';
|
|
57
55
|
export * from './RTF';
|
|
58
56
|
export * from './Search';
|
|
59
57
|
export * from './SendRight';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stream-chat-react-native-core",
|
|
3
3
|
"description": "The official React Native and Expo components for Stream Chat, a service for building chat applications",
|
|
4
|
-
"version": "4.0.0-beta.
|
|
4
|
+
"version": "4.0.0-beta.4",
|
|
5
5
|
"author": {
|
|
6
6
|
"company": "Stream.io Inc",
|
|
7
7
|
"name": "Stream.io Inc"
|
|
@@ -12,9 +12,8 @@ import {
|
|
|
12
12
|
useMessagesContext,
|
|
13
13
|
} from '../../contexts/messagesContext/MessagesContext';
|
|
14
14
|
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
15
|
-
import {
|
|
15
|
+
import { GiphyIcon } from '../../icons';
|
|
16
16
|
import { Lightning } from '../../icons/Lightning';
|
|
17
|
-
import { Right } from '../../icons/Right';
|
|
18
17
|
import type {
|
|
19
18
|
DefaultAttachmentType,
|
|
20
19
|
DefaultChannelType,
|
|
@@ -28,25 +27,20 @@ import type {
|
|
|
28
27
|
import { makeImageCompatibleUrl } from '../../utils/utils';
|
|
29
28
|
|
|
30
29
|
const styles = StyleSheet.create({
|
|
30
|
+
buttonContainer: { alignItems: 'center', borderTopWidth: 1, flex: 1, justifyContent: 'center' },
|
|
31
31
|
cancel: {
|
|
32
32
|
fontSize: 14,
|
|
33
33
|
fontWeight: '600',
|
|
34
34
|
paddingVertical: 16,
|
|
35
35
|
},
|
|
36
|
-
cancelContainer: {
|
|
37
|
-
alignItems: 'center',
|
|
38
|
-
borderRightWidth: 1,
|
|
39
|
-
flex: 1,
|
|
40
|
-
justifyContent: 'center',
|
|
41
|
-
},
|
|
42
36
|
container: {
|
|
43
37
|
overflow: 'hidden',
|
|
44
|
-
width:
|
|
38
|
+
width: 270,
|
|
45
39
|
},
|
|
46
40
|
giphy: {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
borderRadius: 2,
|
|
42
|
+
height: 170,
|
|
43
|
+
width: 270,
|
|
50
44
|
},
|
|
51
45
|
giphyContainer: {
|
|
52
46
|
alignItems: 'center',
|
|
@@ -56,36 +50,47 @@ const styles = StyleSheet.create({
|
|
|
56
50
|
justifyContent: 'center',
|
|
57
51
|
width: 68,
|
|
58
52
|
},
|
|
53
|
+
giphyHeaderText: {
|
|
54
|
+
fontSize: 16,
|
|
55
|
+
fontWeight: '600',
|
|
56
|
+
},
|
|
57
|
+
giphyHeaderTitle: {
|
|
58
|
+
fontSize: 14,
|
|
59
|
+
},
|
|
59
60
|
giphyMask: {
|
|
60
61
|
bottom: 8,
|
|
61
62
|
left: 8,
|
|
62
63
|
position: 'absolute',
|
|
63
64
|
},
|
|
64
|
-
|
|
65
|
+
giphyMaskText: { fontSize: 13, fontWeight: '600' },
|
|
66
|
+
header: {
|
|
67
|
+
alignItems: 'center',
|
|
68
|
+
display: 'flex',
|
|
69
|
+
flexDirection: 'row',
|
|
70
|
+
justifyContent: 'space-between',
|
|
71
|
+
padding: 8,
|
|
72
|
+
width: '60%',
|
|
73
|
+
},
|
|
65
74
|
margin: {
|
|
66
|
-
margin:
|
|
75
|
+
margin: 1,
|
|
67
76
|
},
|
|
68
77
|
row: { flexDirection: 'row' },
|
|
69
78
|
selectionContainer: {
|
|
70
|
-
|
|
79
|
+
borderBottomLeftRadius: 8,
|
|
71
80
|
borderWidth: 1,
|
|
72
81
|
overflow: 'hidden',
|
|
73
|
-
width:
|
|
74
|
-
},
|
|
75
|
-
selector: {
|
|
76
|
-
alignItems: 'center',
|
|
77
|
-
borderBottomWidth: 1,
|
|
78
|
-
flexDirection: 'row',
|
|
79
|
-
justifyContent: 'space-between',
|
|
80
|
-
paddingBottom: 8,
|
|
81
|
-
paddingHorizontal: 8,
|
|
82
|
+
width: 272,
|
|
82
83
|
},
|
|
83
84
|
send: {
|
|
84
85
|
fontSize: 14,
|
|
85
86
|
fontWeight: '600',
|
|
86
87
|
paddingVertical: 16,
|
|
87
88
|
},
|
|
88
|
-
|
|
89
|
+
shuffle: {
|
|
90
|
+
fontSize: 14,
|
|
91
|
+
fontWeight: '600',
|
|
92
|
+
paddingVertical: 16,
|
|
93
|
+
},
|
|
89
94
|
shuffleButton: {
|
|
90
95
|
alignItems: 'center',
|
|
91
96
|
borderRadius: 16,
|
|
@@ -94,11 +99,6 @@ const styles = StyleSheet.create({
|
|
|
94
99
|
justifyContent: 'center',
|
|
95
100
|
width: 32,
|
|
96
101
|
},
|
|
97
|
-
title: {
|
|
98
|
-
fontSize: 14,
|
|
99
|
-
fontStyle: 'italic',
|
|
100
|
-
fontWeight: '500',
|
|
101
|
-
},
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
export type GiphyPropsWithContext<
|
|
@@ -142,22 +142,22 @@ const GiphyWithContext = <
|
|
|
142
142
|
|
|
143
143
|
const {
|
|
144
144
|
theme: {
|
|
145
|
-
colors: { accent_blue, black,
|
|
145
|
+
colors: { accent_blue, black, grey, grey_dark, grey_gainsboro, white },
|
|
146
146
|
messageSimple: {
|
|
147
147
|
giphy: {
|
|
148
|
+
buttonContainer,
|
|
148
149
|
cancel,
|
|
149
|
-
cancelContainer,
|
|
150
150
|
container,
|
|
151
151
|
giphy,
|
|
152
152
|
giphyContainer,
|
|
153
|
+
giphyHeaderText,
|
|
154
|
+
giphyHeaderTitle,
|
|
153
155
|
giphyMask,
|
|
154
|
-
|
|
156
|
+
giphyMaskText,
|
|
157
|
+
header,
|
|
155
158
|
selectionContainer,
|
|
156
|
-
selector,
|
|
157
159
|
send,
|
|
158
|
-
|
|
159
|
-
shuffleButton,
|
|
160
|
-
title: titleStyle,
|
|
160
|
+
shuffle,
|
|
161
161
|
},
|
|
162
162
|
},
|
|
163
163
|
},
|
|
@@ -175,51 +175,49 @@ const GiphyWithContext = <
|
|
|
175
175
|
selectionContainer,
|
|
176
176
|
]}
|
|
177
177
|
>
|
|
178
|
+
<View style={[styles.header, header]}>
|
|
179
|
+
<GiphyIcon />
|
|
180
|
+
<Text style={[styles.giphyHeaderText, giphyHeaderText]}>Giphy</Text>
|
|
181
|
+
<Text
|
|
182
|
+
style={[styles.giphyHeaderTitle, giphyHeaderTitle, { color: grey_dark }]}
|
|
183
|
+
>{`/giphy ${title}`}</Text>
|
|
184
|
+
</View>
|
|
178
185
|
<View style={styles.margin}>
|
|
179
186
|
<Image
|
|
180
187
|
resizeMode='cover'
|
|
181
188
|
source={{ uri: makeImageCompatibleUrl(uri) }}
|
|
182
189
|
style={[styles.giphy, giphy]}
|
|
183
190
|
/>
|
|
184
|
-
<View style={[styles.giphyMask, giphyMask]}>
|
|
185
|
-
<View style={[styles.giphyContainer, { backgroundColor: overlay }, giphyContainer]}>
|
|
186
|
-
<Lightning height={16} pathFill={white} width={16} />
|
|
187
|
-
<Text style={[styles.giphyText, { color: white }, giphyText]}>
|
|
188
|
-
{type?.toUpperCase()}
|
|
189
|
-
</Text>
|
|
190
|
-
</View>
|
|
191
|
-
</View>
|
|
192
191
|
</View>
|
|
193
192
|
<View>
|
|
194
|
-
<View style={
|
|
195
|
-
<TouchableOpacity
|
|
196
|
-
onPress={() => handleAction('image_action', 'shuffle')}
|
|
197
|
-
style={[styles.shuffleButton, { borderColor: border }, shuffleButton]}
|
|
198
|
-
>
|
|
199
|
-
<Left />
|
|
200
|
-
</TouchableOpacity>
|
|
201
|
-
<Text style={[styles.title, { color: black }, titleStyle]}>{`"${title}"`}</Text>
|
|
193
|
+
<View style={styles.row}>
|
|
202
194
|
<TouchableOpacity
|
|
203
195
|
onPress={() => {
|
|
204
|
-
if (actions?.[
|
|
205
|
-
handleAction(actions[
|
|
196
|
+
if (actions?.[2].name && actions?.[2].value && handleAction) {
|
|
197
|
+
handleAction(actions[2].name, actions[2].value);
|
|
206
198
|
}
|
|
207
199
|
}}
|
|
208
|
-
style={[
|
|
200
|
+
style={[
|
|
201
|
+
styles.buttonContainer,
|
|
202
|
+
{ borderColor: grey_gainsboro, borderRightWidth: 1 },
|
|
203
|
+
buttonContainer,
|
|
204
|
+
]}
|
|
209
205
|
>
|
|
210
|
-
<
|
|
206
|
+
<Text style={[styles.cancel, { color: grey }, cancel]}>{actions?.[2].text}</Text>
|
|
211
207
|
</TouchableOpacity>
|
|
212
|
-
</View>
|
|
213
|
-
<View style={styles.row}>
|
|
214
208
|
<TouchableOpacity
|
|
215
209
|
onPress={() => {
|
|
216
|
-
if (actions?.[
|
|
217
|
-
handleAction(actions[
|
|
210
|
+
if (actions?.[1].name && actions?.[1].value && handleAction) {
|
|
211
|
+
handleAction(actions[1].name, actions[1].value);
|
|
218
212
|
}
|
|
219
213
|
}}
|
|
220
|
-
style={[
|
|
214
|
+
style={[
|
|
215
|
+
styles.buttonContainer,
|
|
216
|
+
{ borderColor: grey_gainsboro, borderRightWidth: 1 },
|
|
217
|
+
buttonContainer,
|
|
218
|
+
]}
|
|
221
219
|
>
|
|
222
|
-
<Text style={[styles.
|
|
220
|
+
<Text style={[styles.shuffle, { color: grey }, shuffle]}>{actions?.[1].text}</Text>
|
|
223
221
|
</TouchableOpacity>
|
|
224
222
|
<TouchableOpacity
|
|
225
223
|
onPress={() => {
|
|
@@ -227,7 +225,7 @@ const GiphyWithContext = <
|
|
|
227
225
|
handleAction(actions[0].name, actions[0].value);
|
|
228
226
|
}
|
|
229
227
|
}}
|
|
230
|
-
style={[styles.
|
|
228
|
+
style={[styles.buttonContainer, { borderColor: grey_gainsboro }, buttonContainer]}
|
|
231
229
|
>
|
|
232
230
|
<Text style={[styles.send, { color: accent_blue }, send]}>{actions?.[0].text}</Text>
|
|
233
231
|
</TouchableOpacity>
|
|
@@ -272,9 +270,9 @@ const GiphyWithContext = <
|
|
|
272
270
|
style={[styles.giphy, giphy]}
|
|
273
271
|
/>
|
|
274
272
|
<View style={[styles.giphyMask, giphyMask]}>
|
|
275
|
-
<View style={[styles.giphyContainer, { backgroundColor:
|
|
273
|
+
<View style={[styles.giphyContainer, { backgroundColor: grey_dark }, giphyContainer]}>
|
|
276
274
|
<Lightning height={16} pathFill={white} width={16} />
|
|
277
|
-
<Text style={[styles.
|
|
275
|
+
<Text style={[styles.giphyMaskText, { color: white }, giphyMaskText]}>
|
|
278
276
|
{type?.toUpperCase()}
|
|
279
277
|
</Text>
|
|
280
278
|
</View>
|
|
@@ -86,7 +86,7 @@ const MessageFooterWithContext = <
|
|
|
86
86
|
|
|
87
87
|
const {
|
|
88
88
|
theme: {
|
|
89
|
-
colors: { grey },
|
|
89
|
+
colors: { grey, grey_dark },
|
|
90
90
|
messageSimple: {
|
|
91
91
|
content: { deletedMetaText, eyeIcon, messageUser, metaContainer, metaText },
|
|
92
92
|
},
|
|
@@ -99,11 +99,11 @@ const MessageFooterWithContext = <
|
|
|
99
99
|
<View style={metaContainer} testID='message-deleted'>
|
|
100
100
|
{deletedMessagesVisibilityType === 'sender' && (
|
|
101
101
|
<>
|
|
102
|
-
<Eye pathFill={
|
|
102
|
+
<Eye pathFill={grey_dark} {...eyeIcon} />
|
|
103
103
|
<Text
|
|
104
104
|
style={[
|
|
105
105
|
{
|
|
106
|
-
color:
|
|
106
|
+
color: grey_dark,
|
|
107
107
|
textAlign: alignment,
|
|
108
108
|
},
|
|
109
109
|
metaText,
|
|
@@ -138,11 +138,11 @@ const MessageFooterWithContext = <
|
|
|
138
138
|
<View style={metaContainer} testID='message-status-time'>
|
|
139
139
|
{otherAttachments.length && otherAttachments[0].actions ? (
|
|
140
140
|
<>
|
|
141
|
-
<Eye {...eyeIcon} />
|
|
141
|
+
<Eye pathFill={grey_dark} {...eyeIcon} />
|
|
142
142
|
<Text
|
|
143
143
|
style={[
|
|
144
144
|
{
|
|
145
|
-
color:
|
|
145
|
+
color: grey_dark,
|
|
146
146
|
textAlign: alignment,
|
|
147
147
|
},
|
|
148
148
|
metaText,
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { render, waitFor } from '@testing-library/react-native';
|
|
5
|
+
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
import { ASTNode, SingleASTNode } from 'simple-markdown';
|
|
8
|
+
|
|
9
|
+
import { ListOutput, ListOutputProps } from './renderText';
|
|
10
|
+
|
|
11
|
+
describe('list', () => {
|
|
12
|
+
const createNode = ({
|
|
13
|
+
amount,
|
|
14
|
+
ordered = false,
|
|
15
|
+
start = 1,
|
|
16
|
+
}: {
|
|
17
|
+
amount: number;
|
|
18
|
+
ordered?: boolean;
|
|
19
|
+
start?: number;
|
|
20
|
+
}): SingleASTNode => ({
|
|
21
|
+
items: Array.from(Array(amount).keys()),
|
|
22
|
+
ordered,
|
|
23
|
+
start,
|
|
24
|
+
type: 'text',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const mockOutput = (node: ASTNode) => <Text>{node}</Text>;
|
|
28
|
+
const MockText = ({ node, output, state }: ListOutputProps) => (
|
|
29
|
+
<>
|
|
30
|
+
<ListOutput node={node} output={output} state={state} styles={{}} />
|
|
31
|
+
</>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
it('renders numbered items', async () => {
|
|
35
|
+
const node = createNode({ amount: 3, ordered: true, start: 1 });
|
|
36
|
+
const { getByText } = render(<MockText node={node} output={mockOutput} state={{}} />);
|
|
37
|
+
|
|
38
|
+
await waitFor(() => expect(getByText('1. ')).toBeTruthy());
|
|
39
|
+
await waitFor(() => expect(getByText('2. ')).toBeTruthy());
|
|
40
|
+
await waitFor(() => expect(getByText('3. ')).toBeTruthy());
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('renders numbered items from a start index', async () => {
|
|
44
|
+
const node = createNode({ amount: 3, ordered: true, start: 3 });
|
|
45
|
+
const { getByText } = render(<MockText node={node} output={mockOutput} state={{}} />);
|
|
46
|
+
|
|
47
|
+
await waitFor(() => expect(getByText('3. ')).toBeTruthy());
|
|
48
|
+
await waitFor(() => expect(getByText('4. ')).toBeTruthy());
|
|
49
|
+
await waitFor(() => expect(getByText('5. ')).toBeTruthy());
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('does not throw an error if an item is empty', async () => {
|
|
53
|
+
const node = {
|
|
54
|
+
...createNode({ amount: 3, ordered: true }),
|
|
55
|
+
items: ['Not empty', null, 'Not empty'],
|
|
56
|
+
};
|
|
57
|
+
const { getByText } = render(<MockText node={node} output={mockOutput} state={{}} />);
|
|
58
|
+
|
|
59
|
+
await waitFor(() => expect(getByText('1. ')).toBeTruthy());
|
|
60
|
+
await waitFor(() => expect(getByText('2. ')).toBeTruthy());
|
|
61
|
+
await waitFor(() => expect(getByText('3. ')).toBeTruthy());
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('renders an unordered list', async () => {
|
|
65
|
+
const node = createNode({ amount: 3 });
|
|
66
|
+
const { getAllByText } = render(<MockText node={node} output={mockOutput} state={{}} />);
|
|
67
|
+
|
|
68
|
+
await waitFor(() => expect(getAllByText('\u2022 ')).toHaveLength(3));
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { GestureResponderEvent, Linking, Text, View } from 'react-native';
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
import { GestureResponderEvent, Linking, Text, TextProps, View, ViewProps } from 'react-native';
|
|
3
3
|
|
|
4
4
|
// @ts-expect-error
|
|
5
5
|
import Markdown from 'react-native-markdown-package';
|
|
@@ -12,7 +12,9 @@ import {
|
|
|
12
12
|
ParseFunction,
|
|
13
13
|
parseInline,
|
|
14
14
|
ReactNodeOutput,
|
|
15
|
+
ReactOutput,
|
|
15
16
|
SingleASTNode,
|
|
17
|
+
State,
|
|
16
18
|
} from 'simple-markdown';
|
|
17
19
|
|
|
18
20
|
import { parseLinksFromText } from './parseLinks';
|
|
@@ -171,7 +173,7 @@ export const renderText = <
|
|
|
171
173
|
? onLinkParams(url)
|
|
172
174
|
: Linking.canOpenURL(url).then((canOpenUrl) => canOpenUrl && Linking.openURL(url));
|
|
173
175
|
|
|
174
|
-
const
|
|
176
|
+
const link: ReactNodeOutput = (node, output, { ...state }) => {
|
|
175
177
|
const onPress = (event: GestureResponderEvent) => {
|
|
176
178
|
if (!preventPress && onPressParam) {
|
|
177
179
|
onPressParam({
|
|
@@ -249,56 +251,18 @@ export const renderText = <
|
|
|
249
251
|
);
|
|
250
252
|
};
|
|
251
253
|
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* For lists and sublists, the default behavior of the markdown library we use is
|
|
259
|
-
* to always renumber any list, so all ordered lists start from 1.
|
|
260
|
-
*
|
|
261
|
-
* This custom rule overrides this behavior both for top level lists and sublists,
|
|
262
|
-
* in order to start the numbering from the number of the first list item provided.
|
|
263
|
-
*/
|
|
264
|
-
const customListAtLevel =
|
|
265
|
-
(level: keyof typeof listLevels): ReactNodeOutput =>
|
|
266
|
-
(node, output, { ...state }) => {
|
|
267
|
-
const items = node.items.map((item: Array<SingleASTNode>, index: number) => {
|
|
268
|
-
const withinList = item.length > 1 && item[1].type === 'list';
|
|
269
|
-
const content = output(item, { ...state, withinList });
|
|
270
|
-
|
|
271
|
-
const isTopLevelText =
|
|
272
|
-
['text', 'paragraph', 'strong'].includes(item[0].type) && withinList === false;
|
|
273
|
-
|
|
274
|
-
return (
|
|
275
|
-
<View key={index} style={styles.listRow}>
|
|
276
|
-
<Text style={styles.listItemNumber}>
|
|
277
|
-
{node.ordered ? `${node.start + index}. ` : `\u2022`}
|
|
278
|
-
</Text>
|
|
279
|
-
<Text style={[styles.listItemText, isTopLevelText && { marginBottom: 0 }]}>
|
|
280
|
-
{content}
|
|
281
|
-
</Text>
|
|
282
|
-
</View>
|
|
283
|
-
);
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
const isSublist = level === 'sub';
|
|
287
|
-
return (
|
|
288
|
-
<View key={state.key} style={[isSublist ? styles.list : styles.sublist]}>
|
|
289
|
-
{items}
|
|
290
|
-
</View>
|
|
291
|
-
);
|
|
292
|
-
};
|
|
254
|
+
const list: ReactNodeOutput = (node, output, state) => (
|
|
255
|
+
<ListOutput node={node} output={output} state={state} styles={styles} />
|
|
256
|
+
);
|
|
293
257
|
|
|
294
258
|
const customRules = {
|
|
295
|
-
link: {
|
|
296
|
-
list: { react:
|
|
259
|
+
link: { link },
|
|
260
|
+
list: { react: list },
|
|
297
261
|
// Truncate long text content in the message overlay
|
|
298
262
|
paragraph: messageTextNumberOfLines ? { react: paragraphText } : {},
|
|
299
263
|
// we have no react rendering support for reflinks
|
|
300
264
|
reflink: { match: () => null },
|
|
301
|
-
sublist: { react:
|
|
265
|
+
sublist: { react: list },
|
|
302
266
|
...(mentionedUsers
|
|
303
267
|
? {
|
|
304
268
|
mentions: {
|
|
@@ -327,3 +291,69 @@ export const renderText = <
|
|
|
327
291
|
</Markdown>
|
|
328
292
|
);
|
|
329
293
|
};
|
|
294
|
+
|
|
295
|
+
export interface ListOutputProps {
|
|
296
|
+
node: SingleASTNode;
|
|
297
|
+
output: ReactOutput;
|
|
298
|
+
state: State;
|
|
299
|
+
styles?: Partial<MarkdownStyle>;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* For lists and sublists, the default behavior of the markdown library we use is
|
|
304
|
+
* to always renumber any list, so all ordered lists start from 1.
|
|
305
|
+
*
|
|
306
|
+
* This custom rule overrides this behavior both for top level lists and sublists,
|
|
307
|
+
* in order to start the numbering from the number of the first list item provided.
|
|
308
|
+
*/
|
|
309
|
+
export const ListOutput = ({ node, output, state, styles }: ListOutputProps) => {
|
|
310
|
+
let isSublist = state.withinList;
|
|
311
|
+
const parentTypes = ['text', 'paragraph', 'strong'];
|
|
312
|
+
|
|
313
|
+
return (
|
|
314
|
+
<View key={state.key} style={isSublist ? styles?.sublist : styles?.list}>
|
|
315
|
+
{node.items.map((item: SingleASTNode, index: number) => {
|
|
316
|
+
const indexAfterStart = node.start + index;
|
|
317
|
+
|
|
318
|
+
if (item === null) {
|
|
319
|
+
return (
|
|
320
|
+
<ListRow key={index} style={styles?.listRow} testID='list-item'>
|
|
321
|
+
<Bullet index={node.ordered && indexAfterStart} />
|
|
322
|
+
</ListRow>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
isSublist = item.length > 1 && item[1].type === 'list';
|
|
327
|
+
const isSublistWithinText = parentTypes.includes((item[0] ?? {}).type) && isSublist;
|
|
328
|
+
const style = isSublistWithinText ? { marginBottom: 0 } : {};
|
|
329
|
+
|
|
330
|
+
return (
|
|
331
|
+
<ListRow key={index} style={styles?.listRow} testID='list-item'>
|
|
332
|
+
<Bullet index={node.ordered && indexAfterStart} />
|
|
333
|
+
<ListItem key={1} style={[styles?.listItemText, style]}>
|
|
334
|
+
{output(item, state)}
|
|
335
|
+
</ListItem>
|
|
336
|
+
</ListRow>
|
|
337
|
+
);
|
|
338
|
+
})}
|
|
339
|
+
</View>
|
|
340
|
+
);
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
interface BulletProps extends TextProps {
|
|
344
|
+
index?: number;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const Bullet = ({ index, style }: BulletProps) => (
|
|
348
|
+
<Text key={0} style={[style, defaultMarkdownStyles.listItemNumber]}>
|
|
349
|
+
{index ? `${index}. ` : '\u2022 '}
|
|
350
|
+
</Text>
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
const ListRow = (props: PropsWithChildren<ViewProps>) => (
|
|
354
|
+
<Text style={[props.style, defaultMarkdownStyles.listRow]}>{props.children}</Text>
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
const ListItem = ({ children, style }: PropsWithChildren<TextProps>) => (
|
|
358
|
+
<Text style={style}>{children}</Text>
|
|
359
|
+
);
|
|
@@ -417,18 +417,19 @@ export type Theme = {
|
|
|
417
417
|
moreImagesText: TextStyle;
|
|
418
418
|
};
|
|
419
419
|
giphy: {
|
|
420
|
+
buttonContainer: ViewStyle;
|
|
420
421
|
cancel: TextStyle;
|
|
421
|
-
cancelContainer: ViewStyle;
|
|
422
422
|
container: ViewStyle;
|
|
423
423
|
giphy: ImageStyle;
|
|
424
424
|
giphyContainer: ViewStyle;
|
|
425
|
+
giphyHeaderText: TextStyle;
|
|
426
|
+
giphyHeaderTitle: TextStyle;
|
|
425
427
|
giphyMask: ViewStyle;
|
|
426
|
-
|
|
428
|
+
giphyMaskText: TextStyle;
|
|
429
|
+
header: ViewStyle;
|
|
427
430
|
selectionContainer: ViewStyle;
|
|
428
|
-
selector: ViewStyle;
|
|
429
431
|
send: TextStyle;
|
|
430
|
-
|
|
431
|
-
shuffleButton: ViewStyle;
|
|
432
|
+
shuffle: TextStyle;
|
|
432
433
|
title: TextStyle;
|
|
433
434
|
};
|
|
434
435
|
pinnedHeader: {
|
|
@@ -837,7 +838,7 @@ export const defaultTheme: Theme = {
|
|
|
837
838
|
deletedContainer: {},
|
|
838
839
|
deletedContainerInner: {},
|
|
839
840
|
deletedMetaText: {
|
|
840
|
-
paddingHorizontal:
|
|
841
|
+
paddingHorizontal: 5,
|
|
841
842
|
},
|
|
842
843
|
deletedText: {
|
|
843
844
|
em: {
|
|
@@ -908,18 +909,19 @@ export const defaultTheme: Theme = {
|
|
|
908
909
|
moreImagesText: {},
|
|
909
910
|
},
|
|
910
911
|
giphy: {
|
|
912
|
+
buttonContainer: {},
|
|
911
913
|
cancel: {},
|
|
912
|
-
cancelContainer: {},
|
|
913
914
|
container: {},
|
|
914
915
|
giphy: {},
|
|
915
916
|
giphyContainer: {},
|
|
917
|
+
giphyHeaderText: {},
|
|
918
|
+
giphyHeaderTitle: {},
|
|
916
919
|
giphyMask: {},
|
|
917
|
-
|
|
920
|
+
giphyMaskText: {},
|
|
921
|
+
header: {},
|
|
918
922
|
selectionContainer: {},
|
|
919
|
-
selector: {},
|
|
920
923
|
send: {},
|
|
921
|
-
|
|
922
|
-
shuffleButton: {},
|
|
924
|
+
shuffle: {},
|
|
923
925
|
title: {},
|
|
924
926
|
},
|
|
925
927
|
pinnedHeader: {
|
package/src/icons/index.ts
CHANGED
|
@@ -30,7 +30,6 @@ export * from './Grid';
|
|
|
30
30
|
export * from './Group';
|
|
31
31
|
export * from './HTML';
|
|
32
32
|
export * from './Imgur';
|
|
33
|
-
export * from './Left';
|
|
34
33
|
export * from './Lightning';
|
|
35
34
|
export * from './Link';
|
|
36
35
|
export * from './Loading';
|
|
@@ -54,7 +53,6 @@ export * from './PPT';
|
|
|
54
53
|
export * from './PPTX';
|
|
55
54
|
export * from './RAR';
|
|
56
55
|
export * from './Refresh';
|
|
57
|
-
export * from './Right';
|
|
58
56
|
export * from './RTF';
|
|
59
57
|
export * from './Search';
|
|
60
58
|
export * from './SendRight';
|
package/src/version.json
CHANGED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.Left = void 0;
|
|
7
|
-
|
|
8
|
-
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
9
|
-
|
|
10
|
-
var _react = _interopRequireDefault(require("react"));
|
|
11
|
-
|
|
12
|
-
var _base = require("./utils/base");
|
|
13
|
-
|
|
14
|
-
var _this = this,
|
|
15
|
-
_jsxFileName = "/home/runner/work/stream-chat-react-native/stream-chat-react-native/package/src/icons/Left.tsx";
|
|
16
|
-
|
|
17
|
-
var Left = function Left(props) {
|
|
18
|
-
return _react["default"].createElement(_base.RootSvg, (0, _extends2["default"])({}, props, {
|
|
19
|
-
__self: _this,
|
|
20
|
-
__source: {
|
|
21
|
-
fileName: _jsxFileName,
|
|
22
|
-
lineNumber: 6,
|
|
23
|
-
columnNumber: 3
|
|
24
|
-
}
|
|
25
|
-
}), _react["default"].createElement(_base.RootPath, (0, _extends2["default"])({
|
|
26
|
-
d: "M15.694 18.694a1.043 1.043 0 000-1.476L10.47 12l5.224-5.218a1.043 1.043 0 000-1.476 1.046 1.046 0 00-1.478 0l-5.91 5.904a1.04 1.04 0 00-.305.79 1.04 1.04 0 00.305.79l5.91 5.904c.408.408 1.07.408 1.478 0z"
|
|
27
|
-
}, props, {
|
|
28
|
-
__self: _this,
|
|
29
|
-
__source: {
|
|
30
|
-
fileName: _jsxFileName,
|
|
31
|
-
lineNumber: 7,
|
|
32
|
-
columnNumber: 5
|
|
33
|
-
}
|
|
34
|
-
})));
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
exports.Left = Left;
|
|
38
|
-
//# sourceMappingURL=Left.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["Left.tsx"],"names":["Left","props"],"mappings":";;;;;;;;;AAAA;;AAEA;;;;;AAEO,IAAMA,IAAyB,GAAG,SAA5BA,IAA4B,CAACC,KAAD;AAAA,SACvC,gCAAC,aAAD,gCAAaA,KAAb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MACE,gCAAC,cAAD;AACE,IAAA,CAAC,EAAC;AADJ,KAEMA,KAFN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KADF,CADuC;AAAA,CAAlC","sourcesContent":["import React from 'react';\n\nimport { IconProps, RootPath, RootSvg } from './utils/base';\n\nexport const Left: React.FC<IconProps> = (props) => (\n <RootSvg {...props}>\n <RootPath\n d='M15.694 18.694a1.043 1.043 0 000-1.476L10.47 12l5.224-5.218a1.043 1.043 0 000-1.476 1.046 1.046 0 00-1.478 0l-5.91 5.904a1.04 1.04 0 00-.305.79 1.04 1.04 0 00.305.79l5.91 5.904c.408.408 1.07.408 1.478 0z'\n {...props}\n />\n </RootSvg>\n);\n"]}
|