-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
index.ts
91 lines (75 loc) · 1.91 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import type { Ref } from 'vue-demi'
import { computed, shallowRef, watch } from 'vue-demi'
import { toRef, toValue } from '@vueuse/shared'
import type { MaybeRef, MaybeRefOrGetter } from '@vueuse/shared'
export interface UseCycleListOptions<T> {
/**
* The initial value of the state.
* A ref can be provided to reuse.
*/
initialValue?: MaybeRef<T>
/**
* The default index when
*/
fallbackIndex?: number
/**
* Custom function to get the index of the current value.
*/
getIndexOf?: (value: T, list: T[]) => number
}
/**
* Cycle through a list of items
*
* @see https://vueuse.org/useCycleList
*/
export function useCycleList<T>(list: MaybeRefOrGetter<T[]>, options?: UseCycleListOptions<T>): UseCycleListReturn<T> {
const state = shallowRef(getInitialValue()) as Ref<T>
const listRef = toRef(list)
const index = computed<number>({
get() {
const targetList = toValue<T[]>(list)
let index = options?.getIndexOf
? options.getIndexOf(state.value, targetList)
: targetList.indexOf(state.value)
if (index < 0)
index = options?.fallbackIndex ?? 0
return index
},
set(v) {
set(v)
},
})
function set(i: number) {
const targetList = listRef.value
const length = targetList.length
const index = (i % length + length) % length
const value = targetList[index]
state.value = value
return value
}
function shift(delta = 1) {
return set(index.value + delta)
}
function next(n = 1) {
return shift(n)
}
function prev(n = 1) {
return shift(-n)
}
function getInitialValue() {
return toValue(options?.initialValue ?? toValue<T[]>(list)[0]) ?? undefined
}
watch(listRef, () => set(index.value))
return {
state,
index,
next,
prev,
}
}
export interface UseCycleListReturn<T> {
state: Ref<T>
index: Ref<number>
next: (n?: number) => T
prev: (n?: number) => T
}