@0610studio/zs-ui 0.7.1 → 0.7.2

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 (49) hide show
  1. package/build/index.d.ts +5 -4
  2. package/build/index.d.ts.map +1 -1
  3. package/build/index.js +2 -1
  4. package/build/index.js.map +1 -1
  5. package/build/model/types.d.ts +1 -11
  6. package/build/model/types.d.ts.map +1 -1
  7. package/build/model/types.js.map +1 -1
  8. package/build/model/useOverlay.d.ts +1 -3
  9. package/build/model/useOverlay.d.ts.map +1 -1
  10. package/build/model/useOverlay.js +0 -8
  11. package/build/model/useOverlay.js.map +1 -1
  12. package/build/model/useOverlayProvider.d.ts.map +1 -1
  13. package/build/model/useOverlayProvider.js +8 -38
  14. package/build/model/useOverlayProvider.js.map +1 -1
  15. package/build/model/utils.d.ts +1 -0
  16. package/build/model/utils.d.ts.map +1 -1
  17. package/build/model/utils.js +9 -0
  18. package/build/model/utils.js.map +1 -1
  19. package/build/overlay/BottomSheetOverlay/index.d.ts +2 -1
  20. package/build/overlay/BottomSheetOverlay/index.d.ts.map +1 -1
  21. package/build/overlay/BottomSheetOverlay/index.js +144 -91
  22. package/build/overlay/BottomSheetOverlay/index.js.map +1 -1
  23. package/build/ui/ZSAboveKeyboard/index.d.ts +7 -0
  24. package/build/ui/ZSAboveKeyboard/index.d.ts.map +1 -0
  25. package/build/ui/ZSAboveKeyboard/index.js +47 -0
  26. package/build/ui/ZSAboveKeyboard/index.js.map +1 -0
  27. package/build/ui/ZSContainer/index.d.ts +16 -14
  28. package/build/ui/ZSContainer/index.d.ts.map +1 -1
  29. package/build/ui/ZSContainer/index.js +78 -40
  30. package/build/ui/ZSContainer/index.js.map +1 -1
  31. package/build/ui/ZSPressable/index.d.ts +2 -1
  32. package/build/ui/ZSPressable/index.d.ts.map +1 -1
  33. package/build/ui/ZSPressable/index.js +40 -16
  34. package/build/ui/ZSPressable/index.js.map +1 -1
  35. package/build/ui/ZSTextField/index.d.ts.map +1 -1
  36. package/build/ui/ZSTextField/index.js +127 -41
  37. package/build/ui/ZSTextField/index.js.map +1 -1
  38. package/build/ui/atoms/AnimatedWrapper.d.ts.map +1 -1
  39. package/build/ui/atoms/AnimatedWrapper.js +58 -16
  40. package/build/ui/atoms/AnimatedWrapper.js.map +1 -1
  41. package/package.json +1 -1
  42. package/build/overlay/AboveKeyboard/index.d.ts +0 -4
  43. package/build/overlay/AboveKeyboard/index.d.ts.map +0 -1
  44. package/build/overlay/AboveKeyboard/index.js +0 -41
  45. package/build/overlay/AboveKeyboard/index.js.map +0 -1
  46. package/build/ui/ZSContainer/ui/VariantView.d.ts +0 -17
  47. package/build/ui/ZSContainer/ui/VariantView.d.ts.map +0 -1
  48. package/build/ui/ZSContainer/ui/VariantView.js +0 -13
  49. package/build/ui/ZSContainer/ui/VariantView.js.map +0 -1
@@ -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, 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 {\r\n scrollViewDisabled ? (\r\n <View style={styles.flex1}>\r\n {props.children}\r\n </View>\r\n ) : (\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 )\r\n }\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
+ {"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, useCallback, useMemo } 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\nconst IS_IOS = Platform.OS === 'ios';\r\nconst KEYBOARD_ANIMATION_DELAY = 50;\r\nconst keyboardEvents = {\r\n showEvent: IS_IOS ? 'keyboardWillShow' as const : 'keyboardDidShow' as const,\r\n hideEvent: IS_IOS ? 'keyboardWillHide' as const : 'keyboardDidHide' as const,\r\n};\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 scrollToFocusedInput?: boolean;\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 scrollToFocusedInput = true,\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 const handleKeyboardShow = useCallback((e: any) => {\r\n setKeyboardHeight(e.endCoordinates.height);\r\n \r\n if (scrollViewRef.current && scrollToFocusedInput) {\r\n const keyboardHeight = e.endCoordinates.height;\r\n const safeAreaBottom = 0;\r\n const availableScreenHeight = windowHeight - keyboardHeight - safeAreaBottom;\r\n const currentScrollPosition = positionRef.current || 0;\r\n const touchPosition = lastTouchY.current || 0;\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 }, KEYBOARD_ANIMATION_DELAY);\r\n }\r\n }, [windowHeight, keyboardScrollExtraOffset, scrollToFocusedInput]);\r\n\r\n // 키보드 숨김 핸들러를 메모이제이션하여 성능 최적화\r\n const handleKeyboardHide = useCallback(() => {\r\n setKeyboardHeight(0);\r\n }, []);\r\n\r\n useEffect(() => {\r\n const keyboardShowSubscription = Keyboard.addListener(keyboardEvents.showEvent, handleKeyboardShow);\r\n const keyboardHideSubscription = Keyboard.addListener(keyboardEvents.hideEvent, handleKeyboardHide);\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 }, [keyboardEvents.showEvent, keyboardEvents.hideEvent, handleKeyboardShow, handleKeyboardHide]);\r\n\r\n const handleScroll = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {\r\n if (props.onScroll) props.onScroll(event);\r\n positionRef.current = event.nativeEvent.contentOffset.y;\r\n }, [props.onScroll]);\r\n\r\n const handleTouch = useCallback((evt: any) => {\r\n lastTouchY.current = evt.nativeEvent.pageY;\r\n }, []);\r\n\r\n const safeAreaStyle = useMemo(() => [\r\n { backgroundColor: backgroundColor || palette.background.base }, \r\n styles.flex1\r\n ], [backgroundColor, palette.background.base]);\r\n\r\n const scrollContentStyle = useMemo(() => [\r\n styles.scrollContainerStyle, \r\n { \r\n paddingBottom: keyboardHeight ? (IS_IOS ? keyboardHeight : keyboardScrollExtraOffset) : 0 \r\n }\r\n ], [keyboardHeight, keyboardScrollExtraOffset]);\r\n\r\n const containerStyle = useMemo(() => [\r\n styles.flex1, \r\n props.style\r\n ], [props.style]);\r\n\r\n const shouldShowStatusBar = useMemo(() => \r\n Boolean(barStyle || statusBarColor || translucent), \r\n [barStyle, statusBarColor, translucent]\r\n );\r\n\r\n return (\r\n <SafeAreaView\r\n style={safeAreaStyle}\r\n edges={edges}\r\n >\r\n <View style={styles.flex1}>\r\n {topComponent}\r\n {\r\n scrollViewDisabled ? (\r\n <View style={styles.flex1}>\r\n {props.children}\r\n </View>\r\n ) : (\r\n <ScrollView\r\n ref={scrollViewRef}\r\n style={styles.flex1}\r\n contentContainerStyle={scrollContentStyle}\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={containerStyle}>\r\n {props.children}\r\n </View>\r\n </ScrollView>\r\n )\r\n }\r\n {bottomComponent}\r\n </View>\r\n\r\n {shouldShowStatusBar && (\r\n <StatusBar\r\n barStyle={barStyle}\r\n backgroundColor={statusBarColor || palette.background.base}\r\n translucent={translucent}\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\nconst arePropsEqual = (\r\n prevProps: ZSContainerProps, \r\n nextProps: ZSContainerProps\r\n): boolean => {\r\n return (\r\n prevProps.backgroundColor === nextProps.backgroundColor &&\r\n prevProps.statusBarColor === nextProps.statusBarColor &&\r\n prevProps.barStyle === nextProps.barStyle &&\r\n prevProps.scrollViewDisabled === nextProps.scrollViewDisabled &&\r\n prevProps.showsVerticalScrollIndicator === nextProps.showsVerticalScrollIndicator &&\r\n prevProps.keyboardScrollExtraOffset === nextProps.keyboardScrollExtraOffset &&\r\n prevProps.translucent === nextProps.translucent &&\r\n prevProps.scrollEventThrottle === nextProps.scrollEventThrottle &&\r\n prevProps.scrollToFocusedInput === nextProps.scrollToFocusedInput &&\r\n prevProps.onScroll === nextProps.onScroll &&\r\n prevProps.style === nextProps.style &&\r\n prevProps.children === nextProps.children &&\r\n prevProps.topComponent === nextProps.topComponent &&\r\n prevProps.bottomComponent === nextProps.bottomComponent &&\r\n prevProps.rightComponent === nextProps.rightComponent &&\r\n // edges 배열 비교\r\n JSON.stringify(prevProps.edges) === JSON.stringify(nextProps.edges)\r\n );\r\n};\r\n\r\nexport default React.memo(ZSContainer, arePropsEqual);\r\n"]}
@@ -13,5 +13,6 @@ interface ZSPressableProps extends ViewProps {
13
13
  color?: ViewColorOptions;
14
14
  }
15
15
  declare function ZSPressable({ onPress, onLongPress, isAnimation, pressedBackgroundColor, pressedBackgroundBorderRadius, elevationLevel, fullWidth, color, ...props }: ZSPressableProps): React.JSX.Element;
16
- export default ZSPressable;
16
+ declare const _default: React.MemoExoticComponent<typeof ZSPressable>;
17
+ export default _default;
17
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/ZSPressable/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAmB,SAAS,EAAE,MAAM,cAAc,CAAC;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAIrD,UAAU,gBAAiB,SAAQ,SAAS;IAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IACpC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B;AAED,iBAAS,WAAW,CAAC,EACnB,OAAO,EACP,WAAW,EACX,WAAkB,EAClB,sBAAmD,EACnD,6BAAkC,EAClC,cAAc,EACd,SAAiB,EACjB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,gBAAgB,qBAgDlB;AAED,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/ZSPressable/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAmB,SAAS,EAAE,MAAM,cAAc,CAAC;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAKrD,UAAU,gBAAiB,SAAQ,SAAS;IAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IACpC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B;AAED,iBAAS,WAAW,CAAC,EACnB,OAAO,EACP,WAAW,EACX,WAAkB,EAClB,sBAAmD,EACnD,6BAAkC,EAClC,cAAc,EACd,SAAiB,EACjB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,gBAAgB,qBAkElB;;AAoBD,wBAAsD"}
@@ -1,27 +1,39 @@
1
- import React, { useCallback } from "react";
1
+ import React, { useCallback, useMemo, useRef } from "react";
2
2
  import { Pressable, View } from "react-native";
3
- import Animated, { interpolate, useAnimatedStyle, useSharedValue, withTiming, runOnJS } from "react-native-reanimated";
3
+ import Animated, { interpolate, useAnimatedStyle, useSharedValue, withTiming } from "react-native-reanimated";
4
4
  import AnimatedWrapper from "../atoms/AnimatedWrapper";
5
5
  const DEFAULT_DURATION = { duration: 100 };
6
+ const SCALE_VALUES = [1, 0.96];
6
7
  function ZSPressable({ onPress, onLongPress, isAnimation = true, pressedBackgroundColor = 'rgba(180, 180, 180, 0.1)', pressedBackgroundBorderRadius = 16, elevationLevel, fullWidth = false, color, ...props }) {
7
- const isButtonPress = useSharedValue(0);
8
+ const isButtonPress = useRef(useSharedValue(0)).current;
8
9
  const boxAnimation = useAnimatedStyle(() => {
9
- const scale = interpolate(isButtonPress.value, [0, 1], [1, 0.96], 'clamp');
10
+ const scale = interpolate(isButtonPress.value, [0, 1], SCALE_VALUES, 'clamp');
10
11
  return {
11
- transform: [{ scale: withTiming(scale, DEFAULT_DURATION) }],
12
+ transform: [{ scale }],
12
13
  };
13
14
  }, []);
15
+ const handlePressIn = useCallback(() => {
16
+ isButtonPress.value = withTiming(1, DEFAULT_DURATION);
17
+ }, [isButtonPress]);
18
+ const handlePressOut = useCallback(() => {
19
+ isButtonPress.value = withTiming(0, DEFAULT_DURATION);
20
+ }, [isButtonPress]);
21
+ const pressedStyle = useMemo(() => ({
22
+ backgroundColor: pressedBackgroundColor,
23
+ borderRadius: pressedBackgroundBorderRadius,
24
+ }), [pressedBackgroundColor, pressedBackgroundBorderRadius]);
25
+ const unpressedStyle = useMemo(() => ({
26
+ backgroundColor: 'transparent',
27
+ borderRadius: pressedBackgroundBorderRadius,
28
+ }), [pressedBackgroundBorderRadius]);
14
29
  const handlePressStyle = useCallback((pressed) => {
15
- runOnJS(() => {
16
- isButtonPress.value = pressed ? 1 : 0;
17
- })();
18
- return {
19
- backgroundColor: pressed ? pressedBackgroundColor : 'transparent',
20
- borderRadius: pressedBackgroundBorderRadius,
21
- };
22
- }, [pressedBackgroundColor, pressedBackgroundBorderRadius, fullWidth]);
23
- return (<View style={{ width: fullWidth ? '100%' : undefined }}>
24
- <Pressable onPress={onPress} onLongPress={onLongPress} style={({ pressed }) => handlePressStyle(pressed)}>
30
+ return pressed ? pressedStyle : unpressedStyle;
31
+ }, [pressedStyle, unpressedStyle]);
32
+ const containerStyle = useMemo(() => ({
33
+ width: fullWidth ? '100%' : undefined
34
+ }), [fullWidth]);
35
+ return (<View style={containerStyle}>
36
+ <Pressable onPress={onPress} onLongPress={onLongPress} onPressIn={handlePressIn} onPressOut={handlePressOut} style={({ pressed }) => handlePressStyle(pressed)}>
25
37
  <Animated.View style={boxAnimation}>
26
38
  <AnimatedWrapper color={color} isAnimation={isAnimation} elevationLevel={elevationLevel} style={props.style}>
27
39
  {props.children}
@@ -30,5 +42,17 @@ function ZSPressable({ onPress, onLongPress, isAnimation = true, pressedBackgrou
30
42
  </Pressable>
31
43
  </View>);
32
44
  }
33
- export default ZSPressable;
45
+ const arePropsEqual = (prevProps, nextProps) => {
46
+ return (prevProps.onPress === nextProps.onPress &&
47
+ prevProps.onLongPress === nextProps.onLongPress &&
48
+ prevProps.isAnimation === nextProps.isAnimation &&
49
+ prevProps.pressedBackgroundColor === nextProps.pressedBackgroundColor &&
50
+ prevProps.pressedBackgroundBorderRadius === nextProps.pressedBackgroundBorderRadius &&
51
+ prevProps.elevationLevel === nextProps.elevationLevel &&
52
+ prevProps.fullWidth === nextProps.fullWidth &&
53
+ prevProps.color === nextProps.color &&
54
+ prevProps.style === nextProps.style &&
55
+ prevProps.children === nextProps.children);
56
+ };
57
+ export default React.memo(ZSPressable, arePropsEqual);
34
58
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui/ZSPressable/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,IAAI,EAAa,MAAM,cAAc,CAAC;AAC1D,OAAO,QAAQ,EAAE,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvH,OAAO,eAAe,MAAM,0BAA0B,CAAC;AAIvD,MAAM,gBAAgB,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AAa3C,SAAS,WAAW,CAAC,EACnB,OAAO,EACP,WAAW,EACX,WAAW,GAAG,IAAI,EAClB,sBAAsB,GAAG,0BAA0B,EACnD,6BAA6B,GAAG,EAAE,EAClC,cAAc,EACd,SAAS,GAAG,KAAK,EACjB,KAAK,EACL,GAAG,KAAK,EACS;IACjB,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAExC,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,EAAE;QACzC,MAAM,KAAK,GAAG,WAAW,CACvB,aAAa,CAAC,KAAK,EACnB,CAAC,CAAC,EAAE,CAAC,CAAC,EACN,CAAC,CAAC,EAAE,IAAI,CAAC,EACT,OAAO,CACR,CAAC;QACF,OAAO;YACL,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC;SAC5D,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,gBAAgB,GAAG,WAAW,CAClC,CAAC,OAAgB,EAAE,EAAE;QACnB,OAAO,CAAC,GAAG,EAAE;YACX,aAAa,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,CAAC,CAAC,EAAE,CAAC;QACL,OAAO;YACL,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,aAAa;YACjE,YAAY,EAAE,6BAA6B;SAC5C,CAAC;IACJ,CAAC,EACD,CAAC,sBAAsB,EAAE,6BAA6B,EAAE,SAAS,CAAC,CACnE,CAAC;IAEF,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,MAAe,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAC9D;MAAA,CAAC,SAAS,CACR,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAElD;QAAA,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CACjC;UAAA,CAAC,eAAe,CACd,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,cAAc,CAAC,CAAC,cAAc,CAAC,CAC/B,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAEnB;YAAA,CAAC,KAAK,CAAC,QAAQ,CACjB;UAAA,EAAE,eAAe,CACnB;QAAA,EAAE,QAAQ,CAAC,IAAI,CACjB;MAAA,EAAE,SAAS,CACb;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,eAAe,WAAW,CAAC","sourcesContent":["import React, { useCallback } from \"react\";\nimport { Pressable, View, ViewProps } from \"react-native\";\nimport Animated, { interpolate, useAnimatedStyle, useSharedValue, withTiming, runOnJS } from \"react-native-reanimated\";\nimport AnimatedWrapper from \"../atoms/AnimatedWrapper\";\nimport type { ShadowLevel } from \"../types\";\nimport { ViewColorOptions } from \"../../theme/types\";\n\nconst DEFAULT_DURATION = { duration: 100 };\n\ninterface ZSPressableProps extends ViewProps {\n onPress?: (value?: any) => void;\n onLongPress?: (value?: any) => void;\n pressedBackgroundColor?: string;\n pressedBackgroundBorderRadius?: number;\n isAnimation?: boolean;\n elevationLevel?: ShadowLevel;\n fullWidth?: boolean;\n color?: ViewColorOptions;\n}\n\nfunction ZSPressable({\n onPress,\n onLongPress,\n isAnimation = true,\n pressedBackgroundColor = 'rgba(180, 180, 180, 0.1)',\n pressedBackgroundBorderRadius = 16,\n elevationLevel,\n fullWidth = false,\n color,\n ...props\n}: ZSPressableProps) {\n const isButtonPress = useSharedValue(0);\n\n const boxAnimation = useAnimatedStyle(() => {\n const scale = interpolate(\n isButtonPress.value,\n [0, 1],\n [1, 0.96],\n 'clamp'\n );\n return {\n transform: [{ scale: withTiming(scale, DEFAULT_DURATION) }],\n };\n }, []);\n\n const handlePressStyle = useCallback(\n (pressed: boolean) => {\n runOnJS(() => {\n isButtonPress.value = pressed ? 1 : 0;\n })();\n return {\n backgroundColor: pressed ? pressedBackgroundColor : 'transparent',\n borderRadius: pressedBackgroundBorderRadius,\n };\n },\n [pressedBackgroundColor, pressedBackgroundBorderRadius, fullWidth]\n );\n\n return (\n <View style={{ width: fullWidth ? '100%' as const : undefined }}>\n <Pressable\n onPress={onPress}\n onLongPress={onLongPress}\n style={({ pressed }) => handlePressStyle(pressed)}\n >\n <Animated.View style={boxAnimation}>\n <AnimatedWrapper\n color={color}\n isAnimation={isAnimation}\n elevationLevel={elevationLevel}\n style={props.style}\n >\n {props.children}\n </AnimatedWrapper>\n </Animated.View>\n </Pressable>\n </View>\n );\n}\n\nexport default ZSPressable;\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui/ZSPressable/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useCallback, useMemo, useRef } from \"react\";\nimport { Pressable, View, ViewProps } from \"react-native\";\nimport Animated, { interpolate, useAnimatedStyle, useSharedValue, withTiming } from \"react-native-reanimated\";\nimport AnimatedWrapper from \"../atoms/AnimatedWrapper\";\nimport type { ShadowLevel } from \"../types\";\nimport { ViewColorOptions } from \"../../theme/types\";\n\nconst DEFAULT_DURATION = { duration: 100 } as const;\nconst SCALE_VALUES = [1, 0.96] as const;\n\ninterface ZSPressableProps extends ViewProps {\n onPress?: (value?: any) => void;\n onLongPress?: (value?: any) => void;\n pressedBackgroundColor?: string;\n pressedBackgroundBorderRadius?: number;\n isAnimation?: boolean;\n elevationLevel?: ShadowLevel;\n fullWidth?: boolean;\n color?: ViewColorOptions;\n}\n\nfunction ZSPressable({\n onPress,\n onLongPress,\n isAnimation = true,\n pressedBackgroundColor = 'rgba(180, 180, 180, 0.1)',\n pressedBackgroundBorderRadius = 16,\n elevationLevel,\n fullWidth = false,\n color,\n ...props\n}: ZSPressableProps) {\n const isButtonPress = useRef(useSharedValue(0)).current;\n\n const boxAnimation = useAnimatedStyle(() => {\n const scale = interpolate(\n isButtonPress.value,\n [0, 1],\n SCALE_VALUES,\n 'clamp'\n );\n return {\n transform: [{ scale }],\n };\n }, []);\n \n const handlePressIn = useCallback(() => {\n isButtonPress.value = withTiming(1, DEFAULT_DURATION);\n }, [isButtonPress]);\n \n const handlePressOut = useCallback(() => {\n isButtonPress.value = withTiming(0, DEFAULT_DURATION);\n }, [isButtonPress]);\n\n const pressedStyle = useMemo(() => ({\n backgroundColor: pressedBackgroundColor,\n borderRadius: pressedBackgroundBorderRadius,\n }), [pressedBackgroundColor, pressedBackgroundBorderRadius]);\n \n const unpressedStyle = useMemo(() => ({\n backgroundColor: 'transparent',\n borderRadius: pressedBackgroundBorderRadius,\n }), [pressedBackgroundBorderRadius]);\n \n const handlePressStyle = useCallback(\n (pressed: boolean) => {\n return pressed ? pressedStyle : unpressedStyle;\n },\n [pressedStyle, unpressedStyle]\n );\n\n const containerStyle = useMemo(() => ({\n width: fullWidth ? '100%' as const : undefined\n }), [fullWidth]);\n\n return (\n <View style={containerStyle}>\n <Pressable\n onPress={onPress}\n onLongPress={onLongPress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n style={({ pressed }) => handlePressStyle(pressed)}\n >\n <Animated.View style={boxAnimation}>\n <AnimatedWrapper\n color={color}\n isAnimation={isAnimation}\n elevationLevel={elevationLevel}\n style={props.style}\n >\n {props.children}\n </AnimatedWrapper>\n </Animated.View>\n </Pressable>\n </View>\n );\n}\n\nconst arePropsEqual = (\n prevProps: ZSPressableProps, \n nextProps: ZSPressableProps\n): boolean => {\n return (\n prevProps.onPress === nextProps.onPress &&\n prevProps.onLongPress === nextProps.onLongPress &&\n prevProps.isAnimation === nextProps.isAnimation &&\n prevProps.pressedBackgroundColor === nextProps.pressedBackgroundColor &&\n prevProps.pressedBackgroundBorderRadius === nextProps.pressedBackgroundBorderRadius &&\n prevProps.elevationLevel === nextProps.elevationLevel &&\n prevProps.fullWidth === nextProps.fullWidth &&\n prevProps.color === nextProps.color &&\n prevProps.style === nextProps.style &&\n prevProps.children === nextProps.children\n );\n};\n\nexport default React.memo(ZSPressable, arePropsEqual);\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/ZSTextField/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoD,MAAM,OAAO,CAAC;AACzE,OAAO,EAAqD,cAAc,EAAwB,MAAM,cAAc,CAAC;AAIvH,OAAO,EAAE,WAAW,EAA2B,MAAM,aAAa,CAAC;AAKnE,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;AAIzD,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,iBAAS,WAAW,CAAC,EACnB,IAAe,EACf,MAAkB,EAClB,KAAK,EACL,YAAY,EACZ,KAAqB,EACrB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,WAAiB,EACjB,WAAW,EACX,UAAU,EACV,UAAU,EACV,YAAiB,EACjB,iBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,QAAoB,EACpB,aAAa,EACb,QAAgB,EAChB,gBAAuB,EACvB,UAAkB,GACnB,EAAE,cAAc,GAAG,GAAG,CAAC,OAAO,CA6I9B;;AAED,wBAAuC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/ZSTextField/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AACjF,OAAO,EAAqD,cAAc,EAAwB,MAAM,cAAc,CAAC;AAIvH,OAAO,EAAE,WAAW,EAA2B,MAAM,aAAa,CAAC;AAKnE,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;AAIzD,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,iBAAS,WAAW,CAAC,EACnB,IAAe,EACf,MAAkB,EAClB,KAAK,EACL,YAAY,EACZ,KAAqB,EACrB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,WAAiB,EACjB,WAAW,EACX,UAAU,EACV,UAAU,EACV,YAAiB,EACjB,iBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,QAAoB,EACpB,aAAa,EACb,QAAgB,EAChB,gBAAuB,EACvB,UAAkB,GACnB,EAAE,cAAc,GAAG,GAAG,CAAC,OAAO,CAoN9B;;AAoBD,wBAAsD"}
@@ -1,4 +1,4 @@
1
- import React, { useMemo, useCallback, useState, useEffect } from 'react';
1
+ import React, { useMemo, useCallback, useState, useEffect, useRef } from 'react';
2
2
  import { Platform, TextInput } from 'react-native';
3
3
  import Animated, { interpolate, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
4
4
  import ButtonClose from './ui/ButtonClose';
@@ -9,31 +9,43 @@ import ViewAtom from '../atoms/ViewAtom';
9
9
  const iosOffset = Platform.OS === 'ios' ? 8 : 4;
10
10
  function ZSTextField({ typo = 'body.2', status = 'default', value, onChangeText, label = 'Placeholder', labelColor, placeHolderColor, inputBgColor, labelBgColor, borderWidth = 1.2, borderColor, focusColor, errorColor, borderRadius = 14, paddingHorizontal = 15, errorMessage, textInputProps, boxStyle = 'outline', innerBoxStyle, disabled = false, allowFontScaling = true, isTextArea = false, }) {
11
11
  const { typography, palette } = useTheme();
12
- const [primaryStyle, subStyle] = typo.split('.');
13
- let fErrorColor = errorColor || palette.danger.main;
14
- // 폰트 크기 패밀리 추출
15
- const fontSize = useMemo(() => extractStyle(typography[primaryStyle][subStyle], 'fontSize') || 17, [typography, primaryStyle, subStyle]);
16
- const fontFamily = useMemo(() => extractStyle(typography[primaryStyle][subStyle], 'fontFamily') || '', [typography, primaryStyle, subStyle]);
17
- // 컴포넌트 상태 관리
12
+ const typoConfig = useMemo(() => {
13
+ const [primaryStyle, subStyle] = typo.split('.');
14
+ return { primaryStyle, subStyle };
15
+ }, [typo]);
16
+ const fErrorColor = useMemo(() => errorColor || palette.danger.main, [errorColor, palette.danger.main]);
17
+ const fontSize = useMemo(() => {
18
+ return extractStyle(typography[typoConfig.primaryStyle][typoConfig.subStyle], 'fontSize') || 17;
19
+ }, [typography, typoConfig.primaryStyle, typoConfig.subStyle]);
20
+ const fontFamily = useMemo(() => {
21
+ return extractStyle(typography[typoConfig.primaryStyle][typoConfig.subStyle], 'fontFamily') || '';
22
+ }, [typography, typoConfig.primaryStyle, typoConfig.subStyle]);
18
23
  const [isFocused, setIsFocused] = useState(false);
19
- const labelAnimationValue = useSharedValue(0);
20
- const boxHeightValue = useSharedValue(0);
24
+ const labelAnimationValue = useRef(useSharedValue(0)).current;
25
+ const boxHeightValue = useRef(useSharedValue(0)).current;
21
26
  // 포커스 및 값 변경 시 라벨 애니메이션 트리거
22
27
  useEffect(() => {
23
- labelAnimationValue.value = withTiming(value !== '' || isFocused ? 1 : 0, { duration: 150 });
24
- }, [value, isFocused]);
28
+ labelAnimationValue.value = withTiming(value !== '' || isFocused ? 1 : 0, { duration: 100 });
29
+ }, [value, isFocused, labelAnimationValue]);
30
+ // 애니메이션 관련 상수
31
+ const animationConstants = useMemo(() => ({
32
+ baseFontSize: fontSize + (boxStyle === 'inbox' ? 1 : 0),
33
+ targetFontSize: boxStyle === 'inbox' ? 10 : 11,
34
+ baseTop: isTextArea ? 12 : 0,
35
+ targetTopOffset: boxStyle === 'inbox' ? 17 : 2,
36
+ }), [fontSize, boxStyle, isTextArea]);
25
37
  // 라벨 애니메이션 스타일
26
38
  const animatedLabelStyle = useAnimatedStyle(() => {
27
- const labelFontSize = interpolate(labelAnimationValue.value, [0, 1], [fontSize + (boxStyle === 'inbox' ? 1 : 0), boxStyle === 'inbox' ? 10 : 11], 'clamp');
39
+ const labelFontSize = interpolate(labelAnimationValue.value, [0, 1], [animationConstants.baseFontSize, animationConstants.targetFontSize], 'clamp');
28
40
  const labelTop = interpolate(labelAnimationValue.value, [0, 1], [
29
- isTextArea ? 12 : 0,
30
- isTextArea ? -12 : -(boxHeightValue.value / 2) - 1 + (boxStyle === 'inbox' ? 17 : 2),
41
+ animationConstants.baseTop,
42
+ isTextArea ? -12 : -(boxHeightValue.value / 2) - 1 + animationConstants.targetTopOffset,
31
43
  ], 'clamp');
32
44
  return {
33
45
  top: labelTop,
34
46
  fontSize: labelFontSize,
35
47
  };
36
- });
48
+ }, [animationConstants.baseFontSize, animationConstants.targetFontSize, animationConstants.baseTop, animationConstants.targetTopOffset, isTextArea]);
37
49
  // 레이아웃 핸들러
38
50
  const handleLayout = useCallback((event) => {
39
51
  const { height } = event.nativeEvent.layout;
@@ -43,25 +55,74 @@ function ZSTextField({ typo = 'body.2', status = 'default', value, onChangeText,
43
55
  // 포커스 및 블러 핸들러
44
56
  const handleFocus = useCallback(() => setIsFocused(true), []);
45
57
  const handleBlur = useCallback(() => setIsFocused(false), []);
58
+ const colorConfig = useMemo(() => ({
59
+ primaryColor: focusColor || palette.primary.main,
60
+ defaultBorderColor: borderColor || palette.grey[30],
61
+ defaultLabelColor: labelColor || palette.text.secondary,
62
+ placeholderColor: placeHolderColor || palette.grey[40],
63
+ }), [focusColor, palette.primary.main, borderColor, palette.grey, labelColor, palette.text.secondary, placeHolderColor]);
46
64
  // 상태에 따른 테두리 색상 설정
47
- const computedBorderColor = useMemo(() => (status === 'error' ? fErrorColor : isFocused ? (focusColor || palette.primary.main) : (borderColor || palette.grey[30])), [status, fErrorColor, isFocused, focusColor, borderColor, palette]);
48
- // 상태에 따른 라벨 색상 설정
49
- const computedLabelColor = useMemo(() => (status === 'error' ? fErrorColor : isFocused ? (focusColor || palette.primary.main) : value ? (labelColor || palette.text.secondary) : (placeHolderColor || palette.grey[40])), [status, fErrorColor, isFocused, focusColor, value, placeHolderColor, labelColor, palette]);
65
+ const computedBorderColor = useMemo(() => {
66
+ if (status === 'error')
67
+ return fErrorColor;
68
+ if (isFocused)
69
+ return colorConfig.primaryColor;
70
+ return colorConfig.defaultBorderColor;
71
+ }, [status, fErrorColor, isFocused, colorConfig.primaryColor, colorConfig.defaultBorderColor]);
72
+ // 상태에 따른 라벨 색상 설정
73
+ const computedLabelColor = useMemo(() => {
74
+ if (status === 'error')
75
+ return fErrorColor;
76
+ if (isFocused)
77
+ return colorConfig.primaryColor;
78
+ if (value)
79
+ return colorConfig.defaultLabelColor;
80
+ return colorConfig.placeholderColor;
81
+ }, [status, fErrorColor, isFocused, value, colorConfig.primaryColor, colorConfig.defaultLabelColor, colorConfig.placeholderColor]);
82
+ const styleConfig = useMemo(() => {
83
+ const baseStyle = {
84
+ width: '100%',
85
+ justifyContent: isTextArea ? 'flex-start' : 'center',
86
+ borderRadius,
87
+ paddingHorizontal,
88
+ backgroundColor: inputBgColor || palette.background.base,
89
+ paddingTop: boxStyle === 'inbox' ? 13 : 0,
90
+ };
91
+ // 박스 스타일에 따른 테두리 설정
92
+ let borderStyle = {};
93
+ if (boxStyle === 'outline' || boxStyle === 'inbox') {
94
+ borderStyle = { borderWidth };
95
+ }
96
+ else if (boxStyle === 'underline') {
97
+ borderStyle = { borderBottomWidth: borderWidth };
98
+ }
99
+ // innerBoxStyle에 따른 스타일 설정
100
+ let innerStyle = {};
101
+ if (innerBoxStyle === 'top') {
102
+ innerStyle = {
103
+ borderBottomLeftRadius: 0,
104
+ borderBottomRightRadius: 0,
105
+ borderBottomWidth: borderWidth / 2
106
+ };
107
+ }
108
+ else if (innerBoxStyle === 'middle') {
109
+ innerStyle = {
110
+ borderRadius: 0,
111
+ borderTopWidth: borderWidth / 2,
112
+ borderBottomWidth: borderWidth / 2
113
+ };
114
+ }
115
+ else if (innerBoxStyle === 'bottom') {
116
+ innerStyle = {
117
+ borderTopLeftRadius: 0,
118
+ borderTopRightRadius: 0,
119
+ borderTopWidth: borderWidth / 2
120
+ };
121
+ }
122
+ return { ...baseStyle, ...borderStyle, ...innerStyle };
123
+ }, [isTextArea, borderRadius, paddingHorizontal, inputBgColor, borderWidth, boxStyle, innerBoxStyle, palette.background.base]);
50
124
  // 컨테이너 스타일 정의
51
- const containerStyle = useMemo(() => ({
52
- width: '100%',
53
- justifyContent: isTextArea ? 'flex-start' : 'center',
54
- borderRadius,
55
- paddingHorizontal,
56
- backgroundColor: inputBgColor || palette.background.base,
57
- paddingTop: boxStyle === 'inbox' ? 13 : 0,
58
- ...(boxStyle === 'outline' || boxStyle === 'inbox' ? { borderWidth } : {}),
59
- ...(boxStyle === 'underline' ? { borderBottomWidth: borderWidth } : {}),
60
- ...(innerBoxStyle === 'top' ? { borderBottomLeftRadius: 0, borderBottomRightRadius: 0, borderBottomWidth: borderWidth / 2 }
61
- : innerBoxStyle === 'middle' ? { borderRadius: 0, borderTopWidth: borderWidth / 2, borderBottomWidth: borderWidth / 2 }
62
- : innerBoxStyle === 'bottom' ? { borderTopLeftRadius: 0, borderTopRightRadius: 0, borderTopWidth: borderWidth / 2 }
63
- : {}),
64
- }), [isTextArea, borderRadius, paddingHorizontal, inputBgColor, borderWidth, boxStyle, innerBoxStyle, palette]);
125
+ const containerStyle = styleConfig;
65
126
  // 라벨 스타일 정의
66
127
  const labelTextStyle = useMemo(() => ({
67
128
  fontSize,
@@ -73,19 +134,29 @@ function ZSTextField({ typo = 'body.2', status = 'default', value, onChangeText,
73
134
  fontFamily,
74
135
  borderRadius: boxStyle === 'outline' ? 5 : 0,
75
136
  overflow: 'hidden',
76
- }), [fontSize, paddingHorizontal, labelBgColor, boxStyle, fontFamily, palette]);
137
+ }), [fontSize, paddingHorizontal, labelBgColor, boxStyle, fontFamily, palette.background.base]);
77
138
  // 텍스트 변경 핸들러
78
139
  const handleTextChange = useCallback((text) => {
79
140
  if (onChangeText)
80
141
  onChangeText(text);
81
142
  }, [onChangeText]);
143
+ const textInputStyle = useMemo(() => [
144
+ {
145
+ paddingTop: 7 + iosOffset,
146
+ paddingBottom: 5 + iosOffset,
147
+ color: palette.text.base,
148
+ fontSize,
149
+ width: '100%',
150
+ paddingRight: 25,
151
+ fontFamily
152
+ },
153
+ textInputProps?.style,
154
+ ], [palette.text.base, fontSize, fontFamily, textInputProps?.style]);
155
+ const shouldShowCloseButton = value && isFocused;
156
+ const shouldShowError = status === 'error' && errorMessage;
82
157
  return (<ViewAtom style={{ alignSelf: 'stretch', width: '100%' }}>
83
158
  <ViewAtom style={[containerStyle, { borderColor: computedBorderColor }]} onLayout={handleLayout} pointerEvents={disabled ? 'none' : 'auto'}>
84
- <TextInput {...textInputProps} style={[
85
- { paddingTop: 7 + iosOffset, paddingBottom: 5 + iosOffset, color: palette.text.base },
86
- textInputProps?.style,
87
- { fontSize, width: '100%', paddingRight: 25, fontFamily },
88
- ]} value={value} onFocus={handleFocus} onBlur={handleBlur} onChangeText={handleTextChange} allowFontScaling={allowFontScaling} selectionColor={palette.grey[50]} autoCorrect={false} spellCheck={false}/>
159
+ <TextInput {...textInputProps} style={textInputStyle} value={value} onFocus={handleFocus} onBlur={handleBlur} onChangeText={handleTextChange} allowFontScaling={allowFontScaling} selectionColor={palette.grey[50]} autoCorrect={false} spellCheck={false}/>
89
160
 
90
161
  <ViewAtom pointerEvents="none" style={{ position: 'absolute' }}>
91
162
  <Animated.Text allowFontScaling={allowFontScaling} style={[animatedLabelStyle, labelTextStyle, { color: computedLabelColor }]}>
@@ -93,11 +164,26 @@ function ZSTextField({ typo = 'body.2', status = 'default', value, onChangeText,
93
164
  </Animated.Text>
94
165
  </ViewAtom>
95
166
 
96
- {(value && isFocused) && (<ButtonClose marginTop={isTextArea ? 13 : undefined} onChangeText={onChangeText}/>)}
167
+ {shouldShowCloseButton && (<ButtonClose marginTop={isTextArea ? 13 : undefined} onChangeText={onChangeText}/>)}
97
168
  </ViewAtom>
98
169
 
99
- {status === 'error' && errorMessage && (<ErrorComponent errorMessage={errorMessage} errorColor={fErrorColor}/>)}
170
+ {shouldShowError && (<ErrorComponent errorMessage={errorMessage} errorColor={fErrorColor}/>)}
100
171
  </ViewAtom>);
101
172
  }
102
- export default React.memo(ZSTextField);
173
+ const arePropsEqual = (prevProps, nextProps) => {
174
+ return (prevProps.value === nextProps.value &&
175
+ prevProps.status === nextProps.status &&
176
+ prevProps.disabled === nextProps.disabled &&
177
+ prevProps.errorMessage === nextProps.errorMessage &&
178
+ prevProps.typo === nextProps.typo &&
179
+ prevProps.boxStyle === nextProps.boxStyle &&
180
+ prevProps.innerBoxStyle === nextProps.innerBoxStyle &&
181
+ prevProps.isTextArea === nextProps.isTextArea &&
182
+ prevProps.label === nextProps.label &&
183
+ prevProps.focusColor === nextProps.focusColor &&
184
+ prevProps.borderColor === nextProps.borderColor &&
185
+ prevProps.labelColor === nextProps.labelColor &&
186
+ prevProps.onChangeText === nextProps.onChangeText);
187
+ };
188
+ export default React.memo(ZSTextField, arePropsEqual);
103
189
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui/ZSTextField/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useMemo, useCallback, useState, useEffect } from 'react';\nimport { LayoutChangeEvent, Platform, StyleProp, TextInput, TextInputProps, TextStyle, ViewStyle } from 'react-native';\nimport Animated, { interpolate, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';\nimport ButtonClose from './ui/ButtonClose';\nimport ErrorComponent from './ui/ErrorComponent';\nimport { TypoOptions, TypoStyle, TypoSubStyle } from '../../theme';\nimport { extractStyle } from '../../model/utils';\nimport { useTheme } from '../../model/useThemeProvider';\nimport ViewAtom from '../atoms/ViewAtom';\n\nexport type BoxStyle = 'outline' | 'underline' | 'inbox';\n\nconst iosOffset = Platform.OS === 'ios' ? 8 : 4;\n\ninterface TextFieldProps {\n typo?: TypoOptions;\n status?: 'default' | 'error';\n value: string;\n onChangeText?: (text: string) => void;\n inputBgColor?: string;\n labelBgColor?: string;\n label?: string;\n labelColor?: string;\n placeHolderColor?: string;\n fontSize?: number;\n borderColor?: string;\n borderRadius?: number;\n focusColor?: string;\n errorColor?: string;\n paddingHorizontal?: number;\n borderWidth?: number;\n errorMessage?: string;\n textInputProps?: TextInputProps;\n boxStyle?: BoxStyle;\n innerBoxStyle?: 'top' | 'middle' | 'bottom';\n disabled?: boolean;\n allowFontScaling?: boolean;\n isTextArea?: boolean;\n}\n\nfunction ZSTextField({\n typo = 'body.2',\n status = 'default',\n value,\n onChangeText,\n label = 'Placeholder',\n labelColor,\n placeHolderColor,\n inputBgColor,\n labelBgColor,\n borderWidth = 1.2,\n borderColor,\n focusColor,\n errorColor,\n borderRadius = 14,\n paddingHorizontal = 15,\n errorMessage,\n textInputProps,\n boxStyle = 'outline',\n innerBoxStyle,\n disabled = false,\n allowFontScaling = true,\n isTextArea = false,\n}: TextFieldProps): JSX.Element {\n const { typography, palette } = useTheme();\n const [primaryStyle, subStyle] = typo.split('.') as [TypoStyle, TypoSubStyle];\n let fErrorColor = errorColor || palette.danger.main;\n\n // 폰트 크기 및 패밀리 추출\n const fontSize = useMemo(() => extractStyle(typography[primaryStyle][subStyle], 'fontSize') as number || 17, [typography, primaryStyle, subStyle]);\n const fontFamily = useMemo(() => extractStyle(typography[primaryStyle][subStyle], 'fontFamily') as string || '', [typography, primaryStyle, subStyle]);\n\n // 컴포넌트 상태 관리\n const [isFocused, setIsFocused] = useState<boolean>(false);\n const labelAnimationValue = useSharedValue(0);\n const boxHeightValue = useSharedValue(0);\n\n // 포커스 및 값 변경 시 라벨 애니메이션 트리거\n useEffect(() => {\n labelAnimationValue.value = withTiming(\n value !== '' || isFocused ? 1 : 0,\n { duration: 150 }\n );\n }, [value, isFocused]);\n\n // 라벨 애니메이션 스타일\n const animatedLabelStyle = useAnimatedStyle(() => {\n const labelFontSize = interpolate(\n labelAnimationValue.value,\n [0, 1],\n [fontSize + (boxStyle === 'inbox' ? 1 : 0), boxStyle === 'inbox' ? 10 : 11],\n 'clamp'\n );\n\n const labelTop = interpolate(\n labelAnimationValue.value,\n [0, 1],\n [\n isTextArea ? 12 : 0,\n isTextArea ? -12 : -(boxHeightValue.value / 2) - 1 + (boxStyle === 'inbox' ? 17 : 2),\n ],\n 'clamp'\n );\n\n return {\n top: labelTop,\n fontSize: labelFontSize,\n };\n });\n\n // 레이아웃 핸들러\n const handleLayout = useCallback((event: LayoutChangeEvent) => {\n const { height } = event.nativeEvent.layout;\n if (boxHeightValue.value !== height) boxHeightValue.value = height;\n }, [boxHeightValue]);\n\n // 포커스 및 블러 핸들러\n const handleFocus = useCallback(() => setIsFocused(true), []);\n const handleBlur = useCallback(() => setIsFocused(false), []);\n\n // 상태에 따른 테두리 색상 설정\n const computedBorderColor = useMemo(() => (\n status === 'error' ? fErrorColor : isFocused ? (focusColor || palette.primary.main) : (borderColor || palette.grey[30])\n ), [status, fErrorColor, isFocused, focusColor, borderColor, palette]);\n\n // 상태에 따른 라벨 색상 설정\n const computedLabelColor = useMemo(() => (\n status === 'error' ? fErrorColor : isFocused ? (focusColor || palette.primary.main) : value ? (labelColor || palette.text.secondary) : (placeHolderColor || palette.grey[40])\n ), [status, fErrorColor, isFocused, focusColor, value, placeHolderColor, labelColor, palette]);\n\n // 컨테이너 스타일 정의\n const containerStyle: StyleProp<ViewStyle> = useMemo(() => ({\n width: '100%',\n justifyContent: isTextArea ? 'flex-start' : 'center',\n borderRadius,\n paddingHorizontal,\n backgroundColor: inputBgColor || palette.background.base,\n paddingTop: boxStyle === 'inbox' ? 13 : 0,\n ...(boxStyle === 'outline' || boxStyle === 'inbox' ? { borderWidth } : {}),\n ...(boxStyle === 'underline' ? { borderBottomWidth: borderWidth } : {}),\n ...(innerBoxStyle === 'top' ? { borderBottomLeftRadius: 0, borderBottomRightRadius: 0, borderBottomWidth: borderWidth / 2 }\n : innerBoxStyle === 'middle' ? { borderRadius: 0, borderTopWidth: borderWidth / 2, borderBottomWidth: borderWidth / 2 }\n : innerBoxStyle === 'bottom' ? { borderTopLeftRadius: 0, borderTopRightRadius: 0, borderTopWidth: borderWidth / 2 }\n : {}),\n }), [isTextArea, borderRadius, paddingHorizontal, inputBgColor, borderWidth, boxStyle, innerBoxStyle, palette]);\n\n // 라벨 스타일 정의\n const labelTextStyle: StyleProp<TextStyle> = useMemo(() => ({\n fontSize,\n left: paddingHorizontal,\n backgroundColor: labelBgColor || palette.background.base,\n paddingHorizontal: boxStyle === 'outline' ? 5 : 0,\n paddingVertical: 2,\n textAlignVertical: 'center',\n fontFamily,\n borderRadius: boxStyle === 'outline' ? 5 : 0,\n overflow: 'hidden',\n }), [fontSize, paddingHorizontal, labelBgColor, boxStyle, fontFamily, palette]);\n\n // 텍스트 변경 핸들러\n const handleTextChange = useCallback((text: string) => {\n if (onChangeText) onChangeText(text);\n }, [onChangeText]);\n\n return (\n <ViewAtom style={{ alignSelf: 'stretch', width: '100%' }}>\n <ViewAtom\n style={[containerStyle, { borderColor: computedBorderColor }]}\n onLayout={handleLayout}\n pointerEvents={disabled ? 'none' : 'auto'}\n >\n <TextInput\n {...textInputProps}\n style={[\n { paddingTop: 7 + iosOffset, paddingBottom: 5 + iosOffset, color: palette.text.base },\n textInputProps?.style,\n { fontSize, width: '100%', paddingRight: 25, fontFamily },\n ]}\n value={value}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChangeText={handleTextChange}\n allowFontScaling={allowFontScaling}\n selectionColor={palette.grey[50]}\n autoCorrect={false}\n spellCheck={false}\n />\n\n <ViewAtom pointerEvents=\"none\" style={{ position: 'absolute' }}>\n <Animated.Text allowFontScaling={allowFontScaling} style={[animatedLabelStyle, labelTextStyle, { color: computedLabelColor }]}>\n {label}\n </Animated.Text>\n </ViewAtom>\n\n {(value && isFocused) && (\n <ButtonClose marginTop={isTextArea ? 13 : undefined} onChangeText={onChangeText} />\n )}\n </ViewAtom>\n\n {status === 'error' && errorMessage && (\n <ErrorComponent errorMessage={errorMessage} errorColor={fErrorColor} />\n )}\n </ViewAtom>\n );\n}\n\nexport default React.memo(ZSTextField);\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui/ZSTextField/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useMemo, useCallback, useState, useEffect, useRef } from 'react';\nimport { LayoutChangeEvent, Platform, StyleProp, TextInput, TextInputProps, TextStyle, ViewStyle } from 'react-native';\nimport Animated, { interpolate, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';\nimport ButtonClose from './ui/ButtonClose';\nimport ErrorComponent from './ui/ErrorComponent';\nimport { TypoOptions, TypoStyle, TypoSubStyle } from '../../theme';\nimport { extractStyle } from '../../model/utils';\nimport { useTheme } from '../../model/useThemeProvider';\nimport ViewAtom from '../atoms/ViewAtom';\n\nexport type BoxStyle = 'outline' | 'underline' | 'inbox';\n\nconst iosOffset = Platform.OS === 'ios' ? 8 : 4;\n\ninterface TextFieldProps {\n typo?: TypoOptions;\n status?: 'default' | 'error';\n value: string;\n onChangeText?: (text: string) => void;\n inputBgColor?: string;\n labelBgColor?: string;\n label?: string;\n labelColor?: string;\n placeHolderColor?: string;\n fontSize?: number;\n borderColor?: string;\n borderRadius?: number;\n focusColor?: string;\n errorColor?: string;\n paddingHorizontal?: number;\n borderWidth?: number;\n errorMessage?: string;\n textInputProps?: TextInputProps;\n boxStyle?: BoxStyle;\n innerBoxStyle?: 'top' | 'middle' | 'bottom';\n disabled?: boolean;\n allowFontScaling?: boolean;\n isTextArea?: boolean;\n}\n\nfunction ZSTextField({\n typo = 'body.2',\n status = 'default',\n value,\n onChangeText,\n label = 'Placeholder',\n labelColor,\n placeHolderColor,\n inputBgColor,\n labelBgColor,\n borderWidth = 1.2,\n borderColor,\n focusColor,\n errorColor,\n borderRadius = 14,\n paddingHorizontal = 15,\n errorMessage,\n textInputProps,\n boxStyle = 'outline',\n innerBoxStyle,\n disabled = false,\n allowFontScaling = true,\n isTextArea = false,\n}: TextFieldProps): JSX.Element {\n const { typography, palette } = useTheme();\n \n const typoConfig = useMemo(() => {\n const [primaryStyle, subStyle] = typo.split('.') as [TypoStyle, TypoSubStyle];\n return { primaryStyle, subStyle };\n }, [typo]);\n \n const fErrorColor = useMemo(() => errorColor || palette.danger.main, [errorColor, palette.danger.main]);\n\n const fontSize = useMemo(() => {\n return extractStyle(typography[typoConfig.primaryStyle][typoConfig.subStyle], 'fontSize') as number || 17;\n }, [typography, typoConfig.primaryStyle, typoConfig.subStyle]);\n \n const fontFamily = useMemo(() => {\n return extractStyle(typography[typoConfig.primaryStyle][typoConfig.subStyle], 'fontFamily') as string || '';\n }, [typography, typoConfig.primaryStyle, typoConfig.subStyle]);\n\n const [isFocused, setIsFocused] = useState<boolean>(false);\n \n const labelAnimationValue = useRef(useSharedValue(0)).current;\n const boxHeightValue = useRef(useSharedValue(0)).current;\n\n // 포커스 및 값 변경 시 라벨 애니메이션 트리거\n useEffect(() => {\n labelAnimationValue.value = withTiming(\n value !== '' || isFocused ? 1 : 0,\n { duration: 100 }\n );\n }, [value, isFocused, labelAnimationValue]);\n\n // 애니메이션 관련 상수\n const animationConstants = useMemo(() => ({\n baseFontSize: fontSize + (boxStyle === 'inbox' ? 1 : 0),\n targetFontSize: boxStyle === 'inbox' ? 10 : 11,\n baseTop: isTextArea ? 12 : 0,\n targetTopOffset: boxStyle === 'inbox' ? 17 : 2,\n }), [fontSize, boxStyle, isTextArea]);\n\n // 라벨 애니메이션 스타일\n const animatedLabelStyle = useAnimatedStyle(() => {\n const labelFontSize = interpolate(\n labelAnimationValue.value,\n [0, 1],\n [animationConstants.baseFontSize, animationConstants.targetFontSize],\n 'clamp'\n );\n\n const labelTop = interpolate(\n labelAnimationValue.value,\n [0, 1],\n [\n animationConstants.baseTop,\n isTextArea ? -12 : -(boxHeightValue.value / 2) - 1 + animationConstants.targetTopOffset,\n ],\n 'clamp'\n );\n\n return {\n top: labelTop,\n fontSize: labelFontSize,\n };\n }, [animationConstants.baseFontSize, animationConstants.targetFontSize, animationConstants.baseTop, animationConstants.targetTopOffset, isTextArea]);\n\n // 레이아웃 핸들러\n const handleLayout = useCallback((event: LayoutChangeEvent) => {\n const { height } = event.nativeEvent.layout;\n if (boxHeightValue.value !== height) boxHeightValue.value = height;\n }, [boxHeightValue]);\n\n // 포커스 및 블러 핸들러\n const handleFocus = useCallback(() => setIsFocused(true), []);\n const handleBlur = useCallback(() => setIsFocused(false), []);\n\n const colorConfig = useMemo(() => ({\n primaryColor: focusColor || palette.primary.main,\n defaultBorderColor: borderColor || palette.grey[30],\n defaultLabelColor: labelColor || palette.text.secondary,\n placeholderColor: placeHolderColor || palette.grey[40],\n }), [focusColor, palette.primary.main, borderColor, palette.grey, labelColor, palette.text.secondary, placeHolderColor]);\n\n // 상태에 따른 테두리 색상 설정\n const computedBorderColor = useMemo(() => {\n if (status === 'error') return fErrorColor;\n if (isFocused) return colorConfig.primaryColor;\n return colorConfig.defaultBorderColor;\n }, [status, fErrorColor, isFocused, colorConfig.primaryColor, colorConfig.defaultBorderColor]);\n\n // 상태에 따른 라벨 색상 설정 \n const computedLabelColor = useMemo(() => {\n if (status === 'error') return fErrorColor;\n if (isFocused) return colorConfig.primaryColor;\n if (value) return colorConfig.defaultLabelColor;\n return colorConfig.placeholderColor;\n }, [status, fErrorColor, isFocused, value, colorConfig.primaryColor, colorConfig.defaultLabelColor, colorConfig.placeholderColor]);\n\n const styleConfig = useMemo(() => {\n const baseStyle = {\n width: '100%' as const,\n justifyContent: isTextArea ? 'flex-start' as const : 'center' as const,\n borderRadius,\n paddingHorizontal,\n backgroundColor: inputBgColor || palette.background.base,\n paddingTop: boxStyle === 'inbox' ? 13 : 0,\n };\n\n // 박스 스타일에 따른 테두리 설정\n let borderStyle = {};\n if (boxStyle === 'outline' || boxStyle === 'inbox') {\n borderStyle = { borderWidth };\n } else if (boxStyle === 'underline') {\n borderStyle = { borderBottomWidth: borderWidth };\n }\n\n // innerBoxStyle에 따른 스타일 설정\n let innerStyle = {};\n if (innerBoxStyle === 'top') {\n innerStyle = { \n borderBottomLeftRadius: 0, \n borderBottomRightRadius: 0, \n borderBottomWidth: borderWidth / 2 \n };\n } else if (innerBoxStyle === 'middle') {\n innerStyle = { \n borderRadius: 0, \n borderTopWidth: borderWidth / 2, \n borderBottomWidth: borderWidth / 2 \n };\n } else if (innerBoxStyle === 'bottom') {\n innerStyle = { \n borderTopLeftRadius: 0, \n borderTopRightRadius: 0, \n borderTopWidth: borderWidth / 2 \n };\n }\n\n return { ...baseStyle, ...borderStyle, ...innerStyle };\n }, [isTextArea, borderRadius, paddingHorizontal, inputBgColor, borderWidth, boxStyle, innerBoxStyle, palette.background.base]);\n\n // 컨테이너 스타일 정의\n const containerStyle: StyleProp<ViewStyle> = styleConfig;\n\n // 라벨 스타일 정의\n const labelTextStyle: StyleProp<TextStyle> = useMemo(() => ({\n fontSize,\n left: paddingHorizontal,\n backgroundColor: labelBgColor || palette.background.base,\n paddingHorizontal: boxStyle === 'outline' ? 5 : 0,\n paddingVertical: 2,\n textAlignVertical: 'center',\n fontFamily,\n borderRadius: boxStyle === 'outline' ? 5 : 0,\n overflow: 'hidden',\n }), [fontSize, paddingHorizontal, labelBgColor, boxStyle, fontFamily, palette.background.base]);\n\n // 텍스트 변경 핸들러\n const handleTextChange = useCallback((text: string) => {\n if (onChangeText) onChangeText(text);\n }, [onChangeText]);\n\n const textInputStyle = useMemo(() => [\n { \n paddingTop: 7 + iosOffset, \n paddingBottom: 5 + iosOffset, \n color: palette.text.base,\n fontSize, \n width: '100%' as const, \n paddingRight: 25, \n fontFamily \n },\n textInputProps?.style,\n ], [palette.text.base, fontSize, fontFamily, textInputProps?.style]);\n\n const shouldShowCloseButton = value && isFocused;\n const shouldShowError = status === 'error' && errorMessage;\n\n return (\n <ViewAtom style={{ alignSelf: 'stretch', width: '100%' }}>\n <ViewAtom\n style={[containerStyle, { borderColor: computedBorderColor }]}\n onLayout={handleLayout}\n pointerEvents={disabled ? 'none' : 'auto'}\n >\n <TextInput\n {...textInputProps}\n style={textInputStyle}\n value={value}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChangeText={handleTextChange}\n allowFontScaling={allowFontScaling}\n selectionColor={palette.grey[50]}\n autoCorrect={false}\n spellCheck={false}\n />\n\n <ViewAtom pointerEvents=\"none\" style={{ position: 'absolute' }}>\n <Animated.Text allowFontScaling={allowFontScaling} style={[animatedLabelStyle, labelTextStyle, { color: computedLabelColor }]}>\n {label}\n </Animated.Text>\n </ViewAtom>\n\n {shouldShowCloseButton && (\n <ButtonClose marginTop={isTextArea ? 13 : undefined} onChangeText={onChangeText} />\n )}\n </ViewAtom>\n\n {shouldShowError && (\n <ErrorComponent errorMessage={errorMessage} errorColor={fErrorColor} />\n )}\n </ViewAtom>\n );\n}\n\nconst arePropsEqual = (prevProps: TextFieldProps, nextProps: TextFieldProps): boolean => {\n return (\n prevProps.value === nextProps.value &&\n prevProps.status === nextProps.status &&\n prevProps.disabled === nextProps.disabled &&\n prevProps.errorMessage === nextProps.errorMessage &&\n prevProps.typo === nextProps.typo &&\n prevProps.boxStyle === nextProps.boxStyle &&\n prevProps.innerBoxStyle === nextProps.innerBoxStyle &&\n prevProps.isTextArea === nextProps.isTextArea &&\n prevProps.label === nextProps.label &&\n prevProps.focusColor === nextProps.focusColor &&\n prevProps.borderColor === nextProps.borderColor &&\n prevProps.labelColor === nextProps.labelColor &&\n prevProps.onChangeText === nextProps.onChangeText\n );\n};\n\nexport default React.memo(ZSTextField, arePropsEqual);\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AnimatedWrapper.d.ts","sourceRoot":"","sources":["../../../src/ui/atoms/AnimatedWrapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,EAAQ,SAAS,EAAY,MAAM,cAAc,CAAC;AAGzD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,OAAO,EAA8B,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAKjF,UAAU,oBAAqB,SAAQ,SAAS;IAC9C,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B;AAED,iBAAS,eAAe,CAAC,EACvB,WAAkB,EAClB,cAAkB,EAClB,QAA2B,EAC3B,KAAK,EACL,QAAQ,EACR,KAAK,EACL,GAAG,KAAK,EACT,EAAE,oBAAoB,qBAgDtB;;AAED,wBAA2C"}
1
+ {"version":3,"file":"AnimatedWrapper.d.ts","sourceRoot":"","sources":["../../../src/ui/atoms/AnimatedWrapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAQ,SAAS,EAAY,MAAM,cAAc,CAAC;AAGzD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,OAAO,EAA8B,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAMjF,UAAU,oBAAqB,SAAQ,SAAS;IAC9C,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B;AAED,iBAAS,eAAe,CAAC,EACvB,WAAkB,EAClB,cAAkB,EAClB,QAA2B,EAC3B,KAAK,EACL,QAAQ,EACR,KAAK,EACL,GAAG,KAAK,EACT,EAAE,oBAAoB,qBAkFtB;;AAgBD,wBAA0D"}
@@ -1,27 +1,51 @@
1
- import React, { useMemo, useCallback } from 'react';
1
+ import React, { useMemo, useCallback, useRef } from 'react';
2
2
  import { View, Platform } from 'react-native';
3
3
  import Animated, { FadeInDown, FadeOut, useAnimatedStyle, withTiming, useSharedValue, runOnJS } from 'react-native-reanimated';
4
4
  import { useTheme } from '../../model/useThemeProvider';
5
5
  import { IOS_SHADOW } from '../../theme/elevation';
6
6
  const DEFAULT_DURATION = 200;
7
7
  const SHADOW_DURATION = 50;
8
+ const IS_IOS = Platform.OS === 'ios';
8
9
  function AnimatedWrapper({ isAnimation = true, elevationLevel = 0, duration = DEFAULT_DURATION, style, children, color, ...props }) {
9
10
  const { elevation, palette } = useTheme();
10
- const opacity = useSharedValue(0);
11
- const [c01, c02] = color ? color.split('.') : [undefined, undefined];
12
- const backgroundColor = c02 ? palette[c01][c02] : c01 ? palette.background[c01] : elevationLevel ? palette.background.base : undefined;
13
- // 그림자 기타 스타일을 플랫폼에 맞게 미리 계산
11
+ const opacity = useRef(useSharedValue(0)).current;
12
+ const colorConfig = useMemo(() => {
13
+ if (!color)
14
+ return { c01: undefined, c02: undefined };
15
+ const [c01, c02] = color.split('.');
16
+ return { c01, c02 };
17
+ }, [color]);
18
+ const backgroundColor = useMemo(() => {
19
+ const { c01, c02 } = colorConfig;
20
+ if (c02)
21
+ return palette[c01][c02];
22
+ if (c01)
23
+ return palette.background[c01];
24
+ if (elevationLevel)
25
+ return palette.background.base;
26
+ return undefined;
27
+ }, [colorConfig, palette, elevationLevel]);
14
28
  const staticStyle = useMemo(() => {
15
29
  return { ...elevation[elevationLevel] };
16
- }, [elevation]);
17
- // 애니메이션 스타일 정의 (iOS 그림자 및 Android elevation 처리)
18
- const animatedStyle = useAnimatedStyle(() => {
19
- if (Platform.OS === 'ios') {
20
- return { shadowOpacity: opacity.value * IOS_SHADOW[elevationLevel].shadowOpacity };
30
+ }, [elevation, elevationLevel]);
31
+ const animationConfig = useMemo(() => {
32
+ if (IS_IOS) {
33
+ return {
34
+ type: 'ios',
35
+ maxShadowOpacity: IOS_SHADOW[elevationLevel].shadowOpacity,
36
+ };
21
37
  }
22
- return { elevation: opacity.value * elevationLevel };
38
+ return {
39
+ type: 'android',
40
+ maxElevation: elevationLevel,
41
+ };
23
42
  }, [elevationLevel]);
24
- // 컴포넌트가 등장할 애니메이션 핸들링
43
+ const animatedStyle = useAnimatedStyle(() => {
44
+ if (animationConfig.type === 'ios') {
45
+ return { shadowOpacity: opacity.value * animationConfig.maxShadowOpacity };
46
+ }
47
+ return { elevation: opacity.value * animationConfig.maxElevation };
48
+ }, [animationConfig]);
25
49
  const onEntering = useCallback(() => {
26
50
  opacity.value = withTiming(1, { duration: SHADOW_DURATION });
27
51
  }, [opacity]);
@@ -34,13 +58,31 @@ function AnimatedWrapper({ isAnimation = true, elevationLevel = 0, duration = DE
34
58
  }),
35
59
  exiting: FadeOut.duration(50),
36
60
  }), [duration, onEntering]);
37
- // 애니메이션이 비활성화된 경우 기본 View로 렌더링
61
+ const nonAnimatedStyle = useMemo(() => [
62
+ style,
63
+ backgroundColor && { backgroundColor },
64
+ { ...elevation[elevationLevel] }
65
+ ], [style, backgroundColor, elevation, elevationLevel]);
66
+ const animatedStyleArray = useMemo(() => [
67
+ style,
68
+ backgroundColor && { backgroundColor },
69
+ staticStyle,
70
+ animatedStyle
71
+ ], [style, backgroundColor, staticStyle, animatedStyle]);
38
72
  if (!isAnimation) {
39
- return <View style={[style, backgroundColor && { backgroundColor }, { ...elevation[elevationLevel] }]} {...props}>{children}</View>;
73
+ return <View style={nonAnimatedStyle} {...props}>{children}</View>;
40
74
  }
41
- return (<Animated.View style={[style, backgroundColor && { backgroundColor }, staticStyle, animatedStyle]} {...animationProps} {...props}>
75
+ return (<Animated.View style={animatedStyleArray} {...animationProps} {...props}>
42
76
  {children}
43
77
  </Animated.View>);
44
78
  }
45
- export default React.memo(AnimatedWrapper);
79
+ const arePropsEqual = (prevProps, nextProps) => {
80
+ return (prevProps.isAnimation === nextProps.isAnimation &&
81
+ prevProps.elevationLevel === nextProps.elevationLevel &&
82
+ prevProps.duration === nextProps.duration &&
83
+ prevProps.color === nextProps.color &&
84
+ prevProps.style === nextProps.style &&
85
+ prevProps.children === nextProps.children);
86
+ };
87
+ export default React.memo(AnimatedWrapper, arePropsEqual);
46
88
  //# sourceMappingURL=AnimatedWrapper.js.map