@fountain-ui/lab 2.0.0-beta.42 → 2.0.0-beta.43

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 (30) hide show
  1. package/build/commonjs/BottomSheet/BottomSheetNative.js +15 -3
  2. package/build/commonjs/BottomSheet/BottomSheetNative.js.map +1 -1
  3. package/build/commonjs/BottomSheet/BottomSheetProps.js.map +1 -1
  4. package/build/commonjs/BottomSheet/BottomSheetWeb.js +24 -25
  5. package/build/commonjs/BottomSheet/BottomSheetWeb.js.map +1 -1
  6. package/build/commonjs/BottomSheet/useDynamicSnapPoints.js +37 -21
  7. package/build/commonjs/BottomSheet/useDynamicSnapPoints.js.map +1 -1
  8. package/build/module/BottomSheet/BottomSheetNative.js +16 -5
  9. package/build/module/BottomSheet/BottomSheetNative.js.map +1 -1
  10. package/build/module/BottomSheet/BottomSheetProps.js.map +1 -1
  11. package/build/module/BottomSheet/BottomSheetWeb.js +24 -26
  12. package/build/module/BottomSheet/BottomSheetWeb.js.map +1 -1
  13. package/build/module/BottomSheet/useDynamicSnapPoints.js +33 -22
  14. package/build/module/BottomSheet/useDynamicSnapPoints.js.map +1 -1
  15. package/build/typescript/BottomSheet/BottomSheetProps.d.ts +13 -1
  16. package/build/typescript/BottomSheet/useDynamicSnapPoints.d.ts +7 -6
  17. package/build/typescript/Carousel/Carousel.d.ts +1 -1
  18. package/build/typescript/ViewPager/ViewPager.d.ts +1 -1
  19. package/build/typescript/ViewPager/ViewPager.native.d.ts +1 -1
  20. package/package.json +4 -4
  21. package/src/BottomSheet/BottomSheetNative.tsx +16 -3
  22. package/src/BottomSheet/BottomSheetProps.ts +15 -1
  23. package/src/BottomSheet/BottomSheetWeb.tsx +31 -25
  24. package/src/BottomSheet/useDynamicSnapPoints.ts +49 -28
  25. package/build/commonjs/BottomSheet/BottomSheet.js +0 -177
  26. package/build/commonjs/BottomSheet/BottomSheet.js.map +0 -1
  27. package/build/module/BottomSheet/BottomSheet.js +0 -161
  28. package/build/module/BottomSheet/BottomSheet.js.map +0 -1
  29. package/build/typescript/BottomSheet/BottomSheet.d.ts +0 -2
  30. package/src/BottomSheet/BottomSheet.tsx +0 -184
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useState","useWindowDimensions","convertHeightAsPixel","windowHeight","value","percentageRegex","RegExp","test","percentage","parseFloat","isNaN","Math","round","useDynamicSnapPoints","props","index","currentIndex","initialSnapPoints","height","WINDOW_HEIGHT","snapPoints","setSnapPoints","map","snapPoint","handleContentLayout","event","contentHeight","min","nativeEvent","layout","prevState"],"sources":["useDynamicSnapPoints.ts"],"sourcesContent":["import { useCallback, useState } from 'react';\nimport { LayoutChangeEvent, useWindowDimensions } from 'react-native';\n\ninterface UseDynamicSnapPointsParams {\n index: number;\n initialSnapPoints: (number | string)[];\n}\n\ninterface UseDynamicSnapPointsReturns {\n handleContentLayout: (e: LayoutChangeEvent) => void;\n snapPoints: number[];\n}\n\nconst convertHeightAsPixel = (windowHeight: number, value: number | string): number => {\n if (typeof value === 'number') {\n return value;\n }\n\n const percentageRegex = new RegExp(/^[0-9]+%$/);\n if (percentageRegex.test(value)) {\n const percentage = parseFloat(value) / 100;\n return isNaN(percentage) ? 0 : Math.round(windowHeight * percentage);\n }\n\n return 0;\n};\n\nexport default function useDynamicSnapPoints(props: UseDynamicSnapPointsParams): UseDynamicSnapPointsReturns {\n const {\n index: currentIndex,\n initialSnapPoints,\n } = props;\n\n const { height: WINDOW_HEIGHT } = useWindowDimensions();\n\n const [snapPoints, setSnapPoints] = useState(initialSnapPoints.map((snapPoint) => convertHeightAsPixel(WINDOW_HEIGHT, snapPoint)));\n\n const handleContentLayout = useCallback((event: LayoutChangeEvent) => {\n if (initialSnapPoints[currentIndex] === 'CONTENT_HEIGHT') {\n const contentHeight = Math.min(Math.round(WINDOW_HEIGHT * 0.9), event.nativeEvent.layout.height);\n \n setSnapPoints(prevState => prevState.map((snapPoint, index) => {\n return currentIndex === index ? contentHeight : snapPoint;\n }));\n }\n }, [currentIndex, initialSnapPoints]);\n\n return {\n handleContentLayout,\n snapPoints,\n };\n}\n"],"mappings":"AAAA,SAASA,WAAT,EAAsBC,QAAtB,QAAsC,OAAtC;AACA,SAA4BC,mBAA5B,QAAuD,cAAvD;;AAYA,MAAMC,oBAAoB,GAAG,CAACC,YAAD,EAAuBC,KAAvB,KAA0D;EACnF,IAAI,OAAOA,KAAP,KAAiB,QAArB,EAA+B;IAC3B,OAAOA,KAAP;EACH;;EAED,MAAMC,eAAe,GAAG,IAAIC,MAAJ,CAAW,WAAX,CAAxB;;EACA,IAAID,eAAe,CAACE,IAAhB,CAAqBH,KAArB,CAAJ,EAAiC;IAC7B,MAAMI,UAAU,GAAGC,UAAU,CAACL,KAAD,CAAV,GAAoB,GAAvC;IACA,OAAOM,KAAK,CAACF,UAAD,CAAL,GAAoB,CAApB,GAAwBG,IAAI,CAACC,KAAL,CAAWT,YAAY,GAAGK,UAA1B,CAA/B;EACH;;EAED,OAAO,CAAP;AACH,CAZD;;AAcA,eAAe,SAASK,oBAAT,CAA8BC,KAA9B,EAA8F;EACzG,MAAM;IACFC,KAAK,EAAEC,YADL;IAEFC;EAFE,IAGFH,KAHJ;EAKA,MAAM;IAAEI,MAAM,EAAEC;EAAV,IAA4BlB,mBAAmB,EAArD;EAEA,MAAM,CAACmB,UAAD,EAAaC,aAAb,IAA8BrB,QAAQ,CAACiB,iBAAiB,CAACK,GAAlB,CAAuBC,SAAD,IAAerB,oBAAoB,CAACiB,aAAD,EAAgBI,SAAhB,CAAzD,CAAD,CAA5C;EAEA,MAAMC,mBAAmB,GAAGzB,WAAW,CAAE0B,KAAD,IAA8B;IAClE,IAAIR,iBAAiB,CAACD,YAAD,CAAjB,KAAoC,gBAAxC,EAA0D;MACtD,MAAMU,aAAa,GAAGf,IAAI,CAACgB,GAAL,CAAShB,IAAI,CAACC,KAAL,CAAWO,aAAa,GAAG,GAA3B,CAAT,EAA0CM,KAAK,CAACG,WAAN,CAAkBC,MAAlB,CAAyBX,MAAnE,CAAtB;MAEAG,aAAa,CAACS,SAAS,IAAIA,SAAS,CAACR,GAAV,CAAc,CAACC,SAAD,EAAYR,KAAZ,KAAsB;QAC3D,OAAOC,YAAY,KAAKD,KAAjB,GAAyBW,aAAzB,GAAyCH,SAAhD;MACH,CAF0B,CAAd,CAAb;IAGH;EACJ,CARsC,EAQpC,CAACP,YAAD,EAAeC,iBAAf,CARoC,CAAvC;EAUA,OAAO;IACHO,mBADG;IAEHJ;EAFG,CAAP;AAIH"}
1
+ {"version":3,"names":["R","useCallback","useMemo","useState","useWindowDimensions","convertSnapPoint","snapPoint","windowHeight","maxDynamicContentSize","Math","min","percentageRegex","RegExp","test","percentage","parseFloat","isNaN","round","useDynamicSnapPoints","params","enableDynamicSizing","maxHeightNormalizedRatio","snapPoints","height","contentHeight","setContentHeight","convertedSnapPoints","map","push","Array","from","Set","sort","a","b","highestSnapPoint","last","handleContentSizeChange","_"],"sources":["useDynamicSnapPoints.ts"],"sourcesContent":["import * as R from 'ramda';\nimport { useCallback, useMemo, useState } from 'react';\nimport { useWindowDimensions } from 'react-native';\n\ninterface UseDynamicSnapPointsParams {\n enableDynamicSizing: boolean;\n maxHeightNormalizedRatio: number;\n snapPoints: (number | string)[];\n}\n\ninterface UseDynamicSnapPointsReturns {\n convertedSnapPoints: number[];\n handleContentSizeChange: (w: number, h: number) => void;\n highestSnapPoint: number;\n}\n\nconst convertSnapPoint = (snapPoint: number | string, windowHeight: number, maxDynamicContentSize: number): number => {\n if (typeof snapPoint === 'number') {\n return Math.min(maxDynamicContentSize, snapPoint);\n }\n\n const percentageRegex = new RegExp(/^[0-9]+%$/);\n if (percentageRegex.test(snapPoint)) {\n const percentage = parseFloat(snapPoint) / 100;\n return isNaN(percentage) ? 0 : Math.min(maxDynamicContentSize, Math.round(windowHeight * percentage));\n }\n\n return 0;\n};\n\nexport default function useDynamicSnapPoints(params: UseDynamicSnapPointsParams): UseDynamicSnapPointsReturns {\n const {\n enableDynamicSizing,\n maxHeightNormalizedRatio,\n snapPoints,\n } = params;\n\n const { height: windowHeight } = useWindowDimensions();\n\n const [contentHeight, setContentHeight] = useState<number>(0);\n\n const convertedSnapPoints = useMemo(() => {\n const maxDynamicContentSize = Math.round(windowHeight * maxHeightNormalizedRatio);\n\n const convertedSnapPoints = snapPoints.map((snapPoint) => {\n return convertSnapPoint(snapPoint, windowHeight, maxDynamicContentSize);\n });\n\n if (enableDynamicSizing && contentHeight !== 0) {\n convertedSnapPoints.push(\n convertSnapPoint(contentHeight, windowHeight, maxDynamicContentSize),\n );\n }\n\n return Array.from(new Set(convertedSnapPoints)).sort((a, b) => a - b);\n }, [\n contentHeight,\n snapPoints,\n windowHeight,\n ]);\n\n const highestSnapPoint = R.last(convertedSnapPoints) ?? 0;\n\n const handleContentSizeChange = useCallback((_: number, height: number) => {\n setContentHeight(height);\n }, []);\n\n return {\n convertedSnapPoints,\n handleContentSizeChange,\n highestSnapPoint,\n };\n}\n"],"mappings":"AAAA,OAAO,KAAKA,CAAZ,MAAmB,OAAnB;AACA,SAASC,WAAT,EAAsBC,OAAtB,EAA+BC,QAA/B,QAA+C,OAA/C;AACA,SAASC,mBAAT,QAAoC,cAApC;;AAcA,MAAMC,gBAAgB,GAAG,CAACC,SAAD,EAA6BC,YAA7B,EAAmDC,qBAAnD,KAA6F;EAClH,IAAI,OAAOF,SAAP,KAAqB,QAAzB,EAAmC;IAC/B,OAAOG,IAAI,CAACC,GAAL,CAASF,qBAAT,EAAgCF,SAAhC,CAAP;EACH;;EAED,MAAMK,eAAe,GAAG,IAAIC,MAAJ,CAAW,WAAX,CAAxB;;EACA,IAAID,eAAe,CAACE,IAAhB,CAAqBP,SAArB,CAAJ,EAAqC;IACjC,MAAMQ,UAAU,GAAGC,UAAU,CAACT,SAAD,CAAV,GAAwB,GAA3C;IACA,OAAOU,KAAK,CAACF,UAAD,CAAL,GAAoB,CAApB,GAAwBL,IAAI,CAACC,GAAL,CAASF,qBAAT,EAAgCC,IAAI,CAACQ,KAAL,CAAWV,YAAY,GAAGO,UAA1B,CAAhC,CAA/B;EACH;;EAED,OAAO,CAAP;AACH,CAZD;;AAcA,eAAe,SAASI,oBAAT,CAA8BC,MAA9B,EAA+F;EAC1G,MAAM;IACFC,mBADE;IAEFC,wBAFE;IAGFC;EAHE,IAIFH,MAJJ;EAMA,MAAM;IAAEI,MAAM,EAAEhB;EAAV,IAA2BH,mBAAmB,EAApD;EAEA,MAAM,CAACoB,aAAD,EAAgBC,gBAAhB,IAAoCtB,QAAQ,CAAS,CAAT,CAAlD;EAEA,MAAMuB,mBAAmB,GAAGxB,OAAO,CAAC,MAAM;IACtC,MAAMM,qBAAqB,GAAGC,IAAI,CAACQ,KAAL,CAAWV,YAAY,GAAGc,wBAA1B,CAA9B;IAEA,MAAMK,mBAAmB,GAAGJ,UAAU,CAACK,GAAX,CAAgBrB,SAAD,IAAe;MACtD,OAAOD,gBAAgB,CAACC,SAAD,EAAYC,YAAZ,EAA0BC,qBAA1B,CAAvB;IACH,CAF2B,CAA5B;;IAIA,IAAIY,mBAAmB,IAAII,aAAa,KAAK,CAA7C,EAAgD;MAC5CE,mBAAmB,CAACE,IAApB,CACIvB,gBAAgB,CAACmB,aAAD,EAAgBjB,YAAhB,EAA8BC,qBAA9B,CADpB;IAGH;;IAED,OAAOqB,KAAK,CAACC,IAAN,CAAW,IAAIC,GAAJ,CAAQL,mBAAR,CAAX,EAAyCM,IAAzC,CAA8C,CAACC,CAAD,EAAIC,CAAJ,KAAUD,CAAC,GAAGC,CAA5D,CAAP;EACH,CAdkC,EAchC,CACCV,aADD,EAECF,UAFD,EAGCf,YAHD,CAdgC,CAAnC;EAoBA,MAAM4B,gBAAgB,GAAGnC,CAAC,CAACoC,IAAF,CAAOV,mBAAP,KAA+B,CAAxD;EAEA,MAAMW,uBAAuB,GAAGpC,WAAW,CAAC,CAACqC,CAAD,EAAYf,MAAZ,KAA+B;IACvEE,gBAAgB,CAACF,MAAD,CAAhB;EACH,CAF0C,EAExC,EAFwC,CAA3C;EAIA,OAAO;IACHG,mBADG;IAEHW,uBAFG;IAGHF;EAHG,CAAP;AAKH"}
@@ -10,6 +10,11 @@ export default interface BottomSheetProps extends ComponentProps<{
10
10
  * BottomSheet children, usually the included sub-components.
11
11
  */
12
12
  children?: React.ReactNode;
13
+ /**
14
+ * Enable dynamic sizing for content size.
15
+ * @default true
16
+ */
17
+ enableDynamicSizing?: boolean;
13
18
  /**
14
19
  * Area to be fixed on the top of the bottom sheet.
15
20
  */
@@ -18,6 +23,12 @@ export default interface BottomSheetProps extends ComponentProps<{
18
23
  * Snap index. You could also provide -1 to bottom sheet in closed state.
19
24
  */
20
25
  index: number;
26
+ /**
27
+ * Maximum height(normalized value) of dialog
28
+ * ex. 30% => 0.3 / 90% => 0.9
29
+ * @default 0.9
30
+ */
31
+ maxHeightNormalizedRatio?: number;
21
32
  /**
22
33
  * Callback fired when the index is changed.
23
34
  * Important! Use memoized value.
@@ -27,7 +38,8 @@ export default interface BottomSheetProps extends ComponentProps<{
27
38
  * Points for the bottom sheet to snap to, points should be sorted from bottom to top.
28
39
  * Important! Use memoized value.
29
40
  * Only number type or string type(~% format) can be used.
41
+ * @default []
30
42
  */
31
- snapPoints: Array<number | string>;
43
+ snapPoints?: Array<number | string>;
32
44
  }> {
33
45
  }
@@ -1,11 +1,12 @@
1
- import { LayoutChangeEvent } from 'react-native';
2
1
  interface UseDynamicSnapPointsParams {
3
- index: number;
4
- initialSnapPoints: (number | string)[];
2
+ enableDynamicSizing: boolean;
3
+ maxHeightNormalizedRatio: number;
4
+ snapPoints: (number | string)[];
5
5
  }
6
6
  interface UseDynamicSnapPointsReturns {
7
- handleContentLayout: (e: LayoutChangeEvent) => void;
8
- snapPoints: number[];
7
+ convertedSnapPoints: number[];
8
+ handleContentSizeChange: (w: number, h: number) => void;
9
+ highestSnapPoint: number;
9
10
  }
10
- export default function useDynamicSnapPoints(props: UseDynamicSnapPointsParams): UseDynamicSnapPointsReturns;
11
+ export default function useDynamicSnapPoints(params: UseDynamicSnapPointsParams): UseDynamicSnapPointsReturns;
11
12
  export {};
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
2
  import type CarouselProps from './CarouselProps';
3
3
  import type { CarouselInstance } from './types';
4
- declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Pick<CarouselProps<any>, "style" | "data" | "autoplay" | "autoplayInterval" | "createItemStyle" | "createScrollAnimation" | "disableSmartAutoplay" | "initialIndex" | "itemHeight" | "itemWidth" | "loop" | "onIndexChange" | "renderItem" | "scrollEnabled" | "windowSize"> & React.RefAttributes<CarouselInstance>>>;
4
+ declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Pick<CarouselProps<any>, "style" | "data" | "scrollEnabled" | "autoplay" | "autoplayInterval" | "createItemStyle" | "createScrollAnimation" | "disableSmartAutoplay" | "initialIndex" | "itemHeight" | "itemWidth" | "loop" | "onIndexChange" | "renderItem" | "windowSize"> & React.RefAttributes<CarouselInstance>>>;
5
5
  export default _default;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
2
  import type ViewPagerProps from './ViewPagerProps';
3
3
  import type { ViewPagerInstance } from './types';
4
- declare const ViewPager: React.ForwardRefExoticComponent<Pick<ViewPagerProps, "style" | "children" | "onChange" | "scrollEnabled" | "keyboardDismissMode" | "initialPage" | "loading" | "offscreenPageRerenderLimit" | "pageForceRerenderKey" | "UNSTABLE_sharedPage"> & React.RefAttributes<ViewPagerInstance>>;
4
+ declare const ViewPager: React.ForwardRefExoticComponent<Pick<ViewPagerProps, "style" | "children" | "onChange" | "keyboardDismissMode" | "scrollEnabled" | "initialPage" | "loading" | "offscreenPageRerenderLimit" | "pageForceRerenderKey" | "UNSTABLE_sharedPage"> & React.RefAttributes<ViewPagerInstance>>;
5
5
  export default ViewPager;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
2
  import type ViewPagerProps from './ViewPagerProps';
3
3
  import type { ViewPagerInstance } from './types';
4
- declare const ViewPager: React.ForwardRefExoticComponent<Pick<ViewPagerProps, "style" | "children" | "onChange" | "scrollEnabled" | "keyboardDismissMode" | "initialPage" | "loading" | "offscreenPageRerenderLimit" | "pageForceRerenderKey" | "UNSTABLE_sharedPage"> & React.RefAttributes<ViewPagerInstance>>;
4
+ declare const ViewPager: React.ForwardRefExoticComponent<Pick<ViewPagerProps, "style" | "children" | "onChange" | "keyboardDismissMode" | "scrollEnabled" | "initialPage" | "loading" | "offscreenPageRerenderLimit" | "pageForceRerenderKey" | "UNSTABLE_sharedPage"> & React.RefAttributes<ViewPagerInstance>>;
5
5
  export default ViewPager;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fountain-ui/lab",
3
- "version": "2.0.0-beta.42",
3
+ "version": "2.0.0-beta.43",
4
4
  "private": false,
5
5
  "author": "Fountain-UI Team",
6
6
  "description": "Incubator for Fountain-UI React components.",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "peerDependencies": {
25
25
  "@fountain-ui/core": "^2.0.0-beta.3",
26
- "@gorhom/bottom-sheet": "^4.1.3",
26
+ "@gorhom/bottom-sheet": "^4.5.0",
27
27
  "date-fns": "^2.0.0",
28
28
  "react": "^16.8.0 || ^17.0.0",
29
29
  "react-dom": "^16.8.0 || ^17.0.0",
@@ -43,7 +43,7 @@
43
43
  }
44
44
  },
45
45
  "devDependencies": {
46
- "@gorhom/bottom-sheet": "4.1.3",
46
+ "@gorhom/bottom-sheet": "^4.5.0",
47
47
  "date-fns": "^2.23.0",
48
48
  "react-native-pager-view": "^4.2.4",
49
49
  "react-native-safe-area-context": "^4.0.0"
@@ -70,5 +70,5 @@
70
70
  "publishConfig": {
71
71
  "access": "public"
72
72
  },
73
- "gitHead": "263ed4f4ec14ca755180bad17b877d9ab9658e52"
73
+ "gitHead": "d6fdcaa8a08a999fd1be2f9be76e47230b32545e"
74
74
  }
@@ -1,11 +1,12 @@
1
1
  import React from 'react';
2
- import { Platform } from 'react-native';
2
+ import { Platform, useWindowDimensions } from 'react-native';
3
3
  import { useTheme } from '@fountain-ui/styles';
4
4
  import {
5
5
  BottomSheetBackdrop,
6
6
  BottomSheetBackdropProps,
7
7
  BottomSheetModal,
8
8
  BottomSheetModalProvider,
9
+ BottomSheetScrollView,
9
10
  } from '@gorhom/bottom-sheet';
10
11
  import type BottomSheetProps from './BottomSheetProps';
11
12
  import TransparentBackdrop from './TransparentBackdrop';
@@ -16,14 +17,20 @@ export default function BottomSheet(props: BottomSheetProps) {
16
17
  const {
17
18
  backdropOpacity = 0.5,
18
19
  children,
20
+ enableDynamicSizing = true,
21
+ header,
19
22
  index,
23
+ maxHeightNormalizedRatio = 0.9,
20
24
  onChange,
21
- snapPoints,
25
+ snapPoints = [],
22
26
  } = props;
23
27
 
24
28
  const indexRef = React.useRef<number>(-1);
25
29
  const bottomSheetRef = React.useRef<BottomSheetModal | null>(null);
26
30
 
31
+ const { height: windowHeight } = useWindowDimensions();
32
+ const maxDynamicContentSize = Math.round(windowHeight * maxHeightNormalizedRatio);
33
+
27
34
  const handleChange = React.useCallback((newIndex: number) => {
28
35
  indexRef.current = newIndex;
29
36
 
@@ -91,8 +98,14 @@ export default function BottomSheet(props: BottomSheetProps) {
91
98
  snapPoints={snapPoints}
92
99
  style={modalStyle}
93
100
  enablePanDownToClose={Boolean(onChange)}
101
+ enableDynamicSizing={enableDynamicSizing}
102
+ maxDynamicContentSize={maxDynamicContentSize}
94
103
  >
95
- {children}
104
+ <BottomSheetScrollView stickyHeaderIndices={header ? [0] : undefined}>
105
+ {header}
106
+
107
+ {children}
108
+ </BottomSheetScrollView>
96
109
  </BottomSheetModal>
97
110
  </BottomSheetModalProvider>
98
111
  );
@@ -13,6 +13,12 @@ export default interface BottomSheetProps extends ComponentProps<{
13
13
  */
14
14
  children?: React.ReactNode;
15
15
 
16
+ /**
17
+ * Enable dynamic sizing for content size.
18
+ * @default true
19
+ */
20
+ enableDynamicSizing?: boolean;
21
+
16
22
  /**
17
23
  * Area to be fixed on the top of the bottom sheet.
18
24
  */
@@ -23,6 +29,13 @@ export default interface BottomSheetProps extends ComponentProps<{
23
29
  */
24
30
  index: number;
25
31
 
32
+ /**
33
+ * Maximum height(normalized value) of dialog
34
+ * ex. 30% => 0.3 / 90% => 0.9
35
+ * @default 0.9
36
+ */
37
+ maxHeightNormalizedRatio?: number;
38
+
26
39
  /**
27
40
  * Callback fired when the index is changed.
28
41
  * Important! Use memoized value.
@@ -33,6 +46,7 @@ export default interface BottomSheetProps extends ComponentProps<{
33
46
  * Points for the bottom sheet to snap to, points should be sorted from bottom to top.
34
47
  * Important! Use memoized value.
35
48
  * Only number type or string type(~% format) can be used.
49
+ * @default []
36
50
  */
37
- snapPoints: Array<number | string>;
51
+ snapPoints?: Array<number | string>;
38
52
  }> {}
@@ -1,9 +1,10 @@
1
1
  import React from 'react';
2
- import { useWindowDimensions } from 'react-native';
2
+ import { ScrollView } from 'react-native';
3
3
  import { Modal, Paper, StyleSheet, css, useTheme } from '@fountain-ui/core';
4
4
  import { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';
5
5
  import AnimatedY from '../AnimatedY';
6
6
  import type BottomSheetProps from './BottomSheetProps';
7
+ import useDynamicSnapPoints from './useDynamicSnapPoints';
7
8
 
8
9
  type BottomSheetStyles = NamedStylesStringUnion<'root' | 'animated' | 'paper'>;
9
10
 
@@ -29,41 +30,42 @@ const useStyles: UseStyles<BottomSheetStyles> = function (): BottomSheetStyles {
29
30
  };
30
31
  };
31
32
 
32
- const convertHeightAsPixel = (windowHeight: number, value: number | string): number => {
33
- if (typeof value === 'number') {
34
- return value;
35
- }
36
-
37
- const percentageRegex = new RegExp(/^[0-9]+%$/);
38
- if (percentageRegex.test(value)) {
39
- const percentage = parseFloat(value) / 100;
40
- return isNaN(percentage) ? 0 : Math.round(windowHeight * percentage);
41
- }
42
-
43
- return 0;
44
- };
45
-
46
33
  export default function BottomSheet(props: BottomSheetProps) {
47
34
  const {
48
35
  backdropOpacity,
49
36
  children,
37
+ enableDynamicSizing = true,
38
+ header,
50
39
  index,
40
+ maxHeightNormalizedRatio = 0.9,
51
41
  onChange,
52
- snapPoints,
42
+ snapPoints = [],
53
43
  } = props;
54
44
 
55
45
  const styles = useStyles();
56
46
 
57
- const { height: windowHeight } = useWindowDimensions();
58
-
59
47
  const handleClose = () => {
60
48
  if (onChange) {
61
49
  onChange(-1);
62
50
  }
63
51
  };
64
52
 
65
- const height = convertHeightAsPixel(windowHeight, snapPoints[snapPoints.length - 1] ?? 0);
66
- const translateY = height - (convertHeightAsPixel(windowHeight, snapPoints[index] ?? 0));
53
+ const {
54
+ convertedSnapPoints,
55
+ handleContentSizeChange,
56
+ highestSnapPoint,
57
+ } = useDynamicSnapPoints({
58
+ enableDynamicSizing,
59
+ maxHeightNormalizedRatio,
60
+ snapPoints,
61
+ });
62
+
63
+ const translateY = highestSnapPoint - (convertedSnapPoints[index] ?? 0);
64
+
65
+ const paperStyles = [
66
+ styles.paper,
67
+ { height: highestSnapPoint },
68
+ ];
67
69
 
68
70
  return (
69
71
  <Modal
@@ -78,12 +80,16 @@ export default function BottomSheet(props: BottomSheetProps) {
78
80
  >
79
81
  <Paper
80
82
  elevation={12}
81
- style={[
82
- styles.paper,
83
- { height },
84
- ]}
83
+ style={paperStyles}
85
84
  >
86
- {children}
85
+ <ScrollView
86
+ onContentSizeChange={handleContentSizeChange}
87
+ stickyHeaderIndices={header ? [0] : undefined}
88
+ >
89
+ {header}
90
+
91
+ {children}
92
+ </ScrollView>
87
93
  </Paper>
88
94
  </AnimatedY>
89
95
  </Modal>
@@ -1,52 +1,73 @@
1
- import { useCallback, useState } from 'react';
2
- import { LayoutChangeEvent, useWindowDimensions } from 'react-native';
1
+ import * as R from 'ramda';
2
+ import { useCallback, useMemo, useState } from 'react';
3
+ import { useWindowDimensions } from 'react-native';
3
4
 
4
5
  interface UseDynamicSnapPointsParams {
5
- index: number;
6
- initialSnapPoints: (number | string)[];
6
+ enableDynamicSizing: boolean;
7
+ maxHeightNormalizedRatio: number;
8
+ snapPoints: (number | string)[];
7
9
  }
8
10
 
9
11
  interface UseDynamicSnapPointsReturns {
10
- handleContentLayout: (e: LayoutChangeEvent) => void;
11
- snapPoints: number[];
12
+ convertedSnapPoints: number[];
13
+ handleContentSizeChange: (w: number, h: number) => void;
14
+ highestSnapPoint: number;
12
15
  }
13
16
 
14
- const convertHeightAsPixel = (windowHeight: number, value: number | string): number => {
15
- if (typeof value === 'number') {
16
- return value;
17
+ const convertSnapPoint = (snapPoint: number | string, windowHeight: number, maxDynamicContentSize: number): number => {
18
+ if (typeof snapPoint === 'number') {
19
+ return Math.min(maxDynamicContentSize, snapPoint);
17
20
  }
18
21
 
19
22
  const percentageRegex = new RegExp(/^[0-9]+%$/);
20
- if (percentageRegex.test(value)) {
21
- const percentage = parseFloat(value) / 100;
22
- return isNaN(percentage) ? 0 : Math.round(windowHeight * percentage);
23
+ if (percentageRegex.test(snapPoint)) {
24
+ const percentage = parseFloat(snapPoint) / 100;
25
+ return isNaN(percentage) ? 0 : Math.min(maxDynamicContentSize, Math.round(windowHeight * percentage));
23
26
  }
24
27
 
25
28
  return 0;
26
29
  };
27
30
 
28
- export default function useDynamicSnapPoints(props: UseDynamicSnapPointsParams): UseDynamicSnapPointsReturns {
31
+ export default function useDynamicSnapPoints(params: UseDynamicSnapPointsParams): UseDynamicSnapPointsReturns {
29
32
  const {
30
- index: currentIndex,
31
- initialSnapPoints,
32
- } = props;
33
+ enableDynamicSizing,
34
+ maxHeightNormalizedRatio,
35
+ snapPoints,
36
+ } = params;
37
+
38
+ const { height: windowHeight } = useWindowDimensions();
33
39
 
34
- const { height: WINDOW_HEIGHT } = useWindowDimensions();
40
+ const [contentHeight, setContentHeight] = useState<number>(0);
35
41
 
36
- const [snapPoints, setSnapPoints] = useState(initialSnapPoints.map((snapPoint) => convertHeightAsPixel(WINDOW_HEIGHT, snapPoint)));
42
+ const convertedSnapPoints = useMemo(() => {
43
+ const maxDynamicContentSize = Math.round(windowHeight * maxHeightNormalizedRatio);
37
44
 
38
- const handleContentLayout = useCallback((event: LayoutChangeEvent) => {
39
- if (initialSnapPoints[currentIndex] === 'CONTENT_HEIGHT') {
40
- const contentHeight = Math.min(Math.round(WINDOW_HEIGHT * 0.9), event.nativeEvent.layout.height);
41
-
42
- setSnapPoints(prevState => prevState.map((snapPoint, index) => {
43
- return currentIndex === index ? contentHeight : snapPoint;
44
- }));
45
+ const convertedSnapPoints = snapPoints.map((snapPoint) => {
46
+ return convertSnapPoint(snapPoint, windowHeight, maxDynamicContentSize);
47
+ });
48
+
49
+ if (enableDynamicSizing && contentHeight !== 0) {
50
+ convertedSnapPoints.push(
51
+ convertSnapPoint(contentHeight, windowHeight, maxDynamicContentSize),
52
+ );
45
53
  }
46
- }, [currentIndex, initialSnapPoints]);
47
54
 
48
- return {
49
- handleContentLayout,
55
+ return Array.from(new Set(convertedSnapPoints)).sort((a, b) => a - b);
56
+ }, [
57
+ contentHeight,
50
58
  snapPoints,
59
+ windowHeight,
60
+ ]);
61
+
62
+ const highestSnapPoint = R.last(convertedSnapPoints) ?? 0;
63
+
64
+ const handleContentSizeChange = useCallback((_: number, height: number) => {
65
+ setContentHeight(height);
66
+ }, []);
67
+
68
+ return {
69
+ convertedSnapPoints,
70
+ handleContentSizeChange,
71
+ highestSnapPoint,
51
72
  };
52
73
  }
@@ -1,177 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = BottomSheet;
7
-
8
- var _react = _interopRequireWildcard(require("react"));
9
-
10
- var _reactNative = require("react-native");
11
-
12
- var _core = require("@fountain-ui/core");
13
-
14
- var _useDynamicSnapPoints = _interopRequireDefault(require("./useDynamicSnapPoints"));
15
-
16
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
-
18
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
-
20
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
21
-
22
- function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
23
-
24
- const useStyles = function () {
25
- const theme = (0, _core.useTheme)();
26
- return {
27
- root: {
28
- justifyContent: 'flex-end',
29
- zIndex: theme.zIndex.dialog
30
- },
31
- animated: {
32
- alignSelf: 'center',
33
- maxWidth: 720,
34
- width: '100%'
35
- },
36
- paper: {
37
- borderBottomLeftRadius: 0,
38
- borderBottomRightRadius: 0,
39
- flexGrow: 1,
40
- overflow: 'hidden'
41
- },
42
- scrollView: {
43
- flexGrow: 1
44
- }
45
- };
46
- };
47
-
48
- function BottomSheet(props) {
49
- const {
50
- backdropOpacity,
51
- children,
52
- header,
53
- index,
54
- onChange,
55
- snapPoints: initialSnapPoints
56
- } = props;
57
- const styles = useStyles();
58
- const contentLayout = (0, _react.useRef)({
59
- x: 0,
60
- y: 0,
61
- width: 0,
62
- height: 0
63
- });
64
- const currentScrollY = (0, _react.useRef)(0);
65
- const {
66
- snapPoints,
67
- handleContentLayout
68
- } = (0, _useDynamicSnapPoints.default)({
69
- index,
70
- initialSnapPoints
71
- });
72
- const height = snapPoints[snapPoints.length - 1] ?? 0;
73
- const translateY = height - (snapPoints[index] ?? 0);
74
- const animatedY = (0, _core.useAnimatedValue)(translateY);
75
-
76
- const isInsideScrollView = (locationX, locationY) => {
77
- const {
78
- current: {
79
- x,
80
- y,
81
- width,
82
- height
83
- }
84
- } = contentLayout;
85
- return locationX >= x && locationX <= x + width && locationY >= y && locationY <= y + height;
86
- };
87
-
88
- const panResponder = (0, _react.useMemo)(() => _reactNative.PanResponder.create({
89
- onMoveShouldSetPanResponder: (event, gestureState) => {
90
- const {
91
- nativeEvent: {
92
- locationX,
93
- locationY
94
- }
95
- } = event;
96
-
97
- if (isInsideScrollView(locationX, locationY)) {
98
- return gestureState.dy > 0 && currentScrollY.current === 0;
99
- }
100
-
101
- return true;
102
- },
103
- onPanResponderMove: (_, gestureState) => {
104
- if (gestureState.dy > 0) {
105
- animatedY.setValue(translateY + gestureState.dy);
106
- }
107
- },
108
- onPanResponderRelease: (_, gestureState) => {
109
- if (gestureState.dy > 0 && gestureState.vy > 0.5) {
110
- handleClose();
111
- } else {
112
- _reactNative.Animated.timing(animatedY, {
113
- toValue: translateY,
114
- useNativeDriver: false,
115
- duration: 300
116
- }).start();
117
- }
118
- }
119
- }), [translateY]);
120
- (0, _react.useEffect)(() => {
121
- if (translateY >= 0) {
122
- _reactNative.Animated.timing(animatedY, {
123
- toValue: translateY,
124
- useNativeDriver: false,
125
- duration: 300
126
- }).start();
127
- }
128
- }, [translateY]);
129
-
130
- const handleClose = () => {
131
- if (onChange) {
132
- onChange(-1);
133
- }
134
- };
135
-
136
- const handleScrollViewLayout = event => {
137
- contentLayout.current = event.nativeEvent.layout;
138
- };
139
-
140
- const handleScroll = event => {
141
- currentScrollY.current = event.nativeEvent.contentOffset.y;
142
- };
143
-
144
- const animatedStyles = [styles.animated, {
145
- transform: [{
146
- translateY: animatedY
147
- }]
148
- }];
149
- const paperStyles = [styles.paper, { ...(height !== 0 ? {
150
- height
151
- } : {})
152
- }];
153
- const contentStyle = { ...(snapPoints[index] !== 0 ? {
154
- height: snapPoints[index]
155
- } : {})
156
- };
157
- return /*#__PURE__*/_react.default.createElement(_core.Modal, {
158
- backdropOpacity: backdropOpacity,
159
- onClose: handleClose,
160
- visible: index >= 0,
161
- style: (0, _core.css)([_core.StyleSheet.absoluteFill, styles.root])
162
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, _extends({
163
- style: animatedStyles
164
- }, panResponder.panHandlers), /*#__PURE__*/_react.default.createElement(_core.Paper, {
165
- elevation: 12,
166
- style: paperStyles
167
- }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
168
- style: contentStyle,
169
- onLayout: handleContentLayout
170
- }, header, /*#__PURE__*/_react.default.createElement(_reactNative.ScrollView, {
171
- onLayout: handleScrollViewLayout,
172
- onScroll: handleScroll,
173
- scrollEventThrottle: 300,
174
- style: styles.scrollView
175
- }, children)))));
176
- }
177
- //# sourceMappingURL=BottomSheet.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["useStyles","theme","useTheme","root","justifyContent","zIndex","dialog","animated","alignSelf","maxWidth","width","paper","borderBottomLeftRadius","borderBottomRightRadius","flexGrow","overflow","scrollView","BottomSheet","props","backdropOpacity","children","header","index","onChange","snapPoints","initialSnapPoints","styles","contentLayout","useRef","x","y","height","currentScrollY","handleContentLayout","useDynamicSnapPoints","length","translateY","animatedY","useAnimatedValue","isInsideScrollView","locationX","locationY","current","panResponder","useMemo","PanResponder","create","onMoveShouldSetPanResponder","event","gestureState","nativeEvent","dy","onPanResponderMove","_","setValue","onPanResponderRelease","vy","handleClose","Animated","timing","toValue","useNativeDriver","duration","start","useEffect","handleScrollViewLayout","layout","handleScroll","contentOffset","animatedStyles","transform","paperStyles","contentStyle","css","StyleSheet","absoluteFill","panHandlers"],"sources":["BottomSheet.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef } from 'react';\nimport {\n Animated,\n LayoutChangeEvent,\n LayoutRectangle,\n NativeScrollEvent,\n NativeSyntheticEvent,\n PanResponder,\n ScrollView,\n View,\n} from 'react-native';\nimport { css, Modal, Paper, StyleSheet, useAnimatedValue, useTheme } from '@fountain-ui/core';\nimport { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport BottomSheetProps from './BottomSheetProps';\nimport useDynamicSnapPoints from './useDynamicSnapPoints';\n\ntype BottomSheetStyles = NamedStylesStringUnion<'root' | 'animated' | 'paper' | 'scrollView'>;\n\nconst useStyles: UseStyles<BottomSheetStyles> = function (): BottomSheetStyles {\n const theme = useTheme();\n\n return {\n root: {\n justifyContent: 'flex-end',\n zIndex: theme.zIndex.dialog,\n },\n animated: {\n alignSelf: 'center',\n maxWidth: 720,\n width: '100%',\n },\n paper: {\n borderBottomLeftRadius: 0,\n borderBottomRightRadius: 0,\n flexGrow: 1,\n overflow: 'hidden',\n },\n scrollView: {\n flexGrow: 1,\n },\n };\n};\n\nexport default function BottomSheet(props: BottomSheetProps) {\n const {\n backdropOpacity,\n children,\n header,\n index,\n onChange,\n snapPoints: initialSnapPoints,\n } = props;\n\n const styles = useStyles();\n\n const contentLayout = useRef<LayoutRectangle>({ x: 0, y: 0, width: 0, height: 0 });\n const currentScrollY = useRef<number>(0);\n\n const {\n snapPoints,\n handleContentLayout,\n } = useDynamicSnapPoints({\n index,\n initialSnapPoints,\n });\n\n const height = snapPoints[snapPoints.length - 1] ?? 0;\n const translateY = height - (snapPoints[index] ?? 0);\n\n const animatedY = useAnimatedValue(translateY);\n\n const isInsideScrollView = (locationX: number, locationY: number): boolean => {\n const {\n current: { x, y, width, height },\n } = contentLayout;\n\n return locationX >= x && locationX <= x + width && locationY >= y && locationY <= y + height;\n };\n\n const panResponder = useMemo(() => (\n PanResponder.create({\n onMoveShouldSetPanResponder: (event, gestureState) => {\n const {\n nativeEvent: { locationX, locationY },\n } = event;\n\n if (isInsideScrollView(locationX, locationY)) {\n return gestureState.dy > 0 && currentScrollY.current === 0;\n }\n\n return true;\n },\n onPanResponderMove: (_, gestureState) => {\n if (gestureState.dy > 0) {\n animatedY.setValue(translateY + gestureState.dy);\n }\n },\n onPanResponderRelease: (_, gestureState) => {\n if (gestureState.dy > 0 && gestureState.vy > 0.5) {\n handleClose();\n } else {\n Animated.timing(animatedY, {\n toValue: translateY,\n useNativeDriver: false,\n duration: 300,\n }).start();\n }\n },\n })\n ), [translateY]);\n\n useEffect(() => {\n if (translateY >= 0) {\n Animated.timing(animatedY, {\n toValue: translateY,\n useNativeDriver: false,\n duration: 300,\n }).start();\n }\n }, [translateY]);\n\n const handleClose = () => {\n if (onChange) {\n onChange(-1);\n }\n };\n\n const handleScrollViewLayout = (event: LayoutChangeEvent) => {\n contentLayout.current = event.nativeEvent.layout;\n };\n\n const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n currentScrollY.current = event.nativeEvent.contentOffset.y;\n };\n\n const animatedStyles = [\n styles.animated,\n { transform: [{ translateY: animatedY }] },\n ];\n\n const paperStyles = [\n styles.paper,\n { ...(height !== 0 ? { height } : {}) },\n ];\n\n const contentStyle = {\n ...(snapPoints[index] !== 0 ? { height: snapPoints[index] } : {}),\n };\n\n return (\n <Modal\n backdropOpacity={backdropOpacity}\n onClose={handleClose}\n visible={index >= 0}\n style={css([StyleSheet.absoluteFill, styles.root])}\n >\n <Animated.View\n style={animatedStyles}\n {...panResponder.panHandlers}\n >\n <Paper\n elevation={12}\n style={paperStyles}\n >\n <View\n style={contentStyle}\n onLayout={handleContentLayout}\n >\n {header}\n\n <ScrollView\n onLayout={handleScrollViewLayout}\n onScroll={handleScroll}\n scrollEventThrottle={300}\n style={styles.scrollView}\n >\n {children}\n </ScrollView>\n </View>\n </Paper>\n </Animated.View>\n </Modal>\n );\n}\n"],"mappings":"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"}