@momo-kits/foundation 0.168.1-beta.15 → 0.168.1-beta.16

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.
@@ -16,6 +16,7 @@ import {
16
16
  PanResponder,
17
17
  Platform,
18
18
  Pressable,
19
+ StatusBar,
19
20
  StyleSheet,
20
21
  TouchableOpacity,
21
22
  useWindowDimensions,
@@ -39,18 +40,37 @@ import Animated, {
39
40
  } from 'react-native-reanimated';
40
41
  import { scheduleOnRN } from 'react-native-worklets';
41
42
  import layoutStyles from '../Layout/styles';
43
+ import { DuoMetrics, InnerEdgeStyles, useScreenLayout } from '../Layout/utils';
42
44
  import { getDuoTopInset, isIPhoneDuo } from './device';
45
+ import { SideBarButton } from './Components/SideBarButton';
43
46
 
44
47
  // iPhone Duo inner display: center the sheet instead of spanning the width
45
48
  const DUO_REGULAR_MIN_WIDTH = 600;
46
49
 
50
+ const INDICATOR_HEIGHT = 16;
51
+ const HEADER_HEIGHT = 56;
52
+ const DUO_ORIENTATIONS = ['portrait', 'landscape'];
53
+ const SIDE_COLUMN_OFFSET =
54
+ INDICATOR_HEIGHT + (HEADER_HEIGHT - DuoMetrics.controlSize) / 2;
55
+
47
56
  const BottomSheet: React.FC<BottomSheetParams> = props => {
48
57
  const { theme, navigator } = useContext(ApplicationContext);
49
58
  const context = useContext<any>(MiniAppContext);
50
59
  const windowSize = useWindowDimensions();
51
60
  const isDuo = isIPhoneDuo();
52
- const isDuoCentered = isDuo && windowSize.width >= DUO_REGULAR_MIN_WIDTH;
53
- const isPortrait = windowSize.height > windowSize.width;
61
+ const isDuoCentered =
62
+ isDuo &&
63
+ Math.min(windowSize.width, windowSize.height) >= DUO_REGULAR_MIN_WIDTH;
64
+ const isDuoFloating = isDuo && !isDuoCentered;
65
+ const { sideBar } = useScreenLayout();
66
+ const sideColumnWidth = (sideBar?.width ?? 0) - Spacing.M;
67
+ const sideColumn =
68
+ isDuoFloating &&
69
+ sideColumnWidth >= DuoMetrics.controlSize + Spacing.M &&
70
+ sideBar
71
+ ? sideBar
72
+ : undefined;
73
+ const hasSideColumn = !!sideColumn;
54
74
  // 'screen' is the outer display on iPhone Duo, even when unfolded
55
75
  const screenHeight = Dimensions.get('screen').height;
56
76
  const heightDevice = isDuo ? windowSize.height : screenHeight;
@@ -58,7 +78,9 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
58
78
  const insets = useSafeAreaInsets();
59
79
  const heightHeader = useHeaderHeight();
60
80
  const topGap = Math.max(
61
- getDuoTopInset(insets, windowSize.width, windowSize.height),
81
+ sideColumn
82
+ ? insets.top
83
+ : getDuoTopInset(insets, windowSize.width, windowSize.height),
62
84
  Spacing.XL,
63
85
  );
64
86
  const isIOS = Platform.OS === 'ios';
@@ -83,7 +105,10 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
83
105
  }: BottomSheetParams = props.route.params;
84
106
 
85
107
  const translateY = useSharedValue(heightDevice);
108
+ const onDismissRef = useRef(props.route.params?.onDismiss);
109
+ onDismissRef.current = props.route.params?.onDismiss;
86
110
  const [keyboardLift, setKeyboardLift] = useState(0);
111
+ const [sheetTop, setSheetTop] = useState(windowSize.height);
87
112
 
88
113
  // KeyboardAvoidingView lifts the whole sheet past the top on iPhone Duo,
89
114
  // so lift it here and shrink maxHeight by the same amount instead
@@ -179,15 +204,15 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
179
204
  }
180
205
 
181
206
  /**
182
- * emit dismiss event
207
+ * emit dismiss event, once: folding or rotating iPhone Duo changes the
208
+ * window height while the sheet stays open
183
209
  */
184
210
  useEffect(() => {
185
- translateY.value = heightDevice;
186
211
  openAnimation();
187
212
  return () => {
188
- props.route.params?.onDismiss?.(action.current);
213
+ onDismissRef.current?.(action.current);
189
214
  };
190
- }, [heightDevice, openAnimation, props.route.params, translateY]);
215
+ }, [openAnimation]);
191
216
 
192
217
  /**
193
218
  * handler dismiss
@@ -228,13 +253,42 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
228
253
  return () => backHandler.remove();
229
254
  }, [barrierDismissible, onDismiss]);
230
255
 
256
+ const onPressBack = useCallback(() => {
257
+ onDismiss(true, leftOptions?.onPressIconLeft);
258
+ }, [leftOptions, onDismiss]);
259
+
260
+ const onPressClose = useCallback(() => {
261
+ action.current = 'icon_close';
262
+ onDismiss(true);
263
+ }, [onDismiss]);
264
+
265
+ const showBack = !!leftOptions?.onPressIconLeft;
266
+ const iconBack = leftOptions?.iconLeft ?? 'ic_back';
267
+ const sideColumnCount = showBack ? 2 : 1;
268
+ const sideColumnHeight =
269
+ sideColumnCount * DuoMetrics.controlSize +
270
+ (sideColumnCount - 1) * Spacing.M;
271
+ const coversStatusBar = !!sideColumn && sheetTop < sideColumn.top;
272
+
273
+ useEffect(() => {
274
+ if (!coversStatusBar) {
275
+ return;
276
+ }
277
+ const entry = StatusBar.pushStackEntry({
278
+ barStyle: theme.dark ? 'light-content' : 'dark-content',
279
+ animated: true,
280
+ });
281
+ return () => StatusBar.popStackEntry(entry);
282
+ }, [coversStatusBar, theme.dark]);
283
+
231
284
  /**
232
285
  * render header
233
286
  */
234
287
  const renderHeader = useCallback(() => {
288
+ const showButtons = !hasSideColumn;
235
289
  return (
236
290
  <View {...panResponder.panHandlers}>
237
- <View style={{ height: 16 }}>
291
+ <View style={{ height: INDICATOR_HEIGHT }}>
238
292
  <View style={styles.indicator} />
239
293
  </View>
240
294
  <View
@@ -246,14 +300,9 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
246
300
  },
247
301
  ]}
248
302
  >
249
- {leftOptions?.onPressIconLeft ? (
250
- <TouchableOpacity
251
- style={styles.iconButton}
252
- onPress={() => {
253
- onDismiss(true, leftOptions.onPressIconLeft);
254
- }}
255
- >
256
- <Icon source={leftOptions.iconLeft ?? 'ic_back'} />
303
+ {showButtons && showBack ? (
304
+ <TouchableOpacity style={styles.iconButton} onPress={onPressBack}>
305
+ <Icon source={iconBack} />
257
306
  </TouchableOpacity>
258
307
  ) : null}
259
308
 
@@ -261,9 +310,15 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
261
310
  <View style={Styles.flex}>{options.header}</View>
262
311
  ) : (
263
312
  <>
264
- {!leftOptions ? <View style={styles.iconButton} /> : null}
313
+ {showButtons && !leftOptions ? (
314
+ <View style={styles.iconButton} />
315
+ ) : null}
265
316
  <Text
266
- style={[Styles.flex, { textAlign: 'center' }]}
317
+ style={[
318
+ Styles.flex,
319
+ styles.title,
320
+ !showButtons && styles.titleInset,
321
+ ]}
267
322
  numberOfLines={1}
268
323
  typography="header_default_bold"
269
324
  >
@@ -271,28 +326,63 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
271
326
  </Text>
272
327
  </>
273
328
  )}
274
- <TouchableOpacity
275
- style={styles.iconButton}
276
- onPress={() => {
277
- action.current = 'icon_close';
278
- onDismiss(true);
279
- }}
280
- >
281
- <Icon source="navigation_close" />
282
- </TouchableOpacity>
329
+ {showButtons ? (
330
+ <TouchableOpacity style={styles.iconButton} onPress={onPressClose}>
331
+ <Icon source="navigation_close" />
332
+ </TouchableOpacity>
333
+ ) : null}
283
334
  </View>
284
335
  </View>
285
336
  );
286
337
  }, [
287
- onDismiss,
338
+ hasSideColumn,
339
+ iconBack,
288
340
  leftOptions,
341
+ onPressBack,
342
+ onPressClose,
289
343
  options.header,
290
344
  options.title,
291
345
  panResponder.panHandlers,
346
+ showBack,
292
347
  theme.colors.border.default,
293
348
  useDivider,
294
349
  ]);
295
350
 
351
+ /**
352
+ * iPhone Duo folded: back and close move to the side bar column, drawn on
353
+ * the part of the sheet under the side safe area. They line up with the
354
+ * header row, stay below the status bar cluster on a tall sheet and above a
355
+ * camera at the bottom end of the strip.
356
+ */
357
+ const renderSideColumn = () => {
358
+ if (!sideColumn) {
359
+ return null;
360
+ }
361
+ const lowestTop =
362
+ windowSize.height - sideColumn.bottom - sideColumnHeight - sheetTop;
363
+ const top = Math.min(
364
+ Math.max(sideColumn.top - sheetTop, SIDE_COLUMN_OFFSET),
365
+ lowestTop,
366
+ );
367
+
368
+ return (
369
+ <View
370
+ pointerEvents={'box-none'}
371
+ style={[
372
+ styles.sideColumn,
373
+ sideColumn.edge === 'right' ? styles.alignRight : styles.alignLeft,
374
+ InnerEdgeStyles[sideColumn.edge],
375
+ { top, width: sideColumnWidth },
376
+ ]}
377
+ >
378
+ {showBack ? (
379
+ <SideBarButton icon={iconBack} onPress={onPressBack} />
380
+ ) : null}
381
+ <SideBarButton icon="navigation_close" onPress={onPressClose} />
382
+ </View>
383
+ );
384
+ };
385
+
296
386
  const animatedStyle = useAnimatedStyle(() => {
297
387
  return {
298
388
  transform: [{ translateY: translateY.value }],
@@ -310,12 +400,9 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
310
400
  };
311
401
  });
312
402
 
313
- // landscape side buttons span the full height, so inset the content; in
314
- // portrait the side status bar only covers the top corner
315
- const needsSideInset = isDuo && !isDuoCentered && !isPortrait;
316
- const sideInsetStyle = needsSideInset && {
317
- paddingLeft: insets.left,
318
- paddingRight: insets.right,
403
+ const sideInsetStyle = isDuoFloating && {
404
+ paddingLeft: Math.max(insets.left - Spacing.M, 0),
405
+ paddingRight: Math.max(insets.right - Spacing.M, 0),
319
406
  };
320
407
 
321
408
  const screen = (
@@ -335,6 +422,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
335
422
  }}
336
423
  style={StyleSheet.absoluteFillObject}
337
424
  isModalKit={true}
425
+ supportedOrientations={isDuo ? DUO_ORIENTATIONS : undefined}
338
426
  >
339
427
  <KeyboardAvoidingView
340
428
  behavior={Platform.select({
@@ -357,18 +445,26 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
357
445
  </Pressable>
358
446
 
359
447
  <Animated.View
448
+ onLayout={
449
+ isDuoFloating ? e => setSheetTop(e.nativeEvent.layout.y) : undefined
450
+ }
360
451
  style={[
361
452
  animatedStyle,
362
453
  {
363
454
  backgroundColor,
364
- borderTopLeftRadius: Radius.M,
365
- borderTopRightRadius: Radius.M,
455
+ borderTopLeftRadius: isDuo ? Radius.XL : Radius.M,
456
+ borderTopRightRadius: isDuo ? Radius.XL : Radius.M,
366
457
  overflow: 'hidden',
367
458
  },
368
459
  isDuo && {
369
460
  maxHeight: windowSize.height - topGap - keyboardLift,
370
461
  marginBottom: keyboardLift,
371
462
  },
463
+ isDuoFloating && { marginHorizontal: Spacing.M },
464
+ sideColumn && {
465
+ minHeight:
466
+ SIDE_COLUMN_OFFSET + sideColumnHeight + sideColumn.bottom,
467
+ },
372
468
  isDuoCentered && {
373
469
  // keeps the portrait width in landscape, like system sheets
374
470
  width: Math.min(
@@ -415,6 +511,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
415
511
  }}
416
512
  />
417
513
  )}
514
+ {renderSideColumn()}
418
515
  </Animated.View>
419
516
  </KeyboardAvoidingView>
420
517
  </Container>
@@ -440,10 +537,12 @@ const styles = StyleSheet.create({
440
537
  top: Spacing.S,
441
538
  },
442
539
  header: {
443
- height: 56,
540
+ height: HEADER_HEIGHT,
444
541
  flexDirection: 'row',
445
542
  alignItems: 'center',
446
543
  },
544
+ title: { textAlign: 'center' },
545
+ titleInset: { paddingHorizontal: Spacing.M },
447
546
  iconButton: {
448
547
  width: 24,
449
548
  height: 24,
@@ -452,6 +551,12 @@ const styles = StyleSheet.create({
452
551
  marginHorizontal: Spacing.M,
453
552
  },
454
553
  shrink: { flexShrink: 1 },
554
+ sideColumn: {
555
+ position: 'absolute',
556
+ gap: Spacing.M,
557
+ },
558
+ alignRight: { right: 0 },
559
+ alignLeft: { left: 0 },
455
560
  debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
456
561
  });
457
562
 
@@ -18,7 +18,7 @@ import { Styles } from '../Consts';
18
18
  import Navigation from './Navigation';
19
19
  import { ModalParams } from './types';
20
20
  import BottomSheet from './BottomSheet';
21
- import { getDuoTopInset, isIPhoneDuo } from './device';
21
+ import { getDuoModalBounds, isIPhoneDuo } from './device';
22
22
  import { scheduleOnRN } from 'react-native-worklets';
23
23
 
24
24
  const ModalScreen: React.FC<any> = props => {
@@ -42,6 +42,7 @@ const Modal: React.FC<ModalParams> = props => {
42
42
  const Component = useRef(screen).current;
43
43
  const insets = useSafeAreaInsets();
44
44
  const windowSize = useWindowDimensions();
45
+ const isDuo = isIPhoneDuo();
45
46
 
46
47
  /**
47
48
  * Fire auto_popup_displayed tracking event on mount
@@ -135,6 +136,7 @@ const Modal: React.FC<ModalParams> = props => {
135
136
  onRequestClose={onDismiss}
136
137
  style={StyleSheet.absoluteFillObject}
137
138
  isModalKit={true}
139
+ supportedOrientations={isDuo ? DUO_ORIENTATIONS : undefined}
138
140
  >
139
141
  <KeyboardAvoidingView
140
142
  style={Styles.flexCenter}
@@ -152,14 +154,13 @@ const Modal: React.FC<ModalParams> = props => {
152
154
  opacity,
153
155
  transform: [{ scale }],
154
156
  },
155
- // center below the side status bar and above the home indicator
156
- isIPhoneDuo() && {
157
- marginTop: getDuoTopInset(
158
- insets,
159
- windowSize.width,
160
- windowSize.height,
161
- ),
157
+ isDuo && styles.shrink,
158
+ isDuo && {
159
+ marginTop: insets.top,
162
160
  marginBottom: insets.bottom,
161
+ marginLeft: insets.left,
162
+ marginRight: insets.right,
163
+ ...getDuoModalBounds(insets, windowSize.width, windowSize.height),
163
164
  },
164
165
  modalStyle,
165
166
  ]}
@@ -171,11 +172,14 @@ const Modal: React.FC<ModalParams> = props => {
171
172
  );
172
173
  };
173
174
 
175
+ const DUO_ORIENTATIONS = ['portrait', 'landscape'];
176
+
174
177
  const styles = StyleSheet.create({
175
178
  overlayContent: {
176
179
  flex: 1,
177
180
  backgroundColor: 'rgba(0, 0, 0, 0.6)',
178
181
  },
182
+ shrink: { flexShrink: 1 },
179
183
  });
180
184
 
181
185
  export default ModalScreen;
@@ -1,9 +1,13 @@
1
1
  import { Dimensions, Platform, ScaledSize } from 'react-native';
2
2
  import type { EdgeInsets } from 'react-native-safe-area-context';
3
+ import { Spacing } from '../Consts';
3
4
 
4
5
  // widest short side of any single-display iPhone
5
6
  const IPHONE_MAX_SHORT_SIDE = 440;
6
7
 
8
+ const DUO_MODAL_MAX_WIDTH = 440;
9
+ const DUO_MODAL_MAX_HEIGHT = 640;
10
+
7
11
  // iPhone Duo reports idiom "phone"; 'screen' stays on the outer display, so it
8
12
  // still matches when Split View narrows the window
9
13
  const isIPhoneDuo = () => {
@@ -26,4 +30,23 @@ const getDuoTopInset = (insets: EdgeInsets, width: number, height: number) =>
26
30
  height > width ? Math.max(insets.left, insets.right) * 2 : 0,
27
31
  );
28
32
 
29
- export { isIPhoneDuo, getDuoTopInset };
33
+ /**
34
+ * Max modal size on iPhone Duo: inside the safe area, so clear of the side
35
+ * toolbar strip, and capped so it stays a dialog on the inner display.
36
+ */
37
+ const getDuoModalBounds = (
38
+ insets: EdgeInsets,
39
+ width: number,
40
+ height: number,
41
+ ) => ({
42
+ maxWidth: Math.min(
43
+ width - insets.left - insets.right - Spacing.XL * 2,
44
+ DUO_MODAL_MAX_WIDTH,
45
+ ),
46
+ maxHeight: Math.min(
47
+ height - insets.top - insets.bottom - Spacing.XL * 2,
48
+ DUO_MODAL_MAX_HEIGHT,
49
+ ),
50
+ });
51
+
52
+ export { isIPhoneDuo, getDuoTopInset, getDuoModalBounds };
package/Layout/utils.ts CHANGED
@@ -510,6 +510,7 @@ const useGridSystem = () => {
510
510
  export {
511
511
  DuoMetrics,
512
512
  HeaderMetrics,
513
+ InnerEdgeStyles,
513
514
  getHeaderMargin,
514
515
  getHeaderRowOptions,
515
516
  useGridSystem,
@@ -8,7 +8,7 @@ import { Image } from '../Image';
8
8
  import { Text, useScaleSize } from '../Text';
9
9
  import { PopupNotifyProps } from './types';
10
10
  import { scheduleOnRN } from 'react-native-worklets';
11
- import { usePopupMaxHeight, usePopupWidth } from './utils';
11
+ import { getPopupRadius, usePopupMaxHeight, usePopupWidth } from './utils';
12
12
 
13
13
  const PopupNotify: React.FC<PopupNotifyProps> = ({
14
14
  image,
@@ -26,6 +26,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
26
26
  const [scrollContent, setScrollContent] = useState(false);
27
27
  const popupWidth = usePopupWidth();
28
28
  const maxHeight = usePopupMaxHeight();
29
+ const radius = getPopupRadius();
29
30
  const scaledMaxHeight = useScaleSize(172);
30
31
 
31
32
  const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
@@ -170,7 +171,15 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
170
171
 
171
172
  const body = (
172
173
  <>
173
- {!!image && <Image source={{ uri: image }} style={styles.image} />}
174
+ {!!image && (
175
+ <Image
176
+ source={{ uri: image }}
177
+ style={[
178
+ styles.image,
179
+ { borderTopLeftRadius: radius, borderTopRightRadius: radius },
180
+ ]}
181
+ />
182
+ )}
174
183
  <View style={styles.content}>
175
184
  <Text
176
185
  typography={'header_default_bold'}
@@ -218,9 +227,9 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
218
227
  <View
219
228
  accessibilityLabel={'popup_notify'}
220
229
  style={[
221
- styles.container,
222
230
  {
223
231
  backgroundColor: theme.colors.background.surface,
232
+ borderRadius: radius,
224
233
  width: popupWidth,
225
234
  maxHeight,
226
235
  },
@@ -231,7 +240,13 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
231
240
  body
232
241
  ) : (
233
242
  // scrolls when iPhone Duo landscape is too short; actions stay visible
234
- <ScrollView style={styles.body} bounces={false}>
243
+ <ScrollView
244
+ style={[
245
+ styles.body,
246
+ { borderTopLeftRadius: radius, borderTopRightRadius: radius },
247
+ ]}
248
+ bounces={false}
249
+ >
235
250
  {body}
236
251
  </ScrollView>
237
252
  )}
@@ -242,17 +257,12 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
242
257
  };
243
258
 
244
259
  const styles = StyleSheet.create({
245
- container: {
246
- borderRadius: Radius.L,
247
- },
248
260
  debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
249
261
  image: {
250
- borderTopLeftRadius: Radius.L,
251
- borderTopRightRadius: Radius.L,
252
262
  aspectRatio: 1.7777,
253
263
  overflow: 'hidden',
254
264
  },
255
- body: { flexShrink: 1 },
265
+ body: { flexShrink: 1, overflow: 'hidden' },
256
266
  content: { padding: Spacing.XL },
257
267
  description: {
258
268
  marginTop: Spacing.S,
package/Popup/utils.ts CHANGED
@@ -1,32 +1,26 @@
1
1
  import { Dimensions, useWindowDimensions } from 'react-native';
2
2
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
3
- import { Spacing } from '../Consts';
4
- import { getDuoTopInset, isIPhoneDuo } from '../Application/device';
5
-
6
- // width of a system alert on the iPhone Duo inner display, in both orientations
7
- const DUO_POPUP_MAX_WIDTH = 440;
3
+ import { Radius, Spacing } from '../Consts';
4
+ import { getDuoModalBounds, isIPhoneDuo } from '../Application/device';
8
5
 
9
6
  const usePopupWidth = () => {
10
- const windowSize = useWindowDimensions();
7
+ const insets = useSafeAreaInsets();
8
+ const { width, height } = useWindowDimensions();
11
9
  if (!isIPhoneDuo()) {
12
10
  return Dimensions.get('window').width - Spacing.XL * 2;
13
11
  }
14
- return Math.min(windowSize.width - Spacing.XL * 2, DUO_POPUP_MAX_WIDTH);
12
+ return getDuoModalBounds(insets, width, height).maxWidth;
15
13
  };
16
14
 
17
- // room left for a popup on iPhone Duo, where landscape is too short for it
18
15
  const usePopupMaxHeight = () => {
19
16
  const insets = useSafeAreaInsets();
20
17
  const { width, height } = useWindowDimensions();
21
18
  if (!isIPhoneDuo()) {
22
19
  return undefined;
23
20
  }
24
- return (
25
- height -
26
- getDuoTopInset(insets, width, height) -
27
- insets.bottom -
28
- Spacing.XL * 2
29
- );
21
+ return getDuoModalBounds(insets, width, height).maxHeight;
30
22
  };
31
23
 
32
- export { usePopupWidth, usePopupMaxHeight };
24
+ const getPopupRadius = () => (isIPhoneDuo() ? Radius.XL : Radius.L);
25
+
26
+ export { usePopupWidth, usePopupMaxHeight, getPopupRadius };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/foundation",
3
- "version": "0.168.1-beta.15",
3
+ "version": "0.168.1-beta.16",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {},