Skip to content

Commit

Permalink
add 'animated' option to open/close
Browse files Browse the repository at this point in the history
  • Loading branch information
computerjazz committed Jul 22, 2022
1 parent f7db50e commit dcbf5d4
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 53 deletions.
29 changes: 13 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@ Compatible with [React Native Draggable Flatlist](https://github.com/computerjaz
_NOTE:_ Naming is hard. When you swipe _right_, you reveal the item on the _left_. So what do you name these things? I have decided to name everything according to swipe direction. Therefore, a swipe left reveals the `renderUnderlayLeft()` component with width `underlayWidthLeft`. Not perfect but it works.

```ts
type OpenCloseOptions = { animated?: boolean };
type OpenPromiseFn = (
snapPoint?: number,
options?: OpenCloseOptions
) => Promise<void>;
type ClosePromiseFn = (options?: OpenCloseOptions) => Promise<void>;

export type UnderlayParams<T> = {
item: T;
open: OpenPromiseFn;
close: VoidPromiseFn;
close: ClosePromiseFn;
percentOpen: Animated.DerivedValue<number>;
isGestureActive: Animated.DerivedValue<boolean>;
direction: OpenDirection;
Expand All @@ -31,21 +38,11 @@ export type OverlayParams<T> = {
item: T;
openLeft: OpenPromiseFn;
openRight: OpenPromiseFn;
close: VoidPromiseFn;
close: ClosePromiseFn;
openDirection: OpenDirection;
percentOpenLeft: Animated.DerivedValue<number>;
percentOpenRight: Animated.DerivedValue<number>;
};

type RenderUnderlay<T> = (params: UnderlayParams<T>) => React.ReactNode;

type RenderOverlay<T> = (params: OverlayParams<T>) => React.ReactNode;

enum OpenDirection {
LEFT = "left",
RIGHT = "right",
NONE = "none",
}
```

| Name | Type | Description |
Expand Down Expand Up @@ -84,10 +81,10 @@ function MyOverlayComponent() {

### Instance Methods

| Name | Type | Description |
| :------ | :--------------------------------------------------------------------------------- | :----------------------------------------------------------- |
| `open` | `(OpenDirection.LEFT \| OpenDirection.RIGHT, snapIndex?: number) => Promise<void>` | Imperatively open left or right. Promise resolves once open. |
| `close` | `() => Promise<void>` | Close all. Promise resolves once closed. |
| Name | Type | Description |
| :------ | :------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------- |
| `open` | `(OpenDirection.LEFT \| OpenDirection.RIGHT, snapIndex?: number, options?: { animated: boolean }) => Promise<void>` | Imperatively open left or right. Promise resolves once open. |
| `close` | `(options?: { animated?: boolean}) => Promise<void>` | Close all. Promise resolves once closed. |

```tsx
// Imperative open example
Expand Down
102 changes: 65 additions & 37 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ export enum OpenDirection {

const renderNull = () => null;

type VoidPromiseFn = () => Promise<void>;
type OpenPromiseFn = (snapPoint?: number) => Promise<void>;
type OpenCloseOptions = { animated?: boolean };
type OpenPromiseFn = (
snapPoint?: number,
options?: OpenCloseOptions
) => Promise<void>;
type ClosePromiseFn = (options?: OpenCloseOptions) => Promise<void>;

export type UnderlayParams<T> = {
item: T;
open: OpenPromiseFn;
close: VoidPromiseFn;
close: ClosePromiseFn;
percentOpen: Animated.DerivedValue<number>;
isGestureActive: Animated.DerivedValue<boolean>;
direction: OpenDirection;
Expand All @@ -48,7 +52,7 @@ export type OverlayParams<T> = {
item: T;
openLeft: OpenPromiseFn;
openRight: OpenPromiseFn;
close: VoidPromiseFn;
close: ClosePromiseFn;
openDirection: OpenDirection;
percentOpenLeft: Animated.DerivedValue<number>;
percentOpenRight: Animated.DerivedValue<number>;
Expand Down Expand Up @@ -81,8 +85,12 @@ type Props<T> = {
};

export type SwipeableItemImperativeRef = {
open: (openDirection: OpenDirection, snapPoint?: number) => Promise<void>;
close: () => Promise<void>;
open: (
openDirection: OpenDirection,
snapPoint?: number,
options?: OpenCloseOptions
) => Promise<void>;
close: ClosePromiseFn;
};

function SwipeableItem<T>(
Expand Down Expand Up @@ -178,60 +186,80 @@ function SwipeableItem<T>(
[animStatePos]
);

function openLeft(snapPoint?: number) {
const openLeft: OpenPromiseFn = (snapPoint, options) => {
return new Promise<void>((resolve) => {
function resolvePromiseIfFinished(isFinished: boolean) {
if (isFinished) resolve();
}
animStatePos.value = withSpring(
snapPoint ?? maxSnapPointLeft,
springConfig,
(isFinished) => {

const toValue = snapPoint ?? maxSnapPointLeft;

if (options?.animated === false) {
animStatePos.value = toValue;
resolve();
} else {
animStatePos.value = withSpring(toValue, springConfig, (isFinished) => {
if (isFinished) {
runOnJS(resolvePromiseIfFinished)(isFinished);
}
}
);
});
}
});
}
function openRight(snapPoint?: number) {
};

const openRight: OpenPromiseFn = (snapPoint, options) => {
return new Promise<void>((resolve) => {
function resolvePromiseIfFinished(isFinished: boolean) {
if (isFinished) resolve();
}
animStatePos.value = withSpring(
snapPoint ?? maxSnapPointRight,
springConfig,
(isFinished) => {

const toValue = snapPoint ?? maxSnapPointRight;

if (options?.animated === false) {
animStatePos.value = toValue;
resolve();
} else {
animStatePos.value = withSpring(toValue, springConfig, (isFinished) => {
if (isFinished) {
runOnJS(resolvePromiseIfFinished)(isFinished);
}
}
);
});
}
});
}
};

function close() {
const close: ClosePromiseFn = (options) => {
return new Promise<void>((resolve) => {
function resolvePromiseIfFinished(isFinished: boolean) {
if (isFinished) resolve();
}
animStatePos.value = withSpring(0, springConfig, (isFinished) => {
if (isFinished) {
runOnJS(resolvePromiseIfFinished)(isFinished);
}
});

if (options?.animated === false) {
animStatePos.value = 0;
resolve();
} else {
animStatePos.value = withSpring(0, springConfig, (isFinished) => {
if (isFinished) {
runOnJS(resolvePromiseIfFinished)(isFinished);
}
});
}
});
}
};

useImperativeHandle(ref, () => ({
open: (openDirection: OpenDirection, snapPoint?: number) => {
if (openDirection === OpenDirection.LEFT) return openLeft(snapPoint);
if (openDirection === OpenDirection.RIGHT) return openRight(snapPoint);
return close();
},
close,
}));
useImperativeHandle(ref, () => {
const refObject: SwipeableItemImperativeRef = {
open: (openDirection, snapPoint, options) => {
if (openDirection === OpenDirection.LEFT)
return openLeft(snapPoint, options);
if (openDirection === OpenDirection.RIGHT)
return openRight(snapPoint, options);
return close();
},
close,
};
return refObject;
});

function onAnimationEnd(openDirection: OpenDirection, snapPoint: number) {
setOpenDirection(openDirection);
Expand Down

0 comments on commit dcbf5d4

Please sign in to comment.