Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions configs/eslint/rules/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineConfig } from 'eslint/config'
import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript'

// eslint-disable-next-line import-x/no-named-as-default
import importX from 'eslint-plugin-import-x'
import importX, { createNodeResolver } from 'eslint-plugin-import-x'

export const importConfig = defineConfig([
{
Expand All @@ -18,8 +18,9 @@ export const importConfig = defineConfig([
'import-x/resolver-next': [
createTypeScriptImportResolver({
alwaysTryTypes: true,
project: ['tsconfig.eslint.json'],
project: ['tsconfig.json'],
}),
createNodeResolver(),
],
},
rules: {
Expand Down Expand Up @@ -123,7 +124,7 @@ export const importConfig = defineConfig([
'import-x/extensions': [
'error',
'never',
{ json: 'always', png: 'always', jpg: 'always' },
{ json: 'always', png: 'always', jpg: 'always', mjs: 'always' },
],

// https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/first.md
Expand Down
91 changes: 28 additions & 63 deletions src/components/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { Portal } from '@gorhom/portal'
import React, { useCallback, useEffect } from 'react'
import { View, StyleSheet, BackHandler, Pressable } from 'react-native'
import React, { useCallback, useEffect, useState } from 'react'
import { View, StyleSheet, Pressable, Modal } from 'react-native'
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
withSpring,
runOnJS,
interpolate,
Easing,
} from 'react-native-reanimated'

import { scheduleOnRN } from 'react-native-worklets'

import { DialogComponent, type DialogComponentProps } from './DialogComponent'

const ANIMATION_DURATION = 200
const ANIMATION_BACKDROP_DURATION = 200
const ANIMATION_CONTENT_DURATION = 500
const BACKDROP_OPACITY = 0.5
const SCALE_DAMPING = 5
const SCALE_STIFFNESS = 50
const SCALE_INIT_VALUE = 0.9

export interface DialogProps extends DialogComponentProps {
Expand All @@ -37,30 +36,34 @@ export const Dialog: React.FC<DialogProps> = ({
body,
testID,
}) => {
const [showModal, setShowModal] = useState(false)
const opacity = useSharedValue(0)
const scale = useSharedValue(SCALE_INIT_VALUE)

const handleAnimationComplete = useCallback(() => {
if (onHideComplete) {
onHideComplete()
}

setShowModal(false)
}, [onHideComplete])

useEffect(() => {
if (isVisible) {
opacity.value = withTiming(1, { duration: ANIMATION_DURATION })
scale.value = withSpring(1, {
damping: SCALE_DAMPING,
stiffness: SCALE_STIFFNESS,
setShowModal(true)
opacity.value = withTiming(1, { duration: ANIMATION_BACKDROP_DURATION })
scale.value = withTiming(1, {
duration: ANIMATION_CONTENT_DURATION,
easing: Easing.elastic(1.2),
})
} else {
opacity.value = withTiming(0, { duration: ANIMATION_DURATION })
opacity.value = withTiming(0, { duration: ANIMATION_BACKDROP_DURATION })
scale.value = withTiming(
SCALE_INIT_VALUE,
{ duration: ANIMATION_DURATION },
{ duration: ANIMATION_BACKDROP_DURATION },
(finished) => {
if (finished) {
runOnJS(handleAnimationComplete)()
scheduleOnRN(handleAnimationComplete)
}
}
)
Expand All @@ -77,32 +80,14 @@ export const Dialog: React.FC<DialogProps> = ({
return { opacity: opacity.value, transform: [{ scale: scale.value }] }
})

useEffect(() => {
const subscription = BackHandler.addEventListener(
'hardwareBackPress',
() => {
if (isVisible) {
onClose?.()

return true
}

return false
}
)

return subscription.remove
}, [isVisible, onClose])

return (
<Portal>
<View
style={[
styles.container,
!isVisible && styles.containerNoPointerEvents,
]}
testID={testID ?? DialogTestId.root}
>
<Modal
transparent
animationType='none'
visible={showModal}
onRequestClose={onClose}
>
<View style={styles.container} testID={testID ?? DialogTestId.root}>
<AnimatedPressable
style={[styles.backdrop, backdropAnimatedStyle]}
testID={DialogTestId.backdrop}
Expand All @@ -115,33 +100,13 @@ export const Dialog: React.FC<DialogProps> = ({
<DialogComponent body={body} footer={footer} header={header} />
</Animated.View>
</View>
</Portal>
</Modal>
)
}

const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
flex: 1,
justifyContent: 'center',
alignItems: 'center',
zIndex: 9999,
elevation: 999,
pointerEvents: 'auto',
},
containerNoPointerEvents: { pointerEvents: 'none' },
backdrop: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'black',
},
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
backdrop: { ...StyleSheet.absoluteFillObject, backgroundColor: 'black' },
})

export const DialogTestId = {
Expand Down
Loading
Loading