@@ -27,35 +27,38 @@ import {
2727 StyleSheet ,
2828 useWindowDimensions ,
2929} from 'react-native' ;
30- import {
31- Provider as JotaiProvider ,
32- useAtom ,
33- useAtomValue ,
34- useSetAtom ,
35- } from 'jotai/react' ;
36- import { selectAtom } from 'jotai/utils' ;
3730import { Platform } from 'react-native' ;
3831
39- import { elementsAtom , inputsAtom , wrapperOffsetAtom } from './state' ;
4032import { useKeyboard } from './useKeyboard' ;
4133import { useSafeAreaInsets } from 'react-native-safe-area-context' ;
4234
35+ export type RefType = TextInput | View | Animated . View | null ;
36+
37+ export type Elements = Record <
38+ string ,
39+ {
40+ isFocus : boolean ;
41+ position : number ;
42+ height : number ;
43+ name : string ;
44+ }
45+ > ;
46+
47+ export type InputType = Record < string , RefObject < TextInput > > ;
48+
4349const isAndroid = Platform . OS === 'android' ;
4450
4551function Wrapper ( props : PropsWithChildren < { } > ) {
46- const setWrapperOffsetAtom = useSetAtom ( wrapperOffsetAtom ) ;
4752 const windowDimensions = useWindowDimensions ( ) ;
48- const { wrapperRef } = useSmartScrollContext ( ) ;
53+ const { wrapperRef, setWrapperOffset } = useSmartScrollContext ( ) ;
4954
5055 return (
5156 < View
5257 style = { styles . wrapper }
5358 ref = { wrapperRef }
5459 onLayout = { ( { nativeEvent } ) => {
5560 if ( nativeEvent . layout . height < windowDimensions . height ) {
56- setWrapperOffsetAtom (
57- windowDimensions . height - nativeEvent . layout . height
58- ) ;
61+ setWrapperOffset ( windowDimensions . height - nativeEvent . layout . height ) ;
5962 }
6063 } }
6164 >
@@ -72,11 +75,9 @@ const styles = StyleSheet.create({
7275
7376export default function SmartScrollView ( props : PropsWithChildren < { } > ) {
7477 return (
75- < JotaiProvider >
76- < SmartScrollProvider >
77- < Wrapper { ...props } />
78- </ SmartScrollProvider >
79- </ JotaiProvider >
78+ < SmartScrollProvider >
79+ < Wrapper { ...props } />
80+ </ SmartScrollProvider >
8081 ) ;
8182}
8283
@@ -85,14 +86,31 @@ const SmartScrollContext = React.createContext<{
8586 scrollY : SharedValue < number > ;
8687 isReady : boolean ;
8788 wrapperRef : RefObject < View > ;
89+ wrapperOffset : number ;
90+ setWrapperOffset : React . Dispatch < React . SetStateAction < number > > ;
91+ elements : Elements ;
92+ setElements : React . Dispatch < React . SetStateAction < Elements > > ;
93+ inputs : InputType ;
94+ setInputs : React . Dispatch < React . SetStateAction < InputType > > ;
95+ currentFocus ?: null | Elements [ 0 ] ;
8896} | null > ( null ) ;
8997
9098const SmartScrollProvider = ( { children } : { children : React . ReactNode } ) => {
9199 const scrollRef = useAnimatedRef < Animated . ScrollView > ( ) ;
92100 const scrollY = useSharedValue ( 0 ) ;
93101 const wrapperRef = React . useRef < View > ( null ) ;
94- const [ isReady , setIsReady ] = useState ( false ) ;
95- const currentFocus = useAtomValue ( currentFocusAtom ) ;
102+ const [ isReady , setIsReady ] = useState ( true ) ;
103+ const [ elements , setElements ] = useState < Elements > ( { } ) ;
104+ const [ wrapperOffset , setWrapperOffset ] = useState ( 0 ) ;
105+ const [ inputs , setInputs ] = useState < InputType > ( { } ) ;
106+
107+ const currentFocus = useMemo (
108+ ( ) =>
109+ Object . keys ( elements )
110+ . map ( ( key ) => elements [ key ] )
111+ . find ( ( el ) => el ?. isFocus ) ,
112+ [ elements ]
113+ ) ;
96114
97115 // we have a flick on first focus so we make the scrollview wait a bit before animate
98116 useLayoutEffect ( ( ) => {
@@ -103,7 +121,19 @@ const SmartScrollProvider = ({ children }: { children: React.ReactNode }) => {
103121
104122 return (
105123 < SmartScrollContext . Provider
106- value = { { scrollRef, scrollY, isReady, wrapperRef } }
124+ value = { {
125+ scrollRef,
126+ scrollY,
127+ isReady,
128+ wrapperRef,
129+ wrapperOffset,
130+ setWrapperOffset,
131+ elements,
132+ setElements,
133+ currentFocus,
134+ inputs,
135+ setInputs,
136+ } }
107137 >
108138 { children }
109139 </ SmartScrollContext . Provider >
@@ -114,7 +144,9 @@ export const useSmartScrollContext = () => {
114144 const context = React . useContext ( SmartScrollContext ) ;
115145
116146 if ( ! context ) {
117- throw new Error ( 'Plz wrap with SmartScrollProvider' ) ;
147+ throw new Error (
148+ 'Component must be wrapped in a SmartScrollProvider. Please ensure the provider is included.'
149+ ) ;
118150 }
119151
120152 return context ;
@@ -154,29 +186,25 @@ export const ScrollView = (
154186 ) ;
155187} ;
156188
157- const currentFocusAtom = selectAtom ( elementsAtom , ( val ) =>
158- Object . keys ( val )
159- . map ( ( key ) => val [ key ] )
160- . find ( ( el ) => el ?. isFocus )
161- ) ;
162-
163189export function useFormSmartScroll ( {
164190 padding = 0 ,
165191} : {
166192 padding ?: number ;
167193} = { } ) {
168194 const insets = useSafeAreaInsets ( ) ;
169- const wrapperOffset = useAtomValue ( wrapperOffsetAtom ) ;
170-
171- const { isReady, scrollY, scrollRef } = useSmartScrollContext ( ) ;
195+ const {
196+ currentFocus,
197+ setElements,
198+ isReady,
199+ scrollY,
200+ scrollRef,
201+ wrapperOffset,
202+ inputs,
203+ setInputs,
204+ } = useSmartScrollContext ( ) ;
172205
173206 const _keyboard = useKeyboard ( ) ;
174207
175- const setState = useSetAtom ( elementsAtom ) ;
176- const [ inputs , setInputs ] = useAtom ( inputsAtom ) ;
177-
178- const currentFocus = useAtomValue ( currentFocusAtom ) ;
179-
180208 const scrollHandler = useAnimatedScrollHandler ( ( event ) => {
181209 scrollY . value = event . contentOffset . y ;
182210 } ) ;
@@ -247,6 +275,8 @@ export function useFormSmartScroll({
247275 }
248276 ) ;
249277
278+ console . log ( { isReady } ) ;
279+
250280 const translateStyle = useAnimatedStyle ( ( ) => {
251281 return {
252282 transform : [ { translateY : isReady ? translateY . value : 0 } ] ,
@@ -278,7 +308,7 @@ export function useFormSmartScroll({
278308
279309 const onFocus = useCallback (
280310 ( name : string ) => ( ) => {
281- setState ( ( s ) => ( {
311+ setElements ( ( s ) => ( {
282312 ...s ,
283313 [ name ] : {
284314 height : 0 ,
@@ -289,12 +319,12 @@ export function useFormSmartScroll({
289319 } ,
290320 } ) ) ;
291321 } ,
292- [ setState ]
322+ [ setElements ]
293323 ) ;
294324
295325 const onBlur = useCallback (
296326 ( name : string ) => ( ) => {
297- setState ( ( s ) => ( {
327+ setElements ( ( s ) => ( {
298328 ...s ,
299329 [ name ] : {
300330 height : 0 ,
@@ -305,7 +335,7 @@ export function useFormSmartScroll({
305335 } ,
306336 } ) ) ;
307337 } ,
308- [ setState ]
338+ [ setElements ]
309339 ) ;
310340
311341 /**
0 commit comments