@0610studio/zs-ui 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -5
- package/build/ui/ZSContainer/index.d.ts +1 -13
- package/build/ui/ZSContainer/index.d.ts.map +1 -1
- package/build/ui/ZSContainer/index.js +24 -58
- package/build/ui/ZSContainer/index.js.map +1 -1
- package/build/ui/ZSContainer/ui/VariantView.js +5 -4
- package/build/ui/ZSContainer/ui/VariantView.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -11,23 +11,21 @@ ZS-ui는 JavaScript만으로 구현된 Expo용 UI 컴포넌트 라이브러리
|
|
|
11
11
|
|
|
12
12
|
<br />
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## 설치
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
npx expo install @react-native-async-storage/async-storage react-native-reanimated react-native-svg react-native-safe-area-context
|
|
18
|
-
|
|
19
17
|
npx expo install @0610studio/zs-ui
|
|
20
18
|
```
|
|
21
19
|
|
|
22
20
|
<br />
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
## 사용법
|
|
25
23
|
|
|
26
24
|
사용법은 [문서](https://0610studio.github.io/zs-ui/docs/intro)를 확인해주세요.
|
|
27
25
|
|
|
28
26
|
<br />
|
|
29
27
|
|
|
30
|
-
|
|
28
|
+
## TODO
|
|
31
29
|
|
|
32
30
|
- [ ] 폴더블 폰에서 접힘/펼침 상태 변경으로 인해 액티비티가 재시작되었을 때, `Dimensions.get('window')`가 이전 값을 반환하고 onChange가 호출되지 않는 문제
|
|
33
31
|
|
|
@@ -2,7 +2,6 @@ import React, { ReactNode } from 'react';
|
|
|
2
2
|
import { ViewProps, ScrollView, NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
|
|
3
3
|
export type ZSContainerProps = ViewProps & {
|
|
4
4
|
backgroundColor?: string;
|
|
5
|
-
isLoader?: boolean;
|
|
6
5
|
statusBarColor?: string;
|
|
7
6
|
barStyle?: 'light-content' | 'dark-content';
|
|
8
7
|
edges?: Array<'top' | 'right' | 'bottom' | 'left'>;
|
|
@@ -11,8 +10,6 @@ export type ZSContainerProps = ViewProps & {
|
|
|
11
10
|
bottomComponent?: ReactNode;
|
|
12
11
|
rightComponent?: ReactNode;
|
|
13
12
|
showsVerticalScrollIndicator?: boolean;
|
|
14
|
-
loadingComponent?: React.ReactNode;
|
|
15
|
-
automaticallyAdjustKeyboardInsets?: boolean;
|
|
16
13
|
keyboardScrollExtraOffset?: number;
|
|
17
14
|
translucent?: boolean;
|
|
18
15
|
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
@@ -21,7 +18,6 @@ export type ZSContainerProps = ViewProps & {
|
|
|
21
18
|
export type ZSContainerRef = ScrollView;
|
|
22
19
|
declare const ZSContainer: React.ForwardRefExoticComponent<ViewProps & {
|
|
23
20
|
backgroundColor?: string;
|
|
24
|
-
isLoader?: boolean;
|
|
25
21
|
statusBarColor?: string;
|
|
26
22
|
barStyle?: "light-content" | "dark-content";
|
|
27
23
|
edges?: Array<"top" | "right" | "bottom" | "left">;
|
|
@@ -30,8 +26,6 @@ declare const ZSContainer: React.ForwardRefExoticComponent<ViewProps & {
|
|
|
30
26
|
bottomComponent?: ReactNode;
|
|
31
27
|
rightComponent?: ReactNode;
|
|
32
28
|
showsVerticalScrollIndicator?: boolean;
|
|
33
|
-
loadingComponent?: React.ReactNode;
|
|
34
|
-
automaticallyAdjustKeyboardInsets?: boolean;
|
|
35
29
|
keyboardScrollExtraOffset?: number;
|
|
36
30
|
translucent?: boolean;
|
|
37
31
|
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
@@ -40,19 +34,13 @@ declare const ZSContainer: React.ForwardRefExoticComponent<ViewProps & {
|
|
|
40
34
|
export declare const styles: {
|
|
41
35
|
flex1: {
|
|
42
36
|
flex: number;
|
|
37
|
+
width: "100%";
|
|
43
38
|
};
|
|
44
39
|
scrollContainerStyle: {
|
|
45
40
|
flexGrow: number;
|
|
46
41
|
alignItems: "center";
|
|
47
|
-
};
|
|
48
|
-
splitContainer: {
|
|
49
|
-
flex: number;
|
|
50
|
-
flexDirection: "row";
|
|
51
42
|
width: "100%";
|
|
52
43
|
};
|
|
53
|
-
splitView: {
|
|
54
|
-
minHeight: "100%";
|
|
55
|
-
};
|
|
56
44
|
};
|
|
57
45
|
export default ZSContainer;
|
|
58
46
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/ZSContainer/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAgE,MAAM,OAAO,CAAC;AACvG,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/ZSContainer/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAgE,MAAM,OAAO,CAAC;AACvG,OAAO,EAAE,SAAS,EAAyB,UAAU,EAAE,oBAAoB,EAAE,iBAAiB,EAA4B,MAAM,cAAc,CAAC;AAI/I,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG;IACzC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC;IAC5C,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC;IACnD,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IACpE,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC;AAExC,QAAA,MAAM,WAAW;sBAjBG,MAAM;qBACP,MAAM;eACZ,eAAe,GAAG,cAAc;YACnC,KAAK,CAAC,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;yBAC7B,OAAO;mBACb,SAAS;sBACN,SAAS;qBACV,SAAS;mCACK,OAAO;gCACV,MAAM;kBACpB,OAAO;eACV,CAAC,KAAK,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,KAAK,IAAI;0BAC7C,MAAM;oCAuH5B,CAAC;AAEH,eAAO,MAAM,MAAM;;;;;;;;;;CAGjB,CAAC;AAEH,eAAe,WAAW,CAAC"}
|
|
@@ -1,43 +1,36 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { StatusBar, StyleSheet,
|
|
1
|
+
import React, { useEffect, useImperativeHandle, forwardRef, useRef, useState } from 'react';
|
|
2
|
+
import { StatusBar, StyleSheet, ScrollView, Keyboard, View, Platform } from 'react-native';
|
|
3
3
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
4
4
|
import { useTheme } from '../../model/useThemeProvider';
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const { palette, splitBreakpoint, splitRatio, dimensions: { height: windowHeight, width: windowWidth }, isSplitView } = useTheme();
|
|
8
|
-
const [isDelayed, setIsDelayed] = useState(true);
|
|
9
|
-
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
|
5
|
+
const ZSContainer = forwardRef(function ZSContainer({ backgroundColor, statusBarColor, barStyle, edges = ['top', 'bottom'], scrollViewDisabled = false, topComponent, bottomComponent, rightComponent, showsVerticalScrollIndicator = true, keyboardScrollExtraOffset = 30, translucent, scrollEventThrottle = 16, ...props }, forwardedRef) {
|
|
6
|
+
const { palette, dimensions: { height: windowHeight } } = useTheme();
|
|
10
7
|
const positionRef = useRef(0);
|
|
11
8
|
const scrollViewRef = useRef(null);
|
|
12
9
|
const lastTouchY = useRef(0);
|
|
13
|
-
const
|
|
10
|
+
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
|
14
11
|
useImperativeHandle(forwardedRef, () => scrollViewRef.current, []);
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
const timer = setTimeout(() => {
|
|
17
|
-
setIsDelayed(false);
|
|
18
|
-
}, 200);
|
|
19
|
-
return () => clearTimeout(timer);
|
|
20
|
-
}, []);
|
|
21
12
|
useEffect(() => {
|
|
22
13
|
const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
|
|
23
14
|
const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
|
|
24
15
|
const keyboardShowSubscription = Keyboard.addListener(showEvent, (e) => {
|
|
25
16
|
setKeyboardHeight(e.endCoordinates.height);
|
|
26
|
-
if (scrollViewRef.current
|
|
17
|
+
if (scrollViewRef.current) {
|
|
27
18
|
const screenHeight = windowHeight;
|
|
28
19
|
const keyboardHeight = e.endCoordinates.height;
|
|
29
20
|
const safeAreaBottom = 0;
|
|
30
21
|
const availableScreenHeight = screenHeight - keyboardHeight - safeAreaBottom;
|
|
31
|
-
// 현재 터치 위치와 스크롤 위치를 기반으로 새로운 스크롤 위치 계산
|
|
32
22
|
const currentScrollPosition = positionRef.current || 0;
|
|
33
23
|
const touchPosition = lastTouchY.current || 0;
|
|
24
|
+
// touchPosition이 키보드 높이보다 아래인 경우
|
|
25
|
+
// const isTouchPositionBelowKeyboard = touchPosition > availableScreenHeight;
|
|
26
|
+
// 현재 터치 위치와 스크롤 위치를 기반으로 새로운 스크롤 위치 계산
|
|
34
27
|
const scrollOffset = touchPosition - availableScreenHeight + keyboardScrollExtraOffset;
|
|
35
28
|
setTimeout(() => {
|
|
36
29
|
scrollViewRef.current?.scrollTo({
|
|
37
30
|
y: currentScrollPosition + scrollOffset,
|
|
38
31
|
animated: true,
|
|
39
32
|
});
|
|
40
|
-
},
|
|
33
|
+
}, 100);
|
|
41
34
|
}
|
|
42
35
|
});
|
|
43
36
|
const keyboardHideSubscription = Keyboard.addListener(hideEvent, () => {
|
|
@@ -53,55 +46,28 @@ const ZSContainer = forwardRef(function ZSContainer({ backgroundColor, isLoader
|
|
|
53
46
|
const handleScroll = (event) => {
|
|
54
47
|
if (props.onScroll)
|
|
55
48
|
props.onScroll(event);
|
|
56
|
-
|
|
57
|
-
positionRef.current = event.nativeEvent.contentOffset.y;
|
|
49
|
+
positionRef.current = event.nativeEvent.contentOffset.y;
|
|
58
50
|
};
|
|
59
51
|
const handleTouch = (evt) => {
|
|
60
|
-
|
|
61
|
-
lastTouchY.current = evt.nativeEvent.pageY;
|
|
62
|
-
};
|
|
63
|
-
const renderContent = () => {
|
|
64
|
-
if (isLoader)
|
|
65
|
-
return loadingComponent;
|
|
66
|
-
const leftWidth = (splitEnabled ? `${splitRatio * 100}%` : '100%');
|
|
67
|
-
const rightWidth = `${(1 - splitRatio) * 100}%`;
|
|
68
|
-
return (<View style={styles.splitContainer}>
|
|
69
|
-
|
|
70
|
-
{/* 메인 컴포넌트 */}
|
|
71
|
-
<VariantView style={props.style} children={props.children} scrollViewRef={scrollViewRef} variantWidth={leftWidth} showsVerticalScrollIndicator={showsVerticalScrollIndicator} automaticallyAdjustKeyboardInsets={automaticallyAdjustKeyboardInsets} scrollViewDisabled={scrollViewDisabled} scrollEventThrottle={scrollEventThrottle} handleScroll={handleScroll} handleTouch={handleTouch} keyboardHeight={keyboardHeight}/>
|
|
72
|
-
|
|
73
|
-
{/* 폴드/태블릿 화면 오른쪽 컴포넌트 */}
|
|
74
|
-
{rightComponent && splitEnabled && (<VariantView style={styles.splitView} children={rightComponent} variantWidth={rightWidth} showsVerticalScrollIndicator={showsVerticalScrollIndicator} automaticallyAdjustKeyboardInsets={automaticallyAdjustKeyboardInsets} scrollViewDisabled={false} scrollEventThrottle={scrollEventThrottle}/>)}
|
|
75
|
-
</View>);
|
|
52
|
+
lastTouchY.current = evt.nativeEvent.pageY;
|
|
76
53
|
};
|
|
77
|
-
return (<SafeAreaView style={[
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
54
|
+
return (<SafeAreaView style={[{ backgroundColor: backgroundColor || palette.background.base }, styles.flex1]} edges={edges}>
|
|
55
|
+
<View style={styles.flex1}>
|
|
56
|
+
{topComponent && topComponent}
|
|
57
|
+
<ScrollView ref={scrollViewRef} style={styles.flex1} contentContainerStyle={[styles.scrollContainerStyle, { paddingBottom: Platform.OS === 'ios' ? keyboardHeight || 0 : 0 }]} bounces={false} overScrollMode="never" showsVerticalScrollIndicator={showsVerticalScrollIndicator} keyboardShouldPersistTaps="handled" automaticallyAdjustKeyboardInsets={false} onScroll={handleScroll} onTouchStart={handleTouch} scrollEventThrottle={scrollEventThrottle}>
|
|
58
|
+
<View style={[styles.flex1, props.style]}>
|
|
59
|
+
{props.children}
|
|
60
|
+
</View>
|
|
61
|
+
</ScrollView>
|
|
62
|
+
{bottomComponent && bottomComponent}
|
|
63
|
+
</View>
|
|
87
64
|
|
|
88
65
|
{(barStyle || statusBarColor || translucent) && (<StatusBar barStyle={barStyle} backgroundColor={statusBarColor || palette.background.base} translucent={translucent}/>)}
|
|
89
66
|
</SafeAreaView>);
|
|
90
67
|
});
|
|
91
68
|
export const styles = StyleSheet.create({
|
|
92
|
-
flex1: { flex: 1 },
|
|
93
|
-
scrollContainerStyle: {
|
|
94
|
-
flexGrow: 1,
|
|
95
|
-
alignItems: 'center',
|
|
96
|
-
},
|
|
97
|
-
splitContainer: {
|
|
98
|
-
flex: 1,
|
|
99
|
-
flexDirection: 'row',
|
|
100
|
-
width: '100%',
|
|
101
|
-
},
|
|
102
|
-
splitView: {
|
|
103
|
-
minHeight: '100%',
|
|
104
|
-
},
|
|
69
|
+
flex1: { flex: 1, width: '100%' },
|
|
70
|
+
scrollContainerStyle: { flexGrow: 1, alignItems: 'center', width: '100%' },
|
|
105
71
|
});
|
|
106
72
|
export default ZSContainer;
|
|
107
73
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui/ZSContainer/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { ReactNode, useState, useEffect, useImperativeHandle, forwardRef, useRef } from 'react';\r\nimport { ViewProps, StatusBar, StyleSheet, ActivityIndicator, ScrollView, NativeSyntheticEvent, NativeScrollEvent, Keyboard, View, DimensionValue, Platform } from 'react-native';\r\nimport { SafeAreaView } from 'react-native-safe-area-context';\r\nimport { useTheme } from '../../model/useThemeProvider';\r\nimport VariantView from './ui/VariantView';\r\n\r\nexport type ZSContainerProps = ViewProps & {\r\n backgroundColor?: string;\r\n isLoader?: boolean;\r\n statusBarColor?: string;\r\n barStyle?: 'light-content' | 'dark-content';\r\n edges?: Array<'top' | 'right' | 'bottom' | 'left'>;\r\n scrollViewDisabled?: boolean;\r\n topComponent?: ReactNode;\r\n bottomComponent?: ReactNode;\r\n rightComponent?: ReactNode;\r\n showsVerticalScrollIndicator?: boolean;\r\n loadingComponent?: React.ReactNode;\r\n automaticallyAdjustKeyboardInsets?: boolean;\r\n keyboardScrollExtraOffset?: number;\r\n translucent?: boolean;\r\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\r\n scrollEventThrottle?: number;\r\n};\r\n\r\nexport type ZSContainerRef = ScrollView;\r\n\r\nconst ZSContainer = forwardRef<ZSContainerRef, ZSContainerProps>(function ZSContainer(\r\n {\r\n backgroundColor,\r\n isLoader = false,\r\n statusBarColor,\r\n barStyle,\r\n edges = ['top', 'bottom'],\r\n scrollViewDisabled = false,\r\n topComponent,\r\n bottomComponent,\r\n rightComponent,\r\n showsVerticalScrollIndicator = true,\r\n loadingComponent = <ActivityIndicator />,\r\n automaticallyAdjustKeyboardInsets = true,\r\n keyboardScrollExtraOffset,\r\n translucent,\r\n scrollEventThrottle = 100,\r\n ...props\r\n },\r\n forwardedRef\r\n) {\r\n const { palette, splitBreakpoint, splitRatio, dimensions: { height: windowHeight, width: windowWidth }, isSplitView } = useTheme();\r\n const [isDelayed, setIsDelayed] = useState(true);\r\n const [keyboardHeight, setKeyboardHeight] = useState(0);\r\n const positionRef = useRef<number | null>(0);\r\n const scrollViewRef = useRef<ScrollView>(null);\r\n const lastTouchY = useRef<number | null>(0);\r\n const splitEnabled = !!(isSplitView && (windowWidth >= splitBreakpoint) && rightComponent);\r\n\r\n useImperativeHandle(forwardedRef, () => scrollViewRef.current as ScrollView, []);\r\n\r\n useEffect(() => {\r\n const timer = setTimeout(() => {\r\n setIsDelayed(false);\r\n }, 200);\r\n return () => clearTimeout(timer);\r\n }, []);\r\n\r\n\r\n useEffect(() => {\r\n const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';\r\n const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';\r\n\r\n const keyboardShowSubscription = Keyboard.addListener(showEvent, (e) => {\r\n setKeyboardHeight(e.endCoordinates.height);\r\n if (scrollViewRef.current && keyboardScrollExtraOffset) {\r\n const screenHeight = windowHeight;\r\n const keyboardHeight = e.endCoordinates.height;\r\n const safeAreaBottom = 0;\r\n const availableScreenHeight = screenHeight - keyboardHeight - safeAreaBottom;\r\n\r\n // 현재 터치 위치와 스크롤 위치를 기반으로 새로운 스크롤 위치 계산\r\n const currentScrollPosition = positionRef.current || 0;\r\n const touchPosition = lastTouchY.current || 0;\r\n const scrollOffset = touchPosition - availableScreenHeight + keyboardScrollExtraOffset;\r\n\r\n setTimeout(() => {\r\n scrollViewRef.current?.scrollTo({\r\n y: currentScrollPosition + scrollOffset,\r\n animated: true,\r\n });\r\n }, 150);\r\n }\r\n });\r\n\r\n const keyboardHideSubscription = Keyboard.addListener(hideEvent, () => {\r\n setKeyboardHeight(0);\r\n });\r\n\r\n return () => {\r\n positionRef.current = null;\r\n lastTouchY.current = null;\r\n keyboardShowSubscription.remove();\r\n keyboardHideSubscription.remove();\r\n };\r\n }, [keyboardScrollExtraOffset]);\r\n\r\n const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {\r\n if (props.onScroll) props.onScroll(event);\r\n if (keyboardScrollExtraOffset) positionRef.current = event.nativeEvent.contentOffset.y;\r\n };\r\n\r\n const handleTouch = (evt: any) => {\r\n if (keyboardScrollExtraOffset) lastTouchY.current = evt.nativeEvent.pageY;\r\n };\r\n\r\n const renderContent = () => {\r\n if (isLoader) return loadingComponent;\r\n\r\n const leftWidth = (splitEnabled ? `${splitRatio * 100}%` : '100%') as DimensionValue;\r\n const rightWidth = `${(1 - splitRatio) * 100}%` as DimensionValue;\r\n\r\n return (\r\n <View style={styles.splitContainer}>\r\n\r\n {/* 메인 컴포넌트 */}\r\n <VariantView\r\n style={props.style}\r\n children={props.children}\r\n scrollViewRef={scrollViewRef}\r\n variantWidth={leftWidth}\r\n showsVerticalScrollIndicator={showsVerticalScrollIndicator}\r\n automaticallyAdjustKeyboardInsets={automaticallyAdjustKeyboardInsets}\r\n scrollViewDisabled={scrollViewDisabled}\r\n scrollEventThrottle={scrollEventThrottle}\r\n handleScroll={handleScroll}\r\n handleTouch={handleTouch}\r\n keyboardHeight={keyboardHeight}\r\n />\r\n\r\n {/* 폴드/태블릿 화면 오른쪽 컴포넌트 */}\r\n {rightComponent && splitEnabled && (\r\n <VariantView\r\n style={styles.splitView}\r\n children={rightComponent}\r\n variantWidth={rightWidth}\r\n showsVerticalScrollIndicator={showsVerticalScrollIndicator}\r\n automaticallyAdjustKeyboardInsets={automaticallyAdjustKeyboardInsets}\r\n scrollViewDisabled={false}\r\n scrollEventThrottle={scrollEventThrottle}\r\n />\r\n )}\r\n </View>\r\n );\r\n };\r\n\r\n return (\r\n <SafeAreaView\r\n style={[\r\n { backgroundColor: backgroundColor || palette.background.base },\r\n styles.flex1,\r\n { width: '100%' },\r\n ]}\r\n edges={edges}\r\n >\r\n {!isDelayed && (\r\n <View\r\n style={[styles.flex1, { width: '100%' }]}\r\n >\r\n {topComponent && topComponent}\r\n {renderContent()}\r\n {!isLoader && bottomComponent && bottomComponent}\r\n </View>\r\n )}\r\n\r\n {\r\n (barStyle || statusBarColor || translucent) && (\r\n <StatusBar\r\n barStyle={barStyle}\r\n backgroundColor={statusBarColor || palette.background.base}\r\n translucent={translucent}\r\n />\r\n )\r\n }\r\n </SafeAreaView>\r\n );\r\n});\r\n\r\nexport const styles = StyleSheet.create({\r\n flex1: { flex: 1 },\r\n scrollContainerStyle: {\r\n flexGrow: 1,\r\n alignItems: 'center',\r\n },\r\n splitContainer: {\r\n flex: 1,\r\n flexDirection: 'row',\r\n width: '100%',\r\n },\r\n splitView: {\r\n minHeight: '100%',\r\n },\r\n});\r\n\r\nexport default ZSContainer;\r\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui/ZSContainer/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { ReactNode, useEffect, useImperativeHandle, forwardRef, useRef, useState } from 'react';\r\nimport { ViewProps, StatusBar, StyleSheet, ScrollView, NativeSyntheticEvent, NativeScrollEvent, Keyboard, View, Platform } from 'react-native';\r\nimport { SafeAreaView } from 'react-native-safe-area-context';\r\nimport { useTheme } from '../../model/useThemeProvider';\r\n\r\nexport type ZSContainerProps = ViewProps & {\r\n backgroundColor?: string;\r\n statusBarColor?: string;\r\n barStyle?: 'light-content' | 'dark-content';\r\n edges?: Array<'top' | 'right' | 'bottom' | 'left'>;\r\n scrollViewDisabled?: boolean;\r\n topComponent?: ReactNode;\r\n bottomComponent?: ReactNode;\r\n rightComponent?: ReactNode;\r\n showsVerticalScrollIndicator?: boolean;\r\n keyboardScrollExtraOffset?: number;\r\n translucent?: boolean;\r\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\r\n scrollEventThrottle?: number;\r\n};\r\n\r\nexport type ZSContainerRef = ScrollView;\r\n\r\nconst ZSContainer = forwardRef<ZSContainerRef, ZSContainerProps>(function ZSContainer(\r\n {\r\n backgroundColor,\r\n statusBarColor,\r\n barStyle,\r\n edges = ['top', 'bottom'],\r\n scrollViewDisabled = false,\r\n topComponent,\r\n bottomComponent,\r\n rightComponent,\r\n showsVerticalScrollIndicator = true,\r\n keyboardScrollExtraOffset = 30,\r\n translucent,\r\n scrollEventThrottle = 16,\r\n ...props\r\n },\r\n forwardedRef\r\n) {\r\n const { palette, dimensions: { height: windowHeight } } = useTheme();\r\n const positionRef = useRef<number | null>(0);\r\n const scrollViewRef = useRef<ScrollView>(null);\r\n const lastTouchY = useRef<number | null>(0);\r\n const [keyboardHeight, setKeyboardHeight] = useState<number | null>(0);\r\n\r\n useImperativeHandle(forwardedRef, () => scrollViewRef.current as ScrollView, []);\r\n\r\n useEffect(() => {\r\n const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';\r\n const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';\r\n\r\n const keyboardShowSubscription = Keyboard.addListener(showEvent, (e) => {\r\n setKeyboardHeight(e.endCoordinates.height);\r\n if (scrollViewRef.current) {\r\n const screenHeight = windowHeight;\r\n const keyboardHeight = e.endCoordinates.height;\r\n const safeAreaBottom = 0;\r\n const availableScreenHeight = screenHeight - keyboardHeight - safeAreaBottom;\r\n const currentScrollPosition = positionRef.current || 0;\r\n const touchPosition = lastTouchY.current || 0;\r\n\r\n // touchPosition이 키보드 높이보다 아래인 경우\r\n // const isTouchPositionBelowKeyboard = touchPosition > availableScreenHeight;\r\n\r\n // 현재 터치 위치와 스크롤 위치를 기반으로 새로운 스크롤 위치 계산\r\n const scrollOffset = touchPosition - availableScreenHeight + keyboardScrollExtraOffset;\r\n\r\n setTimeout(() => {\r\n scrollViewRef.current?.scrollTo({\r\n y: currentScrollPosition + scrollOffset,\r\n animated: true,\r\n });\r\n }, 100);\r\n }\r\n });\r\n\r\n const keyboardHideSubscription = Keyboard.addListener(hideEvent, () => {\r\n setKeyboardHeight(0);\r\n });\r\n\r\n return () => {\r\n positionRef.current = null;\r\n lastTouchY.current = null;\r\n keyboardShowSubscription.remove();\r\n keyboardHideSubscription.remove();\r\n };\r\n }, [keyboardScrollExtraOffset]);\r\n\r\n const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {\r\n if (props.onScroll) props.onScroll(event);\r\n positionRef.current = event.nativeEvent.contentOffset.y;\r\n };\r\n\r\n const handleTouch = (evt: any) => {\r\n lastTouchY.current = evt.nativeEvent.pageY;\r\n };\r\n\r\n return (\r\n <SafeAreaView\r\n style={[{ backgroundColor: backgroundColor || palette.background.base }, styles.flex1]}\r\n edges={edges}\r\n >\r\n <View style={styles.flex1}>\r\n {topComponent && topComponent}\r\n <ScrollView\r\n ref={scrollViewRef}\r\n style={styles.flex1}\r\n contentContainerStyle={[styles.scrollContainerStyle, { paddingBottom: Platform.OS === 'ios' ? keyboardHeight || 0 : 0 }]}\r\n bounces={false}\r\n overScrollMode=\"never\"\r\n showsVerticalScrollIndicator={showsVerticalScrollIndicator}\r\n keyboardShouldPersistTaps=\"handled\"\r\n automaticallyAdjustKeyboardInsets={false}\r\n onScroll={handleScroll}\r\n onTouchStart={handleTouch}\r\n scrollEventThrottle={scrollEventThrottle}\r\n >\r\n <View style={[styles.flex1, props.style]}>\r\n {props.children}\r\n </View>\r\n </ScrollView>\r\n {bottomComponent && bottomComponent}\r\n </View>\r\n\r\n {\r\n (barStyle || statusBarColor || translucent) && (\r\n <StatusBar\r\n barStyle={barStyle}\r\n backgroundColor={statusBarColor || palette.background.base}\r\n translucent={translucent}\r\n />\r\n )\r\n }\r\n </SafeAreaView>\r\n );\r\n});\r\n\r\nexport const styles = StyleSheet.create({\r\n flex1: { flex: 1, width: '100%' },\r\n scrollContainerStyle: { flexGrow: 1, alignItems: 'center', width: '100%' },\r\n});\r\n\r\nexport default ZSContainer;\r\n"]}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { styles } from '..';
|
|
2
1
|
import { ScrollView, View } from 'react-native';
|
|
3
2
|
export default function VariantView({ children, scrollViewDisabled, style, scrollViewRef, variantWidth, showsVerticalScrollIndicator, automaticallyAdjustKeyboardInsets, handleScroll, handleTouch, scrollEventThrottle, keyboardHeight }) {
|
|
4
3
|
return (scrollViewDisabled ? (<View style={[style, { width: variantWidth }]}>
|
|
5
4
|
{children}
|
|
6
|
-
</View>) : (<ScrollView ref={scrollViewRef} style={{ width: variantWidth }}
|
|
7
|
-
|
|
5
|
+
</View>) : (<ScrollView ref={scrollViewRef} style={{ width: variantWidth }}
|
|
6
|
+
// contentContainerStyle={[styles.scrollContainerStyle, { paddingBottom: keyboardHeight || 0 }]}
|
|
7
|
+
bounces={false} overScrollMode="never" showsVerticalScrollIndicator={showsVerticalScrollIndicator} keyboardShouldPersistTaps="handled" automaticallyAdjustKeyboardInsets={automaticallyAdjustKeyboardInsets} onScroll={handleScroll} onTouchStart={handleTouch} scrollEventThrottle={scrollEventThrottle}>
|
|
8
|
+
{/* <View style={[styles.splitView, style, { width: '100%' }]}>
|
|
8
9
|
{children}
|
|
9
|
-
</View>
|
|
10
|
+
</View> */}
|
|
10
11
|
</ScrollView>));
|
|
11
12
|
}
|
|
12
13
|
//# sourceMappingURL=VariantView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VariantView.js","sourceRoot":"","sources":["../../../../src/ui/ZSContainer/ui/VariantView.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VariantView.js","sourceRoot":"","sources":["../../../../src/ui/ZSContainer/ui/VariantView.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAA2C,IAAI,EAAwC,MAAM,cAAc,CAAC;AAgB/H,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,QAAQ,EAAE,kBAAkB,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,4BAA4B,EAAE,iCAAiC,EAAE,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE,cAAc,EAAoB;IACzP,OAAO,CACL,kBAAkB,CAAC,CAAC,CAAC,CACnB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,CAC5C;QAAA,CAAC,QAAQ,CACX;MAAA,EAAE,IAAI,CAAC,CACR,CAAC,CAAC,CAAC,CACF,CAAC,UAAU,CACT,GAAG,CAAC,CAAC,aAAa,CAAC,CACnB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAC/B,gGAAgG;IAChG,OAAO,CAAC,CAAC,KAAK,CAAC,CACf,cAAc,CAAC,OAAO,CACtB,4BAA4B,CAAC,CAAC,4BAA4B,CAAC,CAC3D,yBAAyB,CAAC,SAAS,CACnC,iCAAiC,CAAC,CAAC,iCAAiC,CAAC,CACrE,QAAQ,CAAC,CAAC,YAAY,CAAC,CACvB,YAAY,CAAC,CAAC,WAAW,CAAC,CAC1B,mBAAmB,CAAC,CAAC,mBAAmB,CAAC,CAEzC;QAAA,CAAC;;kBAES,CACZ;MAAA,EAAE,UAAU,CAAC,CACd,CACF,CAAA;AACH,CAAC","sourcesContent":["import { styles } from '..';\nimport { ScrollView, NativeSyntheticEvent, NativeScrollEvent, View, DimensionValue, StyleProp, ViewStyle } from 'react-native';\n\ninterface VariantViewProps {\n children: React.ReactNode;\n scrollViewDisabled?: boolean;\n style: StyleProp<ViewStyle>;\n scrollViewRef?: React.RefObject<ScrollView>;\n variantWidth?: DimensionValue;\n showsVerticalScrollIndicator?: boolean;\n automaticallyAdjustKeyboardInsets?: boolean;\n handleScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n handleTouch?: (event: any) => void;\n scrollEventThrottle?: number;\n keyboardHeight?: number;\n}\n\nexport default function VariantView({ children, scrollViewDisabled, style, scrollViewRef, variantWidth, showsVerticalScrollIndicator, automaticallyAdjustKeyboardInsets, handleScroll, handleTouch, scrollEventThrottle, keyboardHeight }: VariantViewProps) {\n return (\n scrollViewDisabled ? (\n <View style={[style, { width: variantWidth }]}>\n {children}\n </View>\n ) : (\n <ScrollView\n ref={scrollViewRef}\n style={{ width: variantWidth }}\n // contentContainerStyle={[styles.scrollContainerStyle, { paddingBottom: keyboardHeight || 0 }]}\n bounces={false}\n overScrollMode=\"never\"\n showsVerticalScrollIndicator={showsVerticalScrollIndicator}\n keyboardShouldPersistTaps=\"handled\"\n automaticallyAdjustKeyboardInsets={automaticallyAdjustKeyboardInsets}\n onScroll={handleScroll}\n onTouchStart={handleTouch}\n scrollEventThrottle={scrollEventThrottle}\n >\n {/* <View style={[styles.splitView, style, { width: '100%' }]}>\n {children}\n </View> */}\n </ScrollView>\n )\n )\n}"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0610studio/zs-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "EXPO ZS-UI",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
15
|
"start:android": "cd example && yarn install && npx expo run:android",
|
|
16
|
-
"start:ios": "cd example && yarn install && npx expo run:ios",
|
|
16
|
+
"start:ios": "cd example && yarn install && npx expo run:ios --device",
|
|
17
17
|
"build": "expo-module build",
|
|
18
18
|
"prepare": "expo-module prepare",
|
|
19
19
|
"---------------------------------------------------------------------------": "",
|