Skip to content

feat: Item context and docs #363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 27, 2025
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: 7 additions & 0 deletions packages/docs/docs/hooks/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"label": "Hooks",
"position": 6,
"link": {
"type": "generated-index"
}
}
110 changes: 110 additions & 0 deletions packages/docs/docs/hooks/useItemContext.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
sidebar_position: 1
description: 'Hook that provides context with useful item-related values'
---

# useItemContext

## Overview

The `useItemContext` hook provides context with useful item-related values.

## Usage

```tsx
import { useItemContext } from 'react-native-sortables';

const ctx = useItemContext(); // inside a sortable item component
```

## Return Values

The `useItemContext` hook returns an object with the following properties:

- `itemKey` - key of the item where the hook is called
- `activeItemKey` - key of the currently active item
- `prevActiveItemKey` - key of the previously active item
- `isActive` - whether the item is currently being dragged
- `dragActivationState` - current drag activation state of the sortable component
- `activationAnimationProgress` - progress of the activation animation (0 to 1) of the currently active item

<details>
<summary>Type definitions</summary>

```tsx
type ItemContextType = {
itemKey: string;
activeItemKey: Readonly<SharedValue<null | string>>;
prevActiveItemKey: Readonly<SharedValue<null | string>>;
isActive: Readonly<SharedValue<boolean>>;
dragActivationState: Readonly<SharedValue<DragActivationState>>;
activationAnimationProgress: Readonly<SharedValue<number>>;
};
```

</details>

## Example

Here's an example of how to use the `useItemContext` hook to create a custom item component that responds to drag states:

```tsx
function GridItem({ item }: { item: string }) {
// highlight-start
const { activationAnimationProgress, dragActivationState } = useItemContext();
// highlight-end

const colorStyle = useAnimatedStyle(() => ({
backgroundColor: interpolateColor(
activationAnimationProgress.value,
[0, 1],
['#36877F', '#063934']
)
}));

const shakeStyle = useAnimatedStyle(() => {
const easeOut = Easing.out(Easing.quad);

return {
transform: [
dragActivationState.value === DragActivationState.ACTIVE
? {
rotate: withSequence(
withTiming('0.08rad', { duration: 80, easing: Easing.linear }),
withTiming('-0.08rad', { duration: 80, easing: Easing.linear }),
withTiming('0.08rad', { duration: 80, easing: Easing.linear }),
withTiming('-0.06rad', { duration: 80, easing: Easing.linear }),
withTiming('0.06rad', { duration: 80, easing: Easing.linear }),
withTiming('-0.04rad', { duration: 80, easing: Easing.linear }),
withTiming('0.04rad', { duration: 80, easing: Easing.linear }),
withTiming('0rad', { duration: 100, easing: easeOut })
)
}
: { rotate: withTiming('0rad', { duration: 100, easing: easeOut }) }
]
};
});

return (
<Animated.View style={[styles.card, colorStyle, shakeStyle]}>
<Text style={styles.text}>{item}</Text>
</Animated.View>
);
}
```

### Result

import itemContextVideo from '@site/static/video/item-context.mp4';

<video autoPlay loop muted width='400px' src={itemContextVideo} />

## Remarks

- The `useItemContext` hook must be used within a component that is rendered as part of a sortable item.

:::info

If you need to access other values, please request them in the [GitHub Discussions](https://github.com/matipl01/react-native-sortables/discussions). There are other properties that can be exposed in the `ItemContextType` type.

:::
Binary file added packages/docs/static/video/item-context.mp4
Binary file not shown.
3 changes: 2 additions & 1 deletion packages/react-native-sortables/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import {
SortableHandle,
SortableLayer
} from './components';
export { useItemContext } from './providers';
import { PortalProvider } from './providers';

export type { SortableHandleProps, SortableLayerProps } from './components';
export * from './constants/layoutAnimations';
export type {
Expand All @@ -32,6 +32,7 @@ export type {
SortableGridRenderItem,
SortableGridStrategyFactory
} from './types';
export { DragActivationState } from './types';

/** Collection of sortable components and utilities for React Native */
const Sortable = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,25 @@ import { useCommonValuesContext } from './CommonValuesProvider';
type ItemContextProviderProps = PropsWithChildren<
{
itemKey: string;
} & Omit<ItemContextType, 'dragActivationState'>
} & Pick<ItemContextType, 'activationAnimationProgress' | 'isActive'>
>;

const { ItemContextProvider, useItemContextContext: useItemContext } =
createProvider('ItemContext', { guarded: true })<
ItemContextProviderProps,
ItemContextType
>(props => {
const { activationState } = useCommonValuesContext();
const { activationState, activeItemKey, prevActiveItemKey } =
useCommonValuesContext();

return { value: { ...props, dragActivationState: activationState } };
return {
value: {
...props,
activeItemKey,
dragActivationState: activationState,
prevActiveItemKey
}
};
});

export { ItemContextProvider, useItemContext };
2 changes: 2 additions & 0 deletions packages/react-native-sortables/src/types/providers/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ export type DragContextType = {

export type ItemContextType = {
itemKey: string;
activeItemKey: Readonly<SharedValue<null | string>>;
prevActiveItemKey: Readonly<SharedValue<null | string>>;
isActive: Readonly<SharedValue<boolean>>;
dragActivationState: Readonly<SharedValue<DragActivationState>>;
activationAnimationProgress: Readonly<SharedValue<number>>;
Expand Down
Loading