| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 |
- import { useRef, useState, useCallback } from 'react';
- import { wrap } from './wrap.mjs';
- /**
- * Cycles through a series of visual properties. Can be used to toggle between or cycle through animations. It works similar to `useState` in React. It is provided an initial array of possible states, and returns an array of two arguments.
- *
- * An index value can be passed to the returned `cycle` function to cycle to a specific index.
- *
- * ```jsx
- * import * as React from "react"
- * import { motion, useCycle } from "framer-motion"
- *
- * export const MyComponent = () => {
- * const [x, cycleX] = useCycle(0, 50, 100)
- *
- * return (
- * <motion.div
- * animate={{ x: x }}
- * onTap={() => cycleX()}
- * />
- * )
- * }
- * ```
- *
- * @param items - items to cycle through
- * @returns [currentState, cycleState]
- *
- * @public
- */
- function useCycle(...items) {
- const index = useRef(0);
- const [item, setItem] = useState(items[index.current]);
- const runCycle = useCallback((next) => {
- index.current =
- typeof next !== "number"
- ? wrap(0, items.length, index.current + 1)
- : next;
- setItem(items[index.current]);
- },
- // The array will change on each call, but by putting items.length at
- // the front of this array, we guarantee the dependency comparison will match up
- // eslint-disable-next-line react-hooks/exhaustive-deps
- [items.length, ...items]);
- return [item, runCycle];
- }
- export { useCycle };
|