-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
index.ts
68 lines (59 loc) · 1.31 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
import type { MaybeRefOrGetter } from '@vueuse/shared'
import { toValue } from '@vueuse/shared'
import type { Ref, WatchOptions } from 'vue-demi'
import { isRef, ref, watch } from 'vue-demi'
export interface UseClonedOptions<T = any> extends WatchOptions {
/**
* Custom clone function.
*
* By default, it use `JSON.parse(JSON.stringify(value))` to clone.
*/
clone?: (source: T) => T
/**
* Manually sync the ref
*
* @default false
*/
manual?: boolean
}
export interface UseClonedReturn<T> {
/**
* Cloned ref
*/
cloned: Ref<T>
/**
* Sync cloned data with source manually
*/
sync: () => void
}
export type CloneFn<F, T = F> = (x: F) => T
export function cloneFnJSON<T>(source: T): T {
return JSON.parse(JSON.stringify(source))
}
export function useCloned<T>(
source: MaybeRefOrGetter<T>,
options: UseClonedOptions = {},
): UseClonedReturn<T> {
const cloned = ref({} as T) as Ref<T>
const {
manual,
clone = cloneFnJSON,
// watch options
deep = true,
immediate = true,
} = options
function sync() {
cloned.value = clone(toValue(source))
}
if (!manual && (isRef(source) || typeof source === 'function')) {
watch(source, sync, {
...options,
deep,
immediate,
})
}
else {
sync()
}
return { cloned, sync }
}