react-native-timer-picker 1.2.10 → 1.3.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 +17 -1
- package/dist/commonjs/components/TimerPicker/DurationScroll.js +22 -3
- package/dist/commonjs/components/TimerPicker/DurationScroll.js.map +1 -1
- package/dist/commonjs/components/TimerPicker/index.js +32 -20
- package/dist/commonjs/components/TimerPicker/index.js.map +1 -1
- package/dist/commonjs/components/index.js +46 -30
- package/dist/commonjs/components/index.js.map +1 -1
- package/dist/module/components/TimerPicker/DurationScroll.js +22 -3
- package/dist/module/components/TimerPicker/DurationScroll.js.map +1 -1
- package/dist/module/components/TimerPicker/index.js +32 -20
- package/dist/module/components/TimerPicker/index.js.map +1 -1
- package/dist/module/components/index.js +46 -30
- package/dist/module/components/index.js.map +1 -1
- package/dist/typescript/components/TimerPicker/DurationScroll.d.ts +3 -1
- package/dist/typescript/components/TimerPicker/index.d.ts +7 -1
- package/dist/typescript/components/index.d.ts +6 -1
- package/package.json +2 -2
- package/src/components/TimerPicker/DurationScroll.tsx +44 -3
- package/src/components/TimerPicker/index.tsx +16 -0
- package/src/components/index.tsx +36 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","forwardRef","useCallback","useImperativeHandle","useRef","useState","View","Text","TouchableOpacity","TimerPicker","Modal","generateStyles","TimerPickerModal","_ref","ref","visible","setIsVisible","onConfirm","onCancel","onDurationChange","closeOnOverlayPress","initialHours","initialMinutes","initialSeconds","hideHours","hideMinutes","hideSeconds","hourLimit","minuteLimit","secondLimit","hourLabel","minuteLabel","secondLabel","padWithNItems","disableInfiniteScroll","hideCancelButton","confirmButtonText","cancelButtonText","modalTitle","LinearGradient","modalProps","containerProps","contentContainerProps","pickerContainerProps","buttonContainerProps","buttonTouchableOpacityProps","modalTitleProps","pickerGradientOverlayProps","topPickerGradientOverlayProps","bottomPickerGradientOverlayProps","styles","customStyles","selectedDuration","setSelectedDuration","hours","minutes","seconds","confirmedDuration","setConfirmedDuration","hideModal","confirm","cancel","durationChange","duration","timerPickerRef","reset","options","_timerPickerRef$curre","initialDuration","current","setValue","value","_timerPickerRef$curre2","createElement","_extends","isVisible","onOverlayPress","undefined","testID","style","container","contentContainer","buttonContainer","onPress","button","cancelButton","confirmButton","memo"],"sources":["index.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { View, Text, TouchableOpacity } from \"react-native\";\n\nimport TimerPicker, { TimerPickerProps, TimerPickerRef } from \"./TimerPicker\";\nimport Modal from \"./Modal\";\n\nimport {\n generateStyles,\n CustomTimerPickerModalStyles,\n} from \"./TimerPickerModal.styles\";\n\nexport interface TimerPickerModalRef {\n reset: (options?: { animated?: boolean }) => void;\n setValue: (\n value: {\n hours: number;\n minutes: number;\n seconds: number;\n },\n options?: { animated?: boolean }\n ) => void;\n}\n\nexport interface TimerPickerModalProps extends TimerPickerProps {\n visible: boolean;\n setIsVisible: (isVisible: boolean) => void;\n onConfirm: ({\n hours,\n minutes,\n seconds,\n }: {\n hours: number;\n minutes: number;\n seconds: number;\n }) => void;\n onCancel?: () => void;\n closeOnOverlayPress?: boolean;\n hideCancelButton?: boolean;\n confirmButtonText?: string;\n cancelButtonText?: string;\n modalTitle?: string;\n modalProps?: React.ComponentProps<typeof Modal>;\n containerProps?: React.ComponentProps<typeof View>;\n contentContainerProps?: React.ComponentProps<typeof View>;\n buttonContainerProps?: React.ComponentProps<typeof View>;\n buttonTouchableOpacityProps?: React.ComponentProps<typeof TouchableOpacity>;\n modalTitleProps?: React.ComponentProps<typeof Text>;\n styles?: CustomTimerPickerModalStyles;\n}\n\nconst TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(\n (\n {\n visible,\n setIsVisible,\n onConfirm,\n onCancel,\n onDurationChange,\n closeOnOverlayPress,\n initialHours = 0,\n initialMinutes = 0,\n initialSeconds = 0,\n hideHours = false,\n hideMinutes = false,\n hideSeconds = false,\n hourLimit,\n minuteLimit,\n secondLimit,\n hourLabel = \"h\",\n minuteLabel = \"m\",\n secondLabel = \"s\",\n padWithNItems = 1,\n disableInfiniteScroll = false,\n hideCancelButton = false,\n confirmButtonText = \"Confirm\",\n cancelButtonText = \"Cancel\",\n modalTitle,\n LinearGradient,\n modalProps,\n containerProps,\n contentContainerProps,\n pickerContainerProps,\n buttonContainerProps,\n buttonTouchableOpacityProps,\n modalTitleProps,\n pickerGradientOverlayProps,\n topPickerGradientOverlayProps,\n bottomPickerGradientOverlayProps,\n styles: customStyles,\n },\n ref\n ): React.ReactElement => {\n const styles = generateStyles(customStyles);\n\n const [selectedDuration, setSelectedDuration] = useState({\n hours: initialHours,\n minutes: initialMinutes,\n seconds: initialSeconds,\n });\n const [confirmedDuration, setConfirmedDuration] = useState({\n hours: initialHours,\n minutes: initialMinutes,\n seconds: initialSeconds,\n });\n\n const hideModal = () => {\n setSelectedDuration({\n hours: confirmedDuration.hours,\n minutes: confirmedDuration.minutes,\n seconds: confirmedDuration.seconds,\n });\n setIsVisible(false);\n };\n\n const confirm = () => {\n setConfirmedDuration(selectedDuration);\n onConfirm(selectedDuration);\n };\n\n const cancel = () => {\n setIsVisible(false);\n setSelectedDuration(confirmedDuration);\n onCancel?.();\n };\n\n // wrapped in useCallback to avoid unnecessary re-renders of TimerPicker\n const durationChange = useCallback(\n (duration: { hours: number; minutes: number; seconds: number }) => {\n setSelectedDuration(duration);\n onDurationChange?.(duration);\n },\n [onDurationChange]\n );\n\n const timerPickerRef = useRef<TimerPickerRef>(null);\n\n useImperativeHandle(ref, () => ({\n reset: (options) => {\n const initialDuration = {\n hours: initialHours,\n minutes: initialMinutes,\n seconds: initialSeconds,\n };\n setSelectedDuration(initialDuration);\n setConfirmedDuration(initialDuration);\n timerPickerRef.current?.reset(options);\n },\n setValue: (value, options) => {\n setSelectedDuration(value);\n setConfirmedDuration(value);\n timerPickerRef.current?.setValue(value, options);\n },\n }));\n\n return (\n <Modal\n isVisible={visible}\n onOverlayPress={closeOnOverlayPress ? hideModal : undefined}\n {...modalProps}\n testID=\"timer-picker-modal\">\n <View {...containerProps} style={styles.container}>\n <View\n {...contentContainerProps}\n style={styles.contentContainer}>\n {modalTitle ? (\n <Text\n {...modalTitleProps}\n style={styles.modalTitle}>\n {modalTitle}\n </Text>\n ) : null}\n <TimerPicker\n ref={timerPickerRef}\n onDurationChange={durationChange}\n initialHours={confirmedDuration.hours}\n initialMinutes={confirmedDuration.minutes}\n initialSeconds={confirmedDuration.seconds}\n hideHours={hideHours}\n hideMinutes={hideMinutes}\n hideSeconds={hideSeconds}\n hourLimit={hourLimit}\n minuteLimit={minuteLimit}\n secondLimit={secondLimit}\n hourLabel={hourLabel}\n minuteLabel={minuteLabel}\n secondLabel={secondLabel}\n padWithNItems={padWithNItems}\n disableInfiniteScroll={disableInfiniteScroll}\n LinearGradient={LinearGradient}\n pickerContainerProps={pickerContainerProps}\n pickerGradientOverlayProps={\n pickerGradientOverlayProps\n }\n topPickerGradientOverlayProps={\n topPickerGradientOverlayProps\n }\n bottomPickerGradientOverlayProps={\n bottomPickerGradientOverlayProps\n }\n styles={customStyles}\n />\n <View\n {...buttonContainerProps}\n style={styles.buttonContainer}>\n {!hideCancelButton ? (\n <TouchableOpacity\n onPress={cancel}\n {...buttonTouchableOpacityProps}>\n <Text\n style={[\n styles.button,\n styles.cancelButton,\n ]}>\n {cancelButtonText}\n </Text>\n </TouchableOpacity>\n ) : null}\n <TouchableOpacity\n onPress={confirm}\n {...buttonTouchableOpacityProps}>\n <Text\n style={[\n styles.button,\n styles.confirmButton,\n ]}>\n {confirmButtonText}\n </Text>\n </TouchableOpacity>\n </View>\n </View>\n </View>\n </Modal>\n );\n }\n);\n\nexport default React.memo(TimerPickerModal);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["React","forwardRef","useCallback","useImperativeHandle","useRef","useState","View","Text","TouchableOpacity","TimerPicker","Modal","generateStyles","TimerPickerModal","_ref","ref","visible","setIsVisible","onConfirm","onCancel","onDurationChange","closeOnOverlayPress","initialHours","initialMinutes","initialSeconds","hideHours","hideMinutes","hideSeconds","hourLimit","minuteLimit","secondLimit","hourLabel","minuteLabel","secondLabel","padWithNItems","disableInfiniteScroll","hideCancelButton","confirmButtonText","cancelButtonText","modalTitle","LinearGradient","modalProps","containerProps","contentContainerProps","pickerContainerProps","buttonContainerProps","buttonTouchableOpacityProps","modalTitleProps","pickerGradientOverlayProps","topPickerGradientOverlayProps","bottomPickerGradientOverlayProps","styles","customStyles","timerPickerRef","selectedDuration","setSelectedDuration","hours","minutes","seconds","confirmedDuration","setConfirmedDuration","hideModalHandler","confirmHandler","_timerPickerRef$curre","_latestDuration$hours","_latestDuration$minut","_latestDuration$secon","latestDuration","current","newDuration","cancelHandler","durationChangeHandler","duration","_timerPickerRef$curre4","_timerPickerRef$curre5","_timerPickerRef$curre6","reset","options","_timerPickerRef$curre2","initialDuration","setValue","value","_timerPickerRef$curre3","createElement","_extends","isVisible","onOverlayPress","undefined","testID","style","container","contentContainer","aggressivelyGetLatestDuration","buttonContainer","onPress","button","cancelButton","confirmButton","memo"],"sources":["index.tsx"],"sourcesContent":["import React, {\n MutableRefObject,\n forwardRef,\n useCallback,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { View, Text, TouchableOpacity } from \"react-native\";\n\nimport TimerPicker, { TimerPickerProps, TimerPickerRef } from \"./TimerPicker\";\nimport Modal from \"./Modal\";\n\nimport {\n generateStyles,\n CustomTimerPickerModalStyles,\n} from \"./TimerPickerModal.styles\";\n\nexport interface TimerPickerModalRef {\n reset: (options?: { animated?: boolean }) => void;\n setValue: (\n value: {\n hours: number;\n minutes: number;\n seconds: number;\n },\n options?: { animated?: boolean }\n ) => void;\n latestDuration: {\n hours: MutableRefObject<number> | undefined;\n minutes: MutableRefObject<number> | undefined;\n seconds: MutableRefObject<number> | undefined;\n };\n}\n\nexport interface TimerPickerModalProps extends TimerPickerProps {\n visible: boolean;\n setIsVisible: (isVisible: boolean) => void;\n onConfirm: ({\n hours,\n minutes,\n seconds,\n }: {\n hours: number;\n minutes: number;\n seconds: number;\n }) => void;\n onCancel?: () => void;\n closeOnOverlayPress?: boolean;\n hideCancelButton?: boolean;\n confirmButtonText?: string;\n cancelButtonText?: string;\n modalTitle?: string;\n modalProps?: React.ComponentProps<typeof Modal>;\n containerProps?: React.ComponentProps<typeof View>;\n contentContainerProps?: React.ComponentProps<typeof View>;\n buttonContainerProps?: React.ComponentProps<typeof View>;\n buttonTouchableOpacityProps?: React.ComponentProps<typeof TouchableOpacity>;\n modalTitleProps?: React.ComponentProps<typeof Text>;\n styles?: CustomTimerPickerModalStyles;\n}\n\nconst TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(\n (\n {\n visible,\n setIsVisible,\n onConfirm,\n onCancel,\n onDurationChange,\n closeOnOverlayPress,\n initialHours = 0,\n initialMinutes = 0,\n initialSeconds = 0,\n hideHours = false,\n hideMinutes = false,\n hideSeconds = false,\n hourLimit,\n minuteLimit,\n secondLimit,\n hourLabel = \"h\",\n minuteLabel = \"m\",\n secondLabel = \"s\",\n padWithNItems = 1,\n disableInfiniteScroll = false,\n hideCancelButton = false,\n confirmButtonText = \"Confirm\",\n cancelButtonText = \"Cancel\",\n modalTitle,\n LinearGradient,\n modalProps,\n containerProps,\n contentContainerProps,\n pickerContainerProps,\n buttonContainerProps,\n buttonTouchableOpacityProps,\n modalTitleProps,\n pickerGradientOverlayProps,\n topPickerGradientOverlayProps,\n bottomPickerGradientOverlayProps,\n styles: customStyles,\n },\n ref\n ): React.ReactElement => {\n const styles = generateStyles(customStyles);\n\n const timerPickerRef = useRef<TimerPickerRef>(null);\n\n const [selectedDuration, setSelectedDuration] = useState({\n hours: initialHours,\n minutes: initialMinutes,\n seconds: initialSeconds,\n });\n const [confirmedDuration, setConfirmedDuration] = useState({\n hours: initialHours,\n minutes: initialMinutes,\n seconds: initialSeconds,\n });\n\n const hideModalHandler = () => {\n setSelectedDuration({\n hours: confirmedDuration.hours,\n minutes: confirmedDuration.minutes,\n seconds: confirmedDuration.seconds,\n });\n setIsVisible(false);\n };\n\n const confirmHandler = () => {\n const latestDuration = timerPickerRef.current?.latestDuration;\n const newDuration = {\n hours: latestDuration?.hours?.current ?? selectedDuration.hours,\n minutes:\n latestDuration?.minutes?.current ??\n selectedDuration.minutes,\n seconds:\n latestDuration?.seconds?.current ??\n selectedDuration.seconds,\n };\n setConfirmedDuration(newDuration);\n onConfirm(newDuration);\n };\n\n const cancelHandler = () => {\n setIsVisible(false);\n setSelectedDuration(confirmedDuration);\n onCancel?.();\n };\n\n // wrapped in useCallback to avoid unnecessary re-renders of TimerPicker\n const durationChangeHandler = useCallback(\n (duration: { hours: number; minutes: number; seconds: number }) => {\n setSelectedDuration(duration);\n onDurationChange?.(duration);\n },\n [onDurationChange]\n );\n\n useImperativeHandle(ref, () => ({\n reset: (options) => {\n const initialDuration = {\n hours: initialHours,\n minutes: initialMinutes,\n seconds: initialSeconds,\n };\n setSelectedDuration(initialDuration);\n setConfirmedDuration(initialDuration);\n timerPickerRef.current?.reset(options);\n },\n setValue: (value, options) => {\n setSelectedDuration(value);\n setConfirmedDuration(value);\n timerPickerRef.current?.setValue(value, options);\n },\n latestDuration: {\n hours: timerPickerRef.current?.latestDuration?.hours,\n minutes: timerPickerRef.current?.latestDuration?.minutes,\n seconds: timerPickerRef.current?.latestDuration?.seconds,\n },\n }));\n\n return (\n <Modal\n isVisible={visible}\n onOverlayPress={\n closeOnOverlayPress ? hideModalHandler : undefined\n }\n {...modalProps}\n testID=\"timer-picker-modal\">\n <View {...containerProps} style={styles.container}>\n <View\n {...contentContainerProps}\n style={styles.contentContainer}>\n {modalTitle ? (\n <Text\n {...modalTitleProps}\n style={styles.modalTitle}>\n {modalTitle}\n </Text>\n ) : null}\n <TimerPicker\n ref={timerPickerRef}\n onDurationChange={durationChangeHandler}\n initialHours={confirmedDuration.hours}\n initialMinutes={confirmedDuration.minutes}\n initialSeconds={confirmedDuration.seconds}\n aggressivelyGetLatestDuration={true}\n hideHours={hideHours}\n hideMinutes={hideMinutes}\n hideSeconds={hideSeconds}\n hourLimit={hourLimit}\n minuteLimit={minuteLimit}\n secondLimit={secondLimit}\n hourLabel={hourLabel}\n minuteLabel={minuteLabel}\n secondLabel={secondLabel}\n padWithNItems={padWithNItems}\n disableInfiniteScroll={disableInfiniteScroll}\n LinearGradient={LinearGradient}\n pickerContainerProps={pickerContainerProps}\n pickerGradientOverlayProps={\n pickerGradientOverlayProps\n }\n topPickerGradientOverlayProps={\n topPickerGradientOverlayProps\n }\n bottomPickerGradientOverlayProps={\n bottomPickerGradientOverlayProps\n }\n styles={customStyles}\n />\n <View\n {...buttonContainerProps}\n style={styles.buttonContainer}>\n {!hideCancelButton ? (\n <TouchableOpacity\n onPress={cancelHandler}\n {...buttonTouchableOpacityProps}>\n <Text\n style={[\n styles.button,\n styles.cancelButton,\n ]}>\n {cancelButtonText}\n </Text>\n </TouchableOpacity>\n ) : null}\n <TouchableOpacity\n onPress={confirmHandler}\n {...buttonTouchableOpacityProps}>\n <Text\n style={[\n styles.button,\n styles.confirmButton,\n ]}>\n {confirmButtonText}\n </Text>\n </TouchableOpacity>\n </View>\n </View>\n </View>\n </Modal>\n );\n }\n);\n\nexport default React.memo(TimerPickerModal);\n"],"mappings":";AAAA,OAAOA,KAAK,IAERC,UAAU,EACVC,WAAW,EACXC,mBAAmB,EACnBC,MAAM,EACNC,QAAQ,QACL,OAAO;AACd,SAASC,IAAI,EAAEC,IAAI,EAAEC,gBAAgB,QAAQ,cAAc;AAE3D,OAAOC,WAAW,MAA4C,eAAe;AAC7E,OAAOC,KAAK,MAAM,SAAS;AAE3B,SACIC,cAAc,QAEX,2BAA2B;AA8ClC,MAAMC,gBAAgB,gBAAGX,UAAU,CAC/B,CAAAY,IAAA,EAuCIC,GAAG,KACkB;EAAA,IAvCrB;IACIC,OAAO;IACPC,YAAY;IACZC,SAAS;IACTC,QAAQ;IACRC,gBAAgB;IAChBC,mBAAmB;IACnBC,YAAY,GAAG,CAAC;IAChBC,cAAc,GAAG,CAAC;IAClBC,cAAc,GAAG,CAAC;IAClBC,SAAS,GAAG,KAAK;IACjBC,WAAW,GAAG,KAAK;IACnBC,WAAW,GAAG,KAAK;IACnBC,SAAS;IACTC,WAAW;IACXC,WAAW;IACXC,SAAS,GAAG,GAAG;IACfC,WAAW,GAAG,GAAG;IACjBC,WAAW,GAAG,GAAG;IACjBC,aAAa,GAAG,CAAC;IACjBC,qBAAqB,GAAG,KAAK;IAC7BC,gBAAgB,GAAG,KAAK;IACxBC,iBAAiB,GAAG,SAAS;IAC7BC,gBAAgB,GAAG,QAAQ;IAC3BC,UAAU;IACVC,cAAc;IACdC,UAAU;IACVC,cAAc;IACdC,qBAAqB;IACrBC,oBAAoB;IACpBC,oBAAoB;IACpBC,2BAA2B;IAC3BC,eAAe;IACfC,0BAA0B;IAC1BC,6BAA6B;IAC7BC,gCAAgC;IAChCC,MAAM,EAAEC;EACZ,CAAC,GAAAtC,IAAA;EAGD,MAAMqC,MAAM,GAAGvC,cAAc,CAACwC,YAAY,CAAC;EAE3C,MAAMC,cAAc,GAAGhD,MAAM,CAAiB,IAAI,CAAC;EAEnD,MAAM,CAACiD,gBAAgB,EAAEC,mBAAmB,CAAC,GAAGjD,QAAQ,CAAC;IACrDkD,KAAK,EAAElC,YAAY;IACnBmC,OAAO,EAAElC,cAAc;IACvBmC,OAAO,EAAElC;EACb,CAAC,CAAC;EACF,MAAM,CAACmC,iBAAiB,EAAEC,oBAAoB,CAAC,GAAGtD,QAAQ,CAAC;IACvDkD,KAAK,EAAElC,YAAY;IACnBmC,OAAO,EAAElC,cAAc;IACvBmC,OAAO,EAAElC;EACb,CAAC,CAAC;EAEF,MAAMqC,gBAAgB,GAAGA,CAAA,KAAM;IAC3BN,mBAAmB,CAAC;MAChBC,KAAK,EAAEG,iBAAiB,CAACH,KAAK;MAC9BC,OAAO,EAAEE,iBAAiB,CAACF,OAAO;MAClCC,OAAO,EAAEC,iBAAiB,CAACD;IAC/B,CAAC,CAAC;IACFzC,YAAY,CAAC,KAAK,CAAC;EACvB,CAAC;EAED,MAAM6C,cAAc,GAAGA,CAAA,KAAM;IAAA,IAAAC,qBAAA,EAAAC,qBAAA,EAAAC,qBAAA,EAAAC,qBAAA;IACzB,MAAMC,cAAc,IAAAJ,qBAAA,GAAGV,cAAc,CAACe,OAAO,cAAAL,qBAAA,uBAAtBA,qBAAA,CAAwBI,cAAc;IAC7D,MAAME,WAAW,GAAG;MAChBb,KAAK,EAAE,CAAAW,cAAc,aAAdA,cAAc,gBAAAH,qBAAA,GAAdG,cAAc,CAAEX,KAAK,cAAAQ,qBAAA,uBAArBA,qBAAA,CAAuBI,OAAO,KAAId,gBAAgB,CAACE,KAAK;MAC/DC,OAAO,EACH,CAAAU,cAAc,aAAdA,cAAc,gBAAAF,qBAAA,GAAdE,cAAc,CAAEV,OAAO,cAAAQ,qBAAA,uBAAvBA,qBAAA,CAAyBG,OAAO,KAChCd,gBAAgB,CAACG,OAAO;MAC5BC,OAAO,EACH,CAAAS,cAAc,aAAdA,cAAc,gBAAAD,qBAAA,GAAdC,cAAc,CAAET,OAAO,cAAAQ,qBAAA,uBAAvBA,qBAAA,CAAyBE,OAAO,KAChCd,gBAAgB,CAACI;IACzB,CAAC;IACDE,oBAAoB,CAACS,WAAW,CAAC;IACjCnD,SAAS,CAACmD,WAAW,CAAC;EAC1B,CAAC;EAED,MAAMC,aAAa,GAAGA,CAAA,KAAM;IACxBrD,YAAY,CAAC,KAAK,CAAC;IACnBsC,mBAAmB,CAACI,iBAAiB,CAAC;IACtCxC,QAAQ,aAARA,QAAQ,eAARA,QAAQ,CAAG,CAAC;EAChB,CAAC;;EAED;EACA,MAAMoD,qBAAqB,GAAGpE,WAAW,CACpCqE,QAA6D,IAAK;IAC/DjB,mBAAmB,CAACiB,QAAQ,CAAC;IAC7BpD,gBAAgB,aAAhBA,gBAAgB,eAAhBA,gBAAgB,CAAGoD,QAAQ,CAAC;EAChC,CAAC,EACD,CAACpD,gBAAgB,CACrB,CAAC;EAEDhB,mBAAmB,CAACW,GAAG,EAAE;IAAA,IAAA0D,sBAAA,EAAAC,sBAAA,EAAAC,sBAAA;IAAA,OAAO;MAC5BC,KAAK,EAAGC,OAAO,IAAK;QAAA,IAAAC,sBAAA;QAChB,MAAMC,eAAe,GAAG;UACpBvB,KAAK,EAAElC,YAAY;UACnBmC,OAAO,EAAElC,cAAc;UACvBmC,OAAO,EAAElC;QACb,CAAC;QACD+B,mBAAmB,CAACwB,eAAe,CAAC;QACpCnB,oBAAoB,CAACmB,eAAe,CAAC;QACrC,CAAAD,sBAAA,GAAAzB,cAAc,CAACe,OAAO,cAAAU,sBAAA,eAAtBA,sBAAA,CAAwBF,KAAK,CAACC,OAAO,CAAC;MAC1C,CAAC;MACDG,QAAQ,EAAEA,CAACC,KAAK,EAAEJ,OAAO,KAAK;QAAA,IAAAK,sBAAA;QAC1B3B,mBAAmB,CAAC0B,KAAK,CAAC;QAC1BrB,oBAAoB,CAACqB,KAAK,CAAC;QAC3B,CAAAC,sBAAA,GAAA7B,cAAc,CAACe,OAAO,cAAAc,sBAAA,eAAtBA,sBAAA,CAAwBF,QAAQ,CAACC,KAAK,EAAEJ,OAAO,CAAC;MACpD,CAAC;MACDV,cAAc,EAAE;QACZX,KAAK,GAAAiB,sBAAA,GAAEpB,cAAc,CAACe,OAAO,cAAAK,sBAAA,gBAAAA,sBAAA,GAAtBA,sBAAA,CAAwBN,cAAc,cAAAM,sBAAA,uBAAtCA,sBAAA,CAAwCjB,KAAK;QACpDC,OAAO,GAAAiB,sBAAA,GAAErB,cAAc,CAACe,OAAO,cAAAM,sBAAA,gBAAAA,sBAAA,GAAtBA,sBAAA,CAAwBP,cAAc,cAAAO,sBAAA,uBAAtCA,sBAAA,CAAwCjB,OAAO;QACxDC,OAAO,GAAAiB,sBAAA,GAAEtB,cAAc,CAACe,OAAO,cAAAO,sBAAA,gBAAAA,sBAAA,GAAtBA,sBAAA,CAAwBR,cAAc,cAAAQ,sBAAA,uBAAtCA,sBAAA,CAAwCjB;MACrD;IACJ,CAAC;EAAA,CAAC,CAAC;EAEH,oBACIzD,KAAA,CAAAkF,aAAA,CAACxE,KAAK,EAAAyE,QAAA;IACFC,SAAS,EAAErE,OAAQ;IACnBsE,cAAc,EACVjE,mBAAmB,GAAGwC,gBAAgB,GAAG0B;EAC5C,GACG9C,UAAU;IACd+C,MAAM,EAAC;EAAoB,iBAC3BvF,KAAA,CAAAkF,aAAA,CAAC5E,IAAI,EAAA6E,QAAA,KAAK1C,cAAc;IAAE+C,KAAK,EAAEtC,MAAM,CAACuC;EAAU,iBAC9CzF,KAAA,CAAAkF,aAAA,CAAC5E,IAAI,EAAA6E,QAAA,KACGzC,qBAAqB;IACzB8C,KAAK,EAAEtC,MAAM,CAACwC;EAAiB,IAC9BpD,UAAU,gBACPtC,KAAA,CAAAkF,aAAA,CAAC3E,IAAI,EAAA4E,QAAA,KACGrC,eAAe;IACnB0C,KAAK,EAAEtC,MAAM,CAACZ;EAAW,IACxBA,UACC,CAAC,GACP,IAAI,eACRtC,KAAA,CAAAkF,aAAA,CAACzE,WAAW;IACRK,GAAG,EAAEsC,cAAe;IACpBjC,gBAAgB,EAAEmD,qBAAsB;IACxCjD,YAAY,EAAEqC,iBAAiB,CAACH,KAAM;IACtCjC,cAAc,EAAEoC,iBAAiB,CAACF,OAAQ;IAC1CjC,cAAc,EAAEmC,iBAAiB,CAACD,OAAQ;IAC1CkC,6BAA6B,EAAE,IAAK;IACpCnE,SAAS,EAAEA,SAAU;IACrBC,WAAW,EAAEA,WAAY;IACzBC,WAAW,EAAEA,WAAY;IACzBC,SAAS,EAAEA,SAAU;IACrBC,WAAW,EAAEA,WAAY;IACzBC,WAAW,EAAEA,WAAY;IACzBC,SAAS,EAAEA,SAAU;IACrBC,WAAW,EAAEA,WAAY;IACzBC,WAAW,EAAEA,WAAY;IACzBC,aAAa,EAAEA,aAAc;IAC7BC,qBAAqB,EAAEA,qBAAsB;IAC7CK,cAAc,EAAEA,cAAe;IAC/BI,oBAAoB,EAAEA,oBAAqB;IAC3CI,0BAA0B,EACtBA,0BACH;IACDC,6BAA6B,EACzBA,6BACH;IACDC,gCAAgC,EAC5BA,gCACH;IACDC,MAAM,EAAEC;EAAa,CACxB,CAAC,eACFnD,KAAA,CAAAkF,aAAA,CAAC5E,IAAI,EAAA6E,QAAA,KACGvC,oBAAoB;IACxB4C,KAAK,EAAEtC,MAAM,CAAC0C;EAAgB,IAC7B,CAACzD,gBAAgB,gBACdnC,KAAA,CAAAkF,aAAA,CAAC1E,gBAAgB,EAAA2E,QAAA;IACbU,OAAO,EAAExB;EAAc,GACnBxB,2BAA2B,gBAC/B7C,KAAA,CAAAkF,aAAA,CAAC3E,IAAI;IACDiF,KAAK,EAAE,CACHtC,MAAM,CAAC4C,MAAM,EACb5C,MAAM,CAAC6C,YAAY;EACrB,GACD1D,gBACC,CACQ,CAAC,GACnB,IAAI,eACRrC,KAAA,CAAAkF,aAAA,CAAC1E,gBAAgB,EAAA2E,QAAA;IACbU,OAAO,EAAEhC;EAAe,GACpBhB,2BAA2B,gBAC/B7C,KAAA,CAAAkF,aAAA,CAAC3E,IAAI;IACDiF,KAAK,EAAE,CACHtC,MAAM,CAAC4C,MAAM,EACb5C,MAAM,CAAC8C,aAAa;EACtB,GACD5D,iBACC,CACQ,CAChB,CACJ,CACJ,CACH,CAAC;AAEhB,CACJ,CAAC;AAED,4BAAepC,KAAK,CAACiG,IAAI,CAACrF,gBAAgB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { MutableRefObject } from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
3
|
import { generateStyles } from "./TimerPicker.styles";
|
|
4
4
|
export interface DurationScrollRef {
|
|
@@ -8,6 +8,7 @@ export interface DurationScrollRef {
|
|
|
8
8
|
setValue: (value: number, options?: {
|
|
9
9
|
animated?: boolean;
|
|
10
10
|
}) => void;
|
|
11
|
+
latestDuration: MutableRefObject<number>;
|
|
11
12
|
}
|
|
12
13
|
type LinearGradientPoint = {
|
|
13
14
|
x: number;
|
|
@@ -31,6 +32,7 @@ interface DurationScrollProps {
|
|
|
31
32
|
padNumbersWithZero?: boolean;
|
|
32
33
|
disableInfiniteScroll?: boolean;
|
|
33
34
|
limit?: LimitType;
|
|
35
|
+
aggressivelyGetLatestDuration: boolean;
|
|
34
36
|
padWithNItems: number;
|
|
35
37
|
pickerGradientOverlayProps?: Partial<LinearGradientProps>;
|
|
36
38
|
topPickerGradientOverlayProps?: Partial<LinearGradientProps>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { MutableRefObject } from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
3
|
import { LimitType } from "./DurationScroll";
|
|
4
4
|
import { CustomTimerPickerStyles } from "./TimerPicker.styles";
|
|
@@ -14,6 +14,11 @@ export interface TimerPickerRef {
|
|
|
14
14
|
}, options?: {
|
|
15
15
|
animated?: boolean;
|
|
16
16
|
}) => void;
|
|
17
|
+
latestDuration: {
|
|
18
|
+
hours: MutableRefObject<number> | undefined;
|
|
19
|
+
minutes: MutableRefObject<number> | undefined;
|
|
20
|
+
seconds: MutableRefObject<number> | undefined;
|
|
21
|
+
};
|
|
17
22
|
}
|
|
18
23
|
export interface TimerPickerProps {
|
|
19
24
|
onDurationChange?: (duration: {
|
|
@@ -24,6 +29,7 @@ export interface TimerPickerProps {
|
|
|
24
29
|
initialHours?: number;
|
|
25
30
|
initialMinutes?: number;
|
|
26
31
|
initialSeconds?: number;
|
|
32
|
+
aggressivelyGetLatestDuration?: boolean;
|
|
27
33
|
hideHours?: boolean;
|
|
28
34
|
hideMinutes?: boolean;
|
|
29
35
|
hideSeconds?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { MutableRefObject } from "react";
|
|
2
2
|
import { View, Text, TouchableOpacity } from "react-native";
|
|
3
3
|
import { TimerPickerProps } from "./TimerPicker";
|
|
4
4
|
import Modal from "./Modal";
|
|
@@ -14,6 +14,11 @@ export interface TimerPickerModalRef {
|
|
|
14
14
|
}, options?: {
|
|
15
15
|
animated?: boolean;
|
|
16
16
|
}) => void;
|
|
17
|
+
latestDuration: {
|
|
18
|
+
hours: MutableRefObject<number> | undefined;
|
|
19
|
+
minutes: MutableRefObject<number> | undefined;
|
|
20
|
+
seconds: MutableRefObject<number> | undefined;
|
|
21
|
+
};
|
|
17
22
|
}
|
|
18
23
|
export interface TimerPickerModalProps extends TimerPickerProps {
|
|
19
24
|
visible: boolean;
|
package/package.json
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
"url": "https://github.com/troberts-28"
|
|
7
7
|
},
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.3.0",
|
|
10
10
|
"main": "dist/commonjs/index.js",
|
|
11
11
|
"types": "dist/typescript/src/index.d.ts",
|
|
12
12
|
"scripts": {
|
|
13
13
|
"test": "jest --forceExit --silent",
|
|
14
14
|
"build": "bob build",
|
|
15
15
|
"clean": "rm yarn.lock && rm -rf ./node_modules && yarn install",
|
|
16
|
-
"start": "cp -Rf src example && cd example &&
|
|
16
|
+
"start": "cp -Rf src example && cd example && npx expo install && npx expo start",
|
|
17
17
|
"lint": "eslint --ext .ts,.tsx .",
|
|
18
18
|
"lint:fix": "eslint --ext .ts,.tsx . --fix",
|
|
19
19
|
"prepare": "yarn build"
|
|
@@ -3,6 +3,7 @@ import React, {
|
|
|
3
3
|
useCallback,
|
|
4
4
|
forwardRef,
|
|
5
5
|
useImperativeHandle,
|
|
6
|
+
MutableRefObject,
|
|
6
7
|
} from "react";
|
|
7
8
|
import {
|
|
8
9
|
View,
|
|
@@ -23,6 +24,7 @@ import { getScrollIndex } from "../../utils/getScrollIndex";
|
|
|
23
24
|
export interface DurationScrollRef {
|
|
24
25
|
reset: (options?: { animated?: boolean }) => void;
|
|
25
26
|
setValue: (value: number, options?: { animated?: boolean }) => void;
|
|
27
|
+
latestDuration: MutableRefObject<number>;
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
type LinearGradientPoint = {
|
|
@@ -50,6 +52,7 @@ interface DurationScrollProps {
|
|
|
50
52
|
padNumbersWithZero?: boolean;
|
|
51
53
|
disableInfiniteScroll?: boolean;
|
|
52
54
|
limit?: LimitType;
|
|
55
|
+
aggressivelyGetLatestDuration: boolean;
|
|
53
56
|
padWithNItems: number;
|
|
54
57
|
pickerGradientOverlayProps?: Partial<LinearGradientProps>;
|
|
55
58
|
topPickerGradientOverlayProps?: Partial<LinearGradientProps>;
|
|
@@ -73,6 +76,7 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
73
76
|
padNumbersWithZero = false,
|
|
74
77
|
disableInfiniteScroll = false,
|
|
75
78
|
limit,
|
|
79
|
+
aggressivelyGetLatestDuration,
|
|
76
80
|
padWithNItems,
|
|
77
81
|
pickerGradientOverlayProps,
|
|
78
82
|
topPickerGradientOverlayProps,
|
|
@@ -83,8 +87,6 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
83
87
|
},
|
|
84
88
|
ref
|
|
85
89
|
): React.ReactElement => {
|
|
86
|
-
const flatListRef = useRef<FlatList | null>(null);
|
|
87
|
-
|
|
88
90
|
const data = generateNumbers(numberOfItems, {
|
|
89
91
|
padWithZero: padNumbersWithZero,
|
|
90
92
|
repeatNTimes: 3,
|
|
@@ -103,6 +105,10 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
103
105
|
disableInfiniteScroll,
|
|
104
106
|
});
|
|
105
107
|
|
|
108
|
+
const latestDuration = useRef(0);
|
|
109
|
+
|
|
110
|
+
const flatListRef = useRef<FlatList | null>(null);
|
|
111
|
+
|
|
106
112
|
useImperativeHandle(ref, () => ({
|
|
107
113
|
reset: (options) => {
|
|
108
114
|
flatListRef.current?.scrollToIndex({
|
|
@@ -121,6 +127,7 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
121
127
|
}),
|
|
122
128
|
});
|
|
123
129
|
},
|
|
130
|
+
latestDuration: latestDuration,
|
|
124
131
|
}));
|
|
125
132
|
|
|
126
133
|
const renderItem = useCallback(
|
|
@@ -154,6 +161,39 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
154
161
|
]
|
|
155
162
|
);
|
|
156
163
|
|
|
164
|
+
const onScroll = useCallback(
|
|
165
|
+
(e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
166
|
+
// this function is only used when the picker is in a modal
|
|
167
|
+
// it is used to ensure that the modal gets the latest duration on clicking
|
|
168
|
+
// the confirm button, even if the scrollview is still scrolling
|
|
169
|
+
const newIndex = Math.round(
|
|
170
|
+
e.nativeEvent.contentOffset.y /
|
|
171
|
+
styles.pickerItemContainer.height
|
|
172
|
+
);
|
|
173
|
+
let newDuration =
|
|
174
|
+
(disableInfiniteScroll
|
|
175
|
+
? newIndex
|
|
176
|
+
: newIndex + padWithNItems) %
|
|
177
|
+
(numberOfItems + 1);
|
|
178
|
+
|
|
179
|
+
// check limits
|
|
180
|
+
if (newDuration > adjustedLimited.max) {
|
|
181
|
+
newDuration = adjustedLimited.max;
|
|
182
|
+
} else if (newDuration < adjustedLimited.min) {
|
|
183
|
+
newDuration = adjustedLimited.min;
|
|
184
|
+
}
|
|
185
|
+
latestDuration.current = newDuration;
|
|
186
|
+
},
|
|
187
|
+
[
|
|
188
|
+
adjustedLimited.max,
|
|
189
|
+
adjustedLimited.min,
|
|
190
|
+
disableInfiniteScroll,
|
|
191
|
+
numberOfItems,
|
|
192
|
+
padWithNItems,
|
|
193
|
+
styles.pickerItemContainer.height,
|
|
194
|
+
]
|
|
195
|
+
);
|
|
196
|
+
|
|
157
197
|
const onMomentumScrollEnd = useCallback(
|
|
158
198
|
(e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
159
199
|
const newIndex = Math.round(
|
|
@@ -264,7 +304,7 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
264
304
|
renderItem={renderItem}
|
|
265
305
|
keyExtractor={KEY_EXTRACTOR}
|
|
266
306
|
showsVerticalScrollIndicator={false}
|
|
267
|
-
decelerationRate={0.
|
|
307
|
+
decelerationRate={0.88}
|
|
268
308
|
scrollEventThrottle={16}
|
|
269
309
|
snapToAlignment="start"
|
|
270
310
|
// used in place of snapToOffset due to bug on Android
|
|
@@ -277,6 +317,7 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
277
317
|
: undefined
|
|
278
318
|
}
|
|
279
319
|
onMomentumScrollEnd={onMomentumScrollEnd}
|
|
320
|
+
onScroll={aggressivelyGetLatestDuration ? onScroll : undefined}
|
|
280
321
|
testID="duration-scroll-flatlist"
|
|
281
322
|
/>
|
|
282
323
|
<View style={styles.pickerLabelContainer} pointerEvents="none">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, {
|
|
2
|
+
MutableRefObject,
|
|
2
3
|
forwardRef,
|
|
3
4
|
useEffect,
|
|
4
5
|
useImperativeHandle,
|
|
@@ -23,6 +24,11 @@ export interface TimerPickerRef {
|
|
|
23
24
|
},
|
|
24
25
|
options?: { animated?: boolean }
|
|
25
26
|
) => void;
|
|
27
|
+
latestDuration: {
|
|
28
|
+
hours: MutableRefObject<number> | undefined;
|
|
29
|
+
minutes: MutableRefObject<number> | undefined;
|
|
30
|
+
seconds: MutableRefObject<number> | undefined;
|
|
31
|
+
};
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
export interface TimerPickerProps {
|
|
@@ -34,6 +40,7 @@ export interface TimerPickerProps {
|
|
|
34
40
|
initialHours?: number;
|
|
35
41
|
initialMinutes?: number;
|
|
36
42
|
initialSeconds?: number;
|
|
43
|
+
aggressivelyGetLatestDuration?: boolean;
|
|
37
44
|
hideHours?: boolean;
|
|
38
45
|
hideMinutes?: boolean;
|
|
39
46
|
hideSeconds?: boolean;
|
|
@@ -72,6 +79,7 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
72
79
|
secondLabel = "s",
|
|
73
80
|
padWithNItems = 1,
|
|
74
81
|
disableInfiniteScroll = false,
|
|
82
|
+
aggressivelyGetLatestDuration = false,
|
|
75
83
|
LinearGradient,
|
|
76
84
|
pickerContainerProps,
|
|
77
85
|
pickerGradientOverlayProps,
|
|
@@ -133,6 +141,11 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
133
141
|
options
|
|
134
142
|
);
|
|
135
143
|
},
|
|
144
|
+
latestDuration: {
|
|
145
|
+
hours: hoursDurationScrollRef.current?.latestDuration,
|
|
146
|
+
minutes: minutesDurationScrollRef.current?.latestDuration,
|
|
147
|
+
seconds: secondsDurationScrollRef.current?.latestDuration,
|
|
148
|
+
},
|
|
136
149
|
}));
|
|
137
150
|
|
|
138
151
|
return (
|
|
@@ -146,6 +159,7 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
146
159
|
numberOfItems={23}
|
|
147
160
|
label={hourLabel}
|
|
148
161
|
initialValue={initialHours}
|
|
162
|
+
aggressivelyGetLatestDuration={aggressivelyGetLatestDuration}
|
|
149
163
|
onDurationChange={setSelectedHours}
|
|
150
164
|
pickerGradientOverlayProps={pickerGradientOverlayProps}
|
|
151
165
|
topPickerGradientOverlayProps={
|
|
@@ -168,6 +182,7 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
168
182
|
numberOfItems={59}
|
|
169
183
|
label={minuteLabel}
|
|
170
184
|
initialValue={initialMinutes}
|
|
185
|
+
aggressivelyGetLatestDuration={aggressivelyGetLatestDuration}
|
|
171
186
|
onDurationChange={setSelectedMinutes}
|
|
172
187
|
padNumbersWithZero
|
|
173
188
|
pickerGradientOverlayProps={pickerGradientOverlayProps}
|
|
@@ -191,6 +206,7 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
191
206
|
numberOfItems={59}
|
|
192
207
|
label={secondLabel}
|
|
193
208
|
initialValue={initialSeconds}
|
|
209
|
+
aggressivelyGetLatestDuration={aggressivelyGetLatestDuration}
|
|
194
210
|
onDurationChange={setSelectedSeconds}
|
|
195
211
|
padNumbersWithZero
|
|
196
212
|
pickerGradientOverlayProps={pickerGradientOverlayProps}
|
package/src/components/index.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, {
|
|
2
|
+
MutableRefObject,
|
|
2
3
|
forwardRef,
|
|
3
4
|
useCallback,
|
|
4
5
|
useImperativeHandle,
|
|
@@ -25,6 +26,11 @@ export interface TimerPickerModalRef {
|
|
|
25
26
|
},
|
|
26
27
|
options?: { animated?: boolean }
|
|
27
28
|
) => void;
|
|
29
|
+
latestDuration: {
|
|
30
|
+
hours: MutableRefObject<number> | undefined;
|
|
31
|
+
minutes: MutableRefObject<number> | undefined;
|
|
32
|
+
seconds: MutableRefObject<number> | undefined;
|
|
33
|
+
};
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
export interface TimerPickerModalProps extends TimerPickerProps {
|
|
@@ -98,6 +104,8 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(
|
|
|
98
104
|
): React.ReactElement => {
|
|
99
105
|
const styles = generateStyles(customStyles);
|
|
100
106
|
|
|
107
|
+
const timerPickerRef = useRef<TimerPickerRef>(null);
|
|
108
|
+
|
|
101
109
|
const [selectedDuration, setSelectedDuration] = useState({
|
|
102
110
|
hours: initialHours,
|
|
103
111
|
minutes: initialMinutes,
|
|
@@ -109,7 +117,7 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(
|
|
|
109
117
|
seconds: initialSeconds,
|
|
110
118
|
});
|
|
111
119
|
|
|
112
|
-
const
|
|
120
|
+
const hideModalHandler = () => {
|
|
113
121
|
setSelectedDuration({
|
|
114
122
|
hours: confirmedDuration.hours,
|
|
115
123
|
minutes: confirmedDuration.minutes,
|
|
@@ -118,19 +126,29 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(
|
|
|
118
126
|
setIsVisible(false);
|
|
119
127
|
};
|
|
120
128
|
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
129
|
+
const confirmHandler = () => {
|
|
130
|
+
const latestDuration = timerPickerRef.current?.latestDuration;
|
|
131
|
+
const newDuration = {
|
|
132
|
+
hours: latestDuration?.hours?.current ?? selectedDuration.hours,
|
|
133
|
+
minutes:
|
|
134
|
+
latestDuration?.minutes?.current ??
|
|
135
|
+
selectedDuration.minutes,
|
|
136
|
+
seconds:
|
|
137
|
+
latestDuration?.seconds?.current ??
|
|
138
|
+
selectedDuration.seconds,
|
|
139
|
+
};
|
|
140
|
+
setConfirmedDuration(newDuration);
|
|
141
|
+
onConfirm(newDuration);
|
|
124
142
|
};
|
|
125
143
|
|
|
126
|
-
const
|
|
144
|
+
const cancelHandler = () => {
|
|
127
145
|
setIsVisible(false);
|
|
128
146
|
setSelectedDuration(confirmedDuration);
|
|
129
147
|
onCancel?.();
|
|
130
148
|
};
|
|
131
149
|
|
|
132
150
|
// wrapped in useCallback to avoid unnecessary re-renders of TimerPicker
|
|
133
|
-
const
|
|
151
|
+
const durationChangeHandler = useCallback(
|
|
134
152
|
(duration: { hours: number; minutes: number; seconds: number }) => {
|
|
135
153
|
setSelectedDuration(duration);
|
|
136
154
|
onDurationChange?.(duration);
|
|
@@ -138,8 +156,6 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(
|
|
|
138
156
|
[onDurationChange]
|
|
139
157
|
);
|
|
140
158
|
|
|
141
|
-
const timerPickerRef = useRef<TimerPickerRef>(null);
|
|
142
|
-
|
|
143
159
|
useImperativeHandle(ref, () => ({
|
|
144
160
|
reset: (options) => {
|
|
145
161
|
const initialDuration = {
|
|
@@ -156,12 +172,19 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(
|
|
|
156
172
|
setConfirmedDuration(value);
|
|
157
173
|
timerPickerRef.current?.setValue(value, options);
|
|
158
174
|
},
|
|
175
|
+
latestDuration: {
|
|
176
|
+
hours: timerPickerRef.current?.latestDuration?.hours,
|
|
177
|
+
minutes: timerPickerRef.current?.latestDuration?.minutes,
|
|
178
|
+
seconds: timerPickerRef.current?.latestDuration?.seconds,
|
|
179
|
+
},
|
|
159
180
|
}));
|
|
160
181
|
|
|
161
182
|
return (
|
|
162
183
|
<Modal
|
|
163
184
|
isVisible={visible}
|
|
164
|
-
onOverlayPress={
|
|
185
|
+
onOverlayPress={
|
|
186
|
+
closeOnOverlayPress ? hideModalHandler : undefined
|
|
187
|
+
}
|
|
165
188
|
{...modalProps}
|
|
166
189
|
testID="timer-picker-modal">
|
|
167
190
|
<View {...containerProps} style={styles.container}>
|
|
@@ -177,10 +200,11 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(
|
|
|
177
200
|
) : null}
|
|
178
201
|
<TimerPicker
|
|
179
202
|
ref={timerPickerRef}
|
|
180
|
-
onDurationChange={
|
|
203
|
+
onDurationChange={durationChangeHandler}
|
|
181
204
|
initialHours={confirmedDuration.hours}
|
|
182
205
|
initialMinutes={confirmedDuration.minutes}
|
|
183
206
|
initialSeconds={confirmedDuration.seconds}
|
|
207
|
+
aggressivelyGetLatestDuration={true}
|
|
184
208
|
hideHours={hideHours}
|
|
185
209
|
hideMinutes={hideMinutes}
|
|
186
210
|
hideSeconds={hideSeconds}
|
|
@@ -210,7 +234,7 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(
|
|
|
210
234
|
style={styles.buttonContainer}>
|
|
211
235
|
{!hideCancelButton ? (
|
|
212
236
|
<TouchableOpacity
|
|
213
|
-
onPress={
|
|
237
|
+
onPress={cancelHandler}
|
|
214
238
|
{...buttonTouchableOpacityProps}>
|
|
215
239
|
<Text
|
|
216
240
|
style={[
|
|
@@ -222,7 +246,7 @@ const TimerPickerModal = forwardRef<TimerPickerModalRef, TimerPickerModalProps>(
|
|
|
222
246
|
</TouchableOpacity>
|
|
223
247
|
) : null}
|
|
224
248
|
<TouchableOpacity
|
|
225
|
-
onPress={
|
|
249
|
+
onPress={confirmHandler}
|
|
226
250
|
{...buttonTouchableOpacityProps}>
|
|
227
251
|
<Text
|
|
228
252
|
style={[
|