Newer
Older
import { cloneDeep, isEqual } from 'lodash'
import { computed, ComputedGetter, ComputedRef, readonly, Ref, ref, watch, watchEffect } from 'vue'
import { formatISO, parseISO } from 'date-fns'
export function computedIter<T>(fn: ComputedGetter<Iterable<T>>): ComputedRef<T[]> {
return computed(() => Array.from(fn()))
}
export const useId = (() => {
let _id = 0
return function useId(prefix = 'component') {
return readonly(ref(`${prefix}-${_id++}`))
}
})()
export function useAsyncFunction<F extends (...args: never[]) => Promise<unknown>>(fn: F) {
async function wrapper(...args: Parameters<F>): Promise<Awaited<ReturnType<F>>> {
return (await fn(...args)) as Awaited<ReturnType<F>>
} finally {
isLoading.value = false
}
}
return { fn: wrapper, isLoading }
}
export function useUpdatableState<T>(
externalStateRef: Ref<T>,
onUpdate: (value: T) => void,
clone: (value: T) => T = cloneDeep,
): Ref<T> {
const localRef = ref()
watchEffect(() => {
localRef.value = clone(externalStateRef.value)
})
watch(
localRef,
(newValue) => {
if (!isEqual(newValue, externalStateRef.value)) {
onUpdate(newValue)
}
},
{ deep: true },
)
return localRef
}
export function useFormattedISODate(date: Ref<Date>) {
return computed({
get() {
return formatISO(date.value, { representation: 'date' })
},
set(dateValue: string) {
date.value = parseISO(dateValue)
},
})
}