agora-appbuilder-core 1.0.8 → 1.0.9

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.
Files changed (51) hide show
  1. package/package.json +1 -1
  2. package/template/agora-rn-uikit/.git/HEAD +1 -0
  3. package/template/agora-rn-uikit/.git/config +16 -0
  4. package/template/agora-rn-uikit/.git/description +1 -0
  5. package/template/agora-rn-uikit/.git/hooks/applypatch-msg.sample +15 -0
  6. package/template/agora-rn-uikit/.git/hooks/commit-msg.sample +24 -0
  7. package/template/agora-rn-uikit/.git/hooks/fsmonitor-watchman.sample +173 -0
  8. package/template/agora-rn-uikit/.git/hooks/post-update.sample +8 -0
  9. package/template/agora-rn-uikit/.git/hooks/pre-applypatch.sample +14 -0
  10. package/template/agora-rn-uikit/.git/hooks/pre-commit.sample +49 -0
  11. package/template/agora-rn-uikit/.git/hooks/pre-merge-commit.sample +13 -0
  12. package/template/agora-rn-uikit/.git/hooks/pre-push.sample +53 -0
  13. package/template/agora-rn-uikit/.git/hooks/pre-rebase.sample +169 -0
  14. package/template/agora-rn-uikit/.git/hooks/pre-receive.sample +24 -0
  15. package/template/agora-rn-uikit/.git/hooks/prepare-commit-msg.sample +42 -0
  16. package/template/agora-rn-uikit/.git/hooks/push-to-checkout.sample +78 -0
  17. package/template/agora-rn-uikit/.git/hooks/update.sample +128 -0
  18. package/template/agora-rn-uikit/.git/index +0 -0
  19. package/template/agora-rn-uikit/.git/info/exclude +6 -0
  20. package/template/agora-rn-uikit/.git/logs/HEAD +2 -0
  21. package/template/agora-rn-uikit/.git/logs/refs/heads/ab-dev-auto +1 -0
  22. package/template/agora-rn-uikit/.git/logs/refs/heads/master +1 -0
  23. package/template/agora-rn-uikit/.git/logs/refs/remotes/origin/HEAD +1 -0
  24. package/template/agora-rn-uikit/.git/objects/pack/pack-eb3b4c374d6e79553b5bbcc78b4399cc766e97cf.idx +0 -0
  25. package/template/agora-rn-uikit/.git/objects/pack/pack-eb3b4c374d6e79553b5bbcc78b4399cc766e97cf.pack +0 -0
  26. package/template/agora-rn-uikit/.git/packed-refs +12 -0
  27. package/template/agora-rn-uikit/.git/refs/heads/ab-dev-auto +1 -0
  28. package/template/agora-rn-uikit/.git/refs/heads/master +1 -0
  29. package/template/agora-rn-uikit/.git/refs/remotes/origin/HEAD +1 -0
  30. package/template/agora-rn-uikit/.gitignore +63 -0
  31. package/template/agora-rn-uikit/package-lock.json +7612 -0
  32. package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +20 -30
  33. package/template/agora-rn-uikit/src/Controls/Local/EndCall.tsx +0 -1
  34. package/template/agora-rn-uikit/src/Controls/Local/LocalAudioMute.tsx +0 -1
  35. package/template/agora-rn-uikit/src/Controls/Local/LocalVideoMute.tsx +0 -1
  36. package/template/agora-rn-uikit/src/Controls/Local/SwitchCamera.tsx +0 -1
  37. package/template/agora-rn-uikit/src/RTCConfigure.tsx +49 -4
  38. package/template/package.json +3 -2
  39. package/template/react-native-toast-message/.gitignore +5 -0
  40. package/template/react-native-toast-message/.npmignore +5 -0
  41. package/template/react-native-toast-message/package-lock.json +10553 -0
  42. package/template/src/.DS_Store +0 -0
  43. package/template/src/components/Precall.native.tsx +22 -14
  44. package/template/src/components/Precall.tsx +19 -18
  45. package/template/src/components/StorageContext.tsx +2 -0
  46. package/template/src/pages/Create.tsx +17 -14
  47. package/template/src/pages/Join.tsx +11 -29
  48. package/template/src/pages/VideoCall.tsx +68 -49
  49. package/template/src/subComponents/.DS_Store +0 -0
  50. package/template/src/subComponents/LogoutButton.tsx +1 -1
  51. package/template/webpack.commons.js +1 -0
Binary file
@@ -46,24 +46,29 @@ const Precall = (props: any) => {
46
46
  <View style={style.heading}>
47
47
  <Text style={style.headingText}>Precall </Text>
48
48
  </View>
49
- <View style={{zIndex: 50, position: 'absolute', width: '100%', left: '18%', top: 10, alignSelf: 'center'}}>
49
+ <View
50
+ style={{
51
+ zIndex: 50,
52
+ position: 'absolute',
53
+ width: '100%',
54
+ left: '18%',
55
+ top: 10,
56
+ alignSelf: 'center',
57
+ }}>
50
58
  {error ? <Error error={error} showBack={true} /> : <></>}
51
59
  </View>
52
60
  <View style={style.full}>
53
61
  <MaxVideoView user={maxUsers[0]} key={maxUsers[0].uid} />
54
62
  </View>
55
63
  {Platform.OS === 'ios' ? (
56
- <View
57
- style={style.textInputHolder}>
64
+ <View style={style.textInputHolder}>
58
65
  <TextInput
59
66
  value={username}
60
67
  onChangeText={(text) => {
61
- if (username !== 'Getting name...') {
62
- setUsername(text);
63
- }
68
+ setUsername(text);
64
69
  }}
65
70
  onSubmitEditing={() => {}}
66
- placeholder="Display Name"
71
+ placeholder={queryComplete ? 'Display name*' : 'Getting name...'}
67
72
  />
68
73
  </View>
69
74
  ) : (
@@ -71,12 +76,11 @@ const Precall = (props: any) => {
71
76
  <TextInput
72
77
  value={username}
73
78
  onChangeText={(text) => {
74
- if (username !== 'Getting name...') {
75
- setUsername(text);
76
- }
79
+ setUsername(text);
77
80
  }}
78
81
  onSubmitEditing={() => {}}
79
- placeholder="Display Name"
82
+ placeholder={queryComplete ? 'Display name*' : 'Getting name...'}
83
+ editable={queryComplete}
80
84
  />
81
85
  </View>
82
86
  )}
@@ -95,10 +99,14 @@ const Precall = (props: any) => {
95
99
  // disabled={!queryComplete}
96
100
  style={{marginBottom: 50}}>
97
101
  {/* <Text style={style.buttonText}> */}
98
- {/* {queryComplete ? 'Join Room' : 'Loading...'} */}
102
+ {/* {queryComplete ? 'Join Room' : 'Loading...'} */}
99
103
  {/* </Text> */}
100
- {/* </TouchableOpacity> */}
101
- <PrimaryButton text={"Join Room"} disabled={!queryComplete} onPress={() => setCallActive(true)} />
104
+ {/* </TouchableOpacity> */}
105
+ <PrimaryButton
106
+ text={'Join Room'}
107
+ disabled={!queryComplete || username.trim() === ''}
108
+ onPress={() => setCallActive(true)}
109
+ />
102
110
  </View>
103
111
  {/* </ImageBackground> */}
104
112
  </View>
@@ -10,13 +10,7 @@
10
10
  *********************************************
11
11
  */
12
12
  import React, {useState, useContext} from 'react';
13
- import {
14
- View,
15
- Text,
16
- StyleSheet,
17
- Dimensions,
18
- Platform,
19
- } from 'react-native';
13
+ import {View, Text, StyleSheet, Dimensions, Platform} from 'react-native';
20
14
  import TextInput from '../atoms/TextInput';
21
15
  import PrimaryButton from '../atoms/PrimaryButton';
22
16
  import {MaxUidConsumer} from '../../agora-rn-uikit/src/MaxUidContext';
@@ -39,6 +33,7 @@ const Precall = (props: any) => {
39
33
  Dimensions.get('window').height,
40
34
  Dimensions.get('window').width > Dimensions.get('window').height,
41
35
  ]);
36
+
42
37
  let onLayout = (e: any) => {
43
38
  setDim([e.nativeEvent.layout.width, e.nativeEvent.layout.height]);
44
39
  };
@@ -94,17 +89,18 @@ const Precall = (props: any) => {
94
89
  <TextInput
95
90
  value={username}
96
91
  onChangeText={(text) => {
97
- if (username !== 'Getting name...') {
98
- setUsername(text);
99
- }
92
+ setUsername(text);
100
93
  }}
101
94
  onSubmitEditing={() => {}}
102
- placeholder="Display Name"
95
+ placeholder={
96
+ queryComplete ? 'Display name*' : 'Getting name...'
97
+ }
98
+ editable={queryComplete}
103
99
  />
104
100
  <View style={style.margin5Btm} />
105
101
  <PrimaryButton
106
102
  onPress={() => setCallActive(true)}
107
- disabled={!queryComplete}
103
+ disabled={!queryComplete || username.trim() === ''}
108
104
  text={queryComplete ? 'Join Room' : 'Loading...'}
109
105
  />
110
106
  </View>
@@ -140,7 +136,11 @@ const Precall = (props: any) => {
140
136
  </Text>
141
137
  {/* </View> */}
142
138
  <View style={{height: 20}} />
143
- <View style={{flex: 1, maxWidth: Platform.OS === 'web'? '25vw' : 'auto'}}>
139
+ <View
140
+ style={{
141
+ flex: 1,
142
+ maxWidth: Platform.OS === 'web' ? '25vw' : 'auto',
143
+ }}>
144
144
  <SelectDevice />
145
145
  </View>
146
146
  <View
@@ -154,17 +154,18 @@ const Precall = (props: any) => {
154
154
  <TextInput
155
155
  value={username}
156
156
  onChangeText={(text) => {
157
- if (username !== 'Getting name...') {
158
- setUsername(text);
159
- }
157
+ setUsername(text);
160
158
  }}
161
159
  onSubmitEditing={() => {}}
162
- placeholder="Display Name"
160
+ placeholder={
161
+ queryComplete ? 'Display name*' : 'Getting name...'
162
+ }
163
+ editable={queryComplete}
163
164
  />
164
165
  <View style={{height: 20}} />
165
166
  <PrimaryButton
166
167
  onPress={() => setCallActive(true)}
167
- disabled={!queryComplete}
168
+ disabled={!queryComplete || username.trim() === ''}
168
169
  text={queryComplete ? 'Join Room' : 'Loading...'}
169
170
  />
170
171
  </View>
@@ -15,6 +15,7 @@ import useMount from './useMount';
15
15
 
16
16
  interface StoreInterface {
17
17
  token: null | string;
18
+ displayName: null | string;
18
19
  }
19
20
 
20
21
  interface StorageContextInterface {
@@ -24,6 +25,7 @@ interface StorageContextInterface {
24
25
 
25
26
  const initStoreValue: StoreInterface = {
26
27
  token: null,
28
+ displayName: '',
27
29
  };
28
30
 
29
31
  const initStorageContextValue = {
@@ -10,12 +10,7 @@
10
10
  *********************************************
11
11
  */
12
12
  import React, {useState} from 'react';
13
- import {
14
- View,
15
- Text,
16
- StyleSheet,
17
- Dimensions,
18
- } from 'react-native';
13
+ import {View, Text, StyleSheet, Dimensions, ScrollView} from 'react-native';
19
14
  import {useHistory} from '../components/Router';
20
15
  import Checkbox from '../subComponents/Checkbox';
21
16
  import {gql, useMutation} from '@apollo/client';
@@ -38,8 +33,16 @@ type PasswordInput = {
38
33
  };
39
34
 
40
35
  const CREATE_CHANNEL = gql`
41
- mutation CreateChannel($title: String!, $backendURL: String!, $enablePSTN: Boolean) {
42
- createChannel(title: $title, backendURL: $backendURL, enablePSTN: $enablePSTN) {
36
+ mutation CreateChannel(
37
+ $title: String!
38
+ $backendURL: String!
39
+ $enablePSTN: Boolean
40
+ ) {
41
+ createChannel(
42
+ title: $title
43
+ backendURL: $backendURL
44
+ enablePSTN: $enablePSTN
45
+ ) {
43
46
  passphrase {
44
47
  host
45
48
  view
@@ -111,7 +114,7 @@ const Create = () => {
111
114
  // style={style.full}
112
115
  // resizeMode={'cover'}>
113
116
  // <KeyboardAvoidingView behavior={'height'} style={style.main}>
114
- <View style={style.main}>
117
+ <ScrollView contentContainerStyle={style.main}>
115
118
  <View style={style.nav}>
116
119
  <Logo />
117
120
  {error ? <Error error={error} /> : <></>}
@@ -179,17 +182,17 @@ const Create = () => {
179
182
  roomTitle={roomTitle}
180
183
  />
181
184
  )}
182
- </View>
185
+ </ScrollView>
183
186
  );
184
187
  };
185
188
 
186
189
  const style = StyleSheet.create({
187
- full: {flex: 1},
188
190
  main: {
189
- flex: 2,
190
- justifyContent: 'space-evenly',
191
+ paddingVertical: '8%',
191
192
  marginHorizontal: '8%',
192
- marginVertical: '2%',
193
+ display: 'flex',
194
+ justifyContent: 'space-evenly',
195
+ flexGrow: 1,
193
196
  },
194
197
  nav: {
195
198
  flex: 1,
@@ -10,11 +10,7 @@
10
10
  *********************************************
11
11
  */
12
12
  import React, {useContext, useState} from 'react';
13
- import {
14
- View,
15
- Text,
16
- StyleSheet,
17
- } from 'react-native';
13
+ import {View, Text, StyleSheet, ScrollView} from 'react-native';
18
14
  import {useHistory} from '../components/Router';
19
15
  import SessionContext from '../components/SessionContext';
20
16
  // import OpenInNativeButton from '../subComponents/OpenInNativeButton';
@@ -38,8 +34,9 @@ const Join = (props: joinProps) => {
38
34
  const history = useHistory();
39
35
  const {primaryColor} = useContext(ColorContext);
40
36
  const {joinSession} = useContext(SessionContext);
41
- const [error, setError] =
42
- useState<null | {name: string; message: string}>(null);
37
+ const [error, setError] = useState<null | {name: string; message: string}>(
38
+ null,
39
+ );
43
40
  // const [dim, setDim] = useState([
44
41
  // Dimensions.get('window').width,
45
42
  // Dimensions.get('window').height,
@@ -57,18 +54,12 @@ const Join = (props: joinProps) => {
57
54
  const startCall = async () => {
58
55
  joinSession({phrase});
59
56
  };
60
- // throw new Error("My first Sentry error!");
57
+
61
58
  return (
62
- // <ImageBackground
63
- // // onLayout={onLayout}
64
- // style={style.full}
65
- // resizeMode={'cover'}>
66
- <View style={style.main}>
67
- {/* <KeyboardAvoidingView behavior={'height'} style={style.main}> */}
59
+ <ScrollView contentContainerStyle={style.main}>
68
60
  <View style={style.nav}>
69
61
  <Logo />
70
62
  {error ? <Error error={error} /> : <></>}
71
- {/* <OpenInNativeButton /> */}
72
63
  </View>
73
64
  <View style={style.content}>
74
65
  <View style={style.leftContent}>
@@ -99,28 +90,19 @@ const Join = (props: joinProps) => {
99
90
  )}
100
91
  </View>
101
92
  </View>
102
- {/* {dim[0] > dim[1] + 150 ? (
103
- <View style={style.full}>
104
- <Illustration />
105
- </View>
106
- ) : (
107
- <></>
108
- )} */}
109
93
  </View>
110
- {/* </KeyboardAvoidingView> */}
111
- </View>
112
- // </ImageBackground>
94
+ </ScrollView>
113
95
  );
114
96
  };
115
97
 
116
98
  const style = StyleSheet.create({
117
- full: {flex: 1},
118
99
  illustration: {flex: 1, alignSelf: 'flex-end'},
119
100
  main: {
120
- flex: 2,
121
- justifyContent: 'space-evenly',
101
+ paddingVertical: '8%',
122
102
  marginHorizontal: '8%',
123
- marginVertical: '2%',
103
+ display: 'flex',
104
+ justifyContent: 'space-evenly',
105
+ flexGrow: 1,
124
106
  },
125
107
  nav: {
126
108
  flex: 1,
@@ -65,7 +65,8 @@ const useChatNotification = (
65
65
  };
66
66
 
67
67
  const NotificationControl = ({children, chatDisplayed, setSidePanel}) => {
68
- const {messageStore, privateMessageStore, userList, localUid} = useContext(ChatContext);
68
+ const {messageStore, privateMessageStore, userList, localUid} =
69
+ useContext(ChatContext);
69
70
  const [
70
71
  lastCheckedPublicState,
71
72
  setLastCheckedPublicState,
@@ -116,8 +117,13 @@ const NotificationControl = ({children, chatDisplayed, setSidePanel}) => {
116
117
  messageStore[messageStore.length - 1]?.uid !== localUid
117
118
  ) {
118
119
  Toast.show({
119
- text1: messageStore[messageStore.length - 1]?.msg.length > 50 ? messageStore[messageStore.length - 1]?.msg.slice(1, 50) + '...' : messageStore[messageStore.length - 1]?.msg.slice(1),
120
- text2: userList[messageStore[messageStore.length - 1]?.uid] ? 'From: ' + userList[messageStore[messageStore.length - 1]?.uid].name : '',
120
+ text1:
121
+ messageStore[messageStore.length - 1]?.msg.length > 50
122
+ ? messageStore[messageStore.length - 1]?.msg.slice(1, 50) + '...'
123
+ : messageStore[messageStore.length - 1]?.msg.slice(1),
124
+ text2: userList[messageStore[messageStore.length - 1]?.uid]
125
+ ? 'From: ' + userList[messageStore[messageStore.length - 1]?.uid].name
126
+ : '',
121
127
  visibilityTime: 1000,
122
128
  onPress: () => {
123
129
  setSidePanel(SidePanelType.Chat);
@@ -212,8 +218,10 @@ enum RnEncryptionEnum {
212
218
  }
213
219
 
214
220
  const VideoCall: React.FC = () => {
215
- const {store} = useContext(StorageContext);
216
- const [username, setUsername] = useState('Getting name...');
221
+ const {store, setStore} = useContext(StorageContext);
222
+ const getInitialUsername = () =>
223
+ store?.displayName ? store.displayName : '';
224
+ const [username, setUsername] = useState(getInitialUsername);
217
225
  const [participantsView, setParticipantsView] = useState(false);
218
226
  const [callActive, setCallActive] = useState($config.PRECALL ? false : true);
219
227
  const [layout, setLayout] = useState(Layout.Grid);
@@ -223,9 +231,9 @@ const VideoCall: React.FC = () => {
223
231
  const [sidePanel, setSidePanel] = useState<SidePanelType>(SidePanelType.None);
224
232
  const {phrase} = useParams();
225
233
  const [errorMessage, setErrorMessage] = useState(null);
226
- let isHost = true; //change to false by default after testing
227
- let title = null;
228
- let rtcProps = {
234
+ const [isHost, setIsHost] = React.useState(false);
235
+ const [title, setTitle] = React.useState('');
236
+ const [rtcProps, setRtcProps] = React.useState({
229
237
  appId: $config.APP_ID,
230
238
  channel: null,
231
239
  uid: null,
@@ -238,60 +246,59 @@ const VideoCall: React.FC = () => {
238
246
  encryption: $config.ENCRYPTION_ENABLED
239
247
  ? {key: null, mode: RnEncryptionEnum.AES128XTS, screenKey: null}
240
248
  : false,
241
- };
242
- let data, loading, error;
249
+ });
243
250
 
244
- ({data, loading, error} = useQuery(
251
+ const {data, loading, error} = useQuery(
245
252
  store.token === null
246
253
  ? JOIN_CHANNEL_PHRASE
247
254
  : JOIN_CHANNEL_PHRASE_AND_GET_USER,
248
255
  {
249
256
  variables: {passphrase: phrase},
250
257
  },
251
- ));
258
+ );
252
259
 
253
- if (error) {
254
- console.log('error', error);
255
- // console.log('error data', data);
256
- if (!errorMessage) {
257
- setErrorMessage(error);
260
+ React.useEffect(() => {
261
+ if (error) {
262
+ console.log('error', error);
263
+ // console.log('error data', data);
264
+ if (!errorMessage) {
265
+ setErrorMessage(error);
266
+ }
267
+ return;
258
268
  }
259
- }
260
269
 
261
- if (!loading && data) {
262
- console.log('token:', rtcProps.token);
263
- console.log('error', data.error);
264
- rtcProps = {
265
- appId: $config.APP_ID,
266
- channel: data.joinChannel.channel,
267
- uid: data.joinChannel.mainUser.uid,
268
- token: data.joinChannel.mainUser.rtc,
269
- rtm: data.joinChannel.mainUser.rtm,
270
- dual: true,
271
- profile: $config.PROFILE,
272
- encryption: $config.ENCRYPTION_ENABLED
273
- ? {
274
- key: data.joinChannel.secret,
275
- mode: RnEncryptionEnum.AES128XTS,
276
- screenKey: data.joinChannel.secret,
277
- }
278
- : false,
279
- screenShareUid: data.joinChannel.screenShare.uid,
280
- screenShareToken: data.joinChannel.screenShare.rtc,
281
- };
282
- isHost = data.joinChannel.isHost;
283
- title = data.joinChannel.title;
284
- console.log('query done: ', data, queryComplete);
285
- if (username === 'Getting name...') {
270
+ if (!loading && data) {
271
+ console.log('token:', rtcProps.token);
272
+ console.log('error', data.error);
273
+ setRtcProps({
274
+ appId: $config.APP_ID,
275
+ channel: data.joinChannel.channel,
276
+ uid: data.joinChannel.mainUser.uid,
277
+ token: data.joinChannel.mainUser.rtc,
278
+ rtm: data.joinChannel.mainUser.rtm,
279
+ dual: true,
280
+ profile: $config.PROFILE,
281
+ encryption: $config.ENCRYPTION_ENABLED
282
+ ? {
283
+ key: data.joinChannel.secret,
284
+ mode: RnEncryptionEnum.AES128XTS,
285
+ screenKey: data.joinChannel.secret,
286
+ }
287
+ : false,
288
+ screenShareUid: data.joinChannel.screenShare.uid,
289
+ screenShareToken: data.joinChannel.screenShare.rtc,
290
+ });
291
+ setIsHost(data.joinChannel.isHost);
292
+ setTitle(data.joinChannel.title);
293
+ console.log('query done: ', data, queryComplete);
294
+ // 1. Store the display name from API
286
295
  if (data.getUser) {
287
296
  setUsername(data.getUser.name);
288
- } else {
289
- setUsername('');
290
297
  }
298
+ console.log('token:', rtcProps.token);
299
+ queryComplete ? {} : setQueryComplete(true);
291
300
  }
292
- console.log('token:', rtcProps.token);
293
- queryComplete ? {} : setQueryComplete(true);
294
- }
301
+ }, [error, loading, data]);
295
302
 
296
303
  const history = useHistory();
297
304
  const callbacks = {
@@ -300,6 +307,14 @@ const VideoCall: React.FC = () => {
300
307
  history.push('/');
301
308
  }, 0),
302
309
  };
310
+
311
+ React.useEffect(() => {
312
+ // Update the username in localstorage when username changes
313
+ if (setStore) {
314
+ setStore({token: store?.token || null, displayName: username});
315
+ }
316
+ }, [username]);
317
+
303
318
  // throw new Error("My first Sentry error!");
304
319
  return (
305
320
  <>
@@ -350,7 +365,11 @@ const VideoCall: React.FC = () => {
350
365
  setLastCheckedPublicState
351
366
  }
352
367
  />
353
- <View style={[style.videoView, {backgroundColor: '#ffffff00'}]}>
368
+ <View
369
+ style={[
370
+ style.videoView,
371
+ {backgroundColor: '#ffffff00'},
372
+ ]}>
354
373
  {layout === Layout.Pinned ? (
355
374
  <PinnedVideo />
356
375
  ) : (
@@ -31,7 +31,7 @@ const LogoutButton = () => {
31
31
 
32
32
  const logout = () => {
33
33
  if (setStore) {
34
- setStore({token: null});
34
+ setStore({token: null, displayName: ''});
35
35
  }
36
36
  logoutQuery({variables: {token}}).catch((e) => {
37
37
  console.log(e);
@@ -94,6 +94,7 @@ module.exports = {
94
94
  plugins: [
95
95
  // Adds support for class properties
96
96
  ['transform-define', configVars],
97
+ '@babel/plugin-proposal-optional-chaining',
97
98
  '@babel/plugin-proposal-class-properties',
98
99
  isDevelopment && require.resolve('react-refresh/babel'),
99
100
  ].filter(Boolean),