{"version":3,"sources":["../../src/use-circular-list/index.ts"],"sourcesContent":["import { useCreation } from '../use-creation'\nimport { useLatest } from '../use-latest'\nimport { useSafeState } from '../use-safe-state'\nimport { useStableFn } from '../use-stable-fn'\nimport { useUpdateEffect } from '../use-update-effect'\n\nexport interface UseCycleListOptions<T, R extends T = T> {\n  /**\n   * Initial value\n   */\n  initialValue?: R\n  /**\n   * Fallback index when the value is not found\n   */\n  fallbackIndex?: number\n  /**\n   * Custom function to get the index of the value\n   *\n   * @param {T} value - `T`, the value to find\n   * @param {T[]} list - `T[]`, the list to search\n   * @returns {number} `number`, the index of the value\n   */\n  getIndexOf?: (value: T, list: T[]) => number\n}\n\nexport type UseCycleListReturnsActions<T> = {\n  /**\n   * Move to the next value\n   *\n   * @param {number} [step] - `number`, the step to move\n   * @returns {T} `T`, the next value\n   */\n  next: (step?: number) => T\n  /**\n   * Move to the previous value\n   *\n   * @param {number} [step] - `number`, the step to move\n   * @returns {T} `T`, the previous value\n   */\n  prev: (step?: number) => T\n  /**\n   * Move to the value at the specified index\n   *\n   * @param {number} index - `number`, the index to move\n   * @returns {T} `T`, the value at the specified index\n   */\n  go: (index: number) => T\n}\n\nexport type UseCycleListReturns<T> = readonly [\n  /**\n   * Current value\n   */\n  state: T,\n  /**\n   * Actions to control the list\n   */\n  UseCycleListReturnsActions<T>,\n  /**\n   * Current index\n   */\n  index: number,\n]\n\n/**\n * A React Hook that helps to create a circular list that can cycle through the list.\n *\n * TODO: rewrite using `NoInfer` in TS 5.4, now downgrade temporarily\n *\n * @param {T[]} list - `T[]`, the list to cycle\n * @param {UseCycleListOptions} [options] - `UseCycleListOptions`, see {@link UseCycleListOptions}\n * @returns {UseCycleListReturns} `UseCycleListReturns`, see {@link UseCycleListReturns} and {@link UseCycleListReturnsActions}\n */\nexport function useCircularList<T, R extends T = T>(\n  list: T[],\n  options: UseCycleListOptions<T, R> = {},\n): UseCycleListReturns<T> {\n  const { initialValue = list[0], fallbackIndex = 0, getIndexOf } = options\n\n  const latest = useLatest({ fallbackIndex, list, getIndexOf })\n\n  const [state, setState] = useSafeState(() => {\n    const index = getIndexOf ? getIndexOf(initialValue, list) : list.indexOf(initialValue)\n    if (index < 0) return list[fallbackIndex]\n    return list[index]\n  })\n\n  const getIndex = useStableFn(() => {\n    const { list, getIndexOf, fallbackIndex } = latest.current\n    let index = getIndexOf ? getIndexOf?.(state, list) : list.indexOf(state)\n    if (index < 0) index = fallbackIndex\n    return index\n  })\n\n  const setValueViaIndex = useStableFn((i: number) => {\n    const { list } = latest.current\n    const length = list.length\n    const index = ((i % length) + length) % length\n    const value = list[index]\n    setState(value)\n    return value\n  })\n\n  const shift = useStableFn((delta = 1) => setValueViaIndex(getIndex() + delta))\n  const next = useStableFn((step = 1) => shift(step))\n  const prev = useStableFn((step = 1) => shift(-step))\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: effect need to re-run when list changes\n  useUpdateEffect(() => void setValueViaIndex(getIndex()), [list])\n\n  const index = getIndex()\n  const actions = useCreation(() => ({ next, prev, go: setValueViaIndex }))\n\n  return [state, actions, index] as const\n}\n"],"names":["useCircularList","list","options","initialValue","fallbackIndex","getIndexOf","latest","useLatest","useSafeState","index","indexOf","state","setState","getIndex","useStableFn","current","setValueViaIndex","i","length","value","shift","delta","next","step","prev","useUpdateEffect","actions","useCreation","go"],"mappings":";;;;+BAyEgBA;;;eAAAA;;;2BAzEY;yBACF;4BACG;2BACD;+BACI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEzB,SAASA,gBACdC,IAAS;QACTC,UAAAA,iEAAqC,CAAC;IAEtC,4BAAkEA,QAA1DC,cAAAA,kDAAeF,IAAI,CAAC,EAAE,mDAAoCC,QAAlCE,eAAAA,oDAAgB,4BAAGC,aAAeH,QAAfG;IAEnD,IAAMC,SAASC,IAAAA,oBAAS,EAAC;QAAEH,eAAAA;QAAeH,MAAAA;QAAMI,YAAAA;IAAW;IAE3D,IAA0BG,iCAAAA,IAAAA,0BAAY,EAAC;QACrC,IAAMC,QAAQJ,aAAaA,WAAWF,cAAcF,QAAQA,KAAKS,OAAO,CAACP;QACzE,IAAIM,QAAQ,GAAG,OAAOR,IAAI,CAACG,cAAc;QACzC,OAAOH,IAAI,CAACQ,MAAM;IACpB,QAJOE,QAAmBH,kBAAZI,WAAYJ;IAM1B,IAAMK,WAAWC,IAAAA,wBAAW,EAAC;QAC3B,IAA4CR,kBAAAA,OAAOS,OAAO,EAAlDd,SAAoCK,gBAApCL,MAAMI,aAA8BC,gBAA9BD,YAAYD,gBAAkBE,gBAAlBF;QAC1B,IAAIK,QAAQJ,aAAaA,uBAAAA,iCAAAA,WAAaM,OAAOV,UAAQA,OAAKS,OAAO,CAACC;QAClE,IAAIF,QAAQ,GAAGA,QAAQL;QACvB,OAAOK;IACT;IAEA,IAAMO,mBAAmBF,IAAAA,wBAAW,EAAC,SAACG;QACpC,IAAM,AAAEhB,SAASK,OAAOS,OAAO,CAAvBd;QACR,IAAMiB,SAASjB,OAAKiB,MAAM;QAC1B,IAAMT,QAAQ,AAAC,CAAA,AAACQ,IAAIC,SAAUA,MAAK,IAAKA;QACxC,IAAMC,QAAQlB,MAAI,CAACQ,MAAM;QACzBG,SAASO;QACT,OAAOA;IACT;IAEA,IAAMC,QAAQN,IAAAA,wBAAW,EAAC;YAACO,yEAAQ;eAAML,iBAAiBH,aAAaQ;;IACvE,IAAMC,OAAOR,IAAAA,wBAAW,EAAC;YAACS,wEAAO;eAAMH,MAAMG;;IAC7C,IAAMC,OAAOV,IAAAA,wBAAW,EAAC;YAACS,wEAAO;eAAMH,MAAM,CAACG;;IAE9C,mGAAmG;IACnGE,IAAAA,gCAAe,EAAC;eAAM,KAAKT,iBAAiBH;OAAa;QAACZ;KAAK;IAE/D,IAAMQ,QAAQI;IACd,IAAMa,UAAUC,IAAAA,wBAAW,EAAC;eAAO;YAAEL,MAAAA;YAAME,MAAAA;YAAMI,IAAIZ;QAAiB;;IAEtE,OAAO;QAACL;QAAOe;QAASjB;KAAM;AAChC"}