race
The first to activate wins; the others fail.
Utilisation
Follow a drag and dismiss on a flick
import {
ContextMenu,
Text,
fling,
motion,
pan,
race,
share,
signal,
spring,
together,
watch,
type Signal,
} from 'kuito';
const MENU = ['Share', 'Keep', 'Pass'].map((label) => ({ value: label.toLowerCase(), label }));
function Card(props: {
title: string;
top: boolean;
verdict: Signal<number>;
onGone: (direction: number) => void;
}) {
const x = motion(0);
const drag = pan({ axis: 'x' }).release(spring({ damping: 8, stiffness: 140 }));
const fly = (direction: number) => {
x.value = spring({ overshoot: false, onEnd: (done) => done && props.onGone(direction) }).to(
direction * 600,
);
};
const flick = race(
fling({ direction: 'left', onEnd: (_, ok) => ok && fly(-1) }),
fling({ direction: 'right', onEnd: (_, ok) => ok && fly(1) }),
);
x.follows(drag.x);
watch(props.verdict, (direction) => {
if (props.top && direction !== 0) fly(direction);
});
return (
<ContextMenu
title={props.title}
items={MENU}
disabled={!props.top}
gestures={props.top ? [together(drag, flick)] : []}
translateX={x}
onSelect={({ value }) =>
value === 'share'
? share({ message: `Watch ${props.title} tonight`, url: 'https://example.com/picks/1' })
: (props.verdict.value = value === 'keep' ? 1 : -1)
}
>
<Text>{props.title}</Text>
</ContextMenu>
);
}
export default function CardStack() {
const verdict = signal(0);
return <Card title="Severance" top verdict={verdict} onGone={() => (verdict.value = 0)} />;
}Signatures
(...gestures: Composable[]): ComposedGestureParamètres
| Nom | Type | Requis | Description |
|---|---|---|---|
...gestures | Composable[] | Oui | — |
Retourne
Généré depuis les déclarations TypeScript publiques : signatures, props et valeurs par défaut viennent de la source vérifiée, les descriptions de sa JSDoc. Aucune valeur par défaut n'est inventée.