@momo-kits/foundation 0.167.1-beta.7 → 0.167.1-duo.12

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 (46) hide show
  1. package/Application/BottomSheet.tsx +115 -14
  2. package/Application/BottomTab/BottomTabBar.tsx +6 -3
  3. package/Application/BottomTab/DuoBarCompression.tsx +135 -0
  4. package/Application/BottomTab/DuoTabBar.tsx +462 -0
  5. package/Application/BottomTab/index.tsx +155 -134
  6. package/Application/Components/DuoGlassBackground.tsx +179 -0
  7. package/Application/Components/DuoQuickReturnHeader.tsx +42 -0
  8. package/Application/Components/HeaderExtendHeader.tsx +65 -28
  9. package/Application/Components/HeaderLeft.tsx +23 -0
  10. package/Application/Components/HeaderRight.tsx +104 -9
  11. package/Application/Components/HeaderTitle.tsx +47 -21
  12. package/Application/Components/OptionalGlassView.ts +11 -0
  13. package/Application/Components/SearchHeader.tsx +15 -14
  14. package/Application/Components/SideBarButton.tsx +128 -0
  15. package/Application/ModalScreen.tsx +16 -2
  16. package/Application/NavigationContainer.tsx +36 -48
  17. package/Application/Navigator.ts +1 -3
  18. package/Application/StackScreen.tsx +2 -5
  19. package/Application/WidgetContainer.tsx +9 -15
  20. package/Application/device.ts +29 -0
  21. package/Application/types.ts +10 -1
  22. package/Application/utils.tsx +10 -3
  23. package/Consts/index.ts +0 -1
  24. package/Consts/theme.ts +3 -4
  25. package/Input/Input.tsx +3 -4
  26. package/Input/InputMoney.tsx +31 -51
  27. package/Input/InputPhoneNumber.tsx +3 -4
  28. package/Input/InputSearch.tsx +3 -4
  29. package/Input/InputTextArea.tsx +3 -4
  30. package/Layout/Card.tsx +8 -26
  31. package/Layout/FloatingButton.tsx +3 -3
  32. package/Layout/Item.tsx +1 -10
  33. package/Layout/ReservedRegions.tsx +47 -0
  34. package/Layout/Screen.tsx +240 -48
  35. package/Layout/Section.tsx +5 -18
  36. package/Layout/index.ts +4 -4
  37. package/Layout/styles.ts +5 -0
  38. package/Layout/utils.ts +375 -5
  39. package/Popup/PopupNotify.tsx +33 -22
  40. package/Popup/PopupPromotion.tsx +20 -8
  41. package/Popup/utils.ts +32 -0
  42. package/Text/index.tsx +5 -15
  43. package/Text/utils.ts +1 -2
  44. package/package.json +3 -2
  45. package/Consts/designSystemFont.ts +0 -25
  46. package/Layout/GridSystem.tsx +0 -137
package/Layout/Screen.tsx CHANGED
@@ -9,6 +9,7 @@ import React, {
9
9
  useContext,
10
10
  useEffect,
11
11
  useImperativeHandle,
12
+ useMemo,
12
13
  useRef,
13
14
  } from 'react';
14
15
  import {
@@ -21,11 +22,14 @@ import {
21
22
  ScrollViewProps,
22
23
  StatusBar,
23
24
  StatusBarStyle,
24
- useWindowDimensions,
25
25
  View,
26
26
  ViewProps,
27
27
  } from 'react-native';
28
- import { useSharedValue, withTiming } from 'react-native-reanimated';
28
+ import {
29
+ useAnimatedReaction,
30
+ useSharedValue,
31
+ withTiming,
32
+ } from 'react-native-reanimated';
29
33
  import {
30
34
  useSafeAreaFrame,
31
35
  useSafeAreaInsets,
@@ -44,7 +48,7 @@ import styles from './styles';
44
48
  import { HeaderType } from './types';
45
49
  import { InputRef } from '../Input';
46
50
  import { exportHeaderTitle, getOptions } from '../Application/utils';
47
- import { validateChildren } from './utils';
51
+ import { getHeaderMargin, useScreenLayout, validateChildren } from './utils';
48
52
  import Section from './Section';
49
53
  import {
50
54
  HeaderBackground,
@@ -53,6 +57,12 @@ import {
53
57
  HeaderTitle,
54
58
  SearchHeader,
55
59
  } from '../Application';
60
+ import {
61
+ DuoGlassBackground,
62
+ DuoScrollGradient,
63
+ } from '../Application/Components/DuoGlassBackground';
64
+ import { DuoQuickReturnHeader } from '../Application/Components/DuoQuickReturnHeader';
65
+ import { useDuoTabBarInset } from '../Application/BottomTab/DuoTabBar';
56
66
 
57
67
  export interface ScreenProps extends ViewProps {
58
68
  /**
@@ -118,7 +128,8 @@ export interface ScreenProps extends ViewProps {
118
128
  layoutOffset?: -8 | -24 | -56 | number;
119
129
 
120
130
  /**
121
- * Optional. Width of the right header.
131
+ * Optional. Width of the right header. Defaults to the toolkit width (73), or 0 when
132
+ * iPhone Duo floats the toolkit into its side bar.
122
133
  */
123
134
  headerRightWidth?: 0 | 73 | 110 | number;
124
135
 
@@ -187,7 +198,7 @@ const Screen = forwardRef(
187
198
  footerComponent: Footer,
188
199
  marginFooter = true,
189
200
  layoutOffset = -56,
190
- headerRightWidth = 73,
201
+ headerRightWidth,
191
202
  backgroundColor,
192
203
  headerType = 'default',
193
204
  floatingButtonProps,
@@ -204,8 +215,8 @@ const Screen = forwardRef(
204
215
  ref: any,
205
216
  ) => {
206
217
  const screenRef = useRef<View | ScrollView>(null);
207
- const { width: widthDevice } = useWindowDimensions();
208
- const { theme, navigator } = useContext(ApplicationContext);
218
+ const layout = useScreenLayout();
219
+ const { theme } = useContext(ApplicationContext);
209
220
  const screen: any = useContext(ScreenContext);
210
221
  const insets = useSafeAreaInsets();
211
222
  const frame = useSafeAreaFrame();
@@ -245,15 +256,66 @@ const Screen = forwardRef(
245
256
  }, [customAnimatedValue, internalShared]);
246
257
 
247
258
  const currentTint = useRef<string | undefined>(undefined);
248
-
259
+
249
260
  const isTab = !!screen?.bottomTab;
261
+ // Duo floating tab bar overlays the tab content instead of taking layout space
262
+ const duoTabInset = useDuoTabBarInset();
250
263
 
251
264
  let handleScroll;
252
265
  let Component: any = View;
253
266
 
254
- const bottomInset = Platform.OS === 'ios' ? Math.min(insets.bottom, 21) : insets.bottom;
267
+ const bottomInset =
268
+ Platform.OS === 'ios' ? Math.min(insets.bottom, 21) : insets.bottom;
269
+ const hasSideBar = !!layout.sideBar;
270
+ // iPhone Duo: content scrolls under a glass header instead of starting below it
271
+ const useDuoGlass =
272
+ hasSideBar &&
273
+ (headerType === 'default' || headerType === 'extended') &&
274
+ !animatedHeader &&
275
+ !inputSearchProps;
276
+
277
+ // iPhone Duo: the header leaves with the content and returns on a reverse scroll
278
+ const useQuickReturn =
279
+ hasSideBar && scrollable && (useDuoGlass || !!animatedHeader);
280
+ const headerHide = useSharedValue(0);
281
+ const lastScrollY = useSharedValue(0);
282
+
283
+ useAnimatedReaction(
284
+ () => sharedValue.value,
285
+ y => {
286
+ const delta = y - lastScrollY.value;
287
+ lastScrollY.value = y;
288
+ if (!useQuickReturn || y <= 0) {
289
+ headerHide.value = 0;
290
+ return;
291
+ }
292
+ headerHide.value = Math.min(
293
+ Math.max(headerHide.value + delta, 0),
294
+ heightHeader,
295
+ );
296
+ },
297
+ [useQuickReturn, heightHeader],
298
+ );
299
+
300
+ const quickReturnOptions: StackNavigationOptions = useMemo(
301
+ () =>
302
+ useQuickReturn
303
+ ? {
304
+ header: (props: any) => (
305
+ <DuoQuickReturnHeader {...props} offset={headerHide} />
306
+ ),
307
+ }
308
+ : { header: undefined },
309
+ [useQuickReturn, headerHide],
310
+ );
311
+
255
312
  let keyboardOffset = heightHeader - bottomInset;
256
- if (headerType === 'extended' || animatedHeader || inputSearchProps) {
313
+ if (
314
+ headerType === 'extended' ||
315
+ animatedHeader ||
316
+ inputSearchProps ||
317
+ useDuoGlass
318
+ ) {
257
319
  keyboardOffset = -bottomInset;
258
320
  }
259
321
 
@@ -280,9 +342,13 @@ const Screen = forwardRef(
280
342
 
281
343
  case 'extended':
282
344
  options = {
345
+ ...quickReturnOptions,
283
346
  headerShown: true,
284
347
  headerTransparent: true,
285
- headerBackground: () => null,
348
+ headerBackground: () =>
349
+ hasSideBar ? (
350
+ <DuoGlassBackground animatedValue={sharedValue} />
351
+ ) : null,
286
352
  headerTitle: (props: any) => <HeaderTitle {...props} />,
287
353
  };
288
354
  if (inputSearchProps) {
@@ -305,6 +371,19 @@ const Screen = forwardRef(
305
371
  break;
306
372
 
307
373
  default:
374
+ if (hasSideBar && !inputSearchProps) {
375
+ options = {
376
+ ...quickReturnOptions,
377
+ headerTransparent: true,
378
+ headerTintColor: Colors.black_17,
379
+ headerShown: true,
380
+ headerBackground: () => (
381
+ <DuoGlassBackground animatedValue={sharedValue} />
382
+ ),
383
+ headerTitle: (props: any) => <HeaderTitle {...props} />,
384
+ };
385
+ break;
386
+ }
308
387
  options = {
309
388
  headerTransparent: false,
310
389
  headerTintColor: Colors.black_17,
@@ -339,7 +418,7 @@ const Screen = forwardRef(
339
418
  }
340
419
  }
341
420
 
342
- navigation?.instance?.setOptions(options);
421
+ navigation?.instance?.setOptions({ header: undefined, ...options });
343
422
  },
344
423
  [
345
424
  gradientColor,
@@ -348,6 +427,8 @@ const Screen = forwardRef(
348
427
  navigation?.instance,
349
428
  sharedValue,
350
429
  useShadowHeader,
430
+ hasSideBar,
431
+ quickReturnOptions,
351
432
  ],
352
433
  );
353
434
 
@@ -363,18 +444,26 @@ const Screen = forwardRef(
363
444
  }
364
445
 
365
446
  options = {
447
+ ...quickReturnOptions,
366
448
  headerTintColor: currentTint.current ?? Colors.black_17,
367
449
  headerTransparent: true,
368
- headerBackground: (props: any) => (
369
- <HeaderBackground
370
- {...props}
371
- animatedValue={sharedValue}
372
- useGradient={false}
373
- useShadowHeader={useShadowHeader}
374
- headerBackground={headerBackground}
375
- gradientColor={gradientColor}
376
- />
377
- ),
450
+ headerBackground: (props: any) =>
451
+ hasSideBar ? (
452
+ // glass shows once the banner has scrolled under the header
453
+ <DuoGlassBackground
454
+ animatedValue={sharedValue}
455
+ fadeStart={Math.max(210 + layoutOffset - heightHeader, 0)}
456
+ />
457
+ ) : (
458
+ <HeaderBackground
459
+ {...props}
460
+ animatedValue={sharedValue}
461
+ useGradient={false}
462
+ useShadowHeader={useShadowHeader}
463
+ headerBackground={headerBackground}
464
+ gradientColor={gradientColor}
465
+ />
466
+ ),
378
467
  headerTitle: (props: any) => {
379
468
  return <HeaderTitle {...props} />;
380
469
  },
@@ -395,6 +484,10 @@ const Screen = forwardRef(
395
484
  navigation?.instance,
396
485
  sharedValue,
397
486
  useShadowHeader,
487
+ hasSideBar,
488
+ layoutOffset,
489
+ heightHeader,
490
+ quickReturnOptions,
398
491
  ],
399
492
  );
400
493
 
@@ -418,14 +511,20 @@ const Screen = forwardRef(
418
511
  ),
419
512
  };
420
513
 
421
- navigation?.instance?.setOptions(options);
514
+ navigation?.instance?.setOptions({ header: undefined, ...options });
422
515
  }, [navigation?.instance, sharedValue]);
423
516
 
424
517
  /**
425
518
  * export search header
426
519
  */
427
520
  const setSearchHeader = (params: SearchHeaderProps) => {
428
- const searchWidth = widthDevice - 24;
521
+ let searchWidth = layout.width - 24;
522
+ let searchLeft = Spacing.M;
523
+ if (layout.sideBar) {
524
+ // back floats in the side bar: the search spans the content width
525
+ searchWidth = layout.contentWidth - Spacing.M * 2;
526
+ searchLeft = Spacing.M - getHeaderMargin(layout.width);
527
+ }
429
528
  const options: StackNavigationOptions = {
430
529
  headerRight: undefined,
431
530
  headerTitleContainerStyle: {
@@ -437,10 +536,10 @@ const Screen = forwardRef(
437
536
  marginHorizontal: 0,
438
537
  marginVertical: 0,
439
538
  margin: 0,
440
- left: Spacing.M,
539
+ left: searchLeft,
441
540
  },
442
541
  headerLeft: (props: any) =>
443
- params?.hiddenBack ? null : <HeaderLeft {...props} />,
542
+ params?.hiddenBack ? null : <HeaderLeft {...props} floating />,
444
543
  headerTitle: () => (
445
544
  <SearchHeader {...params} animatedValue={sharedValue} />
446
545
  ),
@@ -540,8 +639,36 @@ const Screen = forwardRef(
540
639
  * handle scroll end
541
640
  * @param e
542
641
  */
642
+ /**
643
+ * a half-shown quick return header settles fully in or out
644
+ */
645
+ const snapQuickReturnHeader = (offsetY: number) => {
646
+ const hide = headerHide.value;
647
+ // above heightHeader the header still sits on the content
648
+ if (
649
+ !useQuickReturn ||
650
+ offsetY < heightHeader ||
651
+ hide <= 0 ||
652
+ hide >= heightHeader
653
+ ) {
654
+ return;
655
+ }
656
+ headerHide.value = withTiming(
657
+ hide > heightHeader / 2 ? heightHeader : 0,
658
+ { duration: 200 },
659
+ );
660
+ };
661
+
662
+ const handleMomentumScrollEnd = (
663
+ e: NativeSyntheticEvent<NativeScrollEvent>,
664
+ ) => {
665
+ snapQuickReturnHeader(e.nativeEvent.contentOffset.y);
666
+ scrollViewProps?.onMomentumScrollEnd?.(e);
667
+ };
668
+
543
669
  const handleScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
544
670
  const offsetY = e.nativeEvent.contentOffset.y;
671
+ snapQuickReturnHeader(offsetY);
545
672
  if (inputSearchProps && offsetY < 100 && offsetY > 0) {
546
673
  Animated.timing(animatedValue.current, {
547
674
  toValue: 0,
@@ -591,6 +718,8 @@ const Screen = forwardRef(
591
718
  key={`ScreenItem${index}`}
592
719
  style={{
593
720
  marginTop: space,
721
+ marginLeft: layout.insetLeft,
722
+ marginRight: layout.insetRight,
594
723
  flex: item.props?.expanded ? 1 : undefined,
595
724
  }}
596
725
  onLayout={item.props?.onLayout}
@@ -611,6 +740,8 @@ const Screen = forwardRef(
611
740
  key={`ScreenItem`}
612
741
  style={{
613
742
  marginTop: space,
743
+ marginLeft: layout.insetLeft,
744
+ marginRight: layout.insetRight,
614
745
  flex: item?.props?.expanded ? 1 : undefined,
615
746
  }}
616
747
  onLayout={item?.props?.onLayout}
@@ -637,6 +768,15 @@ const Screen = forwardRef(
637
768
  return newHeight;
638
769
  };
639
770
 
771
+ // without the grid, the content container keeps clear of the horizontal insets.
772
+ // Only set when there are insets, so a caller's paddingHorizontal is never overridden.
773
+ const hasContentInset = layout.insetLeft > 0 || layout.insetRight > 0;
774
+ const contentInsetStyle = !useGridLayout &&
775
+ hasContentInset && {
776
+ paddingLeft: layout.insetLeft,
777
+ paddingRight: layout.insetRight,
778
+ };
779
+
640
780
  return (
641
781
  <View
642
782
  style={[
@@ -649,21 +789,36 @@ const Screen = forwardRef(
649
789
  },
650
790
  ]}
651
791
  >
652
- <HeaderExtendHeader
653
- headerType={headerType}
654
- heightHeader={heightHeader}
655
- headerRightWidth={headerRightWidth}
656
- animatedValue={sharedValue}
657
- inputSearchProps={inputSearchProps}
658
- navigation={navigation}
659
- inputSearchRef={inputSearchRef}
660
- useShadowHeader={useShadowHeader}
661
- gradientColor={gradientColor}
662
- headerBackground={headerBackground}
663
- />
792
+ {useDuoGlass ? (
793
+ <DuoScrollGradient
794
+ animatedValue={sharedValue}
795
+ gradientColor={gradientColor}
796
+ headerBackground={headerBackground}
797
+ heightHeader={heightHeader}
798
+ extended={headerType === 'extended'}
799
+ followScroll={useQuickReturn}
800
+ />
801
+ ) : (
802
+ <HeaderExtendHeader
803
+ headerType={headerType}
804
+ heightHeader={heightHeader}
805
+ headerRightWidth={headerRightWidth}
806
+ animatedValue={sharedValue}
807
+ inputSearchProps={inputSearchProps}
808
+ navigation={navigation}
809
+ inputSearchRef={inputSearchRef}
810
+ useShadowHeader={useShadowHeader}
811
+ gradientColor={gradientColor}
812
+ headerBackground={headerBackground}
813
+ />
814
+ )}
664
815
 
665
816
  <KeyboardAvoidingView
666
- style={Styles.flex}
817
+ style={[
818
+ Styles.flex,
819
+ useDuoGlass &&
820
+ (!scrollable || !!Header) && { paddingTop: heightHeader },
821
+ ]}
667
822
  enabled={enableKeyboardAvoidingView}
668
823
  keyboardVerticalOffset={keyboardVerticalOffset ?? keyboardOffset}
669
824
  behavior={Platform.select({
@@ -679,10 +834,24 @@ const Screen = forwardRef(
679
834
  showsVerticalScrollIndicator={false}
680
835
  onScroll={handleScroll}
681
836
  onScrollEndDrag={handleScrollEnd}
837
+ onMomentumScrollEnd={handleMomentumScrollEnd}
682
838
  scrollEventThrottle={16}
683
- style={[Styles.flex]}
839
+ style={[
840
+ Styles.flex,
841
+ !scrollable && contentInsetStyle,
842
+ !scrollable &&
843
+ !Footer &&
844
+ isTab &&
845
+ !!duoTabInset && { paddingBottom: duoTabInset },
846
+ ]}
684
847
  contentContainerStyle={[
685
848
  scrollable && !Footer && !isTab && { paddingBottom: bottomInset },
849
+ scrollable &&
850
+ !Footer &&
851
+ isTab &&
852
+ !!duoTabInset && { paddingBottom: duoTabInset },
853
+ scrollable && contentInsetStyle,
854
+ useDuoGlass && !Header && { paddingTop: heightHeader },
686
855
  scrollViewProps?.contentContainerStyle,
687
856
  ]}
688
857
  >
@@ -692,28 +861,51 @@ const Screen = forwardRef(
692
861
  </Component>
693
862
 
694
863
  {floatingButtonProps && (
695
- <View>
864
+ <View
865
+ style={{
866
+ marginLeft: layout.insetLeft,
867
+ marginRight: layout.insetRight,
868
+ }}
869
+ >
696
870
  <FloatingButton
697
871
  {...floatingButtonProps}
698
872
  animatedValue={sharedValue}
699
- bottom={Footer || isTab ? 12 : bottomInset + Spacing.S}
873
+ bottom={
874
+ Footer || isTab
875
+ ? 12 + (Footer ? 0 : duoTabInset)
876
+ : bottomInset + Spacing.S
877
+ }
700
878
  />
701
879
  </View>
702
880
  )}
703
881
 
704
882
  {Footer && (
883
+ // with side insets, the clip keeps the shadow off the side bar, only the top one shows
705
884
  <View
885
+ pointerEvents={'box-none'}
706
886
  style={[
707
- styles.shadow,
887
+ hasContentInset && styles.footerClip,
708
888
  {
709
- paddingBottom: bottomInset + Spacing.S,
710
- backgroundColor: theme.colors.background.surface,
889
+ marginLeft: layout.insetLeft,
890
+ marginRight: layout.insetRight,
711
891
  },
712
892
  ]}
713
893
  >
714
- {/* The footer inset is a caller decision, not a platform one — a footer
715
- that carries its own horizontal padding passes `marginFooter={false}`. */}
716
- <Section useMargin={marginFooter}>{Footer}</Section>
894
+ <View
895
+ style={[
896
+ styles.shadow,
897
+ {
898
+ paddingBottom:
899
+ (isTab && duoTabInset ? duoTabInset : bottomInset) +
900
+ Spacing.S,
901
+ backgroundColor: theme.colors.background.surface,
902
+ },
903
+ ]}
904
+ >
905
+ {/* The footer inset is a caller decision, not a platform one — a footer
906
+ that carries its own horizontal padding passes `marginFooter={false}`. */}
907
+ <Section useMargin={marginFooter}>{Footer}</Section>
908
+ </View>
717
909
  </View>
718
910
  )}
719
911
  </KeyboardAvoidingView>
@@ -1,9 +1,8 @@
1
- import React, { useContext } from 'react';
2
- import { Dimensions, View, ViewProps } from 'react-native';
3
- import { useGridSystem } from './utils';
1
+ import React from 'react';
2
+ import { View, ViewProps } from 'react-native';
3
+ import { useGridSystem, useScreenLayout } from './utils';
4
4
  import { GridContextProps } from './types';
5
5
  import { GridContext } from './index';
6
- import { ApplicationContext, MiniAppContext } from '../Context';
7
6
  import styles from './styles';
8
7
  import { Image } from '../Image';
9
8
  import { Spacing } from '../Consts';
@@ -34,18 +33,15 @@ const Section: React.FC<SectionProps> = ({
34
33
  style,
35
34
  ...props
36
35
  }) => {
37
- const { showGrid } = useContext(ApplicationContext);
38
36
  const { numberOfColumns } = useGridSystem();
37
+ const { contentWidth } = useScreenLayout();
39
38
 
40
39
  const gutterSize = 12;
41
40
  let margin = 0;
42
41
  if (useMargin) {
43
42
  margin = 12;
44
43
  }
45
- let widthSection = Dimensions.get('window').width;
46
- if (useMargin) {
47
- widthSection = widthSection - margin * 2;
48
- }
44
+ const widthSection = contentWidth - margin * 2;
49
45
 
50
46
  const sizePerSpan =
51
47
  (widthSection - gutterSize * (numberOfColumns - 1)) / numberOfColumns -
@@ -60,13 +56,6 @@ const Section: React.FC<SectionProps> = ({
60
56
  },
61
57
  };
62
58
 
63
- /**
64
- * render overlay only dev mode
65
- */
66
- const renderOverlay = () => {
67
- return <View pointerEvents={'none'} style={styles.boxGridSection} />;
68
- };
69
-
70
59
  return (
71
60
  <GridContext.Provider value={gridContext}>
72
61
  <View
@@ -90,9 +79,7 @@ const Section: React.FC<SectionProps> = ({
90
79
  style={styles.imageBackground}
91
80
  />
92
81
  )}
93
- {/* Render only allowed children as valid React elements */}
94
82
  {children}
95
- {showGrid && renderOverlay()}
96
83
  </View>
97
84
  </GridContext.Provider>
98
85
  );
package/Layout/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import Card from './Card';
2
2
  import Section from './Section';
3
- import GridSystem from './GridSystem';
4
- import { validateChildren } from './utils';
3
+ import { useScreenLayout, validateChildren } from './utils';
4
+ import type { ScreenLayout, SideBarEdge, SideBarLayout } from './utils';
5
5
  import { createContext } from 'react';
6
6
  import { GridContextProps } from './types';
7
7
  import Item from './Item';
@@ -18,14 +18,14 @@ const GridContext = createContext<GridContextProps>({
18
18
  getSizeSpan: () => 0,
19
19
  });
20
20
 
21
- export type { ScreenProps };
21
+ export type { ScreenProps, ScreenLayout, SideBarEdge, SideBarLayout };
22
22
 
23
23
  export {
24
24
  GridContext,
25
25
  Card,
26
26
  Section,
27
- GridSystem,
28
27
  validateChildren,
28
+ useScreenLayout,
29
29
  Item,
30
30
  ItemList,
31
31
  ItemSectionList,
package/Layout/styles.ts CHANGED
@@ -91,5 +91,10 @@ export default StyleSheet.create({
91
91
  },
92
92
  }),
93
93
  },
94
+ footerClip: {
95
+ marginTop: -Spacing.XL,
96
+ paddingTop: Spacing.XL,
97
+ overflow: 'hidden',
98
+ },
94
99
  debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
95
100
  });