Skip to content

Commit e4c84a3

Browse files
rodolfovilacaosdnk
authored andcommitted
feat: add support for onOpenStart, onOpenEnd, onCloseStart and onCloseEnd (#83)
1 parent 38a68f4 commit e4c84a3

File tree

2 files changed

+151
-8
lines changed

2 files changed

+151
-8
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ class Example extends React.Component {
7272
| springConfig | no | `{ }` | Overrides config for spring animation |
7373
| innerGestureHandlerRefs | no | | Refs for gesture handlers used for building bottom sheet. The array consists fo three refs. The first for PanGH used for inner content scrolling. The second for PanGH used for header. The third for TapGH used for stopping scrolling the content. |
7474
| simultaneousHandlers | no | | Accepts a react ref object or an array of refs to handler components. |
75+
| onOpenStart | no | | Accepts a function to be called when the bottom sheet starts to open. |
76+
| onOpenEnd | no | | Accepts a function to be called when the bottom sheet is almost fully openned. |
77+
| onCloseStart | no | | Accepts a function to be called when the bottom sheet starts to close. |
78+
| onCloseEnd | no | | Accepts a function to be called when the bottom sheet is almost closing. |
79+
| callbackThreshold | no | 0.01 | Accepts a float value from 0 to 1 indicating the percentage (of the gesture movement) when the callbacks are gonna be called. |
7580

7681

7782
## Methods

src/index.tsx

Lines changed: 146 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ type Props = {
9898
]
9999

100100
enabledImperativeSnapping?: boolean
101+
102+
onOpenStart?: () => void
103+
onOpenEnd?: () => void
104+
onCloseStart?: () => void
105+
onCloseEnd?: () => void
106+
callbackThreshold?: number
101107
}
102108

103109
type State = {
@@ -169,6 +175,9 @@ const {
169175
decay,
170176
Clock,
171177
lessThan,
178+
call,
179+
lessOrEq,
180+
neq,
172181
} = Animated
173182

174183
function runDecay(
@@ -287,6 +296,7 @@ export default class BottomSheetBehavior extends React.Component<Props, State> {
287296
React.createRef(),
288297
React.createRef(),
289298
],
299+
callbackThreshold: 0.01,
290300
}
291301

292302
private decayClock = new Clock()
@@ -307,6 +317,10 @@ export default class BottomSheetBehavior extends React.Component<Props, State> {
307317
private tapRef: React.RefObject<TapGestureHandler>
308318
private snapPoint: Animated.Node<number>
309319
private Y: Animated.Node<number>
320+
private onOpenStartValue: Animated.Value<number> = new Value(0)
321+
private onOpenEndValue: Animated.Value<number> = new Value(0)
322+
private onCloseStartValue: Animated.Value<number> = new Value(1)
323+
private onCloseEndValue: Animated.Value<number> = new Value(0)
310324

311325
constructor(props: Props) {
312326
super(props)
@@ -638,7 +652,7 @@ export default class BottomSheetBehavior extends React.Component<Props, State> {
638652
state: State | undefined
639653
): State {
640654
let snapPoints
641-
const sortedPropsSnapPints: Array<{
655+
const sortedPropsSnapPoints: Array<{
642656
val: number
643657
ind: number
644658
}> = props.snapPoints
@@ -662,29 +676,29 @@ export default class BottomSheetBehavior extends React.Component<Props, State> {
662676
.sort(({ val: a }, { val: b }) => b - a)
663677
if (state && state.snapPoints) {
664678
state.snapPoints.forEach((s, i) =>
665-
s.setValue(sortedPropsSnapPints[0].val - sortedPropsSnapPints[i].val)
679+
s.setValue(sortedPropsSnapPoints[0].val - sortedPropsSnapPoints[i].val)
666680
)
667681
snapPoints = state.snapPoints
668682
} else {
669-
snapPoints = sortedPropsSnapPints.map(
670-
p => new Value(sortedPropsSnapPints[0].val - p.val)
683+
snapPoints = sortedPropsSnapPoints.map(
684+
p => new Value(sortedPropsSnapPoints[0].val - p.val)
671685
)
672686
}
673687

674688
const propsToNewIndices: { [key: string]: number } = {}
675-
sortedPropsSnapPints.forEach(({ ind }, i) => (propsToNewIndices[ind] = i))
689+
sortedPropsSnapPoints.forEach(({ ind }, i) => (propsToNewIndices[ind] = i))
676690

677691
const { initialSnap } = props
678692

679693
return {
680694
init:
681-
sortedPropsSnapPints[0].val -
682-
sortedPropsSnapPints[propsToNewIndices[initialSnap]].val,
695+
sortedPropsSnapPoints[0].val -
696+
sortedPropsSnapPoints[propsToNewIndices[initialSnap]].val,
683697
propsToNewIndices,
684698
heightOfHeaderAnimated:
685699
(state && state.heightOfHeaderAnimated) || new Value(0),
686700
heightOfContent: (state && state.heightOfContent) || new Value(0),
687-
initSnap: sortedPropsSnapPints[0].val,
701+
initSnap: sortedPropsSnapPoints[0].val,
688702
snapPoints,
689703
heightOfHeader: (state && state.heightOfHeader) || 0,
690704
}
@@ -796,6 +810,130 @@ export default class BottomSheetBehavior extends React.Component<Props, State> {
796810
)}
797811
/>
798812
)}
813+
{(this.props.onOpenStart || this.props.onCloseEnd) && (
814+
<Animated.Code
815+
exec={onChange(this.translateMaster, [
816+
cond(
817+
and(
818+
lessOrEq(
819+
divide(
820+
this.translateMaster,
821+
this.state.snapPoints[
822+
this.state.snapPoints.length - 1
823+
]
824+
),
825+
1 - this.props.callbackThreshold
826+
),
827+
neq(this.onOpenStartValue, 1)
828+
),
829+
[
830+
call([], () => {
831+
if (this.props.onOpenStart) this.props.onOpenStart()
832+
}),
833+
set(this.onOpenStartValue, 1),
834+
cond(
835+
defined(this.onCloseEndValue),
836+
set(this.onCloseEndValue, 0)
837+
),
838+
]
839+
),
840+
])}
841+
/>
842+
)}
843+
{(this.props.onOpenEnd || this.props.onCloseStart) && (
844+
<Animated.Code
845+
exec={onChange(this.translateMaster, [
846+
cond(
847+
and(
848+
lessOrEq(
849+
divide(
850+
this.translateMaster,
851+
this.state.snapPoints[
852+
this.state.snapPoints.length - 1
853+
]
854+
),
855+
this.props.callbackThreshold
856+
),
857+
neq(this.onOpenEndValue, 1)
858+
),
859+
[
860+
call([], () => {
861+
if (this.props.onOpenEnd) this.props.onOpenEnd()
862+
}),
863+
set(this.onOpenEndValue, 1),
864+
cond(
865+
defined(this.onCloseStartValue),
866+
set(this.onCloseStartValue, 0)
867+
),
868+
]
869+
),
870+
])}
871+
/>
872+
)}
873+
{(this.props.onCloseStart || this.props.onOpenEnd) && (
874+
<Animated.Code
875+
exec={onChange(this.translateMaster, [
876+
cond(
877+
and(
878+
greaterOrEq(
879+
divide(
880+
this.translateMaster,
881+
this.state.snapPoints[
882+
this.state.snapPoints.length - 1
883+
]
884+
),
885+
this.props.callbackThreshold
886+
),
887+
neq(this.onCloseStartValue, 1)
888+
),
889+
[
890+
call([], () => {
891+
if (this.props.onCloseStart) this.props.onCloseStart()
892+
}),
893+
set(this.onCloseStartValue, 1),
894+
cond(
895+
defined(this.onCloseStartValue),
896+
set(this.onOpenEndValue, 0)
897+
),
898+
]
899+
),
900+
])}
901+
/>
902+
)}
903+
{(this.props.onCloseEnd || this.props.onOpenStart) && (
904+
<Animated.Code
905+
exec={onChange(this.translateMaster, [
906+
cond(
907+
and(
908+
greaterOrEq(
909+
divide(
910+
this.translateMaster,
911+
this.state.snapPoints[
912+
this.state.snapPoints.length - 1
913+
]
914+
),
915+
1 - this.props.callbackThreshold
916+
),
917+
neq(this.onCloseEndValue, 1)
918+
),
919+
[
920+
call([], () => {
921+
if (this.props.onCloseEnd) this.props.onCloseEnd()
922+
}),
923+
set(this.onCloseEndValue, 1),
924+
cond(
925+
defined(this.onOpenStartValue),
926+
set(this.onOpenStartValue, 0)
927+
),
928+
cond(
929+
defined(this.onOpenEndValue),
930+
set(this.onOpenEndValue, 0)
931+
),
932+
]
933+
),
934+
])}
935+
/>
936+
)}
799937
{this.props.contentPosition && (
800938
<Animated.Code
801939
exec={onChange(

0 commit comments

Comments
 (0)